Prometheus、Istio、Hpa、Keda、Karpenter をベースにした K8s アプリケーションとノードの弾力性の実装

Prometheus、Istio、Hpa、Keda、Karpenter をベースにした K8s アプリケーションとノードの弾力性の実装

導入

この記事では、Prometheus、Istio、HPA、Keda、Karpenter に基づいて自己スケーリング Kubernetes クラスターを作成する方法について説明します。まず、terraform を使用して EKS クラスターを起動します。次に、Prometheus から抽出したメトリックに基づいて自動的にスケーリングできる nginx サービスを開始します (メトリックは istio ingress コントローラーから取得されます)。ここでのスケーリング ツールは keda を使用します。

上記のロジックを実装すると、ビジネスで必要なところにお金をかけながら、1 秒あたり数百万件のリクエストを処理できるようになります (インスタンスが増えるとコストも増えます)。新しいリソースは必要なときに表示され、必要がなくなったら破棄されます。もちろん、実際の環境には制御できない要因が他にもありますが、ここでは無視します。

EKSクラスターを起動する

HashiCorp Terraform は、コードを使用して IT リソースを管理および保守できる IT インフラストラクチャ自動化オーケストレーション ツールです。仮想マシン、ストレージ アカウント、ネットワーク インターフェイスなどのクラウド リソースのトポロジを記述する構成ファイルにインフラストラクチャを書き込みます。 Terraform のコマンドライン インターフェース (CLI) は、AWS またはその他のサポートされているクラウドに構成ファイルをデプロイおよびバージョン管理するためのシンプルなメカニズムを提供します。

terraform を使用して、AWS に EKS クラスターを作成します。また、Helm を通じて IAM を設定し、Karpenter をインストールします。

 モジュール「eks」 {
ソース= "terraform-aws-modules/eks/aws"
バージョン= "<18"
クラスターバージョン= "1.21"
クラスター名= varクラスター名
vpc_id = モジュール 仮想PCID
サブネット= モジュール プライベートサブネット
enable_irsa = 有効
# Karpenter を起動する1 ノードだけが必要です
ワーカーグループ= [
{
インスタンスタイプ= "t3a.medium"
asg_max_size = 1
}
]
}
リソース"helm_release" "カーペンター" {
依存先= [ モジュール. エクkubeconfig ]
名前空間= "karpenter"
名前空間の作成= true
名前= "大工"
リポジトリ= "https://charts.karpenter.sh"
チャート= "大工"
バージョン= "v0.16.0"
セット{
名前= "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"
= モジュールiam_assumable_role_karpenterロール
}
セット{
名前= "クラスター名"
= varクラスター名
}
セット{
名前= "clusterEndpoint"
= モジュールエククラスターエンドポイント
}
}
データ"aws_iam_policy" "ssm_managed_instance" {
arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}
リソース"aws_iam_role_policy_attachment" "karpenter_ssm_policy" {
役割= モジュールエクワーカー_iam_ロール名
policy_arn = データaws_iam_policyssm_managed_instanceアーン
}
リソース"aws_iam_instance_profile" "karpenter" {
名前= "KarpenterNodeInstanceProfile-${var.cluster_name}"
役割= モジュールエクワーカー_iam_ロール名
}
モジュール"iam_assumable_role_karpenter" {
ソース= "terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-oidc"
バージョン= "4.7.0"
ロールの作成= true
role_name = "karpenter-controller-${var.cluster_name}"
provider_url = モジュールエククラスター_oidc_発行者_url
oidc_fully_qualified_subjects = [ "システム:サービスアカウント:karpenter:karpenter" ]
}
リソース"aws_iam_role_policy" "karpenter_controller" {
名前= "karpenter-policy-${var.cluster_name}"
役割= モジュールiam_assumable_role_karpenterロール名
ポリシー= jsonencode ({
バージョン= "2012-10-17"
ステートメント= [
{
アクション= [
「ec2:CreateLaunchTemplate」
「ec2:CreateFleet」
「ec2:RunInstances」
「ec2:タグの作成」
"iam:PassRole"
「ec2:インスタンスの終了」
「ec2:DescribeLaunchTemplates」
「ec2:インスタンスの説明」
「ec2:セキュリティグループの説明」
「ec2:サブネットの説明」
「ec2:インスタンスタイプの説明」
「ec2:インスタンスタイプ提供の説明」
「ec2:アベイラビリティゾーンの説明」
"ssm:GetParameter"
]
効果= 「許可」
リソース= "*"
},
]
})
}
プロバイダー「aws」 {
リージョン= "us-east-1"
}
変数"cluster_name" {
description = "クラスターの名前"
タイプ= 文字列
}
モジュール"vpc" {
ソース= "terraform-aws-modules/vpc/aws"
名前= varクラスター名
cidr = "10.0.0.0/16"
azs = [ "us-east-1a""us-east-1b""us-east-1c" ]
プライベートサブネット= [ "10.0.1.0/24"、"10.0.2.0/24"、"10.0.3.0/24 " ]
パブリックサブネット= [ "10.0.101.0/24"、"10.0.102.0/24"、"10.0.103.0/24 " ]
enable_nat_gateway = 有​​効
シングルNATゲートウェイ= true
one_nat_gateway_per_az = false
プライベートサブネットタグ= {
"kubernetes.io/cluster/${var.cluster_name}" = "所有"
}
}

