티스토리 뷰
VPA(Vertical Pod Autoscaler)란
안정성과 비용효율성간의 관계로 인해 request 혹은 limits를 낮게 혹은 너무 높게 설정하게 될수 있다.
이러한 상황에서는 OOM(out of memory) 및 불필요한 자원 과소비가 이루어지게 된다.
Pod들의 up/down scale을 지원하는 VPA는 이런 이슈를 대응할 수 있는 방안이 된다.
pod내 container들에 대한 최신 resource limits 과 requests를 설정에서 자유롭게 해준다.
자동으로 requests를 사용량에 기반해 설정하고 이로인해 resource 양에 적절한 노드에 적절한 스케쥴링이 이루어지게 된다.
또한 limits과 requests에 사이에 비율도 관리한다.
현재(2023.03 기준) 다음 제약사항이 있다.
최소 2개이상의 pod가 동작되어야 한다. 1개일 경우 아래와 같은 로그를 vpa-updater가 남기면서 vpa가 동작되지 않는다.
pods_eviction_restriction.go:219] too few replicas for ReplicaSet default/cpustress-7db8998dd6. Found 1 live pods, needs 2 (glo bal 2)
HPA(Horizontal Pod Autoscaler 와 함께 사용될 수 없다.(다만, CPU/Memory가 아닌 다른 metric은 HPA와 함께 사용할 수 있다.)
출처 : https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler#known-limitations
How it works
Architecture
VPA를 설치하게 되면 3가지 pods가 동작되어진다.
jacob@laptop:~ $ k get po -n kube-system -l 'app in (vpa-recommender,vpa-admission-controller,vpa-updater)'
NAME READY STATUS RESTARTS AGE
vpa-admission-controller-5596f976dd-mw4xv 1/1 Running 0 128m
vpa-recommender-55f964bd8-42x79 1/1 Running 0 128m
vpa-updater-c4888ff85-tkt68 1/1 Running 0 128m
admission-controller : pod 생성 요청을 수정할 admission webhook을 등록한다. 해당 admission-webhook을 통해 기존 pod가 evicted 된후 새로운 pod가 생성될때 requests/limits가 recommender에 의해 측정된 value로 설정되어 생성된다.
recommender : pod에 대한 resource requests의 높고 낮은 limit을 정의한다.
updater : 현재 pod의 resource requests가 권장되어진 범위내에 있는지 확인한다. 만약 범위내 없는 경우 해당 pod를 kill 하고 controller에 의해 업데이트된 requests에 맞게 pod가 재생성되도록 한다.
출처 : https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler#components-of-vpa
다음 CRD(custom resource definition)를 기반으로 동작되어진다.
jacob@laptop:~ $ k get crds -l helm.toolkit.fluxcd.io/name=overlay-vpa-adapter-helmrelease
NAME CREATED AT
verticalpodautoscalercheckpoints.autoscaling.k8s.io 2023-03-20T02:05:23Z
verticalpodautoscalers.autoscaling.k8s.io 2023-03-20T02:05:23Z
Deep dive
work on real world
실제 동작을 확인해 보면 배포된 deployment의 requests는 다음과 같이 cpu 100m / memory 50Mi 이며
jacob@laptop:~ $ k get deploy/hamster -o jsonpath='{.spec.template.spec.containers[*].resources}' | jq
{
"requests": {
"cpu": "100m",
"memory": "50Mi"
}
}
설정된 vpa는 max cpu 가 1(1000m) 이며 min cpu는 100m로 설정된것이 확인되며
jacob@laptop:~ $ k get vpa hamster-vpa -o jsonpath='{.spec}' | jq
{
"resourcePolicy": {
"containerPolicies": [
{
"containerName": "*",
"controlledResources": [
"cpu",
"memory"
],
"maxAllowed": {
"cpu": 1,
"memory": "500Mi"
},
"minAllowed": {
"cpu": "100m",
"memory": "50Mi"
}
}
]
},
"targetRef": {
"apiVersion": "apps/v1",
"kind": "Deployment",
"name": "hamster"
},
"updatePolicy": {
"updateMode": "Auto"
}
}
vpa에 의해 계산된 결과인 recommendation이 587m임을 확인 할 수 있다.
jacob@laptop:~ $ k get vpa hamster-vpa -o jsonpath='{.status.recommendation}' | jq
{
"containerRecommendations": [
{
"containerName": "hamster",
"lowerBound": {
"cpu": "575m",
"memory": "262144k"
},
"target": {
"cpu": "587m",
"memory": "262144k"
},
"uncappedTarget": {
"cpu": "587m",
"memory": "262144k"
},
"upperBound": {
"cpu": "1",
"memory": "262144k"
}
}
]
}
실제 일정시간이 경과된후 아래와 같이 requests CPU가 587m인 pod가 새로 생성되어음을 확인할 수 있다.
(실제 replica count가 2임에도 3개가 확인되는것은 vpa에 의해 하나의 pod는 evicted 되고 새로운 pod가 requests value를 변경하여 생성되었기 때문이다.)
jacob@laptop:~ $ k get pod -l app=hamster -o jsonpath='{.items[*].spec.containers[*].resources}' | jq
{
"requests": {
"cpu": "100m",
"memory": "50Mi"
}
}
{
"requests": {
"cpu": "587m",
"memory": "262144k"
}
}
{
"requests": {
"cpu": "100m",
"memory": "50Mi"
}
}
이와 같은경우 vpa에 의해 evicted되었다는 event를 아래와 같이 확인할 수 있다.
jacob@laptop:~ $ k get events --sort-by="lastTimestamp"
LAST SEEN TYPE REASON OBJECT MESSAGE
...
3m20s Normal Pulled pod/hamster-65cd4dd797-tx49r Container image "registry.k8s.io/ubuntu-slim:0.1" already present on machine
3m20s Normal Started pod/hamster-65cd4dd797-8kpcg Started container hamster
3m20s Normal Created pod/hamster-65cd4dd797-8kpcg Created container hamster
3m20s Normal Pulled pod/hamster-65cd4dd797-8kpcg Container image "registry.k8s.io/ubuntu-slim:0.1" already present on machine
3m19s Normal Started pod/hamster-65cd4dd797-tx49r Started container hamster
3m19s Normal Created pod/hamster-65cd4dd797-tx49r Created container hamster
107s Normal Killing pod/hamster-65cd4dd797-tx49r Stopping container hamster
107s Normal EvictedByVPA pod/hamster-65cd4dd797-tx49r Pod was evicted by VPA Updater to apply resource recommendation.
107s Normal SuccessfulCreate replicaset/hamster-65cd4dd797 Created pod: hamster-65cd4dd797-9lrr7
106s Normal Created pod/hamster-65cd4dd797-9lrr7 Created container hamster
106s Normal Pulled pod/hamster-65cd4dd797-9lrr7 Container image "registry.k8s.io/ubuntu-slim:0.1" already present on machine
105s Normal Started pod/hamster-65cd4dd797-9lrr7 Started container hamster
47s Normal SuccessfulCreate replicaset/hamster-65cd4dd797 Created pod: hamster-65cd4dd797-nsb8c
47s Normal EvictedByVPA pod/hamster-65cd4dd797-8kpcg Pod was evicted by VPA Updater to apply resource recommendation.
46s Normal Started pod/hamster-65cd4dd797-nsb8c Started container hamster
46s Normal Created pod/hamster-65cd4dd797-nsb8c Created container hamster
46s Normal Pulled pod/hamster-65cd4dd797-nsb8c Container image "registry.k8s.io/ubuntu-slim:0.1" already present on machine
15s Normal Killing pod/hamster-65cd4dd797-8kpcg Stopping container hamster
VPA custom resource 정의
spec:
resourcePolicy:
containerPolicies:
- containerName: '*'
controlledResources:
- cpu
- memory
maxAllowed:
cpu: 1
memory: 500Mi
minAllowed:
cpu: 100m
memory: 50Mi
targetRef:
apiVersion: apps/v1
kind: Deployment
name: hamster
updatePolicy:
updateMode: Auto
위 example manifest에서 볼수 있듯이 주요 3가지 설정이 필요하다.
- resourcePolicy
- targetRef
- updatePolicy
resourcePolicy는 어떤 자원에 대한 허용 가능한 최대/최소 value를 지정한다.
targetRef는 해당 policy를 적용받은 대상을 지정한다.
updatePolicy는 다음 4가지 옵션으로 동작되어질수 있다.
- Auto
- Recreate
- Initial
- Off
- https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler#quick-start
exception cases
vpa의 max를 넘어서는 경우
새로운 pod의 requests는 max까지만 생성되어진다.
jacob@laptop:~ $ k get vpa hamster-vpa -o jsonpath='{.spec}' | jq
{
"resourcePolicy": {
"containerPolicies": [
{
"containerName": "*",
"controlledResources": [
"cpu",
"memory"
],
"maxAllowed": {
"cpu": "400m",
"memory": "100Mi"
},
"minAllowed": {
"cpu": "100m",
"memory": "50Mi"
}
}
]
},
"targetRef": {
"apiVersion": "apps/v1",
"kind": "Deployment",
"name": "hamster"
},
"updatePolicy": {
"updateMode": "Auto"
}
}
실제 vpa도 uncappedTarget는 500m를 넘게 측정되었지만 max가 400m이기에 400m까지만 target이 recommendation이 설정되고
jacob@laptop:~ $ k get vpa hamster-vpa -o jsonpath='{.status.recommendation}' | jq
{
"containerRecommendations": [
{
"containerName": "hamster",
"lowerBound": {
"cpu": "400m",
"memory": "100Mi"
},
"target": {
"cpu": "400m",
"memory": "100Mi"
},
"uncappedTarget": {
"cpu": "587m",
"memory": "262144k"
},
"upperBound": {
"cpu": "400m",
"memory": "100Mi"
}
}
]
}
400m로 cpu request가 설정되어 새로운 pod가 생성되어진다.
jacob@laptop:~ $ k get pod -l app=hamster -o jsonpath='{.items[*].spec.containers[*].resources}' | jq
{
"requests": {
"cpu": "400m",
"memory": "100Mi"
}
}
{
"requests": {
"cpu": "400m",
"memory": "100Mi"
}
}
참고로 새로운 pod에는 annotation이 다음과 같이 붙어진다.
jacob@laptop:~ $ k get pod -l app=hamster -o jsonpath='{.items[*].metadata.annotations}' | jq
{
"vpaObservedContainers": "hamster",
"vpaUpdates": "Pod resources updated by hamster-vpa: container 0: memory request, cpu request"
}
{
"vpaObservedContainers": "hamster",
"vpaUpdates": "Pod resources updated by hamster-vpa: container 0: cpu request, memory request"
}
limits가 max보다 낮을 경우
다음과 같이 deployment에 limit을 앞서 cpu 500m 이상 측정되던 requests 보다 낮게 잡았다.
jacob@laptop:~ $ k get deploy/hamster -o jsonpath='{.spec.template.spec.containers[*].resources}' | jq
{
"limits": {
"cpu": "400m",
"memory": "100Mi"
},
"requests": {
"cpu": "100m",
"memory": "50Mi"
}
}
limit도 늘려서 새로운 pod 생성한다. 아래에 두번째 결과는 vpa에 의해 새로 생성된 pod이며 첫번째 결과는 최초 vpa와 연관없이 배포된 pod 의 requests / limits 이다.
jacob@laptop:~ $ k get pod -l app=hamster -o jsonpath='{.items[*].spec.containers[*].resources}' | jq
{
"limits": {
"cpu": "400m",
"memory": "100Mi"
},
"requests": {
"cpu": "100m",
"memory": "50Mi"
}
}
{
"limits": {
"cpu": "2348m",
"memory": "500Mi"
},
"requests": {
"cpu": "587m",
"memory": "262144k"
}
}
'Cloud > Kubernetes' 카테고리의 다른 글
Postee (0) | 2023.03.17 |
---|---|
kubent(no trouble) (0) | 2023.03.14 |
Custom Container Registry with containerd runtime on Kubernetes (0) | 2023.02.13 |
cert-manager with ingress-nginx (0) | 2023.02.13 |
fluent-bit with azure service (0) | 2023.01.02 |
- Total
- Today
- Yesterday
- metallb
- socket
- open policy agent
- nginx-ingress
- kubernetes install
- ceph
- jenkins
- Jenkinsfile
- crashloopbackoff
- azure policy
- minikube
- vmware openstack
- kubernetes
- boundary ssh
- Helm Chart
- aquasecurity
- OpenStack
- minio
- GateKeeper
- K3S
- DevSecOps
- ansible
- kata container
- wsl2
- mattermost
- openstacksdk
- openstack backup
- hashicorp boundary
- macvlan
- Terraform
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |