はじめに
CYBIRDエンジニア Advent Calendar 20171日目担当の@ntrvです。
CYBIRDでは女性向け恋愛ゲームのサーバ運用・インフラ改善を担当しております。
新卒2年目のGolangでうまいことやりたいと思っているエンジニアです。
最近AWSのRe:inventを連続徹夜で見ていてものすごく眠いです...
ということで, 今年もアドベントカレンダーを開催いたします!
Terraformとは?
- Terraformとはインフラ構築をコード化することのできるツールです。
- CYBIRDではAWSを使用した, 割と最近のタイトルで使用しております。
運用して困ったケース
- ここでは実際に運用しているタイトルでTerraformを使用したタイトルで実際に困った事例を紹介していきたいと思います。
- 手動で追加したセキュリティグループをTerraformに後から追加するとき
- ELB配下のEC2インスタンス(サービス中)のインスタンスタイプを変更したいとき
運用上困ったケース その1
やりたいこと
- 取り急ぎセキュリティグループを手動で追加し, ALBにattachした。
- 手動で追加したセキュリティグループを後からTerraform管理下におきたい。
実施したこと
-
terraform import
を行い, 既存のリソースを.tfstate
に取り込むことを考えた。terraform import module.fuga.aws_security_group.https_hoge sg-1234abcd
- その後,
terraform plan
で差分がなくなるまで*.tf
に書いていく。
困ったこと
理想
- 以下のように
*.tf
に記述できることを望んでいた。- 既存のコードと書きっぷりが変わらないようにしたかった。
-
terraform import
を行うことでaws_security_group.https_hoge
だけが.tfstate
に追加されるものだと考えていた。
resource "aws_security_group" "https_hoge" {
name = "${var.env}-${var.app_name}-HTTPSFromHoge"
description = "Allow HTTPS From Hoge"
vpc_id = "${var.vpc_id}"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = [
"8.8.8.8/32",
"8.8.8.4/32",
]
}
egress {
from_port = 0
to_port = 0
protocol = -1
cidr_blocks = ["0.0.0.0/0"]
}
}
現実
- 実際には以下のように記述する必要がありました。
- セキュリティグループを記述する方法として二通り存在するため。
-
aws_security_group
+aws_security_group_rule
を使用する方法 <- こちらに合わせて書く必要があった。 -
aws_security_group
にインラインで記述する方法
-
- セキュリティグループを記述する方法として二通り存在するため。
-
aws_security_group_rule
に関しては自由な名前を付けることが出来なかった。- 今回は
aws_security_group.https_hoge
の"https_hoge"から連想されてか"aws_security_group_rule.https_hoge-1
と名付けられている。
- 今回は
## 現実
resource "aws_security_group" "https_hoge" {
name = "${var.env}-${var.app_name}-HTTPSFromHoge"
description = "Allow HTTPS From HOGE"
vpc_id = "${var.vpc_id}"
}
resource "aws_security_group_rule" "https_hoge" {
type = "ingress"
from_port = 443
to_port = 443
protocol = "tcp"
security_group_id = "${aws_security_group.hoge.id}"
cidr_blocks = [
"8.8.8.8/32",
"8.8.8.4/32",
]
}
resource "aws_security_group_rule" "https_hoge-1" {
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
security_group_id = "${aws_security_group.hoge.id}"
cidr_blocks = [
"0.0.0.0/0",
]
}
どのようにすればよいか
- 急ぎの場合以外はTerraform管理下のリソースに直接変更を加えない。
-
terraform import
を極力行わないようにする。
-
運用上困ったケース その2
やりたいこと
ELB配下のEC2インスタンスのインスタンスタイプを"安全に"変更したい場合, 手動によるオペレーションでは以下のように必要があります。
- ALBからdetachする
- アクセスログを確認し, 完全に切り離されたことを確認し電源を落とす
- インスタンスタイプを変更し電源をあげる
- ALBにattachする
この手順をTerraform管理下で実施する場合, 以下のような方法が考えられます。
- 手動で上記手順を実施し, 後からTerraformを修正する...①
- ELBへのattachmentはTerraform管理下に置かないようにし, 他はTerraformにまかせる...②
困ったこと
- 今まで(Terraform v0.8.5)は①の方法で実施しておりました。
- しかしTerraform v0.10.4で同じ方法を実施したところ, リソース再作成のplanが表示されました。。
- その後v0.10.7で検証しましたが, 再現しなかった... 今後詳しく調査する予定です。
- しかしTerraform v0.10.4で同じ方法を実施したところ, リソース再作成のplanが表示されました。。
Terraform管理下で実施する方法
- そもそもTerraformで管理しているリソースに手を加えること自体危険であったので, ②の方針にしようかと考えております。
- Terraform v0.8.8からはインスタンスタイプ変更時にリソース再作成ではなく, 再起動してくれるようになりました。
-
provider/aws: Allow aws_instances to be resized rather than forcing a new instance
(#11998)
-
- Terraform v0.8.8からはインスタンスタイプ変更時にリソース再作成ではなく, 再起動してくれるようになりました。
②の方法を採用すると実際の手順は以下のようになります。
- ALBからdetachする
- アクセスログを確認し, 完全に切り離されたことを確認する
- あらかじめ変更しておいた
*.tf
を使用しterraform apply
を実行する - インスタンスタイプが変更され再起動されているので, ALBに手動でattachする
得られた教訓
-
terraform import
を多用すると, コードがカオスなことになってくる。- 緊急時以外はterraform管理下のリソースに手動で変更しない。
-
terraform import
で間違えたときに切り戻しできるように, backendのversioningの機能はONにしておく。
- 運用することを考えて, Terraformを使用する
- 何でもTerraformに落とし込んでしまうと, 運用時に困るものこともある。
-
ignore_changes
を有効利用する。
- Terraformで管理しているリソースに手動で変更を行うことは基本的にしない。
- Terraformで保持している状態と実際の状態が乖離していく。
- 後からTerraform側の修正で対応すると大変なことになる。
その他主張したいこと
- とにかく
terraform plan
は絶対必須!!- TerraformがどのようにAPIを叩くのかを見ることができるため。
- あくまで
terraform
の立てた実行計画なので,apply
時に失敗することはありますが..
- 安全にTerraformを実行できる環境づくりは必要!!
- RDS等消えると困るリソースは
lifecycle.prevent_destroy
でリソース再作成時にエラーとなるようにする。 - State Lockingで
terraform apply
を同時実行されることを防止する。 -
terraform plan
時に生成される.tfplan
をterraform apply
に渡す。 -
terraform apply
はCircle CIやJenkins上から実行する。 - tfenvを使用し, Terraformのバージョンをリポジトリごとに固定する。
- RDS等消えると困るリソースは
感想
- Terraformは難しい...(おざなりな感想)
最後に
CYBIRDエンジニア Advent Calendar 2017 明日は、 @masatoshiitoh の「TCPサーバーを書いてみよう」です!
私のデスクの隣にいる方で, 社内一の超テッキーではないかと噂になっている方です。楽しみですね!