k8s - Pod!

개요

Pod : 고래의 떼(pod of whales)

파드는 쿠버네티스 애플리케이션의 기본 실행 단위,
쿠버네티스 객체 모델 중 만들고 배포할 수 있는 가장 작고 간단한 단위.

아래와 같은 특성을 가진다.

  • 파드에는 하나 이상의 컨테이너가 들어있다.
  • 파드안의 컨테이너는 반드시 동일한 노드에 배치된다.
  • 어플리케이션 스케일 아웃은 파드단위로 이루어진다.
  • 파드안의 컨테이너는 네트워크와 스토리지를 공유한다.
  • 각 파드에는 고유한 IP 주소가 할당되며 파드 내부의 컨테이너는 해당 IP 를 공유한다.
  • 파드는 컨테이너뿐 아니라 스토리지도 가지고 있으며 공유 볼륨을 통행 컨테이너끼리 스토리지를 통해 데이터를 주고받을 수 있다.

kube2

생명주기는 아래와 같다.

  1. Pending - 파드 생성중(이미지 다운, 컨테이너 생성중)
  2. Running - 파드안 모든 컨테이너가 실행중, 시자, 재시작 중
  3. Succeeded - 파드안 모든 컨테이너가 정상 종료 완료
  4. Failed - 파드안 컨테이너중 비정상 종료
  5. Unknown - 파드의 상태 확인 불가, 노드 통신 불가시 발생

생명주기는 kubelet 컴포넌트가 주기적으로 진단한다.

매니페스트

아래 명령으로 파드 매니페스트 속성 종류 및 설명 검생 가능

kubectl explain pods
kubectl explain pods.metadata
kubectl explain pods --recursive

pods.spec

필드 타입 설명
pods.spec.containers Container[] 파드에 속하는 컨테이너 목록
pods.spec.imagePullSecrets LocalObjectReference[] 컨테이너 이미지 취득을 위한 인증정보
pods.spec.initContainers Container[] 초기화 처리를 하는 컨테이너
pods.spec.nodeName String 해당 라벨의 노드에 파드를 배치(스케줄링)
pods.spec.nodeSelector Object 해당 라벨의 노드에 파드를 배치(스케줄링)
pods.spec.priority Integer 파드의 우선순위 지정, 클수록 높음
pods.spec.restartPolicy String 재시작 정책(Always, OnFailure, Never), 기본값은 Always
pods.spec.volumes Volume[] 파드의 마운트할 볼륨 지정

pods.spec.containers

파드 매니페스트 속성의 containers 에 들어가는 객체 배열 Container 에 어떤 속성이 있는지 알아보자.

필드 타입 설명
pods.spec.containers.args String[] 컨테이너에 송신할 인수
pods.spec.containers.env EnvVar[] 컨테이너에 설정한 환경변수
pods.spec.containers.image String 컨테이너 이미지와 해당 경로
pods.spec.containers.imagePullPolicy String 컨테이너 이미지 취득시 규칙(Always, ifNotPresent, Never). 기본값은 pods.spec.containers.ifNotPresent 기존 이미지가 있으면 새로 취득하지 않는다. Always 설정시 항상 이미지 갱신
pods.spec.containers.name String 컨테이너 이름, 컨테이너 내부간에 통신할때 사용(DNS_LABEL)
pods.spec.containers.ports ContainerPort 배열 컨테이너 공개파드
pods.spec.containers.resources ResourceRequirements 컨테이너에 CPU, Memory 같은 리소스 할당
pods.spec.containers.volumeMounts VolumeMount 배열 컨테이너 마운트 볼륨 지정
pods.spec.containers.workingDir String 작업 디렉토리
pods.spec.containers.livenessProbe Probe 컨테이너 감시
pods.spec.containers.readlinessProbe Probe 컨테이너 감시

pods.spec.initContainers

초기화 컨테이너

앱 컨테이너가 실행되기 전 파드를 초기화,

apiVersion: v1
kind: Pod
metadata:
  name: kubernetes-simple-pod
  labels:
    app: kubernetes-simple-pod
