2023-02-09 metrics-server helm
개요
EKS 클러스터에 metrics-server를 설치 및 업그레이드 가이드입니다.
 이 가이드에서는 Helm v3를 사용해 metrics-server를 설치합니다.
이 가이드에서는 크게 2가지 주제를 다루고 있습니다.
- Helm 차트를 사용해서 metrics-server 설치하기
- Helm 차트를 사용해서 metrics-server 버전 업그레이드하기
환경
metrics-server를 배포할 환경은 2대의 EC2 워커노드로 구성된 EKS 클러스터입니다.

로컬 환경
- OS : macOS Ventura 13.2 (M1 Max)
- helm v3.11.0 : brew로 설치
- kubectl v1.26.1 : brew로 설치
클러스터 환경
metrics-server를 설치할 쿠버네티스 클러스터 환경은 2대의 워커노드로 구성된 EKS 클러스터입니다.
- EC2 기반의 워커노드
- 2 nodes
- x86_64
- Kubernetes v1.24 (v1.24.9-eks-49d8fe8)
설치 에드온 정보
- metrics-server v0.6.2 - 차트 버전 : v3.8.3 (2022년 12월 8일 릴리즈됨)
 
배경지식
metrics-server의 필요성
EKS 클러스터에서 kubectl top 명령어 실행시 아래와 같은 오류가 발생합니다.
$ kubectl top node
error: Metrics API not available
$ kubectl top pod
error: Metrics API not available
이 경우, EKS 클러스터에 metrics-server 가 미설치된 상태라 메트릭을 수집할 수 없어서 발생하는 문제입니다.
metrics-server는 크게 2가지 역할을 합니다.
- Horizontal Pod Autoscaler(HPA)가 파드를 스케일 인, 아웃 처리하기 위한 판단 기준인 파드 메트릭 수집
- kubectl top명령어를 사용하기 위한 노드 메트릭 수집
버전 호환성
사용중인 Kubernetes 버전에 따라 metrics-server 버전에도 제약사항이 있습니다.
 예를 들어 Kubernetes v1.19 이상 버전은 반드시 metrics-server v0.6.x를 사용해야 합니다.
자세한 사항은 metrics-server 공식문서에서 확인할 수 있습니다.
메트릭 에드온 비교
쿠버네티스 클러스터 내부의 메트릭 수집을 위한 에드온으로는 크게 2가지가 있습니다.
- kube-state-metrics
- metrics-server
이 2개의 메트릭 에드온의 차이점은 다음과 같습니다.
kube-state-metrics
kube-state-metrics는 Kubernetes API 서버를 수신하고 개체의 상태에 대한 메트릭을 생성하는 간단한 서비스입니다.
 개별 Kubernetes 컴포넌트의 상태가 아니라 Deployment, Node 및 Pod와 같은 내부의 다양한 개체 상태에 중점을 둡니다.
 kube-state-metrics를 사용하면 오픈소스 모니터링 툴킷인 Prometheus를 이용하여 매트릭 데이터를 수집할 수 있습니다.
metrics-server
반면에 metrics-server는 Resource Metrics API를 구현합니다.
 한 문장으로 요약하면 kube-state-metrics는 모든 종류의 Kubernetes 개체에 대한 메트릭을 노출합니다. metrics-server는 노드 및 포드 사용률과 같이 Kubernetes 자체에 매우 적은 메트릭만 노출합니다. 또한, Prometheus에서 metrics-server를 직접 스크랩할 수 없습니다.
이미 다른 유저가 이에 대해 질문한 깃허브 이슈가 있습니다.
 자세한 설명은 Differences between metrics-server repo and kube-state-metrics repo #55 이슈를 참고 부탁드립니다.
