ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 10. 쿠버네티스 핵심 개념 (5)
    24년 11월 이전/데브옵스(DevOps)를 위한 쿠버네티스 마스터 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
Designed by Tistory.