Open10

インフラをTerraformで一元管理する

LeivyLeivy

Terraform とは

Terraform とは、HashiCorp社が提供しているオープンソースの「Infrastructure as Code (IaC)」ツールです。インフラストラクチャ(サーバー、ネットワーク、ストレージ、DNSなど)をコードとして記述し、自動化と再現性を持って管理・デプロイすることができます。

https://www.terraform.io/

LeivyLeivy

開発環境の構築

今回は WSL2 + Ubuntu + DevContainer + Docker を使用して、開発環境を構築します。
Dockerイメージは公式のものがあるようなので、それを使用します。
Terraformのバージョンは最新のものを使用します。

最新のバージョンは以下から確認しましょう。

https://releases.hashicorp.com/terraform/

LeivyLeivy

AWS CLI v2とHashiCorp Terraform公式Dockerイメージの相性問題

AWS CLI v2はglibc環境が必要ですが、AlpineベースのTerraform公式Dockerイメージでは適切に構築できず、多くの課題がありました。その際に以下の記事を発見しました。

該当Issue


結論

Terraform公式イメージで環境を構築しようと試みましたが、AlpineベースのOSではglibcの依存関係などの問題が多く、最終的にDebian SlimUbuntuの選択に至りました。

TerraformやAWS CLIの使用頻度と公式ガイドの採用例を考慮した結果、Ubuntu 22.04を採用して環境を構築することにしました。

以下はそれぞれのファイルです。

Dockerfile

FROM ubuntu:22.04

# 環境変数
ENV LANG=ja_JP.UTF-8 \
    TF_VERSION=1.9.8 \
    AWS_CLI_URL=https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip \
    HADOLINT_VERSION=v2.12.0

# システムのアップデートと基本ツールのインストール
RUN apt-get update && \
    apt-get upgrade -y && \
    apt-get install -y --no-install-recommends \
        less \
        vim \
        curl \
        unzip \
        git \
        make \
        locales \
        ca-certificates \
        openssh-client && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# ロケールの設定
RUN locale-gen ${LANG} en_US.UTF-8 && \
    update-locale LANG=${LANG} && \
    update-ca-certificates

# AWS CLI v2 のインストール
WORKDIR /tmp/awscli
RUN curl --silent --show-error --fail "$AWS_CLI_URL" -o "awscliv2.zip" && \
    unzip -q awscliv2.zip && \
    ./aws/install && \
    rm -rf awscliv2.zip aws

# Terraform のインストール
WORKDIR /tmp/terraform
RUN curl --silent --show-error --fail -L "https://releases.hashicorp.com/terraform/${TF_VERSION}/terraform_${TF_VERSION}_linux_amd64.zip" -o "terraform.zip" && \
    unzip -q -d /usr/local/bin/ terraform.zip && \
    rm terraform.zip

# git-secrets のインストール
WORKDIR /tmp/git-secrets
RUN git clone https://github.com/awslabs/git-secrets.git . && \
    make install && \
    rm -rf /tmp/git-secrets

# hadolint のインストール
WORKDIR /tmp/hadolint
RUN curl --silent --show-error --fail -L "https://github.com/hadolint/hadolint/releases/download/${HADOLINT_VERSION}/hadolint-Linux-x86_64" -o /usr/local/bin/hadolint && \
    chmod +x /usr/local/bin/hadolint

# vscode ユーザー作成と初期設定
WORKDIR /workspace
RUN adduser --disabled-password --gecos "" vscode && \
    mkdir -p /home/vscode/.aws /workspace && \
    chown -R vscode:vscode /home/vscode /workspace

# 初期化スクリプトのコピー
COPY .docker/terraform/init.sh /usr/local/bin/init.sh
RUN chmod +x /usr/local/bin/init.sh

# 作業ディレクトリ設定
USER vscode
WORKDIR /workspace

# エントリーポイントの設定
ENTRYPOINT ["/usr/local/bin/init.sh"]

compose.yml

services:
    terraform:
        container_name: 'terraform'
        image: local/terraform
        build:
            context: .
            dockerfile: .docker/terraform/Dockerfile
        volumes:
            - .:/workspace
            - ./.docker/terraform/.aws/config.default:/home/vscode/.aws/config
            - ./.docker/terraform/.aws/credentials.default:/home/vscode/.aws/credentials
        environment:
            - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
            - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
        tty: true

