El uso de DaemonSet y StatefulSet
Hoy te explicaremos como usar otro Pod
controlador, explicamos principalmente Deployment
el uso de este tipo de recursos de objetos, a continuación explicaremos los controladores que se usan en ocasiones específicas: DaemonSet
y StatefulSet
.
Uso de DaemonSets
Por el nombre del controlador, podemos ver su uso: Daemon se usa para implementar el proceso daemon y se usa para ejecutar una copia del proceso daemon como un proceso en segundo plano DaemonSet
en cada Kubernetes
nodo. un proceso daemon en cada nodo Pod
Copia, cuando un nodo se une Kubernetes
al clúster, Pod
se programará para ejecutarse en el nodo. Cuando el nodo solo se puede eliminar del clúster, este nodo en el nodo Pod
también se eliminará. Por supuesto, si eliminamos DaemonSet
, todos y este objeto Los relacionados Pods
serán eliminados.
¿Bajo qué circunstancias necesitamos utilizar este escenario empresarial? De hecho, este escenario es relativamente común, como por ejemplo:
- Un demonio de almacenamiento de clúster, por ejemplo,
glusterd
paraceph
implementar en cada nodo para proporcionar almacenamiento persistente; - Los demonios de monitoreo de nodos, como
Prometheus
los clústeres de monitoreo, pueden ejecutar un proceso en cada nodonode-exporter
para recopilar información sobre los nodos de monitoreo; - Un demonio de recopilación de registros, como
fluentd
ologstash
, se ejecuta en cada nodo para recopilar registros para contenedores
Una cosa que debe explicarse especialmente aquí es el problema de programación de DaemonSet
la ejecución Pod
. En circunstancias normales, la estrategia del programador determina en Pod
qué nodo ejecutar Kubernetes
. Sin embargo, el nodo DaemonSet
creado por el controlador Pod
en realidad se ha determinado de antemano. ( Pod
especificado en tiempo de creación .spec.nodeName
), entonces:
DaemonSet
No le importan los campos de un nodounshedulable
, que le explicaremos en el capítulo de programación más adelante.DaemonSet
Se puede crearPod
incluso si el programador no se ha iniciado, lo cual es muy importante.
A continuación, usamos directamente un ejemplo para demostrarlo, implementando uno en cada nodo Nginx Pod
: (nginx-ds.yaml)
kind: DaemonSet
apiVersion: apps/v1
metadata:
name: nginx-ds
labels:
k8s-app: nginx
spec:
selector:
matchLabels:
k8s-app: nginx
template:
metadata:
labels:
k8s-app: nginx
spec:
containers:
- image: nginx:1.7.9
name: nginx
ports:
- name: http
containerPort: 80
Luego créalo directamente:
$ kubectl create -f nginx-ds.yaml
Entonces podemos observar Pod
si se distribuye a cada nodo:
$ kubectl get nodes
$ kubectl get pods -o wide
Uso de StatefulSets
Antes de aprender StatefulSet
este tipo de controlador, debemos entender un concepto: ¿qué es un servicio con estado? ¿Qué es un servicio sin estado?
-
Servicio sin estado (Stateless Service): la instancia en ejecución de este servicio no almacenará localmente los datos que deben persistir, y los resultados de varias instancias que responden a la misma solicitud son completamente consistentes, como la instancia que explicamos anteriormente, ¿verdad
WordPress
? Se pueden iniciar varias instancias al mismo tiempo, pero los resultados que obtenemos de cualquier instancia son los mismos, ¿verdad? Debido a que los únicos datos que necesita conservar están almacenados enMySQL
la base de datos, podemos decir queWordPress
esta aplicación es un servicio sin estado, peroMySQL
la base de datos no lo es, porque necesita conservar los datos localmente. -
Servicio con estado (Stateful Service): es lo opuesto al concepto anterior. La instancia en ejecución de este servicio necesita almacenar datos persistentes localmente. Por ejemplo, la base de datos anterior, si está ejecutando en el nodo A ahora, sus datos se almacenarán
MySQL
en En el nodo A, si migra el servicio al nodo B en este momento, no habrá datos anteriores, porque necesita restaurar los datos en el directorio de datos correspondiente y no hay datos en este momento.
Ahora todos tienen una cierta comprensión de stateful y stateless. Por ejemplo, nuestra aplicación WEB común session
mantiene el estado de inicio de sesión del usuario. Si persistimos session
en el nodo, entonces la aplicación es un servicio con estado. Sí, porque ahora estoy conectado y usted tiene persistió mis datos en el nodo A. La próxima vez que inicie sesión, la solicitud puede enrutarse al nodo B, pero no hay datos actuales session
en el nodo B, por lo que se session
Entonces, en general, para la expansión horizontal, cambiaremos este tipo de aplicación WEB a un servicio sin estado, ¿cómo cambiarlo? ¿Es suficiente almacenar session
los datos en un lugar público, como adentro, para algunas solicitudes de clientes, no los usamos para mantener el estado del usuario, y también es posible usarlos en su lugar?redis
API
session
token
Los servicios sin estado se pueden controlar bien mediante el uso de nuestros servicios anteriores o con estado. Para los servicios con estado, hay muchos más detalles a considerar. Una de las tareas más difíciles para las aplicaciones en contenedores es diseñar la implementación de componentes distribuidos con estado Deployment
. RC
Dado que los componentes sin estado pueden no tener secuencias de inicio predefinidas, requisitos de agrupamiento, conexiones TCP punto a punto, identificadores de red únicos, requisitos de inicio y finalización correctos, etc., se pueden almacenar fácilmente en contenedores. Los sistemas como las bases de datos, los sistemas de análisis de big data, los almacenes distribuidos de clave/valor y los intermediarios de mensajes pueden tener arquitecturas distribuidas complejas y pueden utilizar las funciones anteriores. Con este fin, Kubernetes
se introducen recursos StatefulSet
para apoyar esta compleja necesidad.
StatefulSet
Similar a ReplicaSet
, pero puede manejar Pod
la secuencia de inicio, Pod
estableciendo un identificador único para preservar el estado de cada uno, mientras tiene las siguientes funciones:
- Identificador de red único y estable
- Almacenamiento estable y persistente
- Implementación y escalado ordenados y elegantes
- Eliminación y terminación ordenadas y ordenadas
- Actualizaciones continuas automáticas y ordenadas
Crear un StatefulSet
A continuación, le mostraremos StatefulSet
cómo usar el objeto. Antes de comenzar, prepararemos dos volúmenes de almacenamiento (PV) de 1G. En los siguientes cursos, también explicaremos en detalle cómo usar PV y PVC. No entremos en eso. aquí: (pv001.yaml)
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv001
labels:
release: stable
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
hostPath:
path: /tmp/data
El otro solo necesita cambiar el nombre a pv002 y luego crear:
$ kubectl create -f pv001.yaml && kubectl create -f pv002.yaml
persistentvolume "pv001" created
persistentvolume "pv002" created
$ kubectl get pv
kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 1Gi RWO Recycle Available 12s
pv002 1Gi RWO Recycle Available 11s
Puede ver que dos objetos PV se han creado correctamente y el estado es: Disponible.
Luego lo usamos StatefulSet
para crear un Nginx Pod. Para este tipo de recurso, generalmente exponemos Headless Service
el servicio creando un tipo de servicio, que se configurará clusterIP
como None
un servicio sin cabeza: (statefulset-demo.yaml)
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
role: stateful
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 2
selector:
matchLabels:
app: nginx
role: stateful
template:
metadata:
labels:
app: nginx
role: stateful
spec:
containers:
- name: nginx
image: cnych/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
volumeMounts
Tenga en cuenta que un nuevo atributo está asociado con el archivo YAML anterior : volumeClaimTemplates , que declara automáticamente un objeto pvc y pv para la administración:
Entonces aquí abrimos dos ventanas de terminal. En la primera terminal, use kubectl get para ver la creación de los pods de StatefulSet.
$ kubectl get pods -w -l role=stateful
En otra terminal, use kubectl create para crear el servicio Headless y StatefulSet definido en statefulset-demo.yaml.
$ kubectl create -f statefulset-demo.yaml
service "nginx" created
statefulset.apps "web" created
Consulta el índice de pedidos del pod
Para un StatefulSet con N réplicas, los pods se crean en el orden de {0…N-1} cuando se implementan. En la primera terminal podemos ver la siguiente información:
$ kubectl get pods -w -l role=stateful
NAME READY STATUS RESTARTS AGE
web-0 0/1 Pending 0 0s
web-0 0/1 Pending 0 0s
web-0 0/1 ContainerCreating 0 0s
web-0 1/1 Running 0 19s
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 1/1 Running 0 18s
Tenga en cuenta que el Pod web-1 no se iniciará hasta que el Pod web-0 esté en los estados En ejecución y Listo.
Como se mencionó en el concepto StatefulSets, los Pods en un StatefulSet tienen una identidad estable y única. Esta bandera se basa en el índice secuencial único asignado a cada Pod por el controlador StatefulSet. Los nombres de los pods tienen la forma <statefulset name>-<ordinal index>
. El StatefulSet web tiene dos réplicas, por lo que crea dos Pods: web-0 y web-1.
El comando anterior crea dos Pods, cada uno ejecutando un servidor web NGINX. Obtenga el servicio nginx y el StatefulSet web para verificar que se crearon correctamente.
$ kubectl get service nginx
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx None <none> 80/TCP 12s
$ kubectl get statefulset web
NAME DESIRED CURRENT AGE
web 2 1 20s
Utilice una identidad de red estable
Cada Pod tiene un nombre de host estable basado en su índice secuencial. Ejecute el nombre de host en cada Pod con kubectl exec.
$ for i in 0 1; do kubectl exec web-$i -- sh -c 'hostname'; done
web-0
web-1
Luego usamos kubectl run para ejecutar un contenedor que proporciona el comando nslookup. Al hacer un nslookup en los nombres de host de los Pods, puede verificar sus direcciones DNS dentro del clúster.
$ kubectl run -i --tty --image busybox dns-test --restart=Never --rm /bin/sh
nslookup web-0.nginx
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-0.nginx
Address 1: 10.244.1.6
nslookup web-1.nginx
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-1.nginx
Address 1: 10.244.2.6
El CNAME del servicio descentralizado apunta al registro SRV (registrar cada pod en estado En ejecución y Listo). El registro SRV apunta a una entrada de registro que contiene la dirección IP del Pod.
Luego, veamos cómo eliminar el Pod en StatefulSet:
Ver pods de StatefulSet en una terminal:
$ kubectl get pod -w -l role=stateful
Use kubectl delete en otro terminal para eliminar todos los Pods en StatefulSet.
$ kubectl delete pod -l role=stateful
pod "web-0" deleted
pod "web-1" deleted
Espere a que StatefulSet los reinicie y ambos Pods se ejecuten y estén listos.
$ kubectl get pod -w -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 0/1 ContainerCreating 0 0s
web-0 1/1 Running 0 2s
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 1/1 Running 0 34s
Luego, use kubectl exec y kubectl run nuevamente para ver el nombre de host del Pod y las entradas de DNS dentro del clúster.
$ for i in 0 1; do kubectl exec web-$i -- sh -c 'hostname'; done
web-0
web-1
$ kubectl run -i --tty --image busybox dns-test --restart=Never --rm /bin/sh
nslookup web-0.nginx
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-0.nginx
Address 1: 10.244.1.7
nslookup web-1.nginx
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-1.nginx
Address 1: 10.244.2.8
Podemos ver que el número ordinal, el nombre de host, la entrada SRV y el nombre de registro del pod no han cambiado, pero la dirección IP asociada con el pod puede haber cambiado. Por eso es importante no usar la dirección IP del Pod en el StatefulSet para conectarse desde otras aplicaciones. En general, podemos conectarnos directamente a través de registros SRV: web-0.nginx, web-1.nginx, porque son estables, y cuando el estado de su Pod cambia a En ejecución y Listo, su aplicación puede descubrir la dirección de ellos.
Del mismo modo, podemos comprobar el estado de enlace final de PV y PVC:
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 1Gi RWO Recycle Bound default/www-web-0 1h
pv002 1Gi RWO Recycle Bound default/www-web-1 1h
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
www-web-0 Bound pv001 1Gi RWO 22m
www-web-1 Bound pv002 1Gi RWO 22m
El uso de los volúmenes de almacenamiento se explicará más adelante, por lo que no lo explicaremos aquí por el momento para evitar confusiones.
Por supuesto, StatefulSet también tiene otras funciones. En los proyectos reales, rara vez volvemos a implementar nuestros servicios con estado directamente a través de StatefulSet, a menos que usted mismo pueda mantenerlos completamente. Para algunos servicios específicos, podemos usar un Operador más avanzado para implementar, como como etcd-operator, prometheus-operator, etc. Estas aplicaciones pueden administrar bien los servicios con estado, en lugar de simplemente usar un StatefulSet para implementar un Pod, porque para las aplicaciones con estado, lo más importante es la recuperación de datos, la conmutación por error, etc.