StatefulSet de contrôleurs couramment utilisés par Kubernetes

StatefulSet de contrôleurs couramment utilisés par Kubernetes

1. Introduction

Les relations inégales entre les instances et les applications où les instances ont des dépendances sur des données externes sont appelées "applications avec état".
La relation dite inégale entre les instances signifie que pour les applications distribuées, il existe souvent des dépendances relativement importantes entre chaque instance et chaque application. Par exemple, une application doit être démarrée avant les autres applications, sinon les autres applications ne seront pas démarrées.
L'application la plus importante qui dépend des données externes est l'application de base de données. Pour les applications de base de données, nous devons stocker ses données de manière permanente. S'il s'agit d'une application sans état, le redémarrage des données dans la base de données et l'application perdra le contact, ce qui est manifestement une violation Notre intention initiale n'était pas de la mettre en production.

Par conséquent, afin de résoudre le support efficace des applications avec état dans Kubernetes, Kubernetes utilise StatefulSet pour orchestrer et gérer les applications avec état.
StatefulSet est similaire à ReplicaSet. La différence est qu'il peut contrôler la séquence de démarrage des pods et qu'il définit un identifiant unique pour chaque pod. Il a les fonctions suivantes:

  • Identifiant réseau unique et stable

  • Stockage stable et persistant

  • Déploiement et mise à l'échelle ordonnés et élégants

  • Mise à jour progressive et ordonnée

La conception de StatefulSet est facile à comprendre et résume le monde réel dans les deux situations suivantes:
(1) État topologique. Cela signifie qu'il existe une relation asymétrique entre les applications. Les applications doivent être démarrées dans un certain ordre. Même si l'application est redémarrée, elle doit être redémarrée dans l'ordre spécifié et son identification réseau doit être la même que celle d'origine après le redémarrage, afin que l'accès d'origine puisse être garanti L'utilisateur peut accéder au nouveau Pod via la même méthode;
(2), état de stockage. Cela signifie que l'application est liée aux données stockées, peu importe quand, quelle que soit la situation, pour l'application, tant que les données dans le stockage ne changent pas, les données lues doivent être les mêmes;

La fonction principale de StatefulSet est donc d'enregistrer l'état du pod d'une certaine manière, puis de restaurer son état d'une certaine manière lorsque le pod est recréé.

二 、 Service sans tête

Avant d'introduire StatefulSet, comprenons d'abord ce qu'est le service sans tête.
Nous savons que dans Kubernetes, le service est un moyen de fournir un accès externe à un groupe de pods. Habituellement, nous utilisons le service pour accéder au pod des deux manières suivantes:
(1) via l'adresse IP du cluster, cette adresse IP du cluster est équivalente à VIP. Lorsque nous visitons cette adresse IP, la demande sera transmise au pod backend;
(2) via DNS méthode, de cette manière, vous devez d'abord vous assurer qu'il existe un service DNS dans le cluster Kubernetes. À ce stade, tant que nous accédons à "mon-service.my-namespace.svc, cluster.local", nous pouvons accéder au pod backend mandaté par le service nommé my-service;

Pour la deuxième méthode, il existe les deux méthodes de traitement suivantes:
(1) Service normal, c'est-à-dire résoudre le nom de domaine, obtenir l'adresse IP du cluster, puis accéder selon la première méthode;
(2), Service sans tête, c'est-à-dire , résolvez le nom de domaine pour obtenir Est l'adresse IP d'un pod dans le backend, afin qu'il soit accessible directement;

Pour la deuxième méthode de traitement, nous pouvons voir qu'il n'y a pas besoin d'IP de cluster, mais l'adresse IP du pod backend est directement résolue via le nom de domaine pour l'accès.
Ce qui suit est une simple définition de fichier YAML de Headless Service:

apiVersion: v1

kind: Service

metadata:

  name: nginx

  labels:

    app: nginx

spec:

  ports:

  - port: 80

    name: web

  clusterIP: None

  selector:

    app: nginx

Le fichier YAML ci-dessus montre qu'il n'y a pas beaucoup de différence avec notre définition de service ordinaire. La seule différence est que le clusterIP est défini sur None, c'est-à-dire qu'aucun cluster n'est nécessaire. Nous créons ce service via kubectl apply -f , puis vérifiez que l'adresse IP du cluster du service est Aucune.
StatefulSet de contrôleurs couramment utilisés par Kubernetes

