[kubernetes] Pod의 모든 것-2

2해승·2024년 7월 25일

쿠버네티스?!

목록 보기
7/16

지난 글에 이어서 파드에 관한 남은 주제를 다뤄보자.

  • Pod의 개념과 Single Container Pod 실행 방법
  • Multi Container Pod
  • livenessProbe를 이용한 Self-healing Pod 생성하기
  • Init Container
  • Infra Container(pause) 이해하기
  • Static Pod 생성하기
  • Pod에 리소스(cpu, memory) 할당하기
  • Pod의 환경변수 설정하기

Init Container

init container는 파드의 앱 컨테이너들이 실행되기 전에 미리 동작시키는 특수한 컨테이너이다. 본 컨테이너(main container)가 실행되기 전에 사전 작업이 필요한 경우 사용한다.

init container는 다음과 같은 특징을 제외하고는 일반 컨테이너와 매우 유사하다고 한다.

  • 초기화 컨테이너는 항상 완료를 목표로 실행된다.
  • 각 초기화 컨테이너는 다음 초기화 컨테이너가 시작되기 전에 성공적으로 완료되어야 한다.

만약 파드의 초기화 컨테이너가 실패하면 kubelet은 초기화 컨테이너가 성공할 때까지 반복적으로 재시작한다.

예를들어 로그인 기능이 존재하는 컨테이너는 로그인을 위해서 DB에 존재하는 회원정보를 불러와야한다. 이때 DB에 접속하여 회원정보를 우선으로 가져오는 컨테이너를 생성할 수 있는데 해당 컨테이너가 바로 init container가 되고 로그인 컨테이너가 main container가 된다.

이 컨테이너들을 하나의 파드로 동작시키면 회원정보를 가져오는 init container가 성공해야지만 main container를 동작시켜주는 구조이다.

Init Container 예제

init container에 관한 설정을 다음과 같이 설정하고 파드의 상태를 관찰해보자.

// init-container-exam.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app.kubernetes.io/name: MyApp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
$ kubectl create -f init-container-exam.yaml 
pod/myapp-pod created

$ kubectl get pods
NAME        READY   STATUS     RESTARTS   AGE
myapp-pod   0/1     Init:0/2   0          3s

STATUS 값이 Init:0/2로 확인되는 것을 볼 수 있는데 이는 yaml 파일에 설정된 init container에 대한 작업이 완료되면 Running으로 변경될 것이다.

describe의 event 로그를 확인해보자.

Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  62s   default-scheduler  Successfully assigned default/myapp-pod to test-cluster-worker2
  Normal  Pulling    61s   kubelet            Pulling image "busybox:1.28"
  Normal  Pulled     57s   kubelet            Successfully pulled image "busybox:1.28" in 4.424s (4.424s including waiting). Image size: 766512 bytes.
  Normal  Created    57s   kubelet            Created container init-myservice
  Normal  Started    57s   kubelet            Started container init-myservice
  Normal  Pulled     56s   kubelet            Container image "busybox:1.28" already present on machine
  Normal  Created    56s   kubelet            Created container init-mydb
  Normal  Started    56s   kubelet            Started container init-mydb
  Normal  Pulled     55s   kubelet            Container image "busybox:1.28" already present on machine
  Normal  Created    55s   kubelet            Created container myapp-container
  Normal  Started    55s   kubelet            Started container myapp-container

순차적으로 init-myservice 컨테이너 실행 -> init-mydb 컨테이너 실행 이후 myapp-container 컨테이너가 실행되어 파드의 상태가 정상적으로 동작되었다.

NAME        READY   STATUS    RESTARTS   AGE
myapp-pod   1/1     Running   0          6m21s

Infra Container(pause) 이해하기

파드는 컨테이너로 구성되어 있으며 파드가 생성될 때 기본적으로 infra container(pause)가 함께 생성된다. 해당 컨테이너는 파드에 대한 Infra(IP, hostname)을 생성하고 관리하는 역할을 한다.

주로 파드 내의 네트워크 통신 및 파일 시스템 공유를 관리하는데 사용되고 여러 컨테이너가 함께 실행되는 경우 일부 동직을 지원하기도 한다.

  • Network Namespace 공유 : 파드 내의 모든 다른 컨테이너들이 동일한 네트워크 네임스페이스를 공유할 수 있도록 하는 역할을 한다. 이를 통해 같은 파드에 속한 컨테이너들이 동일한 네트워크 인터페이스 및 IP 주소를 사용할 수 있다.

  • IPC (Inter-Process Communication) 공유 : 다른 컨테이너 간의 프로세스 통신을 위해 IPC 네임스페이스를 공유하는 데 사용된다. 이를 통해 같은 파드 내의 다른 컨테이너들이 서로 통신할 수 있다.

  • Volume 마운트 공유 : 파드 내의 다른 컨테이너들이 공유하는 Volumn을 마운트하는 역할을 한다. 이를 통해 파드 내의 컨테이너들이 동일한 파일 시스템을 사용할 수 있다.

