率先して行動し、冷静さを保つ: Kubernetes クラスターの積極的な拡張

率先して行動し、冷静さを保つ: Kubernetes クラスターの積極的な拡張

クラスター リソースが不足している場合、Cluster Autoscaler は新しいノードをプロビジョニングし、クラスターに追加します。 Kubernetes を使用する場合、ノードを作成してクラスターに結合するプロセスに数分かかる場合があります。この間、これ以上の拡張は不可能であるため、アプリケーションは接続で圧倒されやすくなります

仮想マシンのプロビジョニングには数分かかる場合があり、その間はアプリケーションを拡張できない可能性があります。

このような長い待ち時間をなくすにはどうすればよいでしょうか?

プロアクティブなスケーリングまたは:

  1. クラスター オートスケーラーの仕組みを理解し、その効果を最大化します
  2. Kubernetes スケジューラを使用して、ノードに別の Pod を割り当てます。そして
  3. スケーリングを改善するためにワーカーノードを積極的に構成します

注: この記事のすべてのコードはLearnK8s GitHubに公開されています

Linode はこれらのソリューションをサポートできます。最近、Lincode が Akamai ソリューション ファミリーに加わりました。今Linodeに登録すると、100ドル相当の無料利用枠が付与され、Linodeクラウドプラットフォームが提供するさまざまなサービスを自由にご利用いただけます。詳細と登録はこちらをクリックしてください↓↓↓

Akamai Linode のクラウド コンピューティング サービスと機能について詳しくご覧ください

KubernetesでのCluster Autoscaler の仕組み

Cluster Autoscaler は自動スケーリングをトリガーするときに使用可能なメモリやCPUをチェックしませんが、イベントに反応して、スケジュールできないすべてのPodをチェックします。スケジューラがPod を収容できるノードを見つけられない場合、そのPod はスケジュール不可能であると言われます。

これをテストするために、次のようなクラスターを作成できます。

 bash $ linode-cli lke cluster-create \ --label learnk8s \ --region eu-west \ --k8s_version 1.23 \ --node_pools.count 1 \ --node_pools.type g6-standard-2 \ --node_pools.autoscaler.enabled enabled \ --node_pools.autoscaler.max 10 \ --node_pools.autoscaler.min 1 \ $ linode-cli lke kubeconfig-view "insert cluster id here" --text | tail +2 | base64 -d > kubeconfig

以下の詳細にご注意ください:

  1. 各ノードには 4GB のメモリと 2 つの vCPU があります (例: 「g6-standard-2」インスタンス)
  2. クラスターにはノードが1つだけあり
  3. クラスターオートスケーラーは1ノードから10ノードまでスケールするように構成されている

次のコマンドでインストールが成功したことを確認できます。

 bash $ kubectl get pods -A --kubecnotallow=kubeconfig

多くの場合、環境変数を含むkubeconfigファイルをエクスポートすると便利なので、次のように実行できます。

 bash $ export KUBECONFIG=${PWD}/kubeconfig $ kubectl get pods

アプリケーションをデプロイする

1GBのメモリと250m* の CPU を必要とするアプリケーションをデプロイしてみましょう

注: m =コアの容量の 1000 分の 1 なので、 250m = CPU容量の25%になります

 yaml apiVersion: apps/v1 kind: Deployment metadata: name: podinfo spec: replicas: 1 selector: matchLabels: app: podinfo template: metadata: labels: app: podinfo spec: containers: - name: podinfo image: stefanprodan/podinfo ports: - containerPort: 9898 resources: requests: memory: 1G cpu: 250m

次のコマンドを使用して、リソースをクラスターに送信します。

 bash $ kubectl apply -f podinfo.yaml

するとすぐに何かが発見されるでしょう。まず、3 つのPod がほぼ即座に実行を開始し、1 つのPod が保留中状態になります


その後すぐに

  1. 数分後、オートスケーラーは追加のポッドを作成し
  2. 4 番目のPod は新しいノードにデプロイされます

最後に、4番目のポッドが新しいノードにデプロイされます

4 番目のポッドが最初のノードにデプロイされないのはなぜですか?割り当てられたリソースを見てみましょう。

Kubernetesノードにおけるリソースの割り当て

Kubernetesクラスターにデプロイされたポッドは、メモリ、 CPU 、およびストレージ リソースを消費します。さらに、同じノード上で、オペレーティング システムとKubeletもメモリとCPUを消費します

