수동 스케줄링 (Manual Scheduling)
쿠버네티스에서는 일반적으로는 스케줄러가 자동으로 Pod를 적절한 Node에 할당해준다
하지만 스케줄러가 없거나 비활성화 된경우는 수종으로 Pod를 특정 Node에 할당 할 수 도 있다.
pod의 객체를 보면 nodeName이라는 필드가 있는데 이거는 평소에 pod를 생성할때 직접 작성하지는 않는다
(작성하지 않아도 쿠버네티스가 추가해주는 항목이기 때문)
보통은 스케줄러가 Pending 상태의 pod를 모니터링하다가 적적한 Node를 찾아서 nodeName을 설정하거나, 내부적으로 Binding Api를 사용해서 Node에 pod를 할당한다
결과적으로는 저 항목을 pod 생성 yaml에서 직접 선언해주면 수동으로 노드에 할당할 수 있다
(다만 처음 생성시에만 가능, nodeName은 불변 속성)
apiVersion: v1
kind: Pod
metadata:
name: manual-pod
spec:
containers:
- name: nginx
image: nginx
nodeName: <노드 이름>
혹은 아래와 같이 바인딩 객체를 통해서도 가능하다 (바인딩도 pending 상태의 pod에만 사용 가능하다)
apiVersion: v1
kind: Binding
metadata:
name: manual-pod
target:
apiVersion: v1
kind: Node
name: <노드 이름>
어떤 노드 있는지 확인할때
kubectl get nodes
ps. kuebeclt get pods --watch (이러면 같은명령어 계속날릴 필요없이 상태 변하는거 바로 볼수 있음)
kubectl get pods -o wide (더 자세한 내용 볼 수 있음)
Labels and Selectors
쿠버네티스에서 사용하는 라벨이랑 셀렉터는 그룹으로 묶는 방법이다
간단하게 말하면 라벨은 객체에 붙어있는 속성이고 셀렉터는 그 라벨을 기준으로 필터링 할 수 있는 도구 이다.
라벨 (label)
Key/Value 형태의 메타데이터로, Kubernetes 객체에 사용해서 객체에 속성(tag) 을 부여 (그룹화를 가능하게 함)
라벨은 원하는 만큼 붙일 수 있고, 객체 생성 시 혹은 이후에도 추가 가능하다
metadata:
labels:
app: App1
tier: backend
셀렉터(Selector)
라벨을 이용해 특정 객체들을 선택(필터링) 하는 방법
kubectl get pods --selector app=App1
kubectl get pods --selector app=App1 | wc -l (숫자만 알려준다 해당하는 개수)
kubectl get all --selector env=prod (모든걸 찾아준다 해당 라벨의)
kubectl get all --selector env=prod,bu=finance,tier=frontend (여러개의 라벨 찾을때)
쿠버네티스에서 pod service deployment등
수많은 객체가 있고 모두가 다다르다 그래서 이것을 필터링해서 볼 수 있는 방법 필요하고
라벨과 셀렉터로 그런 그룹화와 선택이 가능하다
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: my-replicaset
labels: # ✅ ReplicaSet 자체의 라벨
app: App1
spec:
selector: # ✅ 이 조건과 일치하는 Pod들을 관리
matchLabels:
app: App1
template:
metadata:
labels: # ✅ 생성되는 Pod에 붙는 라벨
app: App1
selector.matchLabels는 Pod의 라벨과 일치해야 한다
즉, Pod Template의 라벨과 selector는 반드시 일치해야 ReplicaSet이 Pod를 제대로 생성하고 관리할 수 있다.
전체가 다 일치할 필요는 없고 selector가 요구하는 라벨의 key-value 값만 일치하면 된다.
메타데이터중 annotation은 라벨과는 비슷하지만 선택/필터링 등에서는 사용되지 않는다
주로 설명, 버전정보등 세부적인 정보를 지정하는데 사용된다
metadata:
annotations:
buildVersion: "1.34"
description: "Test build for staging"
Taints 와Tolerations
쿠버네티스에서 Taints (오염) 랑 Tolerations (내성)는 특정 파드가
특정 Node에 스케줄링되지 않도록 제한하거나 허용하는 것을 의미한다
Taints
노드에 설정하는것으로, 토드에 조건을 걸어서 특정 Pod만 허용 될 수 있도록 한다
즉 기본적으로 해당 Taint 가 설정된 노드에는 해당 조건을 견딜 수 있는 pod만 스케줄링 된다.
kubectl taint nodes <노드이름> <key>=<value>:<effect>
ex) kubectl taint nodes node1 color=blue:NoSchedule (이렇게 생성 명령어임)
# 명령어로 taint 확인후에 해당 taint - 로 삭제할 수 있다
kubectl describe node controlplane | grep Taints
kubectl taint nodes controlplane node-role.kubernetes.io/control-plane:NoSchedule-
Toleration
Pod 쪽에서 Taint 조건을 견딜 수 있다고 명시하는 설정
pod의 spec.tolerations 필드에 작성한다
spec:
tolerations:
- key: "color"
operator: "Equal"
value: "blue"
effect: "NoSchedule"
참고로 바로 명령어로 생성할 수가 없다
kubectl run bee --image=nginx --dry-run=client -o yaml > bee.yaml
이렇게 yaml파일을 실행없이 생성하고 위의 내용을 추가해줘야한다
위의 설정값은 해당 Pod가 color=blue:NoSchedule 이 설정된 노드에 배치될 수 있다는 뜻
toleration을 설정한다고 해당 노드에 배치되도록 강제하는게 아니다
단지 해당 노드에 들어갈 자격이 있다는 뜻이다
실제로 배치되는건 다른 조건들에도 영향을 받는다
| Effect | 의미 |
| NoSchedule | Toleration 없으면 절대 배치 불가 |
| PreferNoSchedule | Toleration 없으면 가급적 피함 (가능하면 안 보내지만, 절대 막지는 않음) |
| NoExcecutes | Toleration 없으면 기존에 있던 Pod도 제거됨 (eviction) + 새 Pod도 못 들어감 |
참고로 마스터 노드에 파드가 스케줄 되지 않는것도 쿠버네티스 설치시 기본적으로 마스터노드에 Taint가 설정되기 때문이다
# taint 설정 보는 명령어
kubectl describe node <노드이름> | grep Taint
# pod 설정 node까지 보는 명령어
kubectl get pod -o wide
Node Selectors & Node Affinity
쿠버네티스 클러스터에서 각 노드는 cpu, 메모리, 디스크등 각 스펙이 다를 수 있다.
파드가 어떤 노드에 배치될지는 기본적으로 스케줄러가 자동으로 결정하며, 특별한 설정이 없다면 균등하게 분산하려고 한다.
하지만 어떤 파드는 리소스가 높은 노드에 배치되어야할 수 도 있고
어떤 파드는 또 다른 특정 노드에만 배치되어야할 수 도 있다.
이러한 파드의 배치 조건을 결정 할 수 있도록 도와주는 방식으로
Node Selector 와 Node Affinity가 있다 (위의 taint toloration이랑은 또 다른 개념)
Taints/Tolerations 도 어떤 노드에 배치될지 제어 하는거지만 이 둘은 목적과 사용방식이 다르다
Taints/Tolerations는 특정 pod만 노드에 들어올 수 있게 제한할때 (누가 못들어 오게 막을 것인가)
selector/affinity는 특정 노드에 보내고 싶을때 (pod이 어디에 가야한다, pod가 자기가 원하는 노드를 선택)
selector/affinity는 요청 또는 선호의 느낌이면 Taints/Tolerations는 차단 강제의 느낌
그리고 보면 Taints/Tolerations는 특정 노드로 보내는게 아니다 (특정 노드에 못가게하는거)
selector/affinity는 특정 노드들로 보내는거고
(그래서 이 둘을 같이 활용하면 확실하게 분배도 가능하다)
NodeSelector
가장 간단한 방식으로 pod가 특정 라벨이 붙은 노드에만 스케줄 되도록 설정한다
노드에도 라벨을 설정해줘야하고 pod의 yaml에서도 해당 내용을 셋팅해줘야한다
가장 직관적이고 간단하지만 복잡한 조건(OR,NOT, 다중값 등) 은 처리할 수 없다는 한계가 있다
# 노드에 라벨 부여
kubectl label nodes <node-name> size=large
# 파드에서 명시할때 key/value로 특정 노드 명시가능
spec:
nodeSelector:
size: large
파드 실행 중 조건이 변화한다고 해도 변화는 무시한다
Node Affinity
NodeSelector보다 유연하고 강력한 조건 표현 가능하다
# 이거는 pod쪽에다가 설정한다 (그리고 그냥 복사 붙여넣기 하면된다 템플랫은 쿠버네티스 공식페이지 참고해서)
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: size
operator: In
values:
- large
operator에 In, NotIn, Exists, DoesNotExist 등 다양한 연산자를 사용할 수 있다
values 에 여러가지 값을 지정 할 수 도 있다.
| 타입 | 설명 |
| requiredDuringSchedulingIgnoredDuringExecution | 스케줄링 시 반드시 조건 만족해야 함실행 중 조건이 바뀌어도 무시 |
| preferredDuringSchedulingIgnoredDuringExecution | 조건을 만족하는 노드가 우선순위지만, 없어도 스케줄링 가능 |
| requiredDuringSchedulingRequiredDuringExecution | 이 옵션은 현재 Kubernetes에서 공식적으로 존재하지 않음“planned” 개념일 수 있지만, 구현되지 않음 |
타입은 스케줄링시에 어떻게 할건지 , 그리고 실행중일 어떻게 할건지 두가지 상황에서 어떻게 할건지를 정의 한다
Resource : Request & Limits
쿠버네티스에서 pod는 cpu와 메모리 같은 리소스를 소비한다.
각 노드들에는 제한되어있는 리소스가 존재하는데
파드를 배치할때 스케줄러는 pod의 요청량을 고려해서 충분한 리소르르 가진 노드에게 pod를 배치한다
(조건을 만족하는 노드가 없다면 pod는 pending 상태로 대기하게 된다)
리소스 설정 방법
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "1"
pod의 spec.containers.resource 필드에서 위와 같이 설정할 수 있다.
requests: 최소 보장 받을 리소스
limits : 최대 사용 가능 리소스
limits만 설정하는 경우 쿠버네티스는 request = limit 으로 자동 간주해서 적용한다 (cpu, memory둘다)
파드의 리소스는 실행중일때 변경은 못한다
별도의 파일을 강제로 업데이트 시켜주는 방법도 있다 (apply 말고)
kubectl replace --force -f filename.yaml (근데 apply가 좋을듯, 일반적으로 목적이 명활할때만 사용할것)
--> 기존 리소스를 삭제하고 새로 생성하는 방식으로 delete + create 강제로 실행하는거 (롤링도 안되고 , 웬만하면 운영에서는 사용하지 말것)
--> 참고로 지우는 대상은 저 yaml에 있는 리소스 kind + name + namespace에 조합에 해당하는 객체를 지우는것
리소스 단위
CPU
1은 1vCPU(core)와 동일하다 (aws기준, 실제 물리 cpu의 1코어에 해당하는 처리능력)
더 작은 단위는 m으로 표시한다 (milliCPU)
100m = 0.1cpu (최소 1m까지 설정가능)
Memory
단위: Mi (mebibyte), Gi (gibibyte) 권장
1Gi = 1,073,741,824 bytes (이진 단위)
1G = 1,000,000,000 bytes (SI 단위, 사용 가능하나 혼동 주의)
SI 단위는 10진수고 MIB GIB는 2진수이다
컴퓨터에서 메모리는 2진수 단위 기반으로 관리되기 떄문에 MI GI를 쓰는게
실제 시스템 자원 계산과 더 일치 한다 (공식문서에도 이걸 사용하는걸 권장함)
참고로 SI 단위 사용해도 문제가 없기는함
리소스 제한 초과 시 동작
CPU : 사용량이 limit 초과하면 제한이 된다 (강제 제어)
Memory : limit 초과하면 OOMKilled(Out of Memory) 로 pod가 종료된다
즉 CPU는 컨트롤 가능하지만, 메모리는 OS레벨에서 강제 종료된다
(컨트롤 가능하다해도 그냥 더 사용 못하게 제어하는것 뿐 , 애플리케이션 느려지거나 응답 지연될 수 있음)
기본값 설정
LimitRange 를 사용하면 특정 네임스페이스에 리소스 설정을 강제할 수 있다
기본 default 랑 min / mix등의 값을 설정할 수 있다
(참고로 ResourceQuota는 네임스페이스 전체 자원에 대해설정하는거 LimitRange는 개별 컨테이너 혹은 파드등 각 리소의 제한 및 기본값 을 설정해주는거다)
apiVersion: v1
kind: LimitRange
metadata:
name: mem-limit-range
namespace: dev-ns
spec:
limits:
- default:
memory: 512Mi
defaultRequest:
memory: 256Mi
type: Container
kubectl get limitrange -n dev-ns
참고로 이렇게 제한을 별도로 두지 않는다면 리소스 요청과 제한은 아무것도 적용이 되지 않는다
쿠버네티스는 cpu와 메모리를 모두 무제한으로 사용 가능하다고 간주한다 (OOMKilled, CPU starvation 같은 현상이 발생할 수 있음)
네임스페이스의 리소스 제한
네임스페이스 전체에서 사용할 수 있는 총 리소스를 제한할 수 있다.
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: dev-ns
spec:
hard:
requests.cpu: "4"
limits.memory: "8Gi"
kubectl get resourcequota -n dev-ns 를 통해서 확인 가능
DaemonSet
daemonset은 replicaset과 유사하게 여러개의 pod를 관리하는리소스 이다.
replicaset이 원하는 개수만큼 pod를 생성하는 반면 daemonset은 클러스터 내 모든 노드에
pod를 하나씩 자동으로 배포한다
새로운 노드가 추가되면 자동으로 pod를 추가하고 , 노드를 삭제하면 그 노드의 daemonset pod도
자동으로 제거가 된다.
사용 사례
- 모니터링 에이전트 (ex prometheus)
- 로그 수집기 (ex filebeat)
- kube-proxy 도 대표적인 daemonset 기반 구성 요소
생성 yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: example-daemon
spec:
selector:
matchLabels:
name: example-daemon
template:
metadata:
labels:
name: example-daemon
spec:
containers:
- name: myapp
image: myapp:latest
구조는 Replicaset이나 deployment와 거의 동일하며 차이점은 kind가 daemonset이라는 점
명령어
kubectl get daemonsets # DaemonSet 목록 확인
kubectl describe daemonset <name> # 상세 정보 확인
kubectl describe daemonset kube-flannel-ds --namespace=kube-flannel (ns로 하면아됨 namespace)
kubectl describe daemonset kube-flannel-ds -n kube-flannel (n 으로하면된다)
생성을 해야할떄는 deployment 로 yaml 만들어서 kind 변경
kubectl create deployment elasticsearch --image=registry.k8s.io/fluentd-elasticsearch:1.20 -n kube-system --dry-run=client -o yaml > fluentd.yaml
kind -> DaemonSet
(근데 이러면 replicas도 지우고 strategy, status 도 지워야한다
동작 방식
Kubernetes 1.1 이하
- DaemonSet이 직접 Pod을 생성하고, 각 Pod에 nodeName을 직접 지정해서 스케줄러를 우회
Kubernetes 1.2 이후
- DaemonSet Controller가 스케줄러를 사용하도록 변경
- 내부적으로 nodeAffinity, nodeSelector, taints/tolerations 등을 활용하여 각 노드에 Pod을 스케줄링함
- 더 표준적이고 확장성 있는 방식으로 개선됨
Static Pod
정적 파드는 kubelet이 독립적으로 생성하고 관리하는 pod다
API 서버나 스케줄러 없이도 실행 가능하며 클러스터와 무관하게 동작할 수 있다.
경로 및 동작 방식
#기본 경로 (별다른 설정 안한경우)
/etc/kubernetes/manifests
#기본 경로 찾는법 (kubelet의 설정파일 보기)
cat /var/lib/kubelet/config.yaml --> 요기서 staticPodPath 확인
# pod 생성 요청할때 --command도 추가해서 생성 가능 하다
kubectl run busybox --image=busybox --command --sleep 1000
# 노드 변경하는법
kubectl get nodes -o wide
-> internal-ip볼 수 있다 그걸로 ssh 명령어 써주면된다 (dns 설정이 되어있다면 이름만 써도 이동가능)
이 디렉토리에 pod의 yaml 파일을 넣으면 kubelet 이 직접 읽고 pod를 생성한다
해당 yaml 파일을 수정하면 pod가 재시작되고 , 삭제하면 pod도 자동으로 삭제된다.
이 pod들은 API 서버가 아니라 kubelet이 직접 실행하기 때문에 static pod 라고 부른다
(참고로 위의 경로는 변경도 가능하다, 초반에 기본 kubelet 옵션으로 --pod-manifest-path=/etc/kubernetes/manifests 가 들어가 있을 뿐)
정적파드는 파드 이름 뒤에 노드 이름이 붙는거로 구분할 수 있다
-> 아니면 yaml파일 정보를 통해서 ownerReferences를 확인하는 방법도 있다
클러스터 안/밖 동작
밖
노드가 클러스터에 등록되지 않고 독립적으로 있다면(api 서버 없음)
kubelet은 정적파드를 실행할 수 있지만 해당 컨테이너에서는 docker ps 나 containerd의 명령어로 확인이 가능하다
kubelet은 api 서버 처럼 동작하는건 아니고 단지 자기 혼자 pod를 생성하고 관리할 뿐이다
안
노드가 클러스터가 일부가 된 상태라면(api서버와 연결된)
kubelet이 정적파드를 만드는건 동일하지만
kubelet이 정적파드의 상태를 api 서버에 복제 형태로 등록을 하게된다
- 이 복제본은 읽기 전용으로 수정/삭제가 불가능하다
수정 /삭제를 위해서는 실제 /etc/kubernetes/manifests 디렉토리에서만 가능하다
왜 사용하는걸까 정적파드는?
클러스터가 완전히 작동하기 전에 필요한 핵심 구성요소들을 띄우기 위해서 사용된다
예를들어서 kube-apiserver, kube-scheduler, kube-controller-manager, etcd등
초기 마스터 노드를 구성할 떄 필수 적인 항목들 의 경우에서 주로 사용된다고 보면된다.
컨트롤 플레인 자체를 구성할 수 있는 매커니즘으로
별도의 배포도구나 외부 바이너리 없이 kubelet만 있어도 클러스터 핵심 구성 요소를 실행 할 수 있게 해준다
결론적으로 정적파드는 보통 마스터 노드에서 클러스터의 초기 부팅 및 마스터 구성요소 를 실행하기 위해서 사용된다고 이해하면된다
ps. commands를 containes 아래 붙이면 이미지도 그 command아래로 들어간다
Multiple Scheduler
kubernetes는 기본적으로 default-scheduler 라는 스케줄러를 제공한다.
하지만 내가 원하는 동작 방식화이 기본 스케줄러와 다른 경우 커스텀 스케줄러를 직접 만들어서 함께 실행할 수 있습니다
즉 쿠버네티스 클러스터에는 동시에 여러개의 스케줄러를 동작시킬 수 있다.
스케줄러를 생성하고 파드에서 spec.schedulerName 필드에 어떤 스케줄러를 사용할지 지정할 있다.
apiVersion: v1
kind: Pod
metadata:
name: example-pod
spec:
schedulerName: my-custom-scheduler # ❗ 여기에 스케줄러 이름 지정
containers:
- name: app
image: nginx
스케줄러의 이름은 중복되지 않도록 고유의 이름을 써야한다.
스케줄러 설정파일
스케줄러는 kind: KubeSchedulerConfiguration를 통해서 생성하며
스케줄러 이름, 정책, leaderElection 여부등을 포함 할 수 있다.
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: my-custom-scheduler
leaderElection:
leaderElect: true
resourceName: my-custom-scheduler
leaderElection은 마스터 노드가 여러개일때 어떤 스케줄러 인스턴스를 주 스케줄러로 활성화 할지를 결정한다
ture로 설정하면 여러 스케줄러중 하나만 활성 상태로 동작하고 나머지는 대기한다
배포 방식
Pod의 리소스로 커스텀 스케줄러를 실행
https://kubernetes.io/ko/docs/tasks/extend-kubernetes/configure-multiple-schedulers/ (공식문서 링크)
아래와 같이 service account와 clusterRoleBinding 으로 인증 관련 처리도 진행해 줘야한다
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-scheduler
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: my-scheduler-as-kube-scheduler
subjects:
- kind: ServiceAccount
name: my-scheduler
namespace: kube-system
roleRef:
kind: ClusterRole
name: system:kube-scheduler
apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: my-scheduler-as-volume-scheduler
subjects:
- kind: ServiceAccount
name: my-scheduler
namespace: kube-system
roleRef:
kind: ClusterRole
name: system:volume-scheduler
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: ConfigMap
metadata:
name: my-scheduler-config
namespace: kube-system
data:
my-scheduler-config.yaml: |
apiVersion: kubescheduler.config.k8s.io/v1beta2
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: my-scheduler
leaderElection:
leaderElect: false
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
component: scheduler
tier: control-plane
name: my-scheduler
namespace: kube-system
spec:
selector:
matchLabels:
component: scheduler
tier: control-plane
replicas: 1
template:
metadata:
labels:
component: scheduler
tier: control-plane
version: second
spec:
serviceAccountName: my-scheduler
containers:
- command:
- /usr/local/bin/kube-scheduler
- --config=/etc/kubernetes/my-scheduler/my-scheduler-config.yaml
image: gcr.io/my-gcp-project/my-kube-scheduler:1.0
livenessProbe:
httpGet:
path: /healthz
port: 10259
scheme: HTTPS
initialDelaySeconds: 15
name: kube-second-scheduler
readinessProbe:
httpGet:
path: /healthz
port: 10259
scheme: HTTPS
resources:
requests:
cpu: '0.1'
securityContext:
privileged: false
volumeMounts:
- name: config-volume
mountPath: /etc/kubernetes/my-scheduler
hostNetwork: false
hostPID: false
volumes:
- name: config-volume
configMap:
name: my-scheduler-config
관련 명령어
#스케줄러 동작 확인
kubectl get pods -n kube-system
# 특정 pod이 어떤 스케줄러에 처리된건지 확인
kubectl get events -o wide
#로그확인을 통해서도 볼 수있다 (어떤 스케줄러가 처리했는지)
kubectl logs my-custom-scheduler -n kube-system
Scheduler Profile (시험 중요)
파드가 처음에 만들어지면 스케줄링 큐에 들어가게된다
만들어진 순서대로 여기에서 pod의 일정이 잡혀있다
기본적으로 생성 순서대로 처리가 되지만 우선순위 설정을 통해서 기준을 변경할 수 있다
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000
globalDefault: false
description: "This priority class is for important workloads."
위와 같이 PriorityClass를 생성하고 pod에서 해당 우선순위를 동록해주면
우선순위가 높은 경우 먼저 처리가된다
#pod에서
spec:
priorityClassName: high-priority
스케줄링되어서 배치되는 단계
추가로 각 단계별로 플러그인 체계로 구성이 되어있다
단계별 플러그인들은 사용자의 정의로 켜거나 끌 수 있고 직접 만든 플러그인도 확장해서 사용이 가능하다
Scheduling Queue
plugin : prioritySort
Filterig
plugin : NodeResourcesFit , NodeName , NodeUnchedulable
실행불가능한 노드가 여기서 걸러진다 (cpu/ memory등 조건에 따라서 해당 파드가 배치 불가능한 케이스)
Scoring
plugin : NodeResourcesFit, ImageLocality
남은 노드들에 대한 스코어를 매긴다 파드가 배치되고 남는 리소스가 많은애가 더 높은 점수를 받는다
Binding
plugin : DefaultBinder
가장 점수가 높았던 노드에 배치되면서 바인딩 된다
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: my-scheduler
plugins:
score:
disabled:
- name: TaintToleration
enabled:
- name: MyCustomScorer
위와 같이 전에 만든 scheduler-config.yaml에서 플러그인 사용 여부를 활성화/비활성화 할 수 있다.
Admission Controllers
우리가 kubectl로 pod를 생성하는 명령을 날리면 요청은
kubectl → API Server → 인증(Authentication) → 인가(Authorization) → Admission Controller → etcd 저장
의 순서로 처리가 된다.
기본 설명
인증
사용자는 ~/.kube/config 파일에 등록된 인증서(cert) 를 통해 요청을 보내고
API 서버는 해당 인증서로 사용자를 신원 확인(인증) 한다.
인가
인증에 성공하면, Kubernetes는 RBAC 등을 통해 이 사용자가 해당 작업을 수행할 권한이 있는지 확인한다
Adminssion Controller
인증, 인가를 통과한 요청이어도
adminssion controller는 해당 요청을 최종적으로 검증하거나 수정, 거부할 수 있다
즉 해당 역할은 요청이 허용 가능한지 검토하고, 요청 내용을 수정하거나, 추가 리소스를 생성, 로깅 등의 작업 수행이 가능하다.
이러한 기능들은 기존 RBAC로는 구현할 수 없는 정책 제어이다
(ex, namespaceAutoProvision기능 존재하지 않는 네임스페이스가 요청되면 자동 생성)
#현재 활성화된 목록 확인
ps -ef | grep kube-apiserver | grep admission-plugins
(비활성화는 enable-admission-plugins)
#이렇게 할 수 도 있음
grep enable-admission-plugins /etc/kubernetes/manifests/kube-apiserver.yaml
#설정하려면 kube-apiserver command에 다음 플래그 사용
--enable-admission-plugins=NamespaceLifecycle,AlwaysPullImages,...
--disable-admission-plugins=...
(순서 중요, 플러그인 순서대로 실행된다)
Validating & Mutating
adminssion controller 는 크게 두가지의 유형이 있다
(동작 mutating 먼저하고 validating한다)
Validating adminssion controller
요청의 유효성을 검사한다
조건을 만족하지 않으면 요청을 거부한다
요청을 그대로 허용할지 거부할지만 판단한다
ex)
이미지가 latest인지 확인하고 거부, 특정 라벨 없으면 거부
Mutating adminssion controller
요청을 수정(변형)한다
요청을 거부하지 않고 자동으로 필드를 추가하거나 값을 변경한다
ex)
annotation 자동 추가
기본 storageClass 할당
WebHook 기반 Admission Controller
쿠버네티스는 위 두가지 기능을 webhook 서버로 확장 할 수 있도록 지원한다
쿠버네티스 클러스터 내부 혹은 외부에 있는 웹서버를 호출해서 http로 검증 /수정 요청을 보낼 수 있다
webHook서버 개발
go, python 등으로 작성하고
/mutate 또는 /validate등의 엔드포인트를 제공한다
로직안에 alloy/deny 또는 patch의 응답이 포함된다
서버 배포
보통은 클러스터 내부에 배포한다 (외부에도 배포는 가능)
webhook 리소스 생성
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: example-mutating-webhook
webhooks:
- name: mutator.example.com
clientConfig:
service: # 내부 클러스터에 배포한경우 이렇게 service로 지정한다
name: my-webhook-service
namespace: webhook-namespace
path: "/mutate"
caBundle: <BASE64-ENCODED-CA> # https로 통신하기 때문 ca 인증서 필요
rules: #언제 호출될지를 지정해주는것
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE"]
resources: ["pods"]
admissionReviewVersions: ["v1"]
sideEffects: None
ps
# 시크린 생성 관련 명령어
kubectl -n webhook-demo create secret tls webhook-server-tls \
--cert "/root/keys/webhook-server-tls.crt" \
--key "/root/keys/webhook-server-tls.key"
'자격증 > CKA' 카테고리의 다른 글
| cluster 관리 (0) | 2025.04.12 |
|---|---|
| Lifecycle Management (2) | 2025.04.06 |
| Logging & Monitoring (0) | 2025.04.06 |
| 구성 요소 설계 및 생성 (0) | 2025.03.08 |
| 기초 개념 정리 (0) | 2025.03.03 |