1. Resource Policies
2.1 Request / Limit (최소요구사항/최대 사용량)
쿠버네티스에서 파드를 어느 노드에 배포할지 스케쥴링 할 때, 스케쥴링이 될 노드에 해당 파드가 동작할 수 있는 충분한 자원이 확보가 되어야 합니다.
쿠버네티스에서 파드(컨테이너)에 필요한 리소스 양을 명시 할 수 있도록 설정을 지원합니다.
cpu/memory와 같은 컴퓨트 리소스 외에도 gpu/storage 리소스에 대한 쿼터도 지정 할 수 있습니다.
CPU는 m(밀리코어, 1코어=1000밀리코어) 단위로 지정하며, 해당 컨테이너에 어느정도의 CPU를 할당할 것인지를 지정합니다.
메모리는 Mi(Mib)를 사용합니다.
--- apiVersion: v1 kind: Pod metadata: name: frontend spec: containers: - name: app image: images.my-company.example/app:v4 resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m" - name: log-aggregator image: images.my-company.example/log-aggregator:v6 resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m"
metrics-server를 이용한 노드 별 리소스 모니터링
root@k8s-master01:~# kubectl top nodes | sort -n -k 2 NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% k8s-worker02 114m 1% 4030Mi 25% k8s-worker01 176m 2% 3196Mi 20% k8s-master03 279m 3% 4727Mi 29% k8s-master02 347m 4% 4144Mi 26% k8s-master01 414m 5% 4557Mi 28%
metrics-server를 이용한 파드 별 리소스 모니터링
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를 이용하여 네임스페이스별로 사용할 수 있는 리소스의 양을 정하고, 컨테이너 마다 사용 할 수 있는 양을 지정할 수 있습니다.
Resource Name | Description |
---|---|
| Across all pods in a non-terminal state, the sum of CPU limits cannot exceed this value. |
| Across all pods in a non-terminal state, the sum of memory limits cannot exceed this value. |
| Across all pods in a non-terminal state, the sum of CPU requests cannot exceed this value. |
| Across all pods in a non-terminal state, the sum of memory requests cannot exceed this value. |
| Across all pods in a non-terminal state, the number of huge page requests of the specified size cannot exceed this value. |
| Same as |
| Same as |
쿼터 오브젝트를 생성하여 특정 우선 순위의 파드와 일치 시키며, "low(낮음)", "medium(중간)", "high(높음)"의 세 가지 우선 순위 클래스 중 하나를 가질 수도 있습니다.
# quota-test.yaml --- apiVersion: v1 kind: ResourceQuota metadata: name: default spec: hard: cpu: "1000" memory: 200Gi pods: "10" # scopeSelector: # matchExpressions: # - operator : In # scopeName: PriorityClass # values: ["high"]
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.19 ports: - containerPort: 80 resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m"
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를 사용합니다.
root@k8s-master01:~# cat LimitRange.yaml apiVersion: v1 kind: LimitRange metadata: name: cpu-min-max-demo-lr namespace: default spec: limits: - max: cpu: "800m" min: cpu: "200m" type: Pod #Container
root@k8s-master01:~# cat LimitRange.yaml apiVersion: v1 kind: LimitRange metadata: name: cpu-min-max-demo-lr namespace: default spec: limits: - max: cpu: "800m" min: cpu: "200m" type: Pod #Container root@k8s-master01:~# more nginx-deploy.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.19 ports: - containerPort: 80 resources: requests: memory: "64Mi" cpu: "1000m" limits: memory: "128Mi" cpu: "1500m"
# kubectl get event --sort-by='lastTimestamp'
LAST SEEN TYPE REASON OBJECT MESSAGE
78s Warning FailedCreate replicaset/nginx-deployment-8579d7f98c Error creating: pods "nginx-deployment-8579d7f98c-mxw8q" is forbidden: maximum cpu usage per Pod is 800m, but limit is 1500m
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. 쿠버네티스 볼륨
PV(PersistentVolume): PV는 관리자가 프로비저닝했거나 스토리지 클래스를 사용해 동적으로 프로비저닝한 클러스터의 스토리지입니다. PV는 볼륨과 같은 볼륨 플러그인이지만 PV를 사용하는 개별 Pod와 독립적인 수명 주기를 가집니다.
PVC(PersistentVolumeClaim): PVC는 사용자가 볼륨을 사용하기 위해 PV에 하는 스토리지 요청입니다. Pod와 유사하게 Pod는 노드 리소스를 소비하고, PVC는 PV 리소스를 소비합니다.
3.1 PV의 Lifecycle
(1) Provisioning
PV를 생성하는 단계로 프로비저닝 방법에는 두 가지가 있습니다.
정적 프로비저닝
정적 프로비저닝은 클러스터 관리자가 미리 적정 용량의 PV를 만들어 두고 사용자의 요청이 있을 시 미리 만들어 둔 PV를 할당하는 방식입니다.
사용할 수 있는 스토리지 용량에 제한이 있을 때 유용합니다.
동적 프로비저닝
동적 프로비저닝은 사용자가 PVC를 거쳐서 PV를 요청했을 때 생성해 제공합니다.
클러스터에 사용자가 원하는 만큼의 스토리지 용량이 있다면, 원하는 용량만큼을 생성해서 사용할 수 있습니다.
(2) Binding
바인딩은 프로비저닝으로 생성된 PV를 PVC와 연결하는 단계입니다. PVC에서 원하는 스토리지 용량과 접근방법을 명시해서 용청하면 거기에 맞는 PV가 할당됩니다. PV와 PVC의 매핑은 1대1 관계입니다.
(3) Using
PVC는 Pod에 설정되고, Pod는 PVC를 볼륨으로 인식해서 사용합니다. 클러스터는 PVC를 확인하여 바인딩된 PV를 찾고 해당 볼륨을 Pod에서 사용할 수 있도록 해줍니다. 할당된 PVC는 파드를 유지하는 동안 계속 사용되며, 시스템에서 임의로 삭제할 수 없습니다.
(4) Reclaiming
사용이 끝난 PVC는 삭제되고, PV를 초기화(reclaim)하는 과정을 거칩니다. PV는 기존에 사용했던 PVC가 아니더라도 다른 PVC로 재활용이 가능합니다.
PV 초기화 정책
Retain: PV의 데이터를 그대로 보존합니다.
Recycle: 재사용하게 될 경우 기존의 PV 데이터들을 모두 삭제 후 재사용합니다.
Delete: 사용이 종료되면 해당 볼륨을 삭제합니다.
3.2 PV 생성
apiVersion: v1 kind: PersistentVolume metadata: name: test-pv labels: name: test-pv spec: capacity: storage: 1Gi accessModes: - ReadWriteMany hostPath: path: "/test/volume" # Value - capacity: 사용할 용량을 설정합니다. - accessModes:특정 접근 모드를 선택합니다. - hostPath: 노드에 저장되는 디렉토리를 설정합니다. # 적용하기 kubectl apply -f test-pv.yaml # PV 조회 kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE test-pv 1Gi RWX Retain Available 15s
3.3 PVC 생성
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: test-pvc spec: accessModes: - ReadWriteMany resources: requests: storage: 1Gi kubectl apply -f test-pvc.yaml # PV, PVC 조회 kubectl get pv,pvc NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE persistentvolume/test-pv 1Gi RWX Retain Bound default/test-pvc 2m22s NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE persistentvolumeclaim/test-pvc Bound test-pv 1Gi RWX 18s => PV와 PVC가 연결되어 PV가 Bound 상태로 변경된 것을 확인할 수 있습니다.
3.4 PVC를 사용할 Pod 생성
apiVersion: v1 kind: Pod metadata: name: test-nginx2 spec: containers: - name: test-nginx2 image: nginx:1.19 ports: - containerPort: 80 volumeMounts: - mountPath: "/test/volume" name: test-pv volumes: - name: test-pv persistentVolumeClaim: claimName: test-pvc # 옵션 - volumeMounts.mountPath: 볼륨 마운트할 컨테이너 안의 경로를 작성합니다. - volumes:.persistentVolumeClaim: 컨테이너에서 사용할 PV의 이름을 가져오고, PV와 연결되어 있으며 요청을 보낼 PVC를 지정합니다. # 적용하기 kubectl apply -f test-nginx2.yaml # 확인해보기 # 외부에서 확인 # kubectl describe pod test-nginx2 | grep -A1 Mounts Mounts: /test/volume from test-pv (rw) # 컨테이너 내부에서 확인 kubectl exec -it test-nginx2 -- bash root@test-nginx2:/# df -Th | grep volume /dev/vda1 xfs 50G 3.7G 47G 8% /test/volume => 지정한 경로에 볼륨이 마운트된 것을 확인할 수 있습니다. # 컨테이너 내부에서 test용 파일 생성 root@test-nginx2:/# touch /test/volume/test.txt # PV 생성 시 설정한 노드의 경로에서도 확인이 가능합니다. [root@worker-node ~]# ls -al /test/volume/ total 0 drwxr-xr-x 2 root root 22 Mar 10 06:22 . drwxr-xr-x 3 root root 20 Mar 10 06:18 .. -rw-r--r-- 1 root root 0 Mar 10 06:22 test.txt