반응형
4장. 레플리케이션과 그 밖의 컨트롤러 : 관리되는 파드 배포
- pod 가 있고 이걸 죽으면 다시 재생시키겠다 : 레플리카셋, 레플리카 컨트롤러(웹서버같은 친구들)
- pod 가 있는데요 작업 끝나면 죽이거나 작업 크론잡을 돌려요 : 잡, 크론잡
- pod 가 있는데요 노드당 한 대 씩 배정 : 데몬셋(로그 , 프로메테우스)
- (개인 의견: 에어플로가 레플리카셋 , airflow 위에 태스크들은 잡 형태가 되지 않을까,,)
4.0 다루는 내용
- 파드의 안정적인 유지
- 동일한 파드의 여러 인스턴스 실행
- 노드 장애시, 자동으로 파드 재스케줄링
- 파드의 수평스케줄링
- 각 클러스터 노드에서 시스템 수준의 파드 실행
- 배치 잡 실행
- 잡을 주기적으로, 또는 한번만 실행하도록 스케줄링
- 파드 : 배포 가능한 기본 단위
- 파드를 수동적으로 개입(생성, 감독, 관리)없이 컨트롤러를 통해 실제 파드를 생성하고 관리
4.1. 파드를 안정적으로 유지하기
- 쿠버네티스 주요 이점 : 컨테이너들이 클러스터 어딘가에서 계속 실행되게 할 수 있다.
- 주 프로세스에 crash 가 발생하면, kubelet 이 컨테이너를 다시 시작하게 한다.
- kubelet : api 서버와 통신, 노드의 컨테이너 관리
- 메모리 누수로 OOM이 발생할 수 있는 경우, 애플리케이션의 상태를 외부에서 체크해 해결 가능
- 프로세스는 계속 실행될 수 있다.
라이브니스 프로브 소개(liveness probe)
- 컨테이너가 살아있는지 확인하는 주된방법
- HTTP GET 프로브
- 지정한 IP 주소, 포트, 경로에 HTTP GET 요청을 수행
- 서버가 오류 응답코드를 리턴하거나 응답하지 않으면 프로브는 실패로 간주하고 컨테이너를 다시 시작
- TCP 소켓 프로브
- 컨테이너의 지정된 포트에 TCP를 연결하려고 시도
- 성공적으로 연결이 되지 않으면 컨테이너가 다시 시작
- Exec 프로브
- 컨테이너 내부에 임의의 명령을 실행하고, 명령의 종료 상태 코드를 확인
- 상태 코드가 0이면 검사 성공. 다른 코드는 오류로 간주
- 파드를 정의하는 YAML 작성 및 생성 (HTTP GET 라이브니스 프로브 포함)
$ kubectl get pod <pod name> -o yaml apiVersion: v1 # 해당 YAML 디스크립터에서 사용한 쿠버네티스 API 버전 kind: Pod # 쿠버네티스 오브젝트/리소스 유형 metadata: # 파드 메타데이터 (이름, 레이블 등...) ... spec: # 파드 정의/내용 (파드 컨테이너 목록, 볼륨 등...) containers: - image: luksa/kubia-unhealthy # 문제가 있는 애플리케이션을 포함하는 이미지 name: kubia livenessProbe: # Http Get을 수행할 라이브니스 프로브 httpGet: path: / # 네트워크 포트 HTTP 요청에서 요청할 경로 port: 8080 # 프로브가 연결해야 하는 네트워크 포트
다섯 번의 요청 후에 쿠버네티스가 프로브를 실패한 것으로 간주하여 컨테이너를 다시 시작
동작 중인 라이브니스 프로브 확인
라이브니스 프로브의 기능 확인 가능
$ kubectl get po kubia-liveness
NAME READY STATUS RESTARTS AGE
kubia-liveness 1/1 Running 1 2m
컨테이너가 다시 시작된 이유 확인 가능
(컨테이너가 종료되면 동일한 컨테이너가 재시작되는 것이 아닌, 새로운 컨테이너가 생성)
$ kubectl describe po kubia-liveness
(생략)
Exit Code: 137 # 128 + x (9 : 프로세스 강제 종료)
(생략)
Killing container ...
라이브니스 프로브의 추가 속성 설정
추가적인 매개변수 지정
(예시 : 초기 지연 설정) - 반드시 지정해야 함
livenessProbe:
httpGet:
path:/
port: 8080
initialDelaySeconds: 15 # 첫 번째 프로브 실행 전 15초 대기
효과적인 라이브니스 프로브 생성
- 애플리케이션의 내부만 체크하고, 외부 요인의 영향을 받지 않도록 해야함
(ex : 프론트엔드 웹서버가 백엔드 데이터베이스에 연결할 수 없을 때 실패를 반환해서는 안됨) - 많은 연산 리소스 사용하면 안됨, 시간이 오래 걸리지 않아야 됨
- 재시도 루프를 구현하지 말아야 함 (실패 임계값으로 대처 가능)
- 크래시가 발생하거나 라이브니스 프로브가 실패한 경우 컨테이너를 다시 시작해 컨테이너를 계속 실행함
- 파드를 호스팅하는 노드에서 Kubelet에 의해 수행
- 노드 자체에 크래시가 발생하는 경우, 포드의 대체 폼을 생성해야 하는 것은 컨트롤 플레인의 몫
(직접 생성한 파드는 노드 자체가 고장나면 아무 것도 할 수 없음)
-> 애플리케이션이 다른 노드에서 시작되도록 하기 위해 레플리케이션컨트롤러 or 유사한 메커니즘으로 파드 관리해야 함
4.2 레플리케이션컨트롤러 소개
- 쿠버네티스는 파드를 항상 실행되게 유지하기 위해 레플리케이션 컨트롤러(Replication Controller)라는 리소스를 활용한다.
- 레플리케이션 컨트롤러는 노드가 (클러스터에서 사라지는 경우나 노드에서 파드가 제거되는 경우 등) 파드가 사라지면, 해당 파드의 복사본을 만든다.
레플리케이션 컨트롤러의 동작
- 실제 파드의 수가 의도하는 수와 일치하는 지 항상 확인한다.(많거나 적으면 추가 혹은 제거)
- 레플리케이션 컨트롤러의 세가지 요소
- 레이블 셀렉터(label selector): 레이블 기반으로 파드를 가지고온다.
- 레플리카 수(replica count): 관리되는 파드의 수
- 파드 템플릿(pod template): 파드에 대한 정보(도커 이미지, 포트, 라벨등)
- 주의 : 레이블 셀렉터와 파드 템플릿을 변경해도 기존 파드에 영향을 미치지 않는다.(삭제 안됨)
- 레플리케이션 컨트롤러 사용 이점
- 기존 파드가 사라지면, 새 파드를 시작해 파드가 항상 실행된다.
- 클러스터 노드가 장애가 발생하면, 장애가 발생한 노드에서 실행중인 모든 파드에 관한 교체 복제본이 생성된다.
- 수동 + 자동으로 파드 쉽게 스케일 아웃가능
레플리케이션 컨트롤러 생성
쿠버네티스 api 서버에 json 또는 yaml 디스크립터를 게시해 레플리케이션컨트롤러를 만든다.
apiVersion: v1
kind : ReplicationController
metadata:
name : kubia # 레플리케이션컨트롤러 이름
spec:
replicas : 3 # 파드 인스턴스 수
selector : # 관리하는 파드 선택
app: kubia
template: # 새 파드에 사용할 파드 템플릿
metadata:
labels:
app:kubia
spec:
containers:
- name: kubia
image: luksa/kubia
ports:
- containerPort: 8080
- 템플릿의 파드 레이블은 레플리케이션 컨트롤러의 레이블 셀렉터와 완전히 일치해야한다.
- (그렇지 않으면 컨트롤러에서 새 파드 무한정 생성할 수있다.)
- 이런 경우를 방지하기 위해 api 서버는 레플리케이션컨트롤러의 정의를 검증하고, 잘못 구성된 경우, 이를 받아들이지 않는다.
- 셀렉터를 지정하지 않으면 자동으로 설정된다.
생성 명령어
$ kubectl create -f kubia-rc.yaml
replicationcontroller "kubia" created
- 레플리케이션 컨츠롤러 작동확인(의도한 파드 인스턴스 3개 생성)
kubectl get pods
NAME READY STATUS RESTARTS AGE
...
- 레플리케이션 컨트롤러 정보 얻기
kubectl get rc
NAME DESIRED CURRENT READY AGE
...
- 레플리케이션 컨트롤러의 세부 정보 표시
kubectl describe rc kubia
세부 정보 표시
- 노드 장애 대응(노드가 여러 개 : 구글 쿠버네티스 엔진일 경우)
- 레플리케이션 컨트롤러는 노드의 파드가 다운됐음을 감지하자마자 파드를 대체하기 위해 새 파드를 기동
- 장애가 발생한 노드는 상태가 NotReady 로 변경되고 새 파드가 하나 생긴다.
- 노드가 다시 부팅되는 경우, 노드가 Ready 상태로 돌아오고 Unknown 상태의 파드는 삭제된다.
- 레플리케이션 컨트롤러는 노드의 파드가 다운됐음을 감지하자마자 파드를 대체하기 위해 새 파드를 기동
레플리케이션 컨트롤러의 범위 안팎으로 파드 이동하기
- 레이블 셀렉터와 일피하는 파드만 관리한다.
- 파드의 레이블을 변경하면 레플리케이션컨트롤러의 범위에서 제거되거나 추가가 가능하다.
파드 템플릿 변경
- 레플리케이션 컨트롤러의 파드 템플릿은 언제든지 수정이 가능하다.
- 레플리케이션 콘트롤의 파드 템플릿을 편집해 컨테이너 이미지를 변경하고, 기존 파드를 삭제함으로써 , 새로운 템플릿을 사용해 기존 파드를 새로운 파드로 교체 가능하다.
(그리 설명 : 레플리케이션컨트롤러의 파드템플릿을 변경하면, 변경 이후에 생성된 파드만 영햐응ㄹ 미치며, 기존 파드는 영향을 밪기 않는다.)
수평파드 스케줄링
레플리케이션 컨트롤러 스케일업, 다운하기
- 방법1
kubectl scale rc kubia --replicas=10
- 방법2
kubectl edit rc kubia # 텍스트 편집기로 spec.replicas 필그 수정
레플리케이션 컨트롤러 삭제
kubectl delete
를 활용한 레플리케이션 컨트롤러 삭제는 파드도 함께 삭제됨- 레플리케이션 컨트롤러만 삭제하고 파드는 실행상태로 두는 방법
kubectl delete rc kubia --cascade=false
4.3. 레플리케이션 컨트롤러 대신 레플리카셋 이용하기
- 초기에는 레플리케이션 컨트롤러가 파드를 복제하고, 노드 장애 발생 시, 재스케줄링하는 유일한 구성요소 였다.
- 추후에, 레플리카셋이라는 유사한 리소스 도입 = 차세대 레플리케이션 컨트롤러
- 초기에 히스토리 및 기존서비스의 유지보수를 위해 레플리케이션 컨트롤러를 설명한다.
- 일반적으로 레플리카셋을 직접 생성하지 않고 , 9장에서 배울 상위 수준의 디플로이먼트 리소스 생성시, 자동으로 생성되게 함
4.3.1. 레플리카셋과 레플리케이션 컨트로럴 비교
- 레플리카셋은 레플리케이션 컨트롤러와 똑같이 동작한다.
- 좀 더 풍부한 표현식을 사용하는 파드 셀렉터를 가지고 있다.
- 특정 레이블이 없는 파드
- 레이블 값과 상관없이 특정 레이블 키를 가지는 파드(env=*)
- 두 파드 세트를 모두 매칭시켜 하나의 그룹 취급 가능 (env=devel, env-production)
4.3.2. 레플리카셋 정의하기
apiVersion: apps/v1beta2
kind: ReplicaSet
... 생략...
spec:
replicas: 3
selector:
matchLabels:
app: kubia
... 생략...
- 적절한 apiVersion 지정 필요
- 셀렉터에 차이가 있다.(selector -> selector.matchLabels)
4.3.3. 레플리카셋 생성 및 검사
kubectl create
명령을 사용해 yaml 파일로 레플리카셋 생성kubectl get rs
로 레플리카셋 검사 가능
4.3.4. 레플리카 셋의 더욱 표현적인 레이블 셀렉터 사용하기
- 레플리카셋의 주요 개선사항은 좀 더 표현적인 셀렉터를 사용할 수 있다.
selector:
matchExpressions:
- key : app
operator: In
values:
- kubia
- 예시
- In : 레이블 값이 지정된 값 중 하나와 일치해야한다.
- NotIn :레이블 값이 지정된 값과 일치하지 않아야한다
- Exists: 파드는 지정된 키를 가진 레이블이 포함돼야한다.
- DoesNotExist : 파드에 지정된 키를 가진 레이블이 포함되지 않아야한다.
- 여러 표현식을 지정하는 경오, 모든 표현식이 true 여야 셀렉터가 파드와 매칭된다.
- matchLabels 와 matchExpressions 를 모두 지정하면, 모든 레이블이 일피하고, 모든 표현식이 true 여야한다.
4.3.5. 레플리카셋 지우기
- 레플리케이션 컨트롤러를 삭제하는 것과 같은 방법으로 레플리카셋을 삭제할 수 있다.
kubectl delete rs kubia
4.4. 데몬셋을 사용해 각 노드에 정확히 한 개의 파드 실행하기
- 레플리케이션 컨트롤러와 레플리카셋은 쿠버네티스 내의 어딘가에 지정된 수의 파드를 실행하는데 사용된다.
- 클러스터의 모든 노드에 노드당 하나의 파드만 실행되기를 원하는 경우가 있을 수 있다.
- 시스템 수준의 작업을 수행해야하는 인프라 관련 파드의 경우
- 로그 수집기, 리소스 모니터, 쿠버 프록시 프로세스
- 시스템 수준의 작업을 수행해야하는 인프라 관련 파드의 경우
- 쿠버네티스를 사용하지 않는 환경에서는 init script , systemd 데몬을 통해 수행된다.
- 데몬셋은 각 노드에서 하나의 파드 복제본만 실행하지만, 레플리카셋은 클러스터 전체에서 무작위로 파드를 분산시킨다.
4.4.1. 데몬셋으로 모든 노드에 파드 실행하기
- 모든 클러스터 노드마다 파드를 하나만 실행하려면, demonSet 오브젝트를 생성해야한다.
- 데몬셋에 의해 생성되는 파드는 타깃 노드가 이미 지정돼있고, 쿠버네티스 스케줄러를 건너뛰는 것을 제외하면, 레플리케이션 컨트롤러와 레플리카셋과 굉장히 유사하다.
- 파드가 클러스터 내에 무작위로 흩어져 배포되지 않는다.
- 레플리카셋은 클러스터에 원하는 수의 파드 복사본이 존재하는지 확인하는 반면, 데몬셋엔 우너하는 복제본 수라는 개념이 없음
- 파드 셀렉터와 일피하는 파드 하나가 각 노드에서 실행중인지 확인
- 노드가 다운되면, 데몬셋은 다른 곳에서 파드를 생성하지 않음
- 새 노드가 클러스터에 추가되면, 데몬 셋은 새 파드 인스턴스를 새 노드에 배포한다.
- 레플리카셋과 마찬가지로 데몬셋은 그 안에 구성된 파드 템플릿으로 파드를 생성한다.
4.4.2. 데몬셋을 사용해 특정 노드에만 파드를 실행하기
- 별도의 지정을 하지 않으면, 데몬셋은 클러스터의 모든 노드에 파드를 배포한다.
- node Selector 속성을 지정하면 된다.(3장과 유사)
- 예제
-
Node selector: disk=ssd
-
- 노드 셀렉터를 가지는 데몬셋을 이요해 특정노드만 시스템 파드 배포하기
- 데몬셋 YAML 정의 생성
- luksa/ssd-monitor컨테이너 이미지를 기반으로 컨테이너를 한 개만 갖는 데몬셋을 정의
- disk=ssd 레이블이 있는 각 노드에 생성
-
apiVersion: apps/v1beta2 kind: DaemonSet metadata: name: ssd-monitor spec: ...생략... template: ...생략... spec: nodeSelector: disk: ssd ...생략...
- 데몬셋 생성
kubectl create -f ssd-monitor-daemonset.yaml
- 필요한 레이블을 노드에 추가하기
kubectl label node nodename dist-ssd
- 노드에 레이블 제거
kubectl label node nodename disk=hdd --overwrite
- 파드 목록 조회해서 확인해보기
kubectl get po
4.5. 완료 가능한 단일 태스크를 수행하는 파드 실행
- 작업 완료 후, 종료되는 태스크만실행하는 경우가 있다.
- 레플리케이션 컨트로럴, 레플리카셋, 데몬셋은 지속적인 태스크를 실행한다.
4.5.1. 잡 리소스 소개
- 쿠버네티스는 job 리소스를 통해 해당 기능을 지원한다.
- 4장에서 논의된 다른 리소스와 유사하지만, 파드의 컨테이너의 내부에서 실행중인 프로세스가 성공적으로 완료되면, 컨테이너를 다시 시작하지 않는다,
- 그렇게 되면, 파드는 완료된 것으로 간주된다.
- 장애가 발생한 경우
- 노드 : 해당 노드에 있던 잡이 관리하는 파드는 레플리카셋 파드와 같은 방식으로 다른 노드로 다시 스케줄링 된다.
- 프로세스 : job 에서 컨테이너를 다시 시작할 것인지 설정 가능
- job 리소스는 작업이 제대로 완료되는 것이 중요한 임시 작업에 유용하다.
- 예. 데이터를 어디엔가 저장하고 있고, 데이터를 변환해 어딘가 전송해야하는 경우
4.5.2. 잡 리소스 정의
apiVersion : batch/v1
kind : Job
metadata:
name : batch-job
spec:
template:
metadata:
labels:
app: batch-job
spec:
restartPolicy : OnFailure
containes:
- name: main
image:luksa/batch
- luksa.batch-job 이미지를 실행할 잡 유형의 리소스를 정의
- 파드 스펙에서는 컨테이너에서 실행중인 프로세스가 종료될 때, 쿠버네티스가 수행할 작업 지정 가능
- 예시는 restartPolicy 로 수행되며, 잡 파드는 무한정 실행하지 않으므로 OnFailure나 Never로 명시적으로 설정해야함
4.5.3. 파드로 실행한 잡 보기
kubectl get jobs
kubectl get po -a
- 해당 파드의 로그 검사
kubectl logs batch-job-28qf4
4.5.4. 잡에서 여러 파드 인스턴스 실행하기
예. https://greencloud33.tistory.com/25
- 잡은 두 개 이상의 파드 인스턴스를 생성해, 병렬 또는 순차적으로 실행할 수 있다
- job spec 의 completions와 parallelism 속성 설정해야함
- completions: 순차적으로 잡 파드 실행
- 완료된 pod 후에 새로운 pod를 생성하여 결과적으로는 연속적으로 5개의 pod를 실행하도록 한다.
-
...생략... spec: completions: 5 ...생략...
- 병렬로 Pod 실행하기
- parallelism : 여러 job이 병렬로 실행되도록 한다.
- completion을 5로 하여 총 5개의 pod를 완료하도록 설정했으며,
- 한번에 두 개까지 병렬로 실행할 수 있다.
apiVersion: batch/v1 kind: Job metadata: name: multi-completion-batch-job spec: completions: 5 parallelism: 2
- job 스케줄링
- job 실행 도중에, parallelism 속성을 변경할 수 있다.
kubectl scale job multi-completion-batch-job --replicas 3
4.5.5. JOB 파드가 완료되는데 걸리는 시간 이해하기
- pod spec 에
activeDeadlineSeconds
속성을 설정해 파드의 실행 시간을 제한 가능하다.
4.6. job 주기적으로, 또는 한 번 실행되게 스케줄링 하기
- 많은 배치 잡들이 특정 시간, 지정된 간격으로 반복 실행해야한다.
- 리눅스에서 cron
- 쿠버네티스에서는 cronjob 리소스를 만들어 구상한다.
4.6.1. 크론잡 생성하기
apiVersion: batch/v1beta1
kind : CronJob
metadata:
name: batch-job-every-fifteen-minutes
spec:
schedule: "0,15,30,45 * * * *"
jobTemplete:
...생략...
- 스케줄 설정하기
- 분 시 일 월 요일
4.6.2. 스케줄된 잡의 실행방법
- job resource 는 대략 예정된 시각에 크론잡 리소스에서 생성된다. (그 때, 잡은 파드를 생성한다.)
- 예정된 시간을 너무 초과해 시작하면 안되는 경우, 크론잡 스펙에 startingDeadlineSeconds 필드를 지정해 데드라인 지정이 가능하다.
반응형
'독후감' 카테고리의 다른 글
쿠버네티스 인 액션 5장. 서비스 (0) | 2022.02.21 |
---|---|
쿠버네티스 패턴 4장. 정상 상태 점검 (0) | 2022.02.15 |
The Google File System 논문 정리 (0) | 2022.02.11 |
쿠버네티스 인 액션 3장 정리 (0) | 2022.02.07 |
쿠버네티스인액션 2장정리 (0) | 2022.01.24 |