쿠버네티스 2일차
3.5 파드의 생명주기와 프로브
파드는 정의된 순서대로 생명주기를 가짐(pending >>> running >>> succeeded 또는 failed
쿠버테니스 노드의 구성 요소인 kubelet은 파드의 컨테이너 상태를 추적하고, 오류가 발생사면 정상상태로 만들기 위한 조치로 컨테이너를 재시작할 수도 있음!!!
파드는 최소 생성시 한 번만 스케줄링 됨, 특정 노드에 할당되면 파드는 중지되거나 종료될 때까지 항상 같은 노드에서 실행됨
1) 파드의 생명주기
파드는 임시로 사용하기 위한 워크로드 리소스이다. 파드가 생성시 파드를 식별하기 위한 고유의 uid가 할당되고, 종료될 때까지 특정 노드에서만 실행된다!!!
쿠버네티스는 파드를 일회용으로 간주하며, 상위 레벨의 추상화 리소스인 컨트롤러 리소스를 이용하여 파드를 관리한다!!!
(1) 파드의 단계 확인
kubectl get pod myapp-pod-annotation -o jsonpath='{.status.phase}'

(2) 파드의 단계
- pending : 파드가 클러스터에서 승인되었지만, 실행되고 있지 않음, 파드가 스케줄링되기 전, 이미지 풀링
- running : 파드가 노드에 할됭됨, 하나 이상의 컨테니어가 실행중, 시작 또는 재시작 중
- succeeded : 모든 컨테이너가 정상적으로 종료, 재시작되지 않음
- failed : 모든 컨테이너가 종료, 하나 이상의 컨테이너가 실패로 종료
- unknown : 알 수 없음, 일반적으로 노드와의 통신 오류
2) 컨테이너 상태
스케줄러가 파드를 특정 노드에 할당하면, kubelet은 컨테이너 런타임을 이용해 컨테이너를 생성하며, kubelet은 컨테이너의 상태를 주기적으로 모니터링 한다!!!
(1) 컨테이너 상태 확인
kubelet은 파드의 단계뿐만 아닌 각 컨테이너의 상태도 모니터링 한다!!!
kubectl get pod myapp-pod-annotation -o jsonpath='{.status.containerStatuses[*].state}'

(2) 컨테이너 상태
- waiting : 컨테이너가 running 또는 terminates 상태가 아닌 상태, 컨테이너 시작 전 필요한 작업 중(이미지 풀링, 스토리지 연결), reason 필드에 이유가 표시됨
- running : 실행중, 해당 상태가 된 시각 표시
- terminated : 컨테이너 실행이 완료됨, 실패, reason 필드에 이유가 표시됨, 해당 상태가 된 시각 표시
3) 컨테이너 재시작 정책
모든 컨테이너는 컨테이너의 오류 발생 시 재시작을 하기 위한 재시작 정책을 가지고 있다!!!
.spec.restartPolicy 재시작 정책
- Always : 종료/실패 시 항상 재시작
- onfailure : 실패 시 재시작( 정상 종료 시 재시작하지 않음)
- never : 재시작 하지 않음
4장 워크로드 - 워크로드 리소스
4.1 레플리케이션 컨트롤러
쿠버네티스 컨트롤러는 파드를 올바르게 동작하기 위해 특정 상태를 보장하기 위해 노력함. 특정 상태는 컨트롤러에 따라 파드를 제어하는 방식 및 정의하는 상태가 조금식 다르다
1) 레플리케이션 컨트롤러
파드가 특정 개수만큼 복제되고 동작하는 것을 보장한다!!
실행중인 파드의 목록을 주기적으로 모니터링하고, 원하는 수의 파드수와 항상 일치시킨다!!!
레플리케이션 컨트롤러 생성
vim myapp-rc.yaml

selector.app 와 labels.app 는 같아야됨 myapp-rc로 같음
매핑을 해준다 중요!!!
kubectl get pods로 확인!!!

3) 레플리케이션 컨트롤러 확인

원하는 복제본의 개수를 3개이고, 현재 존재하는 파드는 3개, 준비된 파드도 3개라고 출력하고 있다.
파드에 구성된 레이블을 같이 살펴보자.

4) 레플리케이션 컨트롤러와 파드
레플리케이션 컨트롤러에서 노드의 장애 발생을 가정하고 파드를 삭제했을 때 어떻게 되는지 확인해보자!!!
kubectl delete pod myapp-rc-w68lh
그리고 파드 목록을 확인해보면

