home..

FeatureGate 와 Pod Resizing

Kubernetes FeatureGate InPlacePodVerticalScaling PodResizing PodResize

온프레미스 기준으로 Feature Gate를 활성화하여 Alpha, Beta 에서 테스트중인 기능들을 활성화하는 방법을 알아보도록 하겠습니다.

GA가 되기까지 Alpha와 Beta 과정을 거쳐야하고, 일부 과정은 Default로 활성화가 되지만 그렇지 않은 기능들도 존재합니다.

Beta의 경우 EKS에서도 사용이 가능하지만, Alpha의 경우 추가적인 개발로 이어지지 않을 확률도 존재하는 기능이기때문에 기능들에 대해서 간단하게 찍먹을 해보는 과정을 다뤄봅니다.

FeatureGates

해당 링크에서 사용 가능한 FeatureGate들을 확인할 수 있고

오늘 살펴볼 주제는 InPlacePodVerticalScaling입니다.

Untitled

노드의 kubelet 설정에서 feature gate를 활성화해줍니다.

Feature Gate 활성화하기

Worker 노드

/etc/systemd/system/kubelet.service


[Service]
EnvironmentFile=-/etc/default/kubelet
ExecStart=/usr/local/bin/kubelet \
                $KUBELET_EXTRA_ARGS

그리고 extra args로 선언한 파일을 신규로 작성해줍니다

/etc/default/kubelet

KUBELET_EXTRA_ARGS=--feature-gates=InPlacePodVerticalScaling=true

이번에 활성화해볼 기능은 InPlacePodVerticalScaling을 테스트해보겠습니다.

sudo systemctl restart kubelet
systemctl daemon-reload

워커노드에서 kubelet을 재실행시켜 featuret-gate가 잘 실행되는지 확인해봅니다.

Untitled

grep으로 feature gate에 잘 들어간것을 확인했으니 control-plane으로 가봅니다.

Control Plane 설정

kube-apiserver의 파일을 수정이 필요한데, 실수로 잘못건들경우 api-server가 안뜰수있으니 백업후 진행하도록 합니다.

/etc/kubernetes/manifest/kube-apiserver.yaml

spec:
  containers:
  - command:
    - kube-apiserver
    - --feature-gates=InPlacePodVerticalScaling=true

해당 기능을 추가하면 자동으로 api-server가 재구동됩니다.

InPlacePodVerticalScaling

이제 기능을 테스트해볼건데요

원래는 Pod spec을 다시 지정하면, kubelet에서 pod을 재구동합니다.

Untitled

이런 Json 형태를 갖는 Event를 가지면서 Pod를 재시작합니다.

apiVersion: v1
kind: Pod
metadata:
  name: resizable-ubuntu
  labels:
    test: resize
  annotations:
    resize: 'enable'
spec:
  containers:
  - name: ubuntu
    image: ubuntu:22.04
    command: ["/bin/sh"]
    args: ["-c", "sleep infinity"]
    resizePolicy:
    - resourceName: cpu
      restartPolicy: NotRequired
    - resourceName: memory
      restartPolicy: NotRequired
      # restartPolicy: RestartContainer
    resources:
      limits:
        memory: "200Mi"
        cpu: "700m"
      requests:
        memory: "200Mi"
        cpu: "700m"

기본 yaml 파일은

Untitled

이렇게 생성됩니다.

이제 새로 생긴 resizePolicy에 맞게 pod의 cpu spec을 patch 해봅니다.

kubectl patch pod resizable-ubuntu -n test --patch '{"spec":{"containers":[{"name":"ubuntu", "resources":{"requests":{"cpu":"2"}, "limits":{"cpu":"2"}}}]}}'

Untitled

State.Started 시간을 비교해볼경우, 위에 Patch 전과 동일한 시간인

Fri, 02 Feb 2024 15:51:26 +0000 이 보입니다.

실제로 Pod가 재시작되지않고, spec이 변경된것을 확인 할 수 있습니다

조금 더 변태적으로 들어가보기 위해

기존에 적용했던 LXCFS라는 File System을 Mount 한 상태에서 pod의 spec을 변경해보겠습니다.

Untitled

Restart Policy에 Memory또한 재시작 정책을 설정하지 않고, 패치를 거듭하며 변경되는 리소스 (CPU 및 Memory)들을 확인해봅니다.

