쿠버네티스의 컨트롤러는 특정 Pod의 수를 보장해주는 역할을 하는 자원을 의미한다. 아래의 쿠버네티스의 마스터노드(컨트롤플레인)가 어플리케이션을 각 노드에서 실행하고, 이를 각 etcd에서 제대로 수행되고 있는지 모니터링하다가 부족한 Pod은 더 실행해주고, 많은 Pod은 종료시켜주는 역할을 한다.
쿠버네티스의 컨트롤러의 종류
쿠버네티스 컨트롤러는 Replication controller, replicaset, deployment, daemonset등 여러가지가 있어서 헷갈린다. 이 자원들은 모두 다 컨트롤로에 속한다. 다만 각각의 자원들이 쿠버네티스가 발전해나감으로서 생긴 디테일의 차이(대동소이)한 것들이 있어서 몇가지 대표적으로 필요한 것들만 알아보면 좋다. 사용목적에 따른 대표적인 것들은 아래와 같다.
- 오랜시간 켜두어야할 어플리케이션이 파드로 존재하는 경우: Replication contoller, Replicaset, Deploment
- 클러스터에 속한 전체 노드에 같은 파드를 실행해야하는 경우: Daemonset
- 일회성 작업을 해야할 때: Job
- 주기적인 배치작업을 해야하는 경우: Cronjob
자세히는 아래와 같다. 리플리케이션 컨트롤러 (Replication controller)은 쿠버네티스 초기부터 있던 컨트롤러로, 지정된 숫자만큼 파드의 개수를 항상 보장해줄 수 있도록 제어해주는 컨트롤러이다. 요즘은 이 리플리케이션 컨트롤러보다 리플리카셋(replicaset)을 주로 이용하거나, 앱 배포면 디플로이먼트(deployment)을 이용한다고 한다.
사용방법은 아래와 같다. 1) Kind에 replicationContoller라고 적는다. 2) spec.replicas내에 몇개의 파드를 유지할 것인지를 명시한다. 3) selector은 레이블이 동일한 어떤 파드를 관찰할 것인지를 명시하는 것이다. 여기서는 app: my-ngnix라는 라벨을 가진 파드를 바라보고 관찰한다. 4) template은 명시한 파드가 개수가 부족한 경우, 어떤 스펙으로 다시 만들지를 정의한다. *주의할 것은 selector이하의 속성값과 template.labels의 속성값은 동일해야 에러가 안난다.
아래와 같은 rc의 실행결과를 확인할 수 있다.
PS C:\Users\PC\Documents\repository\kube> kubectl get rc
NAME DESIRED CURRENT READY AGE
my-rc 3 0 0 24s
리플리카셋(Replicaset, RC): ReplicationContorller의 확장판(+POD 검색기능)
ReplicationContoller은 POD의 개수를 보장한다고 했다. 리플리카셋도 마찬가지로 POD의 개수를 보장한다. 하지만, 리플리카셋이 추가적으로 해주는 기능은,
"="의 selector외에 집합연산자 (in, notin)등을 지원해서 저 쉽게 사용할 수 있다. 리플리카셋의 spec에는 matchLabels과 matchExpressions라는 것을 사용할 수 있는데, matchLabels은 리플리케이션컨트롤러가 해주는 기능과 비슷하다. 다만, matchExpressions으로 좀더 상세하게 POD의 선정을 할 수 있다. 가령 아래와 같이 matchExpression을 써주면 key의 In조건에 맞는 POD들만 선택해서 관리할 수 있다.
# replicaset.yaml
...
spec:
replicas:3
selector:
matchLabels:
app: my-app
matchExpression:
{key: verison, operator: In, value:["3.5", "2.1"]}
하지만 matchExpressions을 꼭 써야하는 것은 아니다. 다음과 같이 작성해도 충분히 동작한다.
위와 같이 파드의 개수를 3개로 유지하게끔 선언했는데, 아래와 같이 파드가 1개 생성된 경경우는 2개가 아직 모종의 이유로 생성되지 안음을 확인할 수 있다. cpu 요구량을 못맞춰서 중단된것을 알 수 있다.
> kubectl get pods
NAME READY STATUS RESTARTS AGE
my-replicaset-q42qp 0/1 ContainerCreating 0 3s
> kubectl describe replicaset my-replicaset
....
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 2m7s replicaset-controller Created pod: my-replicaset-q42qp
Warning FailedCreate 2m7s replicaset-controller Error creating: pods "my-replicaset-86kwg" is forbidden: exceeded quota: mem-cpu-demo, requested: requests.cpu=1, used: requests.cpu=1, limited: requests.cpu=1
Warning FailedCreate 2m7s replicaset-controller Error creating: pods "my-replicaset-n4rkz" is forbidden: exceeded quota: mem-cpu-demo, requested: requests.cpu=1, used: requests.cpu=1, limited: requests.cpu=1
Warning FailedCreate 2m7s replicaset-controller Error creating: pods "my-replicaset-jg6xc" is forbidden: exceeded quota: mem-cpu-demo, requested: requests.cpu=1, used: requests.cpu=1, limited: requests.cpu=1
Warning FailedCreate 2m7s replicaset-controller Error creating: pods "my-replicaset-66pht" is forbidden: exceeded quota: mem-cpu-demo, requested: requests.cpu=1, used: requests.cpu=1, limited: requests.cpu=1
Warning FailedCreate 2m7s replicaset-controller Error creating: pods "my-replicaset-5zg4z" is forbidden: exceeded quota: mem-cpu-demo, requested: requests.cpu=1, used: requests.cpu=1, limited: requests.cpu=1
Warning FailedCreate 2m7s replicaset-controller Error creating: pods "my-replicaset-8ns6f" is forbidden: exceeded quota: mem-cpu-demo, requested: requests.cpu=1, used: requests.cpu=1, limited: requests.cpu=1
Warning FailedCreate 2m7s replicaset-controller Error creating: pods "my-replicaset-w5gsb" is forbidden: exceeded quota: mem-cpu-demo, requested: requests.cpu=1, used: requests.cpu=1, limited: requests.cpu=1
Warning FailedCreate 2m6s replicaset-controller Error creating: pods "my-replicaset-8j4dh" is forbidden: exceeded quota: mem-cpu-demo, requested: requests.cpu=1, used: requests.cpu=1, limited: requests.cpu=1
Warning FailedCreate 2m6s replicaset-controller Error creating: pods "my-replicaset-vtqgv" is forbidden: exceeded quota: mem-cpu-demo, requested: requests.cpu=1, used: requests.cpu=1, limited: requests.cpu=1
Warning FailedCreate 24s (x8 over 2m6s) replicaset-controller (combined from similar events): Error creating: pods "my-replicaset-fx7rt" is forbidden: exceeded quota: mem-cpu-demo, requested: requests.cpu=1, used: requests.cpu=1, limited: requests.cpu=1
디플로이먼트(Deployment)
컨트롤러기보다는 컨트롤러인 레플리카셋(RS)을 제어해주는 역할이다. 디플로이먼트의 가장 큰 목적은 롤링업데이트(Rolling update) 또는 롤링백(Rolling back)을 하기위함이다. 롤링업데이트의 자세한 설명은 링크와 같다. 소프트웨어를 업데이트를 위한 것인데 요약하면 "롤링 업데이트는 파드가 여러 개 있다고 했을 때, 한 번에 모든 파드를 동시에 버전업하는 것이 아닌, 파드를 하나씩 업데이트해서 무중단 업데이트를 해주는 과정"이라고 생각하면 된다. 핵심은 "무중단 + 업데이트"이다.
아래와 같이 대화형 튜토리얼을 이용하면 예시를 직접 해볼 수 있다(링크). 아래의 이미지를 보면, 이름이 "kubernetes-bootcamp"인 deployment가 하나가 실행됨을 확인할 수 있다. 위에서도 디플로이먼트가 레플리카셋을 제어한다고하니, 레플리카셋이 하나 있을 것이고, 레플리카셋은 또 파드를 제어하니, 파드의 생성도 함께 확인할 수 있을 것이다.
그러면, 디플로이먼트를 사용하려면 어떻게 yaml파일을 작성해야하나? 일단, deployment의 버전을 확인하기위해서 아래와 같이 확인한다. deployment은 apps/v1의 APIVERSION에 있다.
PS C:\Users\PC> kubectl api-resources
NAME SHORTNAMES APIVERSION NAMESPACED KIND
...
deployments deploy apps/v1 true Deployment
그리고 아래와 같이 스펙에 맞춰 yaml파일을 작성한다. 형태는 replciaset과 동일하다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 2
selector:
matchLabels:
app: my-nginx
template:
metadata:
name: nginx-pod
labels:
app: my-nginx
spec:
containers:
- name: nginx-container
image: nginx:latest
resources:
limits:
memory: 500Mi
cpu: 1
requests:
memory: 500Mi
cpu: 1
그러면 아래와같이 동작하는 것을 확인할 수 있다. (POD 하나는 리소스 이유 때문에 동작은 하지 않았다.)
PS C:\Users\PC\Documents\repository\kube> kubectl get all -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/my-deployment-cff6c8d86-jgb5g 1/1 Running 0 12s 10.1.0.25 docker-desktop <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 44d <none>
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/my-deployment 1/2 1 1 12s nginx-container nginx:latest app=my-nginx
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replicaset.apps/my-deployment-cff6c8d86 2 1 1 12s nginx-container nginx:latest app=my-nginx,pod-template-hash=cff6c8d86
Deployment을 이용하여 pod을 스케일업하기: kubectl scale deployment [deployment명] --replicas=3
아래의 그림과 같이 deployment은 Replica Set(RS)을 선언적으로 지정해서 관리한다. 또한, Replica Set은 pod을 선언적으로 관리한다.(선언적= 지정한대로 개수, 자원등을 보장해줌). 따라서, deployment을 생성해놓고, replicaset 또는 pod을 직접 관리하면, 삭제되고 재생산된다. 따라서, pod수나 replicas을 변경하고싶으면 deployment을 이용해서 조작해야한다.
아래와같이 쿠버네티스 공식홈페이지에 있는 것과 동일하게 웹서버인 nginx을 서비스하는 deployment을 정의했다.
이를 이용해서 Deployment 및 스케일업을 아래와같이 진행해볼 수 있다. 아래의 코드블럭처럼 replicas을 조절하면 replicas에 딸려있는 pod수가 조절되므로 replicas을 조정해도 된다. replicas을조정하기위해서는 deployment을 조정한다.
// deployment 자원의 생성
$ kubectl create -f nginx-deployment.yaml
deployment.apps/nginx-deployment created
// 자원이 생성되었는지 확인
$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 18s
// replicas을 5개로 스케일업
$ kubectl scale deployment nginx-deployment --replicas=5
deployment.apps/nginx-deployment scaled
// 스케일업 되었는지 pod수를 확인
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-7fb96c846b-88ctt 1/1 Running 0 52s
nginx-deployment-7fb96c846b-dqbhk 1/1 Running 0 7s
nginx-deployment-7fb96c846b-jhgq2 1/1 Running 0 52s
nginx-deployment-7fb96c846b-m2bbg 1/1 Running 0 7s
nginx-deployment-7fb96c846b-xj74r 1/1 Running 0 52s
그리고, kubectl descirbde 을 이용하면 아래와같이 스케일업된것을 확인할 수 있다.
롤링업데이트의 사용은 어떻게 해야하나? 예시로
# set 명령어 인자
kubectl set image deployment <디플로이먼트 이름> <컨테이너이름>=<새 버전>
# 디플로이먼트 내 컨테이너 ngnix 을 1.9.1로 업데이트
kubectl set image deployment/nginx nginx=nginx:1.9.1
# 모든 디플로이먼트와 RC의 컨테이너 내에 있는 ngnix이미지를 1.9.1로 업데이트
kubectl set image deployments,rc nginx=nginx:1.9.1 --all
*references:https://www.macstadium.com/blog/how-to-k8s-pods-replicasets-and-deployments
Deployment의 정지: kubectl delete deployment [deployment명]
// deployment 상태확인
$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
simple-app-deployment 3/3 3 3 11m
$ kubectl delete deployment simple-app-deployment
deployment.apps "simple-app-deployment" deleted
스테이트풀세트(Stateful set)
작성중
데몬세트(Daemon set)
작성중
잡 컨트롤러(Job contoller)
작성중
크론잡(Cronjob)
작성중
기타(트러블 슈팅)
이슈1: error: resource mapping not found for name: "my-rc" namespace: "" from ".\\my_rc.yaml": no matches for kind "ReplicationContoller" in version "v1" ensure CRDs are installed first
해결방법: 아래와 같이 쿠버네티스에서 지원하는 자원들과 APIVERSION을 확인한다. 참고로 해당 이슈는 "ReplicationContoller"을 kind에 썼는데, 아래와 같이 "ReplicationController"에 오타가 난 것을 알 수 있다. 즉, 아래의 리스트의 KIND와 동일한 KINDS을 써주어야한다.
$ kubectl api-resources
NAME SHORTNAMES APIVERSION NAMESPACED KIND
bindings v1 true Binding
componentstatuses cs v1 false ComponentStatus
configmaps cm v1 true ConfigMap
endpoints ep v1 true Endpoints
events ev v1 true Event
limitranges limits v1 true LimitRange
namespaces ns v1 false Namespace
nodes no v1 false Node
...
이슈 2: 리플리카셋에서 아래와 같이 메시지가 나온 경우(failed quota) Error creating: pods "my-replicaset-vvh6n" is forbidden: failed quota: mem-cpu-demo: must specify limits.cpu for: nginx-container; requests.cpu for: nginx-container
해결방법: 리플리카셋 내 template.spec.container.resources 내에 limit 또는 reqeusts을 명시한다.
'Data science > MLOps' 카테고리의 다른 글
Docker: 파일 복사 및 볼륨 마운 (0) | 2022.11.01 |
---|---|
쿠버네티스 오류 해결: The connection to the server localhost:8080 was refused - did you specify the right host or port (0) | 2022.07.26 |
[Fullstack DP 2021] ML 프로젝트 시 고려사항, 실패하는 이유 (0) | 2022.07.25 |
Kubernetes: Pod 이해하기 (Init container, livenessProbe, Infra container, static pod) (0) | 2022.07.15 |
쿠버네티스 클러스터 구성 / 실습 (0) | 2022.07.10 |