metrics-server 설치
helm 세팅
클러스터 안에 metrics-server 파드가 존재하는 지 확인합니다.
$ kubectl get pod -n kube-system
NAME                                            READY   STATUS    RESTARTS   AGE
aws-load-balancer-controller-77fffd87bc-79mwd   1/1     Running   0          7h53m
aws-load-balancer-controller-77fffd87bc-hxtfq   1/1     Running   0          7h53m
aws-node-bllwq                                  1/1     Running   0          9h
aws-node-zhlxf                                  1/1     Running   0          9h
coredns-dc4979556-bps74                         1/1     Running   0          7h53m
coredns-dc4979556-w58mt                         1/1     Running   0          7h53m
ebs-csi-controller-84b55655df-2pr5r             6/6     Running   0          7h52m
ebs-csi-controller-84b55655df-n8pj4             6/6     Running   0          7h53m
...
위와 같은 경우 설치되지 않았다고 판단할 수 있습니다.
헬름 레포를 추가합니다.
$ helm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server/
"metrics-server" has been added to your repositories
등록된 헬름 레포 목록을 확인합니다.
$ helm repo list
NAME            URL
metrics-server  https://kubernetes-sigs.github.io/metrics-server/
metrics-server 레포가 새롭게 추가된 걸 확인할 수 있습니다.
values.yaml 작성
metrics-server의 원본 values.yaml을 자신의 환경에 맞게 수정합니다.
# Default values for metrics-server.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
image:
  repository: registry.k8s.io/metrics-server/metrics-server
  # Overrides the image tag whose default is v{{ .Chart.AppVersion }}
  tag: ""
  pullPolicy: IfNotPresent
imagePullSecrets: []
# - name: registrySecretName
nameOverride: ""
fullnameOverride: ""
serviceAccount:
  # Specifies whether a service account should be created
  create: true
  # Annotations to add to the service account
  annotations: {}
  # The name of the service account to use.
  # If not set and create is true, a name is generated using the fullname template
  name: ""
  # The list of secrets mountable by this service account.
  # See https://kubernetes.io/docs/reference/labels-annotations-taints/#enforce-mountable-secrets
  secrets: []
rbac:
  # Specifies whether RBAC resources should be created
  create: true
  pspEnabled: false
apiService:
  # Specifies if the v1beta1.metrics.k8s.io API service should be created.
  #
  # You typically want this enabled! If you disable API service creation you have to
  # manage it outside of this chart for e.g horizontal pod autoscaling to
  # work with this release.
  create: true
  # Annotations to add to the API service
  annotations: {}
  # Specifies whether to skip TLS verification
  insecureSkipTLSVerify: true
  # The PEM encoded CA bundle for TLS verification
  caBundle: ""
commonLabels: {}
podLabels: {}
podAnnotations: {}
podSecurityContext: {}
securityContext:
  allowPrivilegeEscalation: false
  readOnlyRootFilesystem: true
  runAsNonRoot: true
  runAsUser: 1000
priorityClassName: system-cluster-critical
containerPort: 10250
hostNetwork:
  # Specifies if metrics-server should be started in hostNetwork mode.
  #
  # You would require this enabled if you use alternate overlay networking for pods and
  # API server unable to communicate with metrics-server. As an example, this is required
  # if you use Weave network on EKS
  enabled: false
replicas: 2
updateStrategy: {}
#   type: RollingUpdate
#   rollingUpdate:
#     maxSurge: 0
#     maxUnavailable: 1
podDisruptionBudget:
  # https://kubernetes.io/docs/tasks/run-application/configure-pdb/
  enabled: false
  minAvailable:
  maxUnavailable:
defaultArgs:
  - --cert-dir=/tmp
  - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
  - --kubelet-use-node-status-port
  - --metric-resolution=15s
args: []
livenessProbe:
  httpGet:
    path: /livez
    port: https
    scheme: HTTPS
  initialDelaySeconds: 0
  periodSeconds: 10
  failureThreshold: 3
readinessProbe:
  httpGet:
    path: /readyz
    port: https
    scheme: HTTPS
  initialDelaySeconds: 20
  periodSeconds: 10
  failureThreshold: 3
service:
  type: ClusterIP
  port: 443
  annotations: {}
  labels: {}
  #  Add these labels to have metrics-server show up in `kubectl cluster-info`
  #  kubernetes.io/cluster-service: "true"
  #  kubernetes.io/name: "Metrics-server"
