본문 바로가기

Infrastructure/Kubernetes

[Pod] 개념

파드

쿠버네티스 공식문서를 확인하며 파드에 대해서 기억해야 하는 부분을 기록한다.

  • “파드”는 쿠버네티스에서 생성하고 관리할 수 있는 배포 가능한 가장 작은 컴퓨팅 단위이며 하나 이상의 컨테이너의 그룹이다.
  • “그룹”은 스토리지 및 네티워크를 공유하고, 해당 컨테이너를 구동하는 방식에 대한 명세를 갖는다.
  • “파드의 콘텐츠”는 항상 함께 배치되고, 함께 스케줄되며, 공유 콘텍스트에서 실행된다.
  • 파드는 애플리케이션 별 “논리 호스트"를 모델링한다. 여기에는 상대적으로 밀접하게 결합된 하나 이상의 애플리케이션 컨테이너가 포함된다.
  • 클라우드가 아닌 콘텍스트에서, 동일한 물리 또는 가상 머신에서 실행되는 애플리케이션은 동일한 논리 호스트에서 실행되는 클라우드 애플리케이션과 비슷하다.
  • 애플리케이션 컨테이너와 마찬가지로, 파드에는 파드 시작 중에 실행되는 초기화 컨테이너가 포함될 수 있고 클러스터가 제공하는 경우, 디버깅을 위해 임시 컨테이너를 삽입할 수도 있다.

[정리]

파드는 쿠버네티스에서 컨테이너를 관리하는 가장 작은 컴퓨팅 단위이며 컨테이너의 그룹이다.

애플리케이션을 실행시키는 애플리케이션 컨테이너가 일반적으로 사용되지만 필요에 따라, 파드의 시작을 담당하는 초기화 컨테이너나 디버깅을 위한 임시 컨테이너도 사용할 수 있다.


파드란 무엇인가?

  • 파드의 공유 컨텍스트는 리눅스 네임스페이스, 컨트롤 그룹(cgroup) 및 도커 컨테이너를 격리하는 것과 같이 잠재적으로 다른 격리 요소들이며 파드의 컨텍스트 내에서 개별 애플리케이션은 추가적으로 하위 격리가 적용된다.
  • 도커 개념 측면에서, 파드는 공유 네임스페이스와 공유 파일시스템 볼륨이 있는 도커 컨테이너 그룹과 비슷하다.
  • 도커가 가장 일반적으로 잘 알려진 컨테이너 런타임이지만, 쿠버네티스는 도커 외에도 다양한 컨테이너 런타임을 지원하며, 파드를 설명할 때 도커 관련 용어를 사용하면 더 쉽게 설명할 수 있다.

[정리]

파드의 공유 컨텍스트는 리눅스 네임스페이스, 컨트롤 그룹, 도커 컨테이너를 격리하는 것과 같이 잠재적으로 다른 격리 요소들이며 파드의 컨텍스트 내에서 하위 격리가 적용된다. 도커의 개념과 같이 파드는 공유 네임스페이스와 공유 파일시스템 볼륨이 있는 도커 컨테이너 그룹과 비슷하다.


