Pod
공식 문서: https://kubernetes.io/ko/docs/concepts/workloads/pods/
- 파드는 컨테이너의 모음이다. 하나의 파드에 한 개 이상의 컨테이너가 있을 수 있다.
- 쿠버네티스는 컨테이너를 직접 관리하지 않는다. 쿠버네티스에서 관리하는 가장 작은 워크로드는 파드이다.
kubelet 이 서비스인 이유
kubelet 은 api-server, cm, 스케줄러 등 쿠버네티스의 필수 불가결한 리소스들을 실행시켜주는 역할을 하기 때문에 파드가 아닌 서비스로서 동작한다. 만약 kubelet 까지 파드로 구성되어 있다면 kubernetes 를 띄울 녀석이 존재하지가 않기 때문에 서비스로 동작을 한다.
정적 파드
정적 파드 는 API 서버가 관찰하는 대신 특정 노드의 kubelet 데몬에 의해 직접 관리된다.
대부분의 파드는 컨트롤 플레인(예를 들어, 디플로이먼트)에 의해 관리되고, 정적 파드의 경우, kubelet이 각 정적 파드를 직접 감독한다(실패하면 다시 시작한다).
정적 파드는 항상 특정 노드의 Kubelet 하나에 바인딩된다. 정적 파드의 주요 용도는 자체 호스팅 컨트롤 플레인을 실행하는 것이다. 즉, kubelet을 사용하여 개별 컨트롤 플레인 컴포넌트를 감독한다.
kubelet은 자동으로 각 정적 파드에 대한 쿠버네티스 API 서버에서 미러 파드를 생성하려고 한다. 즉, 노드에서 실행되는 파드는 API 서버에서 보이지만, 여기에서 제어할 수는 없다는 의미이다.
/etc/kubernetes/manifest 에서 yml 파일로 pod 를 작성한 후 실행하면 정적 파드가 생성된다.
kubectl 명령의 서브 명령
kubectl 에서 자주 사용하는 서브 명령어
- create
- get
- describe
- logs
- delete
- replace
- patch
- apply
- diff
명령형 커맨드로 파드 생성
kubectl run myweb --image httpd
kubectl get pods
NAME READY STATUS RESTARTS AGE
myweb 1/1 Running 0 26s
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myweb 1/1 Running 0 2m21s 10.233.109.1 node-3 <none> <none>
파드 상세 정보
kubectl get pods -o yaml 를 사용해서 yaml 형태로 etcd 에서 원본 데이터를 가져온다.
-o wide, -o json 등으로 원하는 포맷팅으로 가져올 수 있다.
kubectl get pods -o yaml
apiVersion: v1
items:
- apiVersion: v1
kind: Pod
metadata:
annotations:
cni.projectcalico.org/containerID: ba98ccabd6b2b011e9654d76181414a90e7eec9729e207ceb6391d513bccfab2
cni.projectcalico.org/podIP: 10.233.109.1/32
cni.projectcalico.org/podIPs: 10.233.109.1/32
creationTimestamp: "2022-05-17T01:38:18Z"
labels:
run: myweb
name: myweb
namespace: default
resourceVersion: "18433"
uid: 4741205a-6581-4ab6-bae5-dc0f6ac35dbc
spec:
containers:
- image: httpd
imagePullPolicy: Always
name: myweb
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access-ff6tf
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
nodeName: node-3
preemptionPolicy: PreemptLowerPriority
priority: 0
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
volumes:
- name: kube-api-access-ff6tf
projected:
defaultMode: 420
sources:
- serviceAccountToken:
expirationSeconds: 3607
path: token
- configMap:
items:
- key: ca.crt
path: ca.crt
name: kube-root-ca.crt
- downwardAPI:
items:
- fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
path: namespace
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2022-05-17T01:38:19Z"
status: "True"
type: Initialized
- lastProbeTime: null
lastTransitionTime: "2022-05-17T01:38:38Z"
status: "True"
type: Ready
- lastProbeTime: null
lastTransitionTime: "2022-05-17T01:38:38Z"
status: "True"
type: ContainersReady
- lastProbeTime: null
lastTransitionTime: "2022-05-17T01:38:19Z"
status: "True"
type: PodScheduled
containerStatuses:
- containerID: containerd://8129401885bc9f1e85e5051c514be51183a784134ad58c2581461e1a2d46e6f7
image: docker.io/library/httpd:latest
imageID: docker.io/library/httpd@sha256:2d1f8839d6127e400ac5f65481d8a0f17ac46a3b91de40b01e649c9a0324dea0
lastState: {}
name: myweb
ready: true
restartCount: 0
started: true
state:
running:
startedAt: "2022-05-17T01:38:38Z"
hostIP: 192.168.100.105
phase: Running
podIP: 10.233.109.1
podIPs:
- ip: 10.233.109.1
qosClass: BestEffort
startTime: "2022-05-17T01:38:19Z"
kind: List
metadata:
resourceVersion: ""
selfLink: ""
describe
kubectl describe pods myweb
Name: myweb
Namespace: default
Priority: 0
Node: node-3/192.168.100.105
Start Time: Tue, 17 May 2022 01:38:19 +0000
Labels: run=myweb
Annotations: cni.projectcalico.org/containerID: ba98ccabd6b2b011e9654d76181414a90e7eec9729e207ceb6391d513bccfab2
cni.projectcalico.org/podIP: 10.233.109.1/32
cni.projectcalico.org/podIPs: 10.233.109.1/32
Status: Running
IP: 10.233.109.1
IPs:
IP: 10.233.109.1
Containers:
myweb:
Container ID: containerd://8129401885bc9f1e85e5051c514be51183a784134ad58c2581461e1a2d46e6f7
Image: httpd
Image ID: docker.io/library/httpd@sha256:2d1f8839d6127e400ac5f65481d8a0f17ac46a3b91de40b01e649c9a0324dea0
Port: <none>
Host Port: <none>
State: Running
Started: Tue, 17 May 2022 01:38:38 +0000
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-ff6tf (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-ff6tf:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 6m22s default-scheduler Successfully assigned default/myweb to node-3
Normal Pulling 6m21s kubelet Pulling image "httpd"
Normal Pulled 6m9s kubelet Successfully pulled image "httpd" in 12.366300856s
Normal Created 6m4s kubelet Created container myweb
Normal Started 6m3s kubelet Started container myweb
event 는 myweb pod 의 라이프 사이클이다.
맨 처음 디폴트 스케줄러에 의해 이벤트가 발생한다. 노드-3 에 파드를 배치했다.
kubelet 이 httpd 이미지를 풀링한다. httpd 폴링이 완료되고 kubelet 이 myweb 컨테이너를 생성하고 실행한다.
파드를 생성했을 때 컨테이너가 제대로 작동하지 않을 경우 kubectl describe pods 로 파드 자체의 로그를 확인하고 그 후에 애플리케이션의 로그를 확인한다.
애플리케이션의 로그를 확인하기 위해서는 kubectl logs <파드_이름> 명령어로 확인 가능하다.
파드 삭제
kubectl delete pods <파드_이름>
YAML 파일로 파드 정의
kubectl explain pods
myweb.yml
apiVersion: v1
kind: Pod
metadata:
name: myweb
spec:
containers:
- name: myweb
image: httpd
ports:
- containerPort: 80
name: myweb
protocol: TCP
Workload resources for managing pods
일반적으로 싱글톤(singleton) 파드를 포함하여 파드를 직접 만들 필요가 없다. 대신, 디플로이먼트(Deployment) 또는 잡(Job)과 같은 워크로드 리소스를 사용하여 생성한다. 파드가 상태를 추적해야 한다면, 스테이트풀셋(StatefulSet) 리소스를 고려한다.
쿠버네티스 클러스터의 파드는 두 가지 주요 방식으로 사용된다.
- 단일 컨테이너를 실행하는 파드. "파드 당 하나의 컨테이너" 모델은 가장 일반적인 쿠버네티스 유스케이스이다. 이 경우, 파드를 단일 컨테이너를 둘러싼 래퍼(wrapper)로 생각할 수 있다. 쿠버네티스는 컨테이너를 직접 관리하는 대신 파드를 관리한다.
- 함께 작동해야 하는 여러 컨테이너를 실행하는 파드. 파드는 밀접하게 결합되어 있고 리소스를 공유해야 하는 함께 배치된 여러 개의 컨테이너로 구성된 애플리케이션을 캡슐화할 수 있다. 이런 함께 배치된 컨테이너는 하나의 결합된 서비스 단위를 형성한다. 예를 들어, 하나의 컨테이너는 공유 볼륨에 저장된 데이터를 퍼블릭에 제공하는 반면, 별도의 사이드카 컨테이너는 해당 파일을 새로 고치거나 업데이트한다. 파드는 이러한 컨테이너, 스토리지 리소스, 임시 네트워크 ID를 단일 단위로 함께 래핑한다.
하나의 파드에는 반드시 하나의 메인 어플리케이션만 있어야 한다. 파드에 여러 컨테이너가 있을 경우에는 메인 어플리케이션 + 메인 어플리케이션을 서포팅하는 다른 컨테이너여야 한다.
하나의 파드에 메인 애플리케이션이 여러개 띄워지면 안된다. -> 안티 패턴이다.
예를 들어 하나의 파드안에 메인이 되는 웹서버가 있고 해당 웹서버로 코드를 가져오거나 정적인 파일을 가져오는 메인 앱을 서포팅하는 앱과 웹서버에서 보내준 로그를 로그 서버로 보내는 메인 앱을 서포팅하는 앱으로 파드가 구성될 수 있다.
하나의 파드는 하나의 호스트(노드)에 배치된다. 즉, 파드 안여 여러 대의 컨테이너가 있어도 하나의 호스트(노드)에 모두 배치된다.
파드 디자인
사이드카 패턴: https://kubernetes.io/blog/2015/06/the-distributed-system-toolkit-patterns/
- 단일 컨테이너: 가장 일반적인 형태, 대부분의 파드는 단일 컨테이너로 이루어져 있다.
- 멀티 컨테이너: 메인 애플리케이션이 존재하고 메인 애플리케이션 기능을 확장하기 위한 컨테이너를 배치
- sidecar: 기능의 확장
- ambassador: proxy/LB
- adaptor: 출력의 표준
파드는 응집력있는 서비스 단위를 형성하는 여러 협력 프로세스(컨테이너)를 지원하도록 설계되었다. 파드의 컨테이너는 클러스터의 동일한 물리 또는 가상 머신에서 자동으로 같은 위치에 배치되고 함께 스케줄된다. 컨테이너는 리소스와 의존성을 공유하고, 서로 통신하고, 종료 시기와 방법을 조정할 수 있다.
예를 들어, 다음 다이어그램에서와 같이 공유 볼륨의 파일에 대한 웹 서버 역할을 하는 컨테이너와, 원격 소스에서 해당 파일을 업데이트하는 별도의 "사이드카" 컨테이너가 있을 수 있다.
일부 파드에는 앱 컨테이너 뿐만 아니라 초기화 컨테이너를 갖고 있다. 초기화 컨테이너는 앱 컨테이너가 시작되기 전에 실행되고 완료된다.
파드는 기본적으로 파드에 속한 컨테이너에 네트워킹과 스토리지라는 두 가지 종류의 공유 리소스를 제공한다.
파드는 딱 하나의 IP 주소를 부여 받는다. 즉, 파드 안에 몇 개의 컨테이너가 있든 간에 모두 같은 IP 주소를 사용한다. → 공유 네트워크
파드에 볼륨을 설정해주면 해당하는 볼륨을 파드 안의 모든 컨테이너가 접근할 수 있고 사용할 수 있다. → 공유 스토리지
포트 및 포트 포워딩
테스트 & 디버깅 목적이다.
kubectl port-forward pods/<파드_이름> 8080:80