Featured image of post 워크로드 API

워크로드 API

워크로드 API

워크로드 API 카테고리

  • 클러스터에 컨테이너를 기동시키기 위해 사용되는 리소스
    • Pod
    • Replication Controller(Deprecated)
    • ReplicaSet
    • Deployment
    • DaemonSet
    • StatefulSet
    • Job
    • CronJob

파드

  • 워크로드 리소스의 최소 단위

파드 디자인 패턴

종류 개요
사이드카 패턴 메인 컨테이너에 기능 추가
앰배서더 패턴 외부 시스템과의 통신 중계
어댑터 패턴 외부 접속을 위한 인터페이스 제공

파드 명령어

1
2
## 파드 생성
$ kubectl apply -f sample-pod.yaml
1
2
## 파드 목록 표시
$ kubectl get pods
1
2
## 파드 상세 정보 표시
$ kubectl get pods --output wide
1
2
3
4
5
6
7
8
9
## 컨테이너에서 /bin/bash 실행
$ kubectl exec -it sample-pod -- /bin/bash
root@sample-pod:/## (이후 컨테이너 내부에서 명령어 실행 가능)

## 컨테이너에서 ls 명령어 실행
$ kubectl exec -it sample-pod -- /bin/ls

## 다수의 컨테이너 포함한 파드의 경우 특정 컨테이너 지정 가능
$ kubectl exec -it sample-2pod -c nginx-container -- /bin/ls

파드 주의 사항

  • 파드 내 컨테이너가 같은 포트로 바인드되면 안됨
  • 쿠버네티스는 ENTRYPOINTcommand, CMDargs라고 부름
  • 파드명 제한
    • 영어 소문자 또는 숫자
    • 기호는 ‘-’ 또는 ‘.’
    • 시작과 끝은 영어 소문자

레플리카셋/레플레케이션 컨트롤러

  • 파드의 레플리카를 생성하고 지정한 파드 수를 유지하는 리소스
  • 노드나 파드에 장애가 발생했을 때도 지정한 파드 수를 유지하기 위해 다른 노드에서 파드를 기동하므로 장애 시에 많은 영향 받지 않음
  • 모니터링은 특정 레이블을 가진 파드 수를 계산하는 형태로 이루어짐

레플리카셋 명령어

1
2
3
4
5
## 레플리카셋 생성
$ kubectl apply -f sample-rs.yaml

## 레플리카셋 확인
$ kubectl get replicasets -o wide
1
2
3
## 레이블 지정하여 파드 목록 표시
## 레플리카셋 이름-임의의 문자열로 명명 ex. sample-rs-cnvm5
kubectl get pods -l app=sample-app -o wide
1
2
## 레플리카셋 상세 정보 표시 (증감 이력 등)
## kubectl describe replicaset sample-rs

레플리카셋 주의점

  • spec.selector와 spec.template.metadata.labels의 레이블의 일치하지 않으면 에러
  • 외부에서 같은 레이블을 가진 파드가 있으면 레플리카 수에 충족되는 만큼 파드 삭제

레플리카셋 스케일링

  • 두 가지 방법
    • 매니페스트 수정하여 kubectl apply -f 명령어 실행
      • IaC(Infrastructure as Code)를 구현하기 위해서라도 해당 방법 권장
      1
      2
      
      $ sed -i -e 's|replicas: 3|replicas: 4|' sample-rs.yaml
      $ kubectl apply -f sample-rs.yaml
      
    • kubectl scale 명령어를 사용하여 스케일 처리
      • 레플리카셋 이외에도 디플로이먼트/스테이트풀셋/잡/크론잡에서 사용 가능
      1
      2
      
      ## 레플리카 수를 5로 변경
      $ kubectl scale replicaset sample-rs --replicas 5 
      

