クラウド

IaC導入実践 ~Terraform~:後編(実際の導入手順と注意点)

本記事はIaC導入を進めるにあたって、苦労した点やその回避策をまとめた内容となります。
前編は導入にあたっての知識を中心に、後編は導入時の技術的な話を中心に記述します。

はじめに

本稿は、Infrastructure as Code (以下、IaC) を導入するに当たっての失敗や苦労話とどのように解決したかをまとめたいと思います。 同様に苦労されている方々の参考になれば幸いです。
また、本記事は複数に分けて投稿しています。 前回は導入時の注意点や、導入のメリット等を中心に書きました。
今回は具体的な構成や技術的な話を書いていきます。

関連ブログ:IaC導入実践 ~Terraform~:前編(導入の苦労とその解決策)

関連製品ページ:HashiCorp Terraform


今回の構成

AWSとAzureを使ったマルチクラウド環境で、それぞれの環境はFortigateで保護されています。

なお、AWS側の構成は商用環境における推奨構成の一例を参考にしており、
本稿ではAWS側の構築を中心に記述しています。

関連製品ページ:https://cn.teldevice.co.jp/product/fortigate_appliance/


構築 (AWS + Fortigate with HCP Terraform)

HCP Terraform から構築を実行するにあたり、アクセスキーやシークレットキー、Fortigateのパスワードなどを利用する必要があります。
コードに直接書くことも可能ですが、ご承知の通りセキュリティ観点から推奨できません。

そこで、HCP Terraform の Variables という機能を利用します。
Variablesでは上記のようなシークレットを安全に保管・管理し、構築時に利用することが可能です。
登録時にSensitiveオプションを利用すると、登録者含めすべてのユーザーが登録後に確認できない状態で登録できます。(更新は可能)
なお、保存されているデータも暗号化されています。
パスワードやシークレットキーなどの機密情報はこの設定で登録することをお勧めします。

 

▼コードの説明

下記は、Terraformで利用するコードの抜粋となります。(EC2インスタンス関連部分)
記述形式はHCLです。

${} で表記されている部分は、変数を代入している個所となります。

##################################################
# EC2 Instance
##################################################
data "aws_ami" "ubuntu" {
  most_recent = true

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }

  owners = ["099720109477"] # Canonical
}

resource "aws_instance" "instance" {
  ami                    = data.aws_ami.ubuntu.id
  instance_type          = var.instance_type
  key_name               = var.keyname
  subnet_id              = aws_subnet.sn1.id
  vpc_security_group_ids = [aws_security_group.sg.id]
  user_data              = data.cloudinit_config.cic.rendered
  tags = {
    Name = "${var.prefix}-instance"
  }
  depends_on = [
    aws_ec2_transit_gateway_route_table_association.tgw_rtb_associ,
    aws_ec2_transit_gateway_route.tgw_rt_sv1vpc
  ]
}

data "cloudinit_config" "cic" {
  gzip          = true
  base64_encode = true
  part {
    filename     = "demo-vm.sh"
    content_type = "text/x-shellscript"
    content      = file("demo-vm.sh")
  }
}

インスタンスの構築時に、ユーザーデータとしてコマンドやスクリプトを実行することでOS上の初期構築を自動化することが可能です。
今回は初期構築を行うコマンドをまとめたスクリプトを渡しており、自動化も実現しています。
その初期設定の中には、adminユーザーの設定・パスワードも定義していますが、
具体的なパスワードは変数を取り込んで反映する形となっています。
この変数はもちろん先に述べたVariablesに登録したものを利用しています。
Variablesはグループとして定義することが可能で、各プロジェクトにアタッチすることで共通設定のように使うことも可能です。

また、Terraformではコードをモジュールとして登録し、テンプレートのように利用することが可能です。
上記のようなEC2の構築部分をモジュールとして登録すると、新たにすべてをコードに書くことなく参照し、
新たな環境用の変数と組み合わせて使うことが可能です。

 

▼HCP Terraform のワークフロー

では実際にコードを実行していきます

今回、コードはGitHubにあるものとして進めます。(HCP Terraformは他にも連携可能なバージョン管理システムがあります)
[対応状況(公式ドキュメント)]

