포스트

[CKA] 쿠버네티스 Pod 설정

[CKA] 쿠버네티스 Pod 설정

본 글은 Udemy Certified Kubernetes Administrator (CKA) 강의를 참조해 정리한 내용을 기록했습니다.

Label & Selector

Kubernetes에는 다양한 리소스가 존재하고 이를 구별하기 위해 그룹화를 하는데 이런 그룹화를 위한 개념

Label은 특정 Pod, Node, Service를 구분하고, Selector를 통해 특정 Label을 가진 리소스를 선택한다.

Label

리소스에 Key-Value 형태로 추가 가능한 메타데이터로 그룹화를 사용하는데 있어 기본적으로 사용된다.

1
2
3
4
5
6
7
8
9
10
11
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  labels:
    app: my-app
    env: production
spec:
  containers:
  - name: nginx
    image: nginx

이 Pod는 my-app 이라는 앱에 속해 있으며, 운영 환경은 production 영역에서 작동한다.

이러한 정보 이외에도 key와 Value는 원하는대로 설정이 가능한데 tier=backend 등등… 이러한 Label의 변화는 리소스를 재시작 하지 않아도 영향에 끼친다.

Selector

Label을 통해 리소를 그룹화 했다면 Selector를 통해 리소스를 선택할 수 있다.

주로 Service, Deployment, ReplicaSet등이 Pod를 선택한다.

Service에서 pod를 연결하기

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: my-app  # app=my-app 라벨이 있는 파드와 연결됨
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

Deployment에서 Pod를 연결하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
  app: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app  # Selector와 일치해야 함
    spec:
      containers:
      - name: nginx
        image: nginx

해당 Deployment는 두 개의 metedata를 보유하고 있는데 template.metadata. 같은 경우 생성되는 Pod에 대한 metada로 관리 되며 my-app 으로 붙여진 pod만 selector 를 통해 관리한다

Resource Requirements and Limits

k8s에서는 pod의 CPU와 메모리를 설정하여 pod가 실제 사용할 수 있는 리소스를 제어할 수 있다.

이는 RequestLimit으로 설정되며 Request는 Pod가 구성되기 위한 최소한으로 보장받는 리소스를 뜻하며, Limit은 Pod가 사용할 수 있는 최대 리소스의 제한을 뜻한다. kube-scheuler는 이러한 정보를 기반으로 Request가 적절하게 요구되는 node로 Pod를 스케줄링한다.

CPU & Memory 단위

리소스단위예제
CPUm (milliCPU)500m = 0.5 vCPU (코어)
메모리Mi, Gi512Mi = 512MB, 1Gi = 1GB

그렇다면 Request와 Limit을 어떤식으로 설정을 해야할까?

Request만 보장

1
2
3
4
5
6
7
8
spec:
  containers:
  - name: my-app
    image: my-image
    resources:
      requests:
        memory: "256Mi"  # 최소 256Mi 메모리 보장
        cpu: "250m"      # 최소 0.25 vCPU 보장

kube-scheduler에게 request를 기준으로 적절한 Pod에 배치해달라고 공지한다.

Limit만 보장

1
2
3
4
5
6
7
8
9
10
11
spec:
  containers:
  - name: my-app
    image: my-image
    resources:
      requests:
        cpu: "250m"  # 최소 0.25 vCPU 보장
        memory: "256Mi"  # 최소 256Mi 보장
      limits:
        cpu: "500m"  # 최대 0.5 vCPU 사용 제한
        memory: "512Mi"  # 최대 512Mi 사용 제한

적절한 Pod에 배치하고 그곳에서 사용량을 제한한다.

이럴 경우 만약 limits를 초과하게 된다면 CPU의 경우 이 이상 자원을 할당받지 못하기에 시스템이 느려지는 등 영향을 끼친다. (Pod가 죽지는 않음)

하지만 Memory가 초과시 처음에는 지속적으로 할당이 되지만 일정량을 초과하면 OOM이 발생하며 pod가 죽는다!

