Gurumee 2021. 8. 14. 18:30
반응형

이 문서는 인프런 강의 "데브옵스를 위한 쿠버네티스 마스터"을 듣고 작성되었습니다. 최대한 요약해서 강의 내용을 최소로 하는데 목표를 두고 있어서, 더 친절하고 정확한 내용을 원하신다면 강의를 구매하시는 것을 추천드립니다. => 강의 링크

네트워크 볼륨 (NFS)

Kubernetes는 스토리지로 네트워크 파일 시스템(NFS, GlusterFS)을 이용할 수 있다. 이 절에서는 NFS를 볼륨으로 이용하는 것에 대해서 다룬다. 이 절은 "VM"에서 진행한다. 먼저 모든 노드에 NFS를 설치한다.

$ sudo -i 

# apt-get install nfs-common nfs-kernel-server portmap -y

 

그리고 노드 1개를 선택해서 다음 작업을 진행한다. 나는 "슬레이브2"에서 진행했다.

## nfs용 디렉토리 생성
# mkdir /home/nfs

## 권한 부여
# chmod 777 /home/nfs

## 모든 노드의 ip nfs 디렉토리 접근할 수 있도록 권한 부여
# tee /etc/exports <<EOF
/home/nfs 10.0.2.15(rw,sync,no_root_squash) 10.0.2.4(rw,sync,no_root_squash) 10.0.2.5(rw,sync,no_root_squash) 
EOF

## nfs 서버 재시작
# systemctl restart nfs-server

## 현재 마운트된 디렉토리 접근 가능 호스트 목록 확인
# showmount -e 127.0.0.1
Export list for 127.0.0.1:
/home/nfs 10.0.2.5,10.0.2.4,10.0.2.15

## /mnt 를 nfs 디렉토리에 마운트, 다음 형식을 따름
## mount -t nfs <자신의 노드>:<NFS 디렉토리> <마운트 디렉토리>
# mount -t nfs 10.0.2.5:/home/nfs /mnt

## 테스트 파일 생성
# echo test >> /home/nfs/test.txt

## /mnt에 공유되는지 확인
# cat /mnt/test.txt
test

 

그 후 다음과 같이 volume-nfs.yaml 파일을 만든다.

 

src/ch10/k8s/volume-nfs.yaml

apiVersion: v1
kind: Pod
metadata:
  name: mongodb
spec:
  containers:
    - image: mongo
      name: mongodb
      volumeMounts:
        - mountPath: /data/db
          name: mongodb
      ports:
        - containerPort: 27017
  volumes:
    - name: mongodb
      nfs:
        server: 10.0.2.5
        path: /home/nfs

 

이제 리소스를 생성한다.

$ kubectl create -f volume-nfs.yaml

 

생성이 끝나면 mongodb 포드에 접속해서 mongo 명령어를 실행한다.

$ kubectl exec -it mongodb mongo
...
> 

 

이제 다음과 같이 mongodb 명령어를 사용해보자. 데이터베이스를 생성하고, 객체를 하나 저장하고 쿼리하는 내용이다.

# 데이터베이스 생성 및 선택
> use mydb
switched to db mydb

# 데이터 추가
> db.foo.insert({name: "test", value: 1234})
WriteResult({ "nInserted" : 1 })

# 데이터 쿼리
> db.foo.find()
{ "_id" : ObjectId("611280e2a9c5bd71d0b71690"), "name" : "test", "value" : 1234 }

# 종료
> exit

 

이제 포드를 제거해보자.

$ kubectl delete -f volume-nfs.yaml

 

그 후 다시 생성한다.

$ kubectl create -f volume-nfs.yaml

 

정상적으로 영구 디스크를 볼륨으로 사용하고 있었다면, 포드를 삭제했더라도 데이터가 남아 있을 것이다. mongodb에 접속해서 데이터베이스 선택, 데이터 쿼리를 진행해보자.

$ kubectl exec -it mongodb mongo
...
# 데이터베이스 선택
> use mydb
switched to db mydb

# 데이터 쿼리
db.foo.find()
{ "_id" : ObjectId("611280e2a9c5bd71d0b71690"), "name" : "test", "value" : 1234 }

