As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.
Plano de dados EKS
Para operar aplicativos de alta disponibilidade e resiliência, você precisa de um plano de dados altamente disponível e resiliente. Um plano de dados elástico garante que o Kubernetes possa escalar e corrigir seus aplicativos automaticamente. Um plano de dados resiliente consiste em dois ou mais nós de trabalho, pode crescer e diminuir com a carga de trabalho e se recuperar automaticamente de falhas.
Você tem duas opções para nós de trabalho com o EKS: EC2instâncias e Fargate. Se você escolher EC2 instâncias, você mesmo poderá gerenciar os nós de trabalho ou usar grupos de nós gerenciados pelo EKS. Você pode ter um cluster com uma combinação de nós de trabalho gerenciados e autogerenciados e Fargate.
O EKS no Fargate oferece o caminho mais fácil para um plano de dados resiliente. O Fargate executa cada pod em um ambiente computacional isolado. Cada pod executado no Fargate tem seu próprio nó de trabalho. O Fargate escala automaticamente o plano de dados à medida que o Kubernetes escala os pods. Você pode escalar o plano de dados e sua carga de trabalho usando o autoescalador horizontal do pod.
A forma preferida de escalar os nós de EC2 trabalho é usando o Kubernetes Cluster EC2 Autoscaler,
Recomendações
Use grupos de EC2 Auto Scaling para criar nós de trabalho
É uma prática recomendada criar nós de trabalho usando grupos de EC2 Auto Scaling em vez de criar EC2 instâncias individuais e juntá-las ao cluster. Os grupos de Auto Scaling substituirão automaticamente todos os nós encerrados ou com falha, garantindo que o cluster sempre tenha a capacidade de executar sua carga de trabalho.
Use o escalonador automático de cluster do Kubernetes para escalar nós
O escalador automático de cluster ajusta o tamanho do plano de dados quando há pods que não podem ser executados porque o cluster não tem recursos suficientes, e adicionar outro nó de trabalho ajudaria. Embora o escalador automático de cluster seja um processo reativo, ele espera até que os pods estejam no estado pendente devido à capacidade insuficiente no cluster. Quando esse evento ocorre, ele adiciona EC2 instâncias ao cluster. Sempre que a capacidade do cluster ficar sem capacidade, novas réplicas — ou novos pods — ficarão indisponíveis (no estado Pendente) até que os nós de trabalho sejam adicionados. Esse atraso pode afetar a confiabilidade de seus aplicativos se o plano de dados não puder ser escalado com rapidez suficiente para atender às demandas da carga de trabalho. Se um nó de trabalho for constantemente subutilizado e todos os seus pods puderem ser programados em outros nós de trabalho, o Cluster Autoscaler o encerrará.
Configure o superprovisionamento com o escalador automático de cluster
O escalonador automático de cluster aciona um aumento de escala do plano de dados quando os pods no cluster já estão pendentes. Portanto, pode haver um atraso entre o momento em que seu aplicativo precisa de mais réplicas e o momento em que, de fato, obtém mais réplicas. Uma opção para compensar esse possível atraso é adicionar mais do que as réplicas necessárias, aumentando o número de réplicas do aplicativo.
Outro padrão recomendado pelo Cluster Autoscaler usa pods de pausa e
Usando o escalador automático de cluster com vários grupos de Auto Scaling
Execute o autoescalador de cluster com o --node-group-auto-discovery
sinalizador ativado. Isso permitirá que o autoescalador de cluster encontre todos os grupos de escalonamento automático que incluem uma determinada tag definida e evita a necessidade de definir e manter cada grupo de escalonamento automático no manifesto.
Usando o escalador automático de cluster com armazenamento local
Por padrão, o Cluster Autoscaler não reduz a escala dos nós que têm pods implantados com armazenamento local conectado. Defina o --skip-nodes-with-local-storage
sinalizador como false para permitir que o escalador automático de cluster reduza esses nós.
Distribua os nós de trabalho e a carga de trabalho em vários AZs
Você pode proteger suas cargas de trabalho contra falhas em uma AZ individual executando nós e pods de trabalho em vários. AZs Você pode controlar a AZ na qual os nós de trabalho são criados usando as sub-redes nas quais você cria os nós.
A implantação abaixo distribui os pods, AZs se possível, permitindo que esses pods funcionem de qualquer maneira, caso contrário:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
spec:
replicas: 3
selector:
matchLabels:
app: web-server
template:
metadata:
labels:
app: web-server
spec:
topologySpreadConstraints:
- maxSkew: 1
whenUnsatisfiable: ScheduleAnyway
topologyKey: topology.kubernetes.io/zone
labelSelector:
matchLabels:
app: web-server
containers:
- name: web-app
image: nginx
resources:
requests:
cpu: 1
nota
kube-scheduler
só conhece os domínios de topologia por meio de nós que existem com esses rótulos. Se a implantação acima for implantada em um cluster com nós somente em uma única zona, todos os pods serão programados nesses nós, pois kube-scheduler
não conhece as outras zonas. Para que essa distribuição de topologia funcione conforme o esperado com o agendador, os nós já devem existir em todas as zonas. Esse problema será resolvido no Kubernetes 1.24 com a adição do MinDomainsInPodToplogySpread
recurso gateminDomains
propriedade para informar o agendador sobre o número de domínios elegíveis.
Atenção
whenUnsatisfiable
Definir como DoNotSchedule
fará com que os pods não sejam programáveis se a restrição de dispersão da topologia não puder ser atendida. Ele só deve ser definido se for preferível que os pods não sejam executados em vez de violar a restrição de dispersão da topologia.
Nas versões mais antigas do Kubernetes, você pode usar regras de antiafinidade de pods para programar pods em vários. AZs O manifesto abaixo informa o programador do Kubernetes a preferir o agendamento de pods de forma distinta. AZs
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
labels:
app: web-server
spec:
replicas: 4
selector:
matchLabels:
app: web-server
template:
metadata:
labels:
app: web-server
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web-server
topologyKey: failure-domain.beta.kubernetes.io/zone
weight: 100
containers:
- name: web-app
image: nginx
Atenção
Não exija que os pods sejam programados de AZs forma distinta, caso contrário, o número de pods em uma implantação nunca excederá o número de. AZs
Garanta a capacidade em cada AZ ao usar volumes do EBS
Se você usa o Amazon EBS para fornecer volumes persistentes, precisará garantir que os pods e o volume associado do EBS estejam localizados na mesma AZ. No momento em que este artigo foi escrito, os volumes do EBS só estavam disponíveis em uma única AZ. Um pod não pode acessar volumes persistentes suportados pelo EBS localizados em uma AZ diferente. O programador do Kubernetes sabe em qual AZ um nó de trabalho
Crie um grupo de Auto Scaling para cada AZ com capacidade suficiente para garantir que o cluster sempre tenha capacidade de programar pods na mesma AZ dos volumes do EBS necessários. Além disso, você deve ativar o --balance-similar-node-groups
recurso no autoescalador de cluster.
Se você estiver executando um aplicativo que usa o volume do EBS, mas não precisa estar altamente disponível, poderá restringir a implantação do aplicativo a uma única AZ. No EKS, os nós de trabalho recebem automaticamente um failure-domain.beta.kubernetes.io/zone
rótulo adicionado, que contém o nome do AZ. Você pode ver os rótulos anexados aos seus nós executandokubectl get nodes --show-labels
. Mais informações sobre rótulos de nós integrados estão disponíveis aqui
No exemplo abaixo, o pod só será programado em us-west-2c
AZ:
apiVersion: v1
kind: Pod
metadata:
name: single-az-pod
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: failure-domain.beta.kubernetes.io/zone
operator: In
values:
- us-west-2c
containers:
- name: single-az-container
image: kubernetes/pause
Os volumes persistentes (apoiados pelo EBS) também são automaticamente rotulados com o nome de AZ; você pode ver a qual AZ seu volume persistente pertence executando. kubectl get pv -L topology.ebs.csi.aws.com/zone
Quando um pod é criado e reivindica um volume, o Kubernetes agenda o pod em um nó na mesma AZ do volume.
Considere esse cenário: você tem um cluster EKS com um grupo de nós. Esse grupo de nós tem três nós de trabalho espalhados por três AZs. Você tem um aplicativo que usa um volume persistente suportado pelo EBS. Quando você cria esse aplicativo e o volume correspondente, seu pod é criado no primeiro dos três AZs. Em seguida, o nó de trabalho que executa esse pod fica insalubre e, posteriormente, indisponível para uso. O escalador automático de cluster substituirá o nó não íntegro por um novo nó de trabalho; no entanto, como o grupo de escalonamento automático se estende por três AZs, o novo nó de trabalho pode ser iniciado na segunda ou na terceira AZ, mas não na primeira AZ, conforme a situação exige. Como o volume do EBS restrito a AZ só existe na primeira AZ, mas não há nós de trabalho disponíveis nessa AZ, o pod não pode ser programado. Portanto, você deve criar um grupo de nós em cada AZ, para que sempre haja capacidade suficiente disponível para executar pods que não podem ser programados em outros AZs.
Como alternativa, o EFS
Detecte problemas de nós com o agente de monitoramento de nós
Falhas nos nós de trabalho podem afetar a disponibilidade de seus aplicativos. Você pode usar o agente de monitoramento de nós para detectar e mostrar problemas de saúde. Você também pode habilitar o reparo automático de nós para substituir automaticamente os nós quando forem detectados problemas.
O agente de monitoramento de nós está incluído como um recurso para todos os clusters do Modo Automático do Amazon EKS. Para outros tipos de cluster, você pode adicionar o agente de monitoramento como um complemento do Amazon EKS. Para obter mais informações, consulte Habilitar o reparo automático do nó e investigar problemas de saúde do nó no Guia do usuário do Amazon EKS.
Reserve recursos para daemons do sistema e do Kubernetes
Você pode melhorar a estabilidade dos nós de trabalho reservando a capacidade computacional para o sistema operacional e os daemons do Kuberneteslimits
declaração, podem saturar os recursos do sistema, colocando os nós em uma situação em que os processos do sistema operacional e os daemons do Kubernetes (kubelet
, tempo de execução do contêiner etc.) competem com os pods pelos recursos do sistema. Você pode usar kubelet
sinalizadores --system-reserved
e reservar recursos --kube-reserved
para processos do sistema (udev
,sshd
, etc.) e daemons do Kubernetes, respectivamente.
Se você usa a AMI Linux otimizada para EKS, a CPU, a memória e o armazenamento são reservados para o sistema e os daemons do Kubernetes por padrão. Quando os nós de trabalho baseados nessa AMI são iniciados, EC2 os dados do usuário são configurados para acionar o bootstrap.sh
scriptKubeletConfiguration
arquivo localizado em/etc/kubernetes/kubelet/kubelet-config.json
.
Talvez seja necessário aumentar a reserva de recursos do sistema se você executar daemons personalizados no nó e a quantidade de CPU e memória reservada por padrão for insuficiente.
eksctl
oferece a maneira mais fácil de personalizar a reserva de recursos para daemons do sistema e do Kubernetes
Implemente QoS
Para aplicações críticas, considere definir requests
= limits
para o contêiner no pod. Isso garantirá que o contêiner não seja eliminado se outro pod solicitar recursos.
É uma prática recomendada implementar limites de CPU e memória para todos os contêineres, pois isso evita que um contêiner consuma inadvertidamente os recursos do sistema e afete a disponibilidade de outros processos co-localizados.
Configurar e dimensionar solicitações/limites de recursos para todas as cargas de trabalho
Algumas orientações gerais podem ser aplicadas ao dimensionamento de solicitações de recursos e limites para cargas de trabalho:
-
Não especifique limites de recursos na CPU. Na ausência de limites, a solicitação atua como um peso sobre quanto tempo relativo de CPU os contêineres recebem
. Isso permite que suas cargas de trabalho usem toda a CPU sem limites artificiais ou inanição. -
Para recursos que não são de CPU, configurar
requests
=limits
fornece o comportamento mais previsível. Serequests
! =limits
, o contêiner também tem sua QOSreduzida de Garantida para Estável, aumentando a probabilidade de ser despejado em caso de pressão no nó. -
Para recursos que não sejam de CPU, não especifique um limite muito maior do que a solicitação. Quanto maiores
limits
forem configurados em relação arequests
, maior a probabilidade de os nós ficarem sobrecarregados, levando a grandes chances de interrupção da carga de trabalho. -
Solicitações dimensionadas corretamente são particularmente importantes ao usar uma solução de auto-escalonamento de nós, como
Karpenter ou Cluster. AutoScaler Essas ferramentas analisam suas solicitações de carga de trabalho para determinar o número e o tamanho dos nós a serem provisionados. Se suas solicitações forem muito pequenas com limites maiores, você poderá descobrir que suas cargas de trabalho foram removidas ou o OOM eliminado se elas estiverem compactadas em um nó.
Determinar as solicitações de recursos pode ser difícil, mas ferramentas como o Vertical Pod Autoscaler
Configurar cotas de recursos para namespaces
Namespaces são destinados para o uso em ambientes com muitos usuários distribuídos entre várias equipes ou projetos. Eles fornecem um escopo para nomes e são uma forma de dividir os recursos do cluster entre várias equipes, projetos e cargas de trabalho. Você pode limitar o consumo agregado de recursos em um namespace. O ResourceQuota
Se a cota de recursos estiver habilitada para um namespace para recursos computacionais, como CPU e memória, os usuários devem especificar solicitações ou limites para cada contêiner nesse namespace.
Considere configurar cotas para cada namespace. Considere usar LimitRanges
para aplicar automaticamente limites pré-configurados aos contêineres em um namespace.
Limitar o uso de recursos do contêiner em um namespace
As cotas de recursos ajudam a limitar a quantidade de recursos que um namespace pode usar. O LimitRange
objetoLimitRange
você pode definir uma solicitação e limites padrão para contêineres, o que é útil se definir limites de recursos computacionais não for uma prática padrão em sua organização. Como o nome sugere, LimitRange
pode impor o uso mínimo e máximo de recursos computacionais por pod ou contêiner em um namespace. Além disso, imponha a solicitação mínima e máxima de armazenamento PersistentVolumeClaim em um namespace.
Considere usar LimitRange
em conjunto com ResourceQuota
para impor limites em um nível de contêiner e namespace. Definir esses limites garantirá que um contêiner ou namespace não interfira nos recursos usados por outros locatários no cluster.
CoreDNS
O CoreDNS cumpre as funções de resolução de nomes e descoberta de serviços no Kubernetes. Ele é instalado por padrão nos clusters EKS. Por questões de interoperabilidade, o Kubernetes Service para CoreDNS ainda se chama kube-dns.kube-system
no namespace e, no EKS, por padrão, ele executa duas réplicas com solicitações e limites declarados. As consultas de DNS são enviadas para o kube-dns
serviço executado no namespace. kube-system
Recomendações
Monitore as métricas do CoreDNS
O CoreDNS tem suporte integrado para o Prometheus.coredns_dns_request_duration_seconds_sum
(antescore_dns_response_rcode_count_total
chamada), os erros coredns_dns_responses_total
(, NXDOMAIN, SERVFAIL FormErr,) e o consumo de memória do CoreDNS Pod.
Para fins de solução de problemas, você pode usar o kubectl para visualizar os registros do CoreDNS:
for p in $(kubectl get pods -n kube-system -l k8s-app=kube-dns -o jsonpath='{.items[*].metadata.name}'); do kubectl logs $p -n kube-system; done
Use NodeLocal DNSCache
Você pode melhorar o desempenho do Cluster DNS executando NodeLocalDNSCachekube-dns
Configurar cluster-proportional-scaler para CoreDNS
Outro método para melhorar o desempenho do Cluster DNS é escalar automaticamente e horizontalmente a implantação do CoreDNS
Os nós e o agregado de núcleos de CPU nos nós são as duas métricas com as quais você pode escalar o CoreDNS. Você pode usar as duas métricas simultaneamente. Se você usa nós maiores, o escalonamento do CoreDNS é baseado no número de núcleos de CPU. Por outro lado, se você usar nós menores, o número de réplicas do CoreDNS depende dos núcleos da CPU em seu plano de dados. A configuração do autoescalador proporcional tem a seguinte aparência:
linear: '{"coresPerReplica":256,"min":1,"nodesPerReplica":16}'
Escolhendo uma AMI com grupo de nós
O EKS fornece soluções otimizadas EC2 AMIs que são usadas pelos clientes para criar grupos de nós autogerenciados e gerenciados. Eles AMIs são publicados em todas as regiões para cada versão compatível do Kubernetes. O EKS os marca AMIs como obsoletos quando algum bug é CVEs descoberto. Portanto, a recomendação é não consumir a versão obsoleta AMIs ao escolher uma AMI para o grupo de nós.
O obsoleto AMIs pode ser filtrado usando a API Ec2 describe-images usando o comando abaixo:
aws ec2 describe-images --image-id ami-0d551c4f633e7679c --no-include-deprecated
Você também pode reconhecer uma AMI obsoleta verificando se a saída describe-image contém um campo as. DeprecationTime Por exemplo:
aws ec2 describe-images --image-id ami-xxx --no-include-deprecated
{
"Images": [
{
"Architecture": "x86_64",
"CreationDate": "2022-07-13T15:54:06.000Z",
"ImageId": "ami-xxx",
"ImageLocation": "123456789012/eks_xxx",
"ImageType": "machine",
"Public": false,
"OwnerId": "123456789012",
"PlatformDetails": "Linux/UNIX",
"UsageOperation": "RunInstances",
"State": "available",
"BlockDeviceMappings": [
{
"DeviceName": "/dev/xvda",
"Ebs": {
"DeleteOnTermination": true,
"SnapshotId": "snap-0993a2fc4bbf4f7f4",
"VolumeSize": 20,
"VolumeType": "gp2",
"Encrypted": false
}
}
],
"Description": "EKS Kubernetes Worker AMI with AmazonLinux2 image, (k8s: 1.19.15, docker: 20.10.13-2.amzn2, containerd: 1.4.13-3.amzn2)",
"EnaSupport": true,
"Hypervisor": "xen",
"Name": "aws_eks_optimized_xxx",
"RootDeviceName": "/dev/xvda",
"RootDeviceType": "ebs",
"SriovNetSupport": "simple",
"VirtualizationType": "hvm",
"DeprecationTime": "2023-02-09T19:41:00.000Z"
}
]
}