Le service créé de cette manière est un service sans tête, il n'a pas de VIP, il exposera donc le pod qu'il a mandaté sous la forme d'enregistrements DNS.

Troisièmement, utilisez StatefulSet

Créez le PV avant de créer le StatefulSet, comme suit:

apiVersion: v1

kind: PersistentVolume

metadata:

  name: pv01

  labels:

    release: stable

spec:

  capacity:

    storage: 1Gi

  accessModes:

  - ReadWriteOnce

  persistentVolumeReclaimPolicy: Recycle

  hostPath:

    path: /tmp/data

---

apiVersion: v1

kind: PersistentVolume

metadata:

  name: pv02

  labels:

    release: stable

spec:

  capacity:

    storage: 1Gi

  accessModes:

  - ReadWriteOnce

  persistentVolumeReclaimPolicy: Recycle

  hostPath:

    path: /tmp/data

Puis exécutez kubectl apply -f pour démarrer PV, comme suit:

[root@master statefulset]# kubectl apply -f pv.yaml

persistentvolume/pv01 created

persistentvolume/pv02 created

[root@master statefulset]# kubectl get pv

NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE

pv01   1Gi        RWO            Recycle          Available                                   10s

pv02   1Gi        RWO            Recycle          Available                                   9s

Vous pouvez voir que les états des deux PV sont tous deux disponibles, puis écrire le fichier YAML du StatefulSet:

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

  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

Notez que le fichier YAML ci-dessus associé à volumeMounts est un nouvel attribut: volumeClaimTemplates, cet attribut déclarera automatiquement un objet pvc et pv pour la gestion, et serviceName: "nginx" signifie que le headless de nginx est utilisé lorsque la boucle de contrôle est exécutée. Service pour enregistrer l'identité résoluble du pod.

Ensuite, nous ouvrons ici deux fenêtres de terminal. Dans le premier terminal, utilisez kubectl get pour visualiser la création des pods du StatefulSet.

$ kubectl get pods -w -l role=stateful

Dans un autre terminal, utilisez kubectl create pour créer le service Headless et StatefulSet définis dans statefulset-demo.yaml.

$ kubectl create -f statefulset-demo.yaml

service "nginx" created

statefulset.apps "web" created

Ensuite, nous observons la séquence de démarrage du Pod:

[root@master ~]# kubectl get pods -w -l role=stateful

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     3m12s

web-1   0/1   Pending             0     0s

web-1   0/1   Pending             0     0s

web-1   0/1   Pending             0     1s

web-1   0/1   ContainerCreating   0     1s

web-1   1/1   Running             0     5s

Grâce au processus de création ci-dessus, nous pouvons voir que StatefulSet numérote les pods qu'il gère. Sa règle de dénomination est [statefulset-name] - [index] et son index commence à 0, ce qui est le même que chaque instance de pod de StatefulSet. Une correspondance, ne jamais répéter. Plus important encore, le processus de création du pod est séquentiel. Comme ci-dessus, web-1 entre dans l'état en attente après que web-0 entre dans l'état en cours d'exécution.

Nous utilisons la commande pour visualiser les résultats de sa création:

[root@master statefulset]# kubectl get statefulset web

NAME   READY   AGE

web    2/2     17m

[root@master statefulset]# kubectl get pods -l role=stateful

NAME    READY   STATUS    RESTARTS   AGE

web-0   1/1     Running   0          17m

web-1   1/1     Running   0          14m

[root@master statefulset]# kubectl get svc nginx

NAME    TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE

nginx   ClusterIP   None         <none>        80/TCP    17m

Lorsque les deux pods entrent en état d'exécution, vous pouvez afficher leurs identités réseau respectives. Nous pouvons les afficher via kubectl exec, comme suit:

[root@master statefulset]# kubectl exec web-0 -- sh -c 'hostname'

web-0

[root@master statefulset]# kubectl exec web-1 -- sh -c 'hostname'

web-1

Vous pouvez voir que le nom d'hôte et le nom de pod des deux pods sont identiques et qu'ils reçoivent tous des numéros correspondants. Ensuite, nous utilisons DNS pour accéder au service Headless.
Nous commençons par démarrer un pod avec la commande suivante:

kubectl run -i --tty --image busybox dns-test --restart=Never --rm /bin/sh

Ensuite, utilisez nslookup pour analyser le service sans tête correspondant à un pod dans ce pod:

kubectl run -i --tty --image centos dns-test --restart=Never --rm /bin/sh

sh-4.2# yum install bind-utils -y

