CI/CD パイプラインを理解しよう

継続的インテグレーションデリバリー、およびデプロイ(総称して CI/CD と呼ばれます)について読んでいるなら、おそらく「自動パイプライン」という言葉に遭遇したことがあり、それがこの手法を実装する上で中心的な役割を果たしていることを聞いたことがあるでしょう。 しかし実際のところ、継続的インテグレーション/継続的デリバリーパイプラインとは一体何なのでしょうか。 どのようにして取り入れることができるのでしょうか。

CI/CD は、品質を損なうことなく、ユーザーにソフトウェアを提供する時間を短縮することを目的としています。 これは、必要な頻度で変更をデプロイして公開できるように、変更を頻繁にチェックインし、厳密にテストし、フィードバックに迅速に対応することで実現します。

CI/CD パイプラインとは

CI/CD パイプラインと言った場合、開発マシンから、テストやステージングを通じて、最終的にユーザーの手に渡るまで、コードが順に通過していく一連のステップを指します。

CI/CD 戦略は、このプロセスを非常に定期的に(通常 1 日に数回)実行することであるため、各ステップが次のステップをトリガーするか、何らかの異常時にはフラグを立てるようにして、できるだけ自動化することが不可欠です。

自動化はプロセス全体を加速化し、それによって各フィードバックループを短縮させるだけでなく、各ステップが一貫して確実に実施されることを保証します。

ビルドパイプラインのステージ

CI/CD パイプラインの実際の形は構築している製品の種類や組織の要件によって異なりますが、すべてのパイプラインが従う汎用的なパターンがあり、ここではその概要を説明しています。

プロセスはマスター(または CI ブランチに指定されたブランチ)へのコミットから始まり、それによってビルドまたは最初のユニットテストがトリガーされます。 その結果はダッシュボードにフィードバックされるのですが、ビルドまたはテストが失敗した場合は、フラグが立てられ、自動通知が送信されます。

プロセスを停止して課題を解決し、新しいコミットから開始できるようにパイプラインを構成することもできれば、特定の障害タイプ用の例外を作成してプロセスを続行させることもできます。

次のステージでは一連の自動テストが実施され、テストが行われるたびにフィードバックが提供されます。 通常、テストは構造化されており、最も簡単なテストを先に実行することで、早期にフィードバックを提供できるようになっています。

エンドツーエンドのテストなど、さらに深く検査するテストの場合は、より長い時間サーバーを占領してしまうため、その前のテストに合格してからしか実行されません。 こうすることで、より効率的にリソースを使用することができます。

自動テストが完了したら、ソフトウェアは通常一連のステージング環境にデプロイされます。この一部を使ってさらに手動テストを行い、残りはトレーニング、サポート、およびカスタマープレビューに使用することができます。

CI/CD パイプラインアーキテクチャの最終ステージでは、変更内容が公開されます。これは手動(継続的デリバリーの場合)または自動(継続的デプロイと同様)で行われます。

各ステージでの考慮事項について、もう少し詳しく見てみましょう。

フラグとブランチ

継続的インテグレーションを導入する最初のステップは、コードベース全体を Git、Mercurial、Perforce といったバージョン管理システム(VCS、バージョン管理、または SCM)に投入し、チーム全員に変更の頻繁なコミットを習慣付けさせることです。 マスターにコミットされるたびに、パイプラインが開始し、コードのビルドとテストが行われ、作成したコードに関するフィードバックが迅速に提供されます。

頻繁にコミットすることは CI/CD パイプラインの重要なプラクティスですが、完成するまでに数日または数週間かかるような大規模な機能に取り組んでいる場合、そのプロセス中に定期的にコミットするのは両刃の剣のように感じられるかもしれません。

一定した増分で変更をパイプラインに押し進めれば、迅速なフィードバックを得られ、最後まで待つよりも競合が複雑化する可能性を低減させることができます。

一方で、中途半端な機能をユーザーにリリースしたり、ステージング環境で未完成のものを社内ユーザーに共有したりするのには億劫に感じられるかもしれません。

この問題については、機能フラグと機能ブランチで対処できます。 機能フラグは、コードがユーザーに公開される環境を指定するために使用できます。 変更はそれでもマスターにコミットされ、チームに公開されますが、その機能がステージングと本番にいつ公開されるかを決定することができます。

機能ブランチを使うと、機能を別のブランチで開発することができるため、自動ビルドとテストのメリットを損なうことがありません。 機能ブランチにコミットされるたびに、CI/CD パイプラインをトリガーすることで、マスターへのコミットと同様に、構築した内容に対するフィードバックを迅速に得ることができます。

ビルドとテスト

コミットによってパイプラインのインスタンスがトリガーされたら、次のステージはビルドとテストです。 ユニットテストを自動化している場合、これらのテストは一般的にリントと静的解析チェックを含む形でビルド前に実行されます。

