Resource Requirements and Limits
- pod는 cpu / mem / disk를 사용한다.
- pod definition file에서 specify한대로 node에 배정된다.
// pod.yaml
spec:
containers:
- name: testcont
image: testcont
ports:
- containerPort: 8080
resources:
requests:
memory: "1Gi"
cpu: 1
- 1cpu == 1 AWS vCPU == 1 GCP Core == 1 Azure Core == 1 Hyperthread
- 기존 도커는 default 설정에서는 리소스에 제한이 없다. 하나가 커지면 다른 컨테이너 자리 잡아먹어서 suffocate한다.
- 반면, k8s는 default로 "1 vcpu, 512 mb"의 리소스 제한이 있다.
- cpu는 기준치 넘어가면 바로 차단하지만, mry는 기준치 넘어가도 사용 가능하다. 한 pod의 mry 제한을 다 쓰면 그때 터진다.
- 주의! 이 limit은 전부 node 내 pod 내 컨테이너 각각에 적용되는 것이다!
https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/memory-default-namespace/
https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/cpu-default-namespace/
pod와 deployments의 수정 팁
- 다음 네 가지 외에 이미 돌아가는 pod의 내용을 바꿀 수 없다.
- spec.containers[*].image
- spec.initContainers[*].image
- spec.activeDeadlineSeconds
- spec.tolerations
- 가령, 환경 변수나 resource limit을 바꾸려면,
kubectl edit pod <pod name>
하고 내용을 수정한 뒤, deni됨을 확인하고, 기존 Pod를 삭제하고, 생성된 tmp 파일로 새로 create한다.
-kubectl get pod webapp -o yaml > my-new-pod.yaml
로 현재 pod definition을 뽑고, 얘를 수정한 뒤, 기존 pod를 삭제하고, 새로운 my-new-pod.yaml로 create한다.
- 반면 deployments는 자유로이 수정 가능하다.
Daemon Sets
- Daemon Sets은 rs와 비슷하다. 클러스터 내 모든 node 내에 pod이 무조건 하나는 떠 있게 해준다.
- 가령, 클러스터를 모니터링하는 pod가 무조건 떠 있어야 할 때 사용할 수 있다. / kube proxy / networking
- 생성 방법은 kind 제외하면 rs와 동일하다.
kubectl get daemonsets
kubectl describe daemonsets <ds name>
- v1.12까지는 내부적으로 nodeName을 creation time에 명시해서 곧바로 해당 노드에 꽂히게 한다.
- v1.12부터는 default scheduler와 node affinity를 사용해서 꽂는다.
Static Pods
- k8s cluster나 master node, api server,, 등 어떠한 오브젝트의 개입 없이, 노드 내에서 직접 kubelet에 의해 생성되는 pod를 static pods라 한다.
- 이건 pod만 된다. rs나 deployment는 불가. 애초에 kubelet은 pod 레벨이다.
/etc/kubernetes/manifests
에 yaml file을 올린다.
- 위 경로를 kubelet.service file에 cmdline option으로 직접 주거나, kubeconfig.yaml을 새로 만들어서 여기에 넣어줘도 된다.
- Q) 그럼 kube api server가 있고, 얘가 Pod 생성 요청하는데, 동시에 Static Pods 생성용 파일도 있으면?
- A) kubelet은 동시에 둘 다 만들 수 있다. kube api server도 static pod의 존재를 인지하긴 한다. (kube api server가 볼 수 있는 read-only mirror pod가 생성되기 때문이다.)
- 근데, 이걸 대체 왜 써? -> Master Node에서 중요한 pod (controller, etcd, apiserver 등)를 생성하고, 꺼지지 않게 유지하기 위해서 static pod로 둔다. 이게 k8s cluster를 처음 생성할 때 진행되는 것이다.
daemon sets vs static pods
- daemon sets는 모든 노드에 최소 하나의 인스턴스는 보장하기 위해 사용된다.
- ds는 kube api server (ds controller)에 의해 생성된다. 모니터링, 로깅 agent를 심는데 주로 사용된다.
- static pods는 kube api server 간섭 없이, kubelet이 직접 생성한다. control plane의 요소들을 생성하는 데 사용된다.
- kube scheduler는 둘 다 무시한다.
Multiple Schedulers
- k8s에서는 여러 scheduler를 사용할 수 있다. 나만의 커스텀 scheduler도.
- 각 sch는 이름이 달라야하고, 당연히 각각 다른 conf 파일로 생성해야 한다.
- 가장 간단한 방법은 scheduler를 하나의 pod로 생성하는 것이다.
// my-custom-scheduler.yaml
kind: Pod
metadata:
name: my-custom-scheduler
namespace: kube-system
spec:
containers:
- command:
- kube-scheduler
- --address=127.0.0.1
- --kubeconfig=/etc/kubernetes/scheduler.conf // auth to connect to kube api server
- --config=/etc/kubernetes/my-scheduler-config.yaml
image: k8s.gcr.io/kube-scheduler-amd64:v1.11.3
name: kube-scheduler
// my-scheduler-config.yaml
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: my-scheduler
leaderElection: // multiple이 떠있을 때, 누가 리딩할꺼냐. (하나만 active 할 수 있다. HA 섹션에서 다시 다룰 것)
leaderElect: true
resourceNamespace: kube-system
resourceName: lock-object-my-scheduler
// pod.yaml
...
spec:
schedulerName: my-custom-scheduler
Configuring Scheduler Profiles
- scheduler는 pod의 조건을 충족하는 node에 호스팅시켜주는 역할이었다.
- 과정 1) Scheduling Queue에 pod들이 담긴다. 이때 priority에 의해 queue에서 순서가 생성된다.
- 과정 2) highest priority pod에 대해, 호스팅 시킬 수 없는 node들을 filter out한다. (Filtering Phase)
- 과정 3) 2까지 통과한 노드들에 대해 점수를 매긴다. 더 높은 점수 == pod을 호스팅할 자격! (Scoring Phase)
- 과정 4) 가장 높은 노드에 pod이 binding 된다. (Binding Phase)
- 위 과정은 모두 plugin으로 진행된다. 가령, 1에는 PrioritySort, 2에는 NodeResourcesFit, NodeName, NodeUnschedulable, 3에는 NodeResoucesFit, ImageLocality, 4에는 DefaultBinder
- 위는 default일 뿐이고, 우리의 plugin은 'extension point'를 사용하여 꽂을 수 있다. queueSort plugin, preFilter, filter, postFilter, preScore, score ... 다양한 플러그인
- 위와 같은 scheduler 내부 내용을 정리, 명문화해놓은게 profile이다.
- Multiple Schedule을 사용하는 가장 기본적인 방법은 각자 다 yaml 파일 만들어서 create하는 것이다. 그러나 이 방법은 귀찮고, 불필요한 자원이 투입된다. 무엇보다, scheduler간 race condition 발생 가능성이 있다.
- 1.18부터는 한 scheduler 내에 여러 profile을 둘 수 있게 되었다.
my-scheduler.yaml
apiVersion: ~
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: sch1
plugins: // 이 아래가 extension point이다.
score:
disabled:
- name: ~
enabled:
- name: ~
- schedulerName: sch2
- schedulerName: sch3