This the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

클러스터 데몬 관리

롤링 업데이트 수행과 같은 데몬셋 관리를 위한 일반적인 작업을 수행한다.

1 - 데몬셋(DaemonSet)에서 롤링 업데이트 수행

이 페이지는 데몬셋에서 롤링 업데이트를 수행하는 방법을 보여준다.

시작하기 전에

  • 데몬셋 롤링 업데이트 기능은 쿠버네티스 버전 1.6 이상에서만 지원된다.

데몬셋 업데이트 전략

데몬셋에는 두 가지 업데이트 전략 유형이 있다.

  • OnDelete: OnDelete 업데이트 전략을 사용하여, 데몬셋 템플릿을 업데이트한 후, 이전 데몬셋 파드를 수동으로 삭제할 때 새 데몬셋 파드가 생성된다. 이것은 쿠버네티스 버전 1.5 이하에서의 데몬셋의 동작과 동일하다.
  • RollingUpdate: 기본 업데이트 전략이다. RollingUpdate 업데이트 전략을 사용하여, 데몬셋 템플릿을 업데이트한 후, 오래된 데몬셋 파드가 종료되고, 새로운 데몬셋 파드는 제어 방식으로 자동 생성된다. 전체 업데이트 프로세스 동안 데몬셋의 최대 하나의 파드가 각 노드에서 실행된다.

롤링 업데이트 수행

데몬셋의 롤링 업데이트 기능을 사용하려면, .spec.updateStrategy.typeRollingUpdate 를 설정해야 한다.

.spec.updateStrategy.rollingUpdate.maxUnavailable(기본값은 1)과 .spec.minReadySeconds(기본값은 0)으로 설정할 수도 있다.

RollingUpdate 업데이트 전략으로 데몬셋 생성

이 YAML 파일은 'RollingUpdate'를 업데이트 전략으로 사용하여 데몬셋을 명시한다.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      tolerations:
      # 이 톨러레이션(toleration)은 마스터 노드에서 실행 가능한 데몬셋이
      # 마스터에서 파드를 실행할 수 없는 경우 이를 제거하는 것이다
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers

데몬셋 매니페스트의 업데이트 전략을 확인한 후, 데몬셋을 생성한다.

kubectl create -f https://k8s.io/examples/controllers/fluentd-daemonset.yaml

또는, kubectl apply 로 데몬셋을 업데이트하려는 경우, 동일한 데몬셋을 생성하는 데 kubectl apply 를 사용한다.

kubectl apply -f https://k8s.io/examples/controllers/fluentd-daemonset.yaml

데몬셋 RollingUpdate 업데이트 전략 확인

데몬셋의 업데이트 전략을 확인하고, RollingUpdate 로 설정되어 있는지 확인한다.

kubectl get ds/fluentd-elasticsearch -o go-template='{{.spec.updateStrategy.type}}{{"\n"}}' -n kube-system

시스템에서 데몬셋을 생성하지 않은 경우, 대신 다음의 명령으로 데몬셋 매니페스트를 확인한다.

kubectl apply -f https://k8s.io/examples/controllers/fluentd-daemonset.yaml --dry-run=client -o go-template='{{.spec.updateStrategy.type}}{{"\n"}}'

두 명령의 출력 결과는 다음과 같아야 한다.

RollingUpdate

출력 결과가 RollingUpdate 가 아닌 경우, 이전 단계로 돌아가서 데몬셋 오브젝트나 매니페스트를 적절히 수정한다.

데몬셋 템플릿 업데이트

RollingUpdate 데몬셋 .spec.template 에 대한 업데이트는 롤링 업데이트를 트리거한다. 새 YAML 파일을 적용하여 데몬셋을 업데이트한다. 이것은 여러 가지 다른 kubectl 명령으로 수행할 수 있다.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      tolerations:
      # 이 톨러레이션(toleration)은 마스터 노드에서 실행 가능한 데몬셋이
      # 마스터에서 파드를 실행할 수 없는 경우 이를 제거하는 것이다
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers

