「Kubernetes Native」なCI/CDとは何か――クラウドネイティブ時代に至る歴史、主要ツール、パイプラインとフローの在り方Cloud Nativeチートシート(5)

Kubernetesやクラウドネイティブをより便利に利用する技術やツールの概要、使い方を凝縮して紹介する連載。今回は、Kubernetesの利用を前提とした「Kubernetes Native」なCI/CDについて踏み込んで説明します。

» 2021年05月28日 05時00分 公開
[山田真也, 正野勇嗣, 岡本隆史株式会社NTTデータ]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

 Kubernetesやクラウドネイティブをより便利に利用する技術やツールの概要、使い方を凝縮して紹介する本連載「Cloud Nativeチートシート」。今回紹介するのは、CI/CD(継続的インテグレーション/継続的デリバリー)です。中でもKubernetes(以下、k8s)の利用を前提とした「Kubernetes Native」なCI/CDについて踏み込んで説明します。

 多種多様なCI/CDツールが存在する中、どういった軸で理解すればいいか分からない方もいることでしょう。以降、CI/CDに関する歴史と背景を踏まえ、CI/CDに具備すべき機能がどういったものかをツールの比較と動向も交えて解説します。

歴史と背景〜Kubernetes NativeなCI/CDに至るまで〜

 CI/CDの進化の歴史と背景を以下の4ステップで紹介します(図1)。CIとCD、アプリケーション(AP)層と基盤層に分けてCI/CDを理解していきましょう。

  1. CIからCI/CDへ
  2. 基盤層:オンプレからクラウド、コンテナ(そしてk8s)へ
  3. AP層:モノリスからマイクロサービスへ
  4. CIOpsからGitOpsへ

図1 CI/CDの進化の歴史

1.CIから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ジョブを数珠つなぎで頑張ってつないできた時代がありました。パイプラインが普及し便利になったなと感じます。

2.基盤層:オンプレからクラウド、コンテナ(そしてk8s)へ

 オンプレミスの時代は、仮にCI/CDやDevOpsにより全自動化を目指そうとした場合に、以下のさまざまな層(レイヤー)を意識する必要がありました。

  • AP:Javaのwarファイルをデプロイ
  • ミドルウェア:Tomcatや「Oracle WebLogic」といったアプリケーションサーバ、「MySQL」「Oracle Database」などのRDBMSの設定
  • OS:ファイルシステムへの設定ファイルなどの配置

 仮想化やクラウド化が進展し、これらAP/ミドルウェア/OSの設定はコンテナやクラウドリソースに代替されるようになりました。つまり、CI/CDツールが直接意識するのはコンテナやクラウドリソースに集約され、1段抽象化されたレイヤーでの管理が可能になります。

 さらにはk8s、つまりコンテナオーケストレーションが出てくると、これらコンテナやクラウドリソースはk8sのマニフェストに代替されます。つまり、CI/CDツールが直接意識するのはマニフェストに集約され、さらに1段階抽象化されたレイヤーでの管理が可能になります。

 もちろん、「全てがマニフェストによる管理になる」とまでは言い切れませんが、より抽象化、集約化されたレイヤーにおいてテキストベースで管理することが可能となります。また、IaC(Infrastructure as Code、システムリソースのコード化)の実現が容易となります。

図2 集約化、抽象化された管理

3.AP層:モノリスからマイクロサービスへ

 DX(デジタルトランスフォーメーション)の時代においては、高頻度でのサービスのリリース要求が高まっています。下支えする技術として、クラウドやアジャイル、マイクロサービスといったものが挙げられます。アプリケーションの単位はモノリスの時代より小さくなり、より柔軟なリリースが可能となります。

 具体的には、リリースの範囲が小さなマイクロサービスの範囲に限定され、昨今当たり前となってきているCI/CDにまつわるさまざまなベストプラクティスが適用しやすくなっています。

  • A/Bテスト
  • Blue/Greenデプロイ
  • カナリアリリース

 一方で、アプリケーションがサイロ化しやすくなり、個別のマイクロサービスの障害がシステム全体の障害につながったり、システム全体の動きが見えづらくなったりします。さらにはシステムの挙動が複雑化するので、品質確保のためのテストについてもこれまで以上の工夫が必要となります。

  • システム全体の障害の防止:サーキットブレーカー
  • 品質確保:カオスエンジニアリング、Contract Tests
  • 見える化:分散トレーシング、ロギング