ここで重要なのは、IAM ポリシーです。これにより、karpenter はメタデータを読み取り、必要なリソースを作成できるようになります。

 terraform プラン --var cluster_name="chris"
terraform を適用 --var クラスター名="chris"
aws eks update-kubeconfig --name クリス

すべてがうまく進んでいることを確認するには、kubectl コマンドを使用してクラスターの準備ができていることを確認します。

istioとprometheusを設定する

現在、空のクラスターを準備しています。まず、Prometheus をインストールする必要があります。 kubernetes に監視をインストールして管理するには、kube-prometheus-stack (https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack) prometheus Operator を使用します。これにより、CLI を介して Kubernetes CRD を使用してターゲットを構成し、スクレイピング エンドポイントを定義し、Prometheus サービスを制御することが可能になります。次に、helm を介して k8s に prometheus をインストールします。

helm を使用してインストールします。

 helm リポジトリにPrometheus を追加- コミュニティhttps://prometheus-community.github.io/helm-charts
helm リポジトリの更新
helm install prometheus prometheus - コミュニティ/ kube - prometheus - スタック- n モニタリング

数分後、Helm によって作成されたいくつかのステートフル セット、デプロイメント、およびデーモン セットが表示されます。 Prometheus CRD にアクセスすることで、Prometheus の構成を表示できます。

 kubectl get pods - n モニタリング
kubectl get Prometheus - n モニタリング

注意: Prometheus が関連するストレージ ボリュームで構成されていない場合、再起動するとインジケーター情報が失われます。

Prometheus は、k8s API、ノード、その他のコンポーネントからメトリックを取得できるようになりました。他のアプリケーション (istio など) からメトリックをインポートすることもできます。また、スケーリングできるように、istio サイドカーからメトリックを取得したいと考えています。

クラスターに istio をインストールし、web 名前空間から始まるすべてのポッドにサイドカーを挿入するように指示します。

 istioctl マニフェストのインストール

すべてが整ったら、ゲートウェイと仮想サービスが適用されます。次の構成は、単に istio に、ホスト名 chris.somecompany.com のトラフィックを nginx ポッドに送信するように指示するだけです。

 ---
