INFRA/Kubernetes

Kubernetes Controller

sshhhh 2024. 7. 10. 00:26

Controller

  • pod 개수를 보장

 

 

1. Replication Controller

  • 옛날방식 → 호환시키기 위해 남겨둠
  • 요구하는 파드의 개수를 보장 → 파드 집합 실행을 항상 안정적으로 유지하는 것이 목표
  • 요구하는 pod개수가 부족하면 template를 이용해 pod추가
  • 요구하는 pod수보다 많으면 최근 생성된 pod를 삭제
  • 기본구성
    • selector : RC가 관리할 파드를 선택하는 라벨 셀렉터
    • replicas : 유지하고자 하는 파드의 수
    • template : 생성될 파드의 템플릿 (selector와 labels이 일치해야 함)
      • 일치하지 않고 실행시키면 The ReplicationController "rc-nginx" is invalid: spec.template.metadata.labels: Invalid value: map[string]string{"app":"web"}: selector does not match template labels 이런 오류문 뜸

 

rc-nginx.yaml 동작

  1. RC를 생성하면 지정된 selector와 일치하는 파드 3개 생성
  2. 파드 중 하나를 삭제하면 RC는 즉시 새로운 파드를 생성하여 replicas 수를 3개로 유지
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
  • label 확인 명령어
root@k8s-masternew:~/k8slab/k8slab/6# kubectl get rc rc-nginx --show-labels
NAME       DESIRED   CURRENT   READY   AGE   LABELS
rc-nginx   3         3         3       16m   app=webui

 

후속 모델인 ReplicaSet 나온 이유

  • 파드를지워도 Replication Controller는 파드 개수를 보장하기 때문에 replicas 설정한대로 다시만들어짐
  • edit로 replicas 5개로 바꿔도 바로 5개로 바꿔짐
  • 근데 이미지내용을 바꾸는 것이 업데이트 안됨 지웠다가 다시 깔아야 업데이트 되어있음
  • 즉 롤링업데이트가 안되는건 아닌데 수작업을 통해해야함 그래서 후속 모델이 나온 것

 

2.ReplicaSet

  • ReplicationController의 후속 모델
  • 파드의 개수를 보장 + 롤링 업데이트 수동으로 가능
  • matchLables 사용하여 파드를 선택

 

rs-nginx.yaml

  • app: webui 라벨을 가진 파드를 3개 생성하고 유지
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: rs-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webui
  template:
    metadata:
      name: nginx-pod
      labels:
        app: webui
    spec:
      containers:
      - name: nginx-container
        image: nginx:1.14
****

 

1. 실행 후 조회

root@k8s-masternew:~/k8slab/k8slab/6# kubectl get pods |grep -i rs-nginx
rs-nginx-9fghk   1/1     Running   0          56s
rs-nginx-pmzkd   1/1     Running   0          56s
rs-nginx-wjpxm   1/1     Running   0          56s

 

2. 파드 지워도 개수 보장해줌 + 레플리카 수정해도 바로 개수 수정해줌

root@k8s-masternew:~/k8slab/k8slab/6# kubectl delete pod rs-nginx-9fghk 
pod "rs-nginx-9fghk" delete

root@k8s-masternew:~/k8slab/k8slab/6# kubectl scale rs rs-nginx --replicas=2
replicaset.apps/rs-nginx scaled

 

3.컨트롤러는 labels를 기준으로 파드를 관리 → app: webui 레이블을 가진 파드가 이미 존재하여 다른 파드 올리려해도 올라가지 않음

--아래의 yaml 실행안됨: 레플리카 두갠데 레이블은 같음 안만들어짐 컨테이너가 달라도 컨트롤러 입장에선 구분못함
root@k8s-masternew:~/k8slab/k8slab/6# kubectl apply -f redis.yaml

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: webui
  name: redis
spec:
  containers:
  - image: redis
    name: redis

 