파드의 사용

  • 아래는 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) 리소스를 고려한다.
  • 쿠버네티스 클러스터 파드는 두 가지 주요 방식으로 사용된다.
    • 단일 컨테이너를 실행하는 파드: “파드 당 하나의 컨테이너” 모델은 가장 일반적인 쿠버네티스 유스케이스다. 이 경우, 파드를 단일 컨테이너를 둘러싼 래퍼로 생각할 수 있고 쿠버네티스는 컨테이너를 직접 관리하는 대신 파드를 관리한다.
    • 함께 작동해야 하는 여러 컨테이너를 실행하는 파드: 파드는 밀접하게 결합되어 있고 리소스를 공유해야 하는 함께 배치된 여러 개의 컨테이너로 구성된 애플리케이션을 캡슐화할 수 있다. 이런 함께 배치된 컨테이너는 하나의 결합된 서비스 단위를 형성한다. 하나의 컨테이너는 공유 볼륨에 저장된 데이터를 퍼블릭에 제공하는 반면, 별도의 “사이드카” 컨테이너는 해당 파일을 새로 고치거나 업데이트한다. 파드는 이러한 컨테이너, 스토리지 리소스, 임시 네트워크 ID를 단일 단위로 함께 래핑한다.
  • 단일 파드에서 함께 배치된 또는 함께 관리되는 여러 컨테이너를 그룹화하는 것은 비교적 고급 유스케이스이며 이러한 패턴은 컨테이너가 밀접하게 결합된 특정 인스턴스에서만 사용해야 한다.
  • 각 파드는 특정 애플리케이션의 단일 인스턴스를 실행하기 위한 것이다.
  • 더 많은 인스턴스를 실행하여 더 많은 전체 리소스를 제공하기 위해 애플리케이션을 수평적으로 확장하려면, 각 인스턴스에 하나씩 여러 파드를 사용해야 한다.
  • 쿠버네티스에서는 이를 일반적으로 레플리케이션이라고 하고 복제된 파드는 일반적으로 워크로드 리소스와 해당 컨트롤러에 의해 그룹으로 생성되고 관리된다.

[정리]

일반적으로 사용자가 직접 파드를 생성하는 일은 없으며 디플로이먼트 또는 잡과 같은 워크로드 리소스를 사용하여 생성한다.

단일 컨테이너를 실행하는 파드는 가장 기본적인 디자인이며 이때의 파드는 컨테이너를 감싸는 래퍼이며 쿠버네티스는 컨테이너를 관리하는 대신 파드를 관리한다.

하나의 파드에서 다중 컨테이너를 실행시키는 디자인은 밀접하게 관련되어 있는 애플리케이션을 실행시킬 때 사용되는 디자인이다. 같은 파드에서 실행되어 애플리케이션을 캡슐화 할 수 있고, 단일 파드 내에서 스토리지 리소스, 임시 네트워크 ID를 단일 단위로 래핑할 수 있다.

애플리케이션을 수평적으로 확장하기 위해서는 각 인스턴스에 하나씩 여러 파드를 사용해야 한다. 일반적으로 워크로드 리소스와 해당 컨트롤러를 통해 그룹으로 생성되고 관리된다.


파드가 여러 컨테이너를 관리하는 방법

  • 파드는 응집력있는 서비스 단위를 형성하는 여러 협력 프로세스(컨테이너)를 지원하도록 설계되었다.

  • 파드의 컨테이너는 클러스터의 동일한 물리 또는 가상 머신에서 자동으로 같은 위치에 배치되고 함께 스케줄된다.

  • 컨테이너는 리소스와 의존성을 공유하고, 서로 통신하고, 종료 시기와 방법을 조정할 수 있다.

  • 아래의 그림에서와 같이 공유 볼륨의 파일에 대한 웹 서버 역할을 하는 컨테이너와 원격 소스에서 해당 파일을 업데이트하는 별도의 “사이드카” 컨테이너가 있을 수 있다.

  • 일부 파드에는 앱 컨테이너 뿐만 아니라 초기화 컨테이너를 가지고 있다. 초기화 컨테이너는 앱 컨테이너가 시작되기 전에 실행되고 완료된다.

  • 파드는 기본적으로 파드에 속한 컨테이너에 네트워킹과 스토리지라는 두 가지 종류의 공유 리소스를 제공한다.

[정리]

파드는 서비스 단위를 형성하는 여러 협력 프로세스를 지원하도록 설계되었다. 동일한 파드의 컨테이너는 클러스터의 동일한 물리 또는 가상 머신에서 자동으로 같은 위치에 배치되어 스케줄링 된다. 각각의 컨테이너는 리소스와 의존성을 공유하기 때문에 동일한 저장소를 업데이트 하는(File Puller) 컨테이너와 제공하는(Web Server) 컨테이너가 위치할 수 있다.