myapp-rc-w68lh 파드가 삭제되고 myapp-rc-5d8w7 파드가 생성되었다!!! 레플리케이션 컨트롤러는 레이블 셀렉터에 의해 관리되는 파드를 확인하고 있다가, 하나의 파드가 삭제 된것을 확인하고, 파드의 복제본 수와 맞추기 위해 하나의 파드를 새롭게 생성한 것임
레플리케이션 컨트롤러의 자세한 정보를 확인해보면 정확하게 어떤 파드가 생성되었는지 확인할 수 있다.
kubectl describe replicationcontrollers myapp-rc

5) 레플리케이션 컨트롤러와 레이블
레플리케이션 컨트롤러는 관리할 파드를 파드의 레이블과 레플리케이션 컨트롤러의 레이블 셀렉터를 이용하여, 관리할 파드를 지정하고 관리하게 된다.
(1) 기존 파드에 레이블 추가
기존 파드의 레이블을 추가하면 어떻게 될지 살펴보자. 우선 파드의 목록 및 레이블을 확인
kubectl get pods --show-labels

myapp-rc-f9mv7 파드에 env=dev 레이블을 추가해 보자
kubectl label pod myapp-rc-f9mv7 env=dev
다시 파드 목록을 확인해보자!!

기존의 파드에 추가 레이블만 구성되었고 변경된 사항은 없음...
(2) 기존 파드의 레이블 변경
그러면 기존 파드의 레이블을 변경해 보자, 즉 app=myapp-rc를 다른 레이블로 변경하면 어떤 결과가 발생하는지 확인해보자
myapp-rc-f9mv7 파드의 app 레이블의 값을 test로 변경해보자.
kubectl label pod myapp-rc-f9mv7 app=test --overwrite
파드 목록 확인

myapp-rc-f9mv7 파드의 레이블을 app=test로 변경한 이후, 레플이케이션 컨트롤러는 app=myapp-rc 레이블을 가진 파드가 두 개 밖에 없기 때문에 새로운 파드를 생성했다!!!
즉, myapp-rc-f9mv7 파드는 더이상 myapp-rc 레플리케이션 컨트롤러가 관리하는 파드가 아니다!!!
다시 원래대로 myapp-rc-f9mv7 파드의 레이블을 app=myapp-rc로 변경해 보자
kubectl label pod myapp-rc-f9mv7 app=myapp-rc --overwrite
다시 파드 목록 확인

myapp-rc-f9mv7 파드의 레이블이 원래대로 app=myapp-rc로 변경되었기 떄문에, myapp-rc 레플리케이션 컨트롤러의 관리 파드로 지정되었다. 그러나 레플리케이션 컨트롤러는 관리할 파드가 네 개가 되었으니, 파드 하나를 삭제했음!!
6) 파드의 수평 스케일링
레플리케이션 컨트롤러의 복제본 수만큼 파드를 만들고 관리한다는 것을 확인하였음, 그러면 복제본 수를 변경하여 수평 스케일링을 해보자!!!
(1) 명령을 이용한 스케일링
kubectl scale replicationcontroller myapp-rc --replicas=4 >>> 복제본 개수를 4개로 스케일링
kubectl get replicationcontrollers >>> myapp-rc 레플리케이션 컨트롤러의 상태를 확인

kubectl get pods >>> 파드의 목록을 확인해보자

파드가 추가로 하나더 생성된것을 확인!!!
(2) 오브젝트 수정을 이용한 스케일링
kubectl edit replicationcontrollers myapp-rc
spec.replicas 필드를 찾아서 값을 변경한다

kubectl get replicationcontrollers >>> myapp-rc 레플리케이션 컨트롤러의 상태를 확인해보자

kubectl get pods로 확인해보기

(3) 오브젝트 파일 수정을 이용한 스케일링
yaml 파일을 수정한 것은 아니기 때문에 yaml 파일 내의 복제본 수는 세 개로 정의되어 있다.
kubectl replace -f myapp-rc.yaml
7) 레플리케이션 컨트롤러 및 파드 삭제
컨트롤러에 의해 관리되는 파드들은 파드 자체를 삭제하더라도 복제본 조건에 따라 다시 생성하게 된다. 그래서 파드를 삭제하면 안 되고, 컨트롤러를 직접 삭제해야 컨트롤러에 의해 관리되는 파드도 같이 삭제가 됨
컨트롤러 삭제 명령어
kubectl delete replicationcontrollers myapp-rc
레플리케이션 컨트롤러의 상태를 확인
kubectl get replicationcontrollers
파드의 목록을 확인
kubectl get pods

