파드(Pod) 는 쿠버네티스에서 생성하고 관리할 수 있는 배포 가능한 가장 작은 컴퓨팅 단위이다.
파드 (고래 떼나 완두콩 꼬투리처럼)는 하나 이상의 컨테이너의 그룹이다. 이 그룹은 스토리지 및 네트워크를 공유하고, 해당 컨테이너를 구동하는 방식에 대한 명세를 갖는다. 파드의 콘텐츠는 항상 함께 배치되고, 함께 스케줄되며, 공유 컨텍스트에서 실행된다. 파드는 애플리케이션별 "논리 호스트"를 모델링한다. 여기에는 상대적으로 밀접하게 결합된 하나 이상의 애플리케이션 컨테이너가 포함된다. 클라우드가 아닌 컨텍스트에서, 동일한 물리 또는 가상 머신에서 실행되는 애플리케이션은 동일한 논리 호스트에서 실행되는 클라우드 애플리케이션과 비슷하다.
애플리케이션 컨테이너와 마찬가지로, 파드에는 파드 시작 중에 실행되는 초기화 컨테이너가 포함될 수 있다. 디버깅을 위해 실행 중인 파드에 임시 컨테이너를 삽입할 수도 있다.
파드의 공유 컨텍스트는 리눅스 네임스페이스, 컨트롤 그룹(cgroups) 및 컨테이너를 격리하는 것과 같이 잠재적으로 다른 격리 요소들이다. 파드의 컨텍스트 내에서 개별 애플리케이션은 추가적으로 하위 격리가 적용된다.
파드는 공유 네임스페이스와 공유 파일 시스템 볼륨이 있는 컨테이너 집합과 비슷하다.
쿠버네티스 클러스터의 파드는 크게 두 가지 방식으로 사용된다.
단일 컨테이너를 실행하는 파드: "파드당 컨테이너 1개(one-container-per-Pod)" 모델은 쿠버네티스에서 가장 흔한 사용 사례이다. 이 경우 파드는 단일 컨테이너를 감싸는 래퍼(wrapper)처럼 볼 수 있으며, 쿠버네티스는 컨테이너 자체가 아니라 파드를 관리한다.
함께 동작해야 하는 여러 컨테이너를 실행하는 파드: 파드는 서로 긴밀하게 결합되어 리소스를 공유해야 하는 여러 개의 컨테이너로 구성된 애플리케이션을 캡슐화할 수 있다. 이렇게 함께 배치되고 공동 관리되는 컨테이너들은 하나의 응집력 있는 단위를 이룬다.
여러 개의 컨테이너를 하나의 파드 안에 두고 관리하여 그룹화하는 것은 상대적으로 고급 사용 사례이다. 컨테이너들이 긴밀히 결합되어 있는 특정한 상황에서만 이 패턴을 사용하는 것을 권장한다.
(복원성 또는 용량으로 인해) 복제를 제공하는 여러 컨테이너를 실행할 필요는 없다. 여러 복제가 필요하다면, 워크로드 관리를 참고한다.
다음은 nginx:1.14.2 이미지를 실행하는 컨테이너로 구성되는 파드의 예시이다.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
위에서 설명한 파드를 생성하려면, 다음 명령을 실행한다.
kubectl apply -f https://k8s.io/examples/pods/simple-pod.yaml
일반적으로 파드는 직접 생성하지는 않으며, 대신 워크로드 리소스를 사용하여 생성한다. 파드 작업 섹션에서 파드와 워크로드 리소스의 관계에 대한 더 많은 정보를 확인한다.
일반적으로 싱글톤(singleton) 파드를 포함하여 파드를 직접 만들 필요가 없다. 대신, 디플로이먼트(Deployment) 또는 잡(Job)과 같은 워크로드 리소스를 사용하여 생성한다. 파드가 상태를 추적해야 한다면, 스테이트풀셋(StatefulSet) 리소스를 고려하자.
각 파드는 특정 애플리케이션의 단일 인스턴스를 실행하기 위한 것이다. 더 많은 인스턴스를 실행하여 더 많은 전체 리소스를 제공하기 위해 애플리케이션을 수평적으로 확장하려면, 각 인스턴스에 하나씩, 여러 파드를 사용해야 한다. 쿠버네티스에서는 이를 일반적으로 레플리케이션 이라고 한다. 복제된 파드는 일반적으로 워크로드 리소스와 해당 컨트롤러에 의해 그룹으로 생성되고 관리된다.
쿠버네티스가 워크로드 리소스와 해당 컨트롤러를 사용하여 애플리케이션 스케일링과 자동 복구를 구현하는 방법에 대한 자세한 내용은 파드와 컨트롤러를 참고한다.
파드는 기본적으로 파드에 속한 컨테이너에 네트워킹과 스토리지라는 두 가지 종류의 공유 리소스를 제공한다.
사용자가 쿠버네티스에서 직접 개별 파드를 만드는 경우는 거의 없다. 싱글톤 파드도 마찬가지이다. 이는 파드가 상대적으로 일시적인, 일회용 엔티티로 설계되었기 때문이다. 파드가 생성될 때(사용자가 직접 또는 컨트롤러가 간접적으로), 새 파드는 클러스터의 노드에서 실행되도록 스케줄된다. 파드는 파드 실행이 완료되거나, 파드 오브젝트가 삭제되거나, 리소스 부족으로 인해 파드가 축출되거나, 노드가 실패할 때까지 해당 노드에 남아 있다.
파드 이름은 유효한 DNS 서브도메인 이름 이어야 하지만, 이 규칙으로 인해 파드 호스트네임이 예상과 달라질 수 있다. 호환성을 최대한 높이려면 이름이 더 엄격한 DNS 레이블 규칙을 따르는 것이 좋다.
.spec.os.name 필드를 windows 또는 linux로 설정하여 해당 파드의 컨테이너가
요구하는 운영 체제를 나타내야 한다. 현재 쿠버네티스가 지원하는 운영 체제는
이 두 가지뿐이다. 향후 이 목록이 확장될 수 있다.
.spec.os.name 값이 노드의 운영 체제와 일치하지 않으면 kubelet은 파드 실행을 거부한다.
그러나 쿠버네티스 v1.37에서 .spec.os.name 값은
kube-scheduler가 파드를 실행할
노드를 선택하는 방식에 영향을 주지 않는다. 서로 다른 운영 체제를 실행하는 노드가 있는
클러스터에서는 각 노드에
kubernetes.io/os
레이블을 올바르게 지정하고, 운영 체제 레이블을 기반으로 파드의
nodeSelector를 정의해야 한다. kube-scheduler는 다른 기준에 따라
파드를 노드에 할당하므로, 파드의 컨테이너에 적합한 운영 체제를 실행하는
노드를 선택할 수도 있고 그렇지 못할 수도 있다.
파드 시큐리티 스탠다드도 이
필드를 사용하여 운영 체제와 관련 없는 정책을 적용하지 않는다.
워크로드 리소스를 사용하여 여러 파드를 만들고 관리할 수 있다. 리소스에 대한 컨트롤러는 파드 장애 시 복제 및 롤아웃과 자동 복구를 처리한다. 예를 들어, 노드가 실패하면, 컨트롤러는 해당 노드의 파드가 작동을 중지했음을 인식하고 대체 파드를 생성한다. 스케줄러는 대체 파드를 정상 노드에 배치한다.
다음은 하나 이상의 파드를 관리하는 워크로드 리소스의 몇 가지 예시이다.
To use this feature, you (or a cluster administrator) will need to enable the GenericWorkload feature gate for all relevant components in your cluster.
See Enable Or Disable Feature Gates for more information.
기본적으로 쿠버네티스는 각 파드를 개별적으로 스케줄한다. 그러나 긴밀하게 결합된 일부 애플리케이션이 올바르게 동작하려면 파드 그룹을 동시에 스케줄해야 한다.
스케줄링 그룹 필드(spec.schedulingGroup)를 사용하여
파드를 파드그룹(PodGroup)에 연결할 수 있다. 이렇게 하면
kube-scheduler는 파드가 특정 그룹에 속해 있음을 알고, 그룹 전체에 대한 배치를 한 번에
조정해서 결정할 수 있다.
워크로드 리소스의 컨트롤러는 사용자를 대신해 파드 템플릿 에서 파드를 생성하고 해당 파드를 관리한다.
파드템플릿(PodTemplate)은 파드를 생성하기 위한 명세이며, 디플로이먼트, 잡 및 데몬셋과 같은 워크로드 리소스에 포함된다.
워크로드 리소스의 각 컨트롤러는 워크로드 오브젝트 내부의 PodTemplate을
사용하여 실제 파드를 생성한다. 어떤 워크로드 리소스를 사용해 앱을 실행하든
PodTemplate은 그 리소스가 의도한 상태의 일부이다.
파드를 생성할 때 파드에서 실행할 컨테이너의 환경 변수를 파드 템플릿에 포함할 수 있다.
아래 샘플은 하나의 컨테이너를 시작하는 template이 있는 간단한 잡의
매니페스트이다. 해당 파드의 컨테이너는 메시지를 출력한 다음 일시 중지한다.
apiVersion: batch/v1
kind: Job
metadata:
name: hello
spec:
template:
# 여기서부터 파드 템플릿이다
spec:
containers:
- name: hello
image: busybox:1.28
command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
restartPolicy: OnFailure
# 여기까지 파드 템플릿이다
파드 템플릿을 수정하거나 새로운 파드 템플릿으로 바꿔도 이미 존재하는 파드에는 직접적인 영향을 주지 않는다. 워크로드 리소스의 파드 템플릿을 변경하는 경우, 해당 리소스는 수정된 템플릿을 사용하는 대체 파드를 생성해야 한다.
예를 들어, 스테이트풀셋 컨트롤러는 실행 중인 파드가 각 스테이트풀셋 오브젝트에 대한 현재 파드 템플릿과 일치하는지 확인한다. 스테이트풀셋을 수정하여 파드 템플릿을 변경하면, 스테이트풀셋이 업데이트된 템플릿을 기반으로 새로운 파드를 생성하기 시작한다. 결국, 모든 이전의 파드가 새로운 파드로 교체되고, 업데이트가 완료된다.
각 워크로드 리소스는 파드 템플릿의 변경 사항을 처리하기 위한 자체 규칙을 구현한다. 스테이트풀셋에 대해 자세히 알아보려면, 스테이트풀셋 기본 튜토리얼에서 업데이트 전략을 읽어본다.
노드에서 kubelet은 파드 템플릿과 업데이트에 대한 상세 정보를 직접 관찰하거나 관리하지 않는다. 이러한 상세 내용은 추상화된다. 이러한 추상화와 관심사 분리(separation of concerns)는 시스템 시맨틱을 단순화하고, 기존 코드를 변경하지 않고도 클러스터의 동작을 확장할 수 있게 한다.
이전 섹션에서 언급한 바와 같이, 워크로드 리소스의 파드 템플릿이 바뀌면, 컨트롤러는 기존의 파드를 갱신하거나 패치하는 대신 갱신된 템플릿을 기반으로 신규 파드를 생성한다.
쿠버네티스는 사용자가 파드를 직접 관리하는 것을 막지는 않는다.
동작 중인 파드의 필드를 갱신하는 것도 가능하다.
그러나,
patch 및
replace와 같은
파드 갱신 작업에는 다음과 같은 제약이 있다.
파드에 대한 대부분의 메타데이터는 불변(immutable)이다. 예를 들면, 사용자는
namespace, name, uid, 또는 creationTimestamp 필드를 변경할 수 없다.
metadata.deletionTimestamp가 설정된 경우,
metadata.finalizers 리스트에 새로운 항목이 추가될 수 없다.
파드 갱신은 spec.containers[*].image,
spec.initContainers[*].image, spec.activeDeadlineSeconds, spec.terminationGracePeriodSeconds,
spec.tolerations 또는 spec.schedulingGates 이외의 필드는 변경할 수 없다. spec.tolerations에는 새로운 항목만 추가할 수 있다.
spec.activeDeadlineSeconds 필드를 갱신할 때는 다음의 두 가지 형태만
허용한다.
앞서 설명한 업데이트 규칙은 일반적인 파드 업데이트에 적용되지만, 서브리소스 를 통해 업데이트할 수 있는 다른 파드 필드도 있다.
resize 서브리소스를 사용하면 컨테이너 리소스(spec.containers[*].resources)를 업데이트할 수 있다.
자세한 내용은 컨테이너 리소스 리사이즈를 참고한다.ephemeralContainers 서브리소스를 사용하면
임시 컨테이너를
파드에 추가할 수 있다.
자세한 내용은 임시 컨테이너를 참고한다.status 서브리소스를 사용하면 파드 상태를 업데이트할 수 있다.
이 서브리소스는 일반적으로 Kubelet과 다른 시스템 컨트롤러에서만 사용한다.binding 서브리소스를 사용하면 Binding 요청을 통해 파드의 spec.nodeName을 설정할 수 있다.
이 서브리소스는 일반적으로 스케줄러에서만 사용한다.metadata.generation 필드는 고유하다. 시스템에서 자동으로 설정되며,
새 파드의 metadata.generation 값은 1이 된다. 파드 스펙의 변경 가능한 필드가
업데이트될 때마다 metadata.generation 값이 1씩 증가한다.This is a stable feature in Kubernetes, and has been since version v1.35. It was first available in the v1.33 release. You can no longer disable or opt out of this feature or behavior (it is locked); if you explicitly set a value for the associated feature gate PodObservedGenerationTracking, Kubernetes ignores it but does not report any error.
observedGeneration은 파드 오브젝트의 status 섹션에 기록되는 필드이다. Kubelet은
파드 상태를 현재 파드 상태와 동기화하기 위해 status.observedGeneration을 설정한다.
파드의 status.observedGeneration은 상태가 보고되는 시점의
metadata.generation을 반영한다.status.observedGeneration 필드는 kubelet에서 관리하며 외부 컨트롤러는 이 필드를 수정하지 않아야 한다.상태 필드는 현재 동기 루프(sync loop)의 metadata.generation과 연결될 수도
있고, 이전 동기 루프의 metadata.generation과 연결될 수도 있다. 핵심 차이는
spec의 변경이 status에 직접 반영되는지, 아니면 실행 중인 프로세스의 간접적인 결과인지에 있다.
할당된 스펙이 직접적으로 반영되는 상태 필드의 경우,
observedGeneration은 현재 metadata.generation(Generation N)과 연결된다.
이 동작은 다음과 같은 경우에 적용한다.
Waiting 상태일 때이다.실행 중인 스펙의 결과로 간접적으로 반영되는 상태 필드의 경우,
observedGeneration은 이전 동기 루프의 metadata.generation(Generation N-1)과 연결된다.
이 동작은 다음과 같은 경우에 적용한다.
ContainerStatus.ImageID는 새 이미지가 풀(pull)
되고 컨테이너가 업데이트되기 전까지 이전 세대의 이미지를 반영한다.파드는 파드에 속한 컨테이너 간의 데이터 공유와 통신을 지원한다.
파드는 공유 스토리지 볼륨의 집합을 지정할 수 있다. 파드의 모든 컨테이너는 공유 볼륨에 접근할 수 있으므로, 해당 컨테이너가 데이터를 공유할 수 있다. 또한 볼륨은 내부 컨테이너 중 하나를 다시 시작해야 하는 경우 파드의 영구 데이터를 유지하도록 허용한다. 쿠버네티스가 공유 스토리지를 구현하고 파드에서 사용할 수 있도록 하는 방법에 대한 자세한 내용은 스토리지를 참고한다.
각 파드에는 각 주소 패밀리에 대해 고유한 IP 주소가 할당된다.
파드의 모든 컨테이너는 네트워크 네임스페이스를 공유하며,
여기에는 IP 주소와 네트워크 포트가 포함된다.
파드 내부(이 경우에 만 해당)에서, 파드에 속한 컨테이너는
localhost를 사용하여 서로 통신할 수 있다.
파드의 컨테이너가 파드 외부의 엔티티와 통신할 때,
공유 네트워크 리소스(포트와 같은)를 사용하는 방법을 조정해야 한다.
파드 내에서 컨테이너는 IP 주소와 포트 공간을 공유하며,
localhost를 통해 서로를 찾을 수 있다.
파드의 컨테이너는 SystemV 세마포어 또는 POSIX 공유 메모리와 같은
표준 프로세스 간 통신을 사용하여 서로 통신할 수도 있다.
다른 파드의 컨테이너는 고유한 IP 주소를 가지며 특별한 구성 없이 OS 수준의 IPC로 통신할 수 없다.
다른 파드에서 실행되는 컨테이너와 상호 작용하려는 컨테이너는 IP 네트워킹을 사용하여 통신할 수 있다.
파드 내의 컨테이너는 시스템 호스트명이 파드에 대해 구성된
name과 동일한 것으로 간주한다. 네트워킹 섹션에 이에 대한
자세한 내용이 있다.
파드와 컨테이너에 보안 제약을 설정하려면 파드 명세의 securityContext 필드를
사용한다. 이 필드를 사용하면 파드나 개별 컨테이너가 수행할 수 있는 작업을 세밀하게
제어할 수 있다. 자세한 내용은 고급 파드 구성을 참고한다.
기본적인 보안 구성에서는 파드 시큐리티 스탠다드의 기본(Baseline) 정책을 충족하고 컨테이너를 루트가 아닌 사용자로 실행해야 한다. 다음과 같이 간단한 보안 컨텍스트를 설정할 수 있다.
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
containers:
- name: sec-ctx-demo
image: busybox
command: ["sh", "-c", "sleep 1h"]
capabilities, seccomp 프로파일, 세부 보안 옵션을 비롯한 고급 보안 컨텍스트 구성은 보안 개념 섹션을 참고한다.
파드를 지정할 때 컨테이너에 필요한 각 리소스의 양을 선택적으로 지정할 수 있다. 가장 일반적으로 지정하는 리소스는 CPU와 메모리(RAM)이다.
파드의 컨테이너에 리소스 요청(request) 을 지정하면 kube-scheduler는 이 정보를 사용하여 파드를 배치할 노드를 결정한다. 컨테이너에 리소스 제한(limit) 을 지정하면 kubelet은 실행 중인 컨테이너가 설정한 제한보다 많은 리소스를 사용할 수 없도록 해당 제한을 적용한다.
CPU 제한은 CPU 쓰로틀링(throttling)으로 적용된다. 컨테이너가 CPU 제한에 가까워지면 커널이 CPU 접근을 제한한다. 메모리 제한은 컨테이너가 제한을 초과할 때 커널이 메모리 부족(OOM)으로 종료하는 방식으로 적용된다.
리소스 단위, 제한 적용 방식, 구성 예시에 대한 자세한 내용은 파드 및 컨테이너 리소스 관리를 참고한다.
스태틱 파드 는 특정 노드의 kubelet 데몬이 직접 관리하며, API 서버는 이를 관찰하지 않는다. 대부분의 파드는 컨트롤 플레인(예를 들어, 디플로이먼트)에서 관리하지만, 스태틱 파드의 경우 kubelet이 각 파드를 직접 감독하고 실패하면 다시 시작한다.
스태틱 파드는 항상 특정 노드의 Kubelet 하나에 바인딩된다. 스태틱 파드의 주요 용도는 자체 호스팅 컨트롤 플레인을 실행하는 것이다. 즉, kubelet을 사용하여 개별 컨트롤 플레인 컴포넌트를 감독한다.
자세한 내용은 스태틱 파드를 참고한다.
파드들은 상호 협력하는 여러 프로세스(컨테이너 형태)를 지원하도록 설계되어 있으며, 하나의 응집력 있는 서비스 단위를 형성한다. 파드의 컨테이너는 클러스터 내 동일한 물리적 또는 가상 머신에 자동으로 함께 배치되고, 함께 스케줄링된다. 컨테이너는 리소스와 종속성을 공유할 수 있고, 서로 통신할 수 있으며, 종료 시점과 방식을 조율할 수 있다.
쿠버네티스 클러스터에서 파드는 다음 두 가지 주요 방식으로 사용한다.
예를 들어, 웹 서버 역할의 한 컨테이너가 공유 볼륨에 있는 파일을 제공하고, 별도의 사이드카 컨테이너가 원격 소스에서 해당 파일을 업데이트하는 경우가 있다. 이는 다음 다이어그램과 같다.
일부 파드에는 애플리케이션 컨테이너 뿐 아니라 초기화 컨테이너도 있다. 기본적으로 초기화 컨테이너는 애플리케이션 컨테이너가 시작되기 전에 실행되고 완료된다.
또한 사이드카 컨테이너를 두어, 메인 애플리케이션 파드에 보조 서비스를 제공할 수도 있다(예: 서비스 메시).
This is a stable feature in Kubernetes, and has been since version v1.33. It was first available in the v1.28 release. You can no longer disable or opt out of this feature or behavior (it is locked); if you explicitly set a value for the associated feature gate SidecarContainers, Kubernetes ignores it but does not report any error.
SidecarContainers 기능 게이트는 기본적으로 활성화되어 있다.
이 기능을 사용하면 초기화 컨테이너에 restartPolicy: Always를 지정할 수 있다.
Always 재시작 정책을 설정하면 쿠버네티스가 해당 초기화 컨테이너를 사이드카 로
취급하여 파드 전체 수명 동안 계속 실행되도록 한다.
명시적으로 사이드카 컨테이너로 정의된 컨테이너는
메인 애플리케이션 파드보다 먼저 시작되고, 파드가 종료될 때까지
계속 실행된다.
kubelet은 컨테이너에서 프로브 라는 진단을 주기적으로 수행한다. 진단을 수행하기 위해 kubelet은 다음 작업 중 하나를 호출할 수 있다.
ExecAction (컨테이너 런타임의 도움을 받아 수행)TCPSocketAction (kubelet에 의해 직접 검사)HTTPGetAction (kubelet에 의해 직접 검사)프로브에 대한 자세한 내용은 파드 라이프사이클 문서를 참고한다.
쿠버네티스가 다른 리소스(스테이트풀셋이나 디플로이먼트와 같은)에서 공통 파드 API를 래핑하는 이유에 대한 컨텍스트를 이해하고자 한다면, 다음과 같은 선행 기술에 대해 읽어보자.