apiバージョン: ネットワークイスティオio / v1alpha3
種類: ゲートウェイ
メタデータ:
名前: ゲートウェイ
名前空間: istio - システム
仕様:
セレクター:
アプリ: istio - ingressgateway
サーバー:
- ポート:
番号: 8080
名前: http
プロトコル: HTTP
ホスト:
- 「chris.somecompany.com」
---
apiバージョン: ネットワークイスティオio / v1alpha3
種類: 仮想サービス
メタデータ:
名前: nginx
名前空間: web
仕様:
ゲートウェイ:
- istio - システム/ ゲートウェイ
ホスト:
- 「chris.somecompany.com」
http://www.google.com/dp ...
- ルート:
- 行き先
ホスト: nginxウェブsvcクラスター地元

Web 名前空間を作成してラベルを付けます。

 kubectl 作成 ns ウェブ
kubectl ラベル名前空間デフォルト istio-injection=enabled --overwrite

nginx ポッドとサービスを作成します。

 kubectl -n web create deploy nginx --image=nginx --port 80
kubectl -n ウェブ公開デプロイ nginx --port 80

nginx ポッドが 2 つのコンテナで起動されていることがわかります。これらは、nginx および istio サイドカー コンテナーになります。

 kubectl -n web ポッドを取得します
名前準備完了ステータス再起動年齢
nginx - 6 c8b449b8f - wkvd6 2 / 2 実行中0 6

また、Prometheus に istio からメトリックをスクレイピングするように指示するためのサービス エントリとポッド モニターも定義します。もちろん、これらには好きなようにラベルを付けることができますが、ここではメトリック スクレイピング構成で定義されるものを示します。

 apiVersion : 監視中コレオスcom / v1
種類: PodMonitor
メタデータ:
名前: 特使- 統計- モニター
名前空間: istio - システム
ラベル:
監視: istio - プロキシ
リリースプロメテウス
仕様:
セレクター:
一致する表現:
- { キー: istio - prometheus - ignore演算子: DoesNotExist }
名前空間セレクタ:
いずれか:
ジョブラベル: 特使- 統計
ポッドメトリックエンドポイント:
- パス: / stats / prometheus
間隔: 15
再ラベル付け:
- アクション: 維持
ソースラベル: [ __meta_kubernetes_pod_container_name ]
正規表現: "istio-proxy"
- アクション: 維持
ソースラベル: [ __meta_kubernetes_pod_annotationpresent_prometheus_io_scrape ]
- ソースラベル: [ __address____meta_kubernetes_pod_annotation_prometheus_io_port ]
アクション: 置換
正規表現: ([ ^ :] + )( ? :: \d + ) ? ;( \d + )
交換$1$2
ターゲットラベル: __アドレス__
- アクション: ラベルドロップ
正規表現: "__meta_kubernetes_pod_label_(.+)"
- ソースラベル: [ __meta_kubernetes_namespace ]
アクション: 置換
ターゲットラベル: 名前空間
- ソースラベル: [ __meta_kubernetes_pod_name ]
アクション: 置換
ターゲットラベル: ポッド名
---
apiVersion : 監視中コレオスcom / v1
種類: ServiceMonitor
メタデータ:
名前: istio - コンポーネント- モニター
名前空間: istio - システム
ラベル:
監視: istio - コンポーネント
リリースプロメテウス
仕様:
ジョブラベル: istio
ターゲットラベル: [ アプリ]
セレクター:
一致する表現:
- { キー: istio演算子: In: [ パイロット]}
名前空間セレクタ:
いずれか:
エンドポイント:
- ポート: http - 監視
間隔: 15

イングレス ゲートウェイを介してトラフィックを送信すると、nginx データが戻ってくるはずです。これは、パケットが Ingress ゲートウェイから nginx コンテナに到達し、アクセス回数が増加していることを示しています。

 # フォアグラウンドトンネルを作成する
kubectl - n istio - システムポート- 転送svc / istio - ingressgateway 8080

http リクエストを送信します。

 curl - H 'ホスト: chris.somecompany.com' ローカルホスト: 8080 | grep -- - i タイトル