디플로이먼트

  • 여러 레플리카셋을 관리하며 롤링 업데이트나 롤백 등을 구현하는 리소스
  • 디플로이먼트 -> 레플리카셋 -> 파드 (관리 순서)
  • 롤링 업데이트 과정
    1. 신규 레플리카셋 생성
    2. 신규 레플리카셋 레플리카 수(파드 수)를 단계적으로 늘림
    3. 이전 레플리카셋의 레플리카 수(파드 수)를 단계적으로 줄임
    4. 2,3 반복
    5. 이전 레플리카셋은 레플리카 수를 0으로 유지
  • 파드를 하나만 기동해도 디플로이먼트 사용을 권장(파드 장애시 자동 재생성, 롤링 업데이트 등)

디플로이먼트 명령어

1
2
## --record를 사용하여 업데이트 이력을 저장. 디플로이먼트 가동 (deprecated option)
$ kubectl apply -f sample-deployment.yaml --record
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
## 디플로이먼트 확인
$ kubectl get deployments
NAME                READY   UP-TO-DATE   AVAILABLE   AGE
sample-deployment   3/3     3            3           2m30s

## 레플리카셋 확인
$ kubectl get replicasets
NAME                           DESIRED   CURRENT   READY   AGE
sample-deployment-77c7b569f6   3         3         3       2m39s

## 파드 확인
$ kubectl get pods
NAME                                 READY   STATUS    RESTARTS   AGE
sample-deployment-77c7b569f6-bnbcw   1/1     Running   0          2m44s
sample-deployment-77c7b569f6-fzh2m   1/1     Running   0          2m44s
sample-deployment-77c7b569f6-wjvbn   1/1     Running   0          2m44s
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
## 컨테이너 이미지 업데이트
$ kubectl set image deployment sample-deployment nginx-container=nginx:1.17 --record

## 디플로이먼트 업데이트 상태 확인
$ kubectl rollout status deployment sample-deployment

## 변경 이력 확인
$ kubectl rollout history deployment sample-deployment

## 초기 상태의 디플로이먼트
$ kubectl rollout history deployment sample-deployment --revision 1

## 한 번 업데이트된 후의 디플로이먼트
$ kubectl rollout history deployment sample-deployment --revision 2

## 버전 지정하여 롤백
$ kubectl rollout undo deployment sample-deployment --to-revision 1

## 직전 버전으로 롤백
$ kubectl rollout undo deployment sample-deployment
1
2
3
4
5
## 업데이트 일시 정지
$ kubectl rollout pause deployment sample-deployment

## 업데이트 일시 정지 해제
$ kubectl rollout resume deployment sample-deployment
1
2
3
4
5
6
## 레플리카 수를 3에서 4로 변경한 매니페스트를 apply - 디플로이먼트 스케일링
$ sed -i -e 's|replicas: 3|replicas: 4|' sample-deployment.yaml
$ kubectl apply -f sample-deployment.yaml

## kubectl scale 명령어
$ kubectl scale deployment sample-deployment --replicas=5
1
2
## 매니페스트를 사용하지 않고 명령어로 디플로이먼트 생성
$ kubectl create deployment sample-deployment-by-cli --image nginx:1.16

디플로이먼트 업데이트 전략

Recreate
  • 모든 파드 삭제하고 다시 파드 생성
  • 다운타임 발생하지만 추가 리소스를 사용하지 않으며 전환이 빠름
    • 기존 레플리카셋의 레플리카 수를 0으로 하고 리소스 반환
    • 신규 레플리카셋 생성하고 레플리카 수 늘림
RollingUpdate
  • 업데이트 중 정지 가능 최대 파드 수(maxUnavailable)와 생성 가능한 최대 파드 수(maxSurge)를 설정 가능
  • 추가 리소스를 사용하지 않도록 하거나 많은 리소스를 소비하지 않고 빠르게 전환하는 등의 동작 제어 가능
  • maxUnavailable과 maxSurge 모두 0은 불가능
