Versión imprimible multipagina. Haga click aquí para imprimir.
Gestionar y ejecutar aplicaciones
1 - Corre una aplicación stateless usando un Deployment
Ésta página enseña como correr una aplicación stateless usando un deployment de Kubernetes.
Objetivos
- Crear un
deploymentde nginx. - Usar kubectl para obtener información acerca del
deployment. - Actualizar el
deployment.
Antes de empezar
Debes tener un cluster Kubernetes a tu dispocición, y la herramienta de línea de comandos kubectl debe estar configurada. Si no tienes un cluster, puedes crear uno utilizando Minikube,
o puedes utilizar una de las siguientes herramientas en línea:
Para verificar la versión, ingresa kubectl version.
Creando y explorando un nginx deployment
Puedes correr una aplicación creando un deployment de Kubernetes, y puedes describir el deployment en un fichero YAML. Por ejemplo, el siguiente fichero YAML describe un deployment que corre la imágen Docker nginx:1.7.9:
apiVersion: apps/v1 # Usa apps/v1beta2 para versiones anteriores a 1.9.0
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2 # indica al controlador que ejecute 2 pods
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
Crea un
deploymentbasado en el fichero YAML:kubectl apply -f https://k8s.io/examples/application/deployment.yamlObtén información acerca del
deployment:kubectl describe deployment nginx-deploymentEl resultado es similar a esto:
Name: nginx-deployment Namespace: default CreationTimestamp: Tue, 30 Aug 2016 18:11:37 -0700 Labels: app=nginx Annotations: deployment.kubernetes.io/revision=1 Selector: app=nginx Replicas: 2 desired | 2 updated | 2 total | 2 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 1 max unavailable, 1 max surge Pod Template: Labels: app=nginx Containers: nginx: Image: nginx:1.7.9 Port: 80/TCP Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: nginx-deployment-1771418926 (2/2 replicas created) No events.Lista los pods creados por el
deployment:kubectl get pods -l app=nginxEl resultado es similar a esto:
NAME READY STATUS RESTARTS AGE nginx-deployment-1771418926-7o5ns 1/1 Running 0 16h nginx-deployment-1771418926-r18az 1/1 Running 0 16hMuestra información acerca del pod:
kubectl describe pod <pod-name>donde
<pod-name>es el nombre de uno de los pods.
Actualizando el deployment
Puedes actualizar el deployment aplicando un nuevo fichero YAML. El siguiente fichero YAML
especifica que el deployment debería ser actualizado para usar nginx 1.8.
apiVersion: apps/v1 # Usa apps/v1beta2 para versiones anteriores a 1.9.0
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.8 # Actualiza la versión de nginx de 1.7.9 a 1.8
ports:
- containerPort: 80
Aplica el nuevo fichero YAML:
kubectl apply -f https://k8s.io/examples/application/deployment-update.yamlComprueba como el
deploymentcrea nuevos pods con la nueva imagen mientras va eliminando los pods con la especificación antigua:kubectl get pods -l app=nginx
Escalando la aplicación aumentado el número de replicas
Puedes aumentar el número de pods en tu deployment aplicando un nuevo fichero YAML.
El siguiente fichero YAML especifica un total de 4 replicas, lo que significa que el deployment debería tener cuatro pods:
apiVersion: apps/v1 # Usa apps/v1beta2 para versiones anteriores a 1.9.0
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 4 # Actualiza el número de réplicas de 2 a 4
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.8
ports:
- containerPort: 80
Aplica el nuevo fichero YAML:
kubectl apply -f https://k8s.io/examples/application/deployment-scale.yamlVerifica que el
deploymenttiene cuatro pods:kubectl get pods -l app=nginxEl resultado es similar a esto:
NAME READY STATUS RESTARTS AGE nginx-deployment-148880595-4zdqq 1/1 Running 0 25s nginx-deployment-148880595-6zgi1 1/1 Running 0 25s nginx-deployment-148880595-fxcez 1/1 Running 0 2m nginx-deployment-148880595-rwovn 1/1 Running 0 2m
Eliminando un deployment
Elimina el deployment por el nombre:
kubectl delete deployment nginx-deployment
ReplicationControllers
La manera preferida de crear una aplicación con múltiples instancias es usando un Deployment, el cual usa un ReplicaSet. Antes de que Deployment y ReplicaSet fueran introducidos en Kubernetes, aplicaciones con múltiples instancias eran configuradas usando un ReplicationController.
¿Qué sigue?
- Aprende más acerca de Deployments.
2 - Escalar un StatefulSet
Esta página muestra cómo escalar un StatefulSet. Escalar un StatefulSet es incrementar o decrementar el número de réplicas.
Antes de empezar
Los StatefulSets están solamente disponibles en Kubernetes 1.5 o posterior. Para verificar su versión de Kubernetes puede ejecutar
kubectl version.No todas las aplicaciones que manejan estados escalan correctamente. Si no está seguro sobre si puede escalar sus StatefulSets, visite los conceptos de StatefulSet o el tutorial sobre StatefulSet para más información.
Solamente se debe realizar un escalamiento cuando esté lo suficientemente seguro del buen funcionamiento de su clúster y de las aplicaciones que manejan estados.
Escalando StatefulSets
Uso de kubectl para escalar StatefulSets
Como primer paso, identifica el StatefulSet que deseas escalar.
kubectl get statefulsets <nombre-del-stateful-set>
Cambia el número de réplicas de tu StatefulSet:
kubectl scale statefulsets <nombre-del-stateful-set> --replicas=<número-de-réplicas>
Hacer actualizaciones "in-place" en los StatefulSets
De manera alternativa, se pueden hacer actualizaciones in-place en tus StatefulSets.
Si el StatefulSet fue inicialmente creado con kubectl apply,
puedes actualizar .spec.replicas en el manifiesto previamente definido y ahí hacer kubectl apply:
kubectl apply -f <archivo-stateful-set-actualizado>
De otra manera, edita esa línea con kubectl edit:
kubectl edit statefulsets <nombre-del-stateful-set>
También puedes usar kubectl patch:
kubectl patch statefulsets <nombre-del-stateful-set> -p '{"spec":{"replicas":<número-de-réplicas>}}'
Solución de Problemas
El escalamiento hacia abajo no funciona correctamente
No se puede escalar hacia abajo un StatefulSet cuando alguno de los Pods que administra está dañado. Desescalar solo tiene lugar después de tener los Pods disponibles.
Si spec.replicas > 1, Kubernetes no puede determinar la razón de un Pod dañado. Esto puede ser el resultado de una falla permanente o una falla transitoria. Una falla transitoria puede ser causada por un reinicio necesario para una actualización o mantenimiento.
Si el Pod está dañado con una falla permanente, escalar sin corregir la falla puede llevarnos a un estado donde el StatefulSet cae en una cantidad de miembros inferior a la cantidad de replicas que son necesarias para funcionar correctamente. Esto puede causar que el StatefulSet no este disponible.
Si el Pod está dañado por una falla transitoria y el Pod puede volver a estar disponible nuevamente, el error transitorio puede interferir con la operación de escalar. Algunas bases de datos distribuidas tienen errores cuando los nodos se unen y abandonan en el mismo momento. Es mejor analizar acerca de escalar la operación a nivel de la aplicación y realizar el escalamiento solamente cuando está seguro que el clúster de la aplicación está funcionando y en buen estado.
¿Qué sigue?
- Aprenda más acerca de borrar un StatefulSet.
3 - Borrar un StatefulSet
Esta página muestra cómo se debe eliminar un StatefulSet.
Antes de empezar
- Se asume que se tiene una aplicación del tipo StatefulSet corriendo en tu clúster.
Borrando un StatefulSet
Se puede eliminar un StatefulSet de la misma manera que se eliminan el resto de los recursos en Kubernetes:
Usa el comando kubectl delete y especifica el StatefulSet, usando su nombre o el archivo con el que fue creado.
kubectl delete -f <archivo.yaml>
kubectl delete statefulsets <nombre-del-stateful-set>
Puede suceder que necesites eliminar los servicios headless asociados después de eliminar el StatefulSet.
kubectl delete service <nombre-del-servicio>
Cuando se elimina un StatefulSet utilizando kubectl, el StatefulSet escala a 0.
Todos los Pods que eran parte de esta carga de trabajo son eliminados. Si tú quieres eliminar
solo el StatefulSet y no los Pods utiliza --cascade=orphan. Por ejemplo:
kubectl delete -f <archivo.yaml> --cascade=orphan
Agregando --cascade=orphan al comando kubectl delete, los Pods administrados por el StatefulSet
dejan de pertenecer al StatefulSet cuando es eliminado. Si los pods tienen una
etiqueta app.kubernetes.io/name=MyApp se los puede eliminar de la siguiente manera:
kubectl delete pods -l app.kubernetes.io/name=MyApp
Volúmenes Persistentes
Eliminar los Pods de un StatefulSet no va a eliminar los volúmenes asociados. Esto es para asegurar que se tiene una oportunidad de copiar los datos fuera del volumen antes de eliminarlo. Borrar el PVC después de que los pods estén terminados puede disparar la eliminación del Volumen Persistente que hay detrás dependiendo de la clase de almacenamiento y la política de reclamo. Nunca debes asumir la capacidad de acceder a un volumen después de la eliminación del claim.
Nota:
Ten cuidado al borrar un PVC ya que puede llevar una pérdida de datos.Eliminación completa de un StatefulSet
Para eliminar todo en un StatefulSet, incluyendo los pods asociados, se puede correr una serie de comandos similares a los siguientes:
grace=$(kubectl get pods <stateful-set-pod> --template '{{.spec.terminationGracePeriodSeconds}}')
kubectl delete statefulset -l app.kubernetes.io/name=MyApp
sleep $grace
kubectl delete pvc -l app.kubernetes.io/name=MyApp
En este ejemplo, los Pods tienen la etiqueta app.kubernetes.io/name=MyApp,
sustituye la misma por tu propia etiqueta.
Forzar la eliminación de los Pods de un StatefulSet
Si encuentras algunos pods bloqueados en tu StatefulSet en el estado 'Terminating' o 'Unknown' por un largo período de tiempo, puede ser que necesites intervenir manualmente para forzar la eliminación de los pods del apiserver. Ésta es una tarea potencialmente riesgosa. Visita Forzar eliminación de Pods en StatefulSet para más detalles.
¿Qué sigue?
Aprende más sobre Forzar eliminación de Pods en StatefulSet.
4 - Eliminación Forzosa de Pods de StatefulSet
Esta página muestra cómo eliminar Pods que son parte de un StatefulSet, y explica las consideraciones a tener en cuenta al hacerlo.
Antes de empezar
- Esta es una tarea bastante avanzada y tiene el potencial de violar algunas de las propiedades inherentes de StatefulSet.
- Antes de proceder, familiarízate con las consideraciones enumeradas a continuación.
Consideraciones de StatefulSet
En la operación normal de un StatefulSet, nunca hay necesidad de eliminar forzosamente un Pod de StatefulSet. El controlador de StatefulSet es responsable de crear, escalar y eliminar miembros del StatefulSet. Intenta asegurar que el número especificado de Pods, desde el ordinal 0 hasta N-1, estén vivos y listos. StatefulSet asegura que, en cualquier momento, exista como máximo un Pod con una identidad dada, corriendo en un clúster. Esto se refiere a la semántica de como máximo uno proporcionada por un StatefulSet.
La eliminación manual forzada debe realizarse con precaución, ya que tiene el potencial de violar la semántica de como máximo uno, inherente a StatefulSet. Los StatefulSets pueden usarse para ejecutar aplicaciones distribuidas y agrupadas que necesitan una identidad de red estable y almacenamiento estable. Estas aplicaciones a menudo tienen configuraciones que dependen de un conjunto de un número fijo de miembros con identidades fijas. Tener múltiples miembros con la misma identidad puede ser desastroso y puede llevar a pérdida de datos (por ejemplo, escenario de cerebro dividido en sistemas basados en quórum).
Eliminar Pods
Puedes realizar una eliminación de Pod paulatina con el siguiente comando:
kubectl delete pods <pod>
Para que lo anterior conduzca a una terminación paulatina, el Pod no debe especificar un
pod.Spec.TerminationGracePeriodSeconds de 0. La práctica de establecer un
pod.Spec.TerminationGracePeriodSeconds de 0 segundos es insegura y se desaconseja rotundamente
para los Pods de StatefulSet. La eliminación paulatina es segura y garantizará que el Pod
se apague de manera paulatina, antes de que kubelet elimine el nombre en el apiserver.
Un Pod no se elimina automáticamente cuando un nodo no es accesible. Los Pods que se ejecutan en un Nodo inaccesible entran en el estado 'Terminating' o 'Unknown' después de un tiempo de espera. Los Pods también pueden entrar en estos estados cuando el usuario intenta la eliminación paulatina de un Pod en un nodo inaccesible. Las únicas formas en que un Pod en tal estado puede ser eliminado del apiserver son las siguientes:
- El objeto Node es eliminado (ya sea por ti, o por el Controlador de Nodo).).
- Kubelet, en el nodo no responsivo, comienza a responder, mata el Pod y elimina la entrada del apiserver.
- Eliminación forzada del Pod por el usuario.
La mejor práctica recomendada es usar el primer o segundo enfoque. Si un nodo está confirmado como muerto (por ejemplo, desconectado permanentemente de la red, apagado, etc.), entonces elimina el objeto Node. Si el nodo es afectado de una partición de red, entonces trata de resolver esto o espera a que se resuelva. Cuando la partición se solucione, kubelet completará la eliminación del Pod y liberará su nombre en el apiserver.
Normalmente, el sistema completa la eliminación una vez que el Pod ya no se está ejecutando en un nodo, o el nodo es eliminado por un administrador. Puedes anular esto forzando la eliminación del Pod.
Eliminación Forzosa
Las eliminaciones forzosas no esperan confirmación de kubelet de que el Pod ha sido terminado. Independientemente de si una eliminación forzosa tiene éxito en matar un Pod, inmediatamente liberará el nombre del apiserver. Esto permitiría que el controlador de StatefulSet cree un Pod de reemplazo con esa misma identidad; esto puede llevar a la duplicación de un Pod que aún está en ejecución, y si dicho Pod todavía puede comunicarse con los otros miembros del StatefulSet, violará la semántica de como máximo uno que StatefulSet está diseñado para garantizar.
Cuando eliminas forzosamente un Pod de StatefulSet, estás afirmando que el Pod en cuestión nunca volverá a hacer contacto con otros Pods en el StatefulSet y su nombre puede ser liberado de forma segura para que se cree un reemplazo.
Si quieres eliminar un Pod de forma forzosa usando la versión de kubectl >= 1.5, haz lo siguiente:
kubectl delete pods <pod> --grace-period=0 --force
Si estás usando cualquier versión de kubectl <= 1.4, deberías omitir la opción --force y usar:
kubectl delete pods <pod> --grace-period=0
Si incluso después de estos comandos el pod está atascado en el estado Unknown, usa el siguiente comando para
eliminar el Pod del clúster:
kubectl patch pod <pod> -p '{"metadata":{"finalizers":null}}'
Siempre realiza la eliminación forzosa de Pods de StatefulSet con cuidado y con pleno conocimiento de los riesgos involucrados.
¿Qué sigue?
Aprende más sobre depurar un StatefulSet.
5 - Especificando un presupuesto de interrupción para tu aplicación
Kubernetes v1.21 [stable]Esta pagina enseña cómo limitar el número de interrupciones concurrentes que afectan a tu aplicación definiendo presupuestos de interrupción de pods, Pod Disruption Budgets (PDB) en inglés. Estos presupuestos definen el mínimo número de pods que deben estar ejecutándose en todo momento para asegurar la disponibilidad de la aplicación durante operaciones de mantenimiento efectuadas sobre los nodos por los administradores del clúster.
Antes de empezar
- Tener permisos de administrador sobre la aplicación que está corriendo en Kubernetes y requiere alta disponibilidad
- Deberías saber cómo desplegar Múltiples réplicas de aplicaciones stateless y/o Múltiples réplicas de aplicaciones stateful.
- Deberías haber leído acerca de Interrupciones de un Pod.
- Deberías confirmar con el propietario del clúster o proveedor del servicio que respeten los presupuestos de interrupción de pods.
Protegiendo una aplicación con un PodDisruptionBudget
- Identifica la aplicación que quieres proteger con un PodDisruptionBudget (PDB).
- Revisa cómo afectan las interrupciones a tu aplicación.
- Crea un PDB usando un archivo YAML.
- Crea el objeto PDB desde el archivo YAML.
Identifica la aplicación que quieres proteger
El caso más común es proteger aplicaciones que usan uno de los controladores incorporados en Kubernetes:
- Deployment
- Replicationcontrolador
- ReplicaSet
- StatefulSet
En este caso, toma nota del .spec.selector que utiliza el controlador; el mismo se utilizará en el spec.selector del PDB.
También puedes utilizar PDBs para proteger pods que no están gestionados por uno de los controladores listados arriba, o agrupaciones arbitrarias de pods, con algunas restricciones descritas en controladores arbitrarios y selectores.
Revisa cómo afectan las interrupciones a tu aplicación
Decide cuántas instancias de tu aplicación pueden estar fuera de servicio al mismo tiempo debido a interrupciones voluntarias de corto plazo.
- Frontend stateless:
- Objetivo: evitar reducir capacidad para servir por más de 10%.
- Solución: usar un PDB que especifica minAvailable 90%.
- Objetivo: evitar reducir capacidad para servir por más de 10%.
- Aplicación Stateful con una sola instancia:
- Objetivo: no terminar esta aplicación sin primero confirmar conmigo.
- Posible Solución 1: No usar un PDB y tolerar inactividad ocasional.
- Posible Solución 2: Crea un PDB con maxUnavailable=0. Entiende que el operador del clúster debe consultar contigo antes de terminar tu aplicación. Cuando el operador te contacte, prepara tu aplicación para downtime y elimina el PDB para indicar que estás preparado para la interrupción. Crea el PDB de nuevo al terminar la interrupción.
- Objetivo: no terminar esta aplicación sin primero confirmar conmigo.
- Aplicación Stateful con múltiples instancias como Consul, ZooKeeper, etcd, Redis o MySQL:
- Objetivo: no reducir el número de instancias por debajo del quorum, de lo contrario, las escrituras fallarían.
- Posible Solución 1: fijar maxUnavailable a 1 (funciona con diferentes escalas de aplicación).
- Posible Solución 2: fijar minAvailable al tamaño del quorum (e.g. 3 cuando hay un total de 5 instancias). (Permite más interrupciones a la vez.).
- Objetivo: no reducir el número de instancias por debajo del quorum, de lo contrario, las escrituras fallarían.
- Trabajos por lote reiniciables:
- Objetivo: El trabajo debe completarse en caso de una interrupción voluntaria.
- Posible solución: No cree un PDB. El controlador de Jobs creará un pod de reemplazo.
- Objetivo: El trabajo debe completarse en caso de una interrupción voluntaria.
Lógica de redondeo al especificar porcentajes
Los valores de minAvailable o maxUnavailable pueden expresarse como un número entero o como porcentaje.
- Cuando se especifica un número entero, este representa el número de pods. Por ejemplo, si estableces
minAvailableen 10, siempre deben estar disponibles 10 pods, incluso durante una interrupción. - Cuando se especifica un porcentaje, asignando al valor una cadena de un porcentaje
(por ejemplo,
"50%"), este representa un porcentaje del total de pods. Por ejemplo, si establecesminAvailablea"50%", al menos el 50% de pods seguirán estando disponibles durante una interrupción.
Cuando se especifica el valor como porcentaje, es posible que no se corresponda con un número exacto de pods.
Por ejemplo, si tienes 7 pods y configuras minAvailable a "50%", no queda claro si eso significa que
deben estar disponibles 3 o 4 pods. Kubernetes redondea al número entero superior más cercano, por lo que en este caso,
deben estar disponibles 4 pods. Cuando especificas el valor maxUnavailable como porcentaje, Kubernetes
redondea al alza el número de pods que pueden sufrir interrupciones. Por lo tanto, una interrupción puede
superar el porcentaje maxUnavailable definido. Puedes examinar el
código
que controla este comportamiento.
Especificando un PodDisruptionBudget
Un PodDisruptionBudget tiene tres atributos:
- Un label selector
.spec.selectorpara especificar el grupo de pods donde aplicar el presupuesto. Este campo es requerido. .spec.minAvailableque es una descripción del número de pods del grupo que deben estar disponibles después del desalojo, incluso en ausencia del pod desalojado.minAvailablepuede ser un número absoluto o un porcentaje..spec.maxUnavailable(disponible en Kubernetes 1.7 y superior) que es una descripción del número de pods del grupo que pueden estar indisponibles después del desalojo. Puede ser un número absoluto o un porcentaje.
Nota:
El comportamiento para un selector vacío difiere entre las APIs policy/v1beta1 y policy/v1 paraPodDisruptionBudgets. En el caso de policy/v1beta1 un selector vacío no coincide con ningún pod, mientras
que para el caso de policy/v1, un selector vacío coincide con todos los pods en el namespace.Puedes especificar únicamente un valor para maxUnavailable y minAvailable por PodDisruptionBudget.
maxUnavailable solo se puede usar para controlar el desalojo de pods
que tienen un controlador asociado manejándolos. En los ejemplos a continuación, "réplicas deseadas"
hace referencia al valor 'scale' del controlador que gestiona el grupo de pods seleccionados por el
PodDisruptionBudget.
Ejemplo 1: Con un minAvailable de 5, se permiten los desalojos siempre que dejen
5 o más pods saludables seleccionadas por el selector del presupuesto de interrupción de pods.
Ejemplo 2: Con un minAvailable del 30%, se permiten los desalojos mientras que al menos 30% de la cantidad de réplicas se mantengan saludables.
Ejemplo 3: Con un maxUnavailable de 5, se permiten desalojos siempre que haya como máximo 5
réplicas no saludables entre el número total de réplicas deseadas.
Ejemplo 4: Con un maxUnavailable de 30%, se permiten los desalojos siempre y cuando el número de réplicas
no saludables no supere el 30% del total de réplicas deseadas redondeando al número entero superior más cercano.
Si el número total de réplicas deseadas es solo uno, se permite que esa única réplica sufra una interrupción,
lo que daría lugar a una indisponibilidad efectiva del 100%.
En el uso típico, se usaría un solo presupuesto para una colección de pods administrados por un controlador, por ejemplo, los pods en un solo ReplicaSet o StatefulSet.
Nota:
Un presupuesto de interrupción no garantiza que el número/porcentaje de pods especificado siempre esté disponible. Por ejemplo, un nodo que alberga un pod del grupo puede fallar cuando el grupo está en el tamaño mínimo especificado en el presupuesto, lo que hace que el número de pods disponibles esté por debajo del tamaño especificado. El presupuesto solo puede proteger contra desalojos voluntarios, no contra todas las causas de indisponibilidad.Si estableces un maxUnavailable de 0% (o 0) o un minAvailable de 100% (o igual al
número de réplicas), estás exigiendo que no se produzcan desalojos voluntarios.
puede prevenir que los nodos sean purgados completamente. Cuando estableces cero desalojos voluntarios para un controlador,
como un ReplicaSet, no es posible drenar correctamente un nodo en el que se esté ejecutando uno de esos pods.
Si intentas drenar un nodo en el que se está ejecutando un pod que no puede ser desalojado, el drenaje nunca se completará.
Esto está permitido según la semántica de PodDisruptionBudget.
Puedes encontrar ejemplos de presupuestos de interrupción de pods definidos a continuación. Los ejemplos aplican al
grupo de pods que tienen la etiqueta app: zookeeper.
Ejemplo de PDB usando minAvailable:
Ejemplo de PDB usando maxUnavailable:
Por ejemplo, si el objeto anterior zk-pdb selecciona los pods de un StatefulSet de tamaño 3, ambas
especificaciones tienen el mismo significado exacto. Se recomienda el uso de maxUnavailable ya que
responde automáticamente a los cambios en el número de réplicas del controlador correspondiente.
Crea el objeto PDB
Puedes crear o actualizar el objeto PDB haciendo uso de kubectl.
kubectl apply -f mypdb.yaml
Comprueba el estado del PDB
Utiliza kubectl para comprobar que se ha creado tu PDB.
Suponiendo que en realidad no tengas pods que coincidan con app: zookeeper en tu namespace,
verás algo como esto:
kubectl get poddisruptionbudgets
NAME MIN AVAILABLE MAX UNAVAILABLE ALLOWED DISRUPTIONS AGE
zk-pdb 2 N/A 0 7s
Si hay pods que coinciden (por ejemplo, 3), entonces debes ver algo similar a esto:
kubectl get poddisruptionbudgets
NAME MIN AVAILABLE MAX UNAVAILABLE ALLOWED DISRUPTIONS AGE
zk-pdb 2 N/A 1 7s
El valor distinto a cero de ALLOWED DISRUPTIONS significa que el controlador de interrupción ha visto los pods, contó los pods coincidentes, y actualizó el estado del PDB.
Puedes obtener más información sobre el estado de un PDB con este comando:
kubectl get poddisruptionbudgets zk-pdb -o yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
annotations:
…
creationTimestamp: "2020-03-04T04:22:56Z"
generation: 1
name: zk-pdb
…
status:
currentHealthy: 3
desiredHealthy: 2
disruptionsAllowed: 1
expectedPods: 3
observedGeneration: 1
Estado de salud de un pod
La implementación actual considera pods saludables a aquellos que tienen el elemento .status.conditions
con type="Ready" y status="True".
Estos pods son supervisados a través del campo .status.currentHealthy en el estado del PDB.
Política de desalojo de pods no saludables
Kubernetes v1.31 [stable](habilitado por defecto)Proteger una aplicación con un presupuesto de interrupción de pods garantiza que el número de pods con
.status.currentHealthy no sea inferior al número especificado en .status.desiredHealthy impidiendo el
desalojo de pods en estado saludable. Usando .spec.unhealthyPodEvictionPolicy, también puedes definir el
criterio para considerar el desalojo de pods en estado no saludable. El comportamiento por defecto cuando
no se especifica ninguna política es IfHealthyBudget.
Políticas:
IfHealthyBudget- Los pods en ejecución (
.status.phase="Running"), pero que aún no estén en estado saludable, pueden ser desalojados solo si la aplicación protegida no sufre interrupciones (.status.currentHealthyes igual o mayor que.status.desiredHealthy). Esta política garantiza que los pods en ejecución de una aplicación que ya ha sido interrumpida tenga las máximas posibilidades de llegar a un estado saludable. Esto tiene implicaciones negativas en el drenaje de nodos, que puede verse bloqueado por aplicaciones que presentan un comportamiento anómalo y que estén protegidas por un PDB. Más concretamente, aplicaciones con pods en estado
CrashLoopBackOff(debido a un bug o a una configuración incorrecta), o simplemente pods que no consiguen notificar la condiciónReadypor cualquier motivo.AlwaysAllow- Los pods en ejecución (
.status.phase="Running"), pero que aún no estén en estado saludable, son considerados para su interrupción y pueden ser desalojados independientemente de si cumplen o no con el criterio definido en su PDB. Esto significa que los pods de una aplicación que estén en proceso de ejecutarse, podrían no tener la oportunidad de alcanzar un estado saludable si son interrumpidos. Al aplicar esta política, los gestores de clústeres pueden desalojar fácilmente las aplicaciones que presentan un comportamiento anómalo y que están protegidas por un PDB. Más concretamente, aplicaciones con pods en estado
CrashLoopBackOff(debido a un bug o a una configuración incorrecta), o simplemente pods que no consiguen notificar la condiciónReadypor cualquier motivo.
Nota:
Los pods en fase "pendiente" (Pending), "exitoso" (Succeeded) o "fallido" (Failed), siempre son considerados
para su desalojo.Controladores y selectores arbitrarios
Puedes omitir esta sección si solo utilizas PDBs con los controladores integrados de aplicaciones (Deployment, Replicationcontrolador, ReplicaSet y StatefulSet), con el selector de PDB coincidiendo con el selector del controlador.
Puedes utilizar un PDB con pods controlados por otro tipo de controlador, por un "Operator", o pods individuales, pero con las siguientes restricciones:
- solo puedes usar
.spec.minAvailable, no.spec.maxUnavailable. - solo puedes usar un número entero en
.spec.minAvailable, no un porcentaje.
Puedes usar un selector que selecciona un subconjunto o superconjunto de los pods que pertenecen a un controlador incorporado. Sin embargo, cuando hay varios PDB en un namespace, debes tener cuidado de no crear PDBs cuyos selectores se superponen.
6 - Accediendo a la API de Kubernetes desde un Pod
Esta guía muestra como acceder a la API de Kubernetes desde de un Pod.
Antes de empezar
Debes tener un cluster Kubernetes a tu dispocición, y la herramienta de línea de comandos kubectl debe estar configurada. Si no tienes un cluster, puedes crear uno utilizando Minikube,
o puedes utilizar una de las siguientes herramientas en línea:
Accediendo a la API desde un Pod
El acceder a la API desde un Pod, la ubicacion y autentication del servidor de la API es ligeramente diferente que en el caso de un cliente externo.
La forma más fácil de usar la API de Kubernetes desde un Pod es utilizando una de las bibliotecas de cliente oficiales. Estas bibliotecas pueden automáticamente descubrir el servidor de la API y autenticarse.
Usando Bibliotecas de Cliente Oficiales
Desde un Pod, las formas recomendadas de conectarse a la API de Kubernetes son:
Para un cliente de Go, utilice la biblioteca oficial del cliente de Go. La función
rest.InClusterConfig()maneja automáticamente el descubrimiento del host de la API y la autenticación. Vea un ejemplo aqui.Para un cliente de Python, utilice la biblioteca oficial del cliente de Python. La función
config.load_incluster_config()maneja automáticamente el descubrimiento del host de la API y la autenticación. Vea un ejemplo aqui.Existen varias bibliotecas disponibles, por favor consulte la página de Bibliotecas de Clientes.
En cada caso, las credenciales de la cuenta de servicio del Pod se utilizan para comunicarse de manera segura con el servidor de la API.
Accediendo directamente a la API REST
Al ejecutarse en un Pod, su contenedor puede crear una URL HTTPS para el servidor de la API de Kubernetes
obteniendo las variables de entorno KUBERNETES_SERVICE_HOSTy KUBERNETES_SERVICE_PORT_HTTPS.
La dirección del servidor de la API dentro del clúster también se publica
en un Servicio llamado kubernetes en el namespace default, de modo que los pods pueden hacer referencia a
kubernetes.default.svc como el nombre DNS para el servidor de la API local.
Nota:
Kubernetes no garantiza que el servidor de API tenga un certificado válido para el nombre de hostkubernetes.default.svc;
Sin embargo, se espera que el plano de control presente un certificado válido para
el nombre de host o la dirección IP que representa $KUBERNETES_SERVICE_HOSTLa forma recomendada para autenticarse con el servidor de la API es con una
credencial de cuenta de servicio.
Por defecto, un Pod esta asociado con una cuenta de servicio,
esta asociado con una cuenta de servicio, y una credencial (token) para esa cuenta
de servicio se coloca en el sistema de archivos de cada contenedor en ese Pod
en la ruta /var/run/secrets/kubernetes.io/serviceaccount/token.
Si está disponible, un paquete de certificados se coloca en el sistema de archivos de
cada contenedor en la ruta /var/run/secrets/kubernetes.io/serviceaccount/ca.crt, y
debe usarse para verificar el certificado de servicio del servidor API.
Finalmente, el Namespace default puede ser utilizado en las operaciones de API con ámbito de espacio de nombres que se colocan en un archivo
con la ruta /var/run/secrets/kubernetes.io/serviceaccount/namespace de cada contenedor
Usando kubectl proxy
Si deseas consultar la API sin una biblioteca de cliente oficial, puedes ejecutar kubectl proxy
como el comando
de un nuevo contenedor sidecar en el Pod. De esta manera, kubectl proxy se autenticará
en la API y la expondrá en la interfaz localhost del Pod, para que otros contenedores
en el Pod puedan usarla directamente.
Sin usar un proxy
Es posible evitar el uso del proxy de kubectl pasando el token de autenticación directamente al servidor de la API. El certificado interno asegura la conexión.
# Apuntar nombre de host del servidor API interno.
APISERVER=https://kubernetes.default.svc
# Ruta del token de ServiceAccount
SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount
# Lectura del Namespace del Pod
NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace)
# Lectura del bearer token del ServiceAccount
TOKEN=$(cat ${SERVICEACCOUNT}/token)
# Referencia a la autoridad de certificación interna (CA)
CACERT=${SERVICEACCOUNT}/ca.crt
# Explora la API con TOKEN
curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET ${APISERVER}/api
La salida será similar a esto:
{
"kind": "APIVersions",
"versions": ["v1"],
"serverAddressByClientCIDRs": [
{
"clientCIDR": "0.0.0.0/0",
"serverAddress": "10.0.1.149:443"
}
]
}