10 errors habituals de Kubernetes

Nota. transl.: Els autors d'aquest article són enginyers d'una petita empresa txeca, pipetail. Van aconseguir reunir una llista meravellosa de problemes [de vegades banals, però encara] molt urgents i idees errònies relacionades amb el funcionament dels clústers de Kubernetes.

10 errors habituals de Kubernetes

Al llarg dels anys d'ús de Kubernetes, hem treballat amb un gran nombre de clústers (administrats i no gestionats, a GCP, AWS i Azure). Amb el temps, vam començar a notar que alguns errors es repetien constantment. No obstant això, això no té vergonya: la majoria els hem fet nosaltres mateixos!

L'article conté els errors més comuns i també esmenta com corregir-los.

1. Recursos: peticions i límits

Definitivament, aquest article mereix la màxima atenció i el primer lloc a la llista.

Sol·licitud de CPU normalment o bé no s'especifica en absolut o té un valor molt baix (per col·locar tantes beines a cada node com sigui possible). Així, els nodes es sobrecarreguen. Durant els temps de càrrega elevada, la potència de processament del node s'utilitza plenament i una càrrega de treball particular rep només el que "demanava" per L'acceleració de la CPU. Això comporta una major latència de l'aplicació, temps d'espera i altres conseqüències desagradables. (Llegiu més sobre això a la nostra altra traducció recent: "Límits de la CPU i acceleració agressiva a Kubernetes"- aprox. trad.)

El millor esforç (extremadament no recomanat):

resources: {}

Sol·licitud de CPU extremadament baixa (extremadament no recomanat):

   resources:
      Requests:
        cpu: "1m"

D'altra banda, la presència d'un límit de CPU pot provocar que els pods ometin els cicles de rellotge de manera no raonable, fins i tot si el processador del node no està completament carregat. De nou, això pot provocar un augment dels retards. La polèmica continua al voltant del paràmetre Quota de CPU CFS al nucli de Linux i l'acceleració de la CPU en funció dels límits establerts, així com desactivar la quota CFS... Per desgràcia, els límits de la CPU poden causar més problemes dels que poden resoldre. Podeu trobar més informació sobre això a l'enllaç següent.

Selecció excessiva (compromis excessiu) problemes de memòria poden provocar problemes més grans. Assolir el límit de la CPU implica saltar els cicles de rellotge, mentre que assolir el límit de memòria implica matar el pod. Has observat mai OOMkill? Sí, és exactament del que estem parlant.

Voleu minimitzar la probabilitat que això passi? No assigneu més memòria i utilitzeu QoS (Qualitat de servei) garantida posant la sol·licitud de memòria al límit (com a l'exemple següent). Llegeix més sobre això a Presentacions de Henning Jacobs (Enginyer principal a Zalando).

Esclatable (més probabilitat de ser mort per OOM):

   resources:
      requests:
        memory: "128Mi"
        cpu: "500m"
      limits:
        memory: "256Mi"
        cpu: 2

Garantit:

   resources:
      requests:
        memory: "128Mi"
        cpu: 2
      limits:
        memory: "128Mi"
        cpu: 2

Què pot ajudar a l'hora de configurar els recursos?

Amb servidor de mètriques podeu veure el consum actual de recursos de la CPU i l'ús de memòria per pods (i contenidors dins d'ells). Molt probablement, ja l'estàs utilitzant. Només heu d'executar les ordres següents:

kubectl top pods
kubectl top pods --containers
kubectl top nodes

Tanmateix, només mostren l'ús actual. Pot donar-vos una idea aproximada de l'ordre de magnitud, però finalment ho necessitareu historial de canvis en les mètriques al llarg del temps (per respondre preguntes com: "Quina va ser la càrrega màxima de la CPU?", "Quina va ser la càrrega ahir al matí?", etc.). Per a això podeu utilitzar Prometeu, DataDog i altres eines. Simplement obtenen mètriques del servidor de mètriques i les emmagatzemen, i l'usuari pot consultar-les i representar-les en conseqüència.

VerticalPodAutoscaler permet automatitzar aquest procés. Fa un seguiment de l'historial d'ús de la CPU i la memòria i estableix noves sol·licituds i límits basats en aquesta informació.

Utilitzar la potència de càlcul de manera eficient no és una tasca fàcil. És com jugar a Tetris tot el temps. Si pagueu massa per una potència de càlcul amb un consum mitjà baix (per exemple, un 10%), us recomanem que busqueu productes basats en AWS Fargate o Virtual Kubelet. Es basen en un model de facturació sense servidor/pagament per ús, que pot resultar més barat en aquestes condicions.

2. Sondes de vivacitat i preparació

