(공식문서)
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/
(한국어 버전)
https://kubernetes.io/ko/docs/concepts/workloads/pods/pod-lifecycle/
파드는 정의된 라이프사이클을 따른다. Pending 단계에서 시작해서, 기본 컨테이너 중 적어도 하나 이상이 OK로 시작하면 Running단계를 통과하고, 그런 다음 파드의 컨테이너가 실패로 종료되었는지 여부에 따라 Succeeded 또는 Failed 단계로 이동한다.
파드가 실행되는 동안 kubelet은 일종의 오류를 처리하기 위해 컨테이너를 다시 시작할 수 있다. 파드 내에서, 쿠버네티스는 다양한 컨테이너 상태를 추적하고 파드를 다시 정상 상태로 만들기 위해 취할 조치를 결정한다.
파드가 노드에 스케줄되면, 파드는 중지되거나 종료될 때까지 해당 노드에서 실행된다.
파드의 수명 (Pod lifetime)
개별 응용 프로그램 컨테이너와 마찬가지로, 파드는 비교적 짧은 지속 시간을 갖는 일시적인 엔티티이다. 파드는 생성되어 고유한 식별자(UID)가 할당되며, 노드에 스케줄되어 종료되거나 삭제될 때까지 해당 노드에 남아있는다. 만약 노드가 다운되면 해당 노드에 스케줄된 파드는 일정 시간이 지난 후 삭제된다.
파드는 스스로 치유되지 않는다. 만약 파드가 노드에 스케줄되었다가 해당 노드가 실패하는 경우, 해당 파드는 삭제된다. 쿠버네티스는 파드 인스턴스를 관리하는 작업을 처리하는 고수준 추상화인 컨트롤러를 사용한다.
UID로 정의된 특정 파드는 다른 노드로 재스케줄 되지 않는다. 대신 해당 파드는 새로운 거의 동일한 파드로 대체될 수 있으며, 필요한 경우 같은 이름으로 생성될 수 있다. 그러나 UID는 달라진다.
볼륨과 같은 어떤 것이 파드와 동일한 수명을 갖는다는 것은, 특정 파드가 존재하는 한 그것이 존재함을 의미한다. 해당 파드가 삭제되고, 동일한 대체 파드가 생성되더라도 관련된 볼륨도 폐기되고 새로 생성된다.
파드의 탄생 (Birth of a Pod)
- 파드 사양을 API 서버에 제출한다.
- API 서버는 파드를 etcd 저장소에 기록한다.
- API 서버는 etcd의 상태 변화를 반영한다.
- 모든 쿠버네티스 컴포넌트들은 API 서버 변경사항을 계속 watch 한다.
- kube-scheduler는 API 서버에 새로운 파드가 생성되었지만 어떤 노드에도 바인딩 되지 않은 것을 확인한다.
- kube-scheduler는 파드에 노드를 할당하고 API 서버를 업데이트 한다.
- 이 변경 사항을 etcd로 전파된다.
- 모든 노드의 kubelet은 API 서버를 계속 감시한다. 대상 노드의 kubelet은 새 파드가 할당된 것을 확인한다.
- kubelet은 docker를 호출하여 해당 노드에서 파드를 시작하고 컨테이너 상태를 다시 API 서버로 업데이트 한다.
- API 서버는 파드 상태를 etcd 전달한다.
- etcd가 상태 쓰기에 성공에 대한 확인을 전송하면 API 서버는 이벤트가 수락되었음을 나타내는 확인을 kubelet에 다시 전송한다.
각 컴포넌트의 책임
- API Server: 유저나 다른 컴포넌트의 명령을 받아 object를 관리 (CRUD)
- Controller Manager: 새로운 Controller를 감지하고 이를 처리
- Deployment Controller -> ReplicaSet Controller
- ReplicaSet Controller -> new unbound Pods
- Scheduler: unbound Pods를 감지하고 이를 처리
- unbound Pods -> bound Pods
- kubelet: bound Pods를 감지하고 실제로 Pod를 띄움
파드가 살아있는 동안의 활동 (Activities during pod’s life)
Init Containers
Init Containers는 기본 애플리케이션 컨테이너가 시작되기 전에 실행되는 컨테이너이다.
Init Containers는 파드의 기본 컨테이너가 시작되기 전에 일부 초기화 작업을 실행해야 하는 경우에 유용하다.
Lifecycle Hooks
kubelet은 Container Lifecycle Hooks. 에 의해 트리거된 코드를 실행할 수 있다. 이를 통해 사용자는 컨테이너 수명 주기의 특정 이벤트 중에 특정 코드를 실행할 수 있다. (예를들면, 컨테이너가 종료되기 전에 정상적인 종료 스크립트를 실행하도록 설정할 수 있다.)
컨테이너에 노출되는 2가지 훅이 있다.
- PostStart - 이 훅은 컨테이너가 생성된 직후에 실행된다. 그러나 컨테이너 ENTRYPOINT 이전에 실행된다는 보장은 없다.
- PreStop - 이 훅은 컨테이너가 종료되기 직전에 호출된다. 컨테이너가 이미 종료 또는 완료상태인 경우 PreStop훅은 실패한다. 컨테이너를 중지하는 TERM 신호를 보내기 전에 훅이 완료되어야 한다.
컨테이너는 해당 훅에 대한 핸들러를 구현하고 등록하여 훅에 액세스할 수 있다. 컨테이너에 대해 구현할 수 있는 두 가지 유형의 훅 핸들러가 있다.
- Exec - 컨테이너의 cgroups 및 namespace 내에서 pre-stop.sh과 같은 특정 명령을 실행한다.
- HTTP - 특정 엔드포인트에 대한 HTTP 요청을 실행한다.
Container Probes
lifecycle hook과는 별개로 파드가 살아있는 동안 발생하는 또 다른 중요한 일은 컨테이너 프로브(container probes) 실행이다.
컨테이너 프로브는 컨테이너에서 kubelet이 수행하는 진단이다. 실행중인 컨테이너에 kubelet이 실행할 수 있는 프로브에는 두 가지 종류가 있다.
- livenessProbe
- 컨테이너가 실행 중인지 여부를 나타낸다.
- liveness probe가 실패하면 kubelet은 컨테이너를 종료하고 컨테이너는 Restart Policy 정책의 적용을 받는다.
- 이를 통해 시스템의 다른 부분에 문제를 일으키지 않고 문제가 있는 컨테이너를 다시 시작할 수 있다.
- readinessProbe
- 컨테이너가 요청을 처리할 준비가 되었는지 나타낸다.
- 프로브가 실패하면, 엔드포인트 컨트롤러는 파드와 일치하는 모든 서비스의 엔드포인트 목록에서 컨테이너 IP를 제거한다. (기본적으로 재시작 X)
프로브를 구현하는 세 가지 방법이 있다.
- ExecAction - 컨테이너 내부에서 명령을 실행한다. 명령이 0을 반환하면 진단이 성공한 것으로 간주된다.
- TCPSocketAction - 컨테이너 IP 및 지정된 포트에 대해 TCP 소켓 검사를 수행한다. 포트가 열려있으면 진단이 성공한 것으로 간주된다.
- HTTPGetAction - 지정된 포트 및 경로를 사용하여 컨테이너 IP에 대해 HTTP GET 작업을 실행한다. 응답에 200에서 400사이의 상태 코드가 있으면 진단이 성공한 것으로 간주된다.
Termination of a Pod
- 파드 삭제 명령어를 보낸다.
- API 서버를 통해 파드 객체는 죽은것으로 간주되는 유예시간(기본 30초)을 업데이트 된다.
- 아래 작업이 병렬로 발생한다.
- 파드는 Terminating 으로 표시된다.
- kubelet은 파드가 종료된 것으로 표시되었음을 확인하면 파드 종료 프로세스를 시작한다.
- 엔드포인트 컨트롤러는 파드가 삭제될 예정임을 감시하고 파드가 서비스하는 모든 엔드포인트에서 파드를 제거한다.
- 파드가 preStop훅을 정의한 경우 파드 내부에서 호출된다.
- 파드의 프로세스는 TERM 신호를 받는다.
- 유예기간(grace period)이 만료되면 파드에서 아직 실행중인 모든 프로세스는 SIGKILL로 종료된다.
- kubelet은 유예기간을 0(즉시삭제)으로 설정하여 API 서버에서 파드 삭제를 완료한다. 파드가 API에서 사라지고 클라이언트에서 더이상 표시되지 않는다.
Liveness / Readiness Probe 실습
Liveness Test
- probe-test.yaml 파일의 27번 line의 값을 / → /none_exist 로 변경하고 배포한다.
- READY = 1/1로 표시되고 localhost:30124로 접근도 가능하지만, 약 60초가 지나면 RESTART 되는 것을 확인할 수 있다.
- livenessProbe에 성공하지 않으면 scheduler는 계속해서 이 pod를 재실행한다.
# probe-test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: probe-test
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /
port: 80
periodSeconds: 10
livenessProbe:
httpGet:
path: /none_exist #이 부분이 포인트
port: 80
periodSeconds: 10
env:
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
command: ["/bin/sh"]
args: ["-c", "echo $POD_IP both probe work normally > /usr/share/nginx/html/index.html && nginx -g 'daemon off;'"]
---
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
selector:
app: nginx
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30124
Readiness Test
- 시간이 지나도 READY = 0/1로 유지되지만 RESTARTS는 0으로 유지된다.
- 재시작 되지 않고, application이 준비되지 않은채로 유지된다.
# probe-test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: probe-test
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /none_exist #이 부분이 포인트
port: 80
periodSeconds: 10
livenessProbe:
httpGet:
path: /
port: 80
periodSeconds: 10
env:
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
command: ["/bin/sh"]
args: ["-c", "echo $POD_IP both probe work normally > /usr/share/nginx/html/index.html && nginx -g 'daemon off;'"]
---
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
selector:
app: nginx
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30124
참고
'클라우드 > Kubernetes(쿠버네티스)' 카테고리의 다른 글
[쿠버네티스] 클러스터 구축 (0) | 2024.06.08 |
---|---|
[kubernetes] kubernetes의 update 종류와 동작 방법 (apply, edit, patch, replace) (0) | 2023.08.18 |
[kubernetes] kube-proxy (0) | 2023.08.03 |
[kubernetes] Kubernetes Networking Model (0) | 2023.08.03 |
[kubernetes] mac m1 kubernetes 구축 (2) | 2022.07.31 |