sh-4.2# nslookup web-0.nginx

Server:        10.68.0.2

Address:    10.68.0.2#53

Name:    web-0.nginx.default.svc.cluster.local

Address: 172.20.2.63

sh-4.2# nslookup web-1.nginx

Server:        10.68.0.2

Address:    10.68.0.2#53

Name:    web-1.nginx.default.svc.cluster.local

Address: 172.20.2.64

A partir de l'analyse des résultats de nslookup, lors de l'accès à web-0.nginx, l'IP du Pod web-0 est analysée, et l'autre est la même.
À ce stade, si nous supprimons les deux pods, observez le processus de redémarrage du pod:

[root@master statefulset]# kubectl delete pod -l role=stateful

pod "web-0" deleted

pod "web-1" deleted

Vérifiez ensuite la séquence de redémarrage comme suit:

[root@master ~]# kubectl get pods -w -l role=stateful

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          2s

Nous pouvons voir qu'après avoir supprimé le Pod, sa séquence de redémarrage est toujours redémarrée selon le numéro d'origine, et son identification réseau reste la même qu'auparavant.
Grâce à cette règle de correspondance stricte, StatefulSet garantit la stabilité de l'identité réseau du Pod. Grâce à cette méthode, l'état topologique du Pod peut être fixé en fonction du nom + du numéro du Pod. En outre, Kubernetes fournit également une entrée d'accès fixe et unique pour chaque pod, c'est-à-dire l'enregistrement DNS du pod.

Nous pouvons également vérifier la liaison du PV et du PVC:

[root@master statefulset]# kubectl get pv

NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE

pv01   1Gi        RWO            Recycle          Bound    default/www-web-0                           129m

pv02   1Gi        RWO            Recycle          Bound    default/www-web-1                           129m

[root@master statefulset]# kubectl get pvc

NAME        STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE

www-web-0   Bound    pv01     1Gi        RWO                           124m

www-web-1   Bound    pv02     1Gi        RWO                           116m

Par conséquent, nous trions StatefulSet comme suit:
(1), StatefulSet gère directement Pod. En effet, les instances de pod dans le StatefulSet ne sont pas exactement les mêmes que les instances de pod dans le ReplicaSet. Elles sont légèrement différentes. Par exemple, le nom et le nom d'hôte de chaque pod sont différents, et la façon dont StatefulSet distingue ces instances est pour ajouter le numéro de pod;
(2), Kubernetes génère un enregistrement avec le même numéro dans le serveur DNS pour ce pod numéroté via le service sans tête. Tant que le StatefulSet peut garantir que le numéro de ce pod reste inchangé, l'enregistrement DNS similaire à web-0.nginx.default.svc.cluster.local dans le service ne changera pas et l'adresse IP du pod résolue par cet enregistrement Il est automatiquement mis à jour avec la recréation du Pod;
(3) StatefulSet peut également allouer et créer un PVC avec le même numéro que le Pod pour chaque Pod. De cette manière, Kubernetes peut lier le PV correspondant à ce PVC via le mécanisme Persitent Volume, afin de garantir que chaque Pod a un Volume indépendant. Dans ce cas, même si le pod est supprimé, son PVC et son PV correspondants seront toujours conservés, donc lorsque le pod est recréé, Kubernetes trouvera le PVC avec le même numéro pour lui, et montera le volume correspondant au PVC. les données précédentes du volume précédent;

Quatre, résumé

L'une des principales fonctions du contrôleur StatefulSet est de les numéroter lors de la création de pods à l'aide du modèle de pod, et d'effectuer les tâches dans l'ordre des numéros. Lorsque la boucle de contrôle du StatefulSet constate que l'état réel du pod est incompatible avec l'état attendu, il fera également fonctionner le pod dans l'ordre.

Bien sûr, StatefulSet a également d'autres fonctionnalités. Dans les projets réels, nous retournons rarement en arrière et déployons nos services avec état directement via StatefulSet, à moins que vous ne puissiez les conserver vous-même. Pour certains services spécifiques, nous pouvons utiliser davantage d'opérateurs avancés, tels que comme etcd-operator, prometheus-operator, etc. Ces applications peuvent très bien gérer les services avec état, au lieu d'utiliser simplement un StatefulSet pour déployer un Pod, car pour les applications avec état, le plus important est la récupération de données, le basculement, etc.

Finir

Je suppose que tu aimes

Origine blog.51cto.com/15080014/2654577
conseillé
Classement