使用するビルドツール(Ant や Maven など)と詳しいビルドステップは、使用している言語とフレームワークによって異なります。 専用のビルドサーバー自動ビルドを実行することで、依存関係の欠落による下流での問題、よくある「自分のマシンでは動作する」問題を回避することができます。

ビルドステップの出力にはインストーラー、バイナリー、またはコンテナー(ビルドアーティファクト)が含まれており、これらはテスト環境にデプロイされてシステムの他の部分と組み合わされて、より高いレベルの自動テストが実行されます。インテグレーションテスト、コンポーネントテスト、およびエンドツーエンドテストだけでなく、パフォーマンスやセキュリティ解析などの機能外のテストです。

これらのテストは、パイプラインを加速化してより素早くフィードバックを得られるように、並行して実行するとも可能です。

コンテナーと VM

自動テストの結果に確実性を持たせるには、これらが一貫して実行することを保証する必要があります。

理想的に言えば、テスト環境はできるだけ本番に似せて構成されるべきであり、テストが実行されるたびに、環境上の矛盾によるテスト結果への影響を回避できるようにリセットされなければなりません。

仮想マシン(VM)はテスト中の新しいビルドごとにプロセスを初期化できるようにスクリプトすることができるため、長い間、テスト環境の実行に使用されてきました。

ところが、新しい VM を取り崩してスピンアップするには時間がかかる上、ソフトウェアが実行する必要のあるすべての依存関係を提供する仮想環境ごとの構成をスクリプトに含める必要があります。 新しい依存関係が追加されると、環境スクリプトも更新が必要となりますが、このような単純な作業は、ビルドが実行しない理由に悩まされるまで気づかないものです。

最初のビルドステップの一環として、コンテナーにコードをパッケージ化することで、この問題を回避することができます。 コンテナーにはソフトウェアが実行する必要のあるすべての依存関係が含まれるため、非常に移植しやすく、別の環境に簡単にデプロイすることができます。

独自のインフラストラクチャに CI/CD パイプラインをホストしている場合は、コンテナーをデプロイするための VM が必要となりますが、テスト環境の準備にかかる手間は少なくなるため、パイプラインの稼働を効率的に維持しやすくなります。 クラウドでパイプラインを実行している場合は、コンテナーを導入することで、マネージドサービスを使用できるようになり、インフラストラクチャ側の作業をクラウドプロバイダーに任せることができます。

本番前環境

パイプラインアーキテクチャ内のテスト環境とステージング環境の数は構築しているものと組織内のさまざまな関係者グループのニーズによって異なります。 探索的テスト、セキュリティレビュー、ユーザー調査、販売デモ、トレーニング環境、およびサポートスタッフが顧客の問題を再現するために使用するサンドボックスなどが例として挙げられます。

これらの環境の作成とそれへのデプロイを自動化することで、手動でリフレッシュするよりも効率的であり、環境ごとに異なるパイプラインのトリガーを構成することができます。

たとえば、テスト環境はビルドごとに更新しても、ステージング環境はそれほど頻繁にではなく、1 日に 1 回または 1 週間に 1 回のペースで、最新の成功ビルドを使用してリフレッシュするように決定することもできます。

デプロイ

コードの変更がパイプラインの手前の全ステージで合格すると、本番にリリースできるようになります。 その最終ステップは、手動ででも自動ででも行うことができます。

手動によるリリース(継続的デリバリー)は、新しい特徴や機能が公開される時期をあなたが制御する場合に役立ちます。デプロイプロセスによってユーザー側にダウンタイムが生じる場合や、製品がインストール済みであるため、変更をバッチ化して定期的なリリーススケジュールに合わせて提供する場合などに有効です。

完全に自動化された継続的デプロイプロセスでは、変更は、前のステージすべてで合格している限り、デプロイされて公開となります。

コードベースに関わっている開発者数とコミットの頻度によって異なりますが、このプロセスでは 1 日に数十回、更新がデプロイされる可能性があります。自動パイプラインがなけれは実質的に不可能なことです。

CI/CD パイプラインを理解しよう: 要約

CI/CD は、できるだけ早期に課題を明確化することで、ソフトウェア開発の効率性を向上させることができます。早いうちに操作に移行し、フィードバックを得ることで、早期に障害を特定することができるためです(「シフトレフト」と呼ばれています)。 自動パイプラインを構築することによって、これらの技法を実践に持ち込めるようになります。

独自の CI/CD プロセスを設計する際には、継続的インテグレーションからステージごとに構築すると設計しやすくなります。 パイプラインの実際のステージと、それぞれのステージがいつトリガーされるのかを決定するロジックは、製品と組織によって異なります。

要件に応じてパイプラインを構成できる柔軟性を提供する一方で、管理しやすい CI/CD プラットフォームを選択することで、信頼できるリリースプロセスを築き、ソフトウェアの品質を改善できるようになります。