HCP Terraformでは一つの実行環境をWorkspaceと呼びます。
今回はコード管理するGitHubのプロジェクトをWorkspaceと連携させて環境を作成しました。(Version Control Workflow)

WorkspaceのRunsというメニューからPlan/Applyの実行・管理が行えます。

  • Plan … コードの事前チェック。どんな変更が行われるのか?の確認
  • Apply … 構築の実行。構築された環境の内容はState fileに記録される

Runが実行されるトリガーには、HCP Terraformから手動で実行する方法だけでなくGitの更新をトリガーにすることも可能です。

実際にPlan/Applyが実行されると下記のように変更が確認できます

同様にApplyが正常に成功していれば構築先のポータル等でも、環境が構築されたことを確認できると思います。

注意:
Terraformから構築した環境に各クラウドのポータル等から変更をするとState fileとの差分(Drift)が発生します。ポータルからの変更がコードへ自動的に反映されるものではありませんのでご注意ください。有償プランを利用すると構築した環境の定期的な差分チェック機能が用意されています

▼Terraform エージェントの紹介

HCP Terraformにはエージェントクライアントが用意されています。
HCP Terraformからデプロイ環境に直接アクセスできない場合や、外部から内部への通信許可を構築しづらい環境の場合に活躍します。
エージェントはWorkspaceと紐づき、エージェントがWorkspaceの更新を定期チェックします。更新があった場合には、エージェント側からHCPTerraformへ接続を行い、Plan/Applyを実行します。
※外部への通信を一切許可されない環境であれば、内部にTerraform Enterpriseを構築するという手法をとれば同様のことが行えます

▼ポリシーの適用

HCP TerraformではPlan/Apply実行時にポリシーチェックを組み込むことが可能です。
組み込む方法は簡単で、登録したポリシーをWorkspaceに紐づけるだけで、次回Plan/Apply以降から適用されます。
※無料プランでも利用可能ですが、紐づけ可能なポリシーを1セットしか登録できないためプロダクト利用ではお勧めできません。

上記のような画面だと、定義したポリシーのいずれかに違反しているということがわかります。
違反時の動作も3種類用意されており、用途、場面に応じてコントロール可能です。

Advisory 通知のみ。処理は継続
Soft mandatory 権限をもつユーザーの承認があれば、継続可能。
Hard mandatory 処理を中止

今回のポリシーチェックでは、簡単なところから始めており

  • インスタンスサイズ
  • リージョン
  • タグの有無

のチェックを実装しました。その他にもVPCのCIDRや、セキュリティグループの指定など今後も追加予定です。


要点・まとめ

さて、ここまでの流れが正常に終了していれば、クラウド環境には指定のリソースが構築されている状態です。
今回構築するにあたっての注意したポイント等をまとめていきます。

  • コードに必要な秘密情報(シークレット)はVariablesの機能を使い、秘匿したまま利用する
    • 絶対にハードコーディングでは利用しない
  • コードをモジュール化して再利用することで、構築手法の統一化を図る
    • 想定した構築方法に集約していく
  • コードで表現することで、ポリシーチェックも自動化しやすくなる。
    • チェック頻度が増えることで想定通りのインフラ構成をキープできているかを担保できる

一つ目に関してはTerraformの利用という以前に、コード表現の前提といえますがセキュリティ観点として当然の注意点といえます。

次に、二つ目に関してはインフラ管理者の視点で考えると手法の統一化は、自分たちの想定内の構築に集約していくことと同義と考えることができます。想定内がわかればポリシーでチェックすべきポイントも絞ることが可能で、ポリシー開発のハードルを下げることにもつながっていきます。

そして、三つ目のようにポリシーチェックが当然のように実行される環境に慣れば、年数回の棚卸しか行っていないような環境とは比べ物にならないほどの新鮮なインフラ情報を持ち続けることが可能となります。

Terraformを使うと、作って終わりのIaCではなく、作った後も管理するIaCが実現可能です。
また、有償プランになると継続的な差分検知や、チームでの利用を可能にする権限管理などが追加され、
プロダクト利用されるようなインフラ環境についても品質を担保した管理を実現することが可能です。


終わりに

本記事で少しでもTerraformに興味を持っていただけますと幸いです。

この記事に関連する製品・サービス

この記事に関連する記事