Realizar tarefas comuns de configuração de Pods e contêineres
Kubernetes v1.18 [stable]
Esta página mostra como configurar Contas de serviço gerenciadas em grupo (GMSA) para Pods e contêineres que vão executar em nós Windows. Contas de serviço gerenciadas em grupo são um tipo específico de conta do Active Directory que provê gerenciamento automático de senhas, gerenciamento simplificado de service principal name (SPN), e a habilidade de delegar o gerenciamento a outros administradores através de múltiplos servidores.
No Kubernetes, especificações de credenciais GMSA são configuradas dentro do escopo do cluster Kubernetes como recursos personalizados. Os Pods Windows, assim como contêineres individuais dentro de um Pod, podem ser configurados para usar as funções GMSA baseadas em domínio (exemplo: autenticação Kerberos) quando interagirem com outros serviços Windows.
Você precisa ter um cluster Kubernetes, e a ferramenta de linha de comando kubectl
precisa estar configurada para comunicar-se com seu cluster.
O cluster deve possuir nós de carga de trabalho Windows.
Esta seção cobre o conjunto inicial de passos requeridos para cada cluster:
Uma CustomResourceDefinition (CRD) para a especificação de recursos de credencial GMSA precisa ser configurada no cluster, para definir o tipo de recurso do cliente GMSACredentialSpec. Faça o download do YAML do CRD de GMSA
e salve como gmsa-crd.yaml.
A seguir, instale o CRD com kubectl apply -f gmsa-crd.yaml.
Dois webhooks precisam ser configurados no cluster Kubernetes para popular e validar as referências de especificação de credenciais GMSA no nível do Pod ou contêiner:
Um webhook de mutação que expanda as referências para as GMSAs, (por nome a partir de uma especificação de Pod) em uma especificação de credencial completa em formato JSON dentro da especificação do Pod.
Um webhook de validação garante que todas as referências para GMSAs estão autorizadas a serem usadas pela conta de serviço do Pod.
A instalação dos webhooks acima e dos objetos associados requer as etapas abaixo:
Crie um par de chaves de certificado (que será usado para permitir que o contêiner do webhook se comunique com o cluster)
Instale um Secret com o certificado acima.
Crie um Deployment para a lógica principal do webhook.
Crie as configurações de webhook de validação e de mutação, referentes ao Deployment.
Um script
pode ser usado para implantar e configurar os webhooks GMSA e objetos associados
mencionados acima. O script pode ser executado com a opção --dry-run=server
para possibilitar que você possa revisar as alterações antes que sejam aplicadas
no seu cluster.
O template YAML usado pelo script também pode ser usado para implantar os webhooks e objetos associados manualmente (com as substituições apropriadas para os parâmetros).
Antes que os Pods no Kubernetes possam ser configurados para usar GMSAs, as GMSAs apropriadas precisam ser provisionadas no Active Directory como descrito na documentação de GMSA do Windows. Nós de carga de trabalho Windows (que são parte do cluster Kubernetes) precisam ser configurados no Active Directory para acessar as credenciais secretas associadas com a GMSA apropriada, como descrito na documentação de GMSA do Windows.
Com o CRD GMSACredentialSpec instalado (como descrito anteriormente), recursos customizados contendo recursos de especificação de credenciais GMSA podem ser configurados. A especificação de credencial GMSA não contém dados secretos nem sensíveis. É informação que o agente de execução de contêiner pode usar para descrever a apropriada GMSA de um contêiner para o Windows. Especificações de credenciais GMSA podem ser geradas em formato YAML com o utilitário PowerShell script.
A seguir são os passos para gerar a especificação de credencial GMSA YAML manualmente, em formato JSON e então convertê-la para YAML:
Importar o módulo CredentialSpec:
ipmo CredentialSpec.psm1
Crie a especificação da credencial em formato JSON usando New-CredentialSpec.
Para criar a especificação da credencial GMSA nomeada WebApp1,
execute New-CredentialSpec -Name WebApp1 -AccountName WebApp1 -Domain $(Get-ADDomain -Current LocalComputer)
Use Get-CredentialSpec para mostrar o caminho do arquivo JSON.
Converta o arquivo credspec de JSON para o formato YAML e aplique os campos
de cabeçalho necessários apiVersion, kind, metadata e credspec para transformá-lo em
uma instância do recurso customizado GMSACredentialSpec que pode ser configurado no Kubernetes.
A configuração YAML a seguir descreve as especificações de credencial GMSA nomeada
gmsa-WebApp1:
apiVersion: windows.k8s.io/v1
kind: GMSACredentialSpec
metadata:
name: gmsa-WebApp1 #Este é um nome arbitrário, mas será usado como referência
credspec:
ActiveDirectoryConfig:
GroupManagedServiceAccounts:
- Name: WebApp1 #Nome de usuário da conta GMSA
Scope: CONTOSO #Nome de Domínio NETBIOS
- Name: WebApp1 #Nome de usuário da conta GMSA
Scope: contoso.com #Nome de domínio DNS
CmsPlugins:
- ActiveDirectory
DomainJoinConfig:
DnsName: contoso.com #Nome de domínio DNS
DnsTreeName: contoso.com #Nome de domínio DNS raiz
Guid: 244818ae-87ac-4fcd-92ec-e79e5252348a #GUID
MachineAccountName: WebApp1 #Nome de usuário da conta GMSA
NetBiosName: CONTOSO #Nome de domínio NETBIOS
Sid: S-1-5-21-2126449477-2524075714-3094792973 #SID da GMSA
O recurso de especificação de credencial acima deve ser salvo como
gmsa-Webapp1-credspec.yaml e aplicado no cluster usando:
kubectl apply -f gmsa-Webapp1-credspec.yml
Uma ClusterRole precisa ser definida para cada recurso de especificação
de credencial GMSA. Isto autoriza o verbo use em um recurso GMSA específico
por um sujeito, geralmente uma conta de serviço. O exemplo a seguir mostra
um ClusterRole que autoriza o uso de credencial gmsa-WebApp1
acima. Salve o arquivo como gmsa-webapp1-role.yaml e aplique
usando kubectl apply -f gmsa-webapp1-role.yaml
#Criando um Role para ler o credspec
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: webapp1-role
rules:
- apiGroups: ["windows.k8s.io"]
resources: ["gmsacredentialspecs"]
verbs: ["use"]
resourceNames: ["gmsa-WebApp1"]
Uma conta de serviço (com a qual os Pods virão configurados), precisa ser vinculada
ao ClusterRole criado acima. Isto autoriza a conta de serviço a usar a especificação apropriada
de recurso de credencial GMSA. O trecho a seguir mostra a conta de serviço padrão vinculada ao ClusterRole webapp1-role, para usar a especificação
de recurso de credencial gmsa-WebApp1 criada acima.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: allow-default-svc-account-read-on-gmsa-WebApp1
namespace: default
subjects:
- kind: ServiceAccount
name: default
namespace: default
roleRef:
kind: ClusterRole
name: webapp1-role
apiGroup: rbac.authorization.k8s.io
O campo securityContext.windowsOptions.gmsaCredentialSpecName do Pod, é usado de referência para recursos customizados, em especificações
de certificado GMSA apropriadas em especificações do Pod.
Isto configura todos contêineres do Pod para usar GMSA.
Uma amostra da anotação populada para referir-se a gmsa-WebApp1:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: with-creds
name: with-creds
namespace: default
spec:
replicas: 1
selector:
matchLabels:
run: with-creds
template:
metadata:
labels:
run: with-creds
spec:
securityContext:
windowsOptions:
gmsaCredentialSpecName: gmsa-webapp1
containers:
- image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
imagePullPolicy: Always
name: iis
nodeSelector:
kubernetes.io/os: windows
Contêineres individuais em uma especificação de Pod podem também indicar
a credencial GMSA apropriada, usando o campo securityContext.windowsOptions.gmsaCredentialSpecName por contêiner. Por exemplo:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: with-creds
name: with-creds
namespace: default
spec:
replicas: 1
selector:
matchLabels:
run: with-creds
template:
metadata:
labels:
run: with-creds
spec:
containers:
- image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
imagePullPolicy: Always
name: iis
securityContext:
windowsOptions:
gmsaCredentialSpecName: gmsa-Webapp1
nodeSelector:
kubernetes.io/os: windows
Assim que as especificações do Pod com os campos GMSA preenchidos (como descrito acima) são aplicadas em um cluster, ocorre a seguinte sequência de eventos:
O webhook de mutação resolve e expande todas as referências aos recursos de especificações de credenciais GMSA para o conteúdo das especificações de credenciais GMSA.
O webhook de validação garante que a conta de serviço associada ao Pod, seja autorizada
para o verbo use na especificação GMSA especificada.
O agente de execução de contêiner configura cada contêiner do Windows com a especificação de credencial GMSA especificada, para que o contêiner possa assumir a identidade do GMSA no Active Directory, e tenha acesso aos serviços no domínio usando essa identidade.
hostname ou FQDNSe você estiver enfrentando problemas ao se conectar aos compartilhamentos SMB de Pods usando o hostname ou o FQDN, mas conseguindo acessar os compartilhamentos por meio de seu endereço IPv4, verifique se a chave do registro a seguir está definida nos nós Windows.
reg add "HKLM\SYSTEM\CurrentControlSet\Services\hns\State" /v EnableCompartmentNamespace /t REG_DWORD /d 1
Os Pods em execução precisarão ser recriados para pegar as mudanças de comportamento. Mais informações sobre como essa chave de registro é usada podem ser encontradas aqui
Se você estiver tendo dificuldades para fazer com que o GMSA funcione em seu ambiente, existem algumas etapas de solução de problemas que você pode tentar.
Primeiro, verifique se a especificação de credencial foi passada para o Pod. Para fazer isso,
você precisará rodar kubectl exec em um de seus Pods e verificar
a saída do comando nltest.exe /parentdomain.
No exemplo abaixo, o Pod não recebeu a especificação de credencial corretamente:
kubectl exec -it iis-auth-7776966999-n5nzr powershell.exe
nltest.exe /parentdomain resulta no seguinte erro:
Getting parent domain failed: Status = 1722 0x6ba RPC_S_SERVER_UNAVAILABLE
Se o seu Pod obteve a especificação de credencial corretamente, o próximo passo é
verificar a comunicação com o domínio. Primeiro, de dentro do seu Pod,
execute rapidamente um nslookup para encontrar a raiz do seu domínio.
Isso vai nos dizer 3 coisas:
Se o DNS e o teste de comunicação passarem, em seguida,
você precisará verificar se o Pod estabeleceu um canal de comunicação segura
com o domínio. Para fazer isso, novamente, em seu Pod
execute o comando nltest.exe /query.
nltest.exe /query
Resulta na seguinte saída:
I_NetLogonControl failed: Status = 1722 0x6ba RPC_S_SERVER_UNAVAILABLE
Isso nos diz que, por algum motivo, o Pod não conseguiu se logar no domínio usando a conta definida na especificação de credencial. Você pode tentar reparar o canal seguro executando o seguinte:
nltest /sc_reset:domain.example
Se o comando for bem sucedido, você verá uma saída semelhante a esta:
Flags: 30 HAS_IP HAS_TIMESERV
Trusted DC Name \\dc10.domain.example
Trusted DC Connection Status Status = 0 0x0 NERR_Success
The command completed successfully
Se o excerto acima corrigir o erro, você poderá automatizar a etapa adicionando
o seguinte lifecycle hook à sua especificação de Pod. Se não corrigiu o erro, você
precisará examinar sua especificação de credencial novamente e confirmar que ela está correta e completa.
image: registry.domain.example/iis-auth:1809v1
lifecycle:
postStart:
exec:
command: ["powershell.exe","-command","do { Restart-Service -Name netlogon } while ( $($Result = (nltest.exe /query); if ($Result -like '*0x0 NERR_Success*') {return $true} else {return $false}) -eq $false)"]
imagePullPolicy: IfNotPresent
Se você adicionar a seção lifecycle, mostrada acima à sua especificação de Pod,
o Pod irá executar os comandos listados para reiniciar o serviço netlogon
até que o comando nltest.exe /query execute sem erro.
Kubernetes v1.18 [stable]
Esta página mostra como usar a configuração runAsUserName para Pods
e contêineres que serão executados em nós Windows. Isso é aproximadamente
equivalente à configuração runAsUser específica do Linux, permitindo a você
executar aplicativos em um contêiner com um nome de usuário diferente do padrão.
Você precisa ter um cluster Kubernetes, e a ferramenta de linha de comando Kubectl deve ser configurada para se comunicar com o seu cluster. Espera-se que o cluster tenha nós de carga de trabalho Windows, onde os Pods com contêineres executando as cargas de trabalho do Windows, serão agendados.
Para especificar o nome de usuário com o qual executar os processos de contêiner do Pod,
inclua o campo securityContext (PodSecurityContext)
na especificação do Pod, e dentro dela, o campo WindowsOptions (WindowsSecurityContextOptions)
contendo o campo runAsUserName.
As opções de contexto de segurança do Windows que você especificar para um Pod, se aplicam a todos os contêineres do Pod, inclusive os de inicialização.
Veja abaixo um arquivo de configuração para um Pod do Windows que possui o campo
runAsUserName definido:
apiVersion: v1
kind: Pod
metadata:
name: run-as-username-pod-demo
spec:
securityContext:
windowsOptions:
runAsUserName: "ContainerUser"
containers:
- name: run-as-username-demo
image: mcr.microsoft.com/windows/servercore:ltsc2019
command: ["ping", "-t", "localhost"]
nodeSelector:
kubernetes.io/os: windowsCrie o Pod:
kubectl apply -f https://k8s.io/examples/windows/run-as-username-pod.yaml
Verifique se o contêiner do Pod está em execução:
kubectl get pod run-as-username-pod-demo
Abra um shell para o contêiner em execução:
kubectl exec -it run-as-username-pod-demo -- powershell
Verifique se o shell está executando com o nome de usuário correto:
echo $env:USERNAME
A saída deve ser:
ContainerUser
Para especificar o nome de usuário com o qual executar os processos de um contêiner,
inclua o campo SecurityContext (SecurityContext)
no manifesto do contêiner, e dentro dele, o campo WindowsOptions
(WindowsSecurityContextOptions)
contendo o campo runAsUserName.
As opções de contexto de segurança do Windows que você especificar para um contêiner, se aplicam apenas a esse contêiner individual, e substituem as configurações feitas no nível do Pod.
Aqui está o arquivo de configuração para um pod que possui um contêiner,
e o campo runAsUserName está definido no nível do Pod e no nível do contêiner:
apiVersion: v1
kind: Pod
metadata:
name: run-as-username-container-demo
spec:
securityContext:
windowsOptions:
runAsUserName: "ContainerUser"
containers:
- name: run-as-username-demo
image: mcr.microsoft.com/windows/servercore:ltsc2019
command: ["ping", "-t", "localhost"]
securityContext:
windowsOptions:
runAsUserName: "ContainerAdministrator"
nodeSelector:
kubernetes.io/os: windows
Crie o Pod:
kubectl apply -f https://k8s.io/examples/windows/run-as-username-container.yaml
Verifique se o contêiner do Pod está em execução:
kubectl get pod run-as-username-container-demo
Abra um shell para o contêiner em execução:
kubectl exec -it run-as-username-container-demo -- powershell
Verifique se o shell está executando o usuário correto, (aquele definido no nível do contêiner):
echo $env:USERNAME
A saída deve ser:
ContainerAdministrator
Para usar esse recurso, o valor definido no campo runAsUserName deve ser um nome
de usuário válido. Deve ter o seguinte formato: DOMAIN\USER, onde DOMAIN\
é opcional. Os nomes de usuário do Windows não diferenciam letras maiúsculas
e minúsculas. Além disso, existem algumas restrições em relação ao DOMAIN e USER:
runAsUserName: não pode estar vazio, e não pode conter caracteres
de controle (Valores ASCII : 0x00-0x1F, 0x7F)DOMAIN NetBios, ou um nome de DNS, cada um com suas próprias restrições:
. (ponto),
e não podem conter os seguintes caracteres: \ / : * ? " < > |. (ponto) ou - (traço).USER: deve ter no máximo 20 caracteres, não pode conter somente pontos ou espaços,
e não pode conter os seguintes caracteres: " / \ [ ] : ; | = , + * ? < > @.Exemplos de valores aceitáveis para o campo runAsUserName: ContainerAdministrator,
ContainerUser, NT AUTHORITY\NETWORK SERVICE, NT AUTHORITY\LOCAL SERVICE.
Para mais informações sobre estas limitações, verifique aqui e aqui.
Esta página mostra como configurar os Pods para que, a eles sejam atribuídos particularmente classes de Qualidade de Serviço (QoS). O Kubernetes usa classes QoS para tomar decisões sobre agendamento e despejo de Pods.
Você precisa ter um cluster do Kubernetes e a ferramenta de linha de comando kubectl deve estar configurada para se comunicar com seu cluster. É recomendado executar esse tutorial em um cluster com pelo menos dois nós que não estejam atuando como hosts de camada de gerenciamento. Se você ainda não possui um cluster, pode criar um usando o minikube ou pode usar um dos seguintes ambientes:
Para verificar a versão, digite kubectl version.
Quando o Kubernetes cria um Pod, ele atribui uma dessas classes de QoS ao Pod:
Crie um namespace, assim os seus recursos criados neste exercício estarão isolados do resto do seu cluster.
kubectl create namespace qos-example
GuaranteedPara que um Pod receba uma classe de QoS Guaranteed:
Essas restrições se aplicam igualmente a contêineres de inicialização bem como de aplicativos.
Aqui está o arquivo de configuração para um pod que possui um contêiner. O contêiner tem um limite de memória e um requisito de memória, ambos iguais a 200 MiB. O contêiner tem um limite de CPU e uma solicitação de CPU, ambos iguais a 700 miliCPU:
apiVersion: v1
kind: Pod
metadata:
name: qos-demo
namespace: qos-example
spec:
containers:
- name: qos-demo-ctr
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "700m"
requests:
memory: "200Mi"
cpu: "700m"
Crie o Pod:
kubectl apply -f https://k8s.io/examples/pods/qos/qos-pod.yaml --namespace=qos-example
Veja informações detalhadas sobre o pod:
kubectl get pod qos-demo --namespace=qos-example --output=yaml
A saída mostra que o Kubernetes forneceu ao pod uma classe de QoS Guaranteed. A saída também
verifica se o contêiner do Pod tem um requisito de memória que corresponde ao seu limite de memória, e possui
um requisito de CPU que corresponde ao seu limite de CPU.
spec:
containers:
...
resources:
limits:
cpu: 700m
memory: 200Mi
requests:
cpu: 700m
memory: 200Mi
...
status:
qosClass: Guaranteed
Apague seu Pod:
kubectl delete pod qos-demo --namespace=qos-example
BurstableUm Pod recebe uma classe de QoS Burstable se:
Guaranteed.Aqui está o arquivo de configuração para um Pod que possui um contêiner. O contêiner tem um limite de memória de 200 MiB e um requisito de memória de 100 MiB.
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-2
namespace: qos-example
spec:
containers:
- name: qos-demo-2-ctr
image: nginx
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
Crie o Pod:
kubectl apply -f https://k8s.io/examples/pods/qos/qos-pod-2.yaml --namespace=qos-example
Veja informações detalhadas sobre o Pod:
kubectl get pod qos-demo-2 --namespace=qos-example --output=yaml
A saída mostra que o Kubernetes forneceu ao pod uma classe de QoS Burstable.
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: qos-demo-2-ctr
resources:
limits:
memory: 200Mi
requests:
memory: 100Mi
...
status:
qosClass: Burstable
Apague seu Pod:
kubectl delete pod qos-demo-2 --namespace=qos-example
BestEffortPara que um Pod receba uma classe de QoS BestEffort, os contêineres no pod não devem
ter quaisquer requisitos ou limites de CPU ou memória.
Aqui está o arquivo de configuração para um Pod que possui um contêiner. O contêiner não tem requisitos ou limites de memória ou CPU:
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-3
namespace: qos-example
spec:
containers:
- name: qos-demo-3-ctr
image: nginx
Crie o Pod:
kubectl apply -f https://k8s.io/examples/pods/qos/qos-pod-3.yaml --namespace=qos-example
Veja informações detalhadas sobre o Pod:
kubectl get pod qos-demo-3 --namespace=qos-example --output=yaml
A saída mostra que o Kubernetes forneceu ao Pod uma classe de QoS BestEffort.
spec:
containers:
...
resources: {}
...
status:
qosClass: BestEffort
Apague seu Pod:
kubectl delete pod qos-demo-3 --namespace=qos-example
Aqui está o arquivo de configuração para um Pod que possui dois contêineres. Um contêiner especifica um requisito de memória de 200 MiB. O outro contêiner não especifica nenhum requisito ou limite.
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-4
namespace: qos-example
spec:
containers:
- name: qos-demo-4-ctr-1
image: nginx
resources:
requests:
memory: "200Mi"
- name: qos-demo-4-ctr-2
image: redis
Observe que este Pod atende aos critérios para a classe de QoS Burstable. Isto é, ele não atende aos
critérios para a classe de QoS Guaranteed, e um de seus contêineres tem um requisito de memória.
Crie o Pod:
kubectl apply -f https://k8s.io/examples/pods/qos/qos-pod-4.yaml --namespace=qos-example
Veja informações detalhadas sobre o Pod:
kubectl get pod qos-demo-4 --namespace=qos-example --output=yaml
A saída mostra que o Kubernetes forneceu ao pod uma classe de QoS Burstable:
spec:
containers:
...
name: qos-demo-4-ctr-1
resources:
requests:
memory: 200Mi
...
name: qos-demo-4-ctr-2
resources: {}
...
status:
qosClass: Burstable
Apague seu Pod:
kubectl delete pod qos-demo-4 --namespace=qos-example
Apague seu namespace:
kubectl delete namespace qos-example
Configurar Requisitos e Limites de Memória Padrão Para um Namespace
Configurar Requisitos e Limites Padrão de CPU Para um Namespace
Configurar Restrições de Memória Mínima e Máxima Para um Namespace
Configurar Restrições Mínimas e Máximas de CPU Para um Namespace
Topologia de Controle de Gerenciamento de Politicas em um Nó
Kubernetes v1.35 [alpha](desabilitado por padrão)Esta página explica como alterar os recursos de CPU e memória definidos no nível do Pod sem recriá-lo.
A funcionalidade de redimensionamento de Pod em vigor permite modificar alocações de recursos para um Pod em execução, evitando a interrupção da aplicação. O processo para redimensionar recursos de contêineres individuais é abordado em Redimensionar recursos de CPU e memória atribuídos a contêineres.
Esta página destaca o redimensionamento de recursos em vigor no nível do Pod. Os recursos no nível do Pod são definidos em spec.resources e atuam como o limite superior dos recursos agregados consumidos por todos os contêineres no Pod. A funcionalidade de redimensionamento de recursos em vigor no nível do Pod permite alterar essas alocações agregadas de CPU e memória para um Pod em execução diretamente.
Você precisa ter um cluster do Kubernetes e a ferramenta de linha de comando kubectl deve estar configurada para se comunicar com seu cluster. É recomendado executar esse tutorial em um cluster com pelo menos dois nós que não estejam atuando como hosts de camada de gerenciamento. Se você ainda não possui um cluster, pode criar um usando o minikube ou pode usar um dos seguintes ambientes:
O seu servidor Kubernetes deve estar numa versão igual ou superior a 1.35.Para verificar a versão, digite kubectl version.
Os seguintes feature gates devem estar habilitados para sua camada de gerenciamento e para todos os nós do seu cluster:
InPlacePodLevelResourcesVerticalScalingPodLevelResourcesInPlacePodVerticalScalingNodeDeclaredFeaturesA versão do cliente kubectl deve ser pelo menos v1.32 para usar a flag --subresource=resize.
O mecanismo que o kubelet usa para rastrear e tentar efetuar novamente alterações de recursos é compartilhado entre solicitações de redimensionamento no nível do contêiner e no nível do Pod.
Os status, motivos e prioridades de retentativa são idênticos aos definidos para redimensionamento de contêiner:
Condições de status: O kubelet usa PodResizePending (com motivos como Infeasible ou Deferred) e PodResizeInProgress para comunicar o estado da solicitação.
Prioridade de retentativa: Redimensionamentos adiados são repetidos com base em PriorityClass, depois na classe de QoS (Guaranteed sobre Burstable) e, finalmente, pela duração em que foram adiados.
Rastreamento: Você pode usar os campos observedGeneration para rastrear qual especificação do Pod (metadata.generation) corresponde ao status da última solicitação de redimensionamento processada.
Para uma descrição completa dessas condições e lógica de retentativa, consulte a seção Status de redimensionamento do Pod na documentação de redimensionamento de contêiner.
O redimensionamento de recursos no nível do Pod não suporta nem requer sua própria política de reinicialização.
Sem política no nível do Pod: Alterações nos recursos agregados do Pod (spec.resources) são sempre aplicadas na versão em vigor sem acionar uma reinicialização. Isso ocorre porque os recursos no nível do Pod atuam como uma restrição geral no cgroup do Pod e não gerenciam diretamente o agente de execução da aplicação dentro dos contêineres.
Política de contêiner ainda governa: A resizePolicy ainda deve ser configurada no nível do contêiner (spec.containers[*].resizePolicy). Esta política determina se um contêiner individual é reiniciado quando suas solicitações ou limites de recursos mudam, independentemente de essa alteração ter sido iniciada por um redimensionamento direto no nível do contêiner ou por uma atualização no envelope geral de recursos no nível do Pod.
Para o Kubernetes 1.35, o redimensionamento de recursos no nível do Pod em vigor está sujeito a todas as limitações descritas para o redimensionamento de recursos no nível do contêiner, que você pode encontrar aqui: Redimensionar recursos de CPU e memória atribuídos a contêineres: Limitações.
Além disso, a seguinte restrição é específica para o redimensionamento de recursos no nível do Pod:
Validação de solicitações de contêiner: Um redimensionamento só é permitido se as solicitações de recursos resultantes no nível do Pod (spec.resources.requests) forem maiores ou iguais à soma das solicitações de recursos correspondentes de todos os contêineres individuais dentro do Pod. Isso mantém a disponibilidade mínima garantida de recursos para o Pod.
Validação de limites de contêiner: Um redimensionamento é permitido se os limites de contêineres individuais forem menores ou iguais aos limites de recursos no nível do Pod (spec.resources.limits). O limite no nível do Pod serve como um limite que nenhum contêiner individual pode exceder, mas a soma dos limites de contêineres pode exceder o limite no nível do Pod, permitindo o compartilhamento de recursos entre contêineres dentro do Pod.
Primeiro, crie um Pod projetado para redimensionamento de CPU em vigor e redimensionamento de memória que requer reinicialização.
apiVersion: v1
kind: Pod
metadata:
name: pod-level-resize-demo
spec:
containers:
- name: pause
image: registry.k8s.io/pause:3.9
resizePolicy:
- resourceName: cpu
restartPolicy: NotRequired # Padrão, mas explícito aqui
- resourceName: memory
restartPolicy: RestartContainer
resources:
requests:
cpu: 100m
memory: 100Mi
- name: nginx-server
image: registry.k8s.io/nginx:latest
resizePolicy:
- resourceName: cpu
restartPolicy: RestartContainer
- resourceName: memory
restartPolicy: RestartContainer
resources: # Recursos no nível do Pod
requests:
cpu: 200m
memory: 200Mi
limits:
cpu: 200m
memory: 200Mi
Crie o Pod:
kubectl create -f pod-level-resize.yaml
Este Pod inicia na classe de QoS Guaranteed, pois as solicitações no nível do Pod são iguais aos limites. Verifique seu estado inicial:
# Aguarde um momento para o Pod estar em execução
kubectl get pod pod-level-resize-demo --output=yaml
Observe o spec.resources (200m CPU, 200Mi memória). Note o
status.containerStatuses[0].restartCount (deve ser 0) e
status.containerStatuses[1].restartCount (deve ser 0).
Agora, aumente a solicitação e o limite de CPU no nível do Pod para 300m. Você usa kubectl patch com o argumento de linha de comando --subresource resize.
kubectl patch pod resize-demo --subresource resize --patch \
'{"spec":{"resources":{"requests":{"cpu":"300m"}, "limits":{"cpu":"300m"}}}}'
# Métodos alternativos:
# kubectl -n qos-example edit pod resize-demo --subresource resize
# kubectl -n qos-example apply -f <updated-manifest> --subresource resize --server-side
--subresource resize requer a versão v1.32.0 ou posterior do cliente kubectl.
Versões mais antigas reportarão um erro invalid subresource.Verifique o status do Pod novamente após aplicar o patch:
kubectl get pod pod-level-resize-demo --output=yaml
Você deve ver:
spec.resources.requests e spec.resources.limits agora mostram cpu: 300m.status.containerStatuses[0].restartCount permanece 0, porque a
resizePolicy de CPU era NotRequired.status.containerStatuses[1].restartCount aumentou para 1 indicando que o
contêiner foi reiniciado para aplicar a alteração de CPU. A reinicialização ocorreu no Contêiner 1 apesar do redimensionamento ser aplicado no nível do Pod, devido à relação intrincada entre limites no nível do Pod e políticas no nível do contêiner. Como o Contêiner 1 não especificou um limite de CPU explícito, sua configuração de recursos subjacente (por exemplo, cgroups) adotou implicitamente o limite geral de CPU do Pod como seu limite máximo efetivo de consumo. Quando o limite de CPU no nível do Pod foi alterado de 200m para 300m, essa ação consequentemente mudou o limite implícito aplicado ao Contêiner 1. Como o Contêiner 1 tinha sua resizePolicy explicitamente definida como RestartContainer para CPU, o kubelet foi obrigado a reiniciar o contêiner para aplicar corretamente essa alteração no mecanismo subjacente de aplicação de recursos, confirmando assim que alterar limites no nível do Pod pode acionar políticas de reinicialização de contêiner mesmo quando os limites de contêiner não são definidos diretamente.Exclua o Pod:
kubectl pod-level-resize-demo
Configurar solicitações e limites de memória padrão para um Namespace
Configurar solicitações e limites de CPU padrão para um Namespace
Configurar restrições mínimas e máximas de memória para um Namespace
Configurar restrições mínimas e máximas de CPU para um Namespace
Kubernetes v1.35 [stable]
Esta página mostra como atribuir recursos estendidos a um Contêiner.
Você precisa ter um cluster do Kubernetes e a ferramenta de linha de comando kubectl deve estar configurada para se comunicar com seu cluster. É recomendado executar esse tutorial em um cluster com pelo menos dois nós que não estejam atuando como hosts de camada de gerenciamento. Se você ainda não possui um cluster, pode criar um usando o minikube ou pode usar um dos seguintes ambientes:
Para verificar a versão, digite kubectl version.
Antes de fazer este exercício, faça o exercício em Anunciar recursos estendidos para um Nó. Isso configurará um de seus nós para anunciar um recurso de dongle.
Para solicitar um recurso estendido, inclua o campo resources:requests no seu
manifesto do contêiner. Recursos estendidos são totalmente qualificados
com qualquer domínio fora do *.kubernetes.io/. Nomes de recursos estendidos válidos
tem a forma de example.com/foo, onde example.com é substituído pelo domínio
da sua organização e foo é um nome descritivo de recurso.
Aqui está o arquivo de configuração para um pod que possui um contêiner:
apiVersion: v1
kind: Pod
metadata:
name: extended-resource-demo
spec:
containers:
- name: extended-resource-demo-ctr
image: nginx
resources:
requests:
example.com/dongle: 3
limits:
example.com/dongle: 3
No arquivo de configuração, você pode ver que o contêiner solicita 3 dongles.
Crie um Pod:
kubectl apply -f https://k8s.io/examples/pods/resource/extended-resource-pod.yaml
Verifique se o pod está em execução:
kubectl get pod extended-resource-demo
Descreva o pod:
kubectl describe pod extended-resource-demo
A saída mostra as solicitações de dongle:
Limits:
example.com/dongle: 3
Requests:
example.com/dongle: 3
Aqui está o arquivo de configuração para um pod que possui um contêiner. O contêiner solicita dois dongles.
apiVersion: v1
kind: Pod
metadata:
name: extended-resource-demo-2
spec:
containers:
- name: extended-resource-demo-2-ctr
image: nginx
resources:
requests:
example.com/dongle: 2
limits:
example.com/dongle: 2
O Kubernetes não poderá satisfazer o pedido de dois dongles, porque o primeiro pod usou três dos quatro dongles disponíveis.
Tente criar um pod:
kubectl apply -f https://k8s.io/examples/pods/resource/extended-resource-pod-2.yaml
Descreva o pod:
kubectl describe pod extended-resource-demo-2
A saída mostra que o pod não pode ser agendado, porque não há nó que tenha 2 dongles disponíveis:
Conditions:
Type Status
PodScheduled False
...
Events:
...
... Warning FailedScheduling pod (extended-resource-demo-2) failed to fit in any node
fit failure summary on nodes : Insufficient example.com/dongle (1)
Veja o status do pod:
kubectl get pod extended-resource-demo-2
A saída mostra que o Pod foi criado, mas não está programado para ser executado em um nó. Tem um status de pendente:
NAME READY STATUS RESTARTS AGE
extended-resource-demo-2 0/1 Pending 0 6m
Exclua os Pods que você criou para este exercício:
kubectl delete pod extended-resource-demo
kubectl delete pod extended-resource-demo-2
Esta página mostra como configurar um Pod para usar um Volume para armazenamento.
O sistema de arquivos de um contêiner apenas existe enquanto o contêiner existir.
Então, quando um contêiner termina e reinicia, as alterações do sistema de arquivos
são perdidas.
Para um armazenamento mais consistente, independente do contêiner, você pode usar um
Volume. Isso é especialmente importante para aplicações
stateful, tal como armazenamentos chave-valor (tal como Redis) e bancos de dados.
Você precisa ter um cluster do Kubernetes e a ferramenta de linha de comando kubectl deve estar configurada para se comunicar com seu cluster. É recomendado executar esse tutorial em um cluster com pelo menos dois nós que não estejam atuando como hosts de camada de gerenciamento. Se você ainda não possui um cluster, pode criar um usando o minikube ou pode usar um dos seguintes ambientes:
Para verificar a versão, digite kubectl version.
Neste exercício, você cria um Pod que executa um contêiner. Este Pod tem um Volume do tipo emptyDir que persiste durante a existência do Pod, mesmo que o contêiner termine e reinicie. Aqui está o arquivo de configuração para o pod:
apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: redis
volumeMounts:
- name: redis-storage
mountPath: /data/redis
volumes:
- name: redis-storage
emptyDir: {}
Crie o Pod:
kubectl apply -f https://k8s.io/examples/pods/storage/redis.yaml
Verifique se o contêiner do pod está funcionando, e então procure por mudanças no Pod:
kubectl get pod redis --watch
A saída se parece com isso:
NAME READY STATUS RESTARTS AGE
redis 1/1 Running 0 13s
Em outro terminal, pegue um shell para o contêiner em execução:
kubectl exec -it redis -- /bin/bash
No seu shell, vá para /data/redis, e então crie um arquivo:
root@redis:/data# cd /data/redis/
root@redis:/data/redis# echo Hello > test-file
No seu shell, liste os processos em execução:
root@redis:/data/redis# apt-get update
root@redis:/data/redis# apt-get install procps
root@redis:/data/redis# ps aux
A saída é semelhante a esta:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
redis 1 0.1 0.1 33308 3828 ? Ssl 00:46 0:00 redis-server *:6379
root 12 0.0 0.0 20228 3020 ? Ss 00:47 0:00 /bin/bash
root 15 0.0 0.0 17500 2072 ? R+ 00:48 0:00 ps aux
Em seu shell, encerre o processo do Redis:
root@redis:/data/redis# kill <pid>
Onde <pid> é o process ID (PID) do Redis.
No seu terminal original, preste atenção nas mudanças no Pod do Redis. Eventualmente, você vai ver algo assim:
NAME READY STATUS RESTARTS AGE
redis 1/1 Running 0 13s
redis 0/1 Completed 0 6m
redis 1/1 Running 1 6m
Neste ponto, o Contêiner terminou e reiniciou. Isso porque o Pod do Redis tem uma
restartPolicy
de Always.
Abra um shell dentro do Contêiner reiniciado:
kubectl exec -it redis -- /bin/bash
No seu shell, vá para /data/redis, e verifique se test-file ainda está lá.
root@redis:/data/redis# cd /data/redis/
root@redis:/data/redis# ls
test-file
Exclua o pod que você criou para este exercício:
kubectl delete pod redis
Veja Volume.
Veja Pod.
Além do armazenamento de disco local fornecido por emptyDir, o Kubernetes
suporta muitas soluções de armazenamento diferentes, conectadas via rede, incluindo PD na
GCE e EBS na EC2, que são preferidos para dados críticos e vão lidar com os
detalhes, como montar e desmontar os dispositivos nos Nós. Veja
Volumes para mais detalhes.
Esta página mostra como configurar um Pod para usar um PersistentVolumeClaim para armazenamento. Aqui está o resumo do processo:
Você, como administrador do cluster, faz a criação de um Volume Persistente suportado por armazenamento físico. Você não associa o volume a nenhum Pod.
Você, agora assumindo o papel de desenvolvedor/usuário do cluster, faz a criação de um PersistentVolumeClaim que é automaticamente vinculado ao Volume Persistente adequado.
Você cria um Pod que usa o PersistentVolumeClaim acima para armazenamento.
Você precisa ter um cluster Kubernetes que tenha apenas um nó, e a ferramenta de linha de comando kubectl configurada para se comunicar com seu cluster. Se você ainda não tem um cluster de um único nó, você pode criar um usando o Minikube.
Familiarize-se com o material em Volumes persistentes.
Abra um shell no único nó do seu cluster. A maneira de abrir um shell vai depender de como
você inicializou seu cluster. Por exemplo, se você estiver usando o Minikube,
você pode abrir um shell para o seu nó digitando minikube ssh.
No seu shell desse nó, crie um diretótio /mnt/data:
# Assumindo que o seu nó use "sudo" para executar comandos
# como superusuário
sudo mkdir /mnt/data
content/pt-br/docs/tasks/configure-pod-container/configure-service-account.md
No diretório /mnt/data, crie o arquivo index.html:
# Novamente assumindo que seu nó use "sudo" para executar comandos
# como superusuário
sudo sh -c "echo 'Hello from Kubernetes storage' > /mnt/data/index.html"
sudo, você pode
geralmente fazer isso funcionar substituindo sudo pelo nome da outra ferramenta.Teste se o arquivo index.html existe:
cat /mnt/data/index.html
A saída deve ser:
Hello from Kubernetes storage
Você agora pode fechar o shell do seu nó.
Neste exercício, você cria um Volume Persistente hostPath. O Kubernetes suporta
hostPath para desenvolvimento e teste em um cluster com apenas um nó. Um Volume Persistente
hostPath usa um arquivo ou diretório no nó, para emular um armazenamento conectado pela rede.
Em um cluster de produção, você não usaria hostPath. Em vez disso um administrador
de cluster provisionaria um recurso de rede, como um disco persistente do
Google Compute Engine, um NFS compartilhado, ou um volume do
Amazon Elastic Block Store. Administradores podem também usar classes de armazenamento
para incializar provisionamento dinâmico.
Aqui está o arquivo de configuração para o Volume Persistente hostPath:
apiVersion: v1
kind: PersistentVolume
metadata:
name: task-pv-volume
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"
O arquivo de configuração especifica que o volume está no diretório /mnt/data do nó do cluster.
A configuração também especifica um tamanho de 10 gibibytes e um modo de acesso
ReadWriteOnce, o que significa que o volume pode ser montado como leitura-escrita
pelo único nó. Define o nome da classe de armazenamento
manual para o Volume Persistente, que será usado para vincular requisições
PersistentVolumeClaim à esse Volume Persistente.
Crie o Volume Persistente:
kubectl apply -f https://k8s.io/examples/pods/storage/pv-volume.yaml
Veja informações do Volume Persistente:
kubectl get pv task-pv-volume
A saída mostra que o Volume Persistente tem um STATUS de Available. Isto
significa que ainda não foi vinculado a um PersistentVolumeClaim.
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM STORAGECLASS REASON AGE
task-pv-volume 10Gi RWO Retain Available manual 4s
PersistentVolumeClaimO próximo passo é criar um PersistentVolumeClaim. Pods usam PersistentVolumeClaims
para requisitar armazenamento físico. Neste exercício, você vai criar
um PersistentVolumeClaim que requisita um volume com pelo menos três
gibibytes, com acesso de leitura-escrita para pelo menos um nó.
Aqui está o arquivo de configuração para oPersistentVolumeClaim:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: task-pv-claim
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
Crie o PersistentVolumeClaim:
kubectl apply -f https://k8s.io/examples/pods/storage/pv-claim.yaml
Após criar o PersistentVolumeClaim, o Kubernetes control plane procura por um
Volume Persistente que satisfaça os requerimentos reivindicados. Se o control plane
encontrar um Volume Persistente adequado, com a mesma classe de armazenamento,
ele liga o volume requisitado.
Olhe novamente o Volume Persistente:
kubectl get pv task-pv-volume
Agora a saída mostra um STATUS de Bound.
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM STORAGECLASS REASON AGE
task-pv-volume 10Gi RWO Retain Bound default/task-pv-claim manual 2m
Olhe para o PersistentVolumeClaim:
kubectl get pvc task-pv-claim
A saída mostra que oPersistentVolumeClaim está vinculado ao seu Volume Persistente,
task-pv-volume.
NAME STATUS VOLUME CAPACITY ACCESSMODES STORAGECLASS AGE
task-pv-claim Bound task-pv-volume 10Gi RWO manual 30s
O próximo passo é criar um Pod que usa o seu PersistentVolumeClaim como um volume.
Aqui está o arquivo de configuração para o Pod:
apiVersion: v1
kind: Pod
metadata:
name: task-pv-pod
spec:
volumes:
- name: task-pv-storage
persistentVolumeClaim:
claimName: task-pv-claim
containers:
- name: task-pv-container
image: nginx
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: task-pv-storage
Note que o arquivo de configuração do Pod especifica um PersistentVolumeClaim, mas não
especifica um Volume Persistente. Do ponto de vista do Pod, a reivindicação é de um volume.
Crie o Pod:
kubectl apply -f https://k8s.io/examples/pods/storage/pv-pod.yaml
Verifique se o contêiner no Pod está executando;
kubectl get pod task-pv-pod
Abra o shell do contêiner, executando no seu Pod:
kubectl exec -it task-pv-pod -- /bin/bash
No seu shell, verifique se o nginx está servindo o arquivo index.html do volume
do hostPath:
# Certifique-se de executar esses 3 comandos dentro do shell, na raiz que vem da
# execução "kubectl exec" do passo anterior
apt update
apt install curl
curl http://localhost/
A saída mostra o texto que você escreveu no arquivo index.html no volume do
hostPath:
Hello from Kubernetes storage
Se você vir essa mensagem, configurou com sucesso um pod para
usar o armazenamento de um PersistentVolumeClaim.
Exclua o Pod, o PersistentVolumeClaim e o Volume Persistente:
kubectl delete pod task-pv-pod
kubectl delete pvc task-pv-claim
kubectl delete pv task-pv-volume
Se você ainda não tem um shell aberto no nó em seu cluster, Abra um novo shell da mesma maneira que você fez antes. No shell do seu nó, remova o arquivo e o diretório que você criou:
# Pressupondo que seu nó usa "sudo" para executar comandos
# como superusuário
sudo rm /mnt/data/index.html
sudo rmdir /mnt/data
Você pode agora fechar o shell do seu nó.
apiVersion: v1
kind: Pod
metadata:
name: test
spec:
containers:
- name: test
image: nginx
volumeMounts:
# a mount for site-data
- name: config
mountPath: /usr/share/nginx/html
subPath: html
# another mount for nginx config
- name: config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
volumes:
- name: config
persistentVolumeClaim:
claimName: test-nfs-claim
Você pode realizar a montagem de 2 volumes no seu contêiner nginx:
/usr/share/nginx/html para o website estático
/etc/nginx/nginx.conf para a configuração padrão
Armazenamento configurado com um group ID (GID) possibilita a escrita somente pelos
Pods usando a mesma GID. GIDs incompatíveis ou perdidos causam erros de negação
de permissão. Para reduzir a necessidade de coordenação de usuários, um administrador
pode anotar um Volume Persistente com uma GID. Então a GID é automaticamente
adicionada a qualquer Pod que use um Volume Persistente.
Use a anotação pv.beta.kubernetes.io/gid como a seguir:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv1
annotations:
pv.beta.kubernetes.io/gid: "1234"
Quando um Pod consome um Volume Persistente que tem uma anotação GID, o GID anotado é aplicado à todos os contêiners no Pod, da mesma forma que as GIDs especificadas no contexto de segurança em que o Pod está. Cada GID, se é originário de uma anotação de Volume Persistente ou da especificação do Pod, é aplicada ao primeiro processo executando em cada contêiner.
Esta página mostra como atribuir um Pod Kubernetes a um nó particular em um cluster Kubernetes.
Você precisa ter um cluster do Kubernetes e a ferramenta de linha de comando kubectl deve estar configurada para se comunicar com seu cluster. É recomendado executar esse tutorial em um cluster com pelo menos dois nós que não estejam atuando como hosts de camada de gerenciamento. Se você ainda não possui um cluster, pode criar um usando o minikube ou pode usar um dos seguintes ambientes:
Para verificar a versão, digite kubectl version.
Liste os nós em seu cluster, juntamente com seus rótulos:
kubectl get nodes --show-labels
A saída é similar a esta:
NAME STATUS ROLES AGE VERSION LABELS
worker0 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker0
worker1 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker1
worker2 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker2
Escolha um de seus nós, e adicione um rótulo a ele:
kubectl label nodes <your-node-name> disktype=ssd
onde <your-node-name> é o nome do seu nó escolhido.
Verifique se seu nó escolhido tem o rótulo disktype=ssd:
kubectl get nodes --show-labels
A saída é similiar a esta:
NAME STATUS ROLES AGE VERSION LABELS
worker0 Ready <none> 1d v1.13.0 ...,disktype=ssd,kubernetes.io/hostname=worker0
worker1 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker1
worker2 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker2
Na saída anterior, você pode ver que o nó worker0 tem o rótulo disktype=ssd.
Este arquivo de configuração de pod descreve um pod que tem um seletor de nó,
disktype: ssd. Isto significa que o pod será agendado em um nó que tem o rótulo disktype=ssd.
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
Use o arquivo de configuração para criar um pod que será agendado no nó escolhido:
kubectl apply -f https://k8s.io/examples/pods/pod-nginx.yaml
Verifique se o pod está executando no nó escolhido:
kubectl get pods --output=wide
A saída é similar a esta:
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 13s 10.200.0.4 worker0
Você pode também agendar um pod para um nó específico usando nodeName.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
nodeName: foo-node # schedule pod to specific node
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
Use o arquivo de configuração para criar um pod que será agendado somente no nó foo-node.
Muitas aplicações dependem da configuração que é usada durante a inicialização do aplicativo ou do agente de execução. Na maioria das vezes, há um requisito para ajustar os valores atribuídos aos parâmetros de configuração. O objeto ConfigMap é a maneira usada no Kubernetes para injetar dados de configuração em Pods de aplicativos. O ConfigMap permite que você desacople os artefatos de configuração do conteúdo da imagem, para manter os aplicativos de contêiner portáveis. Esta página fornece uma série de exemplos de uso, demonstrando como criar ConfigMaps e configurar Pods usando dados armazenados em ConfigMaps.
Você precisa ter um cluster do Kubernetes e a ferramenta de linha de comando kubectl deve estar configurada para se comunicar com seu cluster. É recomendado executar esse tutorial em um cluster com pelo menos dois nós que não estejam atuando como hosts de camada de gerenciamento. Se você ainda não possui um cluster, pode criar um usando o minikube ou pode usar um dos seguintes ambientes:
Para verificar a versão, digite kubectl version.
Você pode usar kubectl create configmap ou um gerador de ConfigMap, em um arquivo kustomization.yaml para criar um ConfigMap. Perceba que o kubectl começou a suportar o kustomization.yaml desde a versão 1.14.
kubectl create configmapUse o comando kubectl create configmap para criar um ConfigMap a partir de diretórios, arquivos, ou valores literais:
kubectl create configmap <map-name> <data-source>
Onde <map-name> é o nome que você quer atribuir ao ConfigMap e <data-source> é o diretório, arquivo, ou o valor literal de onde buscar os dados. O nome de um objeto ConfigMap precisa ser um nome de subdomínio DNS válido. Quando você estiver criando um ConfigMap baseado em um arquivo, a chave no <data-source> é por padrão o nome-base do arquivo, e o valor é por padrão o conteúdo do arquivo.
Você pode usar kubectl describe ou
kubectl get para obter informações
sobre um ConfigMap.
Você pode usar kubectl create configmap para criar um ConfigMap a partir de vários arquivos no mesmo diretório. Quando você está criando um ConfigMap baseado em um diretório, o kubectl identifica arquivos cujo nome-base é uma chave válida no diretório e empacota cada um desses arquivos no novo ConfigMap. Quaisquer entradas existentes no diretório que não sejam arquivos regulares são ignoradas (ex. subdiretórios, links simbólicos, dispositivos, pipes, etc).
Por exemplo:
# Criando o diretório local
mkdir -p configure-pod-container/configmap/
# Baixe os arquivos de amostra no diretório `configure-pod-container/configmap/`
wget https://kubernetes.io/examples/configmap/game.properties -O configure-pod-container/configmap/game.properties
wget https://kubernetes.io/examples/configmap/ui.properties -O configure-pod-container/configmap/ui.properties
# Crie o ConfigMap
kubectl create configmap game-config --from-file=configure-pod-container/configmap/
O comando acima empacota cada arquivo, neste caso, game.properties e ui.properties no diretório configure-pod-container/configmap/ dentro do ConfigMap de nome game-config. Você pode exibir detalhes do ConfigMap usando o seguinte comando:
kubectl describe configmaps game-config
A saída é semelhante a esta:
Name: game-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
ui.properties:
----
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
Os arquivos game.properties e ui.properties no diretório configure-pod-container/configmap/ estão representados na seção data do ConfigMap.
kubectl get configmaps game-config -o yaml
A saída é semelhante a esta:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T18:52:05Z
name: game-config
namespace: default
resourceVersion: "516"
uid: b4952dc3-d670-11e5-8cd0-68f728db1985
data:
game.properties: |
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
ui.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
Você pode usar kubectl create configmap para criar um ConfigMap a partir de um arquivo individual, ou a partir de múltiplos arquivos.
Por exemplo,
kubectl create configmap game-config-2 --from-file=configure-pod-container/configmap/game.properties
Produziria o seguinte ConfigMap:
kubectl describe configmaps game-config-2
Onde a saída é semelhante a esta:
Name: game-config-2
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
Você pode passar o argumento --from-file múltiplas vezes para criar um ConfigMap a partir de múltiplas fontes de dados.
kubectl create configmap game-config-2 --from-file=configure-pod-container/configmap/game.properties --from-file=configure-pod-container/configmap/ui.properties
Você pode exibir detalhes do ConfigMap game-config-2 usando o comando a seguir:
kubectl describe configmaps game-config-2
A saída é semelhante a esta:
Name: game-config-2
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
ui.properties:
----
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
Quando o kubectl cria um ConfigMap a partir de entradas que não são ASCII ou UTF-8, a ferramenta os coloca no campo binaryData do ConfigMap, e não no campo data. Fontes de dados de texto e binário podem ser combinadas em um ConfigMap.
Se você quiser ver o campo binaryData (e seus valores) em um ConfigMap, você pode executar kubectl get configmap -o jsonpath='{.binaryData}' <name>.
Use a opção --from-env-file para criar um ConfigMap a partir de um arquivo de ambiente, por exemplo:
# Os arquivos de ambiente contêm uma lista de variáveis de ambiente.
# Essas regras de sintaxe se aplicam:
# Cada linha em um arquivo de ambiente deve estar em formato VAR=VAL.
# Linhas começando com # (ex. comentários) são ignoradas.
# Linhas em branco são ignoradas.
# Não há manuseio especial de aspas (ex. eles farão parte dos valores do ConfigMap).
# Baixe os arquivos de amostra no diretório `configure-pod-container/configmap/`
wget https://kubernetes.io/examples/configmap/game-env-file.properties -O configure-pod-container/configmap/game-env-file.properties
wget https://kubernetes.io/examples/configmap/ui-env-file.properties -O configure-pod-container/configmap/ui-env-file.properties
# O arquivo de ambiente `game-env-file.properties` se parece como o abaixo
cat configure-pod-container/configmap/game-env-file.properties
enemies=aliens
lives=3
allowed="true"
# Este comentário e a linha vazia acima dela são ignorados
kubectl create configmap game-config-env-file \
--from-env-file=configure-pod-container/configmap/game-env-file.properties
Produziria o seguinte ConfigMap:
kubectl get configmap game-config-env-file -o yaml
onde a saída é semelhante a esta:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2017-12-27T18:36:28Z
name: game-config-env-file
namespace: default
resourceVersion: "809965"
uid: d9d1ca5b-eb34-11e7-887b-42010a8002b8
data:
allowed: '"true"'
enemies: aliens
lives: "3"
A partir do Kubernetes v1.23, o kubectl suporta múltiplas ocorrências do argumento --from-env-file para
criar um ConfigMap para múltiplas fontes de dados.
kubectl create configmap config-multi-env-files \
--from-env-file=configure-pod-container/configmap/game-env-file.properties \
--from-env-file=configure-pod-container/configmap/ui-env-file.properties
Produziria o seguinte ConfigMap:
kubectl get configmap config-multi-env-files -o yaml
Onde a saída é semelhante a esta:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2017-12-27T18:38:34Z
name: config-multi-env-files
namespace: default
resourceVersion: "810136"
uid: 252c4572-eb35-11e7-887b-42010a8002b8
data:
allowed: '"true"'
color: purple
enemies: aliens
how: fairlyNice
lives: "3"
textmode: "true"
Você pode definir uma chave que não seja o nome do arquivo, para usar na seção data do seu ConfigMap quando usar o argumento --from-file:
kubectl create configmap game-config-3 --from-file=<my-key-name>=<path-to-file>
Onde <my-key-name> é a chave que você deseja usar no ConfigMap e <path-to-file> é a localização do arquivo fonte de dados, que você deseja que a chave represente.
Por exemplo:
kubectl create configmap game-config-3 --from-file=game-special-key=configure-pod-container/configmap/game.properties
Produziria o seguinte ConfigMap:
kubectl get configmaps game-config-3 -o yaml
Onde a saída é semelhante a esta:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T18:54:22Z
name: game-config-3
namespace: default
resourceVersion: "530"
uid: 05f8da22-d671-11e5-8cd0-68f728db1985
data:
game-special-key: |
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
Você pode usar kubectl create configmap com o argumento --from-literal para definir um valor literal a partir da linha de comando:
kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm
Você pode passar vários pares de chave-valor. Cada par fornecido na linha de comando é representado como uma entrada separada na seção data do ConfigMap.
kubectl get configmaps special-config -o yaml
A saída é semelhante a esta:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T19:14:38Z
name: special-config
namespace: default
resourceVersion: "651"
uid: dadce046-d673-11e5-8cd0-68f728db1985
data:
special.how: very
special.type: charm
Você também pode criar um ConfigMap a partir de geradores e então aplicá-lo no cluster
para criar objetos no servidor da API.
Você deve especificar os geradores em um arquivo kustomization.yaml dentro de um diretório.
Por exemplo, para gerar um ConfigMap a partir de arquivos configure-pod-container/configmap/game.properties
# Crie um arquivo kustomization.yaml com um ConfigMapGenerator
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: game-config-4
files:
- configure-pod-container/configmap/game.properties
EOF
Aplique o diretório de kustomization para criar o objeto ConfigMap.
kubectl apply -k .
configmap/game-config-4-m9dm2f92bt created
Você pode verificar se o ConfigMap foi criado, assim:
kubectl get configmap
NAME DATA AGE
game-config-4-m9dm2f92bt 1 37s
kubectl describe configmaps/game-config-4-m9dm2f92bt
Name: game-config-4-m9dm2f92bt
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","data":{"game.properties":"enemies=aliens\nlives=3\nenemies.cheat=true\nenemies.cheat.level=noGoodRotten\nsecret.code.p...
Data
====
game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
Events: <none>
Observe que o nome gerado para o ConfigMap tem um sufixo anexado, que é o hash do conteúdo. Isso garante que um novo ConfigMap é gerado cada vez que o seu conteúdo é modificado.
Você pode definir uma chave que não seja o nome do arquivo para usar no gerador do ConfigMap.
Por exemplo, para gerar um ConfigMap a partir de arquivos configure-pod-container/configmap/game.properties
com a chave game-special-key
# Criando um arquivo kustomization.yaml com o ConfigMapGenerator
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: game-config-5
files:
- game-special-key=configure-pod-container/configmap/game.properties
EOF
Aplicar o diretório kustomization para criar o objeto ConfigMap.
kubectl apply -k .
configmap/game-config-5-m67dt67794 created
Este exemplo mostra como criar um ConfigMap a partir de dois literais chave/valor:
special.type=charm e special.how=very, usando Kustomize e kubectl. Para alcançar isso, você pode especificar o gerador
ConfigMap. Crie (ou sobreponha) o arquivo
kustomization.yaml para que ele tenha os seguintes conteúdos:
---
# Conteúdos de um aruivo kustomization.yaml para criar um ConfigMap a partir de literais
configMapGenerator:
- name: special-config-2
literals:
- special.how=very
- special.type=charm
Aplique o diretório kustomization para criar o objeto ConfigMap.
kubectl apply -k .
configmap/special-config-2-c92b5mmcf2 created
Antes de prosseguir, limpe alguns dos ConfigMaps que você fez:
kubectl delete configmap special-config
kubectl delete configmap env-config
kubectl delete configmap -l 'game-config in (config-4,config-5)’
Agora que você aprendeu a definir ConfigMaps, você pode avançar na próxima seção, e aprender como usar esses objetos com Pods.
Defina uma variável de ambiente como um par de chave-valor em um ConfigMap:
kubectl create configmap special-config --from-literal=special.how=very
Atribua o valor special.how definido no ConfigMap para a variável de ambiente SPECIAL_LEVEL_KEY na especificação do pod.
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "env" ]
env:
# Defina a variável de ambiente
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
# O ConfigMap contendo o valor que você deseja atribuir ao SPECIAL_LEVEL_KEY
name: special-config
# Especifique a chave associada ao valor
key: special.how
restartPolicy: Never
Crie o Pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-single-configmap-env-variable.yaml
Agora, a saída do Pod inclui a variável de ambiente SPECIAL_LEVEL_KEY=very.
Como no exemplo anterior, crie primeiro o ConfigMap.
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
---
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config
namespace: default
data:
log_level: INFO
Crie o ConfigMap:
kubectl create -f https://kubernetes.io/examples/configmap/configmaps.yaml
Defina as variáveis de ambiente na especificação do Pod.
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "env" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.how
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: env-config
key: log_level
restartPolicy: Never
Crie o Pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-multiple-configmap-env-variable.yaml
Agora, a saída do Pod inclui as variáveis de ambiente SPECIAL_LEVEL_KEY=very e LOG_LEVEL=INFO.
Criando um ConfigMap contendo vários pares de chave-valor.
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
SPECIAL_LEVEL: very
SPECIAL_TYPE: charm
Crie o ConfigMap:
kubectl create -f https://kubernetes.io/examples/configmap/configmap-multikeys.yaml
Use envFrom para definir todos os dados do ConfigMap como variáveis de ambiente do contêiner. A chave do ConfigMap torna-se o nome da variável de ambiente no Pod.
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "env" ]
envFrom:
- configMapRef:
name: special-config
restartPolicy: Never
Crie o Pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-envFrom.yaml
Agora, a saída do Pod inclui as variáveis de ambiente SPECIAL_LEVEL=very e SPECIAL_TYPE=charm.
Você pode usar variáveis de ambiente definidas no ConfigMap no command e args de um contêiner usando a sintaxe de substituição do Kubernetes $(VAR_NAME).
Por exemplo, a seguinte especificação de Pod
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/echo", "$(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: SPECIAL_LEVEL
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: SPECIAL_TYPE
restartPolicy: Never
criado pela execução
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-env-var-valueFrom.yaml
produz a seguinte saída no contêiner test-container:
kubectl logs dapi-test-pod
very charm
Conforme explicado Criando um ConfigMap a partir de arquivos, quando você cria um ConfigMap usando --from-file, o nome do arquivo se torna uma chave armazenada na seção data do ConfigMap. O conteúdo do arquivo se torna o valor da chave.
Os exemplos nesta seção se referem a um ConfigMap de nome' special-config, mostrado abaixo.
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
SPECIAL_LEVEL: very
SPECIAL_TYPE: charm
Crie o ConfigMap:
kubectl create -f https://kubernetes.io/examples/configmap/configmap-multikeys.yaml
Adicione o nome do ConfigMap debaixo da seção volumes das especificações do Pod.
Isso adiciona os dados do ConfigMap ao diretório especificado como volumeMounts.mountPath (nesse caso, /etc/config).
A seção command lista arquivos do diretório com nomes que correspondem às chaves no ConfigMap.
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "ls /etc/config/" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
# Forneça o nome do ConfigMap que contém os arquivos
# que você deseja adicionar ao contêiner
name: special-config
restartPolicy: Never
Crie o Pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-volume.yaml
Quando o Pod executa, o comando ls /etc/config/ produz a saída abaixo:
SPECIAL_LEVEL
SPECIAL_TYPE
/etc/config/, eles serão excluídos.binaryData.Use o campo path para especificar o caminho de arquivo desejado para ítens específicos do ConfigMap.
Nesse caso, o item SPECIAL_LEVEL será montado no volume config-volume em /etc/config/keys.
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh","-c","cat /etc/config/keys" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: special-config
items:
- key: SPECIAL_LEVEL
path: keys
restartPolicy: Never
Crie o Pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-volume-specific-key.yaml
Quando o Pod executar, o comando cat /etc/config/keys produz a saída abaixo:
very
/etc/config/ serão apagados.Você pode projetar chaves para caminhos específicos e permissões específicas em uma base por-arquivo. O guia do usuário Segredos explica a sintaxe.
Uma referência de ConfigMap pode ser marcada opcional. Se o ConfigMap for inexistente, o volume montado estará vazio. Se o ConfigMap existir, mas a chave referenciada é inexistente, o caminho estará ausente no ponto de montagem.
Quando um ConfigMap montado é atualizado, o conteúdo projetado é eventualmente atualizado também. Isso se aplica no caso em que um ConfigMap referenciado opcionalmente passe a existir após o Pod ser iniciado.
O Kubelet verifica se o ConfigMap montado está atualizado em cada sincronização periódica. No entanto, ele usa seu cache local baseado em TTL para obter o valor atual do ConfigMap. Como resultado, o atraso total, desde o momento em que o ConfigMap foi atualizado até o momento em que novas chaves são projetadas para o pod, pode ser tão longo quanto o período de sincronização do Kubelet (1 minuto por padrão) + TTL de cache do ConfigMap (1 minuto por padrão) no kubelet.
O recurso da API ConfigMap armazena dados de configuração como pares de chave-valor. Os dados podem ser consumidos em Pods, ou fornecidos para componentes do sistema, como controladores. O ConfigMap é similar ao Secret, mas fornece um meio de trabalhar com strings que não contêm informações confidenciais. Usuários e componentes do sistema podem armazenar dados de configuração em ConfigMaps.
/etc do Linux e seus conteúdos. Por exemplo, se você criar um Volume Kubernetes a partir de um ConfigMap, cada item de dados no ConfigMap é representado por um arquivo individual no volume.O campo data do ConfigMap contém os dados de configuração. Como mostrado no exemplo abaixo, estes podem ser simples (como propriedades individuais definidas usando --from-literal) ou complexos (como arquivos de configuração ou blobs JSON definidos usando --from-file).
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T19:14:38Z
name: example-config
namespace: default
data:
# exemplo de uma propriedade simples definida usando --from-literal
example.property.1: hello
example.property.2: world
# exemplo de uma propriedade complexa definida usando --from-file
example.property.file: |-
property.1=value-1
property.2=value-2
property.3=value-3
Você deve criar um ConfigMap antes de referenciá-lo em uma especificação de Pod (a menos que você marque o ConfigMap como optional). Se você referenciar um ConfigMap que não existe, O Pod não vai iniciar. Da mesma forma, referências a chaves que não existem no ConfigMap impedirão o Pod de iniciar.
Se você usar envFrom para definir variáveis de ambiente do ConfigMap, chaves que são consideradas inválidas serão ignoradas. O Pod poderá iniciar, mas os nomes inválidos serão registrados no log de eventos (InvalidVariableNames). A mensagem de log lista cada chave ignorada. Por exemplo:
kubectl get events
A saída é semelhante a esta:
LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON SOURCE MESSAGE
0s 0s 1 dapi-test-pod Pod Warning InvalidEnvironmentVariableNames {kubelet, 127.0.0.1} Keys [1badkey, 2alsobad] from the EnvFrom configMap default/myconfig were skipped since they are considered invalid environment variable names.
O ConfigMap reside em um Namespace específico. Um ConfigMap só pode ser referenciado por Pods residentes no mesmo namespace.
Você não pode usar um ConfigMap para Pods estáticos, porque o kubelet não oferece suporte a isso.
Esta página mostra como atribuir um Pod kubernetes a um nó particular em um cluster Kubernetes utilizando afinidade de nó.
Você precisa ter um cluster do Kubernetes e a ferramenta de linha de comando kubectl deve estar configurada para se comunicar com seu cluster. É recomendado executar esse tutorial em um cluster com pelo menos dois nós que não estejam atuando como hosts de camada de gerenciamento. Se você ainda não possui um cluster, pode criar um usando o minikube ou pode usar um dos seguintes ambientes:
O seu servidor Kubernetes deve estar numa versão igual ou superior a v1.10.Para verificar a versão, digite kubectl version.
Liste os nós em seu cluster, juntamente com seus labels:
kubectl get nodes --show-labels
A saída é semelhante a esta:
NAME STATUS ROLES AGE VERSION LABELS
worker0 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker0
worker1 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker1
worker2 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker2
Escolha um de seus nós e adicione um label a ele:
kubectl label nodes <your-node-name> disktype=ssd
onde <your-node-name> é o nome do seu nó escolhido.
Verifique se seu nó escolhido tem o label disktype=ssd:
kubectl get nodes --show-labels
A saída é semelhante a esta:
NAME STATUS ROLES AGE VERSION LABELS
worker0 Ready <none> 1d v1.13.0 ...,disktype=ssd,kubernetes.io/hostname=worker0
worker1 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker1
worker2 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker2
Na saída anterior, você pode ver que o nó worker0 tem o label
disktype=ssd.
Este manifesto descreve um Pod que possui uma afinidade de nó requiredDuringSchedulingIgnoredDuringExecution com o label disktype: ssd.
Isso significa que o Pod será alocado apenas em um nó que tenha o label disktype=ssd.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
Aplique o manifesto para criar um Pod que será alocado no nó escolhido:
kubectl apply -f https://k8s.io/examples/pods/pod-nginx-required-affinity.yaml
Verifique se o Pod está executando no nó escolhido:
kubectl get pods --output=wide
A saída é semelhante a esta:
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 13s 10.200.0.4 worker0
Este manifesto descreve um Pod que possui uma afinidade de nó requiredDuringSchedulingIgnoredDuringExecution com o label disktype: ssd.
Isso significa que o Pod será alocado de preferência em um nó com o label disktype=ssd.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
Aplique o manifesto para criar um Pod que será alocado no nó escolhido:
kubectl apply -f https://k8s.io/examples/pods/pod-nginx-preferred-affinity.yaml
Verifique se o Pod está executando no nó escolhido:
kubectl get pods --output=wide
A saída é semelhante a esta:
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 13s 10.200.0.4 worker0
Saiba mais sobre Afinidade de nó.
Esta página mostra como configurar o compartilhamento de namespace de processos para um Pod. Quando O compartilhamento de namespace de processos está ativado, os processos em um Contêiner são visíveis para todos os outros Contêineres no mesmo Pod.
Você pode usar este recurso para configurar Contêineres de cooperação, como um manipulador de log
sidecar de contêiner, ou para solucionar problemas em imagens de contêiner que não
incluem utilitários de depuração como um shell.
Você precisa ter um cluster do Kubernetes e a ferramenta de linha de comando kubectl deve estar configurada para se comunicar com seu cluster. É recomendado executar esse tutorial em um cluster com pelo menos dois nós que não estejam atuando como hosts de camada de gerenciamento. Se você ainda não possui um cluster, pode criar um usando o minikube ou pode usar um dos seguintes ambientes:
O compartilhamento de namespace de processos é ativado usando o campo shareProcessNamespace da
.spec para um Pod. Por exemplo:
Crie o pod nginx no seu cluster:
kubectl apply -f https://k8s.io/examples/pods/share-process-namespace.yaml
Conecte ao shell do contêiner e execute o comando ps:
kubectl exec -it nginx -c shell -- /bin/sh
Se você não vir um prompt de comando, tente pressionar Enter. No shell do Contêiner execute:
# execute este comando dentro do "shell" do contêiner
ps ax
A saída é semelhante a esta:
PID USER TIME COMMAND
1 root 0:00 /pause
8 root 0:00 nginx: master process nginx -g daemon off;
14 101 0:00 nginx: worker process
15 root 0:00 sh
21 root 0:00 ps ax
Você pode sinalizar processos em outros Contêineres. Por exemplo, mandando SIGHUP ao
nginx para restartar o processo worker. Isso requer a capacidade SYS_PTRACE.
# execute este comando dentro do "shell" do contêiner
kill -HUP 8 # substitua o "8" pelo PID do processo principal do nginx, se necessário
ps ax
A saída é semelhante a esta:
PID USER TIME COMMAND
1 root 0:00 /pause
8 root 0:00 nginx: master process nginx -g daemon off;
15 root 0:00 sh
22 101 0:00 nginx: worker process
23 root 0:00 ps ax
É até possível acessar o sistema de arquivos de outro contêiner usando o link
/proc/$pid/root.
# execute este comando dentro do "shell" do contêiner
# substitua o "8" pelo PID do processo Nginx, se necessario
head /proc/8/root/etc/nginx/nginx.conf
A saída é semelhante a esta:
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
Os Pods compartilham muitos recursos, por isso faz sentido que eles também compartilhem um namespace de processo. Alguns Contêineres podem esperar serem isolados de outros, no entanto, por isso, é importante entender as diferenças:
O processo de contêiner não tem mais o PID 1. Alguns Contêineres recusam
começar sem o PID 1 (por exemplo, contêineres usando systemd) ou executando comandos
como kill -HUP 1 para sinalizar o processo de Contêiner. Em pods com um
namespace de processos compartilhado, kill -HUP 1 irá sinalizar a sandbox
(/pause no exemplo acima).
Os processos são visíveis para outros contêineres no Pod. Isso inclui todas
informações visíveis em /proc, como senhas que foram passadas como argumentos
ou variáveis de ambiente. Estes são protegidos apenas por permissões regulares do Unix.
Sistema de arquivos do Contêiner são visíveis para outros Contêineres do pod através do link
/proc/$pid/root. Isso facilita a depuração, mas também significa
que os segredos do sistema de arquivos, são protegidos apenas por permissões de sistema de arquivos.
Pods Estáticos são gerenciados diretamente pelo daemon kubelet em um nó específico,
sem o servidor de API
observando-os.
Ao contrário dos pods que são gerenciados pelo Control Plane (por exemplo, uma
Implantação);
em vez disso, o kubelet observa cada Pod estático
(e reinicia-os se falharem).
Pods estáticos estão sempre ligados a um Kubelet em um nó específico.
O Kubelet tenta automaticamente criar um mirror Pod no servidor de API do Kubernetes para cada Pod estático. Isso significa que os pods em execução em um nó são visíveis no servidor de API, mas não podem ser controlados a partir daí. Aos nomes de Pods será sufixados com o nome de host do nó, com um hífem a esquerda.
especificação de um Pod estático não pode referir-se à outros objetos da API
(ex., ServiceAccount,
ConfigMap,
Secret, etc).Você precisa ter um cluster do Kubernetes e a ferramenta de linha de comando kubectl deve estar configurada para se comunicar com seu cluster. É recomendado executar esse tutorial em um cluster com pelo menos dois nós que não estejam atuando como hosts de camada de gerenciamento. Se você ainda não possui um cluster, pode criar um usando o minikube ou pode usar um dos seguintes ambientes:
Para verificar a versão, digite kubectl version.
Esta página assume que você está usando um CRI-O para executar os Pods, e que seus nós estão executando o sistema operacional Fedora. Instruções para outras distribuições, ou instalações de Kubernetes, podem variar.
Você pode configurar um Pod estático com um arquivo de configuração hospedado no sistema de arquivos ou um arquivo de configuração hospedado na Web.
Os manifestos, são definições de Pod padrão em formato JSON ou YAML em um diretório específico. Use o campo staticPodPath: <diretório> no
arquivo de configuração do kubelet,
que periodicamente varre o diretório e cria/exclui Pods estáticos conforme os arquivos YAML/JSON aparecem/desaparecem.
Observe que o Kubelet ignorará os arquivos começando com pontos ao varrer o diretório especificado.
Por exemplo, como iniciar um servidor Web simples como um Pod estático
Escolha um nó onde você deseja executar um Pod estático. Neste exemplo, é my-node1.
ssh my-node1
Escolha um diretório, digamos /etc/kubernetes/manifests e coloque uma definição de pod para um servidor web lá, por exemplo /etc/kubernetes/manifests/static-web.yaml:
# Execute este comando no nó onde o Kubelet está funcionando
mkdir -p /etc/kubernetes/manifests/
cat <<EOF >/etc/kubernetes/manifests/static-web.yaml
apiVersion: v1
kind: Pod
metadata:
name: static-web
labels:
role: myrole
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
protocol: TCP
EOF
Configure seu kubelet no nó para usar este diretório executando-o com o argumento --pod-manifest-path=/etc/kubernetes/manifests/. No Fedora, edite o arquivo /etc/kubernetes/kubelet para incluir esta linha:
KUBELET_ARGS="--cluster-dns=10.254.0.10 --cluster-domain=kube.local --pod-manifest-path=/etc/kubernetes/manifests/"
ou adicione o campo staticPodPath: <o diretótio> no
arquivo de configuração do kubelet.
Reinicie o kubelet. No Fedora, você poderia executar:
# Execute este comando no nó onde o kubelet está funcionando
systemctl restart kubelet
O Kubelet baixa periodicamente um arquivo especificado pelo argumento --manifest-url=<URL>
e interpreta-o como um arquivo JSON/YAML que contém as definições do Pod.
Similar ao que manifestos hospedados no sistema de arquivos fazem, o kubelet
reexamina o manifesto em um agendamento. Se houver alterações na lista de Pods estáticos, o kubelet aplica-os.
Para usar esta abordagem:
Crie um arquivo YAML e armazene-o em um servidor da Web, para que você possa passar o URL desse arquivo para o Kubelet.
apiVersion: v1
kind: Pod
metadata:
name: static-web
labels:
role: myrole
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
protocol: TCP
Configure o kubelet no seu nó selecionado para usar este manifesto da Web, executando-o com --manifest-url=<manifest-url>. No Fedora, edite /etc/kubernetes/kubelet para incluir esta linha:
KUBELET_ARGS="--cluster-dns=10.254.0.10 --cluster-domain=kube.local --manifest-url=<manifest-url>"
Reinicie o Kubelet. No Fedora, você usaria:
# Execute este comando no nó onde o kubelet está funcionando
systemctl restart kubelet
Quando o kubelet começa, inicia automaticamente todos os pods estáticos definidos. Como você definiu um Pod estático e reiniciou o kubelet, o novo pod estático deveria já estar em execução.
Você pode ver os Contêineres em execução (incluindo os Pods estáticos) ao executar (no Nó):
# Execute este comando no nó onde o kubelet está funcionando
crictl ps
A saída pode ser algo como:
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
129fd7d382018 docker.io/library/nginx@sha256:... 11 minutes ago Running web 0 34533c6729106
crictl mostra a URI da imagem e o checksum SHA-256. O NAME vai parecer mais como:
docker.io/library/nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31.Você pode ver o Pod espelho no servidor de API:
kubectl get pods
NAME READY STATUS RESTARTS AGE
static-web 1/1 Running 0 2m
Os Rótulos dos pods estáticos são propagados no Pod espelho. Você pode usar esses rótulos como seletores via normal, etc.
Se você tentar usar o kubectl para excluir o Pod espelho do servidor de API,
o kubelet não remove o Pod estático:
kubectl delete pod static-web
pod "static-web" deleted
Você pode ver que o Pod ainda está funcionando:
kubectl get pods
NAME READY STATUS RESTARTS AGE
static-web 1/1 Running 0 4s
De volta ao seu nó, onde o kubelet está funcionando, você pode tentar parar o Contêiner manualmente. Você verá que, depois de algum tempo, o Kubelet notará e reiniciará o Pod automaticamente:
# Execute esses comandos no nó onde o Kubelet está funcionando
crictl stop 129fd7d382018 # substitua pelo ID do seu contêiner
sleep 20
crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
89db4553e1eeb docker.io/library/nginx@sha256:... 19 seconds ago Running web 1 34533c6729106
O Kubelet em execução varre periodicamente o diretório configurado (/etc/kubernetes/manifests em nosso exemplo) por alterações, e adiciona/remove os pods à medida que os arquivos aparecem/desaparecem neste diretório.
# Pressupondo que você esteja usando a configuração de Pod estático hospedada no sistema de arquivos
# Execute esses comandos no nó onde o Kubelet está funcionando
#
mv /etc/kubelet.d/static-web.yaml /tmp
sleep 20
crictl ps
# Você vê que nenhum contêiner nginx está funcionando
#
mv /tmp/static-web.yaml /etc/kubelet.d/
sleep 20
crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
f427638871c35 docker.io/library/nginx@sha256:... 19 seconds ago Running web 1 34533c6729106
O Kubernetes fornece um controlador de admissão embutido para garantir os padrões de segurança do Pod. Você pode configurar esse controlador de admissão para definir padrões e isenções em todo o cluster.
Após uma release alfa no Kubernetes v1.22, o controlador de admissão Pod Security Admission tornou-se disponível por padrão no Kubernetes v1.23, no estado beta. Da versão 1.25 em diante o controlador de admissão Pod Security Admission está publicamente disponível.
Para verificar a versão, digite kubectl version.
Se você não estiver utilizando o Kubernetes 1.35, você pode verificar a documentação da versão do Kubernetes que você está utilizando.
pod-security.admission.config.k8s.io/v1 requer o Kubernetes v1.25
ou superior.
Para as versões v1.23 e v1.24, utilize v1beta1.
Para a versão v1.22, utilize v1alpha1.apiVersion: apiserver.config.k8s.io/v1 # veja a nota de compatibilidade
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
configuration:
apiVersion: pod-security.admission.config.k8s.io/v1beta1
kind: PodSecurityConfiguration
# Padrões aplicados quando o label de modo não é especificado.
#
# O valor para o label Level deve ser uma das opções abaixo:
# - "privileged" (padrão)
# - "baseline"
# - "restricted"
#
# O valor para o label Version deve ser uma das opções abaixo:
# - "latest" (padrão)
# - versão específica no formato "v1.35"
defaults:
enforce: "privileged"
enforce-version: "latest"
audit: "privileged"
audit-version: "latest"
warn: "privileged"
warn-version: "latest"
exemptions:
# Lista de usuários autenticados a eximir.
usernames: []
# Lista de RuntimeClasses a eximir.
runtimeClasses: []
# Lista de namespaces a eximir.
namespaces: []
--admission-control-config-file do kube-apiserver.Os namespaces podem ser rotulados para aplicar os Padrões de segurança de pod. As três políticas privilegiado, linha de base e restrito cobrem amplamente o espectro de segurança e são implementados pela segurança de Pod controlador de admissão.
O seu servidor Kubernetes deve estar numa versão igual ou superior a v1.22.
Para verificar a versão, digite kubectl version.
PodSecurity do portal de funcionalidades
esteja habilitada.baseline de pod com rótulos em namespaceEste manifesto define um Namespace my-baseline-namespace que:
baseline.restricted.baseline e restricted à v1.35.apiVersion: v1
kind: Namespace
metadata:
name: my-baseline-namespace
labels:
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/enforce-version: v1.35
# Estamos definindo-os para o nosso nível _desejado_ `enforce`.
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/audit-version: v1.35
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/warn-version: v1.35
kubectl labelenforce (ou version) é adicionada ou modificada,
O plugin de admissão testará cada Pod no namespace contra a nova política.
Violações são devolvidas ao usuário como avisos.É útil aplicar a flag --dry-run ao avaliar inicialmente as alterações
do perfil de segurança para namespaces. As verificações padrão de segurança
do pod ainda serão executadas em modo dry run, dando-lhe informações sobre
como a nova política trataria os pods existentes, sem realmente atualizar a política.
kubectl label --dry-run=server --overwrite ns --all \
pod-security.kubernetes.io/enforce=baseline
Se você está apenas começando com os padrões de segurança de pod, um primeiro passo
adequado seria configurar todos namespaces com anotações de auditoria para um
nível mais rigoroso, como baseline:
kubectl label --overwrite ns --all \
pod-security.kubernetes.io/audit=baseline \
pod-security.kubernetes.io/warn=baseline
Observe que isso não está aplicando as definições de nível, para que os namespaces que não foram explicitamente avaliados possam ser distinguidos. Você pode listar os namespaces sem um nível aplicado, explicitamente definido, usando este comando:
kubectl get namespaces --selector='!pod-security.kubernetes.io/enforce'
Você pode atualizar um namespace específico também. Este comando adiciona a política
enforce=restricted ao my-existing-namespace, fixando a política que restringe
à versão v1.35.
kubectl label --overwrite ns my-existing-namespace \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/enforce-version=v1.35