addonResizer:
  enabled: false
  image:
    repository: registry.k8s.io/autoscaling/addon-resizer
    tag: 1.8.14
  resources:
    limits:
      cpu: 40m
      memory: 25Mi
    requests:
      cpu: 40m
      memory: 25Mi
  nanny:
    cpu: 20m
    extraCpu: 1m
    extraMemory: 2Mi
    memory: 15Mi
    minClusterSize: 10
    pollPeriod: 300000
    threshold: 5
metrics:
  enabled: false
serviceMonitor:
  enabled: false
  additionalLabels: {}
  interval: 1m
  scrapeTimeout: 10s
  metricRelabelings: []
  relabelings: []
# See https://github.com/kubernetes-sigs/metrics-server#scaling
resources: {}
extraVolumeMounts: []
extraVolumes: []
nodeSelector: {}
tolerations: []
affinity: {}
topologySpreadConstraints: []
# Annotations to add to the deployment
deploymentAnnotations: {}
schedulerName: ""
기본적으로 metrics-server 컨테이너 이미지를 외부에서 받아오도록 설정되어 있습니다.
 아래는 metric-server 헬름 차트에서 이미지 받아오는 경로에 대한 설정 부분입니다.
# values.yaml
...
image:
  repository: registry.k8s.io/metrics-server/metrics-server
  # Overrides the image tag whose default is v{{ .Chart.AppVersion }}
  tag: ""
  pullPolicy: IfNotPresent
...
위와 같이 기본값을 사용해서 metrics-server 헬름 차트를 설치하는 경우 워커 노드들이 NAT Gateway, Internet Gateway를 통해 도커 허브에 액세스 가능한 상태여야 정상적으로 파드 배포가 완료됩니다.
일반적으로 도커 허브에 업로드된 metrics-server 컨테이너 이미지를 받아오는 대신 Private ECR에 업로드해서 운영하는 걸 권장합니다.
제 경우 기본 차트의 values.yaml 파일에서 고가용성을 위해 아래와 같이 replicas 값만 1에서 2로 변경했습니다.
# values.yaml
...
replicas: 2
...
metrics-server 설치
values.yaml 파일과 같은 경로로 이동합니다.
$ tree
.
└── values.yaml
1 directory, 1 files
최신 버전의 헬름 차트를 사용해서 metrics-server를 설치합니다.
$ helm upgrade \
    --install metrics-server metrics-server/metrics-server \
    --namespace kube-system \
    --values values.yaml \
    --wait
metrics-server 관련 쿠버네티스 리소스는 kube-system 네임스페이스에 설치되어야 합니다.
헬름 설치 후 차트의 배포 상태를 확인합니다.
$ helm status metrics-server -n kube-system
NAME: metrics-server
LAST DEPLOYED: Wed Feb  8 23:49:39 2023
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
***********************************************************************
* Metrics Server                                                      *
***********************************************************************
  Chart version: 3.8.3
  App version:   0.6.2
  Image tag:     registry.k8s.io/metrics-server/metrics-server:v0.6.2
***********************************************************************
클러스터에 배포된 metrics-server 관련 Deployment, Pod 등의 전반적인 상태도 확인합니다.
$ kubectl get all \
    -l app.kubernetes.io/instance=metrics-server \
    -n kube-system
NAME                                  READY   STATUS    RESTARTS   AGE
pod/metrics-server-6c968cf978-hgfx4   1/1     Running   0          38m
pod/metrics-server-6c968cf978-qks6l   1/1     Running   0          38m
NAME                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/metrics-server   ClusterIP   172.20.142.97   <none>        443/TCP   38m
NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/metrics-server   2/2     2            2           38m
NAME                                        DESIRED   CURRENT   READY   AGE
replicaset.apps/metrics-server-6c968cf978   2         2         2       38m
위와 같은 경우 정상적이라고 판단할 수 있습니다.
metrics-server 파드는 Deployment에 의해 항상 동일한 개수를 유지됩니다.
 위의 경우는 2개의 metrics-server 파드를 항상 유지합니다.
