Explicación del controlador de pods de Kubernetes DaemonSet y StatefulSet

El uso de DaemonSet y StatefulSet

Hoy te explicaremos como usar otro Podcontrolador, explicamos principalmente Deploymentel uso de este tipo de recursos de objetos, a continuación explicaremos los controladores que se usan en ocasiones específicas: DaemonSety 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 DaemonSeten cada Kubernetesnodo. un proceso daemon en cada nodo PodCopia, cuando un nodo se une Kubernetesal clúster, Podse programará para ejecutarse en el nodo. Cuando el nodo solo se puede eliminar del clúster, este nodo en el nodo Podtambién se eliminará. Por supuesto, si eliminamos DaemonSet, todos y este objeto Los relacionados Podsserá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, glusterdpara cephimplementar en cada nodo para proporcionar almacenamiento persistente;
  • Los demonios de monitoreo de nodos, como Prometheuslos clústeres de monitoreo, pueden ejecutar un proceso en cada nodo node-exporterpara recopilar información sobre los nodos de monitoreo;
  • Un demonio de recopilación de registros, como fluentdo logstash, se ejecuta en cada nodo para recopilar registros para contenedores

Una cosa que debe explicarse especialmente aquí es el problema de programación de DaemonSetla ejecución Pod. En circunstancias normales, la estrategia del programador determina en Podqué nodo ejecutar Kubernetes. Sin embargo, el nodo DaemonSetcreado por el controlador Poden realidad se ha determinado de antemano. ( Podespecificado en tiempo de creación .spec.nodeName), entonces:

  • DaemonSetNo le importan los campos de un nodo unshedulable, que le explicaremos en el capítulo de programación más adelante.
  • DaemonSetSe puede crear Podincluso 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 Podsi se distribuye a cada nodo:

$ kubectl get nodes
$ kubectl get pods -o wide

Uso de StatefulSets

Antes de aprender StatefulSeteste 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 en MySQLla base de datos, podemos decir que WordPressesta aplicación es un servicio sin estado, pero MySQLla 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 MySQLen 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 sessionmantiene el estado de inicio de sesión del usuario. Si persistimos sessionen 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 sessionen el nodo B, por lo que se sessionEntonces, 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 sessionlos 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?redisAPIsessiontoken

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. RCDado 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, Kubernetesse introducen recursos StatefulSetpara apoyar esta compleja necesidad.

StatefulSetSimilar a ReplicaSet, pero puede manejar Podla secuencia de inicio, Podestableciendo 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 StatefulSetcó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 StatefulSetpara crear un Nginx Pod. Para este tipo de recurso, generalmente exponemos Headless Serviceel servicio creando un tipo de servicio, que se configurará clusterIPcomo Noneun 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

volumeMountsTenga 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.


Supongo que te gusta

Origin blog.csdn.net/u010674953/article/details/129535745
Recomendado
Clasificación