Infrastructure as Code: サーバー設定をGitで管理する理由

新しい機能をデプロイしようとしている。アプリケーションコードは準備完了、テストもパス、プルリクエストも承認済み。しかし、誰かが尋ねる。「新しいエンドポイント用にロードバランサーの設定を更新したっけ?」誰も確信が持てない。前回ロードバランサーを変更した担当者は休暇中だ。クラウドダッシュボードには現在の設定が表示されているが、先週何が変わったのか、なぜ変わったのかは誰も知らない。

このシナリオは、毎日のようにチームで発生している。インフラストラクチャの変更は、暗黙の知識、手動の手順、特定の担当者の可用性に依存している。その担当者が不在なら、変更は待たされる。手順を忘れれば、サーバーは静かに壊れる。そして問題が発生したとき、根本原因を突き止めるには、チャットログ、メール、記憶を掘り返す必要がある。

もっと良い方法がある。インフラストラクチャをコードとして記述することだ。

Infrastructure as Codeの本当の意味

Infrastructure as Code(IaC)とは、サーバー、ネットワーク、データベース、ロードバランサー、その他すべてのインフラストラクチャコンポーネントをテキストファイルで定義するプラクティスである。これらのファイルは、アプリケーションコードと同様にバージョン管理リポジトリに保存される。

重要なのは、インフラストラクチャを記述する方法の転換である。「SSHでサーバーにログインし、このコマンドを実行してNginxをインストールし、この設定ファイルを編集する」といったステップバイステップのコマンドを書く代わりに、インフラストラクチャがどうあるべきかを宣言的に記述する。例えば、「Nginxバージョン1.24を実行し、ポート443で待ち受け、このTLS証明書とこれらのプロキシルールを持つサーバーが必要だ」という具合だ。

これらのファイルを処理するツールは、宣言を読み取り、現在のインフラストラクチャの状態と比較し、一致させるために必要な変更を加える。これが望ましい状態管理(desired state management)と呼ばれるものだ。

以下は、Terraformにおけるシンプルな宣言的設定の例である:

resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"

  user_data = <<-EOF
              #!/bin/bash
              apt-get update
              apt-get install -y nginx
              systemctl enable nginx
              systemctl start nginx
              EOF

  tags = {
    Name = "web-server"
  }
}