---
title: Kubernetes architecture for metrics-server
---
flowchart LR
    subgraph "Kubernetes Cluster"
        direction LR
        subgraph "Namespace kube-system"
            direction LR
            d["`**Deployment**
            metrics-server`"]
            r["**ReplicaSet**"]
            p1(["`**Pod**
            metrics-server`"])
            p2(["`**Pod**
            metrics-server`"])
        end
        kb["kubelet"]
    end
    d --> r --> p1 & p2
    p1 & p2 --Scrape metrics--> kb
    style p1 fill:darkorange, color:white
    style p2 fill:darkorange, color:white
결과 확인
metrics-server를 설치한 후 kubectl top node, kubectl top pod 명령어가 정상적으로 실행되는 지 확인합니다.
$ kubectl top node
NAME                                                CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
ip-10-xxx-xxx-xxx.ap-northeast-2.compute.internal   54m          2%     835Mi           25%
ip-10-xxx-xxx-xxx.ap-northeast-2.compute.internal   69m          3%     2248Mi          67%
$ kubectl top pod
NAME                       CPU(cores)   MEMORY(bytes)
httpbin-648cd984f8-8ttfz   1m           36Mi
이제 metrics-server를 통해 받아온 워커노드와 파드의 리소스 메트릭이 출력됩니다.
이것으로 설치 가이드를 마칩니다.
metrics-server 업그레이드
이 시나리오는 Helm v3를 사용해서 기존에 설치된 metrics-server를 버전 업그레이드합니다.
- 헬름 차트 : 3.8.3 → 3.9.0
- metrics-server 앱 : v0.6.2 → v0.6.3
metrics-server의 ArtifactHUB를 확인한 후 업그레이드할 차트 버전을 지정합니다.
$ CHART_VERSION='3.9.0'
중요
 헬름 차트의 릴리즈 노트를 통해 변경사항을 체크하고 values.yaml을 업데이트한 후 저장합니다.
헬름 차트로 metrics-server를 버전 업그레이드합니다.
# metrics-server 공식 헬름 차트 추가
$ helm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server/
# metrics-server 버전 업그레이드
$ helm upgrade \
    --install metrics-server metrics-server/metrics-server \
    -f values.yaml \
    -n kube-system \
    --version $CHART_VERSION \
    --wait
metrics-server 파드가 교체되는 데 시간이 걸리므로 잠시 기다립니다.
Release "metrics-server" has been upgraded. Happy Helming!
NAME: metrics-server
LAST DEPLOYED: Sun Apr  2 22:14:38 2023
NAMESPACE: kube-system
STATUS: deployed
REVISION: 7
TEST SUITE: None
NOTES:
***********************************************************************
* Metrics Server                                                      *
***********************************************************************
  Chart version: 3.9.0
  App version:   0.6.3
  Image tag:     registry.k8s.io/metrics-server/metrics-server:v0.6.3
***********************************************************************
helm upgrade 명령어의 실행 결과에서 새로운 버전의 Chart version, App version 정보가 출력되는 지 확인합니다.
metrics-server 파드가 사용할 이미지 태그 값은 기본적으로 차트의 App version 값으로 오버라이딩되어 적용됩니다.
아래는 metrics-server의 values.yaml 파일 내용입니다.
# Default values for metrics-server.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
image:
  repository: registry.k8s.io/metrics-server/metrics-server
  # Overrides the image tag whose default is v{{ .Chart.AppVersion }}
  tag: ""
  pullPolicy: IfNotPresent
...
헬름 차트 배포 상태와 metrics-server 관련 리소스의 전반적인 상태를 확인합니다.
$ helm status metrics-server \
    -n kube-system \
    --show-resources
관련자료
metrics-server
 공식 깃허브
metrics-server values.yaml
 metrics-server 헬름차트에서 사용하는 values.yaml 파일
ArtifactHUB - metrics-server
 공식 차트가 업로드된 ArtifactHub