spec:
  initContainers:
  - name: init-myservice
    image: arisu1000/simple-container-app:latest
    command: ['sh', '-c', 'sleep 2; echo helloworld01;']
  - name: init-mydb
    image: arisu1000/simple-container-app:latest
    command: ['sh', '-c', 'sleep 2; echo helloworld02;']
  containers:
  - name: kubernetes-simple-pod
    image: arisu1000/simple-container-app:latest
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']

pods.spec.containers.livenessProbe

파드가 제대로 동작하는지, 파드 내부의 서비스가 제대로 동작하는지 감시 하기 위해
메니페스트에서 livenessProbe 속성을 추가한다.

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness-test-pod
  name: liveness-http

spec:
  containers:
  - name: liveness-test-pod
    image: k8s.gcr.io/liveness
    args:
    - /server
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
        httpHeaders:
        - name: X-Custom-Header
          value: Awesome
      initialDelaySeconds: 10
      periodSeconds: 5

livenessProbe 를 통해 컨테이너에 /healthz URI 에 5초주기(periodSeconds)로 요청을 날리고 200 ~ 400 사이의 값이 반환될 경우 정상으로 간주한다.
그 이외의 값이 반환될 경우 kublet 에 의해 컨테이너가 재시작 된다.

서비스가 실행될 때 까지의 텀(initialDelaySeconds)을 10초로 설정한다.

k8s.gcr.io/liveness 이미지에는 10초동안만 status code 200 을 반환하고 그 이후로는 status code 500을 반환하도록 설정되어있다.

10초 후 아래 명령어를 실행하면

kubectl get pods --output wide
kubectl describe pod liveness-http

CrashLoopBackOff 상태값과 로그에 Liveness probe failed: HTTP probe failed with statuscode: 500 가 찍혀있는걸 확인 가능하다.

http 를 통한 파드 상태확인 외에도 tcp소켓, 명령 실행 등을 통해서도 상태확인이 가능하다.
https://kubernetes.io/ko/docs/concepts/workloads/pods/pod-lifecycle/#컨테이너-프로브-probe

pods.spec.containers.readinessProbe

컨테이너가 실행된 후 실제 서비스 요청에 응답할 수 있을지 설정.

자바 어플리케이션 처럼 실행하는데 시간이 걸릴 경우 유용함.

파드 CRUD

먼저 간단한 이미지를 빌드하고 private registry 에 등록

docker build -t photo-view:v2.0 .
docker image tag photo-view:v2.0 mydomain:5000/photo-view:v2.0

docker images
REPOSITORY                        TAG                 IMAGE ID            CREATED              SIZE
mydomain:5000/photo-view   v2.0                05e6c8ef4559        About a minute ago   924MB
photo-view                        v2.0                05e6c8ef4559        About a minute ago   924MB

docker image push mydomain:5000/photo-view:v2.0

https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/

해당 private registrykubectl 로 사용할 수 있도록 secret 쿠버네티스 리소스 생성

docker login 을 통해 $HOME/.docker/config.json 파일에 인증데이터를 업데이트 후 해당 파일로 secret 리소스를 생성하자.

kubectl create secret generic regcred \
--from-file=.dockerconfigjson=$HOME/.docker/config.json \
--type=kubernetes.io/dockerconfigjson

맥의 경우 key 정보가 config.json 에 저장되는 것이 아닌 별도의 키체인에 저장되어 있어 위의 명령을 사용해봤자 auth faild 오류가 발생할것이다.
맥의 경우 바로 kubectlsecret 생성하는 아래의 명령 사용

kubectl create secret docker-registry regcred \
--docker-server=mydomain:5000 \
--docker-username=admin \
--docker-password=admin

--namespace='' 옵션을 생략했기에 기본적으로 default 에 적용된다.

해당 이미지로 파드 create

# pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: photoview-pod
  labels:
    app: photo-view
    env: stage
spec:
  containers:
  - image: mydomain:5000/photo-view:v2.0
    name: photoview-container
    ports:
    - containerPort: 80
  imagePullSecrets:
    - name: regcred # 생성한 secret name 설정 
