Ao adicionar componentes do Kubernetes a um modelo de nuvem do Cloud Assembly, você pode optar por adicionar clusters ou permitir que os usuários criem namespaces em várias configurações. Normalmente, essa escolha depende dos seus requisitos de controle de acesso, de como você configurou seus componentes do Kubernetes e dos seus requisitos de implantação.
Para adicionar um componente do Kubernetes a um modelo de nuvem no Cloud Assembly, clique em , clique em Novo e localize e expanda a opção Kubernetes no menu à esquerda. Em seguida, faça a seleção desejada, Cluster ou Namespace KBS, arrastando-a até a tela.
Adicionar um cluster do Kubernetes associado a um projeto até um modelo de nuvem é o método mais simples de disponibilizar recursos do Kubernetes para usuários válidos. Você pode usar tags em clusters para controlar onde eles são implantados, como você faz com outros recursos do Cloud Assembly. É possível usar tags para selecionar uma zona e um plano do VMware Tanzu Kubernetes Grid Integrated Edition (TKGI) durante a fase de alocação da implantação do cluster.
Ao adicionar um cluster dessa maneira, ele é disponibilizado automaticamente para todos os usuários válidos.
Exemplos de modelos de nuvem
O primeiro exemplo de modelo de nuvem mostra um modelo para uma implantação simples do Kubernetes que é controlada por marcação. Uma zona do Kubernetes foi criada com dois planos de implantação, configurados na página Nova Zona do Kubernetes. Nesse caso, uma tag chamada placement:tag foi adicionada como recurso na zona e foi usada para corresponder à restrição análoga no modelo de nuvem. Se houver mais de uma zona configurada com a tag, aquela com o número de prioridade mais baixa será selecionada.
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
Os segundo exemplo de modelo de nuvem mostra como configurar um modelo com uma variável chamada $(input.hostname), para que os usuários possam inserir o nome do host do cluster desejado ao solicitar uma implantação. Tags também podem ser usadas para selecionar uma zona e um plano do TKGI durante a fase de alocação de recursos da implantação do 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 quiser usar namespaces para gerenciar o uso do cluster, você poderá configurar uma variável no modelo de nuvem chamada name: ${input.name} para substituir o nome do namespace que um usuário insere ao solicitar uma implantação. Para esse tipo de implantação, crie um modelo semelhante ao exemplo a seguir:
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}
Os usuários podem gerenciar clusters implantados por meio de arquivos kubeconfig acessíveis na página . Localize o cartão na página para o cluster desejado e clique em Kubeconfig.
Namespaces de Supervisor em VMware Cloud Templates
Veja a seguir o esquema para um namespace de supervisor básico em um modelo de nuvem do Cloud Assembly.
{
"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"
]
}
Os VMware Cloud Templates oferecem suporte ao uso de limites com namespaces de supervisor. Os limites permitem que você controle o uso de recursos para CPUs e memória, bem como o número máximo de pods permitidos no namespace por máquinas implantadas.
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
O exemplo a seguir mostra como você pode especificar uma política de armazenamento usando tags.
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'
Usando YAMLs arbitrários com VCTs de cluster ou namespace de autoatendimento
Como parte da criação de um cluster ou namespace, os usuários geralmente desejam executar personalizações adicionais. Por exemplo, você pode querer adicionar usuários (associação de função/ função) ou criar uma política de segurança de pod ou instalar agentes. Usando a propriedade YAML content, os usuários podem definir pacotes personalizados que desejam provisionar nesse cluster/namespace /namespace de supervisor.
Cada pacote de conteúdo YAML associado à propriedade content deve ser separado com um traço triplo (---). Além disso, as informações de conteúdo devem ser uma cadeia de caracteres de várias linhas. Consulte o exemplo YAML a seguir para ver como os pacotes de conteúdo podem ser configurados.
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
O YAML definido na propriedade de conteúdo também aparece na guia Propriedades da implantação.
O Cloud Assembly apenas pode criar recursos de conteúdo no escopo do recurso que está sendo implantado. Por exemplo: se você provisionar um namespace do Kubernetes, o Cloud Assembly não poderá criar uma implantação dentro de um namespace diferente. Os usuários têm os mesmos direitos como se estivessem usando o kubeconfig com kubectl.
Depois que a máquina virtual for provisionada, uma instalação dos objetos Kubernetes dentro da propriedade content será iniciada. Se o provisionamento de um dos recursos referenciados na propriedade de conteúdo YAML falhar, o Cloud Assembly reverterá e excluirá todos os objetos Kubernetes anteriores desse recurso, e a implantação terá um status de Falha. O recurso ainda estará provisionado e visível. Além disso, você ainda pode usar ações de dia 2, incluindo tentar aplicar o conteúdo novamente.
Você pode aprimorar a propriedade content com entradas do modelo de nuvem, como mostra o exemplo a seguir.
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
Além disso, você pode provisionar recursos personalizados, como TanzuKubernetesCluster. Isso falharia como uma operação de dia 1, pois o namespace do supervisor não conterá as classes de máquina virtual e as classes de armazenamento necessárias. Quando as classes de máquina virtual e as classes de armazenamento estão vinculadas ao namespace de supervisor, você pode criar TanzuKubernetesCluster (ou outro recurso) usando a ação de dia 2.
Observação: você pode provisionar um recurso sem conteúdo e ainda poderá adicionar objetos Kubernetes como YAML com a ação de dia 2.
O conteúdo que aparece na propriedade YAML define o que é provisionado no recurso. Quando você edita esse conteúdo, a tabela a seguir mostra os resultados possíveis:
| Ação | Resultado |
|---|---|
| Se adicionar um objeto Kubernetes e enviar. | O objeto especificado é criado no recurso. |
| Se remover um objeto Kubernetes e enviar. | O objeto especificado é excluído do recurso. |
| Se modificar um objeto Kubernetes e enviar. | O objeto especificado é corrigido no recurso. |
É importante esclarecer quais ações são consideradas como uma modificação no objeto atual. Por exemplo: se você modificar o campo de namespace de um objeto, um novo objeto será criado no lugar do antigo que está sendo corrigido.
A exclusividade de um recurso é definida pelos seguintes campos: apiVersion, kind, metadata.name e metadata.namespace