Kubernetesやクラウドネイティブをより便利に利用する技術やツールの概要、使い方を凝縮して紹介する連載。今回は、Kubernetesの利用を前提とした「Kubernetes Native」なCI/CDについて踏み込んで説明します。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
Kubernetesやクラウドネイティブをより便利に利用する技術やツールの概要、使い方を凝縮して紹介する本連載「Cloud Nativeチートシート」。今回紹介するのは、CI/CD(継続的インテグレーション/継続的デリバリー)です。中でもKubernetes(以下、k8s)の利用を前提とした「Kubernetes Native」なCI/CDについて踏み込んで説明します。
多種多様なCI/CDツールが存在する中、どういった軸で理解すればいいか分からない方もいることでしょう。以降、CI/CDに関する歴史と背景を踏まえ、CI/CDに具備すべき機能がどういったものかをツールの比較と動向も交えて解説します。
CI/CDの進化の歴史と背景を以下の4ステップで紹介します(図1)。CIとCD、アプリケーション(AP)層と基盤層に分けてCI/CDを理解していきましょう。
読者の皆さんは、今や当たり前になったCI/CDやDevOpsというキーワードをどのように捉えていらっしゃるでしょうか。「Jenkins」(Hudson)が出てきた当初、CIはコンパイルやテストが中心でしたが、デプロイの重要性が徐々に増してきました。すると、実態に合わせる形でCIではなく「CI/CD」というようになってきました。
内容 | コマンド | |
---|---|---|
CI | ・コンパイル ・テスト ・パッケージ |
「Apache Maven」によるコマンド例 ・mvn compile ・mvn test ・mvn package |
CD | ・デプロイ | CLIによるデプロイ例 ・ftp(ファイル配置) ・curl(「Apache Tomcat」へのデプロイ) |
また、この頃の特徴的な進化はパイプライン機能でしょう。パイプライン機能は、Aジョブ→Bジョブ→Cジョブのようなビルドやデプロイの一連の流れを定義する機能です。バッチ機能の開発に携わったことがある方なら、ジョブネットを想像してもいいでしょう。
パイプライン機能が登場する以前、CIが出始めのJenkins 1.xの頃は、JenkinsのMavenジョブを数珠つなぎで頑張ってつないできた時代がありました。パイプラインが普及し便利になったなと感じます。
オンプレミスの時代は、仮にCI/CDやDevOpsにより全自動化を目指そうとした場合に、以下のさまざまな層(レイヤー)を意識する必要がありました。
仮想化やクラウド化が進展し、これらAP/ミドルウェア/OSの設定はコンテナやクラウドリソースに代替されるようになりました。つまり、CI/CDツールが直接意識するのはコンテナやクラウドリソースに集約され、1段抽象化されたレイヤーでの管理が可能になります。
さらにはk8s、つまりコンテナオーケストレーションが出てくると、これらコンテナやクラウドリソースはk8sのマニフェストに代替されます。つまり、CI/CDツールが直接意識するのはマニフェストに集約され、さらに1段階抽象化されたレイヤーでの管理が可能になります。
もちろん、「全てがマニフェストによる管理になる」とまでは言い切れませんが、より抽象化、集約化されたレイヤーにおいてテキストベースで管理することが可能となります。また、IaC(Infrastructure as Code、システムリソースのコード化)の実現が容易となります。
DX(デジタルトランスフォーメーション)の時代においては、高頻度でのサービスのリリース要求が高まっています。下支えする技術として、クラウドやアジャイル、マイクロサービスといったものが挙げられます。アプリケーションの単位はモノリスの時代より小さくなり、より柔軟なリリースが可能となります。
具体的には、リリースの範囲が小さなマイクロサービスの範囲に限定され、昨今当たり前となってきているCI/CDにまつわるさまざまなベストプラクティスが適用しやすくなっています。
一方で、アプリケーションがサイロ化しやすくなり、個別のマイクロサービスの障害がシステム全体の障害につながったり、システム全体の動きが見えづらくなったりします。さらにはシステムの挙動が複雑化するので、品質確保のためのテストについてもこれまで以上の工夫が必要となります。
最近は「GitOps」という概念も出てきており、CD領域に「ソフトウェア開発の技法」が取り込まれてきています。
これまで、CIツールがビルドからデプロイまで一括して実施してきました(「CIOps」と呼びます)。一方で、GitOpsでは、デプロイをCDツールに任せ、CIツールはビルド部分に専念します。
k8sでGitOpsを実現する際のポイント、特徴として、下記4点が挙げられます。いずれもソフトウェア開発でよく使われる技法です。
なお、少し軸がずれますが「ChatOps」という、開発者のフロントにチャットツールを置くような考え方も出てきており、CI/CDやDevOpsの世界は極めて多様な進化を遂げています。
以降、上記4点について、それぞれ解説します。
・委譲
GitOpsでは、CDツールに処理を委譲するので、セキュリティ面と複雑性の回避の観点でメリットがあります。
まず、セキュリティ面です。CIOpsの世界では、Jenkinsや「CircleCI」など、1つのCIツールを利用して回帰試験〜ビルド〜デプロイまで行います。このように利用している方は多いのではないでしょうか。しかしながら、このようなCI/CDスタイルでは、CIツールに環境にデプロイ(k8sのAPIを実行)するための権限、クレデンシャルを設定する必要があり、セキュリティ面でのリスクが生じてしまいます。GitOpsでは、k8sクラスタ上にCDツールが配備されるので、クレデンシャルがクラスタ内で管理でき、セキュリティのリスクをなくすことができます。
次に、複雑性の回避です。CIOpsでは、さまざまな環境にデプロイが必要になってくると、CIツールの設定が複雑になり、メンテナンスが大変になると思います。GitOpsでは、さまざまな環境にデプロイが必要になっても、各環境内にあるCDツールに対して同一Gitリポジトリを監視するだけでいいので、複雑性も増加しにくくなります。
・宣言的プログラミング
k8sの最大の価値は、挙動の定義ではなく状態(ToBe)の定義が可能な点です。デプロイや障害からの復旧などを全て挙動として定義していたら、状態に応じた挙動の定義(if/elseのような分岐)が必要になり、設定が非常に複雑になります。
状態(ToBe)を「宣言的」にマニフェストファイルで定義することで、最終的にあるべき状態の定義に全集中できます。また、マニフェストファイルをそのままGitリポジトリで管理できるので、Gitとも高い親和性があります。
・Single Source of Truth(イベントリスナ)
自動構築されたサーバに対して個別に暫定対処し、その後、戻し忘れた経験はないでしょうか。いわゆる「Configuration Drift(構成の逸脱)」という状態です。この状態を避けるためには、構成をユーザーに勝手に変更させないImmutable Infrastructureを徹底することが重要です。
Immutable Infrastructureを実践するには、k8sのマニフェストをGitリポジトリで管理してGitリポジトリに保存されたマニフェストを「Single Source of Truth(唯一の信頼できる情報源)」とし、デプロイされた状態を常にGitリポジトリと同期させた状態に保ちます。
「ArgoCD」「Flux2」といったツールはSingle source of Truthやイベントリスナによるソースと環境の同期の思想がビルトインされており、ユーザーが意識せずにImmutable Infrastructureを実践できるようになっています
・DRY(Don't Repeat Yourself)
同じような定義をコピー&ペーストで複製して変更のたびに複製した設定ファイル全てに修正が入ると、生産性が下がるばかりか品質を保証するのが難しくなります。例えば、開発環境と商用環境のマニフェストファイルを別々に管理すると、一方のファイルを更新した際にもう一方のファイルに修正点を反映する必要があるなど、管理が煩雑になります。
DRYは、「同じ内容の記述は、共通化などによって、複数持たない」という思想で実践することにより、CI/CDをシンプルに保つことができます。
連載第2回で紹介した「Kustomize」などのツールはDRYの思想がビルトインされており、ユーザーが強く意識せずともDRYの恩恵を受けることができます。
前節の内容を踏まえ、代表的なツールを比較します(図4)。
まず、CI系のツールを紹介します。オープンソースソフトウェア(OSS)のツールとしてJenkinsや「Concourse CI」があります。k8sに特化したツールとして、「Tekton」「Jenkins X」といったツールもあります。
クラウドベンダーのマネージドサービスとしてAmazon Web Services(AWS)の「AWS CodePipeline」など「Code」シリーズ、Microsoft Azureの「Azure Pipelines」、Google Cloud Platform(GCP)の「Google Cloud Build」といったツールがあります。
SaaS型のツールとして、CircleCIや「Travis CI」があります。Gitを中核に置いた「GitLab」(GitLab CI/CD)や「GitHub」(GitHub Actions)といったツールもあります。CDに特化したツールとして「Spinnaker」、ArgoCD、Flux2があります。
CNCFの調査レポートを基に、ツールの利用状況を把握しましょう。執筆時点での最新のレポートは2020年11月のレポート(PDF)だったので、こちらを引用します(図5)。
CIツールで利用上位となっているのは、Jenkinsで53%、GitLab CI/CDで36%、GitHub Actionsで20%です。CI/CDツールの元祖Jenkinsは、クラウドネイティブのCI/CDのツールとしても多くのユーザーに利用されていることが分かります。
また、開発では「Git」を利用することが一般的になってきましたが、GitのリポジトリサービスにCI/CDが統合されたツールも、すぐに始められて利用しやすいことから、人気が高まっています。
CDツールではArgoCDが非常に多く利用されていることが分かります。
なお本連載では、次回以降、CIツールとしてGitリポジトリが機能として統合され、マージリクエスト(プルリクエスト)をトリガーとしたCIを簡単に実践でき、DevSecOpsにおけるイメージスキャンなどのサードパーティーとの連携スクリプトの情報も多いGitLab CI/CDを取り上げます。また、CDツールとしてArgoCDを取り上げます。
これまでCI/CDツールについて説明しましたが、ここからは、これらのツールを使って「どのようにCI/CDフローを組むといいのか」を考察します。クラウドネイティブのベースとなるコンテナのプラクティス、ブランチ戦略を鑑みて「どのようにCI/CDフローを組み立てるか」を、順を追って見ていきます。
コンテナアプリケーションも同様に、Gitリポジトリ(アプリケーションコード)をSingle Source of Truthとした状態に保つことが望ましいでしょう。すなわち、Gitリポジトリの特定のバージョンに対応するコンテナイメージは1つであり、devやprd環境へのデプロイも同一のコンテナイメージをプロモーションするようなCI/CDフローとすることが望ましいでしょう。
同一のコンテナイメージかどうかは、イメージのdigest値が同一かどうかで検証できます。
また、他にも下記のようなプラクティスを検討するといいでしょう。
Gitを利用するケースでは、Git Flow、GitHub Flow、GitLab Flowのいずれかを採用するケースがほとんどだと思います。本記事では詳細な比較は省略しますが、大まかにはそれぞれ下記のようなケースで採用されます。
フロー | ユースケース |
---|---|
Git Flow | 複雑なアプリケーションコードの管理が必要で、ある程度の期間をかけてリリースするようなケース |
GitHub Flow | Git Flowよりシンプル化されて1日に複数回デプロイするようなアプリケーションを開発するケース |
GitLab Flow | 環境ごとにアプリケーションコードを分離する複雑な管理が必要なケース |
上述したGitOpsのコンセプトを採用すると、CIとCDが分離され、Gitリポジトリにおけるアプリケーションコードのライフサイクルと環境へのデプロイのライフサイクルが異なることにもなります。そのため、アプリケーションコードとデプロイマニフェスト(例えば、k8sの「deployment.yaml」など)は別のGitリポジトリで管理すると、ライフサイクル管理をシンプルに保つことができるでしょう。環境情報についても、k8sの「ConfigMap」「Secret」リソースを利用できるので、アプリケーションコードのリポジトリから環境情報を排除できます。
マイクロサービスのようなアプリケーションを開発するケースにおいて、アプリケーションを管理するGitリポジトリではマイクロサービスのデプロイ容易性を確保しやすいGitHub Flowを採用することをお勧めします。アプリケーションのバージョン管理はタグを利用するといいでしょう。
また、デプロイマニフェストを管理するGitリポジトリでは、連載第2回で紹介したKustomizeを利用すると環境差異を管理しやすくなります。Kustomizeのようなツールを利用するケースでは、ブランチごとに環境情報の管理を分けず、パッチファイルで管理するのでGitLab Flowのように環境ブランチは不要となります。こちらもGitHub Flowを採用するといいでしょう。
ブランチ戦略なども踏まえてCI/CDフローを考察します。まず、CIフロー、CDフローを詳しく説明した後に、CI/CD全体を俯瞰(ふかん)したフローを説明します。
CIツールで実行するパイプラインでは、品質を検証するためのタスクやコンテナイメージ作成のタスクを実施することが求められます。CIパイプラインにおける代表的なタスクとして、下記のようなものが挙げられます。
Gitでの(GitHub Flow)開発ワークフローの各ポイント(プル/マージリクエストやmasterマージなど)でCIを実施することで、常に品質が保っていることを確認できるようにしておくといいでしょう。また、コンテナビルドの際はイメージタグにはGitのブランチやタグ、またはコミットハッシュ値を付与すると、Gitリポジトリの特定時点の状態をコンテナイメージと一致させることで管理しやすくできるでしょう。
CIの導入イメージを見ていきましょう(図7)。
続いてGitOpsをベースにしたCDフローについて説明します。Gitリポジトリは、上述した通りデプロイマニフェストを管理するリポジトリをアプリケーションコードとは別で管理しています。また、Kustomizeを利用すると環境ごとの差分パッチのみ管理できるのでマニフェストも管理しやすくなります。
図8は、既にprd環境に「v0.x」のタグが付与されたコンテナイメージをデプロイされた状態から、「v1.0」のタグのコンテナイメージに変更して新しいコンテナイメージをデプロイする例です。事前にv1.0のコンテナイメージはコンテナレジストリに格納されていることとします。
上述したCIフロー、およびCDフローを含めた全体フローが図9です。
本記事で紹介したのはCI/CDフローの一例ですが、このフローをベースにフローを発展させればクラウドネイティブなアプローチでCI/CDフローを組むことができると思うので、ぜひ参考にしてください。
今回は、Kubernetes NativeなCI/CDを紹介しました。CI/CDに関する歴史と背景を踏まえ、CI/CDに具備すべき機能がどういったものかをツール比較も交えて、説明しました。
次回以降、上述の通り、本連載ではGitLab、ArgoCDを紹介していきます。
Copyright © ITmedia, Inc. All Rights Reserved.