후속 모델인 Deployment 나온 이유

  • Deployment는 롤링 업데이트 자동으로 함
    • 파드가 세 개 있을 경우, 한 개씩 종료하고 새 파드를 생성하는 과정을 반복하며 점진적으로 모든 파드를 새로운 버전으로 업데이트 → 이걸 ReplicaSet은 수동으로 해야함
  • ReplicaSet==파드 개수 보장, Deployment == 버전 자동 업데이트 → 이 때문에 대부분 Deployment를 쓴다.

 

 

3. Deployment

  • 롤링업데이트 + 문제시 자동 롤백 + 파드 개수 보장

 

deoploy-nginx.yaml

  • Deployment → Replicaset → pod 모두 설정 가능
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webui
  template:
    metadata:
      name: nginx-pod
      labels:
        app: webui
    spec:
      containers:
      - name: nginx-container
        image: nginx:1.14

 

1.실행, 조회

Deployment  Replicaset  pod
rc nginx 5hnmt
--실행
root@k8s-masternew:~/k8slab/k8slab/6# kubectl apply -f deploy-nginx.yaml
deployment.apps/deploy-nginx created

NAME             READY   STATUS    RESTARTS   AGE   IP          NODE             NOMINATED NODE   READINESS GATES
rc-nginx-5hnmt   1/1     Running   0          36h   10.38.0.6   k8s-worker2new   <none>           <none>
rc-nginx-6hd5m   1/1     Running   0          36h   10.38.0.7   k8s-worker2new   <none>           <none>
rc-nginx-vlg22   1/1     Running   0          36h   10.40.0.6   k8s-worker1new   <none>           <none>
rs-nginx-s897w   1/1     Running   0          36h   10.38.0.5   k8s-worker2new   <none>           <none>

--조회
root@k8s-masternew:~/k8slab/k8slab/6# kubectl get deployments.apps,rs,pods
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/deploy-nginx   3/3     3            3           97s

NAME                                     DESIRED   CURRENT   READY   AGE
replicaset.apps/deploy-nginx-bd76d5967   3         3         3       97s

NAME                               READY   STATUS    RESTARTS   AGE
pod/deploy-nginx-bd76d5967-8tmdw   1/1     Running   0          97s
pod/deploy-nginx-bd76d5967-gq4fn   1/1     Running   0          96s
pod/deploy-nginx-bd76d5967-pnmhq   1/1     Running   0          96s
--하위계층들은 지워도 다시 살아남
root@k8s-masternew:~/k8slab/k8slab/6# kubectl delete pods deploy-nginx-bd76d5967-8tmdw
pod "deploy-nginx-bd76d5967-8tmdw" deleted

root@k8s-masternew:~/k8slab/k8slab/6# kubectl delete rs deploy-nginx-bd76d5967
replicaset.apps "deploy-nginx-bd76d5967" deleted

--가장 상위계층을 지워야 다 사라짐
root@k8s-masternew:~/k8slab/k8slab/6# kubectl delete deployment.apps/deploy-nginx
deployment.apps "deploy-nginx" deleted

 

 

deployment-exam1

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deploy
spec:
  selector:
    matchLabels:
      app: webui
  replicas: 3
  template:
    metadata:
      labels:
        app: webui
    spec:
      containers:
      - image: nginx:1.14
        name: web
        ports:
        - containerPort: 80

 

1. 실행

root@k8s-masternew:~/k8slab/k8slab/6# kubectl apply -f deployment-exam1.yaml
deployment.apps/app-deploy created

NAME                         READY   STATUS    RESTARTS   AGE   IP          NODE             NOMINATED NODE   READINESS GATES
app-deploy-d599fcdf4-8q9zf   1/1     Running   0          16s   10.40.0.5   k8s-worker1new   <none>           <none>
app-deploy-d599fcdf4-ck6p5   1/1     Running   0          16s   10.38.0.5   k8s-worker2new   <none>           <none>
app-deploy-d599fcdf4-m2c2v   1/1     Running   0          16s   10.38.0.4   k8s-worker2new   <none>           <none>

 

