Quando si aggiungono componenti Kubernetes a un modello cloud di Automation Assembler, è possibile scegliere di aggiungere cluster o consentire agli utenti di creare spazi dei nomi in varie configurazioni. Questa scelta dipende in genere dalle esigenze di controllo degli accessi, da come sono stati configurati i componenti Kubernetes e dalle esigenze di distribuzione.

Per aggiungere un componente Kubernetes a un modello cloud in Automation Assembler, selezionare Progettazione > Modelli cloud, fare clic su Nuovo, quindi individuare ed espandere l'opzione Kubernetes nel menu a sinistra. Selezionare quindi il valore desiderato, ovvero il cluster o lo spazio dei nomi KBS trascinandolo nella tela.

L'aggiunta a un modello cloud di un cluster Kubernetes associato a un progetto è il metodo più semplice per rendere le risorse Kubernetes disponibili per gli utenti validi. È possibile utilizzare i tag nei cluster per controllare dove sono distribuiti proprio come per le altre risorse di Cloud Assembly. È possibile utilizzare i tag per selezionare una zona e un piano VMware Tanzu Kubernetes Grid Integrated Edition (TKGI) durante la fase di allocazione della distribuzione del cluster.

Dopo aver aggiunto un cluster tramite questa procedura, tale cluster è disponibile automaticamente per tutti gli utenti validi.

Esempi di modelli cloud

Il primo esempio di modello cloud mostra un modello per una distribuzione di Kubernetes semplice controllata da tag. Una zona Kubernetes è stata creata con due piani di distribuzione, configurati nella nuova pagina della zona Kubernetes. In questo caso, un tag denominato placement:tag è stato aggiunto come funzionalità nella zona ed è stato utilizzato in modo da corrispondere al vincolo analogo nel modello cloud. Se sono state configurate più zone con il tag, verrà selezionata quella con il numero di priorità più basso.

formatVersion: 1
inputs: {}
resources:
  Cluster_provisioned_from_tag:
    type: Cloud.K8S.Cluster
    properties:
      hostname: 109.129.209.125
      constraints:
	-tag: 'placement tag'
      port: 7003
      workers: 1
      connectBy: hostname 

Il secondo esempio di modello cloud illustra come configurare un modello con una variabile denominata $(input.hostname) in modo che gli utenti possano immettere il nome host del cluster desiderato quando richiedono una distribuzione. I tag possono essere utilizzati anche per selezionare una zona e un piano TKGI durante la fase di allocazione delle risorse della distribuzione del cluster.

formatVersion: 1
inputs:
  hostname:
    type: string
    title: Cluster hostname
resources:
  Cloud_K8S_Cluster_1:
    type: Cloud.K8S.Cluster
    properties:
      hostname: ${input.hostname}
      port: 8443
      connectBy: hostname
      workers: 1

Se si desidera utilizzare gli spazi dei nomi per gestire l'utilizzo del cluster, è possibile configurare una variabile nel modello cloud denominata name: ${input.name} per sostituire il nome dello spazio dei nomi che un utente immette quando richiede una distribuzione. Per questo tipo di distribuzione, è possibile creare un modello simile al seguente esempio:

1 formatVersion: 1
2 inputs:
3 name:
4    type: string
5    title: "Namespace name"
6 resources:
7    Cloud_KBS_Namespace_1:
8        type: Cloud.K8S.Namespace
9        properties:
10            name: ${input.name}

Gli utenti possono gestire i cluster distribuiti tramite i file kubeconfig accessibili dalla pagina Infrastruttura > Risorse > Cluster Kubernetes. Individuare la scheda nella pagina del cluster desiderato e fare clic su Kubeconfig.

Spazi dei nomi supervisore in VMware Cloud Templates

Di seguito è riportato lo schema relativo a uno spazio dei nomi supervisore di base in un modello cloud di Automation Assembler.

