[따배쿠] Controller - ReplicationController란?
Controlller
- Pod의 개수 보장 (Scale Out 보장)
- Controller을 삭제하면 종속된 Pod도 삭제됨
종류
- Replication Controller
- Pod 개수 보장 컨트롤러
- 파드의 복제본 수를 관리하여 항상 지정된 수의 파드가 실행되도록 보장합니다.
- ReplicaSet
- Replication Controller + 풍부한 Label 지원
- 쿠버네티스에서 파드의 복제본을 관리하는 중요한 역할을 하며, Deployment와 함께 사용되어 애플리케이션의 배포 및 업데이트를 효율적으로 관리합니다
- Deployment
- ReplicaSet을 제어 (Rolling Update / Roll back)
- 애플리케이션의 배포 및 업데이트를 관리합니다. 롤링 업데이트와 롤백 기능을 제공하여 애플리케이션의 가용성을 높입니다.
- DaemonSet
- Node 당 1개씩 실행되도록 보장
- 클러스터의 모든 노드에서 특정 파드를 실행하도록 보장합니다. 주로 로그 수집기나 모니터링 에이전트와 같은 시스템 서비스를 배포하는 데 사용됩니다.
- StatefulSet
- Pod의 이름을 보장
- 상태가 있는 애플리케이션을 관리합니다. 각 파드에 고유한 정체성을 부여하고, 안정적인 네트워크 ID와 스토리지를 제공합니다.
- Job Controller
- Pod의 정상적인 종료 관리
- 일회성 작업을 관리합니다. 지정된 수의 파드가 성공적으로 완료될 때까지 작업을 수행합니다.
- CronJob Controller
- Job 스케줄링 예약 사용 지원
- 주기적으로 작업을 실행하도록 예약합니다. 특정 시간에 잡을 실행할 수 있도록 설정할 수 있습니다.
작동 흐름
Flow
1. User가 pod 생성 명령 요청 (CLI 명령 OR yaml 파일)
ex) kubectl create deployment webui --image=nginx --replica=3
2. Master node의 api server가 해당 요청을 받고 문법이나 권한이 합당한지 확인한다.
3. 또한 api server가 etcd 저장소에 있는 정보를 확인해서, scheduler에게 요청을 보낸다.
*컨테이너를 실행할 때 어떤 node에 배포하는게 제일 최적일까? 라는 요청
4. scheduler는 api server가 준 etcd 저장소 정보를 통해, 어떤 node에 배포하는 게 최적일지 판단 후 응답 ex) node2가 최적일 거 같아!
5. api server은 controller에게 pod의 개수를 보장해달라 명령을 내림
ex) replica=3일 경우, pod 3개를 보장해줘!
6. api server는 scheduler에게 응답 받은 정보를 가지고 해당 Worker node의 kubelet에 컨테이너 실행 명령을 전달함으로써, pod를 배포한다.
7. 해당 상황에서 controller는 적절한 개수의 pod 보장되고 있는지 확인하고, 혹시라도 특정 pod가 문제가 생길 경우 api server에게 요청한다.
ex) pod 3개가 보장 되어야 하는데. 1개가 정상적으로 작동하지 않는 경우
8. api server은 scheduler에게 어떤 node에 pod를 다시 배포해야 할 지 요청
9. scheduler에게 응답 받은 후, 해당 Worker node의 kubelet에 컨테이너 실행 명령을 전달함으로써, pod를 배포한다.
Replication Controller
- 요구하는 Pod의 개수를 보장하며, Pod 집합의 실행을 항상 안정적으로 유지하는 것을 목표
- 요구하는 Pod의 개수가 부족하면 template를 이용해 Pod를 추가
- 요구하는 Pod의 개수가 많으면, 최근에 생성된 Pod를 삭제
- 기본 구성
- selector
- replicas
- template
[예시]
apiVersion: v1
kind: ReplicationController
metadata:
name: <RC_이름>
spec:
replicas: <배포 갯수>
selector:
key: value
template:
<컨테이너 템플릿>
selector에 정의된 key : value 라벨을 갖는 Pod를 ex) app = myapp
replicas에 정의된 배포 갯수만큼 배포해달라는 의미
현재 배포된 Pod가 많으면 kill 하고,
현재 배포된 Pod가 적으면 template에 정의된 대로 Pod 생성
동작 원리
# rc-nginx.yaml 파일 작성
apiVersion: v1
kind: ReplicationController
metadata:
name: rc-nginx
spec:
replicas: 3
selector:
app: webui
template:
metadata:
name: nginx-pod
labels:
app: webui
spec:
containers:
- name: nginx-container
image: nginx:1.14
selector에 정의된 app : webui 라벨을 갖는 pod를 3개 배포해달라는 의미
현재 배포된 Pod가 많으면 kill 하고, 현재 배포된 Pod가 적으면 template에 정의된 대로 Pod 생성
예시1 (replicationController 배포)
# rc-nginx.yaml 파일 작성
apiVersion: v1
kind: ReplicationController
metadata:
name: rc-nginx
spec:
replicas: 3
selector:
app: webui
template:
metadata:
name: nginx-pod
labels:
app: webui
spec:
containers:
- name: nginx-container
image: nginx:1.14
# ReplicationController 생성 및 확인
root@master:~/Getting-Start-Kubernetes/6# kubectl create -f rc-nginx.yaml
replicationcontroller/rc-nginx created
root@master:~/Getting-Start-Kubernetes/6# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES <none>
rc-nginx-fxvct 1/1 Running 0 15s 192.168.104.30 node2 <none> <none>
rc-nginx-w26xw 1/1 Running 0 15s 192.168.104.29 node2 <none> <none>
rc-nginx-zpgt6 1/1 Running 0 15s 192.168.166.165 node1 <none> <none>
root@master:~/Getting-Start-Kubernetes/6# kubectl get replicationcontrollers
NAME DESIRED CURRENT READY AGE
rc-nginx 3 3 3 96s
kubectl get replicationcontrollers를 줄여서 kubectl get rc로 쓸 수 있다.
root@master:~/Getting-Start-Kubernetes/6# kubectl get rc
NAME DESIRED CURRENT READY AGE
rc-nginx 3 3 3 116s
kubectl describe rc ~ 명령어를 통해 자세하게 볼 수도 있다.
root@master:~/Getting-Start-Kubernetes/6# kubectl describe rc rc-nginx
Name: rc-nginx
Namespace: default
Selector: app=webui
Labels: app=webui
Annotations: <none>
Replicas: 3 current / 3 desired
Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
Labels: app=webui
Containers:
nginx-container:
Image: nginx:1.14
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
Node-Selectors: <none>
Tolerations: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 2m44s replication-controller Created pod: rc-nginx-w26xw
Normal SuccessfulCreate 2m44s replication-controller Created pod: rc-nginx-fxvct
Normal SuccessfulCreate 2m44s replication-controller Created pod: rc-nginx-zpgt6
예시2
# CLI 명령으로 redis.yaml 파일 생성
root@master:~/Getting-Start-Kubernetes/6# kubectl run redis --image=redis --labels=app=webui --dry-run -o yaml > redis.yaml
root@master:~/Getting-Start-Kubernetes/6# ls
redis.yaml
# redis.yaml 파일 수정
root@master:~/Getting-Start-Kubernetes/6# vi redis.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
app: webui
name: redis
spec:
containers:
- image: redis
name: redis
# 생성
root@master:~/Getting-Start-Kubernetes/6# kubectl create -f redis.yaml
pod/redis created
# 확인
root@master:~/Getting-Start-Kubernetes/6# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mydb-node1 1/1 Running 1 (118m ago) 12m 192.168.166.163 node1 <none> <none>
rc-nginx-fxvct 1/1 Running 0 12m 192.168.104.30 node2 <none> <none>
rc-nginx-w26xw 1/1 Running 0 12m 192.168.104.29 node2 <none> <none>
rc-nginx-zpgt6 1/1 Running 0 12m 192.168.166.165 node1 <none> <none>
redis 0/1 Terminating 0 1s <none> node1 <none> <none>
redis pod가 생성되지 않고 바로 삭제되는 것을 확인
왜냐면 앞서 생성한 replicationController가 아주 잘 작동하고 있기 때문에!
pod가 3개 넘어서니 Controller가 바로 죽여버린다
예시 3
# 기존에 존재하는 replicationController 수정
root@master:~/Getting-Start-Kubernetes/6# kubectl edit rc rc-nginx
replicationcontroller/rc-nginx edited
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
kind: ReplicationController
metadata:
creationTimestamp: "2024-12-04T01:53:51Z"
generation: 2
labels:
app: webui
name: rc-nginx
namespace: default
resourceVersion: "171680"
uid: d48afa97-1744-43f0-8730-d1b6e1962a6d
spec:
replicas: 4
selector:
app: webui
template:
metadata:
creationTimestamp: null
labels:
app: webui
name: nginx-pod
spec:
containers:
- image: nginx:1.14
imagePullPolicy: IfNotPresent
name: nginx-container
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 4
fullyLabeledReplicas: 4
observedGeneration: 2
readyReplicas: 4
replicas: 4
spec 내 replicas를 3개에서 4개로 수정해보자
# 확인
root@master:~/Getting-Start-Kubernetes/6# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
rc-nginx-2xb95 1/1 Running 0 115s 192.168.166.166 node1 <none> <none>
rc-nginx-fxvct 1/1 Running 0 17m 192.168.104.30 node2 <none> <none>
rc-nginx-w26xw 1/1 Running 0 17m 192.168.104.29 node2 <none> <none>
rc-nginx-zpgt6 1/1 Running 0 17m 192.168.166.165 node1 <none> <none>
replicationcontroller를 수정하자마자, pod가 4개로 늘어났다.
예시 4
# replicationcontroller 수정
root@master:~/Getting-Start-Kubernetes/6# kubectl scale rc rc-nginx --replicas=2
replicationcontroller/rc-nginx scaled
이렇게 kubectl scale rc ~ 명령어로도 replicationcontroller를 수정할 수 있다.
기존 4개에서 2개로 줄여보자
# 확인
root@master:~/Getting-Start-Kubernetes/6# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
rc-nginx-fxvct 1/1 Running 0 20m 192.168.104.30 node2 <none> <none>
rc-nginx-w26xw 1/1 Running 0 20m 192.168.104.29 node2 <none> <none>
가장 오래된 pod 2개는 남겨두고, 최신 2개를 삭제한다.
pod 2개를 보장한다.
예시 5
# replication controller 수정
root@master:~/Getting-Start-Kubernetes/6# kubectl edit rc rc-nginx
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
kind: ReplicationController
metadata:
creationTimestamp: "2024-12-04T01:53:51Z"
generation: 3
labels:
app: webui
name: rc-nginx
namespace: default
resourceVersion: "172053"
uid: d48afa97-1744-43f0-8730-d1b6e1962a6d
spec:
replicas: 2
selector:
app: webui
template:
metadata:
creationTimestamp: null
labels:
app: webui
name: nginx-pod
spec:
containers:
- image: nginx:1.15
imagePullPolicy: IfNotPresent
name: nginx-container
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 2
fullyLabeledReplicas: 2
observedGeneration: 3
readyReplicas: 2
replicas: 2
nginx 이미지를 1.15로 바꿔보자
# 확인
root@master:~/Getting-Start-Kubernetes/6# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
rc-nginx-fxvct 1/1 Running 0 27m app=webui
rc-nginx-w26xw 1/1 Running 0 27m app=webui
replication controller 내 컨테이너 image 버전을 수정한다고 해도, 이미 작동중인 pod는 바뀌지 않는다.
# 삭제 후 새로 생긴 pod 확인
root@master:~/Getting-Start-Kubernetes/6# kubectl delete pods rc-nginx-fxvct
pod "rc-nginx-fxvct" deleted
root@master:~/Getting-Start-Kubernetes/6# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
rc-nginx-26xxx 1/1 Running 0 35s app=webui
rc-nginx-w26xw 1/1 Running 0 29m app=webui
기존 pod를 삭제시키면, replicationcontroller에 의해 pod가 2개 보장 되어야하기 때문에
자동으로 1개가 더 생성된다.
새로 생긴 pod를 자세히 보자
root@master:~/Getting-Start-Kubernetes/6# kubectl describe pod rc-nginx-26xxx
Name: rc-nginx-26xxx
Namespace: default
Priority: 0
Service Account: default
Node: node1/10.100.0.101
Start Time: Wed, 04 Dec 2024 02:22:56 +0000
Labels: app=webui
Annotations: cni.projectcalico.org/containerID: 6e46041e35c82088084f59839bd27faa8eafea7bebeb43cf7ebf4da888c272fa
cni.projectcalico.org/podIP: 192.168.166.167/32
cni.projectcalico.org/podIPs: 192.168.166.167/32
Status: Running
IP: 192.168.166.167
IPs:
IP: 192.168.166.167
Controlled By: ReplicationController/rc-nginx
Containers:
nginx-container:
Container ID: containerd://2dd45eec44878b16096cdda1cda53cbcfd2297fd3aec24bac114308929745e51
Image: nginx:1.15
Image ID: docker.io/library/nginx@sha256:23b4dcdf0d34d4a129755fc6f52e1c6e23bb34ea011b315d87e193033bcd1b68
Port: <none>
Host Port: <none>
State: Running
Started: Wed, 04 Dec 2024 02:23:05 +0000
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-fjktq (ro)
Conditions:
Type Status
PodReadyToStartContainers True
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-fjktq:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 97s default-scheduler Successfully assigned default/rc-nginx-26xxx to node1
Normal Pulling 96s kubelet Pulling image "nginx:1.15"
Normal Pulled 88s kubelet Successfully pulled image "nginx:1.15" in 7.459s (7.459s including waiting). Image size: 44795472 bytes.
Normal Created 88s kubelet Created container nginx-container
Normal Started 88s kubelet Started container nginx-container
새로 생긴 pod의 이미지는 nginx:1.15 버전인 것을 알 수 있다.
이렇게 서비스 운영 중에도 replicationcontroller의 속성에 의해 롤링 업데이트를 진행할 수 있다.
자동 업데이트는 아니고, pod를 죽인 다음에 된 거여서 수동 업데이트...? ㅎㅎ
퀴즈
- 다음의 조건으로 ReplicationController를 사용하는 rc-lab.yaml 파일을 생성하고 동작시킵니다.
- labels(name: apache, app:main, rel:stable)을 가지는 httpd:2.2 버전의 Pod를 2개 운영합니다.
- rc name : rc-mainui
- contaiener: httpd:2.2
- 현재 디렉토리에 rc-lab 파일이 생성되어야 하고, 애플리케이션 동작은 파일을 이용해 실행합니다.
- labels(name: apache, app:main, rel:stable)을 가지는 httpd:2.2 버전의 Pod를 2개 운영합니다.
root@master:~/Getting-Start-Kubernetes/6# vi rc-lab.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: rc-mainui
spec:
replicas: 2
selector:
app: main
name: apache
rel: stable
template:
metadata:
labels:
app: main
name: apache
rel: stable
spec:
containers:
- name: webui
image: httpd:2.2
ports:
- containerPort: 80
root@master:~/Getting-Start-Kubernetes/6# kubectl create -f rc-lab.yaml
replicationcontroller/rc-mainui created
root@master:~/Getting-Start-Kubernetes/6# kubectl get pods
NAME READY STATUS RESTARTS AGE
rc-mainui-jjjv7 0/1 ContainerCreating 0 5s
rc-mainui-msx7k 0/1 ContainerCreating 0 5s
root@master:~/Getting-Start-Kubernetes/6# kubectl get replicationcontroller
NAME DESIRED CURRENT READY AGE
rc-mainui 2 2 2 22s
rc-nginx 2 2 2 161m
- 동작되는 http:2.2 버전의 컨테이너를 3개로 확장하는 명령을 적고, 실행하세요
# 방법 1. rc-mainui 파일 수정
root@master:~/Getting-Start-Kubernetes/6# kubectl edit rc rc-mainui
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
kind: ReplicationController
metadata:
creationTimestamp: "2024-12-04T04:35:18Z"
generation: 2
labels:
app: main
name: apache
rel: stable
name: rc-mainui
namespace: default
resourceVersion: "185029"
uid: f1582b5c-4b51-46fb-8c83-fcf601c4f49e
spec:
replicas: 3
selector:
app: main
name: apache
rel: stable
template:
metadata:
creationTimestamp: null
labels:
app: main
name: apache
rel: stable
spec:
containers:
- image: httpd:2.2
imagePullPolicy: IfNotPresent
name: webui
ports:
- containerPort: 80
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 3
fullyLabeledReplicas: 3
observedGeneration: 2
readyReplicas: 3
replicas: 3
# 방법 2. kubectl scale rc 명령어로 수정
kubectl scale rc rc-mainui --replicas=3
# 확인
root@master:~/Getting-Start-Kubernetes/6# kubectl get pods
NAME READY STATUS RESTARTS AGE
rc-mainui-7zgff 1/1 Running 0 9s
rc-mainui-jjjv7 1/1 Running 0 114s
rc-mainui-msx7k 1/1 Running 0 114s