Replicación
Introducción
Section titled “Introducción”Un cluster kubernetes se compone de varias máquinas virtuales o máquinas físicas independientes.
Entorno de trabajo
Section titled “Entorno de trabajo”Para aprender, o hacer pruebas, puedes simular un cluster multi-node con minikube.
Asegúrate de cambiar la configuración de cpus
y memory
en función del número de nodos simulados que utilices!
$ minikube start --nodes 4 -p multi...
Obtén la lista de los nodos:
$ kubectl get nodesNAME STATUS ROLES AGE VERSIONmulti Ready control-plane 5m27s v1.32.0multi-m02 Ready <none> 4m58s v1.32.0multi-m03 Ready <none> 4m29s v1.32.0multi-m04 Ready <none> 4m v1.32.0
También puedes comprobar el estado de tus nodos:
$ minikube status -p multimultitype: Control Planehost: Runningkubelet: Runningapiserver: Runningkubeconfig: Configured
multi-m02type: Workerhost: Runningkubelet: Running
...
ReplicaSet
Section titled “ReplicaSet”Un ReplicationSet
és un recurso que garantiza que un grupo de Pods siempre están ejecutándose.
Un Pod puede desaparecer por cualquier razón, por ejemplo que el nodo dónde se ejecuta el Pod desaparece del cluster o que el Pod ha sido desalojado del nodo.
Un ReplicaSet
monitoriza constantemente mediante un “label selector” una lista de Pods que se están ejecutando, y se asegura que el número de Pods en ejecución sea igual al número deseado mediante la creación o eliminación de Pods a partir de una plantilla de Pod.
flowchart TB start@{shape: circle, label: "Comenzar" } start --> find style start fill:#00f watch(["Esperar notificación de modificación de recursos"]) style watch fill:#048 watch == notificación recibida ==> find find([Encontrar Pods que hacen match en un 'label selector']) find ==> compare style find fill:#080 compare@{ shape: hex, label: "Comparar número de Pods encontrados con el número de pots deseados" } compare == faltan ==> few compare -- ok --> watch few([Crear Pods adicionales a partir de la plantilla]) many([Eliminar los Pods que sobran]) few --> watch compare == sobran ==> many many --> watch style few fill:#800 style many fill:#800
Por tanto, un ReplicaSet
necesita tres elementos fundamentales:
- Un label selector, que determina que Pods tiene que controlar
- Un replica count que especifica el número deseado de Pods que deberían estar en ejecución
- Un Pod template que se utiliza cuando se crean nuevas réplicas del Pod.
En cualquier momento puedes modificar el número de replicas, pero los cambios en el “label selector” y el “Pod template” no afectan a los Pods que se están ejecutando.
A continuación crea un fichero nginx.yaml
:
apiVersion: apps/v1kind: ReplicaSetmetadata: name: nginxspec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80
Crea el ReplicaSet
:
$ kubectl apply -f nginx.yamlreplicaset.apps/nginx created
Puedes ver que se han creado tres Pods con la etiqueta nginx
en tres nodos diferentes:
$ kubectl get pods -o wide -L appNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES APPnginx-78wzt 1/1 Running 0 11s 10.244.2.3 multi-m03 <none> <none> nginxnginx-mxf4c 1/1 Running 0 11s 10.244.1.4 multi-m02 <none> <none> nginxnginx-wdjsh 1/1 Running 0 11s 10.244.3.4 multi-m04 <none> <none> nginx
Kubernetes intenta desplegar los Pods en nodos diferentes para “no tener todos los huevos en la misma cesta”.
Borra uno de los Pods:
$ kubectl delete pod nginx-78wztpod "nginx-78wzt" deleted
Y verifica que el controlador de replicación crea un nuevo Pod:
$ kubectl get podsNAME READY STATUS RESTARTS AGEnginx-lvw9l 1/1 Running 0 19snginx-mxf4c 1/1 Running 0 54snginx-wdjsh 1/1 Running 0 54s
Como hemos dicho al principio, un ReplicationSet
és un recurso igual que un Pod
.
Por tanto, puedes obtener una lista de todos los ReplicaSet
que se han creado:
$ kubectl get rsNAME DESIRED CURRENT READY AGEnginx 3 3 3 96s
Así com una descripción de un controlador de replicación determinado:
$ kubectl describe rs nginxName: nginxNamespace: defaultSelector: app=nginxLabels: <none>Annotations: <none>Replicas: 3 current / 3 desiredPods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 FailedPod Template: Labels: app=nginx Containers: ... Volumes: <none> Node-Selectors: <none> Tolerations: <none>Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal SuccessfulCreate 2m9s replicaset-controller Created pod: nginx-wdjsh Normal SuccessfulCreate 2m9s replicaset-controller Created pod: nginx-mxf4c Normal SuccessfulCreate 2m9s replicaset-controller Created pod: nginx-78wzt Normal SuccessfulCreate 94s replicaset-controller Created pod: nginx-lvw9l
La lista de eventos muestra las acciones realizadas hasta el momento por el controlador: ha creado 4 Pods.
Respondiendo a un fallo de nodo
Section titled “Respondiendo a un fallo de nodo”Cuando pides a kubernetes que despliegue un {% link ”./pod” %}, el despliegue se hará en cualquier nodo que esté disponible.
El problema es que si este nodo “muere” …
$ minikube -p multi node stop multi-m02✋ Stopping node "multi-m02" ...🛑 Apagando "multi-m02" mediante SSH...🛑 Successfully stopped node multi-m02
El nodo ya no está Ready
:
$ kubectl get nodesNAME STATUS ROLES AGE VERSIONmulti Ready control-plane 3d v1.32.0multi-m02 NotReady <none> 3d v1.32.0multi-m03 Ready <none> 3d v1.32.0multi-m04 Ready <none> 3d v1.32.0
Importante. El resultado no es inmediato porque el cluster primero se tiene que asegurar que no es un problema temporal de conexión de pocos segundos.
Si miras las lista de Pods, puedes ver el Pod nginx-lvw9l
está Running
en el nodo multi-m02
…
$ kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESnginx-lvw9l 1/1 Running 0 3m42s 10.244.2.4 multi-m03 <none> <none>nginx-mxf4c 1/1 Running 0 4m17s 10.244.1.4 multi-m02 <none> <none>nginx-wdjsh 1/1 Running 0 4m17s 10.244.3.4 multi-m04 <none> <none>
Aunque puedes verificar que el Pod ya no está ejecutándose:
$ kubectl exec nginx-lvw9l -- basherror: Internal error occurred: error sending request: Post "https://192.168.49.3:10250/exec/default/nginx-gmkgq/nginx?command=bash&error=1&output=1": dial tcp 192.168.49.3:10250: connect: no route to host
El motivo es que Kubernetes espera un rato para asegurarse de que definitivamente la falta de conexión con el nodo no es por un fallo temporal en la red o porque Kubelet se está reiniciando.
Pero después de ese tiempo, Kubernetes notifica un cambio de recursos y el controlado de recursos nginx
crea un nuevo Pod:
$ kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESnginx-lvw9l 1/1 Running 0 9m36s 10.244.2.4 multi-m03 <none> <none>nginx-mxf4c 1/1 Terminating 0 10m 10.244.1.4 multi-m02 <none> <none>nginx-wdjsh 1/1 Running 0 10m 10.244.3.4 multi-m04 <none> <none>nginx-zbw6q 1/1 Running 0 50s 10.244.0.4 multi <none> <none>
Vuelve a arrancar el nodo multi-m02
:
$ minikube -p multi node start multi-m02👍 Starting "multi-m02" worker node in "multi" cluster🚜 Pulling base image v0.0.46 ...🔄 Restarting existing docker container for "multi-m02" ...🐳 Preparando Kubernetes v1.32.0 en Docker 27.4.1...🔎 Verifying Kubernetes components...🌟 Complementos habilitados:😄 Successfully started node multi-m02!
Etiquetas
Section titled “Etiquetas”Un controlador sólo gestiona los Pods que coinciden con su selector de etiquetas.
Para saber a que controlador está asociado un Pod en ese momento, puedes mirar el atributo metadata.ownerReferences
:
$ kubectl get pods nginx-lvw9l -o=jsonpath='{.metadata.ownerReferences[0]}'
{ "apiVersion":"apps/v1", "blockOwnerDeletion":true, "controller":true, "kind":"ReplicaSet", "name":"nginx", "uid":"bb526ba4-f15a-4517-a056-b6ef8c8cd531"}
A un ReplicaSet
no le importa si añades etiquetas adicionales a los Pods que gestiona:
$ kubectl label pod nginx-zbw6q env=prodpod/nginx-zbw6q labeled
Puedes ver que los Pods son los mismos que antes porque este cambio no afecta de ningun manera al ReplicaSet
:
$ kubectl get pods --show-labelsNAME READY STATUS RESTARTS AGE LABELSnginx-lvw9l 1/1 Running 0 14m app=nginxnginx-wdjsh 1/1 Running 0 15m app=nginxnginx-zbw6q 1/1 Running 0 5m55s app=nginx,env=prod
Pero si cambias el valor de la etiqueta app
como se muestra a continuación:
$ kubectl label pod nginx-lvw9l app=nginx-old --overwritepod/nginx-lvw9l labeled
El ReplicaSet
sólo encontrará dos Pods etiquetados como app=nginx
, y creará un nuevo Pod con esta etiqueta:
$ kubectl get pods -L appNAME READY STATUS RESTARTS AGE APPnginx-gvt68 1/1 Running 0 83s nginxnginx-lvw9l 1/1 Running 0 28m nginx-oldnginx-wdjsh 1/1 Running 0 29m nginxnginx-zbw6q 1/1 Running 0 19m nginx
El flag --overwrite
es necesario porque de esta forma no modificarás de manera accidental una etiqueta.
Puedes verificar que el Pod nginx-lvw9l
ya no está gestionado por el controlador:
$ kubectl get pods nginx-lvw9l -o=jsonpath='{.metadata.ownerReferences[0]}'
Esto es útil cuando un Pod no funciona correctamente y quieres probar que está pasando: lo sacas del alcance del controlador, que creará automáticamente un Pod para reemplazarlo, y puedes depurar o averiguar que está sucediendo para luego eliminarlo.
Escalando horizontalmente
Section titled “Escalando horizontalmente”Puedes modificar el número de Pods cambiando el valor del atributo spec.replicas
.
Puedes aumentar el número de Pods
$ kubectl scale rs nginx --replicas=5replicaset.apps/nginx scaled
$ kubectl get pods -L appNAME READY STATUS RESTARTS AGE APPnginx-gvt68 1/1 Running 0 21m nginxnginx-lvw9l 1/1 Running 0 48m nginx-oldnginx-m7b46 1/1 Running 0 39s nginxnginx-sm7zx 1/1 Running 0 39s nginxnginx-wdjsh 1/1 Running 0 49m nginxnginx-zbw6q 1/1 Running 0 40m nginx
O reducir el número de Pods:
$ kubectl scale rs nginx --replicas=2replicaset.apps/nginx scaled
$ kubectl get pods -L appNAME READY STATUS RESTARTS AGE APPnginx-lvw9l 1/1 Running 0 51m nginx-oldnginx-wdjsh 1/1 Running 0 52m nginxnginx-zbw6q 1/1 Running 0 43m nginx
Eliminar un ReplicaSet
Section titled “Eliminar un ReplicaSet”Cuando eliminar un ReplicaSet
mediante kubectl delete
, también se eliminan los Pods a menos que utilices el flag --cascade=orphan
:
$ kubectl delete rs nginx --cascade=falsereplicaset.apps "nginx" deleted
$ kubectl get pods -L appNAME READY STATUS RESTARTS AGE APPnginx-lvw9l 1/1 Running 0 55m nginx-oldnginx-wdjsh 1/1 Running 0 56m nginxnginx-zbw6q 1/1 Running 0 47m nginx
Si vuelves a crea de nuevo el ReplicaSet
, sólo se necesita crear un nuevo Pod para satisfacer las restricciones:
$ kubectl apply -f nginx.yamlreplicaset.apps/nginx created
$ kubectl get pods -L appNAME READY STATUS RESTARTS AGE APPnginx-lnfrd 0/1 ContainerCreating 0 2s nginxnginx-lvw9l 1/1 Running 0 57m nginx-oldnginx-wdjsh 1/1 Running 0 57m nginxnginx-zbw6q 1/1 Running 0 48m nginx
Borra todos los recursos:
{% sol %}
$ kubectl delete rs nginxreplicaset.apps "nginx" deleted
$ kubectl delete pod nginx-lvw9lpod "nginx-lvw9l" deleted
$ kubectl get podsNo resources found in default namespace.
{% endsol %}
DaemonSet
Section titled “DaemonSet”En un ReplicaSet
, Kubernetes despliega el número de Pods indicados en el recurso en los nodos del cluster que le parezcan mejor.
En cambio, en un DaemonSet
Kubernetes despiega un único Pod para cada nodo de cluster.
Esto es útil para Pods de sistema com puede ser un recopilador de “logs”, un monitor de recursos, el proceso kube-proxy, etc.
Por ejemplo, Fluentd es un recopilador de datos para unificar el registro de eventos del sistema.
Crea el fichero fluentd.yaml
apiVersion: apps/v1kind: DaemonSetmetadata: name: fluentdspec: selector: matchLabels: name: fluentd template: metadata: labels: name: fluentd spec: nodeSelector: fluentd-enabled: "true" containers: - name: fluentd-elasticsearch image: quay.io/fluentd_elasticsearch/fluentd:latest
Puedes ver que en la configuración del recurso utilizamos un selector de etiquetas para limitar los nodos en que se desplegará el Pod.
Por ejemplo, etiqueta el nodo multi-m02
con fluentd-enabled=true
:
$ kubectl label node multi-m02 fluentd-enabled=truenode/multi-m02 labeled
Crea el recurso fluentd
:
$ kubectl apply -f fluentd.yamldaemonset.apps/fluentd created
Puedes ver que sólo se ha desplegado un Pod fluend-?????
en el cluster:
$ kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESfluentd-wdh2j 1/1 Running 0 34s 10.244.1.4 multi-m02 <none> <none>
Edita el fichero fluentd.yaml
y elimina el selector:
... spec: containers: - name: fluentd-elasticsearch image: quay.io/fluentd_elasticsearch/fluentd:latest
Actutaliza el recurso:
$ kubectl apply -f fluentd.yamldaemonset.apps/fluentd configured
Ahora se crea un Pod fluend-?????
en cada nodo del cluster:
$ kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESfluentd-gj4hs 1/1 Running 0 15s 10.244.2.3 multi-m03 <none> <none>fluentd-gxrfv 1/1 Running 0 15s 10.244.3.3 multi-m04 <none> <none>fluentd-rp7vz 1/1 Running 0 15s 10.244.0.4 multi <none> <none>fluentd-xqlvp 1/1 Running 0 11s 10.244.1.5 multi-m02 <none> <none>
Vuelve a añadir el selector de nodo y verifica que se eliminan todos los Pods excepto el de multi-m02
:`
$ nano fluentd.yaml
$ kubectl apply -f fluentd.yamldaemonset.apps/fluentd configured
$ kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESfluentd-gxrfv 0/1 Completed 0 7m9s 10.244.3.3 multi-m04 <none> <none>fluentd-xqlvp 1/1 Terminating 0 7m5s 10.244.1.5 multi-m02 <none> <none>
Modifica la etiqueta del nodo multi-m02
a fluentd-enabled=false
y verifica que el Pod fluentd-xqlvp
se elimina:
$ kubectl label node multi-m02 fluentd-enabled=false --overwritenode/multi-m02 labeled
$ kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESfluentd-mszqj 0/1 Completed 0 44s 10.244.1.6 multi-m02 <none> <none>
El contingut d'aquest lloc web té llicència CC BY-NC-ND 4.0.
©2022-2025 xtec.dev