De manera predeterminada, les comprovacions de vivacitat i preparació no estan habilitades a Kubernetes. I de vegades s'obliden d'encendre-les...

Però, de quina altra manera es pot iniciar un reinici del servei en cas d'un error fatal? I com sap l'equilibrador de càrrega que un pod està preparat per acceptar trànsit? O que pot gestionar més trànsit?

Aquestes proves sovint es confonen entre si:

  • Vida — Comprovació de "supervivència", que reinicia el pod si falla;
  • Preparació — comprovació de la preparació, si falla, desconnecta el pod del servei Kubernetes (això es pot comprovar mitjançant kubectl get endpoints) i el trànsit no hi arriba fins que la següent comprovació s'hagi completat correctament.

Aquests dos controls REALITZADA DURANT TOT EL CICLE DE VIDA DEL POD. És molt important.

Una idea errònia comuna és que les sondes de preparació només s'executen a l'inici perquè l'equilibrador pugui saber que el pod està preparat (Ready) i pot començar a processar el trànsit. Tanmateix, aquesta és només una de les opcions per al seu ús.

Una altra és la possibilitat d'esbrinar que el trànsit a la pod és excessiu i la sobrecarrega (o el pod realitza càlculs que requereixen molts recursos). En aquest cas, la comprovació de preparació ajuda reduir la càrrega de la beina i "refredar-la".. La realització satisfactòria d'una comprovació de preparació en el futur permet augmentar de nou la càrrega a la beina. En aquest cas (si la prova de preparació falla), el fracàs de la prova de vivacitat seria molt contraproduent. Per què reiniciar un pod que està sa i treballa dur?

Per tant, en alguns casos, no fer cap comprovació és millor que habilitar-los amb paràmetres configurats incorrectament. Com s'ha dit anteriorment, si verificació de vivacitat còpies verificació de preparació, llavors estàs en grans problemes. La possible opció és configurar només prova de preparacióI vida perillosa deixar de banda.

Ambdós tipus de comprovacions no haurien de fallar quan fallen les dependències comunes, en cas contrari això provocarà una fallada en cascada (com una allau) de tots els pods. En altres paraules, no et facis mal.

3. LoadBalancer per a cada servei HTTP

El més probable és que tingueu serveis HTTP al vostre clúster que us agradaria reenviar al món exterior.

