( 참고 : [교재] 핵심만 콕! 쿠버네티스 )

쿠버네티스 컨트롤러


1. 컨트롤러란?

컨트롤러의 역할

  • control-loop이라는 루프를 계속 돌면서, 쿠버네티스의 특정 리소스를 지속적으로 관찰
  • “현재 상태”가 “바라는 상태”가 되도록!


Example )

  • 리소스 = Job ( 한번 실행하고 완료가되는 배치 작업 수행 )
  • 컨트롤러 = Job Controller
    • 새로운 Job 리소스가 생성되는지 지속적으로 관찰
  • 그 밖에도 다양한 컨트롤러들 존재
    • ex) ReplicaSet, Deployment, Job & CronJob, DaemonSet, StatefulSet
    • 전부 kube-controller-manager 컴포넌트 안에서 동작


2. ReplicaSet

역할 : Pod를 복제 (replicate)

  • 이유 : 1개의 pod에 문제가 생기더라도, 안정적인 서비스 운영 위해!


YAML 파일 ( myreplicaset.yaml )

# myreplicaset.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myreplicaset
spec:
  replicas: 2
  selector:
    matchLabels:
      run: nginx-rs
  template:
    metadata:
      labels:
        run: nginx-rs
    spec:
      containers:
      - name: nginx
        image: nginx
  • replicas : 복제할 pod의 개수
  • selector.matchLabels : 유지할 pod 선택
    • ex) run:nginx-rs 라벨을 가진 pod를 복제/유지
  • template : 복제할 pod 정의


리소스 생성 & 조회

kubectl apply -f myreplicaset.yaml
kubectl get replicaset # rs
  • DESIRED : 원하는 pod의 개수
  • CURRENT : 현재 pod의 개수
  • READY : 생성된 pod 중, 준비 완료된 pod의 개수


pod 리소스 조회하기

kubectl get pod
  • 2개의 pod가 생성된 것 확인 가능

    • (pod1) myreplicaset-XXXX

    • (pod2) myreplicaset-XXXX

      여기서, myreplicaset은, 위 YAML파일에서 정했던 Replicaset의 이름


[ Note ]

  • RepliaSet 리소스는 복제/유지의 기능만 담당할 뿐,

    실제 프로세스 실행은 Pod 리소스를 활용하여 컨테이너 실행

  • Deployment 리소스는 애플리케이션의 배포를 담당하는 리소스


Replica 개수 4개로 늘리기 ( & 확인 )

kubectl scale rs --replicas 4 myreplicaset
kubectl get rs


강제로 삭제 시, 다시 생기는 것을 확인가능

kubectl delete pod myreplicaset-jc496
kubectl get pod


ReplicaSet 리소스 정리하기

kubectl delete rs --all


3. Deployment

역할 : 애플리케이션 업데이트 및 배포 담당

Details

  • 롤링 업데이트 지원 & 롤링 업데이트 되는 Pod의 비율 조절
  • 업데이트 히스토리 저장 & 롤백
  • pod 개수 늘릴 수 있음 (scale out)
  • 배포 상태 확인 가능


YAML 파일 ( mydeploy.yaml )

# mydeploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mydeploy
spec:
  replicas: 10
  selector:
    matchLabels:
      run: nginx
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 25%  
      maxSurge: 25%
  template:
    metadata:
      labels:
        run: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
  • replicas : 복제할 pod의 개수

  • selector.matchLabels : 유지할 pod 선택

  • strategy.type : 배포 전략 종류 선택

  • pod 허용 개수 관련

    ( strategy.type이 rollingUpdate인 경우에만 사용 가능 )

    • strategy.rollingUpdate.maxUnavailable : 최대 중단 pod 허용 개수 (비율)
    • strategy.rollingUpdate.maxSurge : 최대 초과 pod 허용 개수 (비율)
  • template : 복제할 pod 정의


리소스 생성 & 확인

  • --record : 배포 히스토리 확인할 때 위해!
kubectl apply --record -f mydeploy.yaml
kubectl get deployment
# 이름 : mydeploy

kubectl get rs
# 이름 : mydeploy-649xxx

kubectl get pod
# 이름 : mydeploy-649xxx-bbxx


과정 요약

  • Deployment 리소스가 ReplicaSet을 생성

    & ReplicaSet이 Pod 복제본을 생성

  • Deployment = 배포 담당

  • ReplicaSet = 복제 담당

  • Pod = 컨테이너 실행 담당


롤링 업데이트

  • ex) 1.7.9에서 1.9.1로 업그레이드
  • 한번에 모든 pod가 업데이트 (X)
  • rollingUpdate 설정값에 따라, 점진적으로 업데이트 (O)
    • 중단 없이 어플리케이션 배포
kubectl set image dployment mydeploy nginx=nginx:1.9.1 --record
kubectl get pod


배포 상태 확인하기

kubectl rollout status deployment mmydeploy


특정 pod의 이미지 tag 정보 확인

kubectl get pod mydeploy-xxx-xxx -o yaml | grep "image: nginx"


롤백 기능

  • 일부러 에러나게끔, 존재하지 않는 버전(1.9.21)로 업데이트
  • 확인해보면, 새로운 pod가 정상적으로 생성되지 않음을 확인