{
  "title": "Supervisor namespace schema",
  "description": "Request schema for provisioning of Supervisor namespace resource",
  "type": "object",
  "properties": {
    "name": {
      "title": "Name",
      "description": "Alphabetic (a-z and 0-9) string with maximum length of 63 characters. The character ‘-’ is allowed anywhere except the first or last position of the identifier.",
      "type": "string",
      "pattern": "^.*\\$\\{.*\\}.*$|^((?!-)[a-z0-9-]{1,63}(?<!-))$",
      "ignoreOnUpdate": true
    },
    "description": {
      "title": "Description",
      "description": "An optional description of this Supervisor namespace.",
      "type": "string",
      "ignoreOnUpdate": true
    },
    "content": {
      "title": "Content",
      "description": "Kubernetes Yaml Content",
      "type": "string",
      "maxLength": 65000
    },
    "constraints": {
      "title": "Constraints",
      "description": "To target the correct resources, blueprint constraints are matched against infrastructure capability tags. Constraints must include the key name. Options include value, negative [!], and hard or soft requirement.",
      "type": "array",
      "recreateOnUpdate": true,
      "items": {
        "type": "object",
        "properties": {
          "tag": {
            "title": "Tag",
            "description": "Constraint definition in syntax `[!]tag_key[:tag_value][:hard|:soft]` \nExamples:\n```\n!location:eu:hard\n location:us:soft\n!pci\n```",
            "type": "string",
            "recreateOnUpdate": true
          }
        }
      }
    },
    "limits": {
      "title": "Limits",
      "description": "Defines namespace resource limits such as pods, services, etc.",
      "type": "object",
      "properties": {
        "stateful_set_count": {
          "title": "stateful_set_count",
          "description": "This represents the new value for 'statefulSetCount' option which is the maximum number of StatefulSets in the namespace.",
          "type": "integer",
          "recreateOnUpdate": false
        },
        "deployment_count": {
          "title": "deployment_count",
          "description": "This represents the new value for 'deploymentCount' option which is the maximum number of deployments in the namespace.",
          "type": "integer",
          "recreateOnUpdate": false
        },
        "cpu_limit_default": {
          "title": "cpu_limit_default",
          "description": "This represents the new value for the default CPU limit (in Mhz) for containers in the pod. If specified, this limit should be at least 10 MHz.",
          "type": "integer",
          "recreateOnUpdate": false
        },
        "config_map_count": {
          "title": "config_map_count",
          "description": "This represents the new value for 'configMapCount' option which is the maximum number of ConfigMaps in the namespace.",
          "type": "integer",
          "recreateOnUpdate": false
        },
        "pod_count": {
          "title": "pod_count",
          "description": "This represents the new value for 'podCount' option which is the maximum number of pods in the namespace.",
          "type": "integer",
          "recreateOnUpdate": false
        },
        "job_count": {
          "title": "job_count",
          "description": "This represents the new value for 'jobCount' option which is the maximum number of jobs in the namespace.",
          "type": "integer",
          "recreateOnUpdate": false
        },
        "secret_count": {
          "title": "secret_count",
          "description": "This represents the new value for 'secretCount' option which is the maximum number of secrets in the namespace.",
          "type": "integer",
          "recreateOnUpdate": false
        },
        "cpu_limit": {
          "title": "cpu_limit",
          "description": "This represents the new value for 'limits.cpu' option which is equivalent to the maximum CPU limit (in MHz) across all pods in the namespace.",
          "type": "integer",
          "recreateOnUpdate": false
        },
        "cpu_request_default": {
          "title": "cpu_request_default",
          "description": "This represents the new value for the default CPU request (in Mhz) for containers in the pod. If specified, this field should be at least 10 MHz.",
          "type": "integer",
          "recreateOnUpdate": false
        },
        "memory_limit_default": {
          "title": "memory_limit_default",
          "description": "This represents the new value for the default memory limit (in mebibytes) for containers in the pod.",
         "type": "integer",
          "recreateOnUpdate": false
        },
        "memory_limit": {
          "title": "memory_limit",
          "description": "This represents the new value for 'limits.memory' option which is equivalent to the maximum memory limit (in mebibytes) across all pods in the namespace.",
          "type": "integer",
          "recreateOnUpdate": false
        },
        "memory_request_default": {
          "title": "memory_request_default",
          "description": "This represents the new value for the default memory request (in mebibytes) for containers in the pod.",
          "type": "integer",
          "recreateOnUpdate": false
        },
        "service_count": {
          "title": "service_count",
          "description": "This represents the new value for 'serviceCount' option which is the maximum number of services in the namespace.",
          "type": "integer",
          "recreateOnUpdate": false
        },
        "replica_set_count": {
          "title": "replica_set_count",
          "description": "This represents the new value for 'replicaSetCount' option which is the maximum number of ReplicaSets in the namespace.",
          "type": "integer",
          "recreateOnUpdate": false
        },
        "replication_controller_count": {
          "title": "replication_controller_count",
          "description": "This represents the new value for 'replicationControllerCount' option which is the maximum number of ReplicationControllers in the namespace.",
          "type": "integer",
          "recreateOnUpdate": false
        },
        "storage_request_limit": {
          "title": "storage_request_limit",
          "description": "This represents the new value for 'requests.storage' which is the limit on storage requests (in mebibytes) across all persistent volume claims from pods in the namespace.",
          "type": "integer",
          "recreateOnUpdate": false
        },
        "persistent_volume_claim_count": {
          "title": "persistent_volume_claim_count",
          "description": "This represents the new value for 'persistentVolumeClaimCount' option which is the maximum number of PersistentVolumeClaims in the namespace.",
          "type": "integer",
          "recreateOnUpdate": false
        },
        "daemon_set_count": {
          "title": "daemon_set_count",
          "description": "This represents the new value for 'daemonSetCount' option which is the maximum number of DaemonSets in the namespace.",
          "type": "integer",
          "recreateOnUpdate": false
        }
      },
      "additionalProperties": false
    },
    "vm_classes": {
      "title": "VM classes",
      "description": "Defines set of Virtual Machine classes to be assigned to the namespace",
      "type": "array",
      "recreateOnUpdate": false,
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "title": "Name",
            "description": "Name of the Virtual Machine class.",
            "type": "string",
            "recreateOnUpdate": false
          }
        }
      }
    },
    "storage": {
      "title": "Storage policies",
      "description": "Defines set of storage profiles to be used to assign storage policies to the namespace.",
      "type": "array",
      "recreateOnUpdate": false,
      "items": {
        "type": "object",
        "properties": {
          "profile": {
            "type": "object",
            "title": "Storage profile",
            "description": "Defines storage policies to be assigned to the namespace",
            "recreateOnUpdate": false,
            "properties": {
              "constraints": {
                "title": "Constraints",
                "description": "To target the correct storage profiles, blueprint constraints are matched against storage profile capability tags.",
                "type": "array",
                "recreateOnUpdate": false,
                "items": {
                  "type": "object",
                  "properties": {
                    "tag": {
                      "title": "Tag",
                      "description": "Constraint definition in syntax `[!]tag_key[:tag_value][:hard|:soft]` \nExamples:\n```\nlocation:eu:hard\n location:us:soft\n```",
                      "type": "string",
                      "recreateOnUpdate": false
                    }
                  }
                },
                "minItems":1
              },
              "limitMb": {
                "title": "Limit",
                "description": "The maximum amount of storage (in mebibytes) which can be utilized by the namespace for this storage policy. Optional. If unset, no limits are placed.",
                "type": "integer"
              }
            },
            "required": [
              "constraints"
            ]
          }
        }
      }
    }
  },
  "required": [
    "name"
  ]
}