Kubernetesワーカーノードでは、メモリとCPU は次のように分割されます。

  1. オペレーティング システムとシステム デーモン (SSH、Systemd など) を実行するために必要なリソース
  2. Kubelet、コンテナ ランタイム、ノード障害検出器などの Kubernetes エージェントを実行するために必要なリソース
  3. Pod で利用可能なリソース
  4. 削除しきい値用に予約されたリソース

Kubernetes ノードに割り当てられたリソースと予約されたリソース

クラスターがDaemonSet ( kube-proxyなど) を実行している場合、使用可能なメモリとCPUの量はさらに減少します。

したがって、すべてのポッドを同じノードに配置できるように要件を下げましょう

 yaml apiVersion: apps/v1 kind: Deployment metadata: name: podinfo spec: replicas: 4 selector: matchLabels: app: podinfo template: metadata: labels: app: podinfo spec: containers: - name: podinfo image: stefanprodan/podinfo ports: - containerPort: 9898 resources: requests: memory: 0.8G # <- lower memory cpu: 200m # <- lower CPU我们可以使用下列命令修改这个部署: bash $ kubectl apply -f podinfo.yaml

インスタンスの動作を最適化するために適切な量のCPUとメモリを選択することは、難しい作業です。 Learnk8s の計算ツールを使用すると、これをより迅速に行うことができます。

1 つの問題は解決しましたが、新しいノードを作成するのにかかる時間はどうでしょうか?

遅かれ早かれ 4 つ以上のレプリカが必要になりますが、新しいPodを作成する前に本当に数分間待つ必要がありますか?

一言で言えば:はい! Linode は、新しい仮想マシンを最初から作成して構成し、クラスターに接続する必要があります。このプロセスには 2 分以上かかることがよくあります。

しかし、代替手段があります。必要なときに、構成済みのノードを事前に作成することができます

たとえば、常に予備ノードを準備しておくようにAutoscalerを構成できます。 Pod がスタンバイ ノードにデプロイされるAutoscaler はプロアクティブに別のスタンバイ ノードを作成できます。 Autoscalerにはそのような機能は組み込まれていません、簡単に再作成できます。

ノードと同じ数のリソースを要求するポッドを作成できます

 yaml apiVersion: apps/v1 kind: Deployment metadata: name: overprovisioning spec: replicas: 1 selector: matchLabels: run: overprovisioning template: metadata: labels: run: overprovisioning spec: containers: - name: pause image: k8s.gcr.io/pause resources: requests: cpu: 900m memory: 3.8G

次のコマンドを使用して、リソースをクラスターに送信します。

 bash kubectl apply -f placeholder.yaml

このポッドはまったく何もしません。

プレースホルダーポッドを使用してノード上のすべてのリソースを保護する

このノードの役割は、ノードが完全に利用できるようにすることだけです。

次に、ワークロードを拡張する必要があるときに、このプレースホルダーPod をすぐにクリアできるようにする必要があります。このためにPriority Classを使用できます

 yaml apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: overprovisioning value: -1 globalDefault: false description: "Priority class used by overprovisioning." --- apiVersion: apps/v1 kind: Deployment metadata: name: overprovisioning spec: replicas: 1 selector: matchLabels: run: overprovisioning template: metadata: labels: run: overprovisioning spec: priorityClassName: overprovisioning # <-- containers: - name: pause image: k8s.gcr.io/pause resources: requests: cpu: 900m memory: 3.8G用下列命令将其提交至集群: bash kubectl apply -f placeholder.yaml

この時点で設定作業は完了です。

Autoscaler がノードを作成するまでしばらく待つ必要がある場合があります。その後、2 つのノードが作成されます。

  1. 4つのポッドを持つノード
  2. プレースホルダーポッドを含むノード

デプロイメントを5 つのレプリカに拡張するとどうなりますか?オートスケーラーが別の新しいノードを作成するまで待機しますか?

次のコマンドでテストします。

 bash kubectl scale deployment/podinfo --replicas=5

様子を見よう:

  1. 5 番目の Pod はすぐに作成され、10 秒以内に実行状態に変わります
  2. プレースホルダー Pod はクリアされ、5 番目の Pod のためのスペースが確保されます

プレースホルダーポッドは、通常のポッドのためのスペースを確保するためにクリアされます

それから

  1. クラスター オートスケーラーは保留中のプレースホルダーポッドを認識し、新しいノードをプロビジョニングします
  2. プレースホルダーPod は新しく作成されたノードにデプロイされます

保留中のポッドは、クラスタオートスケーラーをトリガーして新しいノードを作成します。

より多くのノードを持つことができるのに、なぜ積極的にノードを作成するのでしょうか?