# 종료
> exit

 

잘 수행이 된다 굳!

클라우드 네트워크 볼륨 (gcePersistentDisk)

이 절은 "GCP"에서 진행한다. 이전 절에서 했던 작업을 GCP 같은 클라우드엣거는 미리 제공을 한다. 여기서는 NFS 역할을 하는 영구 디스크인 gcePersistentDisk를 볼륨으로 사용하는 것을 다룬다. 먼저 영구 디스크인 gcePersistentDisk를 생성한다.

$ gcloud compute disks create --size=10GB --zone=asia-northeast3-a mongodb

 

그 후 다음과 같이 volume-nfs-gce.yaml 파일을 만든다.

 

src/ch10/k8s/volume-nfs-gce.yaml

apiVersion: v1
kind: Pod
metadata:
  name: mongodb
spec:
  containers:
    - image: mongo
      name: mongodb
      volumeMounts:
        - mountPath: /data/db
          name: mongodb
      ports:
        - containerPort: 27017
  volumes:
    - name: mongodb
      gcePersistentDisk:
        pdName: mongodb
        fsType: ext4

 

이제 리소스를 생성한다.

$ kubectl create -f volume-nfs-gce.yaml

 

생성이 끝나면 mongodb 포드에 접속해서 mongo 명령어를 실행한다.

$ kubectl exec -it mongodb mongo
...
> 

 

이제 다음과 같이 mongodb 명령어를 사용해보자. 데이터베이스를 생성하고, 객체를 하나 저장하고 쿼리하는 내용이다.

# 데이터베이스 생성 및 선택
> use mydb
switched to db mydb

# 데이터 추가
> db.foo.insert({name: "test", value: 1234})
WriteResult({ "nInserted" : 1 })

# 데이터 쿼리
> db.foo.find()
{ "_id" : ObjectId("611280e2a9c5bd71d0b71690"), "name" : "test", "value" : 1234 }

# 종료
> exit

 

이제 포드를 제거해보자.

$ kubectl delete -f volume-nfs-gce.yaml

 

그 후 다시 생성한다.

$ kubectl create -f volume-nfs-gce.yaml

 

정상적으로 영구 디스크를 볼륨으로 사용하고 있었다면, 포드를 삭제했더라도 데이터가 남아 있을 것이다. mongodb에 접속해서 데이터베이스 선택, 데이터 쿼리를 진행해보자.

$ kubectl exec -it mongodb mongo
...
# 데이터베이스 선택
> use mydb
switched to db mydb

# 데이터 쿼리
db.foo.find()
{ "_id" : ObjectId("611280e2a9c5bd71d0b71690"), "name" : "test", "value" : 1234 }

# 종료
> exit

 

잘 수행이 된다 굳!

PV와 PVC (1) 정적 프로비저닝

이 절은 "GCP"에서 진행된다. 그리고 이전 절 "클라우드 네트워크 볼륨 (gcePersistentDisk)"을 진행하고 오길 바란다.

 

PersistentVolume(이하 pv)Kubernetes에서 유일하게 운영자가 관리하는 리소스이다. 실제적으로 스토리지 연결을 이 리소스로 한다고 생각하면 된다. PersistentVolumeClaim(이하 pvc)는 추상 계층으로써 개발자가 Kubernetes에서 스토리지 작업을 하지 않고도 작업된 스토리지 볼륨을 사용하는데 쓰이는 리소스이다. 대충 이런 느낌이랄까?

이제 다음과 같이 volume-pv.yaml 파일을 만든다.

 

src/ch10/k8s/volume-pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mongo-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
    - ReadOnlyMany
  persistentVolumeReclaimPolicy: Retain
  gcePersistentDisk:
    pdName: mongodb
    fsType: ext4
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mongo-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: ""
---
apiVersion: v1
kind: Pod
metadata:
  name: volume-pv
spec:
  containers:
    - image: mongo
      name: mongodb
      volumeMounts:
        - mountPath: /data/db
          name: mongodb
      ports:
        - containerPort: 27017
  volumes:
    - name: mongodb
      persistentVolumeClaim:
        claimName: mongo-pvc 

 

