kubectlのtopコマンドを使うためにメトリクスサーバをインストールしたら HTTP probe failed with statuscode: 500 になった

2021/05/20

転職を機に Kubernetes を触り始めたのですが、わからないことだらけで日々、苦戦しています。

そんなある日、Pod のリソース状況を確認したいと思うことがあり、調べていると top コマンドがあることを知り、早速使ってみたらエラーになったので解決までをまとめてみました。

環境

OS

macOS

Kubernetes

v1.19.7

Docker Engine

v20.10.6

kubectl topコマンドでPodのリソース状況を確認

Pod のリソース状況を確認するため、早速コマンドを実行してみると下記のような結果になりました。

$ ku top pod app-54f4fcc564-kjg6s
error: Metrics API not available

「Metrics API」 がないよと言われているので調べてみると、メトリクスサーバをインストールする必要があることがわかりました。

メトリクスサーバをインストール

ローカル環境で試していますが、最終的には EKS のクラスターの反映したいので EKS で調べてみると、AWSのドキュメントがあったので、これをもとにやってみます。

apply コマンドでメトリクスサーバをインストール

ドキュメントにある通り、 kubectl apply コマンドでメトリクスサーバをインストールします。

$ kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
serviceaccount/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
service/metrics-server created
deployment.apps/metrics-server created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created

created と表示されているので、問題なくインストールできたようです。

メトリクスサーバの Pod が起動しているか確認

メトリクスサーバをインストールできたので、起動しているか確認してみたいと思います。

$ kubectl get pod -n kube-system
NAME                                     READY   STATUS    RESTARTS   AGE
metrics-server-5fbdc54f8c-gqnwz          0/1     Running   0          24s

kube-system というネームスペースにインストールしているので、末尾で指定する必要があります。

ステータスは「Running」になっていますが、Readyが「0/1」なので何か問題がありそうな気もしますが、もう一度 kubectl top コマンドを実行してみます。

メトリクスサーバをインストールしたのでリソース状況を再確認

さっきと同じコマンドを実行してみると、エラーの内容が変わりました。

$ ku top pod app-54f4fcc564-kjg6s
Error from server (ServiceUnavailable): the server is currently unable to handle the request (get pods.metrics.k8s.io app-54f4fcc564-kjg6s)

メトリクスサーバのエラーを調査

Pod の状況を確認

Pod自体は作成できていたので、kubectl describe pod で Pod の状況を確認してみます。

$ ku describe pod metrics-server-5fbdc54f8c-gqnwz -n kube-system
Name:                 metrics-server-5fbdc54f8c-gqnwz
Namespace:            kube-system
Priority:             2000000000
Priority Class Name:  system-cluster-critical
Node:                 desktop/192.168.65.4
Start Time:           Wed, 19 May 2021 18:26:43 +0900
Labels:               k8s-app=metrics-server
                      pod-template-hash=5fbdc54f8c
Annotations:          <none>
Status:               Running
IP:                   192.168.1.96
IPs:
  IP:           192.168.1.96