파드 작업

  • 사용자가 쿠버네티스에서 직접 개별 파드나 싱글톤 파드를 만드는 경우는 거의 없다. 파드가 상대적으로 일시적인, 일회용 엔티티로 설계되었기 때문이다.
  • 사용자가 직접 또는 간접적으로 파드를 생성하면 새 파드는 클러스터의 노드에서 실행되도록 스케줄된다.
  • 파드는 파드 실행이 완료, 삭제, 리소스 부족으로 인한 축출, 실패할 때까지 해당 노드에 남아있는다.
  • 파드에서 컨테이너를 다시 시작하는 것과 파드를 다시 시작하는 것을 혼동해서는 안된다. 파드는 프로세스가 아니라 컨테이너를 실행하기 위한 환경이므로 파드는 삭제될 때까지 유지된다.
  • 파드 오브젝트에 대한 매니페스트를 만들 때, 지정된 이름이 유효한 DNS 서브도메인 이름인지 확인해야 한다.

파드와 컨트롤러

  • 워크로드 리소스를 사용하여 어러 파드를 만들고 관리할 수 있다. 리소스에 대한 컨트롤러는 파드 장애 시 복제 및 롤아웃과 자동 복구를 처리한다.
  • 컨트롤러는 해당 노드의 파드가 작동을 중지했음을 인식하고 대체 파드를 생성하고 스케줄러는 대체 파드를 정상 노드에 배치한다.
  • 아래는 하나 이상의 파드를 관리하는 워크로드 리소스의 예시이다.
    • 디플로이먼트(Deployment)
    • 스테이트풀셋(StatefulSet)
    • 데몬셋(DaemonSet)