VMware Cloud Templates supporta l'utilizzo di limiti con gli spazi dei nomi supervisore. I limiti consentono di controllare l'utilizzo delle risorse per CPU e memoria, nonché il numero massimo di pod consentiti nello spazio dei nomi per le macchine distribuite.

formatVersion: 1
inputs: {}
resources:
  Cloud_SV_Namespace_1:
    type: Cloud.SV.Namespace
    properties:
      name: '${env.deploymentName}'
      limits:
        - cpu_limit: 1000
          cpu_request_default: 800
          memory_limit: 2000
          memory_limit_default: 1500
          pod_count: 200

L'esempio seguente illustra come specificare un criterio di storage utilizzando i tag.

formatVersion: 1
inputs: {}
resources:
  Cloud_SV_Namespace_1:
    type: Cloud.SV.Namespace
    properties:
      name: 'ns-with-storage-policy'
      description: 'sample'
      storage: 
        - profile: 
            limitMb: 1000
            constraints: 
              - tag: 'storage:fast'
        - profile: 
            constraints: 
              - tag: 'storage:cheap'

Utilizzo di YAML arbitrari con uno spazio dei nomi self-service o VCT del cluster

Come parte della creazione di un cluster o di uno spazio dei nomi, è possibile che si desideri eseguire personalizzazioni aggiuntive. Ad esempio, può essere necessario aggiungere utenti (ruolo/binding del ruolo) o creare un criterio di sicurezza pod o installare agenti. Utilizzando la proprietà content di YAML, è possibile definire pacchetti personalizzati di cui eseguire il provisioning in tale cluster/spazio dei nomi/spazio dei nomi supervisore.

Ogni pacchetto di contenuti YAML associato alla proprietà content deve essere separato con tre trattini (---). Anche le informazioni dei contenuti devono essere una stringa a più righe. Fare riferimento al seguente esempio di YAML per capire come configurare i pacchetti di contenuti.