Si obriu el servei com type: LoadBalancer, el seu controlador (segons el proveïdor de serveis) proporcionarà i negociarà un LoadBalancer extern (no necessàriament s'executa a L7, sinó fins i tot a L4), i això pot afectar el cost (adreça IPv4 estàtica externa, potència de càlcul, facturació per segon). ) per la necessitat de crear un gran nombre d'aquests recursos.

En aquest cas, és molt més lògic utilitzar un equilibrador de càrrega extern, obrint serveis com type: NodePort. O millor encara, ampliar alguna cosa així nginx-ingress-controller (O traefik), que serà l'únic Port del node punt final associat amb l'equilibrador de càrrega extern i encaminarà el trànsit al clúster mitjançant ingrés-Recursos Kubernetes.

Altres (micro)serveis intraclúster que interactuen entre ells poden "comunicar-se" mitjançant serveis com ClústerIP i un mecanisme de descoberta de serveis integrat mitjançant DNS. Simplement no utilitzeu el seu DNS/IP públic, ja que això pot afectar la latència i augmentar el cost dels serveis al núvol.

4. Autoscaling d'un clúster sense tenir en compte les seves característiques

Quan afegiu nodes i els elimineu d'un clúster, no us hauríeu de confiar en algunes mètriques bàsiques com l'ús de la CPU en aquests nodes. La planificació del pod ha de tenir en compte molts restriccions, com ara l'afinitat de pod/node, contaminacions i toleracions, sol·licituds de recursos, QoS, etc. L'ús d'un autoscaler extern que no tingui en compte aquests matisos pot generar problemes.

Imagineu que s'hauria de programar un pod determinat, però es sol·licita/desmunta tota la potència de la CPU disponible i el pod queda atrapat en un estat Pending. L'autoescalador extern veu la càrrega actual mitjana de la CPU (no la sol·licitada) i no inicia l'expansió (escalada) - no afegeix un altre node. Com a resultat, aquest pod no es programarà.

En aquest cas, escala inversa (ampliació) — eliminar un node d'un clúster sempre és més difícil d'implementar. Imagineu que teniu un pod amb estat (amb emmagatzematge persistent connectat). Volums persistents normalment pertanyen zona de disponibilitat específica i no es reprodueixen a la regió. Així, si un autoscaler extern suprimeix un node amb aquest pod, el planificador no podrà programar aquest pod en un altre node, ja que això només es pot fer a la zona de disponibilitat on es troba l'emmagatzematge persistent. Pod quedarà encallat a l'estat Pending.

Molt popular a la comunitat Kubernetes clúster-autoscaler. S'executa en un clúster, admet API dels principals proveïdors de núvol, té en compte totes les restriccions i pot escalar en els casos anteriors. També és capaç d'ampliar-se mantenint tots els límits establerts, estalviant així diners (que, d'altra manera, es gastarien en capacitat no utilitzada).

5. Descuidar les capacitats IAM/RBAC

Aneu amb compte d'utilitzar usuaris d'IAM amb secrets persistents màquines i aplicacions. Organitzeu l'accés temporal mitjançant rols i comptes de servei (comptes de servei).

Sovint ens trobem amb el fet que les claus d'accés (i els secrets) estan codificats en dur a la configuració de l'aplicació, a més de descuidar la rotació de secrets tot i tenir accés a Cloud IAM. Utilitzeu rols d'IAM i comptes de servei en comptes d'usuaris quan escaigui.

10 errors habituals de Kubernetes

Oblideu-vos de kube2iam i aneu directament als rols IAM per als comptes de servei (tal com es descriu a nota del mateix nom Štěpán Vraný):

apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/my-app-role
  name: my-serviceaccount
  namespace: default

Una anotació. No tan difícil, oi?

A més, no atorgueu privilegis als comptes de servei i als perfils d'instància admin и cluster-adminsi no ho necessiten. Això és una mica més difícil d'implementar, especialment als RBAC K8, però definitivament val la pena l'esforç.

6. No confieu en l'antiafinitat automàtica per a les beines

Imagineu que teniu tres rèpliques d'algun desplegament en un node. El node cau, i juntament amb ell totes les rèpliques. Situació desagradable, oi? Però, per què totes les rèpliques estaven al mateix node? No se suposa que Kubernetes ofereix alta disponibilitat (HA)?!

Malauradament, el programador de Kubernetes, per iniciativa pròpia, no compleix les regles d'existència separada (antiafinitat) per beines. S'han de fer constar explícitament:

// опущено для краткости
      labels:
        app: zk
// опущено для краткости
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: "app"
                    operator: In
                    values:
                    - zk
              topologyKey: "kubernetes.io/hostname"

Això és tot. Ara els pods es programaran en diferents nodes (aquesta condició només es verifica durant la programació, però no durant el seu funcionament, per tant requiredDuringSchedulingIgnoredDuringExecution).

Aquí estem parlant podAntiAffinity en diferents nodes: topologyKey: "kubernetes.io/hostname", - i no sobre diferents zones de disponibilitat. Per implementar un HA complet, haureu d'aprofundir en aquest tema.

7. Ignorant PodDisruptionBudgets

Imagineu que teniu una càrrega de producció en un clúster de Kubernetes. Periòdicament, els nodes i el propi clúster s'han d'actualitzar (o donar de baixa). PodDisruptionBudget (PDB) és una cosa així com un acord de garantia de servei entre administradors i usuaris del clúster.

PDB us permet evitar interrupcions del servei causades per la manca de nodes:

apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: zk-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: zookeeper

En aquest exemple, vostè, com a usuari del clúster, diu als administradors: "Hola, tinc un servei de cuidador del zoològic, i facis el que facis, m'agradaria tenir almenys 2 rèpliques d'aquest servei sempre disponibles".

Podeu llegir més sobre això aquí.

8. Múltiples usuaris o entorns en un clúster comú

Espais de noms de Kubernetes (espais de noms) no proporcionen un aïllament fort.

Una idea errònia comuna és que si desplegueu una càrrega que no sigui de producte en un espai de noms i una càrrega de producte en un altre, no s'influiran mútuament de cap manera... No obstant això, es pot aconseguir un cert nivell d'aïllament utilitzant les sol·licituds/limitacions de recursos, establint quotes i establint classes de prioritat. Una mica d'aïllament "físic" al pla de dades es proporciona per afinitats, toleràncies, taques (o selectors de nodes), però aquesta separació és bastant. difícil implementar.

Aquells que necessiten combinar ambdós tipus de càrregues de treball en un mateix clúster hauran de fer front a la complexitat. Si no hi ha aquesta necessitat, i us podeu permetre el luxe de tenir-ne un un clúster més (per exemple, en un núvol públic), llavors és millor fer-ho. Això aconseguirà un nivell d'aïllament molt més elevat.

9. externalTrafficPolicy: Clúster

Molt sovint veiem que tot el trànsit dins del clúster passa a través d'un servei com NodePort, per al qual s'estableix la política predeterminada. externalTrafficPolicy: Cluster... Vol dir això Port del node està obert a tots els nodes del clúster i podeu utilitzar qualsevol d'ells per interactuar amb el servei desitjat (conjunt de pods).

10 errors habituals de Kubernetes

Al mateix temps, els pods reals associats amb el servei NodePort esmentat anteriorment solen estar disponibles només en un determinat subconjunt d'aquests nodes. En altres paraules, si em connecto a un node que no té el pod requerit, reenviarà el trànsit a un altre node, afegint un salt i augmentar la latència (si els nodes es troben en diferents zones de disponibilitat/centres de dades, la latència pot ser força elevada; a més, els costos de trànsit de sortida augmentaran).

D'altra banda, si un determinat servei de Kubernetes té una política establerta externalTrafficPolicy: Local, llavors NodePort només s'obre en aquells nodes on s'estan executant els pods necessaris. Quan s'utilitza un equilibrador de càrrega extern que comprova l'estat (control de salut) punts finals (com ho fa AWS ELB), Ell enviarà trànsit només als nodes necessaris, que tindrà un efecte beneficiós sobre els retards, les necessitats d'informàtica, les factures de sortida (i el sentit comú dicta el mateix).

Hi ha una gran probabilitat que ja estigueu utilitzant alguna cosa així traefik o nginx-ingress-controller com a punt final de NodePort (o LoadBalancer, que també utilitza NodePort) per encaminar el trànsit d'entrada HTTP, i establir aquesta opció pot reduir significativament la latència d'aquestes sol·licituds.

В aquesta publicació Podeu obtenir més informació sobre externalTrafficPolicy, els seus avantatges i desavantatges.

10. No us lligueu als clústers i no abuseu del pla de control

Anteriorment, era costum cridar als servidors amb noms propis: Anton, HAL9000 i Colossus... Avui s'han substituït per identificadors generats aleatòriament. No obstant això, l'hàbit es va mantenir, i ara els noms propis van als clústers.

Una història típica (basada en fets reals): tot va començar amb una prova de concepte, de manera que el clúster tenia un nom orgullós les proves… Han passat anys i ENCARA s'utilitza a la producció, i tothom té por de tocar-lo.

No hi ha res divertit que els grups es converteixin en mascotes, així que recomanem que els elimineu periòdicament mentre practiqueu recuperació de desastres (això ajudarà enginyeria del caos -aprox. trad.). A més, no estaria malament treballar a la capa de control (avió de control). Tenir por de tocar-lo no és bon senyal. Etcd mort? Nois, esteu realment en problemes!

D'altra banda, no t'has de deixar portar manipulant-lo. Amb temps la capa de control pot tornar-se lenta. Molt probablement, això es deu al fet que es creen un gran nombre d'objectes sense la seva rotació (una situació habitual quan s'utilitza Helm amb la configuració predeterminada, per això no s'actualitza el seu estat en configmaps/secrets; com a resultat, milers d'objectes s'acumulen en la capa de control) o amb l'edició constant d'objectes kube-api (per a l'escalat automàtic, per a CI/CD, per al monitoratge, registres d'esdeveniments, controladors, etc.).

A més, recomanem consultar els acords SLA/SLO amb el proveïdor de Kubernetes gestionat i parar atenció a les garanties. El venedor pot garantir control de la disponibilitat de la capa (o els seus subcomponents), però no el retard p99 de les sol·licituds que li envieu. En altres paraules, podeu entrar kubectl get nodes, i rebrà una resposta només després de 10 minuts, i això no suposarà una violació dels termes de l'acord de servei.

11. Bonificació: utilitzant l'última etiqueta

Però això ja és un clàssic. Últimament ens trobem amb aquesta tècnica amb menys freqüència, ja que molts, després d'haver après d'una amarga experiència, han deixat d'utilitzar l'etiqueta. :latest i va començar a fixar versions. Hura!

ECR manté la immutabilitat de les etiquetes d'imatge; Us recomanem que us familiaritzeu amb aquesta característica excepcional.

Resum

No espereu que tot funcioni d'un dia per l'altre: Kubernetes no és una panacea. Mala aplicació romandrà així fins i tot a Kubernetes (i probablement empitjorarà). La negligència comportarà una complexitat excessiva, un treball lent i estressant de la capa de control. A més, corre el risc de quedar-se sense una estratègia de recuperació de desastres. No espereu que Kubernetes proporcioni aïllament i alta disponibilitat immediatament. Passeu una estona fent que la vostra aplicació sigui realment nativa del núvol.

Podeu familiaritzar-vos amb les experiències infructuoses de diversos equips aquest recull de contes per Henning Jacobs.

Aquells que vulguin afegir-se a la llista d'errors que apareixen en aquest article poden contactar amb nosaltres a Twitter (@MarekBartik, @MstrsObserver).

PS del traductor

Llegeix també al nostre blog:

Font: www.habr.com

Afegeix comentari