devops

Karpenter의 Provisioner 본문

DevOps/Kubernetes

Karpenter의 Provisioner

vata500 2023. 7. 2. 16:21
반응형

Provisioner

프로비저너는 카펜터를 시작할 때 기본적으로 사용되는 노드와 파드의 구성값, 제약 조건을 설정한다.

  • pod의 리밋인 taint를 정의
  • node의 zone, instance type, computer architecture 정의
  • node expiration 정의

spec.requirements

  # Requirements that constrain the parameters of provisioned nodes.
  # These requirements are combined with pod.spec.affinity.nodeAffinity rules.
  # Operators { In, NotIn } are supported to enable including or excluding values
  requirements:
    - key: "karpenter.k8s.aws/instance-category"
      operator: In
      values: ["c", "m", "r"]
    - key: "karpenter.k8s.aws/instance-cpu"
      operator: In
      values: ["4", "8", "16", "32"]
    - key: "karpenter.k8s.aws/instance-hypervisor"
      operator: In
      values: ["nitro"]
    - key: karpenter.k8s.aws/instance-generation
      operator: Gt
      values: ["2"]
    - key: "topology.kubernetes.io/zone"
      operator: In
      values: ["us-west-2a", "us-west-2b"]
    - key: "kubernetes.io/arch"
      operator: In
      values: ["arm64", "amd64"]
    - key: "karpenter.sh/capacity-type" # If not included, the webhook for the AWS cloud provider will default to on-demand
      operator: In
      values: ["spot", "on-demand"]

requirements는 Provisioner API 섹션이다. 인스턴스의 타입과 CPU, region, architecture 등 을 정의한다. 사실 architecture를 제외하면 크게 설정할 필요가 없다. karpenter가 비용효율적으로 Node의 consolidate와 Node 생성과 삭제를 진행하기 때문. 

만약 Capacity type이 spot이라면 남는 resource의 instance type이 있어야 가능하기 때문에 instance category를 최대한 많이 설정할 필요가 있다.

spec.kubeletConfiguration

spec:
  ...
  kubeletConfiguration:
    clusterDNS: ["10.0.1.100"]
    containerRuntime: containerd
    systemReserved:
      cpu: 100m
      memory: 100Mi
      ephemeral-storage: 1Gi
    kubeReserved:
      cpu: 200m
      memory: 100Mi
      ephemeral-storage: 3Gi
    evictionHard:
      memory.available: 5%
      nodefs.available: 10%
      nodefs.inodesFree: 10%
    evictionSoft:
      memory.available: 500Mi
      nodefs.available: 15%
      nodefs.inodesFree: 15%
    evictionSoftGracePeriod:
      memory.available: 1m
      nodefs.available: 1m30s
      nodefs.inodesFree: 2m
    evictionMaxPodGracePeriod: 60
    imageGCHighThresholdPercent: 85
    imageGCLowThresholdPercent: 80
    cpuCFSQuota: true
    podsPerCore: 2
    maxPods: 20

 

kubelet은 각 노드에서 실행되는 Node agent로 Node에 Pod를 직접 생성, 삭제, 관리하는 역할을 한다. karpenter는 Provisioner를 통해서 이 kubelet에 관련된 argumentes를 설정할 수 있다.

  • Reserved Resources : 카펜터는 kube reserve resource 요청을 사용자를 대신하여 자동으로 구성한다. 이 요청은 노드를 구성하고 포드에 대한 스케쥴링에 사용된다.
  • Eviction Thresholds : kubelet은 evction thresholds를 지원하는데, 노드에 충분한 리소스가 유지될 때 시스템 데몬과 다른 시스템이 안정적으로 작동하기 위해서 pod를 제거한다. 여기서 kubelet은 hard, soft evction 두 가지 방식으로 eviction을 실행한다.hard 방식.spec.kubeletConfiguration.evictionHard은 조건에 부합하면 즉시 evict하는 것이고, soft 방식.spec.kubeletConfiguration.evictionSoft은 pod가 우아하게? 제거되도록 기회, 시간을 준다.

eviction 설정에 대한 내

spec.limits.resources

imits.resources는 리소스의 최대량을 설정한다. 이 리밋을 초과하면 노드는 제거되도록 하여 불필요한 리소스 낭비를 제한한다.

apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
  name: default
spec:
  requirements:
    - key: karpenter.sh/capacity-type
      operator: In
      values: ["spot"]
  limits:
    resources:
      cpu: 1000
      memory: 1000Gi
      nvidia.com/gpu: 2

그러나 카펜터으 프로비저닝은 병렬적으로 진행되기 때문에 급진적인 스케일아웃의 경우, 리밋을 초과하는 overrun이 발생할 수 있다.

spec.providerRef

미리 선언된 Nodetemplate을 참조

spec.consolidation

카펜터는 효율적인 노드 관리를 위해 불필요한 노드는 deprovisioning하여 인스턴스를 통합한다. 여기서 사용되는 값은 spec.TTLSecondsAfterEmpty, spec.ttlSecondsUntilExpired, spec.consolidation.enabled 이 있다.


Use-case 1 / taints-tolerations

apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
  name: gpu
spec:
  consolidation:
    enabled: true
  requirements:
  - key: node.kubernetes.io/instance-type
    operator: In
    values: ["p3.8xlarge", "p3.16xlarge"]
  taints:
  - key: nvidia.com/gpu
    value: "true"
    effect: NoSchedule

위는 nvidia.com/gpu 키의 taint가 설정된 provisioner이다. taint가 설정되었기 때문에 toleration이 설정된 pod만 해당 노드에서 생성될 수 있다. consolidation이 enable되었기 때문에 인스턴스의 통합이 가능하다.

아래는 nvidia.com/gpu toleration이 설정된 pod yaml이다. 이 pod는 위 node에서 생성이 가능하다. 왜? 오염에 대한 내성(tolerance)가 있어서.

apiVersion: v1
kind: Pod
metadata:
  name: mygpupod
spec:
  containers:
  - name: gpuapp
    resources:
      requests:
        nvidia.com/gpu: 1
      limits:
        nvidia.com/gpu: 1
    image: mygpucontainer
  tolerations:
  - key: "nvidia.com/gpu"
    operator: "Exists"
    effect: "NoSchedule"

operator 옵션

  • Equal : 키, 값, 효과가 모두 같은지 확인.
  • Exists : 값을 확인하지 않으며, 필요하지 않음. key값이 설정되어 있지않으면, 어떤 taint가 걸려있어도 무시하고 스케쥴링되어 포드 실행함. key값이 하나라도 존재하면 해당 키의 taint가 적용된 노드에만 실행됨

effect 옵션

  • NoSchedule : toleration이 없으면 포드가 스케쥴되어 실행되지 않음. 기존에 실행되던 포드에는 적용되지 않음.
  • PreferNoSchedule: toleration이 없으면 포드를 스케쥴링 하지 않으려고 하긴 하지만 필수는 아님. 클러스터내의 자원이  부족하거나 하면 taint가 걸려 있는 노드에서 포드가 스케쥴링 될 수 있음.
  • NoExecute : 새로운 포드도 toleration이 없으면 실행되지 않게 하고, 기존에 있던 포드역시 taint에 맞는 toleration설정이 없으면 종료. 
반응형
Comments