즉.. 서비스 자원을 최적화하는 것도 중요하지만 Limit은 적절하게 설정하여 pod가 죽어 서비스가 다운되는 현상이 발생하지 않게 해야한다.

DaemonSet

모든 Node에 1개씩의 Pod의 실행을 보장하는 컨트롤러로 Node가 추가될 경우 해당 Node에 Pod를 자동으로 하나 배포 한다.

이는 주로 클러스터 전체에서 로그를 수집하거나 모니터링을 사용하는데 주로 사용된다.

image.png모니터링과 logger로 사용되는 daemonset

또한 kube-proxy 같은 자주 사용되는 pod 또한 daemonset 형식으로 관리되어진다.

image.pngkube-proxy는 실제로 특정 pod에서만 실행된다.

DeamonSet 만들어보기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: busybox-daemon
  labels:
    app: busybox
spec:
  selector:
    matchLabels:
      app: busybox
  template:
    metadata:
      labels:
        app: busybox
    spec:
      containers:
        - name: busybox-container
          image: busybox
          command: ["sleep", "10000"]

DaemonSet은 모든 node에서 실행된다.

이렇게 배포된 deamonSet을 확인하기 위해서는 get 명령어를 사용한다.

1
kubectl get daemonset -A

-A 옵션은 --all-namespaces와 같은 의미로 모든 namespaces의 pod를 가져오는데 사용된다.

DeamonSet이 특정 node에만 있으면 좋겠어요

모든 node에 pod의 실행을 보장하는건 강력하지만 때로는 자원의 낭비를 초래할 수 있다. 그렇기에 label을 이용해 특정 node에만 DaemonSet를 사용할 수 있다.

우선 Deamonset의 label에 value를 설정한다.

1
2
3
4
5
spec:
  template:
    spec:
      nodeSelector:
        dedicated: monitoring

그리고 node에 kubectl label nodes <노드이름> dedicated=monitoring 를 설정하면 해당 value를 설정한 Node에만 pod가 실행되는 것을 확인 할 수 있다.

Static Pods

static pod란 node의 kubelet에 직접 실행되는 pod로, kube-api 에 의해 관리되지 않는 Node에서 직접 실행되는 pod이다.

클러스터(kube-api)가 관리하지 않기에 kubectl delete pod 명령어로 삭제할 수 없다. 하지만 read 를 사용하는 kubectl get pods 에서는 관측된다.

image.png

어떻게 생성하지?

cd /etc/kubernetes/manifests 로 디렉터리를 이동한다. 그곳에는 이미 ETCD나 kube-api 같은 static podsyaml이 있으며 그곳에 직접 YAML을 생성하면 자동으로 배포가 된다.

만약 내가 만든 static pods이 정상적으로 배포가 된 것을 확인 할려면 모든 namespaces에 대해 get을 하면 된다.

1
kubectl get pods --all-namespaces

삭제 할경우 해당 YAML을 제거하면 된다.

왜 사용하지?

image.png

Master Node에는 지속적으로 있어야할 k8s 관리 pod들이 존재한다.

이러한 pod들을 static pods로 설정함으로써 별도의 배포 없이 관리 pod들이 기동되어진다.

DaemonSet vs Static Pod

kube-api가 관리하는 DaemonSet과 kubelet이 직접 관리하는 Static Pods의 경우는 비슷한 요구사항을 만족하는데 사용할 수 있지만 적절하게 사용하면 더 큰 효율을 볼 수 있다.

DaemonSet 같은 경우 kube-api가 관리해주기에 관리가 편하며 label을 통해 조건을 쉽게 조절할 수 있다. 그렇기에 로그 수집, 모니터링 같은 요구사항에 더 적합하다.

Static Pod의 같은 경우 Node에 직접 yaml을 통해 배포되기에 클러스터의 핵심 컴포넌트를 배포할 때 적절하게 사용되어진다. (클러스터가 초기화 되어도 자동으로 실행됨)

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.