Infra/Kubernetes

[쿠버네티스 입문] 6-1. 컨트롤러 (Replication Controller, ReplicaSet, Deployment )

에드박 2023. 1. 16. 16:58

쿠버네티스의 컨트롤러(Controller)

  • 파드들을 관리하는 역할
  • 다양한 목적에 맞게 사용할 컨트롤러들이 존재

레플리케이션 컨트롤러 (Replication Controller)

  • 지정한 숫자만큼 파드가 항상 클러스터 안에서 실행되도록 관리
  • 컨트롤러 없이 파드를 직접 실행하면 파드에 문제가 생겨 종료됐거나 삭제됐을 때 재시작하기 어렵다.
  • 등호 기반(equality-based)의 셀렉터 지원
    • 셀렉터가 레이블을 선택할 때 `=` , `!=` 연산자 지원
  • 최근에는 레플리케이션 컨트롤러 대신 레플리카세트를 사용하는 추세

레플리카 세트 (Replica Set)

  • 레플리케이션 컨트롤러의 발전형
  • 집합기반(set-based)의 셀렉터 지원
    • 셀렉터가 레이블을 선택할 때 in, notin, exists 연산자 지원
  • 레플리케이션 컨트롤러를 사용하면 kubectl에서 rolling-update 옵션 사용이 가능
  • 레플리카 세트에서 rolling-update 를 사용하려면 디플로이먼트(deployment)를 사용해야함
# replicaSet 예시

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx-replicaset
spec:
  template:
    metadata:
      name: nginx-replicaset
      labels:
        app: nginx-replicaset
    spec:
      containers:
      - name: nginx-replicaset
        image: nginx
        ports:
        - containerPort: 80
  replicas: 3
  selector:
    matchLabels:
      app: nginx-replicaset
  • 명세는 .spec 필드에 설정
  • .spec.template 필드에 레플리카세트가 어떤 파드를 실행할지에 관한 정보를 설정
# 레플리카 셋 생성
$ kubectl apply -f replicaset-nginx.yaml 

레플리카 셋 생성 후 확인

# 레플리카 셋과 파드를 한꺼번에 삭제
$ kubectl delete replicaset {컨테이너 이름}

# 파드에 영향없이 레플리카 세트만 삭제
$ kubectl delete replicaset --cascade=orphan
  • 현재 실행중인 파드의 정보를 수정하기
$ kubectl edit pod {파드 이름}

# 편집기 화면이 나왔을 때 수정하고 저장

  • 각 파드의 .metadata.labels.app 필드 설정 확인
$ kubectl get pods -o=jsonpath="{range .items[*]}{.metadata.name}{'\t'}{.metadata.labels}{'\n'}{end}"


디플로이먼트 (Deployment)

  • 쿠버네티스에서 상태가 없는(stateless) 앱을 배포할 때 사용하는 가장 기본적인 컨트롤러
    • 초기에는 레플리케이션 컨트롤러를 사용했으나 최근에는 디플로이먼트를 앱 배포에 사용함
  • Deployment는 ReplicaSet을 관리하면서 앱 배포를 더 세밀하게 관리 (배포 기능을 세분화)
    • 실행시켜야 할 파드 개수 유지, 롤링 업데이트, 앱 배포 도중 멈췄다가 다시 배포, 앱 배포 후 이전 버전으로 롤백
    • Deployment의 PodTemplateSpec 을 수정하여 파드의 새로운 상태를 선언. 새로운 ReplicaSet이 생성되면 기존 ReplicaSet에서 새로운 ReplicaSet으로 속도를 제어하며 이동하는 것을 제어.
# deployment-nginx.yaml

apiVersion: apps/v1
# kind의 타입 이름 첫 글자는 대문자로 시작해야한다. (소문자로 했을 시 오류 발생)
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-deployment
  template:
    metadata:
      labels:
        app: nginx-deployment
    spec:
      containers:
      - name: nginx-deployment
        image: nginx
        ports:
        - containerPort: 80
  • .metadata.name : deployment 이름
  • .spec.replicas : 레플리카 파드의 개수를 선언
  • .spec.selector : deployment가 관리할 파드를 찾는 방법을 정의

deployment 생성 / 조회

$ kubectl apply -f deployment-nginx.yaml

# deployment 조회
$ kubectl get deploy

  • 조회 해보면 Deployment 에 의해 생성된 ReplicaSet 이름에 UUID가 부여됨
  • ReplicaSet 에 의해 생성된 Pod 들을 보면 ReplicaSet UUID 뒤에 랜덤값이 부여된 것을 볼 수 있음

 

