Groupの@_k_e_k_eと@micnncimです。移行は多くの利点をもたらしましたが、移行は簡単ではなくいくつかの懸念点がありました。本記事では、その移行の全体像とKleatについて紹介します。メルカリのSpinnaker本題に入る前に、メルカリでのSpinnakerの使い方を紹介します。Engine(GKE)クラスタにデプロイしています。Spinnakerは専用のGKEクラスタ上でホストされています。メルカリにおけるマイクロサービスのデプロイワークフローの概略図Spinnakerがメルカリに導入されたのは4年ほど前のことです。事業の成長に伴い、マイクロサービスアーキテクチャも成熟していました。この記事を書くにあたり、Spinnakerの使用状況を定量的に紹介するために改めてデータを集めてみました。データが示すように、Spinnakerはメルカリで最も使われているプロダクトの一つになりました。Spinnakerの管理・運用方法Spinnakerを導入当初からHalyardによって管理しています。HalyardとはSpinnakerの設定、インストール、アップデートのためのツールです。クラスタにデプロイしています。メルカリにおけるHalyardの概要Spinnakerの操作を行うにはVPN経由でSSH接続してログインする必要がありました。Spinnakerの設定を定期的にバックアップしていました。Halyardの問題4年近くこの方法で運用してきましたが、以下のような使い勝手の悪さがありました。Halyardは、Halyardインスタンス内にあるHalconfigという設定ファイルを設定することでSpinnakerを管理・デプロイします。この設定ファイルには、Spinnakerのバージョン、特定の機能のオンオフ、認証認可の設定などが含まれています。これをGitで管理しようとすると大変で、Spinnakerの設定情報を確認するためにインスタンスにログインして、変更の際にはHalyardからSpinnakerをデプロイしなければなりませんでした。認証機能を有効にすると、100以上のマイクロサービスの権限の設定を追加する必要があり、Halconfigを手動で更新しなければならず、IaCの恩恵を受けることができませんでした。そのため、インフラの変更を見直すのが大変で、Spinnakerはスノーフレークサーバーになっていました。Spinnakerの変更を行うには、HalyardインスタンスへのSSH接続が大きな障害でした。Ansible、Puppet、Chefなどを試してみましたが、次はこのPlaybook、マニフェストやレシピなどを管理しなければならず、数珠つなぎで管理しなければならないので断念しました。そのため、手作業によるタスクが多く発生していました。Deploymentsとしてデプロイされます。Halyardはkubectlをラップし、限られたAPIしか公開していないため、一部のコンポーネントの構成を変更することができませんでした。そもそも設定オプションが多いため、設定ファイルの管理が難しいです。Halconfigは、Spinnakerに関連するすべての設定の単一のエントリーポイントになるように設計されています。Halyardに設定を複数のファイルに分けてマージできる仕組みはありますが、基本的には全てを一つのHalconfigファイルに書き込まなければなりません。すべての設定をHalconfigに載せることができるため、必要のないフィールドが多く、Halconfigは巨大で管理が大変です。Halyardはメリットも多かったのですが、ここで紹介したようにデメリットもありました。当時はSpinnakerを簡単に導入して管理する方法は他にありませんでした※。そこにKleatが登場してきました。Kleatとは?KleatはSpinnakerの設定を管理するための軽量なツールで、Halyardの代替です。Kleat単体ではSpinnakerをデプロイしないので、Kubernetesの設定管理ツールであるKustomizeと併用することが多いことに注意してください。Halyard"を読んでみてください。簡単に説明すると、これまでHalyardで使っていたHalconfigをベースに、各コンポーネントの設定ファイルを出力して管理できるツールです。図3に示すように、Kleatを使って各コンポーネントの設定ファイルを作成し、Kustomizeを使ってKubernetesマニフェストとしてバンドルします。最後にkubectlでデプロイします。以下のようにしてマイグレーションは行いました。1.Spinnakerのマイクロサービスのデプロイメント構成をKubernetesマニフェストに移植するまず、既存のSpinnakerマイクロサービスのレプリカ数やメモリリソースなどの構成をKubernetesマニフェストに移植しました。Halyardでのデプロイ構成例は以下の通りです。例として、次のようなものがあります。1Giここでは各マイクロサービスのリソースを設定しているのですが、以下のようなKubernetesマニフェストへ移植しました。1GiSpinnakerマイクロサービスの公式Kubernetesマニフェストであるspinnaker/kustomization-baseをフォークして、それと上記のようなKubernetesマニフェストをバンドルしました。Secretとして管理することを目的としています。Bootは、アプリケーションプロパティで環境変数を解決することができます。Secretsとして定義し、それ以外はConfigMapとして定義しました。設定ファイルの必要な部分だけを環境変数に置き換えることで、ほとんどの設定ファイルをプレーンテキストとして管理できるようになりました。これによりGitHubなどGitホスティングサービスによるコードレビューが簡単に出来るようになりました。Halyardを使っていたときには出来なかったことです。以下はGitHubトークンを使ったHalconfigのサンプルです。Secretを作成してPodにマウントします。artifactsクレデンシャルと設定を明確に分離し、設定をより簡単に管理をすることができるようになりました。リリースをサポートするためのパッチの追加この部分が一番苦労しました。1.20)を完全にはサポートしていないので、以下のように設定してパッチを当てる必要があります。1.20を完全にはサポートしていないので、後ほど説明するパッチを当てる必要があります。移行したい場合は以下の手順に従ってください。プロバイダはSpinnakerの1.21リリースから完全にサポート対象外になっていましたが、メルカリにはまだいくつか使用しているアカウントが残っていました。それがブロッカーになってしまい、Spinnakerの新しいバージョンにアップグレードできていませんでした。パッチを当てることでKleatへマイグレーションを可能にしました。Kubernetesプロバイダの設定を設定します。各マイクロサービスの設定ファイルに以下のようなRedisの設定を追加しました。Kleatの生成物にパッチを当てるKleatの生成物にもパッチを当てる必要がありました。サポートしていないため、削除されてKleatの生成物は出力されるからです。そこで、以下のBashスクリプトによるパッチをcloudriver.yamlに適用しました。V1プロバイダを追加します。1.24を使用しているので、これらのパッチは不要になり、すでに削除されています。CLIコマンドを使ってSpinnakerを完全に削除しました。kubectlを使用して再デプロイし、フルリプレースを行いました。Kleatは何をもたらしたのか?マイグレーションのメリットは以下の通りです。FiatのCPUリソースリミットを上げるためのGitHubのプルリクエスト(PR)Spinnakerのすべてのコンポーネントの構成とデプロイを包括的にHalyardで管理するのではなく、それぞれのKubernetesマニフェストを独立して定義して適用できるようになりました。これにより、Kubernetesの構成をより柔軟に管理し、Spinnakerの各マイクロサービスの負荷に合わせてリソースを調整することができます。上の図5のように、例えばFiatのCPUリソース制限を上げたいときはFiatのKubernetesマニフェストを更新するだけでよくなりました。Code(IaC)のメリットを得ることができます。同時に、GitHubのによる設定変更のレビューが容易になり、運用が格段に楽になります。先ほどの図のように、PRを通じてSpinnakerを管理・更新することができます。オペレータは、Halconfigを更新するためにHalyardインスタンスにSSH接続して手作業をする必要がなくなりました。SpinnakerのCI/CDのフローHalyardのGCEインスタンスにSSH接続をして運用する必要がなくなり、他のマイクロサービスと同じように容易にSpinnakerをデプロイできるようになりました。Actions経由でSpinnakerをデプロイしているので、アップデートなども非常に簡単です。これはGitHubで設定ファイルを管理できるKleatのメリットの一つです。他のKubernetesマニフェストと同様に、viglesiasce/kube-lintなどを使ってKubernetesマニフェストをリントすることができるようになりました。Nativeアプリケーションを開発・運用するための強力なツールが用意されているので、それらを活用することによって、大きなコストをかけることなくSpinnakerの設定をより安全に変更することができるようになりました。Kleatの懸念点しかし、良いことばかりではなく、懸念点もあります。SecretやConfigMapの定義方法などコミュニティのKustomize-baseとの大きな違いがあるからです。そのため、アップストリームの変更に追従しなければならず、Spinnakerのアップグレード時の負荷が大きくなってしまいます。spinnaker/kustomize-baseではHalconfigで直接クレデンシャルを設定しています。Secretとして専用の別のシークレットを作成したいのでフォークしました。spinnaker/kustomize-baseを見てみて、設計・ユースケースに合わなければフォークするか、一から作り直す必要があります。Halconfigを変更した場合の影響範囲の想定が難しいKleatを使ってもHalyardを使っても、Spinnakerの設定を行うにはHalconfigファイルが唯一のエントリーポイントであることに変わりはありません。Kleatを使うとKubernetesのマニフェストが分散して定義されるので、管理するものが増えます。SecretをFiatやGateなどの環境変数に設定する必要があります。特定の機能を変更することによってSpinnakerの各コンポーネントにどのような影響があるのか知る必要があります。Halconfigを変更したときに考えることHalconfigで特定の機能を有効にした後に、Spinnakerの各マイクロサービスにクレデンシャルをマウントするのを忘れてしまうことがよくありました。コミュニティのkustomize-baseをベースにしていれば問題ないのですが、Halconfigでアップデートを行う際に注意が必要です。V1プロバイダのサポート外になってから長い時間が経ちました。デプロイ・管理を改善するツールとなる理由がわかった今、移行を検討するには良いタイミングではないかなと思います。RFCで説明されているようにHalyardは将来的には非推奨になるので、移行の準備をしておくべきです。継続的なデリバリーは、ソフトウェア開発において最も重要な要素の一つであり、競争力を測る上で最も重要な指標の一つです。今回の移行は一筋縄ではいきませんでしたが、Kleatを導入することでSpinnaker自体のデプロイ・管理コストが削減され、用途に応じてより柔軟にSpinnakerの各マイクロサービスを運用できるようになり、より安定した信頼性の高いプラットフォームを提供できるようになりました。改善できる余地はありますが、Kleatによってプラットフォームの品質は大きく向上しました。