プレースホルダーポッドを複数のレプリカに拡張することができ、各レプリカには標準のワークロードを受け入れる準備が整った事前構成済みのKubernetesノードが含まれます。ただし、これらのノードはアイドル状態ですが、それによって発生する料金はクラウド サービスの料金に含まれます。したがって、ノードを作成しすぎないように注意してください。

水平ポッドオートスケーラークラスターオートスケーラーの使用

このテクノロジーが何を意味するのかを理解するために、クラスター オートスケーラー水平ポッド オートスケーラー( HPA )を組み合わせることができます。 HPA を使用すると、デプロイメント内のレプリカの数を増やすことができます。

アプリケーションが受信するトラフィックが増えるにつれて、 Autoscaler でリクエストを処理するレプリカの数を調整できるようになります。ポッドが利用可能なリソースをすべて使い果たすクラスター オートスケーラーがトリガーされて新しいノードが作成され、 HPA が引き続きレプリカを作成できるようになります。

上記の効果をテストするために新しいクラスターを作成できます。

 bash $ linode-cli lke cluster-create \ --label learnk8s-hpa \ --region eu-west \ --k8s_version 1.23 \ --node_pools.count 1 \ --node_pools.type g6-standard-2 \ --node_pools.autoscaler.enabled enabled \ --node_pools.autoscaler.max 10 \ --node_pools.autoscaler.min 3 \ $ linode-cli lke kubeconfig-view "insert cluster id here" --text | tail +2 | base64 -d > kubeconfig-hpa

次のコマンドを使用して、インストール プロセスが成功したことを確認します。

 bash $ kubectl get pods -A --kubecnotallow=kubeconfig-hpa

環境変数を使用してkubeconfigファイルをエクスポートすると便利です。これを行うには、次のコマンドを実行します。

 bash $ export KUBECONFIG=${PWD}/kubeconfig-hpa $ kubectl get pods

次に、 Helmを使用してPrometheusをインストールし、このデプロイメントに関連するメトリックを表示します。 Helmの詳しいインストール方法は公式ウェブサイトで確認できます

 bash $ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts $ helm install prometheus prometheus-community/prometheus Kubernetes为HPA提供了一个控制器,借此可以动态增减副本数量。然

HPAにもいくつかの制限があります。

  1. 箱から出してすぐには使用できません。メトリックを集約して公開するには、Metrics Server をインストールする必要があります
  2. PromQL クエリはそのままでは動作しません

幸いなことに、 KEDAを使用できます。KEDA は、いくつかの便利な機能 ( Prometheusからのメトリックの読み取りを含む) によってHPAコントローラーの使用を拡張します KEDA は、次の 3 つのコンポーネントに適用できるオートスケーラーです

  1. スケーラー
  2. メトリックス アダプター
  3. コントローラ


KEDAアーキテクチャ

Helm経由でKEDAをインストールできます

 bash $ helm repo add kedacore https://kedacore.github.io/charts $ helm install keda kedacore/keda

PrometheusKEDAをインストールしたら、デプロイメントを作成しましょう。

この実験では、1 秒あたり一定数のリクエストを処理できるアプリケーションを使用します。各ポッドは1 秒あたり最大 10 件のリクエストを処理できます。 Pod が11 番目のリクエストを受信した場合、リクエストを一時停止し、後で処理します。

 yaml apiVersion: apps/v1 kind: Deployment metadata: name: podinfo spec: replicas: 4 selector: matchLabels: app: podinfo template: metadata: labels: app: podinfo annotations: prometheus.io/scrape: "true" spec: containers: - name: podinfo image: learnk8s/rate-limiter:1.0.0 imagePullPolicy: Always args: ["/app/index.js", "10"] ports: - containerPort: 8080 resources: requests: memory: 0.9G --- apiVersion: v1 kind: Service metadata: name: podinfo spec: ports: - port: 80 targetPort: 8080 selector: app: podinfo

次のコマンドを使用して、リソースをクラスターに送信します。

 bash $ kubectl apply -f rate-limiter.yaml