선언적 커맨드

구성 파일을 사용하여 데몬셋을 업데이트하는 경우, kubectl apply 를 사용한다.

kubectl apply -f https://k8s.io/examples/controllers/fluentd-daemonset-update.yaml

명령형 커맨드

명령형 커맨드를 사용하여 데몬셋을 업데이트하는 경우, kubectl edit 를 사용한다.

kubectl edit ds/fluentd-elasticsearch -n kube-system
컨테이너 이미지만 업데이트

데몬셋 템플릿(예: .spec.template.spec.containers[*].image)에 의해 정의된 컨테이너 이미지만 업데이트하려면, kubectl set image 를 사용한다.

kubectl set image ds/fluentd-elasticsearch fluentd-elasticsearch=quay.io/fluentd_elasticsearch/fluentd:v2.6.0 -n kube-system

롤링 업데이트 상태 관찰

마지막으로, 최신 데몬셋 롤링 업데이트의 롤아웃 상태를 관찰한다.

kubectl rollout status ds/fluentd-elasticsearch -n kube-system

롤아웃이 완료되면, 출력 결과는 다음과 비슷하다.

daemonset "fluentd-elasticsearch" successfully rolled out

문제 해결

데몬셋 롤링 업데이트가 더 이상 진행되지 않는다(stuck)

가끔씩, 데몬셋 롤링 업데이트가 더 이상 진행되지 않을 수 있다. 이와 같은 상황이 발생할 수 있는 원인은 다음과 같다.

일부 노드에 리소스가 부족하다

적어도 하나의 노드에서 새 데몬셋 파드를 스케줄링할 수 없어서 롤아웃이 중단되었다. 노드에 리소스가 부족할 때 발생할 수 있다.

이 경우, kubectl get nodes 의 출력 결과와 다음의 출력 결과를 비교하여 데몬셋 파드가 스케줄링되지 않은 노드를 찾는다.

kubectl get pods -l name=fluentd-elasticsearch -o wide -n kube-system

해당 노드를 찾으면, 데몬셋이 아닌 파드를 노드에서 삭제하여 새 데몬셋 파드를 위한 공간을 생성한다.

참고: 삭제된 파드가 컨트롤러에 의해 제어되지 않거나 파드가 복제되지 않은 경우 서비스 중단이 발생한다. 이 때 PodDisruptionBudget정책도 적용되지 않는다.

롤아웃 실패

최근 데몬셋 템플릿 업데이트가 중단된 경우(예를 들어, 컨테이너가 계속 크래시되거나, 컨테이너 이미지가 존재하지 않는 경우(종종 오타로 인해)), 데몬셋 롤아웃이 진행되지 않는다.

이 문제를 해결하려면, 데몬셋 템플릿을 다시 업데이트한다. 이전의 비정상 롤아웃으로 인해 새로운 롤아웃이 차단되지는 않는다.

클럭 차이(skew)

데몬셋에 .spec.minReadySeconds 가 명시된 경우, 마스터와 노드 사이의 클럭 차이로 인해 데몬셋이 올바른 롤아웃 진행 상황을 감지할 수 없다.

정리

네임스페이스에서 데몬셋을 삭제한다.

kubectl delete ds fluentd-elasticsearch -n kube-system

다음 내용

2 - 데몬셋(DaemonSet)에서 롤백 수행

이 페이지는 데몬셋에서 롤백을 수행하는 방법을 보여준다.

시작하기 전에

쿠버네티스 클러스터가 필요하고, kubectl 커맨드-라인 툴이 클러스터와 통신할 수 있도록 설정되어 있어야 한다. 만약, 아직 클러스터를 가지고 있지 않다면, minikube를 사용해서 생성하거나 다음의 쿠버네티스 플레이그라운드 중 하나를 사용할 수 있다.

