[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가 실제 사용할 수 있는 리소스를 제어할 수 있다.
이는 Request와 Limit으로 설정되며 Request는 Pod가 구성되기 위한 최소한으로 보장받는 리소스를 뜻하며, Limit은 Pod가 사용할 수 있는 최대 리소스의 제한을 뜻한다. kube-scheuler
는 이러한 정보를 기반으로 Request가 적절하게 요구되는 node로 Pod를 스케줄링한다.
CPU & Memory 단위
리소스 | 단위 | 예제 |
---|---|---|
CPU | m (milliCPU) | 500m = 0.5 vCPU (코어) |
메모리 | Mi , Gi | 512Mi = 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를 자동으로 하나 배포 한다.
이는 주로 클러스터 전체에서 로그를 수집하거나 모니터링을 사용하는데 주로 사용된다.
또한 kube-proxy
같은 자주 사용되는 pod 또한 daemonset 형식으로 관리되어진다.
kube-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
에서는 관측된다.
어떻게 생성하지?
cd /etc/kubernetes/manifests
로 디렉터리를 이동한다. 그곳에는 이미 ETCD나 kube-api
같은 static pods의 yaml
이 있으며 그곳에 직접 YAML을 생성하면 자동으로 배포가 된다.
만약 내가 만든 static pods이 정상적으로 배포가 된 것을 확인 할려면 모든 namespaces에 대해 get을 하면 된다.
1
kubectl get pods --all-namespaces
삭제 할경우 해당 YAML을 제거하면 된다.
왜 사용하지?
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
을 통해 배포되기에 클러스터의 핵심 컴포넌트를 배포할 때 적절하게 사용되어진다. (클러스터가 초기화 되어도 자동으로 실행됨)