2. 롤링 업데이트 : 이미지 버전 업데이트 를 해보았다.

--web :컨테이너 이름
root@k8s-masternew:~/k8slab/k8slab/6# kubectl set image deploy app-deploy web=nginx:1.16
deployment.apps/app-deploy image updated

--지워지고 다시 만들어졌다.
NAME                          READY   STATUS    RESTARTS   AGE   IP          NODE             NOMINATED NODE   READINESS GATES
app-deploy-7579bc79dd-gs74s   1/1     Running   0          17s   10.40.0.5   k8s-worker1new   <none>           <none>
app-deploy-7579bc79dd-xfw9z   1/1     Running   0          25s   10.38.0.5   k8s-worker2new   <none>           <none>
app-deploy-7579bc79dd-zwcxv   1/1     Running   0          9s    10.38.0.4   k8s-worker2new   <none>           <none>

 

 

deployment-exam2.yaml

  • 롤링업데이트 추가하여 서비스 중단없이 업데이트 수행
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx
  annotations:
    kubernetes.io/change-cause: version 1.15
spec:
  progressDeadlineSeconds: 600
  revisionHistoryLimit: 10
  strategy:
    rollingUpdate:
      maxSurge: 25% --업데이트 중에 생성될 수 있는 최대 추가 파드 수
      maxUnavailable: 25% --업데이트 중에 사용할 수 없는 최대 파드 수
    type: RollingUpdate
  replicas: 3
  selector:
    matchLabels:
      app: webui
  template:
    metadata:
      labels:
        app: webui
    spec:
      containers:
      - name: web
        image: nginx:1.15
        ports:
        - containerPort: 80
  1. 실행
root@k8s-masternew:~/k8slab/k8slab/6# kubectl apply -f deployment-exam2.yaml
deployment.apps/deploy-nginx created

root@k8s-masternew:~/k8slab/k8slab/6# kubectl rollout history deployment deploy-nginx
deployment.apps/deploy-nginx 
REVISION  CHANGE-CAUSE
1         version 1.15

--edit로 version,image 1.16으로 바꿔주었더니 바로 롤링업데이트 
--그러나 근거가 안남으니 쓰지말것
root@k8s-masternew:~/k8slab/k8slab/6# kubectl edit deployments.apps deploy-nginx
deployment.apps/deploy-nginx edited

root@k8s-masternew:~/k8slab/k8slab/6# kubectl rollout history deployment deploy-nginx
deployment.apps/deploy-nginx 
REVISION  CHANGE-CAUSE
1         version 1.15
2         version 1.16

 

롤링 업데이트 명령어

--#pause: 일시 중단
root@k8s-masternew:~/k8slab/k8slab/6# kubectl rollout pause deploy app-deploy
deployment.apps/app-deploy paused

--#resume : 진행
root@k8s-masternew:~/k8slab/k8slab/6# kubectl rollout resume deploy app-deploy
deployment.apps/app-deploy resumed

--#status : 상태 모니터링
--배포가 잘되었는지 확인 
root@k8s-masternew:~/k8slab/k8slab/6# kubectl rollout status deploy app-deploy 
deployment "app-deploy" successfully rolled out

--이미지버전 롤링 업데이트 --record로 기록
root@k8s-masternew:~/k8slab/k8slab/6# kubectl set image deploy app-deploy web=nginx:1.19 --record
Flag --record has been deprecated, --record will be removed in the future
deployment.apps/app-deploy image updated

--#history : 롤링 업데이트에 대한 기존 정보를 보고 싶을 때 
root@k8s-masternew:~/k8slab/k8slab/6# kubectl rollout history deploy app-deploy
deployment.apps/app-deploy 
REVISION  CHANGE-CAUSE
1         <none>
4         <none>
5         kubectl set image deploy app-deploy web=nginx:1.19 --record=true
8         kubectl set image deploy app-deploy web=nginx:1.20 --record=true