쿠버네티스 서버의 버전은 다음과 같거나 더 높아야 함. 버전: 1.7. 버전 확인을 위해서, 다음 커맨드를 실행 kubectl version.

데몬셋에서 롤링 업데이트를 수행하는 방법을 이미 알고 있어야 한다.

데몬셋에서 롤백 수행

1단계: 롤백할 데몬셋 리비전 찾기

마지막 리비전으로 롤백하려는 경우 이 단계를 건너뛸 수 있다.

데몬셋의 모든 리비전을 나열한다.

kubectl rollout history daemonset <daemonset-name>

이 명령은 데몬셋 리비전 목록을 반환한다.

daemonsets "<daemonset-name>"
REVISION        CHANGE-CAUSE
1               ...
2               ...
...
  • 변경 원인은 데몬셋 어노테이션 kubernetes.io/change-cause 에서 생성 시의 리비전으로 복사된다. 변경 원인 어노테이션에서 실행된 명령을 기록하도록 kubectl--record=true 를 지정할 수 있다.

특정 리비전의 세부 사항을 보려면 다음을 수행한다.

kubectl rollout history daemonset <daemonset-name> --revision=1

이 명령은 해당 리비전의 세부 사항을 반환한다.

daemonsets "<daemonset-name>" with revision #1
Pod Template:
Labels:       foo=bar
Containers:
app:
 Image:        ...
 Port:         ...
 Environment:  ...
 Mounts:       ...
Volumes:      ...

2단계: 특정 리비전으로 롤백

# --to-revision에 1단계에서 얻는 리비전 번호를 지정한다
kubectl rollout undo daemonset <daemonset-name> --to-revision=<revision>

성공하면, 명령은 다음을 반환한다.

daemonset "<daemonset-name>" rolled back
참고: --to-revision 플래그를 지정하지 않은 경우, kubectl은 가장 최신의 리비전을 선택한다.

3단계: 데몬셋 롤백 진행 상황 확인

kubectl rollout undo daemonset 은 서버에 데몬셋 롤백을 시작하도록 지시한다. 실제 롤백은 클러스터 컨트롤 플레인 내에서 비동기적으로 수행된다.

롤백 진행 상황을 보려면 다음의 명령을 수행한다.

kubectl rollout status ds/<daemonset-name>

롤백이 완료되면, 출력 결과는 다음과 비슷하다.

daemonset "<daemonset-name>" successfully rolled out

데몬셋 리비전의 이해

이전 kubectl rollout history 단계에서, 데몬셋 리비전 목록을 얻었다. 각 리비전은 ControllerRevision이라는 리소스에 저장된다.

각 리비전에 저장된 내용을 보려면, 데몬셋 리비전 원시 리소스를 찾는다.

kubectl get controllerrevision -l <daemonset-selector-key>=<daemonset-selector-value>

이 명령은 ControllerRevision의 목록을 반환한다.

NAME                               CONTROLLER                     REVISION   AGE
<daemonset-name>-<revision-hash>   DaemonSet/<daemonset-name>     1          1h
<daemonset-name>-<revision-hash>   DaemonSet/<daemonset-name>     2          1h

각 ControllerRevision은 데몬셋 리비전의 어노테이션과 템플릿을 저장한다.

kubectl rollout undo 는 특정 ControllerRevision을 가져와 데몬셋 템플릿을 ControllerRevision에 저장된 템플릿으로 바꾼다. kubectl rollout undokubectl edit 또는 kubectl apply 와 같은 다른 명령을 통해 데몬셋 템플릿을 이전 리비전으로 업데이트하는 것과 같다.

참고: 데몬셋 리비전은 롤 포워드만 한다. 즉, 롤백이 완료된 후, 롤백될 ControllerRevision의 리비전 번호(.revision 필드)가 증가한다. 예를 들어, 시스템에 리비전 1과 2가 있고, 리비전 2에서 리비전 1으로 롤백하면, ControllerRevision은 .revision: 1 에서 .revision: 3 이 된다.

문제 해결