Horizontal Pod AutoscalerのメトリクスにCloudWatchを使用する
KubernetesのHorizontal Pod Autoscaler(HPA)を使用することで、CPUやメモリの使用状況に応じてPodをスケールアウトすることができます。
また、HPAではカスタムメトリクスを使うことで、CPUやメモリ以外のメトリクスを活用できます。
AWSでは、CloudWatchのメトリクスが利用できるHPA向けのadapterを用意しています。
SQSのメッセージ数に応じてPodをスケールアウトすることができます。
AWSのブログでこのadapterに関する記事が公開されていたので、この内容に沿ってadapterを試してみました。
環境準備
adapterを利用するための環境を準備します。
EKSのクラスタを作る
eksctlを利用して、EKSでKubernetesの環境を作ります。
$ eksctl create cluster --node-type t3.small
EKSのNodeに権限を付与する
NodeからはCloudWatchやSQSにアクセスするため、IAMの設定が必要です。
eksctlで作成したNodeのIAMロールにAdministratorAccessというAWS管理ポリシーを付与します。
※デモ用に管理者権限のポリシーを付与していますが、実際には適切なポリシーを適用すべきです
adapterをデプロイする
CloudWatchのadapterをデプロイします。
$ kubectl apply -f https://raw.githubusercontent.com/awslabs/k8s-cloudwatch-adapter/master/deploy/adapter.yaml
これでHPAでCloudWatchのメトリクスを利用できるようになります。
動作確認をする
SQSを利用するサンプルアプリケーションをデプロイして、adapterの動作確認をします。
SQSをセットアップする
動作確認に利用するサンプルプログラムではhelloworld
というqueue名のSQSを利用しますので、このSQSのリソースを作成します。
$ aws sqs create-queue --queue-name helloworld
SQSからメッセージを受信するサンプルプログラムを実行する
定期的にSQSからメッセージを受信するサンプルプログラムをデプロイします。
$ kubectl apply -f https://raw.githubusercontent.com/awslabs/k8s-cloudwatch-adapter/master/samples/sqs/deploy/consumer-deployment.yaml
HPAをセットアップする
HPAで利用するメトリクスを定義します。
5分ごとにSQSのメッセージ数をカウントするメトリクスを設定しています。
$ kubectl apply -f https://raw.githubusercontent.com/awslabs/k8s-cloudwatch-adapter/master/samples/sqs/deploy/externalmetric.yaml
HPAを作成します。
SQSのメッセージ数が30個を超えるごとにメッセージを受信するPodをスケールアウトします。
$ kubectl apply -f https://raw.githubusercontent.com/awslabs/k8s-cloudwatch-adapter/master/samples/sqs/deploy/hpa.yaml
SQSにメッセージを送信するサンプルプログラムを実行する
SQSからメッセージを送信するサンプルプログラムをデプロイします。
一度に20000個のメッセージを送信します。
$ kubectl apply -f https://raw.githubusercontent.com/awslabs/k8s-cloudwatch-adapter/master/samples/sqs/deploy/producer-deployment.yaml
結果を確認する
5分ほど経過した後にHPAの状況を確認します。
$ kubectl get hpa sqs-consumer-scaler NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE sqs-consumer-scaler Deployment/sqs-consumer 16104/30 1 10 10 13m
Pod数が最大の10個まで増えています。
まとめ
KubernetesからCloudWatchのメトリクスを活用して、Podのスケールアウトができました。
今回のようにAWSのサービスとKubernetesを連携するための拡張機能の開発が進められています。
日々このような情報を収集していく必要がありそうです。
参考
サンプルプログラムの内容
client-goを使ってKubernetesのAPIに触れた
client-goとは
KubernetesのAPIを実行するためのgoのモジュールです。
Kubernetesの拡張にも使われてます。
ゼロから始めるKubernetes Controller / Under the Kubernetes Controller - Speaker Deck
これ以降は実際に使ってみた内容です。
筆者はgo初心者であるため初歩的なセットアップからつまずきながら進めました。
client-goを使ってみる
client-go/examples/out-of-cluster-client-configuration at master · kubernetes/client-go · GitHub
client-goのリポジトリに使用例があります。
Authenticating outside the clusterを動かしてみます。
client-goをインストールする
環境の前提としてmacOSを利用しています。
goをインストールします。
Downloads - The Go Programming Language
$GOPATHの配下に作業ディレクトリを配置する必要があるので以下のようにしました。
$ export GOPATH=$HOME/go $ pwd [Home Directory]/go/src/github.com/hi1280/out-of-cluster-client-configuration
client-goのインストールについてはこちらに書いてあります。
client-go/INSTALL.md at master · kubernetes/client-go · GitHub
goのversionが1.11以降からはgo modulesというモジュール管理の仕組みを使うことになったようなので、それに基づいてセットアップします。
Enabling go modulesの項にある通りに以下のコマンドを実行します。
$ export GO111MODULE=on $ go mod init
go.modというファイルが作成されます。
client-goをインストールします
$ go get k8s.io/client-go@master
コードを書く
使用例をほぼコピーしました。
podの数と該当のpodがあるかどうかを出力するプログラムです。
pod名は適宜自身の環境に合わせて変更する必要があります。
// Note: the example only works with the code within the same release/branch. package main import ( "flag" "fmt" "os" "path/filepath" "time" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/clientcmd" // // Uncomment to load all auth plugins _ "k8s.io/client-go/plugin/pkg/client/auth" // // Or uncomment to load specific auth plugins // _ "k8s.io/client-go/plugin/pkg/client/auth/azure" // _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" // _ "k8s.io/client-go/plugin/pkg/client/auth/oidc" // _ "k8s.io/client-go/plugin/pkg/client/auth/openstack" ) func main() { var kubeconfig *string if home := homeDir(); home != "" { kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file") } else { kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file") } flag.Parse() // use the current context in kubeconfig config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig) if err != nil { panic(err.Error()) } // create the clientset clientset, err := kubernetes.NewForConfig(config) if err != nil { panic(err.Error()) } for { pods, err := clientset.CoreV1().Pods("").List(metav1.ListOptions{}) if err != nil { panic(err.Error()) } fmt.Printf("There are %d pods in the cluster\n", len(pods.Items)) // Examples for error handling: // - Use helper functions like e.g. errors.IsNotFound() // - And/or cast to StatusError and use its properties like e.g. ErrStatus.Message namespace := "default" pod := "nginx-deployment-54f57cf6bf-j6sxf" _, err = clientset.CoreV1().Pods(namespace).Get(pod, metav1.GetOptions{}) if errors.IsNotFound(err) { fmt.Printf("Pod %s in namespace %s not found\n", pod, namespace) } else if statusError, isStatus := err.(*errors.StatusError); isStatus { fmt.Printf("Error getting pod %s in namespace %s: %v\n", pod, namespace, statusError.ErrStatus.Message) } else if err != nil { panic(err.Error()) } else { fmt.Printf("Found pod %s in namespace %s\n", pod, namespace) } time.Sleep(10 * time.Second) } } func homeDir() string { if h := os.Getenv("HOME"); h != "" { return h } return os.Getenv("USERPROFILE") // windows }
clientsetオブジェクトを生成することで、KubernetesのAPIを実行できることが分かります。
実行する
go buildして実行します。
$ go build -o app . $ ./app There are 9 pods in the cluster Pod nginx-deployment-54f57cf6bf-j6sxf in namespace default not found
応用して作ったもの
client-goを使ってkubernetes向けのCLIツールを作りました。
擬似的なpatchを適用することでdeploymentの更新を実行します。
image tagは変えたくないけど、imageを更新したいという場合の使用を想定しています。
と、作ってみたものの同様のものが公式のkubectlで既に実装済みでした。
やり方もほぼ一緒なので、kubectlのバージョンさえ上げれば、kubernetesクラスタのバージョンはあまり気にしなくて良さそうです。
まとめ
client-goを使うことで、KubernetesのAPIをプログラムから扱うことができました。
ただclient-goのドキュメントはあまりないので、APIのリファレンスを見ながら、それっぽいAPIを呼び出すというコーディングが必要になるかと思います。
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/
Kubernetes向けのツールはOSSになっているものが多いので、それらを参考にすると良いかもしれません。
JAWS-UGコンテナ支部 #16〜EKS on Fargateローンチ記念!EKS祭りだワッショイ 参加レポート
JAWS-UGコンテナ支部 #16〜EKS on Fargateローンチ記念!EKS祭りだワッショイの参加レポートです。
イベント名のとおり、AWSのサービスであるAmazon EKSやそのベースとなるKubernetesについての発表が数多く行われたイベントです。
自分は業務でEKSを運用しているので、業務に役立つことを知りたいと思い、参加しました。
参加した結果、EKS、Kubernetesの運用について色々見直したいという思いになりました。
自分が気になった内容を重点的に紹介・感想を書いていきます。
今こそ振り返るEKSの基礎
EKSの基礎とはeksctlが何をやっているかを知ることがメインの内容でした。
eksctlを使うといい感じに環境が作れるので、eksctl自体が何をやっているかを意識しなくなるというのはそのとおりで。
発表の中で、eksctlが何をやっているのかという解説の中では知らないことが多々ありました。
タグ付けとか、IAMロールの作成とか、VPCの作成などです。
これらの要素について、こと細かに解説が行われました。
今だとマネージド型のノードグループが作れるようになっていることも知りました。
発表を通して、自分が触り始めた時より、EKSはより便利になっていると感じました。
EKSを学ぶ上でEKSのアドベントカレンダーが役立つとのことです。
実践的な内容が多いとのことです。
EKSが半額になったことですし、AWSのコンソールからEKSの環境を作ってみようと思いました。
コンテナうまみつらみ〜Kubernetes初心者がEKSと格闘した1年を振り返る〜
2019年4月からEKSを使った開発を始めて、そこから得られた知見を紹介するという発表でした。
本番稼動後に求められる非機能要件を満たすための対策が実体験に基づいて、自分の環境も見直さなければと思わせる内容でした。
以下の内容が参考になりました。
- Podへのリソース割り当ては、Limitを設定せずに性能評価をした上で設定する
- カスタムメトリクスなどを使い、Pod自体をスケールアウトさせる工夫をすることで同時実行数を上げる
- Podの死活監視はsidecarが含まれることで難しくなる
自分の環境では、envoyを使うようなサービス間の連携といったものはないです。
ただマイクロサービス化が進むと今後必要になってくるものだと思うので、今回の話のようなツライ問題を知れて参考になりました。
Kubernetesをめぐる冒険
Kubernetesのバージョンが1.5の時から本番運用してきての運用の大変さとそれにどう対処してきたかの発表でした。
Kubernetesクラスタのアップデートなどにより、Kubernetesクラスタを作る機会が頻繁にあるので、その運用を改善するためのノウハウが紹介されました。
eksctl, variant, helm, helmfileを活用しつつ、ほぼ数回のコマンドで必要な管理系のサービスが入ったKubernetesクラスタを作れているとのことでした。
自分はまだKubernetesクラスタのアップデート作業を経験していないので、この発表内容を参考に対応したいと思いました。
自分の環境だと何回もkubectlやデプロイ用のコマンドを実行しないと環境が作れないという状態なので、賢く運用している実践例として参考になりました。
CI/CDについて、Flux + ArgoというGitOpsのための構成について紹介がありました。
自分もゆくゆくはGitOpsに対応していく必要があると思っていたので気になりました。
OSSから理解するEKSとそのエコシステムについて
Kubernetesのコントローラによる拡張によってAWSとKubernetesがどのように統合されているか様々な要素を紹介する発表でした。
AWSのKubernetes環境が様々なOSSで支えられていることを知り、このようなOSSを自分でも調べてみたいと思いました。
そのほかの発表
そのほか以下の発表がありました。
- EKS on Fargate を紹介したい
- IAM Role for Pods and Instance Meta Data Service - Speaker Deck
- Service Topology による効率的なロードバランシング #jawsug_ct / JAWS Container SIG 16th - Speaker Deck
- Linux経験ゼロからCKAD(Certified Kubernetes Application Developer)に合格するまで - Qiita
- EKS for EFS - Speaker Deck
どれも興味深い内容ばかりでした。
まとめ
個人的にEKS、Kubernetesの運用についての話はどれも興味深い内容で参考にしたいと思いました。
また、EKS、Kubernetesをもっとやっていかないとという気持ちになりました。
最後にイベントを開催してくれた運営の皆様ありがとうございました!