Kubernetes: Martian Kubernetes Kitの舞台裏の秘密を大公開(翻訳)
Kubernetesは、コンテナオーケストレーションで真っ先に挙げられる選択肢であり、コンテナ化アプリケーションのデプロイ、スケーリング、管理を自動化可能なフレームワークを提供します。ただし、クラスタのセットアップは簡単にはいかないこともあります。
そんなときは、ぜひMartian Kubernetes Kitをどうぞ!導入プロセスがシンプルになるので、背後のインフラストラクチャに煩わされずにアプリ開発に集中できるようになります。本記事を読んでMartian Kubernetes Kitのしくみを学びましょう。
- Kubernetesをスムーズに導入するEvil Martians特製Kubernetesツールキット(翻訳)
- Kubernetes: Martian Kubernetes Kitの舞台裏の秘密を大公開(翻訳) -- 本記事
シリーズの前回記事では、Martian Kubernetes Kitの高レベルな概要について説明しました。今回の記事からは技術的側面をより詳しく見ていくことにします。最初はインフラストラクチャについて解説し、今後の記事でデプロイします。
私たちがMartian Kubernetes Kitを設計した理由は、お客様の業務を簡素化し、Kubernetes利用時のトータルなエクスペリエンスを向上させ、組織を支えるインフラストラクチャに煩わされることなくアプリケーション開発に集中できるようにするためです。
このような「いつでもデプロイ可能なセットアップ」を作成するには、そこで使われているさまざまな技術を実際に用いた経験に基づいて、いくつもの意思決定を正しく下さなければなりません。
そこで本記事では、利用するツールやテンプレート、新しいクライアントのセットアップ、基本インフラストラクチャを2日以内に実行可能にする方法について詳しく議論してきた結果のそうした決定事項について、ほんの少し舞台裏を皆さんにお目にかけたいと思います。
決定事項1: Terragruntでインフラをコード化する
インフラストラクチャは、GKE(Google Kubernetes Engine)やAWSのEKS(Elastic Kubernetes Service)でクラスタを作成しておしまい、というわけにはいきません。そのクラスタを周囲のインフラストラクチャと結合するためのVPCやIPアドレスなどのコンポーネントも必要です。つまり、インフラストラクチャをリポジトリに保存したコンフィグとして記述することは避けられません。従来であればTerraformが頼りになるツールでしたが、私たちの場合は柔軟性とモジュール性をさらに高める必要があったので、Terragruntの採用が最初の決定事項となりました。
Terragruntは、Terraformの薄いラッパーとして振る舞い、「コードの再利用」「リモートのステート管理」「依存関係管理」「環境固有のコンフィグ」を追加することでワークフローを強化します。私たちがTerragruntで気に入っている点の1つは、Terragruntモジュールが独自のTerraformステートを持っていることです。つまり、インフラストラクチャである場所を変更したときに、別の場所が壊れる可能性が著しく下がるということです。
Terragruntの素晴らしい点は、新しい抽象化をほぼまったく追加しないことです。
Terragruntではこれまでどおり、慣れ親しんだHCL(HashiCorp Configuration Language)を利用することも、Terraform Registryから同じモジュールをインポートすることも可能です。もちろん、Terraformの場合と同様にプレーンな.tfファイルも利用できます。既にTerraformを利用しているのであれば、Terragruntを試してみることをおすすめします。Terragruntを使うと作業が大幅に楽になります。
決定事項2: TerraformはKubernetes内部とAPIに一切の責務を負ってはならない -> ArgoCDを採用
実行するクラスタが空っぽのままでよければ当然嬉しいですよね?しかしMartian Kubernetes Kitを支えているのは「包括的なソリューション」というアイデアなので、いずれ空のままではいられなくなります。
利用可能なプロジェクト環境を手に入れるには、何らかのツールを読み込む必要がありますが、どうすればいいでしょうか?すぐ思いつく方法は、TerragruntやTerraformを引き続き利用して、Kubernetesのあらゆる共通部分やコントローラ、Kubernetes内部の他のアプリケーションをTerragruntやTerraformでブートストラップする方法です。
しかし問題が1つあります。Terraformは自身のステートを保持していますが、それが変更されるのはTerraformコードを適用中のときだけです。しかしKubernetesは動的かつ流動的な環境であり、それらの状態を監視して、必要な変更に即座に対応するよう設計されています。
動的なKubernetes環境では、ステートの一貫性を維持しつつ最新に保つのは難しい作業になる可能性があります。インフラストラクチャのあらゆる変更はTerraformのステートファイルに正確に反映されなければならず、もし不一致が生じると、デプロイや更新の最中に重大な問題が発生する可能性があります。そういうわけで、問題解決のためのツールが別途必要になります。私たちの場合、それがArgo CDでした。
Argo CDをメインのGitOpsツールとして採用するという決定は、私たちにとって次の重要な決断でした(そして素晴らしい結果となりました)。
Argo CDは、「信頼できる唯一の情報源」としてGitを利用し、(プッシュではなく)プルベースの手法に依存しています。この手法はKubernetesの動的な性質と自然に調和するので、変更管理をよりシームレスかつ手軽に行えるようになります。
それまでの私たちは、Fluxという別のGitOpsツールをかなり長い間利用していましたが、機能の豊富さが決め手となって、ある時点からArgo CDに乗り換えました。Argo CDには、アプリケーションのステートやログを手軽に確認できる有用なGUIがあり、同期やロールバックを手動で実行したりノードの現在の負荷状況を確認したり、他にもさまざまな機能があります。
以下のように、インターネットからアプリケーションに流れ込むデータフローをグラフ表示することも可能です。
Argo CDは、「YAMLマニフェスト」「Kustomizeアプリケーション」、そしてもちろん「Helmチャート」のプレーンディレクトリを同期できます。Helmチャートの更新は、Helmチャートのバージョンを更新するだけで完了します(Argo CDがチャートをダウンロードして新旧の差分を表示し、自動適用するか、さもなければ承認待ち状態になります)。
Argo CDはさらに、アプリケーションのデプロイプロセスの管理に役立つツールも多数提供しています。詳しくは本シリーズの次回記事で解説します。
決定事項3: Argo CDをクラスタに導入するため、クラスタをブートストラップする
クラスタにArgo CDを初期インストールして、設定全体を読み込む方法をまだ解決していません。次の決定事項は、ここでどんな方法を選ぶかでした。
Argo CDには自分自身をブートストラップするツールがありません。しかも、GitHubリポジトリにアクセスしたり、通知を送信するのに使うトークンをセットアップしたりするために、secrets(秘密情報)などのリソースをセットアップしておく必要もあります。
最終的に、これらの作業はすべてシェルスクリプトで自動化することに決めました。今は2024年ですが、このスクリプトは1回適用すれば以後不要なので、慣れ親しんだ昔ながらの古いテクニックを存分に使って楽をしても大丈夫です。
このシェルスクリプトの目的は、以下のステップを実行することです。
- 既存のテンプレートから
argocd
ディレクトリを作成し、そこに顧客の情報を入力する - デプロイキーを生成してから、GitHub上で顧客のインフラストラクチャリポジトリに追加する
- Argo CD管理ユーザーと、アプリケーションのデプロイで使われるユーザーをそれぞれ追加する
- GitHub OAuthアプリケーションを作成する(GitHubアカウントでArgo CDとGrafanaにログインするのに使う)
- Slackチャンネルを作成する(アラート監視用)
- AlertmanagerとOpsGenieとのコネクションを設定する
- Argo CDをクラスタにデプロイする
このスクリプトを実行すると、cert-managerから監視スタックまで、あらゆる必要なコンポーネントをクラスタに追加する準備が整います。
ここまでできたら、クラスタ内部を詳しく調べていきましょう。最初は必要なコンポーネントを見ていきます。
決定事項4: クラスタに最初は何を置くべきか
Argo CDが、変更内容をリポジトリからクラスタに同期する作業を担当すること、そしてMartian Kubernetes Kitを使うとこのプロセスがとても簡単になることがわかりました。しかし、この同期でそもそも何をしようとしているのでしょうか?
繰り返しますが、空っぽのクラスタで満足する人はいないでしょう。顧客からの要望をアプリケーションに反映する作業を支援するツールがもっと必要ですし、それを監視するためにさらに多くのツールが必要です。他にも便利ツールを置けるなら、置いても損はないでしょう。
既にいくつかのコンポーネントについては述べましたので、中でも興味深いコンポーネントをいくつか詳しく見てみましょう。
- NGINX Ingress Controller
NGINXをリバースプロキシおよびロードバランサーとして利用し、Kubernetesクラスタ内で実行されるサービスへの外部アクセスを管理するコントローラです。受信トラフィックのエントリポイントを提供し、定義済みルールやコンフィグに基づいて、トラフィックを適切なサービスにルーティングします。
マーケットには他にもさまざまなIngressコントローラがありますが、NGINX Ingress Controllerは広く知られ、実証済みで、ドキュメントも充実しており、現在も優れたオプションです。 -
Cert-manager
これもKubernetesのコントローラの一種で、TLS証明書の管理やプロビジョニングを自動化するよう設計されています。Cert-managerはKubernetesのネイティブAPIと統合されており、Let's EncryptやVaultなどさまざまな機関から証明書を取得・更新・取り消しを手軽に行えるので、開発で非常に重宝します。 -
Prometheus、Grafana、Alertmanager
私たちの監視・アラートスタックを構成するために選び抜いたのがこの3つです。私たちはこれらのセットアップ経験を豊富に蓄積しています(現時点で7年以上)。この3つはメトリクスの監視やビジュアル表示にも最適で、Kubernetesクラスタ自身のみならず、クライアントアプリケーションにも利用できます。
何よりも、Prometheusは他の有名な監視サービスと比較してもかなりコスパが高く、現代のソフトウェアではメトリクスをPrometheusフォーマットで公開するのがほぼ当たり前になりつつあるほど、事実上の標準となっています。
さらに、私たちが強化したアラートルールのセットによって、Kubernetesクラスタで一般に用いられるさまざまな監視シナリオをカバーできます。 -
LokiとPromtail
この2つは、クラスタの隅々からログを収集・集約するログ機能スタックを構成しています。私たちの経験では、新しく立ち上げたインフラストラクチャのログ収集を支援するソリューションとして、多くの場合これが最適であることが示されています。このセットアップに上述の監視用スタックを併用することで、コスパの良い包括的なソリューションを提供できるようになります。Grafanaとネイティブ統合されているので、Grafanaの豊富なビジュアル表示機能を活用して、Lokiに保存されたログデータのクエリ・探索・ビジュアル表示が可能になります。 -
Sealed Secrets Controller
このツールは、GitOpsに適した形でsecretsの安全な保管と管理を行えるようにします。これにより、機密情報(APIトークン、パスワード、証明書など)を暗号化して、「シールド済み」secretsとしてGitHubリポジトリに保存できます。
このツールは、コアインフラストラクチャ向けのコンポーネントでは極めて便利ですが、クライアントアプリケーションでの利用にはあまり向いていません。
また、クラスタ操作中にいつでもオンにできる追加コンポーネントも豊富に揃っています。
- External-DNS
Kubernetesクラスタ内で実行されているサービスの、外部DNSレコードの管理を自動化するアドオンです。 -
External Secrets Operator
外部のsecretsストア(HashiCorp Vault、AWS Secrets Manager、Google Secret Managerなど、さまざまなsecrets管理システム)に保存されているsecretsを安全に管理できるようにするツールです。 -
Postgres Operator
Kubernetes環境で利用するPostgreSQLクラスタの管理、デプロイ、スケーリングを管理・自動化するように設計されています。これはアプリケーションのステージングやプレビューで利用するDBを起動するツールとして非常に貴重です。ただし、production環境内ではクラスタ上の PostgreSQLインスタンスを利用することはおすすめできません。そうした目的には、AWS AuroraかGCP Cloud SQLを検討してください。 -
VictoriaMetrics
オープンソースの時系列(time-series)データベースで、高速、スケーラブル、高コストパフォーマンスです。VictoriaMetricsは、Prometheusの長期保存用ストレージや、クラスタ内にPrometheusインスタンスが複数ある場合にきわめて有用です。 -
Prometheus Adapter
KubernetesのHPA(Horizontal Pod Autoscaling: 水平Pod自動スケーリング)やカスタムメトリクスAPIでPrometheusが収集したカスタムメトリクスを利用可能にするコンポーネントです。このアダプタは、PrometheusとKubernetes間のブリッジとして機能し、Prometheusメトリクスをアプリケーションのスケーリングや監視用に利用可能にします。
決定事項5: Martian Kubernetes Kitを作る
私たちがやりたかったのは、これまで述べてきた基本的なクラスタコンポーネント構成を私たちの顧客に速やかに提供することでした。しかし顧客側のコンフィグが時とともに進化すると、大量のカスタマイズが必要になってしまいます。さらに、Kubernetesも、それを取り巻く環境とコミュニティも爆速で進歩を繰り返しています。新しいAPIオブジェクトが導入されたかと思えば古いAPIオブジェクトが廃止されるという具合に、Kubernetesクラスタ上で使われるソフトウェア全般が絶え間なく進歩し続けています。
腕利きのDr.HOUSEの定番のセリフは「人間はいつの時代も変わらない」ですが、インフラストラクチャはその逆に、大変な勢いで変わり続けます。
たとえば、さまざまな変更点が長年降り積もったままの状態で、ある日バグが発見され、緊急で何かをアップデートしなければならなくなったとしましょう(例: 上述のNGINX Ingress Controllerを新バージョンに更新する)。
同時に、Kubernetesでは前述したように、どのソフトウェアも絶え間なく更新されているので、年に3〜4回のペースでインフラストラクチャを更新するのが理想です。
以上の点を考慮して、私たちには顧客のためのターンキーソリューションが必要であることを痛感しました。用途が広く、かつ上述の問題に直面したときにただちに対応できるソリューションが必要なのです。
この段階で、こんなアイデアが浮かびました。「私たちの全顧客が何らかの同じ「コア」リポジトリを参照するようにし、インフラの全基本設定をそこに保存しておいて簡単にアップデートできるようにしておき、顧客固有の変更は顧客のローカルリポジトリに置いておく、という方法はどうだろう?」
この問いかけこそ、私たちがMartian Kubernetes Kitを作ったきっかけとなったものです。Martian Kubernetes Kitのおかげで、多種多様なKubernetesクラスタ設定を楽に管理できるようになり、コンポーネントの追加や更新も迅速に行えるようになり、さまざまな顧客が運営している複数バージョンのアプリケーションを同時にサポートしたり、ステージングアプリやプレビューアプリを素早く自動作成したり、その他にも多くのことが可能になりました。
決定事項6: Martian Kubernetes Kitに何を含めるか
Martian Kubernetes Kitの中心にあるのは、多種多様なインフラストラクチャコンポーネントのバージョンや設定を記述する、複雑に分岐するHelmチャートです。
内容は以下のようにいくつかに分けられます。
base
:
すべてのクラスタで必要なコンポーネント(cert-manager
、prometheus
、grafana
、loki
など)。-
aws
またはgcp
:
選択したクラウドプロバイダ固有のコンポーネント(cluster-autoscaler
、stackdriver-exporter
など) -
addons
:
さまざまな状況で有用なオプションのコンポーネント(external-dns
、postgres-operator
、prometheus-adapter
など)
常に必要とは限らなくても、さまざまなインフラストラクチャで必要が生じることの多いものを選択した。
AWSとGCPに特化している理由は、私たちの顧客が最もよく利用しているクラウドプロバイダがこの2つであり、プラットフォームとして安定していることがわかってきたからです。
Martian Kubernetes Kitのコアリポジトリにあるbaseセクションをざっと見てみましょう。
私たちのコンフィグは、基本的に「コンポーネント」「そのバージョン」「デフォルト値」のリストでできていることがわかります。このように体系化された手法を採用したことで、管理や更新を実装するうえで非常に役立ちました。
決定事項7: コアリポジトリのバージョンを管理・参照する方法
- 管理
Martian Kubernetes Kitを支える堅固な構造について大まかに説明したので、「私たちが提供するものと常に一貫させるにはどうすればよいか」という次の問題に進みましょう。
私たちは、Martian Kubernetes Kitの個別の新バージョンをGitリポジトリで個別のブランチとすることを決定しました。バージョンをブランチと対応させる方法は、バージョンをタグと対応させる方法よりも、緊急で変更が必要になったときの対応に優れていることがわかってきたからです。各セクションの設定やチャートのバージョンに対する変更は、1個のブランチに集約します。
Martian Kubernetes Kitでリリースされる新バージョンと一般に最も関連が深い変更は、メインチャートのメジャーアップデートか、Kubernetesの新バージョンリリースです。
Martian Kubernetes Kitの最新バージョンのchangelogは以下のようになっています。
- 参照
中心となるコアリポジトリについて説明が終わったので、次は顧客側でMartian Kubernetes Kitがどのように動くかに注目してみましょう。
特定顧客のインフラストラクチャに対応する個別のArgo CDリポジトリは、Martian Kubernetes Kitのコンポーネントの特定のバージョンを指すだけです。Martian Kubernetes Kitがリリースされるとこれらのバージョンは修正され、以後変更されることはありません(重大なバグの場合を除く)。
ここで架空の顧客名"Kuvaq"と"Menetekel"で説明すると、"Kuvaq"と"Menetekel"が使っているMartians Kubernetes Kitのバージョンが同一であれば、それぞれのクラスタ内にある全コンポーネントが(NginxもGrafanaも何もかも)完全に同一バージョンになっていることを私たちが保証できるようになるのです。
もちろん、顧客のリポジトリにある設定は上書き可能ですが、上書きするのはその顧客にのみ関係ある全体設定(ドメイン名やGitHub Organization名など)のごく一部にとどまります。つまり、私たちは個別のプロジェクトを丸ごと更新することはありません。私たちがMartian Kubernetes Kitの新バージョンをリリースしたら、すべてのプロジェクトを1つずつ新バージョンに切り替えます。顧客側からは以下のように見えます。
この図から、顧客がコアリポジトリのさまざまなセクションを参照している様子や、addons
セクションのappEnabled
リストでオプションコンポーネントを有効にしている様子がわかります。また、base
ディレクトリの左側には、各コンポーネント用の顧客専用設定が保存されている様子もわかります。
インフラストラクチャの先にあるもの
本記事では、クラスタの作成方法と、インフラストラクチャのコンポーネントをクラスタに追加する方法について説明しました。
しかし本記事をお読みいただいている皆さんが、まだ説明されていない重要な詳細部分が残っていることに既にお気づきだと確信しています。つまり、私たちが最初にこの基礎工事を行ったときの対象であるクライアントアプリケーションについてまだ何も触れていないのです。
次回の記事では、デプロイプロセスの仕組みやsecrets、プレビューアプリケーションの作成方法など、アプリケーション寄りのその他の問題について取り上げる予定です。
私たちのSREサービスについて興味がおありの方は、Evil Martiansの各種SREサービス事例を自由にご覧いただけますので、ぜひお気軽にお問い合わせください。
私たちは、Kubernetesが現在の姿になる前からKubernetesを使い続けており、そこで培った経験を活かして、お客様のプロジェクトにKubernetesを採用する適切なタイミングについて決定を下すお手伝いに参上いたします。私たちはいつでも出動できるようスタンバイしておりますので、元記事のフォームにてご連絡をお待ちしております。
関連記事
The post Kubernetes: Martian Kubernetes Kitの舞台裏の秘密を大公開(翻訳) first appeared on TechRacho.
概要
元サイトの許諾を得て翻訳・公開いたします。
日本語タイトルは内容に即したものにしました。