ReplicaSetの動作を確認する


はじめに

Podの性能や可用性を高めるために、Kubernetesは基本的に「スケールアウト」させます。スケールアウトはノード(ここではPod/コンテナ)のCPU/メモリを増やすのではなく、ノード(Pod/コンテナ)を増やします。
ちなみに、CPUやメモリを増やすのは「スケールアップ」。
このスケールアウトの仕組みとしてReplicaSetがあるので、今回はこの動作を確認してみます。

ReplicaSetの作成

以下のyamlファイルを作成しました。

sampleReplicaSet.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: sample-pod3
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-redis
  template:
    metadata:
      labels:
        app: nginx-redis
    spec:
      containers:
        - name: nginx
          image: nginx:latest
        - name: redis
          image: redis:latest

デプロイします。

$ kubectl apply -f sampleReplicaSet.yaml
replicaset.apps/sample-pod3 created

ここでは、一発でデプロイできてることになってますが、実際にはyamlファイルのミスで何度かエラーが出てます。
・スペルミス
・インデントがずれてる
yamlの書式にも慣れていかないと。

確認

$ kubectl get rs
NAME          DESIRED   CURRENT   READY   AGE
sample-pod3   3         3         3       16m
$ kubectl get replicasets.apps -o wide
NAME          DESIRED   CURRENT   READY   AGE   CONTAINERS    IMAGES                      SELECTOR
sample-pod3   3         3         3       16m   nginx,redis   nginx:latest,redis:latest   app=nginx-redis
$ kubectl get pod -o wide
NAME                READY   STATUS    RESTARTS   AGE   IP               NODE           NOMINATED NODE   READINESS GATES
sample-pod3-7nxxr   2/2     Running   0          18m   192.168.69.216   k8s-worker02   <none>           <none>
sample-pod3-86kqh   2/2     Running   0          18m   192.168.79.74    k8s-worker01   <none>           <none>
sample-pod3-thbbx   2/2     Running   0          18m   192.168.69.202   k8s-worker02   <none>           <none>

sample-pod3のレプリカが3つ作成されていることが確認できます。
Pod名は「[metadata.name]-[ランダムな英数字]」になっています。
ちなみに、レプリカセットを確認するサブコマンドの「rs」と「replicasets.apps」は同じ意味です。

Podがデプロイされているworkerノードも分散されていますね。
図で書くとこんな感じです。

セルフヒーリング機能の確認

Kubernetesの特徴としてセルフヒーリング機能があります。これは、何かしら障害が発生した場合にもあらかじめ設定してある「あるべき姿」に戻す機能です。
この場合の「あるべき姿」はsample-pod3のレプリカが3つであることです。

workerノードの停止

ここではworker01を停止します。shutdownするだけなので、割愛。
状態を確認します。worker01がNotReadyになっています。

$ kubectl get node
NAME           STATUS     ROLES    AGE   VERSION
k8s-master     Ready      master   11d   v1.17.3
k8s-worker01   NotReady   <none>   11d   v1.17.3
k8s-worker02   Ready      <none>   11d   v1.17.3

ReplicaSetの確認

停止して少し待ってから状態を確認します。

$ kubectl get pod -o wide
NAME                READY   STATUS        RESTARTS   AGE   IP               NODE           NOMINATED NODE   READINESS GATES
sample-pod3-7nxxr   2/2     Running       0          66m   192.168.69.216   k8s-worker02   <none>           <none>
sample-pod3-86kqh   2/2     Terminating   0          66m   192.168.79.74    k8s-worker01   <none>           <none>
sample-pod3-ngw8x   2/2     Running       0          20m   192.168.69.217   k8s-worker02   <none>           <none>
sample-pod3-thbbx   2/2     Running       0          66m   192.168.69.202   k8s-worker02   <none>           <none>
$ kubectl get rs
NAME          DESIRED   CURRENT   READY   AGE
sample-pod3   3         3         3       70m

worker01にあった「sample-pod3-86kqh」が「Terminating」状態になって、新たに「sample-pod3-ngw8x」がworker02にデプロイされています。
新しく作成されているところがポイントで、Active-Standbyのようなデータを引き継いだフェイルオーバーではなく、新しいPodがデプロイされています。つまり、いままでworker01で処理されていたデータは引き継がれていません。
Kubernetesで実現するマイクロサービスは、このようにデータを保持しない「ステートレス」なアプリを基本とします。
そのために、保持しなければいけないデータやログなんかは別のボリュームに保存したりするので、この辺りはまた調べたいと思います。

なお、Podのデプロイ履歴は以下で確認できます。

$ kubectl describe rs sample-pod3
Name:         sample-pod3
・・・
Events:
  Type    Reason            Age    From                   Message
  ----    ------            ----   ----                   -------
  Normal  SuccessfulCreate  49m    replicaset-controller  Created pod: sample-pod3-thbbx
  Normal  SuccessfulCreate  49m    replicaset-controller  Created pod: sample-pod3-86kqh
  Normal  SuccessfulCreate  49m    replicaset-controller  Created pod: sample-pod3-7nxxr
  Normal  SuccessfulCreate  3m30s  replicaset-controller  Created pod: sample-pod3-ngw8x

このTerminatingになっているPodは、deleteで消せばいいらしいです。
Kubernetes.io

$ kubectl delete pod sample-pod3-86kqh
pod "sample-pod3-86kqh" deleted

なんとなく、使えなくなったPodのdeleteまでやってくれればいい気がしますが、何か理由でもあるのかな?
これで一通りReplicaSetの動作の確認ができました。ReplicaSetはKubernetesを使っていくうえで重要な要素だと思いますので、もう少し調べてみたいと思います。