Versión imprimible multipagina. Haga click aquí para imprimir.
Gestionar y ejecutar aplicaciones
- 1: Corre una aplicación stateless usando un Deployment
- 2: Escalar un StatefulSet
- 3: Borrar un StatefulSet
- 4: Especificando un presupuesto de disrupción para tu aplicación
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
deployment
de 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:
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
deployment
basado en el fichero YAML:kubectl apply -f https://k8s.io/examples/application/deployment.yaml
-
Obtén información acerca del
deployment
:kubectl describe deployment nginx-deployment
El 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=nginx
El 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 16h
-
Muestra 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.yaml
-
Comprueba como el
deployment
crea 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.yaml
-
Verifica que el
deployment
tiene cuatro pods:kubectl get pods -l app=nginx
El 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.
Siguientes pasos
- 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.
Siguientes pasos
- 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.
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.
Siguientes pasos
Aprende más sobre Forzar eliminación de Pods en StatefulSet.
4 - Especificando un presupuesto de disrupción para tu aplicación
Ésta pagina enseña como limitar el numero de disrupciones concurrentes que afectan a tu aplicación definiendo presupuestos de disrupció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 cluster.
Antes de empezar
- Tener permisos de administrador sobre la aplicación que esta corriendo en Kubernetes y requiere alta disponibilidad
- Deberías saber como desplegar Múltiples réplicas de aplicaciones stateless y/o Múltiples réplicas de aplicaciones stateful.
- Deberías haber leido acerca de Disrupciones de un Pod.
- Deberías confirmar con el propietario del cluster o proveedor de servicio que respetan Presupuestos de Disrupción para Pods.
Protegiendo una aplicación con un PodDisruptionBudget
- Identifica la aplicación que quieres proteger con un PodDisruptionBudget (PDB).
- Revisa como afectan las disrupciones a tú aplicación.
- Crea un PDB usando un archivo YAML.
- Crea el objecto PDB desde el archivo YAML.
Identifica la applicació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 estan gestionados por uno de los controladores listados arriba, o agrupaciones arbitrarias de pods, con algunas restricciones descritas en Controladores Arbitrarios y Selectors.
Revisa como afectan las disrupciones a tú aplicación
Decide cuántas instancias de tu aplicación pueden estar fuera de servicio al mismo tiempo debido a disrupciones voluntarias de corto plazo.
- Frontend stateless:
- Objetivo: evitar reducir capacidad para servir por mas de 10%.
- Solución: usar un PDB que especifica minAvailable 90%.
- Objetivo: evitar reducir capacidad para servir por mas 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 cluster 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 estas preparado para la disrupción. Crea el PDB de nuevo al terminar la disrupció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 numero 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 mas disrupciones a la vez.).
- Objetivo: no reducir el numero 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.
Especificando un PodDisruptionBudget
Un PodDisruptionBudget
tiene tres atributos:
- Un label selector
.spec.selector
para especificar el grupo de pods donde aplicar el presupuesto. Este campo es requerido. .spec.minAvailable
que 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.minAvailable
puede ser un número absoluto o un porcentaje..spec.maxUnavailable
(disponible en Kubernetes 1.7 y superior) que es una descripción del numero de pods del grupo que pueden estar indisponibles despues del desalojo. Puede ser un número absoluto o un porcentaje.
PodDisruptionBudget
utilizando la herramienta de línea de comandos kubectl
, el campo minAvailable
es 1 por defecto si no se especifica minAvailable
ni maxUnavailable
.
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 disponibles entre las seleccionadas por el selector
del PodDisruptionBudget.
Ejemplo 2: Con un minAvailable
del 30%, se permiten los desalojos mientras que al menos 30% de la cantidad de réplicas se mantengan disponibles.
Ejemplo 3: Con un maxUnavailable
de 5, se permiten desalojos siempre que haya como máximo 5
réplicas indisponibles entre el número total de réplicas deseadas.
Ejemplo 4: Con un maxUnavailable
de 30%, se permiten los desalojos siempre y cuando no más del 30%
de las réplicas esten indisponibles.
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.
Un maxUnavailable
de 0% (o 0) o un minAvailable
de 100% (o igual al
número de réplicas) puede prevenir que los nodos sean purgados completamente.
Esto está permitido según la semántica de PodDisruptionBudget
.
Puedes encontrar ejemplos de presupuestos de disrupción de pods definidas a continuación. Los ejemplos aplican al grupo de pods que tienen la etiqueta app: zookeeper
.
Ejemplo de PDB usando minAvailable:
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: zk-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: zookeeper
Ejemplo de PDB usando maxUnavailable (Kubernetes 1.7 o superior):
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: zk-pdb
spec:
maxUnavailable: 1
selector:
matchLabels:
app: zookeeper
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 el objeto PDB con el comando kubectl apply -f mypdb.yaml
.
No puedes actualizar objetos PDB. Deben ser eliminados y recreados.
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 su namespace,
entonces verás algo como esto:
kubectl get poddisruptionbudgets
NAME MIN-AVAILABLE ALLOWED-DISRUPTIONS AGE
zk-pdb 2 0 7s
Si hay pods que coinciden (por ejemplo, 3), entonces debes ver algo similar a esto:
kubectl get poddisruptionbudgets
NAME MIN-AVAILABLE ALLOWED-DISRUPTIONS AGE
zk-pdb 2 1 7s
El valor distinto a cero de ALLOWED-DISRUPTIONS
significa que el controlador de disrupció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/v1beta1
kind: PodDisruptionBudget
metadata:
creationTimestamp: 2017-08-28T02:38:26Z
generation: 1
name: zk-pdb
...
status:
currentHealthy: 3
desiredHealthy: 3
disruptedPods: null
disruptionsAllowed: 1
expectedPods: 3
observedGeneration: 1
Por último, los PodDisruptionBudgets también se pueden consultar con kubectl utilizando el nombre corto pdb:
kubectl get pdb
NAME MIN-AVAILABLE ALLOWED-DISRUPTIONS AGE
zk-pdb 2 0 7s
Controladores y selectors 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.