🔠 쿠버네티스에서 컨테이너를 관리하는 기본단위 (하나 이상의 컨테이너의 그룹)
쿠버네티스는 실제로 파드라는 단위로 컨테이너를 묶어서 관리한다.
파드로 컨테이너 여러 개를 한꺼번에 관리할 때는 컨테이너마다 역할을 부여할 수 있다.
파드 하나에 속한 컨테이너들은 모두 노드 하나 안에서 실행
pod lifecycle
🔠 파드는 생성부터 삭제까지의 과정에 생명 주기가 있다.
- pending : 쿠버네티스 시스템에 파드를 생성하는 중
컨테이너 이미지를 다운로드 한 후 전체 컨테이너를 실행하는 단계 - Running : 파드 안 모든 컨테이너가 실행 중인 상태
1개 이상의 컨테이너가 실행 중이거나 시작 또는 재시작 상태 - Succeeded : 파드 안 모든 컨테이너가 정상 실행 종료된 상태로 재시작 되지 않습니다.
- Failed : 파드 안 모든 컨테이너 중 정상적으로 실행 종료되지 않은 컨테이너가 있는 상태
컨테이너 종료 코드가 0이 아니면 비정상 종료 이거나 시스템이 직접 컨테이너를 종료 - Unknown : 파드의 상태를 확인할 수 없는 상태
보통 파드가 있는 노드와 통신할 수 없을때
# 아래 처럼 STATUS 부분에서 확인 할수 있으며 -w 옵션을 줘서 실시간으로 확인이 가능하다.
$ kubectl get pod -w
NAME READY STATUS RESTARTS AGE
cozserver-deployment-5cc4cd8d69-4krsb 1/1 Running 1 (5h10m ago) 29h
cozserver-deployment-5cc4cd8d69-7l974 1/1 Running 1 (5h10m ago) 29h
hello-minikube-84bcf5d5d8-rwvjg 1/1 Running 2 (5h10m ago) 2d6h
kubernetes-bootcamp-5485cc6795-bzx9v 1/1 Running 2 (5h10m ago) 2d4h
pod condition
🔠 pod의 현재 상태 정보
- Initialized : 모든 초기화 컨테이너가 성공적으로 시작 완료
- Ready : pod는 요청들을 실행할 수 있고 연결된 모든 서비스의 로드밸런싱 풀에 추가되어야 한다.
- ContainersReady : pod안 모든 컨테이너가 준비 상태
- PodScheduled : pod가 하나의 노드로 스케줄을 완료
- Unschedulable : 스케줄러가 자원의 부족이나 다른 제약 등으로 지금 당장 파드를 스케줄 할 수 없다
$ kubectl describe pods cozserver-deployment
Name: cozserver-deployment-5cc4cd8d69-4krsb
Namespace: default
Priority: 0
Service Account: default
Node: minikube/192.168.49.2
Start Time: Fri, 19 May 2023 13:39:08 +0900
Labels: app=nginx
. . .
. . .
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-scgfs:
. . .
. . .
Container
pod는 앱들을 실행하는 다수의 container를 포함할 수 있고 container 실행 전에 동작되는 하나 이상의 init container 도 포함 할 수 있다.
Init Container
App Container가 실행되기 전 pod를 초기화합니다. 보안상 이유로 앱 컨테이너 이미지와 같이 두면 안되는 앱의 소스 코드를 별도로 관리할 때 유용합니다.
- init container는 여러 개를 구성 가능
init container 가 여러 개 있다면 pod template 에 명시한 순서대로 init container 가 실행됩니다. - init container 실행이 실패하면 성공할 때까지 재시작
(Kubernetes의 ‘선언적’ 특징에서 벗어날 수 있습니다. 즉, 필요한 명령들을 순서대로 실행하는 데 사용하는 것) - init container가 모두 실행된 후 App Container 실행이 시작
- readinessProbe를 지원하지 않음
💡 이러한 특징을 이용하면 pod 를 실행할 때 App Container가 외부의 특정 조건을 만족할 때까지 기다렸다가 실행하도록 만들 수 있습니다.
# init container example
apiVersion: v1
kind: Pod
metadata:
name: simple-pod
labels:
app: simple-pod
spec:
initContainers:
- name: init-myservice
image: hello-world:latest
command: ['sh', '-c', 'sleep 2; echo helloworld01;']
- name: init-mydb
image: hello-world:latest
command: ['sh', '-c', 'sleep 2; echo helloworld02;']
containers:
- name: simple-pod
image: hello-world:latest
command: ['sh', '-c', 'echo app is running && sleep 3600;']
Pause Container
모든 pod에서 항상 실행되는 pause container가 있습니다. 이 pause를 pod infrastructure container
라고 합니다.
PID가 1로 설정되므로 다른 container의 부모 container 역할을 합니다.
pod 안 다른 container 는 pause container 가 제공하는 네트워크를 공유해서 사용합니다.
그래서 pod 안 다른 container가 재시작 됐을 때는 pod의 IP를 유지하지만 pause container가 재시작 되면 pod 안 모든 container도 재시작 합니다.
Static Pod
- kube-apiserver를 통하지 않고 kubelet이 직접 실행하는 pod
- static pod는 kubelet이 직접 관리하면서 이상이 생기면 재시작
- kubelet이 실행중인 node에서만 실행되고 다른 node에서는 실행되지 않음
- kube-apiserver로 pod를 조회할 수 있지만 static pod에 어떤 명령 실행 불가
- 보통 kube-apiserver라던가 etcd 같은 system pod를 실행하는 용도로 사용
Pod Resource
여러 개 작은 process를 실행하면 한 node에 여러 pod를 실행하는 일이 있습니다.
이때 자원 사용량이 많은 pod가 한 node에 모여 있다면 pod들의 성능이 나빠지며 전체 cluster의 자원 사용 효율도 낮아지게 됩니다.
예를 들어 어떤 node에는 pod가 없어서 CPU,Memory가 남고 다른 node에는 pod들이 많아서 CPU,Memory 부족한 현상이 발생할 수도 있습니다.
이러한 상황을 예방하기 위해 아래 코드와 같이 resources 필드에서 CPU,Memory 제한을 설정해 놓을 수 있습니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: cozserver-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: sebcontents/cozserver:2.0
resources:
limits:
memory: "128Mi"
cpu: "0.5"
ports:
- containerPort: 8080
💡 자원 사용량을 할당할 때의 단위
memoy는 접두어를 사용해서 Eexa, Ppeta, Ttera, Ggiga, Mmega, Kkilo를 사용하지만
CPU는 보통 코어 개수로 1,2,3,4 정소로만 설정할 수 있다고 생각하지만 항상 상대적인 양이 아니라 절대적인 양으로 요청한다. (1 이상 안됨)
e.g : 0.5는 50%만큼 연산능력을 할당하며 이는 500m(milliCPU)d와 동일
Pod Environment
apiVersion: v1
Kind: Pod
metadata:
name: hello-world
labels:
app: hello-world
spec:
containers:
- name: helloworld
image: helloworld:latest
ports:
- containerPort: 8080
env:
- name: TESTENV01
value: "test01"
- name: HOSTNAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: CPU_REQUEST
valueFrom:
resourceFieldRef:
containerName: hello-wolrd
resource: requests.cpu
- name: CPU_LIMIT
valueFrom:
resourceFieldRef:
containerName: hello-wolrd
resource: limits.cpu
name
: 사용할 환경 변수의 이름을 설정value
: 문자열이나 숫자 형식의 값valueFrom
: 값을 직접 할당하는 것이 아닌 다른곳에서 참조하는 값을 설정fieldRef
: pod의 현재 설정 내용을 값으로 설정한다는 선언fieldPath
: .fieldRef에서 어디서 값을 참조할건지 지정 (항목 위치 지정)resourceFieldRef
: 컨테이너에 CPU, Memory 사용량을 얼마나 할당했는지에 관한 정보를 가져옴containerName
: 환경 변수 설정을 가져올 컨테이너 이름을 설정resource
: 어떤 자원의 정보를 가져올지 설정
Pod Environment Check
kubectl exec -it [pod_name] sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/app # env
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT=443
NODE_VERSION=16.14.0
HOSTNAME=cozserver-deployment-5cc4cd8d69-7l974
YARN_VERSION=1.22.17
SHLVL=1
HOME=/root
COZSERVER_SERVICE_SERVICE_HOST=10.99.253.50
COZSERVER_SERVICE_PORT=tcp://10.99.253.50:80
COZSERVER_SERVICE_SERVICE_PORT=80
TERM=xterm
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
COZSERVER_SERVICE_PORT_80_TCP_ADDR=10.99.253.50
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
COZSERVER_SERVICE_PORT_80_TCP_PORT=80
COZSERVER_SERVICE_PORT_80_TCP_PROTO=tcp
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_HOST=10.96.0.1
COZSERVER_SERVICE_PORT_80_TCP=tcp://10.99.253.50:80
PWD=/app
pod 구성 패턴
🔠 구글 실제 시스템에서 수년간 container를 운영해온 경험을 정리해서 Design patterns for container-based distributed system이라는 자료를 공개 했으며 단일 노드에서 여러 container를 구성할 때의 패턴들이 소개되어 있다
Sidecar 패턴

- 원래 사용하려던 기본 container의 기능을 확장하거나 강화하는 용도의 container를 추가하는것이며 기본 container는 원래 목적의 기능에만 충실하도록 구성하고, 나머지 공통 부가 기능들은 sidecar container를 추가해서 사용
- 왼쪽 그림과 같이 구성하면 WebServer Container를 다른 역할을 하는 Container로 변경했을 때도 로그 수집 Container는 그대로 사용가능
Amberssador 패턴

- pod 안에서 proxy역할을 하는 container를 추가하는 패턴
- pod안에서 외부 서버에 접근할 때 내부 proxy에 접근하도록 설정하고 실제 외부와의 연결은 proxy에서 처리
Adaptor 패턴

- pod 외부로 노출되는 정보를 표준화하는 adaptor container를 사용