--#undo : 롤백 (바로 이전)
root@k8s-masternew:~/k8slab/k8slab/6# kubectl rollout undo deploy app-deploy 
deployment.apps/app-deploy rolled back

--원하는 버전으로 이동
root@k8s-masternew:~/k8slab/k8slab/6# kubectl rollout undo deploy app-deploy --to-revision=8
deployment.apps/app-deploy rolled back
  • yaml 내용 추가 설명
root@k8s-masternew:~/k8slab/k8slab/6# kubectl get deployments.apps app-deploy -o yaml
spec:
  progressDeadlineSeconds: 600 --10분내에 롤링업데이트를 완료해야 한다.
  replicas: 3
  revisionHistoryLimit: 10 --히스토리 정보 10개 저장
  selector:
    matchLabels:
      app: webui
  strategy:
    rollingUpdate:
    --롤링 업데이트 과정에서 동시에 실행될 수 있는 최대 Pod 수 3개의 25% (1개)이므로 
      최대 1개의 Pod가 새 버전으로 업데이트되고 실행
    --숫자가 크면 클수록 롤링업데이트 속도 빨라짐
      maxSurge: 25%
      maxUnavailable: 25% -- 롤링 업데이트 과정에서 동시에 사용할 수 없는 최대 Pod 수, 1개를 실행할 수 없음 
    type: RollingUpdate

 

 

4. Daemon Set

  • 클러스터내의 전체 노드에서 파드를 띄울때 사용하는 컨트롤러 → 모든 노드에 하나씩 꼭 배치되어 있음 (kube-proxy, weave-net)
  • 주로 네트워크 설정, 로그 수집기, 모니터링 에이전트 등을 각 노드에 자동으로 배포하는 데 사용
  • 삭제되도 바로 다시 생성됨
# kubectl get pods -A 확인
kube-system   kube-proxy-gbwxq                        
kube-system   kube-proxy-mnn5m                        
kube-system   kube-proxy-pz464
                                
kube-system   weave-net-42njd                         
kube-system   weave-net-qclnm                         
kube-system   weave-net-x9x4q
  • 롤링업데이트 된다

 

DaemonSet.yaml

  • app: webui라벨이 지정된 모든 노드에 nginx:1.14 이미지를 사용하는 파드 배포
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: daemonset-nginx
spec:
  selector:
    matchLabels:
      app: webui
  template:
    metadata:
      name: nginx-pod
      labels:
        app: webui
    spec:
      containers:
      - name: nginx-container
        image: nginx:1.14
  1. 실행
root@k8s-masternew:~/k8slab/k8slab/6# kubectl apply -f daemonset-exam.yaml
daemonset.apps/daemonset-nginx created

--노드당 하나씩 만들어짐 마스터 노드는 안만들어짐
NAME                    READY   STATUS    RESTARTS   AGE   IP          NODE             NOMINATED NODE   READINESS GATES
daemonset-nginx-6ddjc   1/1     Running   0          37s   10.40.0.7   k8s-worker1new   <none>           <none>
daemonset-nginx-d758r   1/1     Running   0          37s   10.38.0.4   k8s-worker2new   <none>           <none>

 

2.마스터 노드에는 DaemonSet 파드 만들어지지 않음

  • 마스터 노드에는 스케쥴을 할당하지 마십시오. -> 데몬셋, 파드 안만들어짐 -> 왜? 마스터 노드는 할일많음 kubectl get pods -A로 확인해 보면 스케쥴, 백업, dns 관리등...하는게 많음
root@k8s-masternew:~/k8slab/k8slab/6# kubectl describe nodes k8s-masternew |grep -i noschedule
Taints:             node-role.kubernetes.io/control-plane:NoSchedule

--워크노드는 스케쥴 할당받음
--taint도 설정됨
root@k8s-masternew:~/k8slab/k8slab/6# kubectl describe nodes k8s-worker1 |grep -i noschedule
root@k8s-masternew:~/k8slab/k8slab/6# kubectl describe nodes k8s-worker2 |grep -i noschedule

