목차 |
---|
...
1. Resource Policies
2.1 Request / Limit (최소요구사항/최대 사용량)
쿠버네티스에서 파드를 어느 노드에 배포할지 스케쥴링 할 때, 스케쥴링이 될 노드에 해당 파드가 동작할 수 있는 충분한 자원이 확보가 되어야 합니다.
쿠버네티스에서 파드(컨테이너)에 필요한 리소스 양을 명시 할 수 있도록 설정을 지원합니다.
cpu/memory와 같은 컴퓨트 리소스 외에도 gpu/storage 리소스에 대한 쿼터도 지정 할 수 있습니다.
CPU는 m(밀리코어, 1코어=1000밀리코어) 단위로 지정하며, 해당 컨테이너에 어느정도의 CPU를 할당할 것인지를 지정합니다.
메모리는 Mi(Mib)를 사용합니다.
...
코드 블럭 |
---|
root@k8s-master01:~# kubectl -n kube-system top pod | sort -n -k 2 NAME CPU(cores) MEMORY(bytes) nginx-proxy-k8s-worker01 1m 16Mi nginx-proxy-k8s-worker02 1m 17Mi dns-autoscaler-59b8867c86-hjkvs 2m 7Mi kube-controller-manager-k8s-master02 4m 19Mi kube-controller-manager-k8s-master03 4m 19Mi nodelocaldns-rdkbl 4m 15Mi coredns-588bb58b94-9qcvw 5m 16Mi kube-scheduler-k8s-master02 5m 20Mi nodelocaldns-sd99v 5m 10Mi coredns-588bb58b94-zcnvc 6m 14Mi kube-proxy-h584h 7m 22Mi kube-scheduler-k8s-master03 7m 19Mi nodelocaldns-9vlvr 7m 9Mi nodelocaldns-b8gpm 7m 9Mi metrics-server-6f77f96b88-v5jjs 8m 17Mi nodelocaldns-r4sjf 8m 16Mi kube-scheduler-k8s-master01 9m 21Mi kube-proxy-x8gcq 12m 22Mi calico-kube-controllers-75748cc9fd-gqdzw 13m 21Mi kube-proxy-w87v4 13m 15Mi kube-proxy-96tsm 20m 15Mi kube-proxy-tj8pv 24m 14Mi kube-controller-manager-k8s-master01 36m 52Mi calico-node-87g22 42m 85Mi calico-node-kk5vn 51m 84Mi calico-node-wckv7 51m 85Mi calico-node-8278d 64m 91Mi etcd-k8s-master02 70m 89Mi calico-node-4hzx4 71m 109Mi kube-apiserver-k8s-master02 77m 303Mi etcd-k8s-master03 81m 84Mi kube-apiserver-k8s-master01 94m 349Mi etcd-k8s-master01 99m 95Mi kube-apiserver-k8s-master03 111m 310Mi |
2.2 ResourceQuota
쿠버네티스 운영 시 특정 팀에서 많은 리소스를 요구할 경우 ResourceQuota를 이용하여 네임스페이스별로 사용할 수 있는 리소스의 양을 정하고, 컨테이너 마다 사용 할 수 있는 양을 지정할 수 있습니다.
...
코드 블럭 |
---|
root@k8s-master01:~# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-deployment-5bccc488d-bqkvz 1/1 Running 0 18h nginx-deployment-5bccc488d-r4s5d 1/1 Running 0 18h nginx-deployment-5bccc488d-z29wp 1/1 Running 0 18h root@k8s-master01:~# kubectl get quota NAME AGE REQUEST LIMIT default 32s cpu: 750m/1k, memory: 192Mi/200Gi, pods: 3/10 |
2.3 LimitRange
ResourceQuota를 사용하면 네임스페이스의 리소스를 제한하고, LimitRange는 네임스페이스 내 파드(컨테이너)의 리소스를 제한합니다.
사용자가 컨테이너 리소스를 너무 크게 사용하면 특정 컨테이너가 많은 리소스를 점유하는 것을 방지할 수 있기 때문에 LimitRange를 사용합니다.
...
경고 |
---|
# kubectl get event --sort-by='lastTimestamp' |
...
2. Label & Selector
Label
Label은 Pod와 같은 객체에 연결된 키/값 쌍입니다.
리소스를 논리적인 그룹으로 나누거나, 식별의 편의를 위해 붙이는 이름표입니다.
Label은 생성 시 객체에 첨부할 수 있으며 나중에 언제든지 추가 및 수정할 수 있습니다.
Selector
특정 Label에 해당하는 객체를 식별하고 검색할 수 있습니다.
2.1 Node Label
...
코드 블럭 |
---|
# Node Label 확인 kubectl get nodes --show-labels # Node Label 추가 kubectl label nodes k8s-worker01 svc=web |
2.2 Pod Selector
pod-label.yml
코드 블럭 |
---|
apiVersion: v1 kind: Pod metadata: name: nginx labels: env: test spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent nodeSelector: svc: web |
...
3. 쿠버네티스 볼륨
지금까지 우리는 많은 실습을 통해 Pod를 배포하고 Service를 만들어 접속 할 수 있게 되었습니다.
...
이러한 데이터의 유지를 위하여 volume을 사용 합니다.
3.1 emptyDir
emptyDir 볼륨은 파드가 노드에 할당될 때 처음 생성되며, 해당 노드에서 파드가 실행되는 동안에만 존재합니다.
이름에서 알 수 있듯이 emptyDir 볼륨은 처음에는 비어있습니다.
파드 내 모든 컨테이너는 emptyDir 볼륨에서 동일한 파일을 읽고 쓸 수 있지만, 해당 볼륨은 각각의 컨테이너에서 동일하거나 다른 경로에 마운트 될 수 있습니다.
노드에서 파드가 제거되면 emptyDir 의 데이터가 영구적으로 삭제됩니다.
emptyDir은 주로 Pod내부에서 실행 중인 애플리케이션 간의 휘발성 파일을 공유할 때 유용하게 사용 됩니다.
공유가 필요 없는 볼륨이라면 굳이 emptyDir를 사용 할 필요는 없습니다 명시하지 않은 모든 볼륨의 데이터는 휘발성입니다 (이미지에 존재하지 않는 mountpath생성을 위한 용도로는 사용할 될 수 있습니다)
...
코드 블럭 | ||
---|---|---|
| ||
kubectl apply -f 012.nginx-vol-2.yml pod/nginx-vol-2 created kubectl get pod NAME READY STATUS RESTARTS AGE nginx-vol-2 2/2 Running 0 8s # 확인하면 포드내 컨테이너가 2개로 보입니다 # 생성된 컨테이너를 확인합니다 # 컨테이너가 2개 이상인경우 get pod 명령어를 활용해서 컨테이너를 식별하고 제어하지 못합니다. $ kubectl describe pod/nginx-vol-2 ...... Containers: nginx: Container ID: containerd://a9eac4ae13b2a8f052fe9bf6eca53c93e95c0de7ce4352cf1e77a0c4d2e1c5bb Image: nginx Image ID: docker.io/library/nginx@sha256:6926dd802f40e5e7257fded83e0d8030039642e4e10c4a98a6478e9c6fe06153 Port: <none> Host Port: <none> State: Running Started: Wed, 13 Sep 2023 11:05:21 +0900 Ready: True Restart Count: 0 Environment: <none> Mounts: /cache from cache-volume (ro) /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-pjccg (ro) fortune: Container ID: containerd://6e343b738170e0b1d0b0fa18fe641c0cd0b1257ae3cab9d7fc75fff041f09084 Image: luksa/fortune Image ID: docker.io/luksa/fortune@sha256:814dd72ecc4b431560ca6ede8649fc4862c401ba5b6d37520e6672e0657deea9 Port: <none> Host Port: <none> State: Running Started: Wed, 13 Sep 2023 11:05:33 +0900 Ready: True Restart Count: 0 Environment: <none> Mounts: /cache from cache-volume (rw) /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-pjccg (ro) Volumes: cache-volume: Type: EmptyDir (a temporary directory that shares a pod's lifetime) Medium: SizeLimit: <unset> # 두번째 yml을 보면 volume type을 EmptyDir로 선언하는것을 생략하였습니다 아무런 type이 없으면 기본값으로 EmptyDir를 사용 하게 됩니다 ..... # nginx와 fortune 2개의 컨테이너가 생성된것을 확인 할수 있습니다 # rw로 마운트된 fortune에서 파일을 생성하고 nginx컨테이너에서 파일을 볼수 있는지 실습 해봅시다 # pod내 컨테이너 선택은 -c옵션을 이용합니다 # fortune 컨테이너에서 만든 파일을 같은 pod내에 있는 nginx컨테이너테서 확인 할 수 있습니다. [root@m-k8s vagrant]# kubectl exec nginx-vol-2 -c fortune -- bash -c ' echo "test" > /cache/test.txt ' [root@m-k8s vagrant]# kubectl exec nginx-vol-2 -c fortune -- ls -l /cache total 4 -rw-r--r--. 1 root root 5 Sep 13 02:19 test.txt [root@m-k8s vagrant]# kubectl exec nginx-vol-2 -c nginx -- ls -l /cache total 4 -rw-r--r--. 1 root root 5 Sep 13 02:19 test.txt # 아래와 같이 nginx는 ro권한밖에 없으므로, 실제 write는 불가능합니다. [root@m-k8s vagrant]# kubectl exec nginx-vol-2 -c nginx -- bash -c 'echo "test" > /cache/test2.txt' bash: line 1: /cache/test2.txt: Read-only file system command terminated with exit code 1 # 실습환경을 정리합니다. kubectl delete -f 012.nginx-vol-2.yml pod "nginx-vol-2" deleted *기본적으로 emptydir은 worker노드에 디스크(파일시스템)에 생성되지만 상황에따라 memory나 fc disk등에 생성 할 수도 있습니다. |
3.2 hostpath
hostPath 볼륨은 호스트 노드의 파일시스템에 있는 파일이나 디렉터리를 파드에 마운트 합니다.
emptydir과 달리 pod를 삭제하여도 워커노드의 파일은 삭제되지 않습니다.
각 워커노드의 파일이 다를 수 있으므로 사용에 주의하도록 합니다.
node seletor를 이용하여 필요한 볼륨이 있는 node만 스케줄되게 하거나 모든 node가 동일한 파일을 가지거나 등의 조치를 하지 않고 배포 시 문제가 발생 할 수 있습니다.
...
코드 블럭 | ||
---|---|---|
| ||
# yaml 파일을 적용합니다. kubectl apply -f 012.nginx-vol-3.yml # 생성된 파드에서 마운트 된 경로의 파일을 확인합니다. kubectl exec -it nginx-vol-3 -- ls -l /usr/share/nginx/html total 4 -rw-r--r-- 1 root root 9 Apr 28 01:17 index.html # 파일 내용을 확인합니다. kubectl exec -it nginx-vol-3 -- cat /usr/share/nginx/html/index.html hihihihi [root@m-k8s vagrant]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-vol-3 1/1 Running 0 107s 172.16.221.185 w1-k8s <none> <none> [root@m-k8s vagrant]# [root@m-k8s vagrant]# curl 172.16.221.185 hihihihi # node에서 생성한 파일이 pod에 hostpath를 이용해 마운트 된것을 확인 할 수 있습니다. # hostpath의 경우 권한이 다르면 사용할수 없으므로 컨테이너 내 사용자로 권한을 바꾸거나 root사용자로 구동되도록 하여야 합니다. # 실습을 위해 실습환경을 정리합니다. [root@m-k8s vagrant]# kubectl delete -f 012.nginx-vol-3.yml pod "nginx-vol-3" deleted |
3.3 NFS
NFS를 volume으로 사용할 수 있습니다.
NFS를 이용하면 여러 pod에 동일한 volume을 마운트 할 수 있고, 여러 노드가 읽고 쓸 수 있으므로 파일 공유에 많은 이점이 있습니다.
...
코드 블럭 |
---|
kubectl apply -f 012.nginx-vol-4.yaml pod/nginx-vol-4 created [root@m-k8s vagrant]# k get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-vol-4 1/1 Running 0 53s 172.16.221.186 w1-k8s <none> <none> [root@m-k8s vagrant]# curl 172.16.221.186 hiihi kubectl exec -it nginx-vol-4 -- df -h Filesystem Size Used Avail Use% Mounted on ... w2-k8s:/nfs 37G 4.4G 33G 12% /usr/share/nginx/html ... # pod가 구동중인 worker1의 마운트 상태 확인 [root@w1-k8s /]# df -h Filesystem Size Used Avail Use% Mounted on w2-k8s:/nfs 37G 4.4G 33G 12% /var/lib/kubelet/pods/23229ac8-acb5-4aa0-b 0f1-6d8f36236366/volumes/kubernetes.io~nfs/nfs-volume #hostpath의 경우 해당파일이 존재하는 워커노드에서만 수행되도록 설정하였으나 nfs사용시에는 어느 노드에서 구동되어도 상관이 없습니다 # 다음 실습을 위해 실습환경을 정리 합니다. kubectl delete -f 012.nginx-vol-4.yml pod "nginx-vol-4" deleted |
3.4 Persistent Volume(PV)
PV(PersistentVolume): PV는 관리자가 프로비저닝했거나 스토리지 클래스를 사용해 동적으로 프로비저닝한 클러스터의 스토리지입니다. PV는 볼륨과 같은 볼륨 플러그인이지만 PV를 사용하는 개별 Pod와 독립적인 수명 주기를 가집니다.
PVC(PersistentVolumeClaim): PVC는 사용자가 볼륨을 사용하기 위해 PV에 하는 스토리지 요청입니다. Pod와 유사하게 Pod는 노드 리소스를 소비하고, PVC는 PV 리소스를 소비합니다.
...
코드 블럭 |
---|
# 파드를 생성합니다. kubectl apply -f 012.nginx-vol-6.yml pod/nginx-vol-6 created # 컨테이너 안에서 마운트 상태를 확인합니다. kubectl exec -it nginx-vol-6 -- df -h Filesystem Size Used Avail Use% Mounted on w2-k8s:/nfs 37G 4.4G 33G 12% /vol # 정상적으로 마운트 된것을 확인 할수 있습니다 ## 실습 환경을 정리 합니다 # 파드 삭제 kubectl delete pod nginx-vol-6 pod "nginx-vol-6" deleted # PVC 삭제 kubectl delete pvc/nginx-pvc-1 persistentvolumeclaim "nginx-pvc-1" deleted # PV 삭제 kubectl delete pv/nginx-vol-pv-5 persistentvolume "nginx-vol-pv-5" deleted |
3.5 동적 프로비저닝 + 프로덕션 환경 테스트
정보 |
---|
Dynamic 프로비저닝을 하려면 CSI를 제공하는 스토리지가 필요합니다. 보통 운영환경에서는 모두 이 방식을 사용합니다. 동적 프로비저닝의 의미는 PV를 PVC요청에 따라 동적으로 할당 한다는 것을 의미 합니다. |
...