사실 변경되는 값에대해서는 실시간으로 /proc 내부의 데이터가 변경되지 않을것으로 예상했지만

예상을 뛰어넘는 결과였네요.

사실 아직 InPlacePodVerticalScaling 의 Deployment에 대한 내용은 없었습니다.

실제로 Deployment에서 명세된 pod의 spec을 변경하면,

그럼 이걸 deployment에 녹여내보도록 하겠습니다.

사실 deployment의 spec을 변경하면, 변경된 spec에 맞는 pod이 “재생성” 되는게 원칙이기때문에

직접적인 기능을 지원하고있지 않습니다.

하지만, deployment에서 생성될 pod의 spec에 resize Policy가 생성가능하다는것을 직접 만들어보니 어렵지 않게 찾을수 있었습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: resizable-ubuntu-deployment
  namespace: test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: resizable-ubuntu
  template:
    metadata:
      labels:
        app: resizable-ubuntu
      annotations:
        resize: 'enable'
    spec:
      containers:
      - name: ubuntu
        resizePolicy:
        - resourceName: cpu
          restartPolicy: NotRequired
        - resourceName: memory
          restartPolicy: NotRequired
        image: ubuntu:22.04
        command: ["/bin/sh"]
        args: ["-c", "sleep infinity"]
        resources:
          limits:
            memory: "200Mi"
            cpu: "1"
          requests:
            memory: "200Mi"
            cpu: "1"

해당 형태로 pod을 명세할경우 resizepolicy가 적용된 pod을 품은 deployment가 생성됩니다.

이렇게 생성된 pod들또한, patch를 이용한 pod resizing이 가능한데요

기존에 생성했던 pod과 다른점은, pod name이 임의로 생성되기 때문에 비교적 까다로운 과정을 거치긴 해야합니다.

#!/bin/bash

# Set the namespace and deployment name
NAMESPACE=test
DEPLOYMENT_NAME=resizable-ubuntu-deployment

# Fetch the pods for the given deployment
PODS=$(kubectl get pods -n $NAMESPACE -l app=resizable-ubuntu -o jsonpath="{.items[*].metadata.name}")

for POD in $PODS
do
  echo "Patching Pod: $POD"
  kubectl patch pod $POD -n $NAMESPACE --patch '{
    "spec": {
      "containers": [
        {
          "name": "ubuntu",
          "resources": {
            "requests": {
              "cpu": "2",
              "memory": "600Mi"
            },
            "limits": {
              "cpu": "2",
              "memory": "600Mi"
            }
          }
        }
      ]
    }
  }'
done

echo "All pods patched successfully."

간단한 shell script를 작성해 deployment 이름을 기준으로 pod name을 획득하여 pod를 patch하는 shell script를 작성했습니다.

사실 고객사에서는 내부적인 서비스들을 통해 deployment의 spec을 재조절하는 시스템이 이미 개발되어있지만, 간단하게 흉내를 내보기위한 작업입니다.

Untitled

기존에 생성된 자원과, patch하여 resizing 된 pod 의 spec을 실시간으로 확인 할 수 있었군요.

실시간으로 top을 보고있어도, 변경되는 자원을 확인 할 수 있습니다.

Animation.gif

Untitled

노드의 allocate 되어있는 리소스를 비교해봐도 패치이후에 변하는 값들에 대해선 인식에 문제가 없음을 확인했습니다.

Untitled

성공적인 pod resizing에 성공했지만, 내렸던 결론이 있었습니다.

아직 정식으로 지원하는 기능은 아니기때문에, pod resizing은 pod의 patch만을 지원하기때문에

deployment에 명세 되어있는 spec과 실제로 pod의 spec이 달라집니다.

이런 desired state가 달라지는 것은 주의가 필요해 보입니다.

그래도 pod이 재시작 되지 않고, 리소스를 재분배할수있다는것은 꽤 매력적인 기능임에 분명합니다.

HPA등으로 pod 자체를 분할 할 수 있다면, 쪼개서 로드밸런싱등을 하는것도 좋다고 생각이되지만, 모든 아키텍처와 워크로드가 동일하지 않기때문에 적극적인 도입을 검토해볼 필요는 있다고 생각됩니다.

© 2024 mont kim   •  Powered by Soopr   •  Theme  Moonwalk