resource "aws_security_group" "web_sg" {
  name        = "web-sg"
  description = "Allow HTTP and SSH"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["10.0.0.0/8"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

このファイルは、NginxがインストールされたEC2インスタンスと、Webトラフィックを許可するセキュリティグループという、必要な状態を正確に宣言している。Terraformはこの宣言をAWSアカウントの現在の状態と比較し、一致させるために必要な変更のみを加える。

日常業務がどう変わるか

インフラストラクチャがコードになれば、サーバー設定の変更は、マシンにログインしてコマンドを打つことではなくなる。ファイルを編集し、プルリクエストを開き、レビューを受け、マージすることになる。新しい設定が適用されると、サーバーは自動的に更新される。

これにより、ワークフロー全体が変わる:

  • すべての変更が追跡される。 リポジトリのコミット履歴を見れば、先週の火曜日の本番ロードバランサーの設定が正確にわかる。推測も「誰かが設定を変えたと思う」も不要になる。

  • 変更はレビュー可能になる。 インフラストラクチャの変更が本番環境に到達する前に、アプリケーションの変更と同じコードレビュープロセスを経る。チームメンバーはコメントし、改善を提案し、ダウンタイムを引き起こす前にミスを発見できる。

  • 誰でも変更を提案できる。 新しいデータベース接続プールが必要な開発者は、設定を書いてプルリクエストを送信できる。運用チームの空き時間を待つ必要はない。運用チームは変更を実行する代わりにレビューする。

  • ロールバックが簡単になる。 設定変更で問題が発生した場合、コミットを元に戻して再適用する。変更を元に戻すための手動手順の正確な順序を覚えておく必要はない。

望ましい状態(Desired State)の概念

Infrastructure as Codeにおける最も重要な考え方は、望ましい状態(desired state)である。設定ファイルは、インフラストラクチャの理想的な状態を記述する。IaCツールは、実際の状態が望ましい状態と一致するように継続的に保証する。

誰かがサーバーの設定を手動で変更した場合、ツールはドリフト(ずれ)を検出して元に戻す。サーバーがクラッシュして交換された場合、ツールは新しいサーバーを正しい設定で自動的にプロビジョニングする。一度だけ実行されるスクリプトを書いているのではない。目標を定義しており、システムがその目標を維持するのだ。

これは、サーバーをセットアップするスクリプトを書き、一度実行し、その後何も変わらないことを願うという古いアプローチとは根本的に異なる。望ましい状態があれば、システムは自己修復的かつ自己監査的になる。

Infrastructure as Codeではないもの

Infrastructure as Codeは特定のツールではない。Terraform、AWS CloudFormation、Ansible、Pulumiなどは、その概念の実装である。ツール自体よりも、インフラストラクチャ設定をバージョン管理され、レビュー可能で、宣言的なコードとして扱うプラクティスの方が重要だ。

また、手作業を完全になくすことでもない。インフラストラクチャを理解することは依然として必要だ。ネットワーキング、セキュリティ、スケーリングに関する設計上の決定は引き続き行う。しかし、それらの決定は、レビュー、テスト、再現が可能なファイルにエンコードされる。

CI/CDにとってこれが重要な理由

Infrastructure as Codeは、CI/CDパイプラインにおいて、インフラストラクチャの変更をアプリケーションの変更と同じように扱うための基盤である。インフラストラクチャがコードであれば、以下のことが可能になる:

  • インフラストラクチャの変更を適用する前に自動テストを実行する
  • 設定ファイルが構文的に正しいことを検証する
  • セキュリティポリシー違反を自動的にチェックする
  • アプリケーションをデプロイするのと同じパイプラインを通じて変更を適用する
  • 環境間の一貫性を確保する

Infrastructure as Codeがなければ、CI/CDパイプラインはアプリケーションコードしか処理できない。インフラストラクチャの変更は手動のままで、エラーが発生しやすく、パイプラインからは見えない。これにより、アプリケーションのデプロイは自動化されているが、その基盤となるインフラストラクチャは自動化されていないというギャップが生じる。

始めるための実践的なチェックリスト

Infrastructure as Codeの導入を検討しているなら、以下が実践的な出発点となる:

  • 1つの環境から始める。 インフラストラクチャ全体を一度に変換しようとしない。ステージング環境や開発環境から始める。
  • 宣言的なファイルを書く。スクリプトではない。 達成方法ではなく、何を望むかに焦点を当てる。宣言的なファイルはレビューと保守が容易だ。
  • すべてをバージョン管理に保存する。 リポジトリには、頻繁に変更されるファイルだけでなく、すべての設定ファイルを含める。
  • インフラストラクチャの変更をコードのようにレビューする。 アプリケーションの変更と同様に、インフラストラクチャの変更にもプルリクエストと承認を必須にする。
  • 適用する前にテストする。 設定ファイルを検証し、実際のサーバーに影響を与える前に変更をシミュレーションできるツールを使用する。
  • 手順ではなく、望ましい状態を文書化する。 ファイルは、目標とする設定を記述すべきであり、そこに到達するためのコマンドの順序ではない。

まとめ

Infrastructure as Codeは、一部の人だけが理解しているブラックボックスだったサーバーを、文書化され、再現可能で、管理可能なコンポーネントに変える。すべての設定変更はコミット履歴に痕跡を残す。すべてのサーバーは一貫した結果でスクラッチから再構築できる。すべてのチームメンバーが、深い運用アクセス権限を必要とせずにインフラストラクチャの改善を提案できる。

次に誰かが「先週、本番で何が変わった?」と尋ねてきたとき、推測する必要はない。リポジトリを開いてコミットログを確認すればいい。これが、インフラストラクチャを「芸術」として扱うことと「コード」として扱うことの違いだ。