상세 업데이트 파라미터
  • minReadySeconds(최소 대기 시간(초))
    • 파드가 Ready 상태가 된 후 디플로이먼트 리소스에서 파드 기동이 완료되었다고 판단(다음 파드의 교체가 가능하다고 판단)하기까지의 최소 시간
  • revisionHistoryLimit(수정 버전 기록 제한)
    • 디플로이먼트가 유지할 레플리카셋 수
    • 롤백이 가능한 이력 수
  • progressDeadlineSeconds(진행 기한 시간(초))
    • Recreate/RollingUpdate 처리 타임아웃 시간
    • 타임아웃 시간 경과시 자동 롤백

디플로이먼트 주의사항

  • 실제 환경에서는 롤백 보다는 이전 매니테스트를 kubectl apply를 실행하여 적용하는 것이 호환성 면에서 좋음
  • pause 상태에서는 업데이트가 즉시 반영되지 않고, 롤백도 되지 않음

데몬셋

  • 레플리카셋의 특수 형태 (각 노드에 파드를 하나씩 배치)
  • 노드를 늘렸을 때도 데몬셋의 파드는 자동으로 늘어난 노드에서 기동
  • 로그 수집또는 모니터링 프로세스를 위해 사용

데몬셋 명령어

1
2
## 데몬셋 생성
$ kubectl apply -f sample-ds.yaml

데몬셋 업데이트 전략

OnDelete
  • 데몬셋 매니페스트를 수정해도 기존 파드는 업데이트 X
    • 일반적으로 모니터링, 로그 전송에 사용되므로 업데이트는 다음에 다시 생성하거나 수동으로 임의의 시점에 하도록
    • 운영상 정지하면 안되는 파드, 업데이트가 급히 필요하지 않은 경우 사용 (이전 버전이 계속 사용되는 점 주의)
1
2
## 파드 업데이트 시 수동 정지 후 자동화된 복구 기능으로 새 파드 생성
$ kubectl delete pod sample-ds-ondelete-xxxxx
RollingUpdate
  • 데몬셋에서는 하나의 노드에 동일 파드를 여러개 생성할 수 없음
    • maxSurge 설정 불가
    • maxUnavailable만 지정하여 RollingUpdate
    • maxUnavailable 0 불가

스테이트풀셋

  • DB와 같은 stateful한 워크로드에 사용하기 위한 리소스
  • 레플리카셋과의 주된 차이점
    • 생성되는 파드의 접미사는 숫자 인덱스 (sample-statefulset-0, sample-statefulset-1, …)
    • 파드명 불변
    • 데이터를 영구적으로 저장하는 구조 (영구 볼륨을 사용하는 경우 파드 재기동시 같은 디스크 사용)
  • 동시에 여러 파드가 생성되지 않고 하나씩 생성하며, Ready 상태가 되면 다음 파드를 생성
    • podManagemetPolicyParallel로 설정하여 병렬로 동시에 기동 가능

스테이트풀셋 명령어

1
2
3
4
5
## 스테이트풀셋 생성
$ kubectl apply -f sample-statefulset.yaml

## 스테이트풀셋 확인
$ kubectl get statefulsets
1
2
3
4
5
## 영구 볼륨 클레임 확인
$ kubectl get persistentvolumeclaims

## 영구 볼륨 확인
$ kubectl get persistentvolumes

스테이트풀셋 스케일링

1
2
3
4
5
6
## 레플리카 수를 3에서 4로 변경한 매니페스트를 apply
$ sed -i -e 's|replicas: 3|replicas: 4|' sample-statefulset.yaml
$ kubectl apply -f sample-statefulset.yaml

## kubectl scale을 사용한 스케일링
$ kubectl scale statefulset sample-statefulset --replicas=5
  • 기본적으로 파드를 동시에 하나씩만 생성하고 삭제하므로 시간이 더 걸림
  • 스케일 아웃일 때는 인덱스가 가장 작은 것 부터 파드를 하나씩 생성하고, 이전에 생성된 파드가 Ready 상태가 되고 나서 다음 파드 생성
  • 스케일 인일 때는 인덱스가 가장 큰(가장 최근) 파드 부터 삭제
  • 항상 0번째 파드가 먼저 생성되고 나중에 삭제되므로 마스터 노드로 사용하는 이중화 구조 애플리케이션에 적합