init.sh

#!/bin/bash

# AWS Config の設定
if [[ ! -f /home/vscode/.aws/config ]]; then
    mv /home/vscode/.aws/config.default /home/vscode/.aws/config
fi

# AWS Credentials の設定
if [[ ! -f /home/vscode/.aws/credentials ]]; then
    mv /home/vscode/.aws/credentials.default /home/vscode/.aws/credentials
    sed -i "s/<access-key>/\${AWS_ACCESS_KEY_ID}/g" /home/vscode/.aws/credentials
    sed -i "s/<secret-key>/\${AWS_SECRET_ACCESS_KEY}/g" /home/vscode/.aws/credentials
fi

# シェルを起動
exec bash
LeivyLeivy

一括インポートできない

次のエラーが発生し、一括インポートができない問題に直面しました

aws error initializing resources in service accessanalyzer, err: operation error AccessAnalyzer: ListAnalyzers, failed to resolve service endpoint, an AWS region is required, but was not found

https://github.com/GoogleCloudPlatform/terraformer/issues/1590

そこで次のようにしてみたところインポート自体は成功した

$ terraformer import aws -r="ec2_instance,s3" --regions=ap-northeast-1

リージョンを明記するのも大事そう(明記しなかった場合s3が正しくインポートできなかった)

結論

いくつかのリソースで同時にインポートしようとするとエラーを吐くものがあったので、ひとつずつインポートすることにしました。

https://github.com/GoogleCloudPlatform/terraformer/blob/master/docs/aws.md

ただ、Cloud Mapのリソースがうまく取得できなかったので、これはterraform importコマンドでインポートしました

LeivyLeivy

インポートしたリソースの整理

以下を参考に整理していきます

https://qiita.com/YK0214/items/9e5975cc3cb50192719e

調査を進めると、どうやらterrraformerは銀の弾丸ではなかった模様・・・
結局インポートしたリソースを"使って"構築するという認識が正しいのかもしれない
そのままでは使えないですね

https://qiita.com/Kiyo_Karl2/items/0ef55620dbe507a793ac
https://developer.hashicorp.com/terraform/language/v1.1.x/upgrade-guides/1-0

さらに、terraformerでインポートすると Terraform 0.12 環境の tfstate になるため、Terraform 1.0 までアップグレードする必要があるようです

https://developers.cyberagent.co.jp/blog/archives/33331/

まずはインポートしたすべてのリソースのバージョンを、最新の1.9.8にアップグレードしていきます

tfenv を利用し適宜 Terraform のバージョンを変更していますが、下位ディレクトリに .terraform-version ファイルがある場合にはそのバージョンに引っ張られるため、.terraform-version を変更し、作業前に意図したバージョンになっているかを $ terraform version で確認することをオススメします。

0.12 -> 0.13

$ cd generated/aws/ec2_instance
$ tfenv use 0.13.7
$ terraform 0.13upgrade
$ terraform init
$ terraform plan
$ terraform apply

Warning で非推奨の書き方をしている場合があるのでそれを修正しましょう。

Warning: Interpolation-only expressions are deprecated
on outputs.tf line 6, in output "aws_instance_tfer--i-06ab3a2a9cffebacd_hoge_id":
6: value = "${aws_instance.tfer--i-06ab3a2a9cffebacd_hoge.id}"
これは
value = aws_instance.tfer--i-06ab3a2a9cffebacd_hoge.id
と書き換えるだけです。

なお、このエラーの修正作業には以下のGPTs等を活用しました
https://chatgpt.com/g/g-BGOjJYEsy-noterraform-expert

0.13 -> 0.14

$ tfenv use 0.14.11
$ terraform init
$ terraform plan
$ terraform apply

0.14 -> 1.9.8

$ tfenv use 1.9.8
$ terraform init
$ terraform plan
$ terraform apply

これで 0.12 から最新のバージョンへアップグレードできます。
ローカルにある tfstate の terraform_version が 1.9.8 になっているはずです。

続けて、以下を参考にリソースを一つずつterraformで構築していく

https://engineering.nifty.co.jp/blog/29177
https://speakerdeck.com/harukasakihara/besutona-terraform-deirekutorigou-cheng-wokao-cha-sitemita?slide=6
https://techblog.forgevision.com/entry/Terraform/directory