Pod

노재원·2022년 4월 14일
0

Kubernetes

목록 보기
2/8
post-thumbnail

쿠버네티스에서 어플리케이션을 띄울 때 가장 작은 기본 단위

Pod 구조


쿠버네티스(k8s)는 컨테이너 오케스트레이션(Container Orchestration) 툴이기 때문에 모든 어플리케이션이 컨테이너에서 동작한다. 쿠버네티스의 기본 단위가 파드이며, 한 파드는 여러 컨테이너를 포함할 수 있다. 왜 쿠버네티스는 컨테이너를 직접 다루지 않고 파드라는 단위를 만들어서 관리할까

하나의 컨테이너는 오직 하나의 프로세스를 돌리는 것이 목적이다. 이 때문에 컨테이너에는 systemd와 같은 프로세스 관리자가 없다 (물론 설치해서 만들 수도 있다). 그래서 만약 컨테이너에 여러 어플리케이션을 돌리게 되면, 컨테이너 안에서 실행되는 모든 어플리케이션의 관리는 모두 사용자 책임이다. 예를 들어 프로세스 재시작이나 로그 관리 같은 것들이 전부 사용자가 관리해야 한다. 따라서 하나의 컨테이너에 다중 프로세스보다 다중 컨테이너 구조가 쿠버네티스에 적합하며, 다중 컨테이너를 쉽게 관리하기 위한 것이 파드라고 할 수 있다.

파드 단위로 관리하게 되면 여러 장점이 있다. 보통 파드 하나에 한 개의 컨테이너가 있지만, 위에서 언급했듯이 한 컨테이너에 여러 어플리케이션을 넣는 대신, 여러 어플리케이션을 각각 컨테이너에 실행시킨 후 해당 컨테이너들을 하나의 파드로 관리한다. 보통 이런 경우는 어플리케이션 간의 긴밀한 관계가 있는데, 하나의 파드에 있으면 디렉토리 공유, 네트워크 공유가 가능하기 때문에, 한 컨테이너에 포함되어 있는 것처럼 동작한다. 쿠버네티스에서 파드 내에 컨테이너들은 같은 리눅스 네임스페이스를 공유하도록 설정했기 때문에 가능하다.

파드 안에 여러 컨테이너를 삽입하는 경우는 주로 해당 컨테이너들이 같은 호스트에서 실행돼야 하는지 여부를 따져서 판단한다.

Pod Network


원래 컨테이너들은 리눅스 네임스페이스가 다르기 때문에 서로 완전히 분리되어 있다. 하지만 파드 안의 컨테이너들은 같은 네트워크 네임스페이스를 공유하기 때문에 IP와 포트공간을 공유하게 된다. 이 말은 파드 안의 컨테이너들은 서로 localhost로 접근이 가능하며, 다른 컨테이너에서 사용하는 포트번호를 또 다른 컨테이너에선 사용할 수 없다는 것이다.

컨테이너 런타임에 따라 다르지만, 가장 많이 사용하는 도커의 경우에는 파드 안의 컨테이너들이 같은 리눅스 네임스페이스를 공유하도록 하는 것이 pause 컨테이너 이다.

파드 간에는 플랫 네트워크 위에 있어서 서로의 고유한 파드IP를 가지고 직접 통신할 수 있다. 파드가 어떤 노드에 떠 있는지는 상관없이 접근가능하며, 이는 CNI를 통해 이루어진다.

Pause Container


도커 기반의 쿠버네티스를 설치하면 /pause 명령어로 시작하는 컨테이너들이 꽤 많이 보일 것이다. 이는 파드의 컨테이너들이 같은 리눅스 네임스페이스를 공유할 수 있도록 하는 아주 중요한 역할을 하는 컨테이너이기 때문이다.

이외에도 다른 역할이 있는데 바로 좀비 프로세스를 거둬들이는 역할이다. pause 컨테이너가 PID 네임스페이스도 공유하게 되는데, 그러면 pause 컨테이너가 파드에서 Init Process 역할을 하게 되고, 이는 pause 컨테이너가 부모 프로세스가 된다는 의미이다. 그러면 다른 컨테이너에서 좀비 프로세스가 생겨도 pause 컨테이너가 해당 프로세스를 자식 프로세스로 물려받기 때문에 좀비 프로세스를 거둬들이는 효과가 발생한다.

Liveness Probe


어플리케이션의 오류로 컨테이너가 죽으면, kubelet이 이를 알아채고 해당 컨테이너를 재시작한다. 하지만 만약 어플리케이션이 무한 루프에 빠져서 오류 발생은 안했지만 제대로 기능을 하지 못할 땐 kubelet도 이를 감지하지 못한다. liveness probe 는 이런 상황을 kubelet이 인지하게 해주는 수단이다. 그래서 어플리케이션이 정상적이지 않는다고 판단하면 해당 파드를 재시작시킨다.

프로브는 HTTP, TCP, 그리고 Exec 총 3가지 방법이 있다. 웹서버의 경우 주로 HTTP 프로브를 많이 사용한다.

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  containers:
  - name: liveness
    image: k8s.gcr.io/liveness
    args:
    - /server
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
      initialDelaySeconds: 3
      periodSeconds: 3

웹 서버를 구현할 때 /healthz uri에 200 응답을 줄 수 있도록 구현을 해놓고, 위와 같이 프로브를 추가한 파드를 띄우면 웹 서버가 기능 오류로 요청을 받지 못하는 상황일 때 kubelet이 이를 감지하고 컨테이너를 강제 종료 후 재시작한다.

  • 주의사항
    1. 어플리케이션 내부만 체크해야지, 외부 요인에 영향을 받지 않도록 해야 한다. 예를 들어 프론트 엔드가 db연결에 실패한 것에 대한 프로브를 설정하는 경우가 있다. 이는 프론트 엔드 문제가 아니라 db문제 일수도 있기 때문이다.
    2. 되도록 1초 안에 완료되도록 가볍게 만드는 것이 좋다. 너무 무거우면 컨테이너 성능이 저하 될 수 있다.
    3. yaml에서 프로브에 대한 여러 옵션을 제공하고 있으므로, 프로브 자체에서 재시도 로직은 없는 것이 좋다.

Readiness Probe

liveness probe 는 어플리케이션의 오류로 인해 컨테이너를 재시작하는데 반해, readiness probe 는 데이터 로딩 등의 무거운 작업이나 외부 서비스 의존성으로 인해서 일시적으로 서비스 불가 상태일 때 사용한다. 컨테이너가 서비스를 할 수 없는 상태라고 인식하면 재시작하지 않고 서비스 목록에서 제외시킨다. 컨테이너의 상태를 NotReady로 변경해서 요청이 가지 않도록 막는 것이다. 이렇게 하는 이유는 readiness probe로 체크하는 케이스는 단순히 재시작한다고 해서 해결되는 케이스로 보지 않기 때문이다.

사용법은 liveness probe 와 완전히 동일하며, 이름만 livenessProbe에서 readinessProbe로 수정해서 사용한다.

Reference

159. [Kubernetes] Pause 컨테이너의 역할과 원리 (원문: The Almighty Pause Container)

[번역] 쿠버네티스 네트워킹 이해하기#1: Pods

0개의 댓글