kubectl set image dployment mydeploy nginx=nginx:1.9.21 --record
kubectl get pod
  • 따라서, 이전으로 롤백해야!
    • 과거 history 확인하기
    • 과거로 undo하기
kubectl rollout history deployment mydeploy
kubectl rollout undo deployment mydeploy
  • 직접 배포 version을 명시하여 롤백할 수 있음
kubectl rollout undo deployment mydeploy --to-revision=1


edit 명령으로 직접 YAML파일 수정 가능

kubectl edit deploy mydeploy


deployment 리소스 정리하기

kubectl delete deploy --all


쿠버네티스 리소스 컨셉 (계층도)

deployment

  • replicaset # 1
    • pod #1-1
      • container # 1-1-a
      • container # 1-1-b
    • pod #1-2
      • container # 1-2-a
      • container # 1-2-b


4. StatefulSet

Stateful한 pod를 생성해야 하는 경우

  • StatefulSet
    • “순서에 따라 고유한 역할”
    • pod마다 고유한 식별자 존재 & 고유한 데이터 보관
  • Deployment, Replicaset
    • 서로 구분하지 않는 pod 생성/복제


언제 사용?

  • 1) 고유의 Pod 식별자가 필요한 경우
  • 2) 명시적으로 pod마다 저장소가 특정되어야 하는 경우
  • 3) pod 간의 순서에 민감한 애플리케이션
  • 4) 애플리케이션이 순서대로 update되어야 하는 경우


YAML 파일 ( mysts.yaml )

# mysts.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysts
spec:
  serviceName: mysts
  replicas: 3
  selector:
    matchLabels:
      run: nginx
  template:
    metadata:
      labels:
        run: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        volumeMounts:
        - name: vol
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: vol
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi
---
apiVersion: v1
kind: Service
metadata:
  name: mysts
spec:
  clusterIP: None
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 80
  selector:
    run: nginx
  • serviceName : StatefulSEt와 연결할 service의 이름
  • selector.matchLabels : 유지할 pod 선택
  • template : 복제할 pod 정의


리소스 생성 & 확인

kubectl apply -f mysts.yaml
kubectl get statefulset


[참고]

  • pod의 이름 = pod 순서가 적힌 식별자

  • Statefulset의 pod들이..

    • 동일한 저장소 (X)
    • 각자의 볼륨 (O)

    을 사용한다

  • 삭제 : 식별자의 역순으로 pod 삭제


replica 개수 줄이기 & 확인

kubectl scale sts mysts --replicas=0
kubectl get pod


statefulset 리소스 정리하기

kubecetl delete sts mysts


5. DaemonSet

모든 노드에 동일한 pod를 실행하고자 할 때!

  • 모든 노드에서 항상 동일한 작업을 수행해야하는 경우!


YAML 파일 ( fluentd.yaml )

# fluentd.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
spec:
  selector:
    matchLabels:
      name: fluentd
  template:
    metadata:
      labels:
        name: fluentd
    spec:
      containers:
      - name: fluentd
        image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
        volumeMounts:
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      volumes:
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers


리소스 생성 & 확인

kubectl apply -f fluentd.yaml
kubectl get daemonset


6. Job & CronJob

6-1. Job

항상 실행 X, 한번 실행되고 완료 O


ex) ML task

  • train.py : ML 스크립트
    • 상단 parameter 부분에, 파라미터를 입력받음
  • Dockerfile : ML 스크립트를 docker image로 변환
  • job.yaml : Job 실행을 위한 리소스 정의서


step 1) ML 스크립트 작성


step 2) 도커 파일 작성

# Dockerfile
FROM python:3.6.8-stretch
RUN pip install tensorflow==1.5 keras==2.0.8 h5py==2.7.1
COPY train.py .
ENTRYPOINT ["python", "train.py"]


step 3) 도커 이미지 빌드

docker build . -t $USERNAME/train


step 4) 도커 허브 로그인 & 업로드

docker login
docker push $USERNAME/train


step 5) Job 리소스 작성 ( job.yaml )

# job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: myjob
spec:
  template:
    spec:
      containers:
      - name: ml
        image: $USERNAME/train
        args: ['3', 'softmax', '0.5']
      restartPolicy: Never
  backoffLimit: 2
  • backoffLimit : 재시도 횟수

    ( 해당 횟수만큼 재시도 후, 최종적으로 실패로 기록 )


step 6) 리소스 생성 & 확인

kubectl apply -f job.yaml
kubectl get job


[참고]

  • 기존 pod와 다르게, 계속 Running이 아니라, 완료 후에는 Completed


Job 리소스 정리하기

kubecetl delete job --all


6-2. CronJob

주기적으로 Job을 실행할 수 있도록 하는 리소스

  • cron 형식을 따름
# cronjob.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            args:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure
  • schedule : Job 리소스 실행 주기
  • jobTemplate : Job 리소스에서 사용하는 스펙 동일하게


리소스 생성 & 확인

kubectl apply -f cronjob.yaml
kubectl get cronjob


cronjob 리소스 정리하기

kubectl delete cronjob --all


7. 요약

  • 쿠버네티스의 모든 것은 “리소스”로 표현

  • 여러 컨테이너가 모여서 Pod가 생성,

    이것을 모아서 Deployment/Service의 작은 컴포넌트를 만들고,

    이것을 모아서 하나의 애플리케이션 만들기!