<title> nginx ようこそ! </title>

Prometheus に接続してターゲットを確認します。

 kubectl -n 監視ポート-forward svc / prometheus -operated 9090

有効なターゲットを持つ envoy-stats-monitor があり、prometheus が nginx コンテナとメトリック エンドポイントを探していることがわかります。これらのメトリックは、各ポッドで実行されている istio サイドカーから取得されます。


nginx ラベルを使用して istio_requests_total メトリックをクエリすると、カウントが返されます。

 um ( istio_requests_total { destination_app = "nginx" })

上記で返された結果は 8 です。これは、nginx コンテナが 8 回アクセスされたことを意味します。

これで istio と prometheus が設定されました。処理する必要がある他のメトリックがある場合は、いつでもこれを拡張できます。

kedaをインストールしてHPAを定義する

KEDA を使用すると、CPU やメモリなどの標準の組み込み Kubernetes メトリックだけでなく、メッセージ キューのキューの深さ、1 秒あたりのリクエスト数、スケジュールされた cron ジョブ、独自のアプリケーション ログからのカスタム メトリックなど、想像できるあらゆる高度なメトリックに基づいて、Kubernetes がポッド レプリカをゼロ以上にスケールできるようになります。これは、Kubernetes に組み込まれた HPA では簡単には実行できないことです。

helm 経由で keda をインストールします。このオープンソース ツールを Kubernetes に追加して、イベントに応答することができます (この記事では、Prometheus メトリックからイベントをトリガーするために使用されます)。

helm 経由で keda をインストールします。

 helm リポジトリkedacore を追加しますhttps://kedacore.github.io/charts
helm リポジトリの更新
kubectl 名前空間keda を作成します
helm でkeda をインストールしますkedacore / keda -- 名前空間keda

次に、Prometheus からの istio_requests_total メトリックを監視する ScaledObject CRD を定義します。メトリック数が 10 を超えると、ポッドのレプリカが増加します。

CRD の作成:

 ---
apiバージョン: keda.sh/v1alpha1
種類: スケールオブジェクト
メタデータ:
名前: nginx
名前空間: web
仕様:
スケールターゲット参照:
種類: デプロイメント
名前: nginx
最小レプリカ数: 1
最大レプリカ数: 10
クールダウン期間: 30
ポーリング間隔: 1
トリガー:
- タイプ: プロメテウス
メタデータ:
サーバーアドレス: http : //prometheus-operated.monitoring:9090
メトリック名: istio_requests_total_keda
クエリ: |
合計( istio_requests_total { destination_app = "nginx" })
しきい値: "10"

実際にポッドの数を変更する HPA も作成されます。

 kubectl - n web get hpa keda - hpa - nginx

トラフィックを生成します。

 curl - H 'ホスト: chris.somecompany.com' ローカルホスト: 8080 | grep -- - i タイトル
<title> nginx ようこそ! </title>

十分なトラフィックが生成されると、keda が HPA 上のレプリカの数を増やし、ポッドのレプリカが増えることがわかります。

Prometheus メトリックを監視することでポッドのレプリカを増やすだけです。

 # 新しいHPA 値kubectl get hpa - n web
名前参照ターゲットMINPODS MAXPODS レプリカ年齢
keda - hpa - nginx デプロイメント/ nginx 8667 m / 10 ( 平均) 1 10 3 11 m
kubectl get pods -n web
名前準備完了ステータス再起動年齢
nginx - 6 c8b449b8f - 7 mr4x 2 / 2 実行中0 3 分29秒
nginx - 6 c8b449b8f - lfmdv 0/2 PodInitializing 0
nginx - 6 c8b449b8f - wkvd6 2 / 2 実行中0 41

次のコマンドを実行すると、なぜこのようにスケーリングされるのかがわかります。

 kubectl はhpa keda を記述します- hpa - nginx - n web
