GitOps とは
GitOpsという新たな潮流
ITインフラの管理は新しい問題ではありません。
ソフトウェア開発のライフサイクルはほとんどが自動化され、多くのソリューションが提供されています。
他方でITインフラ管理の大部分は手作業のままであり、依然として専門チームを必要としています。
しかし今、インフラは柔軟に拡張できることが求められています。
専門チームによる手作業が作業の大部分を占めたままでは、ビジネスからのITプラットフォームへの要望にいつまでも応えることができません。
つまり自動化によってインフラ管理を大きく改善することが必要に迫られています。
この中で今注目を集めているのが GitOps です。
GitOps は最近新たに現れた技術用語です。
これが多くのインフラチームが探し求めていた答えになるとも噂されています。
GitOps は本当にその期待に応えるソリューションとなるのでしょうか。
GitOps の中核はアプリケーション開発ですでに使用している技術を活用し、インフラ管理を自動化することです。
つまりバージョン管理やCI/CD、コンプライアンス、コラボレーションなど、既に多くのアプリケーション開発の現場で使われている DevOps のベストプラクティスをインフラの運用に適用拡大するフレームワークです。
GitOpsとInfrastructure as Code(IaC) はどう違うのか
ITインフラを運用を自動化すると聞くと Infrastructure as Code (IaC) といった言葉が思い浮かぶ人もいるでしょう。
では GitOps と IaC は同じことを指しているのでしょうか。
もしくは異なる、敵対する、どちらか一方のみを選ばないといけない、そんかな関係でしょうか。
そもそも Infrastructure as Code (IaC) とはなんでしょう。
今現在において IaC とは特定のワークフローではありません。
IaC はパターンです。
今日の IaC は、元々の意図がどうであれ、様々な意味を持っています。
そして様々な方法で実装されています。
その中で GitOps はクラウドネイティブ時代における IaC の規定スタイルであり、それをベースにして組み合わせたものです。
つまり GitOps は下記を提供します。
・オーケストレーション
・観測可能性
・宣言型Infrastructure as Code
・コンテナと不変的なインフラ
・DevOpsのベストプラクティス
例えばコンテナを Kubernetes 環境にデプロイするのに GitOps を用いると、
GitOps は毎回同じコンテナが、同じ設定で、同じ挙動を、確実に提供するようにデプロイします。
利用者が望む状態が確実にソースとして保持され、管理され、再現性が担保されます。
残念ながら一部の IaC ツールでは、そうではありません。
IaC ツールが利用者が望む状態を保持・管理し、再現性を担保することは IaC ツール利用者に任されている状況がよく見受けられます。
IaC の実装は様々で、例えば本当のソースが Git レポジトリとデータベースの間で別々に管理されていることもあれば、複数の Git レポジトリ間で繋がりが薄く、バラけてしまうこともあります。
例えば Puppet を用いて GitOps と同じように全体的なワークフローを提供しているITプラットフォーム管理チームが多く見受けられます。
確かにそのような環境でも、適切に構成すれば、変更がプッシュされると自動的に意図した環境の変更を実現することが可能です。
Puppet Masterを使って、インフラが定義されたものと異なる場合に警告を出すようにしているところもあります。
しかしこれらのツールが導入され始めた当初は、そのようにはされていないことが一般的でした。
IaC ツールはインフラを管理する方法を提供します。
しかし残念ながらクラウドネイティブスタック全体を管理するものではありません。
これに対して GitOps はプラットフォーム全体を管理することができます。
GitOps では IaC ツールを使って、インフラのアップデートを Git を用いて実現することができます。
例えば Terraform は GitOps との相性も悪くはありませんが、それでも人手による適切な管理が必要です。
その意味で GitOps は IaC ツールの伝統を継承する、新たなステップだとも言えるます。
また、ACMジャーナルに掲載されたこの記事(GitOps: A Path to More Self-service IT)のように、GitOps は IaC の延長線上にあると言う人もいます。
GitOpsはInfrastructure as Codeにとって、MicroservicesがSOAにとって、XPがアジャイルにとってのようなものだ。
Weaveworks CEO アレクシス・リチャードソン
コンバージェンス機構とは
GitOps では「実際の」システムを Git レポジトリ上の構成ファイルに記述されている理想的なシステムに近づけるプロセスをコンバージェンス (収斂) と呼びます。
逆に「実際の」システムと理想的なシステムが同期していない場合はディバージェンス(発散) と呼びます。
Gitを通じて設定が更新されると、Kubernetesのオーケストレーターはクラスタの状態が Git で更新された設定になるまで、クラスターに変更を適用し続けます。
このモデルはあらゆる Kubernetes リソースに対応しており、Kubernetes Custom Resource Definitions (CRD) を使って拡張することも可能です。
アップデートが発生すると、次のようになります。
1. クラスタの状態を把握し Git レポジトリと比較
2. コンバージェンスした時にはデプロイメント成功の通知を送信
3. ディバージェンス時にはアラートが送信され、設定されていればコンバージェンスが開始されます。
このコンバージェンス・メカニズムは Terraform の Diff アラートや WeaveCloud のDeployment Automator を介して伝えられます。
CIサーバを使用しクラスタ内のコンバージェンスをオーケストレーションすることは可能か
CIサーバはオーケストレーションツールではありません。
継続的に(差分がなくなるまで)進歩を試みるものが必要です。
CIは差分が発生すると失敗します。
人間のオペレーターとの組み合わせで、CIサーバーは強制的にコンバージェンスさせることはできますが、これには別の問題があります。
また何かが壊れると(壊れる可能性はあります)部分的で未知の状態になってしまい、修正するためには再起動が必要になるかもしれません。
CIツールに依存するのではなく、Kubernetes や Terraform のような専用のオーケストレーターを使ってコンバージェンスさせる方が簡単です。
使用しているCIツールを捨てるべきか
既に CI ツールを利用しているのであれば、メインラインへのマージやビルド、テストなどの開発をコントロールするためにCIサーバーを使い続けるべきです。
しかし CD を行うために CI サーバーを使うべきではありません。
GitOps パイプラインは、既存の CI/CD パイプラインを改良したものです。
Jenkins などの CI エンジンが更新のオーケストレーションを担当しますが、その後正しく完了せずに失敗することがあります。
CIは更新をトランクにマージして統合するために使用され、GitOpsではトランクの更新に基づくデプロイメントの内部管理をKubernetesやクラスタに依存しています。
私たちはこれをCDのプルモデルと呼んでいます。
なぜプッシュモデルに対してプルモデルのパイプラインが重要なのか?
現在利用できるほとんどのCI/CDツールは、プッシュモデルを用います。
プッシュベースのパイプラインとは、コードがCIシステムから始まり、一連のエンコードされたスクリプトを介してパスを継続し、Kubernetesクラスタに変更をプッシュします。
CIシステムをデプロイの基盤として使用したくない理由は、認証情報をクラスタの外部に公開する可能性があるからです。
CIスクリプトを保護することは可能ですが、クラスタの信頼ドメインの外で作業することになり、これは推奨できません。
プルパイプラインでは、Kubernetesオペレータがクラスタ内から新しいイメージをデプロイします。
1. オペレーターは新しいイメージがレジストリにプッシュされたことを認識
2. クラスタのコンバージェンスへと移行
3. 新しいイメージがレジストリから引き出される
4. マニフェストが自動的に更新
5. 新しいイメージがクラスタにデプロイされます。
リポジトリからイメージを引き出すパイプラインを使えば、クラスタの認証情報が本番環境の外に出ることはありません。
観測された状態とは
実際の状態が何であるかを言うことはできません。
私たちはそれを観測することしかできません。
これが diff の重要性の理由です。
可観測性は GitOps に不可欠な要素であり、ディバージェンスに警告を発し、「真実の源」と異なる場合には「実際の」システムをコンバージェンスさせます。
クラスタの更新が成功したかどうかを知る方法
Git でのトランザクショナルな更新が、クラスターでの正しい更新につながったかどうかを知りたい場合
・クラスタを観測し、Git にあるものと比較
・デプロイメントが間近に迫っている場合やコンバージェンスの場合は、成功したことを通知
・乖離している場合は、コンバージェンスのきっかけとなるアラートを出す
デベロッパー・エクスペリエンスの重要性
GitOpsは Kubernetesを使いやすくするという目標を共有する、新世代のワークフローとツールの一部です。
Gitのワークフローは運用と開発の両方に適用できるようになりました。
チームの開発者は皆、Gitに慣れ親しんでおり、プルリクエストを行うことができます。
さらに今では Git を使って Kubernetes へのアプリケーションのデプロイを加速し、簡素化できるようになりました。
Gitを使いたくない場合
多くの開発者はプル・リクエストを使って運用を変えたいと思っています。
しかしすべての開発者がGitを気に入っているわけではありません。
Gitに書き込むことで遅くなることもあります。
快適なUI/UXを持つ高度なGUIでGitにコミットを書き込むことができることを想像するのは至極当然のことです。
これらは例えば交通整理などに使われるかもしれません。
またGitの後ろに書き込むクラスタへのプレコミットも考えられます。
GitOpsアトミック・デプロイメントとは
すべての更新が適用されるか、あるいは何も適用されないアトミック・デプロイメントができたら、とても素敵ですよね。
Gitはトランザクション・システムですから、GitOpsを使ってKubernetesのデプロイメントにトランザクションの動作を提供することはできないでしょうか?
残念ながらこれは一般的には不可能です。
Kubernetesでは更新は必ずしもトランザクションではありません。
ここで、私たちが言えることは
1. Kubernetesは一連のアップデートを1つのグループとして適用
Kubernetesがコンバージェンスとディバージェンスを備えている為
2. Kubernetesはグループの更新成功を保証しない
例えば3つのアップデートグループの中で1つが失敗することがある
これはいわゆる「部分的な失敗」となる
3. Kubernetesは何が失敗したかを報告することができる
オーケストレーターは部分的な失敗から成功に向けて進めることができる
重要なのは効率:1日に100台のマシンを1000回も起動する必要はない
4. ロールバック状態、つまり前回のGitトランザクションの状態はログに記録される
5. 理想のトランザクション運用に近づくものです
少なくとも手作業でのアプローチやスクリプトよりも優れています。
設定データベースではなくGitを選ぶのか
・バージョン管理された望ましい状態のセットを Git で用意に管理できる
このセットは環境の履歴についてはトランク内で線形順序を形成し、異なる環境については部分的な順序を形成
・設定は、人間と機械が読めるテキストにすることができる
コードはイメージレポに格納
コンテナは不変的なインフラの一つ
・Gitには不変性と否認防止を提供する
特にトランザクション、ロールバック、監査のための取り返しのつかない、議論の余地のないログを保持する
またソーシャル・ログでもあり、開発者は文脈に応じた説明をすることが可能
・GitHubのようなGitレポ・マネージャーを使用すると、ピア・レビューもネイティブにサポートされる。
また単一または複数の承認ライフサイクルにより、変更のリスクを低減し、職務分離の義務を満たすことができます。
これらのことは、DBよりも優れています。
システム全体が意味するもの
GitOpsでは、環境はKubernetesだけではありません。
環境全体を管理するためには、同じ方法を使うべきです。
ベアメタルでない場合は、インフラを明示的に構築する。
アプリの設定、マシンの設定、ポリシールール、ルーティングルール、ダッシュボード、アラートなど、その他すべてを明示的に管理します。
Gitを使って、明示的な状態でホストの構成を管理します。
秘密の管理
レポジトリにアクセスできる人なら誰でもわかるように秘密を Git で管理すべきではありません。
組織で GitOps を採用するのなら、クラスタの秘密は HashiCorp の Vault や Bitnami の Sealed Secrets ようなもので管理すべきです。
Sealed-secretsは次のような問題を解決します。
・Secrets以外のすべてのKubernetesの設定をGitで管理可能
・Sealed Secrets は KubernetesのCustom Resource Definition ControllerでGitに機密情報(別名Secrets)を保存可能
GitOps におけるデータベースやその他のステートフル・アプリケーションとの連携
データベースや永続的なデータを持つサービスは、別の方法で処理する必要があります。
GitOps を使って変更を管理することはできますが、データベースのスキーマを他のコードと一緒に更新できるようにしなければなりません。
ローリングアップデート時のデータベースの扱い方については"How to Correctly Handle DB Schemas During Kubernetes Rollouts "を参照
この記事が気に入ったらサポートをしてみませんか?