스테이트풀셋 업데이트 전략

Ondelete
  • 데몬셋과 동일하게 매니페스트 변경해도 기존 파드는 그대로임
  • 영속성 영역을 가진 DB나 클러스터등에서 많이 사용하므로 임의의 시점이나 다음에 재기동할 때 업데이트
RollingUpdate
  • maxSurge, maxUnavailable 둘 다 사용 불가능
  • 파드마다 Ready 상태인지 확인하고 업데이트
  • Parallel로 설정되어 있는 경우에도 하나씩 업데이트가 이루어짐
  • partition 설정시 전체 파드 중 어떤 파드까지 업데이트할지 지정 가능
    • 전체에 영향을 주지 않고 부분적으로 업데이트를 확인할 수 있어 보다 안전
    • 수동으로 재기동해도 Ondelete와 달리 partition보다 작은 인덱스를 가진 파드는 업데이트 X
      • 예) partition이 3이면 0,1,2 인덱스 파드는 업데이트 X
    • partition 값 수정하면 해당 값에 맞는 인덱스를 가진 파드들 업데이트됨

영구 볼륨 데이터 저장 확인

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
## 컨테이너 내부에 영구 볼륨 마운트 확인
$ kubectl exec -it sample-statefulset-0 -- df -h | grep /dev/sd

## 영구 볼륨에 sample.html 이 없는지 확인
$ kubectl exec -it sample-statefulset-0 -- ls /usr/share/nginx/html/sample.html
ls: cannot access '/usr/share/nginx/html/sample.html': No such file or directory

## 영구 볼륨에 sample.html 생성
kubectl exec -it sample-statefulset-0 -- touch /usr/share/nginx/html/sample.html

## 영구 볼륨에 sample.html 이 있는지 확인
$ kubectl exec -it sample-statefulset-0 -- ls /usr/share/nginx/html/sample.html
/usr/share/nginx/html/sample.html

## 예상치 못한 파드 정지 1(파드 삭제)
$ kubectl delete pod sample-statefulset-0

## 예상치 못한 파드 정지 2(nginx 프로세스 정지)
$ kubectl exec -it sample-statefulset-0 -- /bin/bash -c 'kill 1'

## 파드 정지, 복구 후에도 파일 유실 없음
$ kubectl exec -it sample-statefulset-0 -- ls /usr/share/nginx/html/sample.html
/usr/share/nginx/html/sample.html
  • 스테이트풀셋을 삭제해도 영구 볼륨은 해제되지 않음
  • 영구 볼륨 해제하지 않고 스테이트풀셋 재기동시 그대로 파드가 기동
1
2
## 스테이트풀셋이 확보한 영구 볼륨 해제
$ kubectl delete persistentvolumeclaims www-sample-statefulset-{0..4}

  • 컨테이너를 사용하여 한 번만 실행되는 리소스
  • N개의 병렬로 실행하면서 지정한 횟수의 컨테이너 실행(정상 종료)를 보장하는 리소스
  • 파드의 정지가 정상 종료되는 작업에 적합 (레플리카셋의 경우 파드의 정지는 예상치 못한 에러임)
  • 잡에서는 정상 종료한 파드 수(COMPLETION)을 표기함

잡 명령어

1
2
3
4
5
6
7
8
## 잡 생성
$ kubectl apply -f sample-job.yaml

## 잡 목록 표시
$ kubectl get jobs

## 잡이 생성한 파드 확인
$ kubectl get pods --watch
1
2
## 잡 상태 모니터링
$ kubectl get job sample-job-ttl --watch --output-watch-events
1
2
3
4
## 매니페스트를 사용하지 않고 명령어로 잡 생성
$ kubectl create job sample-job-by-cli \
--image=amsy810/tools:v2.0 \
-- sleep 30
1
2
## 크론잡 기반 잡 생성
$ kubectl create job sample-job-from-cronjob --from cronjob/sample-cronjob

restartPolicy

Never
  • 파드에 장애가 발생하면 신규 파드가 생성