4.2 레플리카셋
레플리케이션 컨트롤러의 몇몇 문제점 및 기능 개선을 위해 레플리카셋 이라는 컨트롤러를 추가하였다
레플리카셋은 레플리케이션 컨트롤러가 제공하는 기능과 거의 비슷하다. 기본적으로 요구하는 복제본 개수만큼 파드를 복제하고 모니터링하고 관리한다.
현재는 레플리케이션 컨트롤러보다 레플라카셋 또는 디플로이먼트를 사용하는 것을 권장한다
2) 레플리카셋과 레플리케이션 컨트롤러의 비교
레플리케이션 컨트롤러 : 일치성 기준 레이블 셀렉터 지원
레플리카셋 : 일치성 및 집합성 기준 레이블 셀렉터 지원
스크린샷, 2023-07-04 12-06-35
3) 레플리케이션 생성
지금까지 생성한 오브젝트의 api버전은 v1이었지만, 지금 생성하는 레플리카셋은 apps/v1 api를 사용한다!!!

레플리카셋은 matchLabels 및 matchExpressions 필드로 레이블을 선택한다.
.spec.selector.matchLabels : 일치성 기준 레이블 셀렉터 지정
.spec.selector.matchExpresssions : 집합성 기준 레이블 셀렉터 지정
4) matchExpressions를 사용한 레플리카셋 생성
vim myapp-rs-exp.yaml

4.2 레플리카셋
kubectl create -f myapp-rs-exp.yaml >>> 레플리케이션 실행 명령어
5) 레플리카셋 확인
kubectl get replicasets.apps -o wide

레플리카셋 컨트롤러에 의해 생성된 파드의 목록을 확인한다
kubectl get pods --show-labels

kubectl get pods -l k8s-app=nodelocaldns -n kube-system -o jsonpath='{.item[*].spec.containers[*].args[*]}'
결론은 레플리카셋을 정리하면 레플리케이션 컨트롤러와 기능이 같지만, 집합성 기반의 레이블을 지원한다!!!!
6) 레플리카셋 삭제
kubectl delete replicasets.apps myapp-rs-exp >>> 레플키 카셋을 삭제한다!!!
4.3 데몬셋(복제본 제공하지 않음)
노드 레이블과 매칭이 되는 모든 노드 또는 노드 레이블이 없다면 모든 노드에 파드를 하나씩 배치하는 컨트롤러이다.
기능은 레플리카셋과 비슷함, but 복제본을 지정하지 않음. 당연하게도 모든 노드에 하나씩의 파드만을 배치하게 떄문이다.
ds(데몬셋) 은 모든 노드에 하나씩 배치시키는것!! 절대 같은 노드에 배치 시키지 않음!!!
컨트롤 플레인에는 데몬셋이 배치되지 않도록 막혀있음!!
2) 데몬셋 생성
메몬셋 api버전 확인
kubectl api-resources | grep daemonset

vim myapp-ds.yaml

.sepc.template.spec.nodeSelector : 노드 레이블 셀렉터, 파드를 특정 노드에 배치
데몬셋 오브젝트를 생성해보자
kubectl create -f myapp-ds.yaml
3) 데몬셋 확인
생성한 데몬셋을 확인
kubectl get daemonsets.apps

DESIRED, CURRENT, READY 가 0 인 것을 알 수 있다. 당연하게도 파드는 생성되지 않는다.
이유는 오브젝트 정의에 노드셀렉터로 node = development 레이블을 선택하도록 정의했음 이 때문에 노드 레이블과 매칭되는 노드가 없기 떄문에 아무 파드를 생성하지 않는다
노드 레이블을 확인하기 위해 --show-labels 옵션을 사용하면 노드에 설정된 레이블을 확인할 수 있다
kubectl get nodes --show-labels
4) 노드 레이블 지정
생성한 데몬셋 오브젝트가 파드를 생성하기 위해 노드에 레이블 추가로 지정해 보자 추가할 레이블은 오브젝트에 정의한 node=development 레이블이다.
kubectl label nodes kube-node1 node=development
kubectl get node kube-node1 --show-labels >>> 추가한 노드 레이블을 확인해보자

5) 데몬셋 확인
kubectl get damonsets.apps

파드가 실행된 것을 확인할 수 있다.
파드 목록도 확인
kubectl get pods

