Pod
Last updated
Last updated
파드 는 쿠버네티스에서 생성되고 관리될 수 있는 배포 가능한 최소 컴퓨팅 단위이다.
파드 는 (고래 떼(pod of whales)나 콩꼬투리(pea pod)와 마찬가지로) 하나 이상의(도커 컨테이너 같은) 컨테이너 그룹이다. 이 그룹은 스토리지/네트워크를 공유하고, 해당 컨테이너를 구동하는 방식에 대한 명세를 갖는다. 파드의 콘텐츠들은 항상 함께 배치되고 같이 스케줄되며, 공유 컨텍스트 내에서 구동된다. 파드는 애플리케이션에 특화된 "논리 호스트"를 모델로 하고 있다. 이것은 하나 또는 강하게 서로 결합되어 있는 여러 애플리케이션 컨테이너를 포함한다. 컨테이너 이전의 세상에서 같은 물리적 또는 가상의 머신에서 실행되는 것은 같은 논리적 호스트에서 실행되고 있는 것을 의미한다.
쿠버네티스는 도커 이외에도 많은 컨테이너 런타임을 지원하지만, 도커는 가장 일반적으로 알려진 런타임이므로 도커 용어로 파드를 설명하는 것이 도움이 된다.
파드의 공유 컨텍스트는 리눅스 네임스페이스, 컨트롤 그룹(cgroup) 및 도커 컨테이너를 격리하는 것과 같이 잠재적으로 다른 격리 요소들이다. 파드의 컨텍스트 내에서 개별 응용 프로그램은 추가적으로 하위 격리가 적용된다.
파드 안의 컨테이너들은 IP주소와 포트 공간을 공유하고, 서로를 localhost
를 통해 찾을 수 있다. 그들은 또한 SystemV 세마포어나, POSIX 공유 메모리와 같은 표준 프로세스 간 통신 방식으로 서로 통신할 수 있다. 다른 파드의 컨테이너에는 고유한 IP 주소가 있고, 특별한 구성 없이는 IPC에 의해서 통신 할 수 없다. 컨테이너는 주로 서로의 IP 주소를 통해 소통한다.
또한 파드 안의 애플리케이션은 파드의 일부로 정의되어, 각각의 애플리케이션의 파일시스템에 마운트 할 수 있도록 만들어진 공유 볼륨에 엑세스 할 수 있다.
도커의 구조 관점에서 보면 파드는 공유 네임스페이스와 공유 볼륨을 가진 도커 컨테이너 그룹으로 모델링 된다.
개별 애플리케이션 컨테이너와 같이, 파드는 상대적으로 수명이 짧은 엔터티로 간주된다. 파드의 생애에서 논의된 것과 같이, 파드가 만들어지고 고유한 ID(UID)가 할당되고, 재시작 정책에 따라서 종료 또는 삭제될 때 까지 노드에 스케줄된다. 노드가 종료되면 해당 노드로 스케줄 된 파드는 제한시간이 지나면 삭제되도록 스케줄된다. 해당 파드(UID로 정의된)는 새로운 노드에 "리스케줄(reschedule)" 되지 않는다. 대신, 동일한 파드로, 원한다면 이름도 동일하게, 교체될 수 있지만, 새로운 UID가 부여된다. 더 자세한 내용은 레플리케이션 컨트롤러를 참조한다.
볼륨과 같이 파드와 동일한 수명이 있다고 하면, UID를 포함한 해당 파드가 존재하는 한 그것도 존재한다는 것을 의미한다. 어떤 이유로든 해당 파드가 삭제 된 경우, 동일한 대체품이 만들어 지더라도 관련된 것(예 : 볼륨) 또한 삭제되고 새로 만들어진다.
파드 다이어그램
파일 풀러(Puller)와 컨테이너 간 공유 스토리지로 퍼시스턴트 볼륨을 사용하는 웹 서버를 포함하는 멀티 컨테이너 파드.
파드는 응집력 있는 서비스 단위를 형성하는 여러 개의 협력 프로세스를 모델로 한다. 파드는 그 구성 요소 집합보다 높은 수준의 추상화를 제공함으로써 애플리케이션 배포 및 관리를 단순화한다. 파드는 전개 단위, 수평 확장 및 복제를 한다. 공동 스케줄링, 공유된 생애주기(예: 종료), 조정된 복제, 자원 공유 및 종속성 관리는 파드의 컨테이너에 대해 자동으로 처리된다.
파드는 그 구성 요소 간에 데이터 공유 및 통신이 가능하다.
파드의 모든 애플리케이션은 동일한 네트워크 네임스페이스(동일한 IP 및 포트 공간)를 사용하므로 서로를 찾고 통신하는데 localhost
를 사용할 수 있다. 이 때문에 파드의 애플리케이션은 포트 사용을 조정 해야한다. 각 파드에는 다른 물리적 컴퓨터 및 파드들과 네트워크를 통해 통신할 수 있는 공유 네트워크 공간의 IP 주소가 있다.
호스트 이름은 파드 안에있는 애플리케이션 컨테이너의 파드 이름으로 설정된다. 더 자세한 내용은 네트워킹 섹션을 참조한다.
파드는 파드 안의 애플리케이션 컨테이너를 정의하는 것 이외에도 공유 저장 볼륨의 집합을 지정한다. 볼륨은 컨테이너가 재시작되어도 데이터가 생존할 수 있도록 하고, 파드 안의 애플리케이션들끼리 데이터를 공유할 수 있게 해준다.
파드는 수직으로 통합 된 애플리케이션 스택(예 : LAMP)을 호스팅하는 데 사용할 수 있다. 하지만, 주요 동기는 공동 배치 및 공동 관리되는 헬퍼(helper) 프로그램을 지원하는 것이다. 예를 들면,
컨텐츠 관리 시스템, 파일과 데이터 로더, 로컬 캐시 관리 등.
로그와 백업 체크포인트, 압축, 로테이션, 스냅샷 등.
데이터 변동 감시자, 로그 추적자, 로깅 및 모니터링 어댑터, 이벤트 관리 등.
프록시, 브릿지, 어댑터
컨트롤러, 매니저, 설정, 업데이트
일반적으로 하나의 파드는 동일한 애플리케이션의 여러 인스턴스를 실행하도록 사용하지 않는다.
더 자세한 설명을 보려면 분산 시스템 툴킷: 복합 컨테이너를 위한 패턴을 참조한다.
싱글 (도커)컨테이너에서 다중 프로그램을 실행하지 않는 이유는 무엇인가?
투명도. 인프라에 파드 내의 컨테이너를 표시하면, 인프라에서 프로세스 관리와 리소스 모니터링과 같은 기능을 제공할 수 있다. 이 기능들은 사용자에게 편의를 제공한다.
소프트웨어 의존성 분리. 각각의 컨테이너는 독립적으로 버전 관리, 재빌드, 재배포될 수 있다. 언젠가는 쿠버네티스에서 개별 컨테이너의 실시간 업데이트도 할 수 있을 것이다.
사용의 편의성. 사용자는 자신의 프로세스 매니저를 따로 실행 할 필요가 없고, 시그널이나 종료 코드(exit-code) 전파 등에 대해 걱정할 필요가 없다.
효율성. 인프라측에서 많은 책임을 가지고 있으므로, 컨테이너는 더 가벼워 질 수 있다.
컨테이너의 어피니티(affinity) 기반 공동 스케줄링을 지원하지 않는 이유는 무엇인가?
이와 같은 접근은 공동위치를 제공하지만, 리소스 공유, IPC, 보장된 생애 공유, 관리의 단순화와 같은 파드가 가진 대부분의 장점을 제공하지 못한다.
파드는 내구성이 강한 엔터티로 취급하지는 않는다. 파드는 스케줄링 실패, 노드 장애 또는 그 밖에 리소스가 부족해서, 또는 노드 정비를 위한 경우와 같이 축출(eviction)되는 상황에서는 살아남을 수 없을 것이다.
일반적으로 사용자는 파드를 직접 만들 필요가 없다. 싱글톤이라도 대부분 디플로이먼트(Deployment)와 같은 컨트롤러를 사용한다. 컨트롤러는 클러스터 범위에서 복제와 롤아웃 관리 뿐 만 아니라 자가치료 기능도 제공한다. 스테이트풀셋과 같은 컨트롤러는 상태를 저장하는 파드에도 위와 같은 기능 제공을 할 수 있다.
사용자 지향적으로 선정된 API를 사용하는 것은 Borg, Marathon, Aurora와 Tupperware를 비롯한 클러스터 스케줄링 시스템에서 비교적 일반적이다.
파드는 아래와 같은 사항들을 용이하게 하기 위해 노출이 된다:
스케줄러 및 컨트롤러 연결 가능
"프록시" 없이 컨트롤러 API를 통한 파드-레벨 수준의 동작 지원
부트스트랩과 같이 컨트롤러의 생애와 파드의 생애 분리
컨트롤러와 서비스의 분리 — 파드를 감시하는 엔드 포인트 컨트롤러
클러스터 레벨과 kubelet 레벨 기능의 깔끔한 구성 — Kubelet은 효과적인 "파드 컨트롤러" 이다.
계획된 삭제 또는 이미지 프리페칭과 같이 파드가 종료되기 전에 교체가 될 것이고, 삭제 전에는 확실히 교체되는 고가용성 애플리케이션.
파드는 클러스터의 노드에서 실행 중인 프로세스를 나타내므로, 이러한 프로세스가 더 이상 필요하지 않을 때(KILL 시그널로 강제로 죽여서 정리할 기회를 주지 않는 것과 대조적으로) 정상적으로 종료 되도록 허용하는 것이 중요하다. 사용자는 삭제를 요청할 수 있어야 하며, 프로세스가 종료 될 때 알 수 있어야 할 뿐만 아니라, 삭제가 결국 완료되는 것을 확인할 수 있어야 한다. 사용자가 파드를 삭제하도록 요청하면, 시스템은 파드가 강제로 종료되기 전에 예정된 유예 기간을 기록하고, TERM 시그널이 각 컨테이너의 주 프로세스로 전송된다. 유예 기간이 만료되면, KILL 신호가 해당 프로세스로 전송되고, 파드가 API 서버에서 삭제된다. 프로세스가 종료되기를 기다리는 동안 Kubelet 또는 컨테이너 관리자가 다시 시작되면, 종료가 전체 유예 기간과 함께 재시도된다.
흐름 예시:
사용자가 파드 삭제 명령을 내린다. (기본 유예 기간 30초)
API 서버 안의 파드는 유예 기간에 따라, 시간을 넘은(죽은) 것으로 간주되는 파드가 업데이트된다.
클라이언트 명령에서 파드는 "Terminating" 이라는 문구를 나타낸다.
(3번 단계와 동시에) Kubelet은 파드가 2번 단계에서 설정된 시간으로 인해 Terminating으로 표시되는 것을 확인하면 파드 종료 단계를 시작한다.
파드의 컨테이너 중 하나에 preStop hook이 정의된 경우, 해당 컨테이너 내부에서 실행된다. 유예 기간이 만료된 후에도 preStop
훅이 계속 실행 중이면, 유예 기간을 짧게(2초)를 1회 연장해서 2번 단계를 실행한다.
파드의 프로세스에 TERM 시그널이 전달된다. 파드의 모든 컨테이너가 TERM 시그널을 동시에 받기 때문에 컨테이너의 종료 순서가 중요한 경우에는 preStop
훅이 각각 필요할 수 있음을 알아두자. 만약 preStop
훅을 완료하는 데 더 오랜 시간이 필요한 경우 terminationGracePeriodSeconds
를 수정해야 한다.
(3번 단계와 동시에) 파드는 서비스를 위해 엔드포인트 목록에서 제거되며, 더 이상 레플리케이션 컨트롤러가 실행 중인 파드로 고려하지 않는다. 느리게 종료되는 파드는 로드밸런서(서비스 프록시와 같은)의 로테이션에서 지워지기 때문에 트래픽을 계속 처리할 수 없다.
유예 기간이 만료되면, 파드에서 실행중이던 모든 프로세스가 SIGKILL로 종료된다.
Kubelet은 유예기간 0(즉시 삭제)을 세팅하여 API 서버에서 파드 삭제를 끝낼 것이다. API 서버에서 사라진 파드는 클라이언트에게서 더 이상 보이지 않는다.
기본적으로 모든 삭제는 30초 이내에 끝이 난다. kubectl delete
명령은 사용자가 기본 설정을 오버라이드하고 자신이 원하는 값을 설정할 수 있게 해주는 --grace-period=<seconds>
옵션을 지원한다. 0
값은 파드를 강제로 삭제한다. kubectl 1.5 버전 이상에서는, 강제 삭제 수행을 위해서 반드시 --grace-period=0
와 함께 추가 플래그인 --force
를 지정해야 한다.
파드 강제 삭제는 클러스터 및 etcd에서 즉시 삭제하는 것으로 정의된다. 강제 삭제가 수행되면, API 서버는 kubelet에서 실행 중이던 노드에서 파드가 종료되었다는 확인을 기다리지 않는다. API에서 파드를 즉시 제거하므로 동일한 이름으로 새 파드를 만들 수 있다. 노드에서 즉시 종결되도록 설정된 파드에는 강제 삭제되기 전에 짧은 유예 기간이 주어진다.
강제 삭제는 일부 파드의 경우 잠재적으로 위험할 수 있으므로 주의해서 수행해야 한다. 스테이트풀셋 파드의 경우 스테이트풀셋 파드 삭제에 대한 작업 문서를 참조한다.
파드의 모든 컨테이너는 컨테이너 스펙의 시큐리티 콘텍스트(security context)의 privileged
플래그를 사용하여 특권 모드를 사용할 수 있다. 이것은 네트워크 스택을 조작하고 장치에 액세스하는 것과 같은 리눅스 기능을 사용하려는 컨테이너에 유용하다. 컨테이너 내의 프로세스는 컨테이너 외부의 프로세스에서 사용할 수 있는 거의 동일한 권한을 갖는다. 특권 모드를 사용하면 네트워크 및 볼륨 플러그인을 kubelet에 컴파일할 필요가 없는 별도의 파드로 쉽게 만들 수 있다.
참고: 이와 같은 설정을 위해서는 컨테이너 런타임에서 반드시 특권 컨테이너 개념을 지원해야 한다.