pod에서 볼륨은 이제 pvc로 지정하는 것을 볼 수 있다. 이 때 claimNamepvc의 이름이어야 한다. 또한 pvc에 작성된 spec을 토대로 알맞는 pv가 있다면 그것을 사용하게 된다. 그리고 pv는 이전 절과 같이 gcePersistentDisk를 사용한다. 이제 리소스를 생성한다.

$ kubectl create -f volume-pv.yaml

 

생성이 끝나면 다음 명령어들을 확인해보자.

$ kubectl get pv
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE
mongo-pv   10Gi       RWO,ROX        Retain           Bound    default/mongo-pvc                           25s

$ kubectl get pvc
NAME        STATUS   VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mongo-pvc   Bound    mongo-pv   10Gi       RWO,ROX                       28s

 

이때 pv에서 CLAIM에서 pvc가 보이는지 STATUS는 "Bound"인지 확인한다. 마찬가지로 pvc에서는 STATUS가 "Bound"인지 VOLUMEpv의 이름이 설정됐는지 확인하면 된다. 이제 mongodb 포드에 접속해서 mongo 명령어를 실행한다.

$ kubectl exec -it mongodb mongo
...
> 

 

이제 다음과 같이 mongodb 명령어를 사용해보자. 이전 절에서 진행했다면 데이터베이스를 선택하고 바로 저장한 객체를 다음과 같이 불러올 수 있을 것이다.

# 데이터베이스 선택
> use mydb
switched to db mydb

# 데이터 쿼리
db.foo.find()
{ "_id" : ObjectId("611280e2a9c5bd71d0b71690"), "name" : "test", "value" : 1234 }

# 종료
> exit

PV와 PVC (2) 동적 프로비저닝 StorageClass

이 절은 "GCP"에서 진행한다. pv는 몇 가지 고려 사항이 몇 가지 있다.

  1. 개발 팀에 스토리지를 관리할 수 있는 자원이 있는가
  2. 디스크의 양이 충분한가

결국 pv는 스토리지 영역을 컨트롤 할 수 있는 운영자가 절대적으로 필요하다. 만약 이런 부분이 미흡하다면 어떻게 해야 할까? StorageClass를 이용하면 이 문제를 손쉽게 해결할 수 있다. StorageClasspv를 만들지 않고도 동적으로 pvc가 요청한 크기만큼 스토리지를 볼륨으로 프로비저닝할 수가 있다. 다만 클라우드 프로바이더 GCP, AWS, Azure 등의 환경에서 사용하는 것이 권장된다.

 

다음과 같이 코드를 작성해보자. (이 때 pv, pvc는 모두 삭제해두어야 한다.)

src/ch10/k8s/volume-storage-class.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: mongo-stroage-class
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-ssd
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mongo-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: mongo-stroage-class
---
apiVersion: v1
kind: Pod
metadata:
  name: mongodb
spec:
  containers:
    - image: mongo
      name: mongodb
      volumeMounts:
        - mountPath: /data/db
          name: mongodb
      ports:
        - containerPort: 27017
  volumes:
    - name: mongodb
      persistentVolumeClaim:
        claimName: mongo-pvc

 

이전 절에서 진행했던 코드에서 다음이 변경되었다.

  1. pv는 storageClass로 대체한다.
  2. pvc의 storageClassName 필드에 storageClass의 이름을 할당한다.

이제 리소스를 생성한 후 다음 명령어들을 확인해보자.

# 리소스 생성
$ kubectl create -f volume-storage-class.yaml

# pv 확인
$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM               STORAGECLASS          REASON   AGE
mongo-pv                                   10Gi       RWO,ROX        Retain           Released   default/mongo-pvc                                  34m
pvc-9a48f495-1af2-4174-824b-20c28d177615   1Gi        RWO            Delete           Bound      default/mongo-pvc   mongo-stroage-class            4m18s

# pvc 확인
$ kubectl get pvc
NAME        STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
mongo-pvc   Bound    pvc-9a48f495-1af2-4174-824b-20c28d177615   1Gi        RWO            mongo-stroage-class   4m39s

 