4.CIOpsからGitOpsへ

 最近は「GitOps」という概念も出てきており、CD領域に「ソフトウェア開発の技法」が取り込まれてきています。

 これまで、CIツールがビルドからデプロイまで一括して実施してきました(「CIOps」と呼びます)。一方で、GitOpsでは、デプロイをCDツールに任せ、CIツールはビルド部分に専念します。

図3 CIOpsとGitOpsの違い

 k8sでGitOpsを実現する際のポイント、特徴として、下記4点が挙げられます。いずれもソフトウェア開発でよく使われる技法です。

  • 委譲
  • 宣言的プログラミング
  • Single Source of Truth(イベントリスナ)
  • DRY

 なお、少し軸がずれますが「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の恩恵を受けることができます。

CI/CDツールの比較

 前節の内容を踏まえ、代表的なツールを比較します(図4)。

図4 代表的なCI/CDの比較表

 まず、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があります。

CI/CDツールの利用状況

 CNCFの調査レポートを基に、ツールの利用状況を把握しましょう。執筆時点での最新のレポートは2020年11月のレポート(PDF)だったので、こちらを引用します(図5)。

図5 CNCF CI/CDツール 利用状況レポートから引用

 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フローを組むといいのか」を考察します。クラウドネイティブのベースとなるコンテナのプラクティス、ブランチ戦略を鑑みて「どのようにCI/CDフローを組み立てるか」を、順を追って見ていきます。

コンテナにおけるCI/CDのプラクティス

 コンテナアプリケーションも同様に、Gitリポジトリ(アプリケーションコード)をSingle Source of Truthとした状態に保つことが望ましいでしょう。すなわち、Gitリポジトリの特定のバージョンに対応するコンテナイメージは1つであり、devやprd環境へのデプロイも同一のコンテナイメージをプロモーションするようなCI/CDフローとすることが望ましいでしょう。

 同一のコンテナイメージかどうかは、イメージのdigest値が同一かどうかで検証できます。

図6 同一コンテナイメージの配布

 また、他にも下記のようなプラクティスを検討するといいでしょう。

  • コンテナイメージを小さく保つ(「.dockerignore」を使って不要なファイルが含まれることを防止する)
  • タグを活用しバージョンや安定性、目的などを分かりやすく保つ
  • マルチステージビルドやキャッシュを利用してビルドを高速化し、イメージを最小化する
  • コンテナスキャンなどの機能を有効にしてコンテナイメージをセキュアに保つ

ブランチ戦略

 Gitを利用するケースでは、Git FlowGitHub FlowGitLab 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/CD全体を俯瞰(ふかん)したフローを説明します。

CIフロー

 CIツールで実行するパイプラインでは、品質を検証するためのタスクやコンテナイメージ作成のタスクを実施することが求められます。CIパイプラインにおける代表的なタスクとして、下記のようなものが挙げられます。

  • ソースコードの静的解析(例:「SonarQube」など)
  • 回帰テスト
  • コンテナビルド
  • コンテナスキャン
  • コンテナプッシュ

 Gitでの(GitHub Flow)開発ワークフローの各ポイント(プル/マージリクエストやmasterマージなど)でCIを実施することで、常に品質が保っていることを確認できるようにしておくといいでしょう。また、コンテナビルドの際はイメージタグにはGitのブランチやタグ、またはコミットハッシュ値を付与すると、Gitリポジトリの特定時点の状態をコンテナイメージと一致させることで管理しやすくできるでしょう。

