kubernetes

[따배쿠] Controller - ReplicationController란?

bbiyak2da 2024. 12. 4. 09:26

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 파일이 생성되어야 하고, 애플리케이션 동작은 파일을 이용해 실행합니다.
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