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 으로 롤백
- 역시나 롤백 대상이 된 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 로 바꿀 수 있음