kubectl apply -f Pod/pod.yaml
pod/photoview-pod created

kubectl get pods --show-labels
NAME            READY   STATUS    RESTARTS   AGE     LABELS
photoview-pod   1/1     Running   0          2m13s   app=photo-view,env=stage

kubectl describe pods photoview-pod
// 상세정보 확인 가능

항상 imagePullSecrets를 매니페스트 파일에 적용해야만 다운이 가능한데 이를 service account 에 포함하여 생략할 수 있다.

kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "regcred"}]}'

새로운 이미지 photo-view:v1.0 을 빌드, 태그, private-registrypush

docker build -t photo-view:v1.0 .
docker image tag photo-view:v1.0 mydomain:5000/photo-view:v1.0
docker image push mydomain:5000/photo-view:v1.0

위에 생성한 photoview-pod의 이미지를 photo-view:v1.0 로 변경해보자.

매니페스트 파일의 image 속성을 변경

# pod.yaml
apiVersion: v1
kind: Pod
...
spec:
  containers:
  - image: mydomain:5000/photo-view:v1.0
  ...
...
kubectl apply -f Pod/pod.yaml
pod/photoview-pod configured

apply 명령으로 생성/수정이 가능하다.

파드 삭제

kubectl delete -f Pod/pod.yaml

파드 스케줄링 구조

스케줄링은 쿠버네티스 마스터 서버 API Server 에서 관리한다.
파드가 마스터 서버에 의해 어떤 노드에 전개(스케줄링)될지 알아보자.

API Server는 클러스터 안의 쿠버네티스 리소스를 관리(CRUD), etcd 에 접근지원 하기 위해 Restfule 인터페이스를 지원한다.

파드가 생성되는 루틴은 대략적으로 아래와 같다.

  1. kubectl 명령 실행 - API ServerRestAPI 요청.
  2. 클러스터 구성 정보 갱신 - kubectl 로 인해 변경된 매니페스트 내용을 etcd 에 저장.
  3. 클러스터 구성 변경 - 젼달받은 매니페스트와 etcd의 데이터간 변화가 있다면 API Server에게 통지.
  4. 파드의 작성 - API Server가 통지받은 내용이 있다면 워커노드에 파드 업데이트 하도록 명령 송신, 노드내의 kubelet 은 전달받은 명령을 수행한다(새로운 파드 생성).

3번과 4번 과정 사이에서 파드를 어떤 노드에 스케줄링할지 결정한다.

스케줄링은 아래 2가지 규칙에 의해 결정된다.

  1. 노드의 필터링
    • 파드에 NodeSelector 를 설정하고 있는지 검사
    • 파드에 설정된 리소스 요구에 매칭되는 노드 필터링
  2. 노드의 우선순위
    • CPU, Memory 사용량에 따라 노드의 우선순위 결정
    • 우선순위별로 파드를 배치

파드 스케줄링 제어

위의 nodeSelector 속성을 정의해 명시적으로 노드를 정해주지 않고도 스케줄링할 수있는 방법이 여럿 있다.

Affinity

https://kubernetes.io/ko/docs/concepts/configuration/assign-pod-node/#어피니티-affinity-와-안티-어피니티-anti-affinity

Affinity 는 친밀감이란 뜻으로 서로다른 2개의 파드를 왠만하면 같은노드에 배치시키고 싶을때(podAffinity)
혹은 다른노드에 배치시키고 싶을때(podAntiAffinity) 사용한다.

또한 특정 조건을 갖춘 노드에서만 동작하도록 하는 nodeAffinity 도 있다.

Taints, Tolerations

https://kubernetes.io/ko/docs/concepts/configuration/taint-and-toleration/

Taints: 오염시키다 Tolerations: 용인,관용

서로 상반되는 역할을 하는 명령

Taints는 노드에 설정하는 것으로 파드를 스케줄링 하거나 조건에 맞는 파드만 스케줄링 하도록 할 수 있다.
Taints가 설정된 노드에 파드를 배치하고 싶다면 Tolerations 설정이 필요하다.