deployment 이미지 수정방법

  • kubectl set 명령으로 직접 컨테이너 이미지를 지정
$ kubectl set image deployment/{디플로이먼트 이름} {컨테이너이름}={컨테이너이미지}

# Example
$ kubectl set image deployment/nginx-deployment nginx-deployment=nginx:1.9.1
  • kubectl edit 명령으로 현재 파드의 설정 정보를 연 다음 컨테이너 이미지 정보를 수정
$ kubectl edit deployment {디플로이먼트 이름}

# Example
$ kubectl edit deployment nginx-deployment

# edit 화면에서 이미지 부분을 찾아서 수정
  • deployment 템플릿의 컨테이너 이미지 정보를 수정하고 kubectl apply 명령을 실행하여 수정사항 적용
# deployment yaml 파일에서 image 필드 값 수정 후
$ kubectl apply -f {적용할 deplyment 템플릿 이름}

템플릿에 변화가 없을 때 -> unchanged

템플릿에 수정사항이 있어 적용될 때 -> configured

 

deployment 롤백

  • 이미지 변경 내역 조회
# 변경 내역 전체 조회
$ kubectl rollout history deploy {디플로이먼트 이름}

# 변경 내역 상세 조회
$ kubectl rollout history deploy {디플로이먼트 이름} revision={조회할 revision 숫자}

  • 바로 이전 Revision 으로 롤백
    • 롤백 대상이 된 Revision 이 가장 최신값으로 업데이트된다
$ kubectl rollout undo deploy {디플로이먼트 이름}

revision 1 이었던 버전이 3으로 변경된 셈이다.

  • 특정 Revision 으로 롤백
    • 역시나 롤백 대상이 된 Revision 이 가장 최신값으로 업데이트된다
$ kubectl rollout undo deploy {대상 디플로이먼트 이름} --to-revision={롤백할 revision 번호}

# Example
$ kubectl rollout undo deploy nginx-deployment --to-revision=2

  • CHANGE-CAUSE(변경 사항 메모) 에 값을 남기는 법
    • .metadata.anotation 의 하위 필드로 kubernetes.io/change-cause 필드를 추가하고 내용을 추가한다.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx-deployment
  # annotations 항목을 추가
  annotations:
    kubernetes.io/change-cause: version 1.9.1
... 생략

다시 apply 를 하면 CHANGE-CAUSE 에 값이 채워진다. (아래 이미지에서 REVISION 4 참고)

  • 파드 개수 조정하기
$ kubectl scale deploy {디플로이먼트 이름} --replicas={조정할 파드 개수}

# Example
$ kubectl scale deploy nginx-deploymeny --replicas=5

  • 디플로이먼트 배포 정지, 재개, 재시작

배포 일시 정지(pause) : kubectl rollout pause 명령을 사용해 진행중인 배포를 잠시 멈출 수 있음

$ kubectl rollout pause deployment/{디플로이먼트 이름}

배포 정지한 상태에서는 image수정 등의 작업을 진행해도 배포가 진행되지 않음

 

배포 재개(resume) : kubectl rollout resume 명령을 사용해 정지된 상태를 재개할 수 있음

$ kubectl rollout resume deployment/{디플로이먼트 이름}

재개하면 정지 상태에서 수정하고 적용한 부분들이 배포됩니다.

 

재시작(restart) : 파드 전체를 단순 재시작 하고 싶은경우 사용할 수 있습니다.

$ kubectl rollout restart deployment/{디플로이먼트 이름}

Deployment 상태

  • Progressing
    • 새로운 ReplicaSet 을 생성할 때
    • 새로운 ReplicaSet의 Pod를 조절 중일 때
    • 예전 ReplicaSet의 Pod를 조절 중일 때
    • 새로운 Pod가 준비 상태가 되거나 이용 가능한 상태가 됐을 때
  • Complete
    • 해당 Deployment 가 관리하는 모든 ReplicaSet이 업데이트 완료됐을 때
    • 모든 ReplicaSet이 사용 가능한 상태
    • 예전 ReplicaSet이 모두 종료됐을 때
  • Fail
    • 배포 중 이상이 있을 때
    • 쿼터 부족
    • readinessProbe 진단 실패
    • 컨테이너 이미지 가져오기 에러
    • 권한 부족
    • 제한 범위 초과
    • 앱 실행 조건을 잘못 지정
    • .spec.progressDeadlineSeconds 항목을 추가하면 지정된 시간이 지났을 때 상태를 False 로 바꿀 수 있음