Controlled By:  ReplicaSet/metrics-server-5fbdc54f8c
Containers:
  metrics-server:
    Container ID:  docker://667f17ee8d609192d95415085ded5651f5286994f991ba5977d5a57dd33fb4e4
    Image:         k8s.gcr.io/metrics-server/metrics-server:v0.4.4
    Image ID:      docker-pullable://k8s.gcr.io/metrics-server/metrics-server@sha256:f8643f007c8a604388eadbdac43d76b95b56ccd13f7447dd0934b594b9f7b363
    Port:          4443/TCP
    Host Port:     0/TCP
    Args:
      --cert-dir=/tmp
      --secure-port=4443
      --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
      --kubelet-use-node-status-port
    State:          Waiting
      Reason:       CrashLoopBackOff
    Last State:     Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Wed, 19 May 2021 18:29:48 +0900
      Finished:     Wed, 19 May 2021 18:30:17 +0900
    Ready:          False
    Restart Count:  5
    Liveness:       http-get https://:https/livez delay=0s timeout=1s period=10s #success=1 #failure=3
    Readiness:      http-get https://:https/readyz delay=0s timeout=1s period=10s #success=1 #failure=3
    Environment:    <none>
    Mounts:
      /tmp from tmp-dir (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from metrics-server-token-js6l2 (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             False
  ContainersReady   False
  PodScheduled      True
Volumes:
  tmp-dir:
    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:
    SizeLimit:  <unset>
  metrics-server-token-js6l2:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  metrics-server-token-js6l2
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  kubernetes.io/os=linux
Tolerations:     node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type     Reason     Age                    From               Message
  ----     ------     ----                   ----               -------
  Normal   Scheduled  3m35s                  default-scheduler  Successfully assigned kube-system/metrics-server-5fbdc54f8c-gqnwz to desktop
  Normal   Pulled     2m41s (x3 over 3m33s)  kubelet            Container image "k8s.gcr.io/metrics-server/metrics-server:v0.4.4" already present on machine
  Normal   Created    2m41s (x3 over 3m33s)  kubelet            Created container metrics-server
  Normal   Started    2m41s (x3 over 3m33s)  kubelet            Started container metrics-server
  Normal   Killing    2m41s (x2 over 3m11s)  kubelet            Container metrics-server failed liveness probe, will be restarted
  Warning  Unhealthy  2m31s (x7 over 3m31s)  kubelet            Liveness probe failed: HTTP probe failed with statuscode: 500
  Warning  Unhealthy  2m26s (x7 over 3m25s)  kubelet            Readiness probe failed: HTTP probe failed with statuscode: 500

エラーが発生していることが発覚

実行結果を確認してみると、「 Liveness probe failed: HTTP probe failed with statuscode: 500」と「Readiness probe failed: HTTP probe failed with statuscode: 500」というエラーが発生しているのが確認できます。

エラーの内容を調べているとオプションで回避できそうなことがわかったので、ダウンロードしたマニフェストファイルとドキュメントの設定欄と見比べてみます。

認証をしないオプションがあった

ドキュメントを確認していると、 --kubelet-insecure-tls というオプションがあり、これを指定するとCAの認証をしないようです。

メトリクスサーバ起動時のオプションを追加

解決に向けて、マニフェストファイルのオプションを指定している箇所に --kubelet-insecure-tls を追加します。

$ vim components.yaml
~ #省略
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
spec:
  selector:
    matchLabels:
      k8s-app: metrics-server
  strategy:
    rollingUpdate:
      maxUnavailable: 0
  template:
    metadata:
      labels:
        k8s-app: metrics-server
    spec:
      containers:
      - args:
        - --cert-dir=/tmp
        - --secure-port=4443
        - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
        - --kubelet-use-node-status-port
        - --kubelet-insecure-tls # 追加
        image: k8s.gcr.io/metrics-server/metrics-server:v0.4.4
        imagePullPolicy: IfNotPresent
~ #省略

.spec.template.spec.containers.args にオプションが並んでいるので、一番下に追加します。

メトリクスサーバを作り変え

そのまま更新できそうですが、念のため一度削除してから作り直してみます。

$ kubectl delete -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

削除が終わったら、ローカルで編集したファイルでメトリクスサーバを作成。

$ kubectl apply -f components.yaml
serviceaccount/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
service/metrics-server created
deployment.apps/metrics-server created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io create

無事に作成できました。

新しいメトリクスサーバの状況を確認

メトリクスサーバの作り変えが終わったので、もう一度 Pod の状況を確認してみます。

$ ku describe pod metrics-server-6778f49766-ntrwn -n kube-system
Name:                 metrics-server-6778f49766-ntrwn
Namespace:            kube-system
Priority:             2000000000
Priority Class Name:  system-cluster-critical
Node:                 desktop/192.168.1.4
Start Time:           Wed, 19 May 2021 18:57:55 +0900
Labels:               k8s-app=metrics-server
                      pod-template-hash=6778f49766
Annotations:          <none>
Status:               Running
IP:                   192.168.1.104
IPs:
  IP:           192.168.1.104
Controlled By:  ReplicaSet/metrics-server-6778f49766
Containers:
  metrics-server:
    Container ID:  docker://ea009e52c36a0d075e9a8c60be7d9e872f0cbcb4e10bed33bf7c107f09c17ff7
    Image:         k8s.gcr.io/metrics-server/metrics-server:v0.4.4
    Image ID:      docker-pullable://k8s.gcr.io/metrics-server/metrics-server@sha256:f8643f007c8a604388eadbdac43d76b95b56ccd13f7447dd0934b594b9f7b363
    Port:          4443/TCP
    Host Port:     0/TCP
    Args:
      --cert-dir=/tmp
      --secure-port=4443
      --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
      --kubelet-use-node-status-port
      --kubelet-insecure-tls
    State:          Running
      Started:      Wed, 19 May 2021 18:57:56 +0900
    Ready:          True
    Restart Count:  0
    Liveness:       http-get https://:https/livez delay=0s timeout=1s period=10s #success=1 #failure=3
    Readiness:      http-get https://:https/readyz delay=0s timeout=1s period=10s #success=1 #failure=3
    Environment:    <none>
    Mounts:
      /tmp from tmp-dir (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from metrics-server-token-k5rdk (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  tmp-dir:
    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:
    SizeLimit:  <unset>
  metrics-server-token-k5rdk:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  metrics-server-token-k5rdk
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  kubernetes.io/os=linux
Tolerations:     node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Scheduled  2m58s  default-scheduler  Successfully assigned kube-system/metrics-server-6778f49766-ntrwn to desktop
  Normal  Pulled     2m56s  kubelet            Container image "k8s.gcr.io/metrics-server/metrics-server:v0.4.4" already present on machine
  Normal  Created    2m56s  kubelet            Created container metrics-server
  Normal  Started    2m56s  kubelet            Started container metrics-server

もともと出ていたエラーが消えました!これで問題なく起動できていそうです。

kubectl top コマンドでリソース状況を確認

メトリクスサーバの作成ができたので、今回の目的である kubectl top コマンドを実行します。

※メトリクスサーバを作成してすぐだとデータを取れないことがあるため少しおいてから実行すると良さそうです

$ ku top pod app-54f4fcc564-kjg6s
NAME                     CPU(cores)   MEMORY(bytes)
app-54f4fcc564-kjg6s   1m           122Mi

おぉー!無事に kubectl top コマンドの結果が表示されました!

エラーになるとめちゃくちゃ不安になりますが、無事に解決できると嬉しいですね。

今後は、kubectl top コマンドを活用していこうと思います。