|
Prometheus を使用して Kubernetes クラスターを監視する場合、kube-state-metrics (KSM) は必須コンポーネントです。KSM は APIServer を監視し、リソースオブジェクトの状態メトリクスを生成します。個々の Kubernetes コンポーネントの健全性ではなく、デプロイメント、ノード、ポッド、イングレス、ジョブ、サービスなど、さまざまなリソースオブジェクトの健全性に焦点を当てています。各リソースオブジェクトには必要なメトリクスが含まれており、公式ドキュメント (https://github.com/kubernetes/kube-state-metrics/tree/main/docs) で確認できます。 KSMのインストールも非常に簡単です。コードリポジトリには対応するリソースマニフェストファイルが含まれています。ただし、インストールバージョンがKubernetesクラスターのバージョンと一致していることを確認してください。 ここでのテスト クラスターはバージョン 1.25 なので、まずそのブランチに切り替えます。 $ git clone https://github.com/kubernetes/kube-state-metrics && cd kube-state-metrics ` gitチェックアウトv2.7.0` $ kubectl apply -f例/標準 このメソッドは、デプロイメント メソッドを使用して KSM インスタンスをデプロイします。 $ kubectl get deploy -n kube -system kube -state -metrics 名前準備完了最新利用可能年齢 kube -状態-メトリクス1 / 1 1 1 2分49秒 $ kubectl get pods -n kube -system -l app.kubernetes.io / name = kube -state - metrics 名前準備完了ステータス再起動年齢 kube -状態-メトリクス- 548546f c89 - zgkx5 1/1実行中0 2 m51s 後は、Prometheus に KSM インスタンスを検出させるだけです。もちろん、検出方法は様々です。例えば、アノテーションを追加して自動的に検出したり、KSM 用のジョブを別途作成したりすることも可能です。Prometheus Operator を使用している場合は、ServiceMonitor オブジェクトを作成して KSM のメトリックデータを取得することもできます。 このアプローチは、データ量が限られている小規模なクラスターではうまく機能し、本番環境でKSMの高可用性が維持されている限り、通常のサービスを提供します。しかし、大規模クラスターでは非常に困難になります。例えば、私たちのクラスターは約8,000個のPodで構成されていますが、これはそれほど大規模ではありません。 しかし、単一のKSMインスタンスのみを使用してメトリクスを提供することは非常に困難です。多くの場合、メトリクスインターフェースのデータ量が多すぎるため、メトリクスが利用できない可能性があります。 たとえ時折取得できたとしても、`scrape_interval` ごとにこのメトリックインターフェースにアクセスするため、取得に時間がかかる可能性があります。1つのリクエストが完了する前に、次のリクエストが開始される可能性もあります。この問題を解決するには、KSM側で対処する必要があります。KSMの起動パラメータで、不要なメトリックタグを削除するフィルターを設定できます。 $ kube -state -metrics -h kube - state - metricsは、 Kubernetes APIサーバーをリッスンし、オブジェクトの状態に関するメトリックを生成するシンプルなサービスです。
使用法: kube -状態-メトリクス[フラグ] kube -状態-メトリック[コマンド]
使用可能なコマンド: 完了kube - state - metricsの完了スクリプトを生成します。 ヘルプ。コマンドに関するヘルプ。 versionバージョン情報を出力します。
フラグ: -- add_dir_header trueの場合、ログメッセージのヘッダーにファイルディレクトリを追加します -- alsologtostderr はファイルだけでなく標準エラーにもログを記録します( -logtostderr = trueの場合は効果がありません) -- apiserver stringマスターとして使用するapiserverのURL -- config string kube - state - metricsオプション設定ファイルへのパス --custom - resource - state - config文字列インラインカスタムリソース状態メトリック設定YAML (実験的) --custom - resource - state - config - file文字列カスタムリソース状態メトリック設定ファイルへのパス(実験的) -- custom - resource - state - onlyカスタムリソース状態メトリックのみを提供します(試験的) -- enable - gzip - encodingクライアントから'Accept-Encoding: gzip'ヘッダー経由で要求された場合のGzip応答。 -h , --helpヘルプテキストを印刷する -- host stringメトリックを公開するホスト。 (デフォルト: "::" ) -- kubeconfig文字列kubeconfigファイルへの絶対パス -- log_backtrace_at traceLocationログが行ファイルにヒットしたとき: N 、スタックトレースを出力します(既定値: 0 ) -- log_dir文字列空でない場合、このディレクトリにログファイルを書き込みます( -logtostderr = trueの場合は効果がありません) -- log_file文字列空でない場合は、このログファイルを使用します( -logtostderr = trueの場合は効果がありません) -- log_file_max_size uintログファイルの最大サイズを定義します( -logtostderr = trueの場合は無効です)。単位はメガバイトです。値が0の場合、最大ファイルサイズは無制限です(デフォルトは1800 ) 。 -- logtostderrファイルではなく標準エラーにログを記録します(デフォルトはtrue ) --metric - allowlist string公開するメトリックのカンマ区切りリスト。このリストは、正確なメトリック名と/または正規表現パターンで構成されます。ホワイトリストとブラックリストは相互に排他的です。 -- metric - annotations - allowlist stringリソース' labels 'メトリックで使用されるKubernetesアノテーションキーのコンマ区切りリスト。デフォルトでは、メトリックには名前と名前空間のみが含まれます。追加のアノテーションを含めるには、複数形のリソース名と、それらに許可する Kubernetes アノテーション キーのリストを指定します (例: ' = namespaces = [ kubernetes . io / team ,...], pods = [ kubernetes . io / team ],...) '。代わりに、リソースごとに 1 つの ' * ' を指定してアノテーションを許可することもできますが、パフォーマンスに重大な影響が生じます (例: ' = pods = [ * ] ')。 --metric - denylist string有効化しないメトリックのコンマ区切りリスト。このリストは、メトリック名と/または正規表現パターンで構成されます。ホワイトリストとブラックリストは相互に排他的です。 -- metric - labels - allowlist文字列 リソースのlabelsメトリックで使用される追加のKubernetesラベルキーのコンマ区切りリスト。デフォルトでは、メトリックには名前と名前空間ラベルのみが含まれます。追加するには、複数形のリソース名とそれらに許可する Kubernetes ラベルキーのリストを提供します (例: ' = namespaces = [ k8s - label - 1 、 k8s - label - n 、...]、 pods = [ app labels ]、...) '。代わりに、リソースごとに 1 つの ' * ' を指定して任意のラベルを許可できますが、パフォーマンスに重大な影響があります (例: ' = pods = [ * ] ')。また、アスタリスク (*) をキーとして提供することもできます。これはすべてのリソースに解決されます。つまり、 ' -- resources = deployments 、 pods ' と仮定すると、 ' =*= [ * ] ' は ' = deployments = [ * ]、 pods = [ * ] 'に解決されます。 -- metric - opt - in - list stringカンマ区切りのオプトインで、デフォルトでは有効になっていないメトリックのリスト。これはメトリックの許可リストと拒否リストに追加されます。 -- namespaces string有効にする名前空間のコンマ区切りリスト。デフォルトは" " -- namespaces - denylist string有効化しない名前空間のコンマ区切りリスト。namespacesとnamespaces - denylistの両方が設定されている場合は、 namespaces - denylistで除外されている名前空間のみが使用されます。 -- node string kube - state - metricsポッドを含むノードの名前。おそらく、 downward API経由で渡されるでしょう。これはデーモンセットのシャーディングに使用されます。spec.nodeName fieldSelectorをサポートするリソース(ポッドメトリクス)でのみ利用可能です。これは実験的なものです。 -- one_output trueの場合、ログをネイティブの重大度レベルにのみ書き込みます(それより低い重大度レベルにも書き込みません。 - logtostderr = trueの場合は効果がありません) --pod string kube - state - metricsコンテナを含むポッドの名前。設定する場合、 -- podと--pod - namespaceの両方が設定されている必要があります。多くの場合、これは下位API経由で渡されるはずです。これは自動検出シャーディングに使用されます。設定されている場合、静的に設定されたシャーディングよりも優先されます。これは実験的な機能であり、予告なく削除される可能性があります。 --pod - namespace string --podで指定されたポッドのネームスペース名。設定する場合、 --podと--pod - namespaceの両方が設定されていることが想定されます。多くの場合、これは下位API経由で渡されるはずです。これは自動検出シャーディングに使用されます。設定されている場合、静的に設定されたシャーディングよりも優先されます。これは実験的な機能であり、予告なく削除される可能性があります。 -- port intメトリックを公開するポート。 (デフォルト8080 ) -- resources string有効にするリソースのコンマ区切りリスト。デフォルトは「 certificatesigningrequests ,configmaps,cronjobs,daemonsets,deployments,endpoints,horizontalpodautoscalers , ingresses,jobs,leases,limitranges,mutatingwebhookconfigurations,namespaces,networkpolicies,nodes,persistentvolumeclaims,persistentvolumes,poddisruptionbudgets,pods,replicasets,replicationcontrollers,resourcequotas,secrets,services,statefulsets,storageclasses,validatingwebhookconfigurations,volumeattachments」です。 -- shard int32シャードの総数のうち、インスタンスのシャード名目値(インデックスはゼロ)です。(デフォルトは0 ) -- skip_headers trueの場合、ログメッセージ内のヘッダープレフィックスを回避します -- skip_log_headers trueの場合、ログファイルを開くときにヘッダーを回避します( -logtostderr = trueの場合は効果がありません) --stderrthreshold重大度がこのしきい値以上のログは、ファイルとstderrに書き込むときにstderrに送信されます( -logtostderr = trueまたは-alsologtostderr = falseの場合は効果がありません) (デフォルト2 ) -- telemetry - host string kube - state - metricsの自己メトリクスを公開するホスト。 (デフォルト: "::" ) -- telemetry - port int kube - state - metrics の自己メトリクスを公開するポート。 (デフォルト8081 ) -- tls - config文字列TLS設定ファイルへのパス -- total - shards intシャードの総数。シャードの総数が1に設定されている場合、シャーディングは無効になります。 (デフォルト: 1 ) --use - apiserver - cacheは、 etcdクォーラム読み取りの代わりにapiserverからのキャッシュされたリソースを使用して、 ListWatchリクエストにresourceVersinotallow = 0を設定します。 - v , -- vログレベルの詳細度のレベル番号 -- vmodule moduleSpecカンマ区切りのパターンリスト= Nファイルフィルタリングされたログの設定
コマンドの詳細については、 「 kube-state-metrics [command] --help」を使用してください。 `--metric-allowlist` または `--metric-denylist` パラメータを使用してメトリクスをフィルタリングできます。しかし、不要なメトリクスやタグをフィルタリングした後でも、メトリクスAPIデータが依然として非常に大きい場合はどうすればよいでしょうか? 実際、どれだけフィルタリングを適用しても、単一のリクエストでメトリクスインターフェースに到達するデータ量は常に膨大になることが想像できます。この時点で、メトリクスデータを分割するしか解決策はないのではないでしょうか?複数のKSMインスタンスをデプロイし、それぞれがインターフェースデータの一部を提供することで、負荷を軽減できます。これは一般的に水平シャーディングと呼ばれています。水平シャーディングのために、kube-state-metricsには既にいくつかの自動シャーディング機能が実装されており、以下のフラグを使用して設定します。 - --shard (0 から始まる)
- --合計シャード数
シャーディングは、Kubernetes オブジェクトの UID を MD5 ハッシュ化し、シャードの総数を法として計算することで実現されます。各シャードは、対応する kube-state-metrics インスタンスがオブジェクトを処理するかどうかを決定します。ただし、シャードを持つインスタンスも含め、すべての kube-state-metrics インスタンスは、割り当てられた部分だけでなく、すべてのオブジェクトのネットワークトラフィックとリソース消費を処理することに注意することが重要です。これを最適化するには、Kubernetes API がシャード化されたリスト/ウォッチ機能をサポートする必要があります。理想的には、各シャードのメモリ消費量は、シャード化されていない設定よりも 1/n 少なくなります。通常、kube-state-metrics がメトリクスを Prometheus に迅速に返すことができるように、メモリとレイテンシの最適化が必要です。kube-state-metrics と kube-apiserver 間のレイテンシを短縮する 1 つの方法は、KSM を `--use-apiserver-cache` フラグ付きで実行することです。このオプションはレイテンシを短縮するだけでなく、etcd の負荷も軽減するため、このパラメータを有効にすることをお勧めします。 シャーディングを使用する場合は、シャーディング設定が期待どおりであることを確認するために、シャーディング関連のメトリクスを監視することをお勧めします。アラートには、次の2つのアラートルールを使用できます。 -アラート: KubeStateMetricsShardingMismatch 注釈: 説明: kube - state - metricsポッドが異なる--total - shards構成で実行されているため、一部のKubernetesオブジェクトが複数回公開されるか、まったく公開されない可能性があります。 概要: kube - state - metricsシャーディングが正しく構成されていません。 式: | stdvar ( kube_state_metrics_total_shards {ジョブ= "kube-state-metrics" }) != 0 15メートル ラベル: 重大度:重大 -アラート: KubeStateMetricsShardsMissing 注釈: 説明: kube - state - metricsシャードが欠落しており、一部のKubernetesオブジェクトが公開されていません。 概要: kube - state - metricsシャードが見つかりません。 式: | 2 ^max ( kube_state_metrics_total_shards {ジョブ= "kube-state-metrics" }) - 1 - 合計( 2 ^ max by ( shard_ordinal ) ( kube_state_metrics_shard_ordinal {ジョブ= "kube-state-metrics" }) ) != 0 15メートル ラベル: 重大度:重大 シャードを手動で設定するとエラーが発生する可能性があるため、KSM は自動シャーディング機能も提供しています。StatefulSet を使用することで、KSM の複数のレプリカをデプロイできます。自動シャーディングにより、StatefulSet 内にデプロイされた各シャードはインスタンスの場所を検出できるため、シャードの自動設定に非常に役立ちます。したがって、自動シャーディングを有効にするには、StatefulSet を介して kube-state-metrics を実行し、`--pod` および `--pod-namespace` フラグを使用してポッド名と名前空間を kube-state-metrics プロセスに渡す必要があります。以下に例を示します。 apiバージョン:アプリ/ v1 種類:ステートフルセット メタデータ 名前: kube -状態-メトリック 名前空間: kube -システム 仕様: レプリカ: 10 セレクター: マッチラベル app.kubernetes.io / name : kube - state - metrics サービス名: kube -状態-メトリック テンプレート: メタデータ ラベル: app.kubernetes.io/component :エクスポーター app.kubernetes.io / name : kube - state - metrics app.kubernetes.io /バージョン: 2.8.0 仕様: automountServiceAccountToken : true コンテナ -引数: --pod = $ (ポッド名) - -- pod -名前空間= $ ( POD_NAMESPACE ) 環境: -名前: POD_NAME 値の開始値: フィールド参照: フィールドパス:メタデータ名 -名前: POD_NAMESPACE 値の開始値: フィールド参照: fieldPath :メタデータ.名前空間 イメージ: registry.k8s.io/kube-state-metrics/kube-state-metrics : v2.8.0 # …… このシャードのデプロイ方法は、シャードごとにデプロイメントを用意するのではなく、単一のKubernetesリソース(この場合は単一のStatefulSet)を通じてKSMシャードを管理したい場合に便利です。この利点は、多数のシャードをデプロイする場合に特に顕著です。 もちろん、自動シャーディングによるデプロイメント方法にも欠点はあります。主な欠点は、StatefulSetがサポートするローリングアップグレード戦略です。StatefulSetで管理する場合、ポッドは1つずつ置き換えられます。ポッドが終了すると、再作成されます。このアップグレード速度は遅く、各シャードで短時間のダウンタイムが発生する可能性があります。アップグレード中にPrometheusがクロールされると、kube-state-metricsによってエクスポートされた一部のメトリクスが失われる可能性があります。 自動シャーディング機能の例のリストは、examples/autosharding ディレクトリにあり、次のコマンドを使用して直接デプロイできます。 $ kubectl apply -k例/自動シャーディング 上記のコマンドは、StatefulSet を使用して 2 つの KSM インスタンスをデプロイします。 $ kubectl get pods -n kube -system -l app.kubernetes.io / name = kube -state - metrics 名前準備完了ステータス再起動年齢 kube -状態-メトリクス- 0 1 / 1実行中0 70 m kube -状態-メトリクス- 1 1 / 1実行中0 65分 任意の Pod のログを表示できます。 $ kubectlログ- f kube -状態-メトリクス- 1 - nkube -システム I0216 05 : 53 : 23.151163 1 wrapper.go : 78 ] kube - state - metricsを起動しています I0216 05 : 53 : 23.154495 1 server . go : 125 ] "デフォルトのリソースを使用しました" I0216 05 : 53 : 23.154923 1種類. go : 184 ] 「すべての名前空間を使用しています」 I0216 05 : 53 : 23.155556 1 server . go : 166 ] "Metric allow-denylisting" allowDenyStatus = "ブラックリストにあった以下のリストを除外します: " W0216 05 : 53 : 23.155792 1 client_config.go : 617 ] --kubeconfigも--masterも指定されていません。inClusterConfigを使用しています。これは動作しない可能性があります。 I0216 05 : 53 : 23.178553 1 server . go : 311 ] "サーバーとの通信をテストしました" I0216 05 : 53 : 23.241024 1 server . go : 316 ] "Kubernetesクラスターバージョンで実行" major = "1" minor = "25" gitVersinotallow = "v1.25.3" gitTreeState = "clean" gitCommit = "434bfd82814af038ad94d62ebe59b133fcb50506" platform = "linux/arm64" I0216 05 : 53 : 23.241169 1 server . go : 317 ] "サーバーとの通信に成功しました" I0216 05 : 53 : 23.245132 1 server . go : 263 ] "メトリクスサーバーを起動しました" metricsServerAddress = "[::]:8080" I0216 05 : 53 : 23.246148 1 metrics_handler . go : 103 ] "ポッドで自動シャーディングが有効になりました" pod = "kube-system/kube-state-metrics-1" I0216 05 : 53 : 23.246233 1 metrics_handler . go : 104 ] "シャーディング設定の自動検出" I0216 05 : 53 : 23.246267 1 server.go : 252 ] "kube-state-metricsセルフメトリクスサーバーを起動しました" telemetryAddress = " [::]:8081" I0216 05 : 53 : 23.253477 1サーバー. go : 69 ] levelinfomsgListening onaddress [::]: 8081 I0216 05 : 53 : 23.253477 1サーバー. go : 69 ] levelinfomsgListening onaddress [::]: 8080 I0216 05 : 53 : 23.253944 1サーバー. go : 69 ] levelinfomsgTLSが無効です. http2falseaddress [::]: 8080 I0216 05 : 53 : 23.254534 1サーバー. go : 69 ] levelinfomsgTLSが無効です. http2falseaddress [::]: 8081 I0216 05 : 53 : 23.297524 1 metrics_handler . go : 80 ] "このインスタンスのシャーディングを、合計シャード数のうちのシャードインデックス(ゼロインデックス)に設定しています" shard = 1 totalShards = 2 I0216 05 : 53 : 23.411710 1 builder.go : 257 ] 「アクティブリソース」 activeStoreNames = 「証明書署名リクエスト、構成マップ、cronジョブ、デーモンセット、デプロイメント、エンドポイント、水平ポッドオートスケーラー、イングレス、ジョブ、リース、制限範囲、変更ウェブフック構成、名前空間、ネットワークポリシー、ノード、永続ボリュームクレーム、永続ボリューム、ポッド中断予算、ポッド、レプリカセット、レプリケーションコントローラー、リソースクォータ、シークレット、サービス、ステートフルセット、ストレージクラス、検証ウェブフック構成、ボリュームアタッチメント」 「このインスタンスのシャーディングを、合計シャード数のうちシャードインデックス(ゼロインデックス)に設定しています」shard=1 totalShards=2 のようなログメッセージが表示されており、自動シャーディングが成功したことを示しています。シャーディングされたメトリックデータのサイズを取得し、シャーディング前のサイズと比較することができます。シャーディング後、メトリックデータが大幅に減少していることがわかります。単一インスタンスのメトリックデータが依然として大きすぎる場合は、StatefulSetのレプリカ数を増やすことができます。 さらに、`--node` と `--resource` を追加するだけで、各ノードのポッドメトリクスを個別にシャーディングすることもできます。この場合、以下のように DaemonSet を直接使用して KSM インスタンスを作成できます。 apiバージョン:アプリ/ v1 種類: DaemonSet 仕様: テンプレート: 仕様: コンテナ -イメージ: registry.k8s.io / kube - state - metrics / kube - state - metrics : IMAGE_TAG 名前: kube -状態-メトリック 引数: --resource =ポッド --ノード= $ (ノード名) 環境: -名前: NODE_NAME 値の開始値: フィールド参照: apiバージョン: v1 フィールドパス: spec.nodeName その他のメトリクスについては、`--resource` を使用して個別にデプロイメントを指定するか、シャーディングを引き続き使用できます。まとめると、大規模クラスタで kube-state-metrics を使用するには、大幅な最適化が必要です。 - 不要なメトリックとラベルを除外します。
- シャーディングによるKSMインスタンスのストレス軽減
- DaemonSet メソッドを使用して、個々のポッドのメトリックをデプロイできます。
もちろん、「自社のビジネスメトリクスも非常に大きい場合はどうするのか?」という疑問も生じるでしょう。その場合、ビジネス側で対応する必要があります。まず、そのような大きなメトリクスデータが正常かどうかを判断する必要があります。もしそれが要件であれば、シャーディングをサポートする方法を見つける必要があります。 |