既存インフラをコード化する時に気を付けること
概要
昨年の12月から社内のAWSインフラシステムをコード管理(IaC=Infrastructure as Code)しようという動きが始まりました。
新規リソースをTerraformやAWS CDKなどを活用してコード化する事例は数多く紹介されていましたが、意外と既存インフラをコード化する方法については数が少なく結構大変なことがありました。
この記事では私が直面した既存インフラのコード化でハマった点について紹介していきます。
背景
2020年まで社内のインフラチームは2人しかおらず、うち1人はマネージャーで基本的にビジネス職とのコミュニケーションがメインだったため実質1人でインフラ構築や運用、新規メディアサーバーの作成を担当していました。
1人で検証環境のEC2インスタンス含め数百台のサーバーを運用管理、新規メディアのサーバーを構築していました。
当然時間も足りず、スピードを優先してAWSコンソール画面からの操作でリソース構築していました。
昨年から人数も増え、新しいマネージャーがジョインされたことでチームとして体制が整いサーバー構築従来よりも早く作れるようになったことからIaCに取り組もうということになりました。
マネージャーからはチームに適したIaCツールの選定と運用方法について考えてほしいと頼まれましたので、12月は各種ツールの技術選定と検証を行ないました。
技術選定調査
まずはAWSリソースをIaCする場合どんなツールが使われているのか調べてみました。
そのなかで以下のツールが他社事例や日本語記事も多くありましたので、学習コストの敷居の低さからこの3つの中から検証してみました。
- AWS CloudFormation
- AWS CDK
- Terraform
また選定基準としては、既存リソースをコード化する場合の難易度、コードの可読性、将来的な運用の拡張性をポイントにしました。
将来的な運用の拡張性ですが、今後Git上にCI/CD環境基盤に構成管理ツールを実装して、git push
したら自動デプロイされて、インフラリソースが更新されるようになるようにしたいと考えていました。
AWS CloudFormation
ただ既存リソースをインポートする場合、事前にリソースに合ったテンプレートファイルを用意しなければいけないということがあり、既存リソースのコード化には難しいと感じました。
AWS CDK
2022年1月現在は以下のプログラミング言語が対応されています。
- JavaScript
- TypeScript
- Python
- Java
- C#
- Go(preview)
ただチームで対応されている言語を扱ったことのあるメンバーが少なく、私自身もプログラミングがあまり得意ではなかったので、AWS CDKを使ってIaCを行なうことは断念しました。
またAWS CDKには既存リソースをインポートする機能がなく、OSSのformer2を使えば実現できますが、L1 Constructという抽象度の低いコードが生成されてしまうため、CDKの恩恵が受けづらいと感じました。[1]
(あと、生成されるコードが1系でそのままcdk
コマンドを実行すると失敗したのですが、あまりPythonに詳しくない私では原因がわからなかったこともあります)
AWS CDKには下記の日本語のワークショップも用意されていて、少ない記述で簡単にAWSリソースを構築できたのは感動しましたので、後述のCDK for Terraformで再挑戦してみたいと思います。
Terraform
Terraformにはimport
サブコマンドを使って既存リソースのインポートができます。
ただimport
コマンドはEC2やVPC、RDSなど複数のリソースをまとめてインポートできないため、対象リソースの数が多いと辛くなるという問題がありました。
そこでterraformerというOSSを使って、既存リソースをインポートするようにしました。
また個人的な感想ですが、CloudFormationのテンプレートファイル形式であるYAML形式よりもTerraform独自のHCL形式で書かれたTerraformファイルのほうが読みやすいかなと思いました。
将来的な運用の拡張性でもGitHub ActionsとTerraformを使ったCI/CD環境基盤の構築は可能であることは以前私が書いた記事でも検証済みですので期待が持てると思いました。
もう1つ面白そうだと思ったのが、CDK for TerraformというCDKを使ってTerraformを実行できる機能です。 まだベータ版ですので本番運用するのは難しそうですが、これがGAされればTerraformからAWS CDKへの移行も容易になるのかなと思います。
ハマった点
ただそれでも既存リソースでハマった点が出てきましたので、その部分について紹介します。
Terraformとterraformerのバージョン差異
$ terraform --version
Terraform v1.1.3
on linux_amd64
$ cat terraform.tfstate | jq -r '. | { terroform_version: .terraform_version }'
{
"terroform_version": "0.12.31"
}
Terraformは.tfstate
というインフラリソース構成情報を保存するファイルを基にインフラリソースをIaC化しますが、terraformerで既存リソースインポート時に生成される.tfstate
ファイルはバージョンが0.12系と古いものが生成されます。
このままterraform init
を実行してもバージョンコンフリクトによるエラーが出てしまい、Terraformが実行できません。
$ terraform init
Initializing the backend...
╷
│ Error: Invalid legacy provider address
│
│ This configuration or its associated state refers to the unqualified provider "aws".
│
│ You must complete the Terraform 0.13 upgrade process before upgrading to later versions.
解決方法としてはTerraformのバージョン管理ツールのtfenvで端末のTerraformバージョンを0.12系に変更するか、terraformerのtfstateファイルのバージョンをアップグレードする方法があります。
私はtfstateファイルのTerraformのバージョンを1系にするほうを選択しました。
詳しい手順はサイバーエージェントさんのテックブログが参考になるかと思います↓
importできないAWSリソース
terraformerですが全部のAWSリソースをインポートできるわけではなく、terraformer import aws list
で一覧にあるリソースのみインポートできます。
$ terraformer import aws list
accessanalyzer
acm
alb
api_gateway
appsync
auto_scaling
batch
budgets
cloud9
cloudformation
cloudfront
cloudhsm
cloudtrail
cloudwatch
codebuild
codecommit
codedeploy
codepipeline
cognito
config
customer_gateway
datapipeline
devicefarm
docdb
dynamodb
ebs #EBSについて注目
ec2_instance
ecr
ecrpublic
ecs
efs
eip
eks
elastic_beanstalk
elasticache
elb
emr
eni
es
firehose
glue
iam
igw
iot
kinesis
kms
lambda
logs
media_package
media_store
msk
nacl
nat
opsworks
organization
qldb
rds
resourcegroups
route53
route_table
s3
secretsmanager
securityhub
servicecatalog
ses
sfn
sg
sns
sqs
ssm
subnet
swf
transit_gateway
vpc
vpc_peering
vpn_connection
vpn_gateway
waf
waf_regional
workspaces
xray
すべてのAWSリソースに対応していないとはいえ主要なAWSリソースは一通りそろっており今回のケースでは問題ないかと思いました。
ただなぜかEBSはリストにあるにも関わらず、インポートができませんでした。
$ terraformer import aws -r ebs
2022/01/16 14:25:57 aws importing default region
2022/01/16 14:25:59 aws importing... ebs
2022/01/16 14:25:59 aws done importing ebs
2022/01/16 14:25:59 Number of resources for service ebs: 0 #インポートされず
2022/01/16 14:25:59 aws Connecting....
2022/01/16 14:25:59 aws save ebs
2022/01/16 14:25:59 aws save tfstate for ebs
マネージャーにも相談しましたが現状EBSに関しては直接手でtfファイルを書いてコード化しようと考えています。
所感
既存リソースをIaC化することは思ったよりも難しいということがわかりました。
AWSも既存リソースを簡単にインポートしてくれるツールがまだ提供されていないことから、既存リソースの難しさは最初からコード化するよりも大変ということがわかります。
今年前半期は主要サービス部分をTerraformでコード管理して、後半期に全リソースをIaC化してチーム内にIaC運用を広めることを目標に今年1年頑張っていきたいと思います。
LT資料
LTのスライド資料です。
英語記事
英訳しました。
参考文献
Discussion