こんにちは。技術開発室の小嶋です。
技術開発室運用技術開発チームが担当している hbdesk というプロダクトにおいて、GKE (Google Kubernetes Engine)クラスタのアップグレード通知を設定する機会がありましたので紹介します。
GKE (Google Kubernetes Engine)は、Google社のパブリッククラウドサービスであるGCP (Google Cloud Platform)上で提供されているKubernetesのマネージド・サービスです。
技術開発室運用技術開発チーム
運用技術開発チームは「いつかは避けては通れない重い課題」の解消を目指し、MSPサービス(※)に必要なシステム・ツールの開発・運用や自動化に取り組んでいるチームです。
※ 弊社が提供している監視一次対応サービスやマネージドサービスなどを総称してMSPサービスと呼んでいます。
現在は3名のチームメンバーで活動しており、そのうち2名は地方に在住しながらフルリモートで業務にあたっています。
少人数ではあるものの、目の前にある課題に対して優先度を考え、自分たちが「これがいい」と思う解決方法や利用する技術を議論しながら、課題の解消に向けて日々取り組んでいます。
自分たちで開発したプロダクトを自分たちの手で運用しており、フロントエンド・バックエンド・インフラなど技術の垣根なく様々な技術に触れるため、「何でもやってみたい」という志向のエンジニアにはとても楽しい環境だと感じています。
hbdesk
hbdeskは「MSPサービスのコミュニケーションの窓口となる」ことを目指して開発を進めている、お客さまと弊社担当者がやり取りを行うポータルサイトです。
技術スタックは下記のような構成となっており、GKE (Google Kubernetes Engine)上で運用を行っています。
フロントエンド | TypeScript(4.3.x) / React(16.x) |
バックエンド | Python(3.9.x) / Django(2.2 LTS) |
インフラ | Docker / GKE |
開発環境 | VSCode / devcontainer / docker-compose / GitLab(CI/CD) |
コミュニケーションツール | Slack |
GKEクラスタのアップグレード
現在、hbdeskのGKEクラスタはStandardクラスタを利用しており、定期的にコントロールプレーンとノードプールのアップグレードが必要となります。
GKEのドキュメントにある通り、リージョンクラスタ+複数ノードの構成をとり、適切なKubernetesのマニフェストを利用することで、サービスに影響を与えずにアップグレードをGKEにまかせる運用をとることができます。
hbdeskの運用においてもアップグレードはGKEにまかせる運用をとっていますが、万が一の場合でもすみやかに対処が行えるよう平日営業時間帯にアップグレードする運用をとりたかったため、メンテナンスウィンドウの設定を追加しています。
以上のような形式で、アップグレード作業はGKEにおまかせする運用がとれるようになりましたが、定期的にGCPコンソールへログインしてアップグレードの状況を確認するという心温まる運用タスク(ぐぬぬ)が残っている状況となっていました。
GKEクラスタのアップグレード結果をSlackへ通知したい
「GKEクラスタがアップグレードされたら結果をSlackへ通知する」というGKEの設定があれば完璧だったのですが、残念ながら現状ではサポートされていません。
しかしながら、クラスタ アップグレード通知の受信として、「GKEクラスタがアップグレードされたら結果をCloud Pub/Subへ連携する」という仕組みが用意されていたため、これを利用してGKEクラスタのアップグレード結果をSlackへ通知する仕組みを作りました。
GKEクラスタのアップグレード結果をSlackへ通知する仕組み
GKEのドキュメントのとおり進めることで、GKEクラスタのアップグレード結果をSlackへ通知する仕組みを作ることができます。
大まかな流れとしては、GKE -> Cloud Pub/Sub -> Cloud Functions -> Slackの順序でメッセージがハンドリングされ、アップグレード結果が通知されます。
hbdeskでは、下記のような流れで設定を行いました。
1. Slack Appsの作成
はじめに、Slackへ通知を行うため、Slack Appsを作成します。
Slackチャンネルへ書き込みを行うため、Scopesにchat:writeを設定し、Tokenを発行しました。
2. Cloud Pub/Subトピックの作成
次に、GKEからのアップグレード通知を受け取る、Cloud Pub/Subのトピックを作成します。
$ gcloud pubsub topics create projects//topics/<トピック>
3. Cloud Functionsの作成
続けて、golangでCloud Functionを作成します。
"cloud.google.com/go/pubsub"をインポートし、エントリポイントとなる関数の引数に指定することで、GKEクラスタのアップグレードのメッセージを受け取ることができます。
hbdeskでは、GKEクラスタのアップグレード前後のバージョン(currentVersion / targetVersion)を含めて通知を行いたかったため、JSON文字列の処理が必要でした。
gcloudコマンドでデプロイをする際に、Pub/Subのトピックとエントリポイント関数を指定します。
package function import ( ... "cloud.google.com/go/pubsub" ) func <エントリポイント関数>(ctx context.Context, m *pubsub.Message) error { // m に Pub/Subのメッセージが連携される // type Message struct { // ID string // Data []byte // Attributes map[string]string // ... // } // m.Attributes["payload"] は JSON形式の文字列なので、構造体にマッピングする type Payload struct { ResourceType string `json:"resourceType"` Operation string `json:"operation"` OperationStartTime string `json:"operationStartTime"` CurrentVersion string `json:"currentVersion"` TargetVersion string `json:"targetVersion"` } var p Payload if err := json.Unmarshal([]byte(m.Attributes["payload"]), &p); err != nil ... } // 通知メッセージを作成する ... // Slackへ通知する ... }
$ gcloud functions deploy \ <ファンクション> \ --trigger-topic <トピック> \ --entry-point <エントリポイント関数> ...
4. GKEクラスタアップグレード通知の有効化
最後に、Pub/Subのトピックを指定して、GKEクラスタのアップグレード通知を有効化すれば完了です。
通知をテストする際には、GCPコンソールのPub/Subからメッセージ(GKEのドキュメントに記載のあるJSONの形式)をパブリッシュすることでテストができます。
$ gcloud container clusters update--notification-config=pubsub=ENABLED,pubsub-topic=projects/ /topics/<トピック名>
最終的には、下記のような動作イメージとなります。
今後の取り組み
GKEクラスタのアップグレード通知の有効化でちょっとだけ楽をできるようになりましたが、課題の解消に集中するため、運用技術開発チームではさらに日々の開発や運用をより良いものにしていきたいと考えています。
次に取り組む改善の候補としては、TerraformによるIaC化やGKEクラスタのAutopilot化、Djangoの3.2(LTS)へのアップグレードなどが挙がっています。
開発も運用もやりたい、いろんな技術スタックを触りたい、エンジニアが利用するシステム・ツールを作りたい、というような方にはとても楽しい環境だと思うので、ぜひ一緒に仕事ができるとうれしいです。
詳細は、採用サイトや運用技術開発チームの募集ページをチェックしてみてください。