pvc에서 요청했던대로 1Gi 만큼의 볼륨이 생긴 것을 확인할 수 있다. 디스크를 확인해보면 ssd 형 디스크가 하나 생성한 것을 확인할 수 있다.

StatefulSet

StatefulSet은 애플리케이션의 상태를 저장하고 관리하는데 사용되는 리소스이다. Deployment와 상당히 유사한데, 차이점이라면 Deployment는 포드가 무작위로 생성되고 배치되는 반면, StatefulSet은 포드의 순서와 배치를 결정할 수 있다.

 

StatefulSet은 다음과 같은 경우에 사용할 수 있다.

  1. 안정적이고 고유한 네티워크 식별자가 필요한 경우
  2. 안정적이고 지속적인 스토리지를 사용해야 하는 경우
  3. 질서 정연한 포드의 배치와 확장을 원하는 경우
  4. 포드의 자동 롤링 업데이트를 사용하기 원하는 경우

각 포드의 상태를 유지할 수 있는 장점이 생기는 반면 다음과 같은 단점도 생긴다.

  1. StatefulSet 관련된 볼륨이 자동으로 삭제되지 않는다.
  2. Pod의 Storage는 PV 혹은 StorageClass로 프로비저닝을 해주어야 한다.
  3. 롤링 업데이트 수행 시 수동으로 복구해야 하는 경우가 생긴다.
  4. Pod 네트워크 ID를 유지하기 위해서 Headless Service가 필요하게 된다.

즉 상태를 유지할 수 있는 장점과 동시에 수동으로 관리의 필요성이 생긴다는 단점이 생긴다. 한 번 StatefulSet을 만들어보자. 이 절은 "GCP"에서 진행한다. (로컬도 상관은 없다.) 다음과 같이 파일을 작성한다.

 

src/ch10/k8s/statefulset.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
    - port: 80
      name: web
  clusterIP: None # Headless
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx
  serviceName: "nginx"
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      terminationGracePeriodSeconds: 10
      containers:
        - name: nginx
          image: k8s.gcr.io/nginx-slim:0.8
          ports:
            - containerPort: 80
              name: web
          volumeMounts:
            - name: www
              mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
    - metadata:
        name: www
      spec:
        accessModes: [ "ReadWriteOnce" ]
        storageClassName: "stateful-set-storage-class"
        resources:
          requests:
            storage: 1Gi
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: stateful-set-storage-class
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-ssd

 

작성 요령은 Deployment와 거의 동일하다. 가장 먼저 차이점은 Service 작성 요령에 있다.

apiVersion: v1
kind: Service
# ...
spec:
  # ...
  clusterIP: None # Headless

 

spec.clusterIP의 값이 "None"이다. 이렇게 작성된 리소스를 Headless Service라고 한다. StatefulSet이 관리하는 PodService로 연결해주려면 반드시 이렇게 만들어주어야 한다.

# ...
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  # ...
    spec:
      terminationGracePeriodSeconds: 10
      containers:
        - name: nginx
          image: k8s.gcr.io/nginx-slim:0.8
          ports:
            - containerPort: 80
              name: web
# ...

 

StatefulSet 관련해서 Deployment와 가장 큰 차이점은 Pod에 대해 작성할 때 다음 데이터가 반드시 필요하다.

  • spec.terminationGracePeriodSeconds
  • spec.containers[].ports.ports[].name

terminationGracePeriodSeconds는 리소스를 종료할 때 대기해주는 시간을 의미한다. 순서대로 배치시키기 때문에 이 값은 필수적으로 들어간다. 또한, ports 관련 작성 시 이름이 필수적으로 들어가게 된다.

# ...
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
  # ...
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "stateful-set-storage-class"
      resources:
        requests:
          storage: 1Gi

 

또한 volumeClaimTemplates에서 pvc와 연결해주어야 한다. 작성 요령은 Podvolumes와 유사하다. 이제 터미널에 다음을 입력하여 리소스를 생성한다.