トラフィックを生成するには、 Locustを使用できます。次のYAML定義は、分散負荷テスト クラスターを作成します。

 yaml apiVersion: v1 kind: ConfigMap metadata: name: locust-script data: locustfile.py: |- from locust import HttpUser, task, between class QuickstartUser(HttpUser): @task def hello_world(self): self.client.get("/", headers={"Host": "example.com"}) --- apiVersion: apps/v1 kind: Deployment metadata: name: locust spec: selector: matchLabels: app: locust-primary template: metadata: labels: app: locust-primary spec: containers: - name: locust image: locustio/locust args: ["--master"] ports: - containerPort: 5557 name: comm - containerPort: 5558 name: comm-plus-1 - containerPort: 8089 name: web-ui volumeMounts: - mountPath: /home/locust name: locust-script volumes: - name: locust-script configMap: name: locust-script --- apiVersion: v1 kind: Service metadata: name: locust spec: ports: - port: 5557 name: communication - port: 5558 name: communication-plus-1 - port: 80 targetPort: 8089 name: web-ui selector: app: locust-primary type: LoadBalancer --- apiVersion: apps/v1 kind: DaemonSet metadata: name: locust spec: selector: matchLabels: app: locust-worker template: metadata: labels: app: locust-worker spec: containers: - name: locust image: locustio/locust args: ["--worker", "--master-host=locust"] volumeMounts: - mountPath: /home/locust name: locust-script volumes: - name: locust-script configMap: name: locust-script

次のコマンドを実行してクラスターに送信します。

 bash $ kubectl locust.yaml Locust会读取下列locustfile.py文件,该文件存储在一个ConfigMap中: py from locust import HttpUser, task, between class QuickstartUser(HttpUser): @task def hello_world(self): self.client.get("/")

このファイルは特別なことは何もせず、単にURLにリクエストを送信します Locustダッシュボードに接続するにはロードバランサーのIPアドレスを指定する必要があります。これを行うには、次のコマンドを使用してアドレスを取得します。

 bash $ kubectl get service locust -o jsnotallow='{.status.loadBalancer.ingress[0].ip}'

次にブラウザを開いてIPアドレスにアクセスします。

注意する必要がある問題が 1 つあります。それは、 Horizo​​ntal Pod Autoscalerです KEDA オートスケーラーは、 ScaledObjectと呼ばれる特別なオブジェクトを使用して水平オートスケーラーをカプセル化します

 yaml apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: podinfo spec: scaleTargetRef: kind: Deployment name: podinfo minReplicaCount: 1 maxReplicaCount: 30 cooldownPeriod: 30 pollingInterval: 1 triggers: - type: prometheus metadata: serverAddress: http://prometheus-server metricName: connections_active_keda query: | sum(increase(http_requests_total{app="podinfo"}[60s])) threshold: "480" # 8rps * 60s

KEDA はPrometheusによって収集されたメトリックに接続し、それをKubernetesに送信できます最後に、これらのメトリックを使用してHorizo​​ntal Pod Autoscaler (HPA)も作成します

次のコマンドを使用して、 HPA を手動で確認できます

 bash $ kubectl get hpa $ kubectl describe hpa keda-hpa-podinfo

次のコマンドを使用してオブジェクトを送信します。

 bash $ kubectl apply -f scaled-object.yaml

次に、拡張効果をテストできます。 Locustダッシュボード次の設定で実験を開始します。

  1. ユーザー数: 300
  2. 出現率: 0.4
  3. ホスト: http://podinfo


クラスターと水平ポッドオートスケーラーを組み合わせる

ご覧の通り、レプリカの数が増えました!

効果は良いのですが、気づいたかどうか分からない問題があります。

デプロイメントが8 つのポッドに拡張された後新しいノードに新しいポッドが作成されるまでに数分かかります。この間、現在の8 つのレプリカはそれぞれ10 件のリクエストしか処理できないため、1 秒あたりに処理されるリクエストの数は増加していません。

ボリュームを縮小して実験を繰り返してみましょう。

 bash kubectl scale deployment/podinfo --replicas=4 # or wait for the autoscaler to remove pods

今回、プレースホルダーPodを使用してオーバープロビジョニングを実装します

 yaml apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: overprovisioning value: -1 globalDefault: false description: "Priority class used by overprovisioning." --- apiVersion: apps/v1 kind: Deployment metadata: name: overprovisioning spec: replicas: 1 selector: matchLabels: run: overprovisioning template: metadata: labels: run: overprovisioning spec: priorityClassName: overprovisioning containers: - name: pause image: k8s.gcr.io/pause resources: requests: cpu: 900m memory: 3.9G

次のコマンドを実行してクラスターに送信します。

 bash kubectl apply -f placeholder.yaml

Locustダッシュボードを開き、次の設定で実験を繰り返します。

  1. ユーザー数: 300
  2. 出現率: 0.4
  3. ホスト: http://podinfo


クラスターと水平ポッドオートスケーラーをオーバープロビジョニングと組み合わせる