OnFailure
  • 파드 장애 발생시 다시 동일한 파드를 사용하여 잡을 다시 시작
  • RESTART 카운터가 증가
  • 파드 IP 주소는 변경 X, 영구 볼륨이나 hostPath 마운트하지 않은 경우 데이터 유실

태스크와 작업 큐 병렬 실행

  • completion: 몇 회 완료시 잡을 성공으로 표기할 것인지(기본값 1), 변경 불가
  • parallelism: 병렬성 지정(기본값 1), 변경 가능
  • backoffLimit: 실패 허용 횟수, 변경 가능
워크로드 completions parallelism backoffLimit 목적
1회만 실행하는 태스크 1 1 0 성공 유무에 관계 없이 반드시 1회 실행
N개 병렬로 실행시키는 태스크 M N P 병렬 태스크 수행
한 개씩 실행하는 작업 큐 미지정 1 P 한 번 정상 종료할 때까지 한 개씩 실행
N개 병렬로 실행하는 작업 큐 미지정 N P 큰 처리 전체가 정상 종료할 때까지 몇 개의 병렬 수로 계속 실행하고픈 경우
1
2
## 병렬성을 2에서 3으로 변경한 매니페스트 apply
$ sed -e 's|parallelism: 1|parallelism: 2|' sample-job.yaml | kubectl apply -f -

크론잡

  • 스케줄링된 시간에 잡 생성
  • 크론잡 -> 잡 -> 파드 (3계층 관리 구조)

크론잡 일시정지

  • 점검이나 어떤 이유로 잡 생성 원하지 않을 경우 suspend(일시정지)
  • 매니페스트 수정 후 kubectl apply 실행
  • kubectl patch
    1
    
    $ kubectl patch cronjob sample-cronjob -p '{"spec": {"suspend":true}}'
    

동시 실행 제어

  • 잡이 의도한 시간 간격에서 정상 종료시 동시 실행되지 않고 알아서 새로운 잡 실행
  • 기존 잡이 실행되고 있을 때를 제어하고 싶은 경우
정책 개요
Allow(기본값) 동시 실행에 대한 제한 X
Forbid 이전 잡이 종료되지 않은 경우 다음 잡 실행 X (동시 실행 X)
Replace 이전 잡 취소 후 잡 시작(이전 잡의 레플리카 수를 0으로 변경)

실행 시작 기한 제어

  • 쿠버네티스 마스터가 일시적으로 정지되는 경우와 같이 시작 시간 지연시, 이 지연 시간을 허용하는 시간
  • 기본값은 아무리 늦어져도 잡을 생성
  • 예) 매시 00분 시작 잡을 ‘매시 00~05분에만 실행 가능’ 설정 시 300초로 설정

크론잡 이력

설정 항목 개요
spec.successfulJobsHistoryLimit 성공한 잡을 저장하는 개수
spec.failedJobsHistoryLimit 실패한 잡을 저장하는 개수
  • 실제 운영 환경에서는 컨테이너 로그를 외부 로그 시스템을 통해 운영하는 것이 좋음
  • 둘 다 0으로 설정시 잡은 종료시 즉시 삭제

매니페스트 사용하지 않고 크론잡 생성

1
2
3
4
$ kubectl create cronjob sample-cronjob-by-cli \
--image amsy810/random-exit:v2.0 \
--schedule "*/1 * * * *" \
--restart Never

정리

  • 파드나 레플리카셋 생성 시 처음부터 디플로이먼트로 생성하는 것이 좋음
    리소스 종류 사용 방법
    파드 디버깅이나 확인 용도
    레플리카셋 파드 스케일링, 관리
    디플로이먼트 스케일링할 워크로드에 사용
    데몬셋 각 노드에 파드 하나씩 배포할 때
    스테이트풀셋 영속성 데이터 등의 상태를 가진 워크로드에 사용
    작업 큐나 태스크 등 컨테이너 종료가 필요한 워크로드에 사용
    크론잡 정기적으로 잡을 생성하고 싶은 경우
Hugo로 만듦
JimmyStack 테마 사용 중