正常成功再スケール6 m18s 水平ポッドオートスケーラー新しいサイズ: 3 ;
理由: 外部メトリックs0 - prometheus - istio_requests_total_keda ( & LabelSelector { MatchLabels : map [ string ] string { scaledobject . keda . sh / name : nginx ,}, MatchExpressions :[] LabelSelectorRequirement {},}) ターゲット以上

カーペンター

Karpenter は、Kubernetes 用に構築されたオープンソースの自動スケーリング プロジェクトです。コンピューティング リソースを手動でプロビジョニングしたり、過剰にプロビジョニングしたりすることなく、Kubernetes アプリケーションの可用性が向上します。 Karpenter は、スケジュール不可能なポッドの集約的なリソース要求を監視し、ノードの起動と終了に関する決定を行うことで、スケジュールの遅延を最小限に抑えるように設計されており、数分ではなく数秒でアプリケーションのニーズを満たす適切なコンピューティング リソースを提供します。

クラスターを起動したときに karpenter をインストールしましたが、構成しませんでした。 terraform を使用して定義した自動スケーリング グループ (ASG) を見ると、最大値が 1 になっているため、この時点では 1 つの ec2 インスタンスが実行されているはずです。

helm を使用して手動でインストールする場合は、次のコマンドを参照してください。

 Helm リポジトリにKarpenter を追加https://charts.karpenter.sh/
helm リポジトリの更新
helm アップグレード-- インストール-- 名前空間karpenter -- 作成- 名前空間\
大工大工/ 大工\
--バージョンv0.6.3 \
-- サービスアカウントを設定します注釈"eks\.amazonaws\.com/role-arn" = $ { KARPENTER_IAM_ROLE_ARN } \
-- clusterName = $ { CLUSTER_NAME } を設定します\
-- clusterEndpoint$ { CLUSTER_ENDPOINT } 設定します\
-- aws を設定しますdefaultInstanceProfile = KarpenterNodeInstanceProfile - $ { CLUSTER_NAME } \
--set logLevel = デバッグ\
--待ってください

HPA は負荷に基づいてポッドを追加しますが、ノードのスペースが不足した場合はどうなるでしょうか?ここで、カーペンターを使用する必要があります。

必要なサイズをいくつか定義し、ラベルを使用するように指示し、どのクラスターに適用するかを指定する必要があります。

 apiバージョン: karpenter.sh/v1alpha5
種類: プロビジョナー
メタデータ:
名前: デフォルト
仕様:
要件
- キーカーペンターsh / 容量- タイプ
演算子:
​​: [ "オンデマンド" ]
制限:
リソース
CPU : 1000
メモリ: 1000 Gi
プロバイダー:
サブネットセレクタ:
kubernetes .io / クラスター/ クリス: '*'
セキュリティグループセレクタ:
kubernetes .io / クラスター/ クリス: '*'
インスタンスプロファイル: chris2022090904481313660000000c
空になってからの経過時間: 30
有効期限までの秒数: 2592000

したがって、負荷の増加により多数の新しいポッドが追加された場合、karpenter は chris2022090904481313660000000c プロファイルを使用してさらに多くのノードを起動します。もちろん、さらにグループや設定を追加することもできますが、現在の構成で十分です。

トラフィックを生成し続けると、監視メトリックの数が増加し、レプリカをさらに追加する必要があることが HPA に通知されます。現時点ではスケジュールするのに十分なリソースがないため、ポッドは保留状態になります。

 kubectl ポッドを取得する| grep 保留
nginx - 6799f c88d8-2 rplf 0/1 保留中0 32
nginx - 6799f c88d8 - 8l n6v 0 / 1 保留中0 32
nginx - 6799f c88d8 - hhhgn 0 / 1 保留中0 32
nginx - 6799f c88d8 - mfh7v 0 / 1 保留中0 32
nginx - 6799f c88d8 - nmdtj 0 / 1 保留中0 32
nginx - 6799f c88d8 - rjnfx 0 / 1 保留中0 32
nginx - 6799f c88d8 - szgnd 0 / 1 保留中0 32
nginx - 6799f c88d8 - t9p6s 0/1 保留中0 32