파드 리소스 설정

CPU, Memory 리소스는 매니페스트 파일에서 설정 가능하다.

apiVersion: v1
kind: Pod
metadata:
  name: requests-pod

spec:
  containers:
  - image: busybox
    command: ["dd", "if=/dev/zero", "of=/dev/null"]
    name: main
    resources:
      requests:
        cpu: 50m
        memory: 300Mi # (K M G T P), (Ki Mi Gi Ti Pi) 사용 가능

Minikube 에서 생성된 nodeCPU Limits100m, Memory Limits390Mi남아있다. 위의 매니페스트 설정대로 파드를 생성하고 줄어드는 Limits 를 확인

requests 속성을 파드의 최소 리소스 요청 단위를 뜻한다.

kubectl create -f Pod/pod-request.yaml
pod/requests-pod created 

kubectl get pods --output wide
NAME           READY   STATUS    RESTARTS   AGE   IP           NODE           NOMINATED NODE   READINESS GATES
requests-pod   1/1     Running   0          39s   172.18.0.2   minikube-m03   <none>           <none>

kubectl describe node minikube-m03 명령으로 남은 리소스를 확인해보면 정확인 CPU 50m, Memory 300Mi 만큼 Limits 가 줄어있다.

쿠버네티스에서 파드를 스케줄링할때 실제 노드의 리소스사용량이 아닌 메니페스트에 설정된 리소스 설정으로 스케줄링 됨을 알 수 있다.
파드에 많은 리소스를 할당하게 되면 그만큼 다른 파드를 노드에 설정할 수 없다.

만약 파드에 설정한 resources 사용량을 넘게되면 쿠버네티스에서 어떻게 처리하는지 알아보자.

apiVersion: v1
kind: Pod
metadata:
  name: limits-pod
spec:
  containers:
  - name: main
    image: polinux/stress
    resources:
      limits:
        cpu: 90m
        memory: 300Mi
    command: ["stress"]
    args: ["--vm", "1", "--vm-bytes", "500M", "--vm-hang", "1"]

stress 프로그램으로 Memory300M를 넘는 500M 를 설정하여 실행

limits 속성은 파드 요청 제한 단위를 뜻한다.

kubectl get pods --output wide
NAME         READY   STATUS              RESTARTS   AGE   IP       NODE           NOMINATED NODE   READINESS GATES
limits-pod   0/1     ContainerCreating   0          6s    <none>   minikube-m03   <none>           <none>

kubectl get pods --output wide
NAME         READY   STATUS    RESTARTS   AGE   IP           NODE           NOMINATED NODE   READINESS GATES
limits-pod   1/1     Running   0          9s    172.18.0.2   minikube-m03   <none>           <none>

kubectl get pods --output wide
NAME         READY   STATUS      RESTARTS   AGE   IP           NODE           NOMINATED NODE   READINESS GATES
limits-pod   0/1     OOMKilled   0          9s    172.18.0.2   minikube-m03   <none>           <none>

kubectl get pods --output wide
NAME         READY   STATUS             RESTARTS   AGE   IP           NODE           NOMINATED NODE   READINESS GATES
limits-pod   0/1     CrashLoopBackOff   2          43s   172.18.0.2   minikube-m03   <none>           <none>
kubectl describe pod limits-pod
# 상세 로그 확인.  

쿠버네티스에선 복구기능을 갖고 있기에 오류가 감지되면 기본적으로 재시작한다.
restartPolicy속성 에 따라 옵션이 다르며 기본값은 Always 이다.

kubectl get pods --output wide
NAME         READY   STATUS             RESTARTS   AGE     IP           NODE           NOMINATED NODE   READINESS GATES
limits-pod   0/1     CrashLoopBackOff   6          7m15s   172.18.0.2   minikube-m03   <none>           <none>

시간이 지남에 따라 RESTARTS 횟수가 계속 늘어나고 있다.

카테고리:

업데이트: