CI/CDパイプライン設計

継続的インテグレーションと継続的デリバリー(CI/CD)の概念、テストの自動化、自動デプロイの流れを学びます。

学習をスタートする

ロードマップ

1

CI/CDの基本概念と自動化の価値

ソフトウェア開発において、コードの変更を安全かつ迅速にユーザーへ届けるための仕組みが CI/CD(継続的インテグレーション/継続的デリバリー・デプロイ) です。本章では、CI/CDの基本概念と、それらが開発にもたらす価値について解説します。 1. CI/CD とは何か? CI/CD は、コード変更からテスト、本番環境への配置(デプロイ)に至るプロセスを自動化し、リリース頻度と品質を向上させるためのプラクティスです。 1. 継続的インテグレーション (CI: Continuous Integration) 開発者がコードを変更(コミット・プッシュ)するたびに、自動的に ビルド と テスト を実行する仕組みです。 * 目的: 複数の開発者が書いたコードを常に統合し、早期にバグを発見して修正すること。 2. 継続的デリバリー (CD: Continuous Delivery) CIによって検証されたコードを、本番環境にリリース可能な状態に保つプロセスです。ステージング環境や本番環境へのビルド生成物を自動で用意しますが、本番デプロイの実行自体は 人間の手(承認ボタンなど) で行われます。 3. 継続的デプロイ (CD: Continuous Deployment) 継続的デリバリーをさらに進め、テストを通過した変更を、人間の介入なしで 自動的に本番環境へデプロイ する仕組みです。 2. CI/CD パイプラインの流れ(図解) 一般的なCI/CDパイプラインは、開発者がコードをリポジトリにプッシュしたことをトリガーに、以下のようなフェーズを自動的に駆け抜けます。 3. CI/CD 導入のメリット * バグの早期発見: 手動テストに頼らず、コミットの度に自動テストが走るため、バグを混入させた本人がその場で気づいて修正できます。 * リリースの心理的障壁を下げる: 「デプロイ手順書」を見ながら手動でコマンドを打つ必要がなくなるため、リリースの作業ミス(オペレーションミス)がなくなり、安全に頻繁なアップデートが行えます。 * フィードバックサイクルの高速化: 新機能を素早く本番環境へ届けられるため、ユーザーからのフィードバックを迅速に得てプロダクト改善に活かすことができます。 まとめ * CI はビルドとテストを自動化し、統合時のバグを早期発見する。 * CD はリリースプロセスを自動化し、本番デプロイまでの手間とミスを削減する。 * CI/CD を導入することで、リリース頻度が高まり、プロダクト開発のサイクルが高速化する。

2

GitHub Actionsを用いたCIの実践

現代のWeb開発で最も人気のあるCI/CDプラットフォームの1つが GitHub Actions です。GitHubリポジトリと完全に統合されており、YAMLファイルで定義するだけで簡単に自動化処理を組み込むことができます。本章では、GitHub Actionsの基本概念と、実践的なCIパイプラインの記述方法を学びます。 1. GitHub Actions の主要概念 * ワークフロー (Workflows): リポジトリに設定する自動化プロセスの単位です。.github/workflows/ ディレクトリ配下に YAML 形式で作成します。 * イベント (Events): ワークフローを実行するトリガー(きっかけ)です。例: 「コードが main ブランチにプッシュされた時」「プルリクエストが作成された時」。 * ジョブ (Jobs): 同一の仮想マシン(ランナー)上で実行される、複数の「ステップ」の集まりです。複数のジョブはデフォルトで並列に実行されます。 * ステップ (Steps): 実行される個々のタスクやコマンドです。 * アクション (Actions): よく使われる処理(Node.jsのセットアップやチェックアウトなど)を再利用可能なモジュールにしたものです。 2. 実践的なCIワークフローの例 以下は、Node.js プロジェクトにおいて、コードがプッシュされた際に自動的にコードフォーマット (Prettier) や 静的解析 (ESLint) を実行し、ユニットテストを通してビルドの成否をチェックする YAML 定義です。 3. パイプラインを高速化するテクニック CIパイプラインは開発者が頻繁に待つことになるため、実行速度の最適化が非常に重要です。 * キャッシュ (Caching) の活用: 上記の actions/setup-node の cache: 'npm' のように、node_modules などの依存関係ファイルをキャッシュしておくことで、毎回の npm install の時間を劇的に(数分から数十秒へ)削減できます。 * 並列ジョブ (Parallel Jobs): テストジョブと、静的チェックジョブを別々のJobに分割して並列実行させることで、全体の完了時間を短縮できます。 まとめ GitHub Actions の設定は .github/workflows/.yml** に記述する。 * ジョブ (Jobs) は並列で走り、その中の ステップ (Steps) は順次コマンドを実行する。 * キャッシュ などを駆使して、開発者を待たせない「高速なCIパイプライン」を維持することが重要である。

3

安全なデプロイ戦略(Blue-Green, Canary)

検証済みのアプリケーションを本番環境へ反映する「CD (継続的デリバリー・デプロイ)」において、システムの停止(ダウンタイム)を無くし、障害発生時に即座に切り戻し(ロールバック)ができるような安全な デプロイ戦略 の設計が求められます。本章では、代表的なデプロイ戦略について学びます。 1. 代表的なデプロイ戦略 1. インプレースデプロイ (In-place Deployment) 稼働しているサーバー上のプログラムを直接上書きする手法です。 * 特徴: 最もシンプルで追加のインフラコストがかかりません。 * 課題: デプロイ中や再起動中にシステムが一時停止する(ダウンタイムが発生する)可能性が高く、切り戻しにも時間がかかります。 2. ローリングアップデート (Rolling Update) 複数のサーバー(インスタンス)がある環境において、1台ずつ順番に新しいバージョンに入れ替えていく手法です。 * 特徴: 常に一部のサーバーが稼働しているためダウンタイムが発生しません。 * 課題: デプロイ中、新旧バージョンが混在する状態が発生するため、データベースなどの後方互換性を保つ設計が必要です。 2. 高度で安全なデプロイ戦略(図解) プロダクション環境で広く利用されている、より安全なデプロイ方式です。 ブルーグリーンデプロイメント (Blue-Green Deployment) 現在稼働中の環境(Blue)とは別に、全く同じ構成の新しい環境(Green)を構築し、ロードバランサーなどのルーティング(DNS等)を一瞬で切り替えることでデプロイを完了させる手法です。 * メリット: - ダウンタイムがゼロ。 - Green環境で事前に十分テストしてから本番化できる。 - 障害が発生した場合、ルーターを元のBlue環境に戻すだけで、瞬時にロールバック(切り戻し)ができる。 * デメリット: 一時的にインフラコストが2倍かかる。 3. カナリアデプロイメント (Canary Deployment) 本番環境のサーバーの一部(例えば 10%)だけに新しいバージョンを適用し、一部のユーザーにだけ先行公開して様子を見る手法です。問題がなければ徐々に新バージョンの割合を増やし、最終的に100%に移行します。 * メリット: - バグやパフォーマンスの問題があった場合の影響を、全ユーザーではなくごく一部(10%)に限定できる。 * デメリット: ルーティング設定が複雑になる。 デプロイ戦略の比較 戦略 ダウンタイム インフラコスト ロールバック 難易度 インプレース あり 低 遅い 容易 ローリング なし 低 中速 中 ブルーグリーン なし 高 瞬時 高 カナリア なし 中〜高 瞬時 極めて高 まとめ * インプレースデプロイ は簡単だがダウンタイムが発生する。 * ブルーグリーンデプロイ は新旧の環境を丸ごと切り替えることで、ダウンタイムゼロと一瞬でのロールバックを実現する。 * カナリアデプロイ は一部のユーザーに限定公開してエラー率などを監視し、段階的に適用範囲を広げていく。

4

CI/CDにおけるセキュリティと脆弱性スキャン

CI/CDパイプラインは非常に強力である一方、リポジトリや本番サーバーへのデプロイ権限を持つため、攻撃者にとって格好の標的になります。ビルドやデプロイを自動化するのと同様に、セキュリティの検証もパイプライン内で自動化する「DevSecOps」の実践が求められます。 第4章では、CI/CDで担保すべき主要なセキュリティ対策について学びます。 1. シークレット管理とOIDCの活用 データベースのパスワードやクラウドのAPIキーなどの機密情報(シークレット)を、決してコード内に直接記述(ハードコード)してはいけません。 OIDC (OpenID Connect) 接続の推奨 従来はクラウドへの接続時、CIツールの環境変数(GitHub Secretsなど)に長期アクセストークンを保管していました。しかし、これらは漏洩のリスクがあります。 現在推奨されているのは OIDC を用いた一時的な認証方式です。CI/CD実行時に信頼されたプロバイダ(例: GitHub)から一時的な署名付きトークンを発行し、それをクラウド(例: AWS IAM)に提示して、その場で有効期限が短い(例: 1時間)キーを取得して処理を実行します。 2. 静的解析(SAST)と依存関係スキャン(SCA) 安全なコードを自動で検証するために、CI/CDで以下の2種類のスキャンを実行します。 SAST (Static Application Security Testing) ソースコードそのものをスキャンし、SQLインジェクション、XSS、不適切なシークレットのハードコードといった脆弱性を検出します。 * ツール例: SonarQube, GitHub CodeQL, Semgrep SCA (Software Composition Analysis) プロジェクトが利用している外部ライブラリ(npm や pip パッケージなど)を検証し、既知の脆弱性(CVE)が含まれていないかをデータベースと照合してチェックします。 * ツール例: Trivy, Dependabot, Snyk 3. コンテナとインフラの脆弱性スキャン アプリケーションコードだけでなく、デプロイされるコンテナイメージやIaCテンプレート(Terraformなど)の設定不備もスキャン対象です。 * コンテナスキャン: ベースイメージ(OSパッケージ等)に潜む古いパッケージの脆弱性をビルド直後に検出します。 * IaC静的解析: TerraformやCloudFormationの定義ファイルで、S3バケットがパブリック公開されていないか、不要なポートが全開放されていないかを検証します。 * ツール例: tfsec, Checkov パイプライン内にこれらの自動セキュリティチェックを組み込むことで、問題のあるコードや設定が本番環境へデプロイされるのを防ぐ盾を作ることができます。

5

パイプラインの最適化とキャッシュ戦略

CI/CDパイプラインは開発フローの品質を保証しますが、その実行時間が長すぎると開発者体験(DX)が低下し、フィードバックループが遅れてしまいます。さらに、従量課金制のCIツールでは、実行時間の増加がそのままコストの増加に直結します。 第5章では、CI/CDを高速化し、効率的かつ低コストで運用するための最適化手法とキャッシュ戦略について解説します。 1. 依存関係のキャッシュ戦略 CIランナー(仮想マシン)は、実行ごとにまっさらな状態で起動します。そのため、そのままでは毎回依存関係パッケージ(例: node_modules)をインターネット経由でゼロからダウンロードすることになり、無駄な時間が発生します。 これを防ぐために、キャッシュアクションを使用します。 GitHub Actionsでの設定例 actions/setup-node など多くの標準アクションには、キャッシュ機能が統合されています。 2. Dockerレイヤーキャッシュ (GitHub Actions) DockerイメージをCI内でビルドする場合、Dockerのビルドキャッシュも同様に重要です。 GitHub Actionsでは、GitHub Actions Cacheバックエンド(gha)をエクスポート先・インポート先に指定することで、別々のランナー間でもキャッシュを引き継ぐことができます。 これにより、変更のない Dockerfile の命令(例: RUN npm install)がキャッシュから即座に解決され、イメージのビルド時間を数分から数秒へと劇的に縮小できます。 3. 並列処理とマトリックスビルド テスト件数が多い場合、1つのランナーで順次テストを実行すると膨大な時間がかかります。これらを 「並列実行(Parallel Execution)」 させることで解決します。 マトリックスビルドの活用 複数のNode.jsバージョンや、異なるOS環境、あるいはテストスイートの分割などで複数のテストを同時に並行して走らせる機能です。 この設定により、3つのバージョン × 2つのOS = 計6個のジョブが独立したランナーで同時に並行実行され、全体の待機時間が最も長いジョブの実行時間(ボトルネック)のみに抑えられます。 キャッシュと並行処理を適切に組み合わせることで、開発チームはバグや変更のテスト結果を即座に受け取ることができ、アジャイルな開発サイクルがより活性化します。