파드 템플릿

  • 워크로드 리소스에 대한 컨트롤러는 파드 템플릿에서 파드를 생성하고 사용자 대신 해당 파드를 관리한다.
  • 파드 템플릿(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
    # 여기까지 파드 템플릿이다
  • 파드 템플릿을 수정하거나 새로운 파드 템플릿으로 바꿔도 이미 존재하는 파드에는 직접적인 영향을 주지 않는다. 워크로드 리소스의 파드 템플릿을 변경하는 경우, 해당 리소스는 수정된 템플릿을 사용하는 대체 파드를 생성해야 한다.
  • 스테이트풀셋 컨트롤러는 실행 중인 파드가 각 스테이트풀셋 오브젝트가 현재 파드 템플릿과 일치하는지 확인한다. 만약 스테이트풀셋을 수정하여 파드 템플릿을 변경되면, 스테이트풀셋이 업데이트된 템플릿을 기반으로 새로운 파드를 생성하기 시작하고 모든 파드가 새로운 파드로 교체된다.
  • 각 워크로드 리소스는 파드 템플릿과 업데이트에 대한 상세 정보를 직접 관찰하거나 관리하지 않고 추상화된다.
  • 이러한 추상화와 관심사 분리(separation of concerns)는 시스템 시맨틱을 단순화하고, 기존 코드를 변경하지 않고도 클러스터의 동작을 확장할 수 있게 한다.

[정리]

쿠버네티스에서 파드는 일회용 엔티티로 설계되었기 때문에 사용자가 직접 생성할 일은 없고 워크로드 리소스에 의해 관리된다. 파드는 컨테이너가 실행되는 환경이기 때문에 파드당 컨테이너가 실행되고 있더라도 파드와 컨테이너를 동일하게 바라봐서는 안된다.

파드에 문제가 발생한 경우 컨트롤러는 새로운 파드를 생성하고 스케줄러는 새롭게 생성된 파드를 노드에 배치한다.

워크로드 리소스는 컨트롤러를 통해서 파드를 관리할 때 파드 템플릿을 통해서 관리한다.

파드 템플릿의 내용이 수정되는 경우 이전에 생성된 파드에는 영향을 주지 않기 때문에 기존에 사용되던 파드는 삭제하고 새로운 대체 파드를 생성해야 한다.


파드 갱신 및 교체

  • 워크로드 리소스의 파드 템플릿이 바뀌면 컨트롤러는 기존의 파드를 갱신하거나 배치하는 대신 갱신된 템플릿을 기반으로 신규 파드를 생성한다.
  • 쿠버네티스는 사용자가 파드를 직접 관리하는 것을 막지 않기 때문에 동작 중인 파드의 필드를 갱신하는 것도 가능하다. 하지만 patch, replace와 같은 파드 갱신 작업에는 아래와 같은 제약사항이 있다.
    • 파드에 대한 대부분의 메타데이터는 불변(immutable)이다. 사용자는 namespace, name, uid, creationTimestamp필드를 변경할 수 없고 generation 필드는 고유하다.
    • metadata.deletionTimestamp가 설정된 경우, metadata.finalizers 리스트에 새로운 항목이 추가될 수 없다.
    • 파드 갱신은 spec.containers[*].image, spec.initContainers[*].image, spec.activeDeadlineSeconds 또는 spec.tolerations 이외의 필드는 변경하지 않고 spec.tolerations 필드에만 값을 추가할 수 있다.
    • spec.activeDeadlineSeconds 필드를 추가할 때는, 아래의 두 가지 형태의 갱신만 허용된다.
      • 지정되지 않은 필드를 양수로 설정.
      • 필드의 양수를 음수가 아닌 더 작은 숫자로 갱신.

[정리]

쿠버네티스는 사용자가 직접 파드를 관리하는 것을 막지 않지만 일부 필드에는 제약사항이 있다.


리소스 공유와 통신

  • 파드는 파드에 속한 컨테이너 간의 데이터 공유와 통신을 지원한다.

파드 스토리지

  • 파드는 공유 스토리지 볼륨의 집합을 지정할 수 있다.
  • 파드의 모든 컨테이너는 공유 볼륨에 접근할 수 있으므로, 해당 컨테이너가 데이터를 공유할 수 있다.
  • 볼륨은 내부 컨테이너 중 하나를 다시 시작해야 하는 경우 파드의 영구 데이터를 유지하도록 허용한다.

파드 네트워킹

  • 각 파드에는 각 주소 패밀리에 대해 고유한 IP 주소가 할당된다.
  • 파드의 모든 컨테이너는 네트워크 네임스페이스를 공유하며, 여기에는 IP 주소와 네트워크 포트가 포함된다.
  • 파드 내부에서, 파드에 속한 컨테이너는 localhost를 사용하여 서로 통신할 수 있다. 파드의 컨테이너가 파드 외부의 엔티티와 통신할 때, 공유 네트워크 리소스를 사용하는 방법을 조정해야 한다.
  • 파드 내에서 컨테이너는 IP 주소와 포트 공간을 공유하며, localhost를 통해 서로를 찾을 수 있다.
  • 파드의 컨테이너는 SystemV 세마포어 또는 POSIX 공유 메모리와 같은 표준 프로세스 간 통신을 사용하여 서로 통신할 수도 있다.
  • 다른 파드의 컨테이너는 고유한 IP 주소를 가지며 특별한 구성 없이 OS 수준의 IPC로 통신할 수 없다.
  • 다른 파드에서 실행되는 컨테이너와 상호 작용하려는 컨테이너는 IP 네트워킹을 사용하여 통신할 수 있다.
  • 파드 내의 컨테이너는 시스템 호스트명이 파드에 대해 구성된 **name과 동일한 것으로 간주**한다.

[정리]

파드는 파드에 속한 컨테이너가 공유 볼륨에 접근할 수 있게 설정하여 데이터 공유와 통신을 지원한다. 공유 볼륨이기 때문에 컨테이너를 다시 시작해야 하는 경우에도 데이터가 영구적으로 유지된다.

각 파드에는 고유한 IP주소와 IP주소와 네트워크 포트가 포함된 네트워크 네임스페이스를 공유한다.

파드 내부에서는 동일한 네트워키에 속하기 때문에 localhost를 사용하여 통신이 가능하다. 하지만 다른 파드의 컨테이너는 또 다른 고유한 IP 주소를 가지고 있기 때문에 특별한 구성 없이 OS 수준의 IPC로 통신할 수 없다.


컨테이너에 대한 특권 모드

  • 리눅스에서, 파드의 모든 컨테이너는 컨테이너 명세의 보안 컨텍스트에 있는 **privileged 플래그를 사용하여 특권 모드를 활성화**할 수 있다.
  • 특권 모드는 네트워크 스택 조작이나 하드웨어 장치 접근과 같은 운영 체제 관리 기능을 사용하려는 컨테이너에 유용하다.
  • 클러스터가 WindowsHostProcessContaienrs 기능을 활성화하였다면, 파드 스펙의 보안 컨텍스트의 windowsOptions.hostProcess에 의해 윈도우 HostProcess 파드를 생성할 수 있다. 모든 컨테이너는 윈도우 HostProcess 컨테이너로 실행해야 한다.
  • HostProcess 파드는 직접적으로 호스트에서 실행하는 것으로, 리눅스 특권이 있는 컨테이너에서 수행되는 관리 태스크 수행에도 사용할 수 있다.
  • 파드의 모든 컨테이너는 윈도우 HostProcess 컨테이너로 반드시 실행해야 한다.
  • HostProcess 파드는 호스트에서 직접 실행되며 리눅스 특권이 있는 컨테이너에서 수행되는 것과 같은 관리 작업을 수행하는데도 사용할 수 있다.
  • 특권 모드를 사용하려면 사용자의 컨테이너 런타임이 특권이 있는 컨테이너의 개념을 지원해야 한다.

[정리]

리눅스에서 특권 모드를 사용할 수 있고 운영 체제의 관리 기능을 사용할 때 유용하게 사용할 수 있다.


정적(static) 파드

  • 정적 파드는 API 서버가 관찰하는 대신 특정 노드의 kubelet 데몬에 의해 직접 관리된다.
  • 대부분의 파드는 컨트롤 플레인에 의해 관리되고 정적 파드의 경우 kubelet이 각 정적 파드를 직접 감독한다.
  • 정적 파드는 항상 특정 노드의 kubelet 하나에 바인딩된다.
  • 정적 파드의 주요 용도는 자체 호스팅 컨트롤 플레인을 실행하는 것이다. 즉, kubelet을 사용하여 개별 컨트롤 플레인 컴포넌트를 감독한다.
  • kubelet은 자동으로 각 정적 파드에 대한 쿠버네티스 API 서버에서 미러 파드를 생성하려고 한다. 즉, 노드에서 실행되는 파드는 API 서버에서 보이지만, 여기에서 제어할 수는 없다는 의미이다.
  • 정적 파드의 스펙(spec)은 다른 API 오브젝트가 참조할 수 없다.

[정리]

정적 파드는 특정 노드의 kubelet 데몬에 의해 직접 관리하고 kubelet 하나에 바인딩된다.

주로 사용되는 용도는 자체 호스팅 컨트롤 플레인을 실행하는 것이고 kubelet을 사용하여 개별 컨트롤 플레인 컴포넌트를 감독한다. kubelet은 자동으로 각 정적 파드에 대한 쿠버네티스 API 서버에서 미러 파드를 생성한다.

생성된 정적 파드의 스펙은 다른 API 오브젝트에서 참조할 수 없다.


컨테이너 프로브

  • “프로브”는 컨테이너의 kubelet에 의해 주기적으로 실행되는 진단이다. 진단을 수행하기 위하여 kubelet은 아래와 같은 작업을 호출할 수 있다.
    • ExecAction: 컨테이너 런타임의 도움을 받아 수행
    • TCPScoketAction: kubelet에 의해 직접 검사
    • HTTPGetAction: kubelet에 의해 직접 검사

참고 자료

'Infrastructure > Kubernetes' 카테고리의 다른 글

[Pod] 초기화 컨테이너  (0) 2022.10.18
[Pod] 라이프사이클  (0) 2022.10.18
[워크로드] 개념  (0) 2022.10.14
[컨테이너] 환경변수와 라이프사이클 훅(Hook)  (0) 2022.10.14
[컨테이너] 런타임클래스  (0) 2022.10.14