$ kubectl create -f statefulset.yaml
service/nginx created
statefulset.apps/web created
storageclass.storage.k8s.io/stateful-set-stroage-class created

 

리소스가 다 생성된다면 다음 명령어로 만들어진 리소스들을 확인해보자.

$ kubectl get pod -w
# 순서대로 web-n (0, 1, 2...) 로 만들어지는 것을 확인할 수 있다. 
NAME    READY   STATUS              RESTARTS   AGE
web-0   0/1     ContainerCreating   0          26s
web-0   1/1     Running             0          32s
web-1   0/1     Pending             0          0s
web-1   0/1     Pending             0          0s
web-1   0/1     Pending             0          7s
web-1   0/1     ContainerCreating   0          7s
web-1   1/1     Running             0          22s
web-2   0/1     Pending             0          0s
web-2   0/1     Pending             0          0s
web-2   0/1     Pending             0          7s
web-2   0/1     ContainerCreating   0          7s
web-2   1/1     Running             0          17s

$ kubectl get pvc
# 역시 www-web-n (0, 1, 2..) 형식으로 출력된다.
NAME        STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS                 AGE
www-web-0   Bound    pvc-fc161b94-5c7d-4367-b15d-c148eab6cdea   1Gi        RWO            stateful-set-storage-class   2m16s
www-web-1   Bound    pvc-a49ba9cf-2b6d-48e7-b8c8-d78ec259d554   1Gi        RWO            stateful-set-storage-class   104s
www-web-2   Bound    pvc-7e940025-e320-4da5-a3ef-500b4e5134a3   1Gi        RWO            stateful-set-storage-class   82s

$ kubectl get statefulset
NAME   READY   AGE
web    3/3     2m55s

 

이제 StatefulSet을 스케일 아웃해보자. 3개에서 5개로 Pod를 늘린다.

$ kubectl scale statefulset web --replicas=5 
statefulset.apps/web scaled

$ kubectl get pod -w
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          12m
web-1   1/1     Running   0          11m
web-2   1/1     Running   0          11m
# 여기서부터 확인 가능하다. 역시 오름차순 형태로 pod가 생성된다.
web-3   0/1     Pending   0          5s
web-3   0/1     Pending   0          7s
web-3   0/1     ContainerCreating   0          7s
web-3   1/1     Running             0          17s
web-4   0/1     Pending             0          0s
web-4   0/1     Pending             0          0s
web-4   0/1     Pending             0          7s
web-4   0/1     ContainerCreating   0          7s
web-4   1/1     Running             0          17s

$ kubectl get pvc
NAME        STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS                 AGE
www-web-0   Bound    pvc-fc161b94-5c7d-4367-b15d-c148eab6cdea   1Gi        RWO            stateful-set-storage-class   13m
www-web-1   Bound    pvc-a49ba9cf-2b6d-48e7-b8c8-d78ec259d554   1Gi        RWO            stateful-set-storage-class   13m
www-web-2   Bound    pvc-7e940025-e320-4da5-a3ef-500b4e5134a3   1Gi        RWO            stateful-set-storage-class   12m
www-web-3   Bound    pvc-7565e8f0-7c9a-4f9f-b38f-e6f582e33187   1Gi        RWO            stateful-set-storage-class   86s
www-web-4   Bound    pvc-0ddd0bae-7aa9-4543-9dd0-0e176970ba09   1Gi        RWO            stateful-set-storage-class   69s

 

이제는 스케일 인해보자. 5개에서 1개로 줄인다.

$ kubectl scale statefulset web --replicas=1

$ kubectl get pod -w
NAME    READY   STATUS        RESTARTS   AGE
NAME    READY   STATUS        RESTARTS   AGE
web-0   1/1     Running       0          14m
web-1   1/1     Running       0          13m
web-2   1/1     Running       0          13m
# web-4는 순식간에 삭제되었다.. 역순으로 삭제된다.
web-3   0/1     Terminating   0          118s
web-3   0/1     Terminating   0          2m3s
web-3   0/1     Terminating   0          2m3s
web-2   1/1     Terminating   0          13m
web-2   0/1     Terminating   0          13m
web-2   0/1     Terminating   0          13m
web-2   0/1     Terminating   0          13m
web-1   1/1     Terminating   0          14m
web-1   0/1     Terminating   0          14m
web-1   0/1     Terminating   0          14m
web-1   0/1     Terminating   0          14m