--지워도 노드당 하나씩 생성됨
--마스터 노드가 컨트롤러이기 때문에
root@k8s-masternew:~/k8slab/k8slab/6# kubectl delete pod daemonset-nginx-6ddjc 
pod "daemonset-nginx-6ddjc" deleted

root@k8s-masternew:~/k8slab/k8slab/6# kubectl delete pod daemonset-nginx-d758r 
pod "daemonset-nginx-d758r" deleted

NAME                    READY   STATUS    RESTARTS   AGE   IP          NODE             NOMINATED NODE   READINESS GATES
daemonset-nginx-4w9bl   1/1     Running   0          31s   10.38.0.4   k8s-worker2new   <none>           <none>
daemonset-nginx-98mwq   1/1     Running   0          49s   10.40.0.7   k8s-worker1new   <none>           <none>
  • 롤링 업데이트 가능 (--record로 기록남김)
데몬셋이름 daemonset-nginx
root@k8s-masternew:~/k8slab/k8slab/6# kubectl set image ds daemonset-nginx nginx-container=nginx:1.15 --record
Flag --record has been deprecated, --record will be removed in the future
daemonset.apps/daemonset-nginx image updated
--버전 바꾸고 저장하면 
root@k8s-masternew:~/k8slab/k8slab/6# kubectl edit ds daemonset-nginx 

--새롭게 생성됨
NAME                    READY   STATUS    RESTARTS   AGE   IP          NODE             NOMINATED NODE   READINESS GATES
daemonset-nginx-jtktl   1/1     Running   0          89s   10.38.0.4   k8s-worker2new   <none>           <none>
daemonset-nginx-pq9rh   1/1     Running   0          91s   10.40.0.7   k8s-worker1new   <none>           <none>

 

5. StatefulSet

  • 상태가 있는(==Stateful) 파드를 관리 → 컨테이너가 종료되더라도 컨테이너 내부의 데이터가 지속적으로 유지되어, 파드를 재시작하더라도 데이터가 보존된다는 의미
  • 파드 이름 보존할때 주로 쓰임 + DB 컨테이너

 

statefulset-exam.yaml

  • 파드이름 지정해서 만들 수 있다.
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: sf-nginx
spec:
  replicas: 3
  serviceName: sf-service
#  podManagementPolicy: OrderedReady
  podManagementPolicy: Parallel
  selector:
    matchLabels:
      app: webui
  template:
    metadata:
      name: nginx-pod
      labels:
        app: webui
    spec:
      containers:
      - name: nginx-container
        image: nginx:1.14
  1. 실행
root@k8s-masternew:~/k8slab/k8slab/6# kubectl apply -f statefulset-exam.yaml
statefulset.apps/sf-nginx created

NAME         READY   STATUS    RESTARTS   AGE   IP          NODE             NOMINATED NODE   READINESS GATES
sf-nginx-0   1/1     Running   0          10s   10.40.0.7   k8s-worker1new   <none>           <none>
sf-nginx-1   1/1     Running   0          10s   10.40.0.9   k8s-worker1new   <none>           <none>
sf-nginx-2   1/1     Running   0          10s   10.38.0.4   k8s-worker2new   <none>           <none>

 

2. 삭제 후 다시 확인

--삭제해도 똑같은 이름으로 다시 만들어짐 
root@k8s-masternew:~/k8slab/k8slab/6# kubectl delete pods sf-nginx-1
pod "sf-nginx-1" deleted

NAME         READY   STATUS    RESTARTS   AGE    IP          NODE             NOMINATED NODE   READINESS GATES
sf-nginx-0   1/1     Running   0          2m4s   10.40.0.7   k8s-worker1new   <none>           <none>
sf-nginx-1   1/1     Running   0          33s    10.40.0.9   k8s-worker1new   <none>           <none>
sf-nginx-2   1/1     Running   0          2m4s   10.38.0.4   k8s-worker2new   <none>           <none>

 

