metrics-server@ハードウェアリソース管理系¶
はじめに¶
本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。
01. metrics-serverの仕組み¶
アーキテクチャ¶
metrics-serverは、拡張APIサーバー、ローカルストレージ、スクレイパー、といったコンポーネントから構成される。
PodとNodeのメトリクスのデータポイントを収集し、kubectl top
コマンドでこれを取得できる。
また必須ではないが、HorizontalPodAutoscalerとVerticalPodAutoscalerを作成すれば、Podの自動水平スケーリングや自動垂直スケーリングを実行できる。
KubernetesのNodeとPod (それ以外のKubernetesリソースは対象外) のメトリクスのデータポイントを収集しつつ、収集したデータポイントを拡張APIサーバーで公開する。
似た名前のツールにkube-metrics-serverがあるが、こちらはExporterとして稼働する。
(1)
-
クライアント (
kubectl top
コマンド実行者、HorizontalPodAutoscaler、VerticalPodAutoscaler) がmetrics-serverのAPIからメトリクスを参照しようとする。 (2)
-
クライアントは、kube-apiserverにリクエストが送信する。
(3)
-
kube-apiserverは、metrics-serverのプロキシ (APIService) にリクストを転送する。
(4)
-
APIServiceは、クライアントにメトリクスを返信する。
拡張APIサーバー¶
▼ 拡張APIサーバーとは¶
拡張APIサーバーは、ServiceとAPIServiceを介して、クライアント (kubectl top
コマンド実行者、HorizontalPodAutoscaler、VerticalPodAutoscaler) からのリクエストを受信し、メトリクスのデータポイントを含むレスポンスを返信する。
データポイントはローカルストレージに保管している。
ローカルストレージ¶
ローカルストレージは、クライアント (kubectl top
コマンド実行者、HorizontalPodAutoscaler、VerticalPodAutoscaler) 宛先となっているPodやNodeのメトリクスのデータポイントを保管する。
スクレイパー¶
スクレイパーは、kubeletのデーモンからPodやNodeからメトリクスのデータポイントを定期的に収集し、ローカルストレージに保管する。
kubeletのデーモンはメトリクス収集用エンドポイント (例:/metrics/resource
、/stats
など) を持ち、これがスクレイパーの収集対象になる。
そのため、PodやNodeにメトリクス収集用エンドポイント (例:/metrics
) を設ける必要はない。
01-02. マニフェスト¶
Deployment配下のPod¶
記入中...
apiVersion: apps/v1
kind: Pod
metadata:
name: metrics-server
namespace: kube-system
spec:
containers:
- name: metrics-server
image: registry.k8s.io/metrics-server/metrics-server:v0.6.3
imagePullPolicy: IfNotPresent
args:
- --cert-dir=/tmp
- --secure-port=4443
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --kubelet-use-node-status-port
# メトリクスの収集間隔を最小にする。
# https://github.com/kubernetes-sigs/metrics-server/blob/master/FAQ.md#how-often-metrics-are-scraped
- --metric-resolution=15s
resources:
requests:
cpu: 100m
memory: 200Mi
ports:
- name: https
containerPort: 4443
protocol: TCP
readinessProbe:
httpGet:
path: /readyz
port: https
scheme: HTTPS
periodSeconds: 10
failureThreshold: 3
initialDelaySeconds: 20
livenessProbe:
httpGet:
path: /livez
port: https
scheme: HTTPS
periodSeconds: 10
failureThreshold: 3
# metrics-serverの準備完了を待たずにReadinessProbeヘルスチェックを実施しないように、初回のヘルスチェックを開始するまでの待機時間を延長する
# https://github.com/kubernetes-sigs/metrics-server/issues/1056#issuecomment-1288198994
initialDelaySeconds: 80
securityContext:
readOnlyRootFilesystem: "true"
runAsNonRoot: "true"
runAsUser: 1000
volumeMounts:
- mountPath: /tmp
name: tmp-dir
priorityClassName: system-cluster-critical
serviceAccountName: metrics-server
volumes:
- emptyDir: {}
name: tmp-dir
APIService¶
記入中...
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
labels:
k8s-app: metrics-server
name: v1beta1.metrics.k8s.io
spec:
group: metrics.k8s.io
groupPriorityMinimum: 100
insecureSkipTLSVerify: "true"
service:
name: metrics-server
namespace: kube-system
version: v1beta1
versionPriority: 100
02. kubectl top
コマンド¶
node¶
▼ nodeとは¶
Nodeのハードウェアリソースの消費量を取得する。
# Nodeのメトリクスを取得
$ kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
foo-node 174m 2% 8604Mi 30%
bar-node 2917m 82% 16455Mi 57%
baz-node 352m 4% 9430Mi 33%
また、クライアントがHorizontalPodAutoscalerやVerticalPodAutoscalerの場合は、kube-apiserverを介して、拡張APIサーバーからNodeやPodのメトリクスを取得し、Podのオートスケーリングする。
▼ デバッグ¶
metrics-serverが正しく動作していない場合、Nodeのハードウェアリソースの消費量が<unknown>
になる。
$ kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
master-1 192m 2% 10874Mi 68%
node-1 582m 7% 9792Mi 61%
node-2 <unknown> <unknown> <unknown> <unknown>
pod¶
▼ podとは¶
Podのハードウェアリソースの消費量を取得する。
$ kubectl top pod -n foo-namespace
NAME CPU(cores) MEMORY(bytes)
foo-pod 5m 104Mi
▼ --containers¶
Podのコンテナに関して、ハードウェアリソースの消費量を取得する。
コンテナのKubernetesリソース使用量を足した値が、Pod内で使用するリソース消費量になる。
$ kubectl top pod --container -n foo-namespace
POD NAME CPU(cores) MEMORY(bytes)
foo-pod foo-container 1m 19Mi
foo-pod istio-proxy 5m 85Mi
▼ デバッグ¶
metrics-serverが正しく動作していない場合、Podのハードウェアリソースの消費量が<unknown>
になる。
$ kubectl top pod
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
foo-pod <unknown> <unknown> <unknown> <unknown>
03. Podの自動水平スケーリング/自動垂直スケーリング¶
HorizontalPodAutoscaler¶
▼ HorizontalPodAutoscalerとは¶
Deployment、StatefulSet、ReplicaSet、の単位でPodの自動水平スケーリングを実行する。
metrics-serverから取得したPodに関するメトリクス値とターゲット値を比較し、kubeletを介して、Podをスケールアウト/スケールインさせる。
設定されたターゲットを超過しているようであればスケールアウトし、反対に下回っていればスケールインする。
HorizontalPodAutoscalerを使用するためには、metrics-serverも別途インストールしておく必要がある。
▼ 最大Pod数の求め方¶
オートスケーリング時の現在のPod数は、次の計算式で算出される。
算出結果に基づいて、スケールアウト/スケールインが実行される。
(必要な最大Pod数)
= (現在のPod数) x (現在のPodのCPU平均使用率) ÷ (現在のPodのCPU使用率のターゲット値)
例えば、『現在のPod数 = 5
』『現在のPodのCPU平均使用率 = 90
』『現在のPodのCPU使用率のターゲット値 = 70
』だとすると、『必要な最大Pod数 = 7
』となる。
算出結果と比較して、現在のPod数不足しているため、スケールアウトが実行される。
▼ デバッグ¶
Deployment配下のPodで、.spec.containers[*]resources
キーに要求量を設定すると、HorizontalPodAutoscalerが要求量に対する使用量 (Target列) を取得できるようになる。
一方でこれを取得できていない場合、設定が無いか、metrics-serverが正しく動作していない可能性がある。
$ kubectl get hpa -A
NAMESPACE NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
foo foo-deployment Deployment/foo-deployment <unknown>/80% 1 1 1 391d
bar bar-deployment Deployment/bar-deployment <unknown>/80% 1 1 1 391d
baz baz-deployment Deployment/baz-deployment <unknown>/80% 1 1 1 391d
▼ レプリカ数との衝突¶
Deploymentのレプリカ数よりも、HorizontalPodAutoscalerが優先される。
そのため、もしDeploymentにレプリカ数が設定されていると、マニフェストをデプロイした場合に一度レプリカ数に戻される。
HorizontalPodAutoscalerを使用する場合、Deploymentのレプリカ数の設定を削除する。
▼ メトリクスでのPodの増減¶
メトリクス上では、既存のPodが削除されて、新しいPodが作成されていることを確認できる。
VerticalPodAutoscaler¶
▼ VerticalPodAutoscalerとは¶
Podの垂直スケーリングを実行する。
▼ Podの再作成のない垂直スケーリング¶
執筆時点 (2022/12/31) の仕様では、Podを垂直スケーリングする場合に、Podの再作成が必要になる。
これを解決するために、いくつかの方法が提案されている。
方法 | 説明 |
---|---|
マニフェストの新しい設定値の追加 | マニフェストに、垂直スケーリング時のルールに関する設定値 (例:.spec.containers[*].resources[*].resizePolicy キー) を追加する。 |
eBPFによるインプレース変更 | ハードウェアリソースの不足が検知された時に、eBPFを使用して、Podのマニフェストを変更するJSONPatch処理をフックする。 |