formatVersion: 1
inputs: {}
resources:
  Cloud_Tanzu_Cluster_1:
    type: Cloud.Tanzu.Cluster
    properties:
      name: ddonchev-tkc
      plan: small
      content: |-
        apiVersion: rbac.authorization.k8s.io/v1
        kind: ClusterRoleBinding
        metadata:
          name: psp:authenticated-from-yaml
        subjects:
        - apiGroup: rbac.authorization.k8s.io
          kind: Group
          name: system:authenticated
        roleRef:
          apiGroup: rbac.authorization.k8s.io
          kind: ClusterRole
          name: psp:vmware-system-privileged
        ---
        apiVersion: apiextensions.k8s.io/v1
        kind: CustomResourceDefinition
        metadata:
          # name must match the spec fields below, and be in the form: <plural>.<group>
          name: crontabs.stable.example.com
        spec:
          # group name to use for REST API: /apis/<group>/<version>
          group: stable.example.com
          # list of versions supported by this CustomResourceDefinition
          versions:
            - name: v1
              # Each version can be enabled/disabled by Served flag.
              served: true
              # One and only one version must be marked as the storage version.
              storage: true
              schema:
                openAPIV3Schema:
                  type: object
                  properties:
                    spec:
                      type: object
                      properties:
                        cronSpec:
                          type: string
                        image:
                          type: string
                        replicas:
                          type: integer
          # either Namespaced or Cluster
          scope: Namespaced
          names:
            # plural name to be used in the URL: /apis/<group>/<version>/<plural>
            plural: crontabs
            # singular name to be used as an alias on the CLI and for display
            singular: crontab
            # kind is normally the CamelCased singular type. Your resource manifests use this.
            kind: CronTab
            # shortNames allow shorter string to match your resource on the CLI
            shortNames:
            - ct

Il codice YAML definito nella proprietà del contenuto viene visualizzato anche nella scheda Proprietà per la distribuzione.

Automation Assembler può creare risorse di contenuti solo nell'ambito della risorsa da distribuire. Ad esempio, se si esegue il provisioning di uno spazio dei nomi Kubernetes, Automation Assembler non può creare una distribuzione all'interno di uno spazio dei nomi diverso. Gli utenti hanno gli stessi diritti che avrebbero se stessero usando kubeconfig con kubectl.

Dopo il provisioning della macchina virtuale, viene avviata l'installazione degli oggetti Kubernetes della proprietà content. Se per una delle risorse a cui si fa riferimento nella proprietà del contenuto YAML non è possibile eseguire il provisioning, Automation Assembler eseguirà il rollback ed eliminerà tutti gli oggetti Kubernetes precedenti dalla risorsa e la distribuzione avrà lo stato Non riuscita. La risorsa verrà comunque sottoposta a provisioning e sarà visibile. Sarà inoltre possibile utilizzare le azioni giorno 2, incluso il tentativo di applicare nuovamente il contenuto.

È possibile migliorare la proprietà content con input del modello cloud come illustrato nell'esempio seguente.

formatVersion: 1
inputs: {}
resources:
  Cloud_SV_Namespace_1:
    type: Cloud.SV.Namespace
    properties:
      name: sv-namespace-with-vm-classes
      vm_classes:
        - name: best-effort-2xlarge
        - name: best-effort-4xlarge
        - name: best-effort-8xlarge

È inoltre possibile eseguire il provisioning di risorse personalizzate come TanzuKubernetesCluster. Questa operazione non riuscirà come operazione giorno 1 perché lo spazio dei nomi supervisore non conterrà le classi di storage e le classi di macchine virtuali necessarie. Quando le classi di macchine virtuali e le classi di storage sono associate allo spazio dei nomi supervisore, è possibile creare TanzuKubernetesCluster (o un'altra risorsa) utilizzando l'azione giorno 2.

Nota: è possibile eseguire il provisioning di una risorsa senza contenuto ed aggiungere comunque oggetti Kubernetes come YAML con l'azione giorno 2.

Il contenuto visualizzato nella proprietà YAML definisce il contenuto di cui viene eseguito il provisioning nella risorsa. Quando si modificano questi contenuti, la seguente tabella mostra i possibili risultati:

Azione Risultato
Se si aggiunge un oggetto Kubernetes e si invia. L'oggetto specificato viene creato nella risorsa.
Se si rimuove un oggetto Kubernetes e si invia. L'oggetto specificato viene eliminato dalla risorsa.
Se si modifica un oggetto Kubernetes e si invia. L'oggetto specificato è sottoposto a patch nella risorsa.

È importante chiarire quali azioni vengono considerate come modifiche dell'oggetto corrente. Ad esempio, se si modifica il campo dello spazio dei nomi di un oggetto, viene creato un nuovo oggetto anziché sottoporre a patch quello precedente.

L'univocità di una risorsa è definita dai seguenti campi: apiVersion, kind, metadata.name, metadata.namespace