ただし、新しいノードが起動すると、これらすべてが実行を開始します。

 nginx - 6799f c88d8 - cc8x5 1 / 1 実行中0 24 
nginx - 6799f c88d8 - cpzx6 1 / 1 実行中0 46
nginx - 6799f c88d8 - dlz4d 1 / 1 実行中0 24
nginx - 6799f c88d8 - gwdrh 1 / 1 実行中0 24
nginx - 6799f c88d8 - hg4s6 1 / 1 実行中0 24

レプリカをスケールダウンする場合、ノードも破棄されます。

まとめ

この記事では、Karpenter を使用してリソースに基づいて動的にノードを追加する Kubernetes クラスターを作成しました。 istio から Prometheus メトリックを表示することで、ポッドの数を制御できます。最終的に、コスト削減と効率向上の要件を満たしながら、高い弾力性と高負荷を実現する優れた自動スケーリング クラスターを作成しました。

<<:  ネットユーザーの質問に答えます: Promise オブジェクトを Await すると何が起こりますか?

>>:  クラウド上の OLAP エンジンのクエリ パフォーマンス評価フレームワーク: 設計と実装

推薦する

AI、5G、クラウドコンピューティングが2021年にエッジコンピューティングに与える影響

エッジ コンピューティングは今のところ有望ですが、まだ進化を続けています。 2021 年までに、生産...

無線ネットワーク向け将来の通信インフラの革新

テクノロジーが進歩するにつれ、より高速で信頼性の高いワイヤレス ネットワークの必要性が個人や企業にと...

SEO診断: ログからウェブサイトのデッドロックを見つける

数日前、友人とチャットをしていて、8月末のBaiduアルゴリズムのアップデートについて意見を交換しま...

オンデマンドで支払わない SaaS と不正な SaaS の違いは何ですか?

SaaS に関する記事を読んだり書いたり、何人かの SaaS 起業家と会って話をしたりしてきましたが...

ツール型ウェブサイトのエクスペリエンスデザイン——広告プラットフォームから始める

抄録: はじめに:私は2010年に入社して以来、2年半にわたり広告プラットフォーム部門のプロダクトデ...

Weiboのトピックを見てSEOの価値を分析する

昨晩Weiboをチェックしていたところ、興味深い話題が2つ見つかったので、返信し、ネットユーザーのコ...

#blackfriday# ipage - 25% オフ/無料ドメイン名/無制限のウェブサイトホスティング

11月20日から27日まで、ipageは感謝祭、ブラックフライデー、サイバーマンデーを含む1週間にわ...

ウェブサイトをより良く発展させたいなら、ユーザーエクスペリエンスに重点を置くべきです

どの業界のウェブマスターも、SEO最適化の重要性をよく知っています。これらの業界の中で、タオバオのS...

新しいハイブリッド クラウド アーキテクチャについてどれくらいご存知ですか?

クラウド時代の広範な進歩に伴い、クラウド時代の新しい概念が普及してきました。ハイブリッド クラウド ...

2018 年に推奨される安価なアメリカの VPS トップ 10

どの米国の VPS が優れていますか?米国で良い評価を得ている VPS プロバイダーはどれですか?初...

フォグコンピューティングについて知っておくべきことすべて

モノのインターネットの台頭により、これらのデバイスによって生成される膨大な量のデータをサポートできる...

百度製品「外部リンク終末」が静かに到来

世界はまだ終わっていないが、百度製品が引き起こした「外部リンク終末」は静かに到来した。外部リンクの時...

中小企業向け検索エンジンマーケティングソリューションの概要

2012年の独身の日におけるアリペイの取引額は191億元、2013年の独身の日におけるアリペイの取引...