CIの導入イメージを見ていきましょう(図7)。

図7 CIフロー
  1. 開発者はmasterからブランチを作成してブランチ内で開発したソースコードをコミット
  2. 開発者はソースコードの開発が完了したら、Gitリポジトリにブランチをプッシュしてプル/マージリクエストを作成
  3. CIツールが変更をトリガーにCIを実行(図7の【1】)
  4. CIツールで回帰テストなどによる品質検証(図7の【2】)
  5. 品質検証に問題なければCIツールでコンテナビルド&プッシュ(図7の【3】)

CDフロー

 続いてGitOpsをベースにしたCDフローについて説明します。Gitリポジトリは、上述した通りデプロイマニフェストを管理するリポジトリをアプリケーションコードとは別で管理しています。また、Kustomizeを利用すると環境ごとの差分パッチのみ管理できるのでマニフェストも管理しやすくなります。

 図8は、既にprd環境に「v0.x」のタグが付与されたコンテナイメージをデプロイされた状態から、「v1.0」のタグのコンテナイメージに変更して新しいコンテナイメージをデプロイする例です。事前にv1.0のコンテナイメージはコンテナレジストリに格納されていることとします。

図8 CDフロー
  1. masterからブランチを作成してブランチ内でデプロイマニフェストを修正(コンテナイメージタグをv1.0に修正)
  2. Gitリポジトリにブランチをプッシュし、プル/マージリクエストを作成
  3. プル/マージリクエストをmasterにマージ
  4. GitOpsツールがGitリポジトリを監視し、変更を検知(図8の【1】)
  5. GitOpsツールがk8sクラスタの現状態(v0.x)との差分を検出してクラスタの状態とGitリポジトリの状態を同期(コンテナイメージv1.0のデプロイマニフェストを適用)(図8の【2】)
  6. コンテナイメージv1.0をk8sクラスタにデプロイ(図8の【3】)

CI/CD全体フロー

 上述したCIフロー、およびCDフローを含めた全体フローが図9です。

図9 CI/CDフロー
  1. Gitリポジトリ(アプリケーションコード)にコードをプッシュ、プル/マージリクエスト、masterマージ、タグ作成
  2. CIツールがGitリポジトリ(アプリケーションコード)の変更をトリガーにCIを実行(図9の【1】)
  3. CIツールで回帰テストなどによる品質検証テスト(図9の【2】)
  4. 品質検証に問題なければCIツールでコンテナビルド&プッシュ(図9の【3】)
  5. Gitリポジトリ(デプロイマニフェスト)のmasterからブランチを作成し、ブランチ内でデプロイマニフェストを修正。Gitリポジトリにブランチをプッシュし、プル/マージリクエストを作成
  6. Gitリポジトリ(デプロイマニフェスト)のプル/マージリクエストをmasterにマージ
  7. GitOpsツールがGitリポジトリを監視して変更を検知(図9の【4】)
  8. GitOpsツールがk8sクラスタの現状態との差分を検出してクラスタの状態とGitリポジトリの状態を同期(図9の【5】)
  9. 新しいコンテナイメージをk8sクラスタにデプロイ(図9の【6】)

 本記事で紹介したのはCI/CDフローの一例ですが、このフローをベースにフローを発展させればクラウドネイティブなアプローチでCI/CDフローを組むことができると思うので、ぜひ参考にしてください。

次回は、GitLab、ArgoCDについて

 今回は、Kubernetes NativeなCI/CDを紹介しました。CI/CDに関する歴史と背景を踏まえ、CI/CDに具備すべき機能がどういったものかをツール比較も交えて、説明しました。

 次回以降、上述の通り、本連載ではGitLab、ArgoCDを紹介していきます。

Copyright © ITmedia, Inc. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。