Static Pod 만들기

Static Pod는 API 서버 없이 특정 노드에 있는 kubelet 데몬에 의해 직접 관리된다. Control-Plane에 의해 관리되는 파드와는 달리 kubelet이 각각의 static pod를 감시하기 때문에 항상 특정 노드에 있는 하나의 kubelet에 매여있는 것이 특징이다.

static pod의 예제는 쿠버네티스 공식 문서에서 자세히 설명하고 있기 때문에 링크로 대체하도록 하겠다.

Static Pod 생성하기

유의할 점으로는 kubelet의 설정 파일에서 staticPodPath의 경로를 확인한 다음에 쿠버네티스 yaml 파일을 생성해야한다.

(일반적으로 staticPodPath는 /etc/kubernetes/manifests를 사용함)

Pod에 리소스(cpu, memory) 할당하기

쿠버네티스는 파드를 어느 노드에 배포할지 스케줄러가 정하는데 스케줄러는 새로운 파드를 각 노드의 리소스 사용량에 따라 배치 기준을 판단한다.

쿠버네티스는 CPU와 Memory를 관리하고 기본적으로 컨테이너 단위로 리소스를 제한한다. 이때 리소스에 제한을 두지않으면 해당 노드에 할당된 컨테이너가 노드의 모든 리소스를 사용할 수 있는데 이는 새로운 파드가 스케줄링되지 않는 경우가 발생 수 있다.

따라서 해당 파드의 리소스 사용량을 결정하고 Limit를 적절하게 걸어주어야 한다. 예시 파일을 통해 설정하는 방법에 대해 알아보자.

requests, limits 둘 다 설정하기

// pod-nginx-resorce.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod-resource
spec:
  containers:
  - name: nginx-container
    image: nginx:1.14
    ports:
    - containerPort: 80
      protocol: TCP
    resources:
      requests:
        cpu: 200m
        memory: 250Mi
      limits:
        cpu: 1
        memory: 500Mi

yaml 파일 하단을 보면 resources 항목을 확인할 수 있다. 여기서 파드의 리소스를 요청하고 제한할 수 있는데 각 설정 값이 의미하는 바는 다음과 같다.

  • requests: 파드를 실행하기 위한 최소 리소스 양을 요청
  • Limits: 파드가 사용할 수 있는 최대 리소스 양을 제한 -> memory limit를 초과해서 사용되는 파드는 종료되며 다시 스케줄링 된다.

설정된 리소스에 대해서는 describe 명령어를 통해 자세한 확인이 가능하다.

$ kubectl describe pod nginx-pod-resource
Name:             nginx-pod-resource
Namespace:        default
.
.
.
  Limits:
    cpu:     1
    memory:  500Mi
  Requests:
    cpu:        200m
    memory:     250Mi

하나씩만 설정할 경우

1. requests만 설정할 경우

requests에 설정한 리소스만큼 여유가 있는 노드에 배치해달라고 요청한다. requests의 경우 limits는 자동으로 설정되지 않는다.

2. limits만 설정할 경우

파드가 사용할 수 있는 최대 리소스 양을 제한하는 것이기 때문에 requests 값이 Limits와 동일한 값으로 설정된다.

Pod의 환경변수 설정하기

파드 내의 컨테이너가 실행될 때 필요한 변수를 컨테이너 제작 시 yaml 파일로 미리 정의 할 수 있다.

  • ex) Database를 설치하고 접속 유저정보를 불러오기 등...
// pod-nginx-env.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod-env
spec:
  containers:
  - name: nginx-container
    image: nginx:1.14
    ports:
    - containerPort: 80
      protocol: TCP
    env:
    - name: MYVAR
      value: "testvaule"

yaml 파일을 통해 환경변수가 설정된 파드를 실행하고 컨테이너 내에 적용이 잘 됐는지 확인할 수 있다.

exec 명령어를 통해 컨테이너 내부로 접속해보자.

$ kubectl exec nginx-pod-env -it -- /bin/bash

이렇게 내부에서 사전에 설정한 환경변수가 적용된 것을 확인할 수 있다!

쿠버네티스 공식 문서
infra container
Pod 리소스 할당

profile
주니어 데브옵스 엔지니어

0개의 댓글