2-1. 삭제

--pod수 늘렸다가 줄이면 
root@k8s-masternew:~/k8slab/k8slab/6# kubectl scale sts sf-nginx --replicas=4
statefulset.apps/sf-nginx scaled

root@k8s-masternew:~/k8slab/k8slab/6# kubectl scale sts sf-nginx --replicas=2
statefulset.apps/sf-nginx scaled

--가장 최근에 만든게 삭제된다.
NAME         READY   STATUS    RESTARTS   AGE     IP          NODE             NOMINATED NODE   READINESS GATES
sf-nginx-0   1/1     Running   0          9m38s   10.40.0.7   k8s-worker1new   <none>           <none>
sf-nginx-1   1/1     Running   0          8m7s    10.40.0.9   k8s-worker1new   <none>           <none>

 

 

계층 구조

  • Pod: 쿠버네티스의 가장 작은 배포 단위 → 하나 이상의 컨테이너를 포함
  • ReplicaSet: 동일한 Pod의 복제본을 보장하여 지정된 수의 Pod가 항상 실행되도록 함
  • Deployment: ReplicaSet을 관리하며, 애플리케이션의 배포 및 업데이트를 쉽게 할 수 있도록 함
  • →pods << replicaset << deployments.apps
root@k8s-masternew:~# kubectl get pods, replicaset ,deployments.apps
제일 하위
NAME                             READY   STATUS             RESTARTS   AGE
pod/webserver-5d5c5c44c7-6xz5w   0/1     ImagePullBackOff   0          19m
pod/webserver-5d5c5c44c7-gvpvr   0/1     ImagePullBackOff   0          7m9s
pod/webserver-5d5c5c44c7-jjkhb   0/1     ImagePullBackOff   0          9m50s

하위
NAME                                   DESIRED   CURRENT   READY   AGE
replicaset.apps/webserver-5d5c5c44c7   3         3         0       20m

상위
NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/webserver   0/3     3            0           20m
  1. 제일 상위계층이 삭제되어야 아래 계층도 사라짐
--ReplicaSet을 삭제하려해도 쿠버네티스가 다시 살려냄
root@k8s-masternew:~# kubectl delete rs webserver-5d5c5c44c7
replicaset.apps "webserver-5d5c5c44c7" deleted

--Deployment는 삭제됨
root@k8s-masternew:~# kubectl delete deployments.apps webserver 
deployment.apps "webserver" deleted

 

2. 상위 오브젝트 없이 하위 오브젝트 유지 : cascade로 삭제 → 단독 파드로 전환 ==상위 계층이 없으니 그렇게 된 것

root@k8s-masternew:~/k8slab/k8slab/6# kubectl get pods,rs
NAME                 READY   STATUS    RESTARTS   AGE
pod/rs-nginx-p6vdb   1/1     Running   0          10m
pod/rs-nginx-s897w   1/1     Running   0          51s

NAME                       DESIRED   CURRENT   READY   AGE
replicaset.apps/rs-nginx   2         2         2       15m
--ReplicaSet만 삭제
root@k8s-masternew:~/k8slab/k8slab/6# kubectl delete rs rs-nginx --cascade=false
warning: --cascade=false is deprecated (boolean value) and can be replaced with --cascade=orphan.
replicaset.apps "rs-nginx" deleted

root@k8s-masternew:~/k8slab/k8slab/6# kubectl get pods,rs
NAME                 READY   STATUS    RESTARTS   AGE
pod/rs-nginx-p6vdb   1/1     Running   0          12m
pod/rs-nginx-s897w   1/1     Running   0          2m8s

--단독파드니까 그냥 지워짐
root@k8s-masternew:~/k8slab/k8slab/6# kubectl delete pods rs-nginx-p6vdb 
pod "rs-nginx-p6vdb" deleted