今回は、バックグラウンドで新しいノードが作成され、1 秒あたりのリクエスト数は停止せず、増減し続けます。素晴らしい!

要約する

この記事では、次の内容について説明します。

  1. クラスター オートスケーラーは CPU やメモリの使用状況を追跡しませんが、代わりに保留中のポッドを監視します
  2. 使用可能なメモリと CPU の合計量を持つ Pod を作成することで、Kubernetes ノードをプロアクティブに構成できます
  3. Kubernetes ノードは、Kubelet、オペレーティング システム、およびドレインしきい値用に特定のリソースを予約します
  4. Prometheus と KEDA を一緒に使用して、PromQL クエリを通じてポッドをスケーリングできます。

この記事の内容は大丈夫でしょうか?今すぐ Linode プラットフォームで試してみませんか?今すぐ登録すると、100 ドル相当の無料クレジットを獲得できることをお忘れなく。早速、この記事で紹介した機能やサービスを実際に体験してみましょう↓↓↓

Akamai Linode のクラウド コンピューティング サービスと機能について詳しくご覧ください

高可用性 MySQL/MariaDB リファレンス アーキテクチャと豊富なアプリケーション例について学ぶには、 Akamai Zhihu アカウントをフォローしてください


<<:  ハイブリッドクラウドにおけるDevOpsのベストプラクティス

>>:  マルチクラウド戦略の力を最大限に引き出すにはどうすればよいでしょうか?

推薦する

SEO は今でも役に立つのでしょうか?

SEO は今でも役に立ちますか? 最近、検索エンジン最適化が Baidu にどの程度影響を及ぼしてい...

SEOはキーワードを最適化するほど単純ではありません

SEO 業界では、SEO が検索エンジンのランキング技術であることを誰もが理解しています。ランキング...

香港でiPhone 6Sを購入する方法

香港でiPhone 6SやPS4ゲームを購入する価格は、中国本土よりはるかに安いです。64Gバージョ...

電子商取引ウェブサイトのロングテールキーワードのマイニングに関する経験の共有

業界の特殊性により、キーワードをマイニングする際、eコマースのウェブサイトはトラフィックを誘致するこ...

7日間で30万人の新規ユーザーを獲得した小規模チームは、どうやってWeiboで収益を上げたのでしょうか?

7日間で、単一のAPPアプリケーションはTencent Weibo Open Platformから毎...

moecloud: サンノゼ cn2 gia vps、新年20%オフ、月額47元、512Mメモリ/1コア/10g SSD/450gトラフィック/200M帯域幅

中国の商人であるMoecloudは、2008年にVPS事業を開始しました。現在は、米国西海岸サンノゼ...

早く来なさい! Amazon クラウド テクノロジー AI カンファレンス オープンソース スペシャル セッションが盛り上がりを見せる

人間の知能をシミュレートし、拡張し、拡大するにはどうすればいいのでしょうか?私: 人工知能!データか...

今年のトップ 10 ブランド ライブ ストリーミング マーケティング モデル!

ほとんどのブランドにとって、ライブストリーミングは定期的なマーケティング活動となっていますが、ブラン...

フォレスター、ガートナー、IDCが2022年の最もホットな4つのトレンドを予測

3 大調査コンサルティング組織である Forrester、Gartner、IDC は、毎年末にトレン...

cloudcone: $4/KVM/2g メモリ/2 コア/50g ハードディスク/2T トラフィック、フロントエンドの高防御に最適

Cloudcone は最新の 2 つのプロモーションを送信しました: ロサンゼルス、MC データ セ...

恵州市商務局が北京で「恵州と手を携えて湾岸へ出航」投資環境促進会議を成功裏に開催

11月26日午後、「恵州と手を携えて湾岸へ出航」恵州市投資環境促進会議が北京で開催された。プロモーシ...

袁福道は別の道を模索しているのだろうか?

最近、「元福道がダウンジャケットを作る」「元福道が新ブランドを立ち上げる」などのニュースがインターネ...

Weiboマーケティングの3つの戦略についてお話しします

ショートビデオ、セルフメディア、インフルエンサーのためのワンストップサービスWeibo はネットユー...

特別オファー: 250 元/鎮江テレコム/I3-4130/120gSSD/10M/8gDDOS 保護

HostCatは、中国のホストに関する情報をこれまで公開したことがありません。もちろん、例外もありま...

採用ウェブサイトは卒業生にサービスを提供するためにU-Mail電子メールマーケティングプラットフォームを使用しています

2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っています暑い7月は...