$ kubectl get pvc
www-web-0   Bound    pvc-fc161b94-5c7d-4367-b15d-c148eab6cdea   1Gi        RWO            stateful-set-storage-class   15m
www-web-1   Bound    pvc-a49ba9cf-2b6d-48e7-b8c8-d78ec259d554   1Gi        RWO            stateful-set-storage-class   14m
www-web-2   Bound    pvc-7e940025-e320-4da5-a3ef-500b4e5134a3   1Gi        RWO            stateful-set-storage-class   14m
www-web-3   Bound    pvc-7565e8f0-7c9a-4f9f-b38f-e6f582e33187   1Gi        RWO            stateful-set-storage-class   3m5s
www-web-4   Bound    pvc-0ddd0bae-7aa9-4543-9dd0-0e176970ba09   1Gi        RWO            stateful-set-storage-class   2m48s

 

리소스가 오름차순으로 순차적으로 늘어나는것과 반대로 내림차순으로 삭제되는 것을 확인할 수 있다. 한 가지 이상한 점이 눈에 띈다. pvc는 삭제되지 않았다는 것이다. 스토리지 볼륨의 경우 삭제하고 싶다면 수동으로 삭제를 진행해야 한다. 이번엔 롤링 업데이트를 해보자. StatefulSet의 업데이트 전략은 2가지가 있다.

  • OnDelete : 모든 Pod를 수동으로 삭제 후 새로운 Pod가 업데이트 된다.
  • RollingUpdate : Pod가 내림차순으로 삭제 후
$ kubectl edit statefulset web

 

다음 처럼 수정한다. (replicas = 1 -> 3, image = 0.8 -> 0.9)

 

그 후 리소스 변화를 관찰해보자.

$ kubectl get pod -w
NAME    READY   STATUS              RESTARTS   AGE
web-0   1/1     Running             0          20m
web-1   0/1     ContainerCreating   0          3s
web-1   1/1     Running             0          24s
web-2   0/1     Pending             0          0s
web-2   0/1     Pending             0          0s
web-2   0/1     ContainerCreating   0          0s
web-2   1/1     Running             0          17s
web-0   1/1     Terminating         0          21m
web-0   0/1     Terminating         0          21m
web-0   0/1     Terminating         0          21m
web-0   0/1     Terminating         0          21m
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          10s

 

먼저 web-0가 실행되는 상황에서 Pod가 2개 더 필요하다. 그럼 web-1, web-2는 최신 버전인 "0.9"로 컨테이너가 실행된다. 그 후 web-0가 삭제 후 다시 만들어진다. 다시 버전을 0.8로 복귀시켜보자.

$ kubectl edit statefulset web
statefulset.apps/web edited

$ kubectl get pod -w
NAME    READY   STATUS        RESTARTS   AGE
web-0   1/1     Running       0          2m28s
web-1   1/1     Running       0          3m11s
web-2   0/1     Terminating   0          2m47s
web-2   0/1     Terminating   0          2m50s
web-2   0/1     Terminating   0          2m50s
web-2   0/1     Pending       0          0s
web-2   0/1     Pending       0          0s
web-2   0/1     ContainerCreating   0          0s
web-2   1/1     Running             0          10s
web-1   1/1     Terminating         0          3m24s
web-1   0/1     Terminating         0          3m25s
web-1   0/1     Terminating         0          3m34s
web-1   0/1     Terminating         0          3m34s
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          10s
web-0   1/1     Terminating         0          3m1s
web-0   0/1     Terminating         0          3m2s
web-0   0/1     Terminating         0          3m11s
web-0   0/1     Terminating         0          3m11s
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          10s

 

역순으로 업데이트되는 것을 확인할 수 있다. 즉 레플리카 수에서 부족한 번호부터 채우되 기본적으로는 역순으로 업데이트하는 것을 확인할 수 있다.

728x90
반응형