6) 노드 레이블 제거
노드 레이블을 제거하여 데몬셋이 실행되는 파드를 제거할 수 있다. 레이블 제거는 레이블의 값을 제거할 수도 있고, 레이블의 키를 제거할 수도 있다. 키를 제거한다는 것은 값도 제거된다는 의미임
(1) 노드 레이블 값 제거
kubectl label node kube-node1 node='' --overwrite >>> kube-node1 노드의 node 레이블의 값을 제거한다.
kube-node1의 노드 레이블의 값을 제거

(2) 노드 레이블 키 제거
kubectl label nodes kube-node1 node-
노드 레이블을 확인해본다.

node=development 레이블이 삭제되었다.
둘 다 모든 경우 노드 레이블 셀렉터와 매칭이 되지 않기 떄문에 파드는 제거된다.
kubectl get daemonsets.apps

7) 데몬셋 삭제
생성한 데몬셋 컨트롤러를 삭제한다
kubectl delete -f myapp-ds.yaml
4.4 잡
잡 컨트롤러는 파드의 애플리케이션의 실행이 완료/종료되는 것에 초점을 맞춘 컨트롤러이다.
레플리케이션 컨트롤러, 레플리카셋, 데몬셋은 파드의 애플리케이션이 계속적으로 잘 동작하는 것을 초점을 맞춘 것에 대비된다. 즉, 애플리케이션이 실행되고 실행이 완료되면 파드의 할 일이 끝난 것으로 간주하고 파드를 종료시킨다.
잡 컨트롤러는 임시(ad-hoc) 작업 및 배치 작업에 유용하게 사용될 수 있다.
만약 애플리케이션이 실행되고 있는 중에 노드가 죽거나 파드의 실행이 완료되지 않았다면, 파드를 다시 스케줄링하여 재실행하게 구성할 수 있다.
2) 잡 컨트롤러의 레이블 셀렉터
지금까지 확인했던 컨트롤러와 다르게, 잡/크론잡 컨트롤러는 일반적으로 파드 레이블 셀렉터(.spec.selector)를 직접 지정해 사용하지 않는다.
클러스터가 잡/크론잡 컨트롤러를 생성할 떄 컨트롤러에 부여된 uid 기반의 레이블을 셀렉터로 사용한다!!!
레이블 셀렉터를 사용하지 않는 이유는, 셀렉터에 의해 관련 없는 파드가 선택되어 잡이 이미 실행되고 있다고 판단하거나, 잡이 이미 완료되었다고 판단해 잡을 삭제하는 경우 등 예상치 못한 결과를 발생할 수 있기 때문이다!!!
3) 잡 컨트롤러 생성

잡 오브젝트의 api는 batch 그룹의 v1 버전을 사용한다!!!
vim myapp-job.yaml

잡 컨트롤러는 레플리케이션 컨트롤러, 레플리카셋, 데몬셋처럼 계속 동작하는 방식이 아니기 떄문에, 재시작 정책(restartPolicy)을 기본값이 always가 아닌 onfailure 또는 Never로 명시적으로 선언해야 한다. 즉, 잡 컨트롤러의 파드 오브젝트는 재실행하지 않는다.
job.spec.template.spec.restartPolicy 재지작 정책:
- always : (기본값) 종료/실패 시 항상 재시작
- onfailure : 실패 시 재시작 (정상 종료 시 재시작하지 않음)
- never : 종료 또는 오류 시 절대 재시작 하지 않음
이미지는 perl 이미지를 사용하였고, 원주율(파이) 값을 소수점 1000자리 까지 계산하도록 하는 명령이 실행되도록 구성하였음, 즉 원주율을 소수점 1000자리까지 계산하면 애플리케이션이 완료된다!!
잡 오브젝트를 생성해보자
kubectl create -f myapp-job.yaml
4) 잡 컨트롤러 및 파드 확인
kubectl get jobs.batch 명령으로 잡 상태를 확인

하나의 파드가 있고 아직 잡이 완료되지 않았다는 의미
시간이 지난후 파드 상태를 다시 확인해보면

잡이 완료된 것을 확인할 수 있다.
kubectl get pods

파드의 상태가 완료됨 상태로 보고하고 있다. 실행중인 상태가 아님!!!!!
5) 잡 컨트롤러 삭제
완료된 잡 컨트롤러를 삭제한다
kubectl delete -f myapp-job.yaml
4.5 크론잡
잡 컨트롤러는 잡이 한 번만 실행이 되지만 크론잡 컨트롤러는 주기적으로 잡을 반복적으로 실행할 필요가 있을 때 사용하는 컨트롤러이다.