Lors de l'ajout de composants Kubernetes à un modèle de cloud Automation Assembler, vous pouvez choisir d'ajouter des clusters ou d'autoriser les utilisateurs à créer des espaces de noms dans différentes configurations. Généralement, ce choix dépend de vos besoins en matière de contrôle d'accès et de déploiement, ainsi que de la configuration de vos composants Kubernetes.

Pour ajouter un composant Kubernetes à un modèle de cloud dans Automation Assembler, sélectionnez Conception > Modèles, cliquez sur Nouveau à partir de > Canevas vide, puis localisez et développez l'option Kubernetes dans le menu de gauche. Effectuez ensuite la sélection souhaitée, à savoir un cluster Kubernetes ou un espace de noms Kubernetes, par glisser-déposer vers le canevas.

Pour octroyer aux utilisateurs autorisés l'accès aux ressources Kubernetes disponibles, la méthode la plus simple consiste à sélectionner un cluster Kubernetes associé à un projet et à l'ajouter à un modèle de cloud. De même que pour les autres ressources Automation Assembler, vous pouvez utiliser des balises sur les clusters pour contrôler les emplacements auxquels ils sont déployés. Lors du déploiement du cluster, vous pouvez utiliser des balises pour sélectionner une zone et un plan VMware Tanzu Kubernetes Grid Integrated Edition (TKGi) en phase d'allocation.

Une fois que vous avez ajouté un cluster de cette façon, il est automatiquement disponible pour tous les utilisateurs autorisés.

Exemples de modèle de cloud

Le premier exemple montre un modèle de cloud dédié à un déploiement Kubernetes simple contrôlé par balisage. Une zone Kubernetes a été créée avec deux plans de déploiement, configurés sur la page Nouvelle zone Kubernetes. Dans ce cas, une balise nommée placement:tag a été ajoutée sur la zone pour définir la capacité. Elle a été utilisée pour correspondre à la contrainte analogue sur le modèle de cloud. Si plusieurs zones sont configurées avec la balise, celle dont le numéro de priorité est le plus bas est sélectionnée.

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 

Le deuxième exemple montre comment configurer un modèle de cloud avec une variable nommée $(input.hostname) pour permettre aux utilisateurs d'entrer le nom d'hôte de cluster de leur choix lorsqu'ils effectuent une demande de déploiement. Lors du déploiement du cluster, vous pouvez également utiliser les balises pour sélectionner une zone et un plan TKGI en phase d'allocation des ressources.

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

Si vous souhaitez utiliser des espaces de noms pour gérer l'utilisation des clusters, configurez une variable appelé name: ${input.name} dans le modèle de cloud, afin d'utiliser le nom d'espace de noms entré par l'utilisateur lors de la demande d'un déploiement. Pour ce type de déploiement, vous devez créer un modèle semblable à l'exemple suivant :

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}

Les utilisateurs peuvent gérer les clusters déployés à l'aide des fichiers kubeconfig accessibles depuis la page Infrastructure > Ressources > Kubernetes. Localisez la fiche sur la page du cluster souhaité et cliquez sur Kubeconfig.

Espaces de noms de superviseur dans les VMware Cloud Templates

Voici le schéma d'un espace de noms de superviseur de base dans un modèle de cloud 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"
  ]
}

Les modèles de cloud prennent en charge l'utilisation de limites avec les espaces de noms de superviseur. Les limites vous permettent de contrôler l'utilisation des ressources de CPU et de mémoire, ainsi que le nombre maximal d'espaces autorisés dans l'espace de noms par machine déployée.

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'exemple suivant montre comment vous pouvez spécifier une stratégie de stockage à l'aide de balises.

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'

Utilisation de YAML arbitraires avec un espace de noms en libre-service ou des VCT de cluster

Dans le cadre de la création d'un cluster ou d'un espace de noms, vous pouvez exécuter des personnalisations supplémentaires. Par exemple, vous pouvez ajouter des utilisateurs (rôle/liaison de rôle), créer une stratégie de sécurité d'espace ou installer des agents. À l'aide de la propriété YAML content, vous pouvez définir des modules personnalisés à provisionner sur ce cluster/espace de noms/espace de noms de superviseur.

Ce module de contenu YAML associé à la propriété content doit être séparé par un tiret triple (---). En outre, les informations de contenu doivent constituer une chaîne multiligne. Reportez-vous à l'exemple YAML suivant pour voir comment les modules de contenu peuvent être configurés.

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

Le YAML défini dans la propriété de contenu s'affiche également dans l'onglet Propriétés du déploiement.

Automation Assembler ne peut créer que des ressources de contenu dans l'étendue de la ressource en cours de déploiement. Par exemple, si vous provisionnez un espace de noms Kubernetes, Automation Assembler ne peut pas créer un déploiement à l'intérieur d'un espace de noms différent. Les utilisateurs disposent des mêmes droits que s'ils utilisaient kubeconfig avec kubectl.

Une fois la machine virtuelle provisionnée, une installation des objets Kubernetes à l'intérieur de la propriété content commence. Si l'une des ressources référencées dans la propriété de contenu YAML ne parvient pas à assurer le provisionnement, Automation Assembler restaure et supprime tous les objets Kubernetes précédents de la ressource et le déploiement prend l'état Échec. La ressource sera toujours provisionnée et visible. En outre, vous pouvez toujours utiliser les actions du jour 2, notamment essayer d'appliquer à nouveau le contenu.

Vous pouvez améliorer la propriété content avec des entrées du modèle de cloud, comme indiqué dans l'exemple suivant.

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
En outre, vous pouvez provisionner des ressources personnalisées, telles que TanzuKubernetesCluster. Cette opération échouerait en tant qu'opération du jour 1, car l'espace de noms de superviseur ne contient pas les classes de machine virtuelle et les classes de stockage requises. Lorsque les classes de machine virtuelle et les classes de stockage sont liées à l'espace de noms du superviseur, vous pouvez créer TanzuKubernetesCluster (ou une autre ressource) à l'aide de l'action du jour 2.
Note : Vous pouvez provisionner une ressource sans contenu et vous pouvez toujours ajouter des objets Kubernetes en tant que YAML avec l'action du jour 2.

Le contenu qui s'affiche dans la propriété YAML définit ce qui est provisionné sur la ressource. Lorsque vous modifiez ce contenu, le tableau suivant affiche les résultats possibles :

Action Résultat
Si vous ajoutez un objet Kubernetes, puis confirmez l'action. L'objet spécifié est créé sur la ressource.
Si vous supprimez un objet Kubernetes, puis confirmez l'action. L'objet spécifié est supprimé de la ressource.
Si vous modifiez un objet Kubernetes, puis confirmez l'action. L'objet spécifié est corrigé sur la ressource.

Il est important de définir clairement quelles actions sont considérées comme une modification de l'objet actuel. Par exemple, si vous modifiez le champ d'espace de noms d'un objet, un nouvel objet est créé à la place de l'ancien en cours de correction.

L'unicité d'une ressource est définie par les champs suivants : apiVersion, kind, metadata.name, metadata.namespace