terraform について

## はじめに

- みんな大好き terraform をさくっと教えることになったのでさっと説明する資料。
- クラウドやインフラにあまり明るくないとのことなのでイメージだけ。
- PlantUML の練習も兼ねてる。Qiita ネイティブで書けると楽なんだけど。[PlantUMLを書くツール](https://plantuml-editor.kkeisuke.com/#)

## 過去


一人でやってるうちは自己責任だしどうにでもなる。

- マネジメントコンソールを使う
- 再現性はない
- サンプルのCloudFormationやドキュメントの手順

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44420/8d499803-a193-58f0-2176-3f6da60b7bfc.png)

<details><summary>PlantUML コード</summary><div>

```uml
@startuml
actor UserA
UserA --> (Cloud)
@enduml
```

</div></details>


## 現在

複数人になると問題が出やすくなる。

- 俗人化
- 変更内容や日時が残らない（誰かの実施した変更がわからない）
- 元に戻すのが困難になる
- クラウド側も日々変更される
- 再現性に乏しい（似たようなのをもう１つ作って）
- セキュリティや機能面で複雑性が増す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44420/b0d46cc1-19fb-cca0-c039-9d4c0ef7a2eb.png)

<details><summary>PlantUML コード</summary><div>

```uml
@startuml
actor UserA
actor UserB
actor UserC
UserA --> (Cloud)
UserB --> (Cloud)
UserC --> (Cloud)
@enduml
```

</div></details>


## 未来

terraform により宣言的コードによるクラウドの抽象化が可能になった

- コード管理（git）によって変更内容の記録が取りやすくなる
- state の存在によってコードとリソースの差分が取得可能になる
- 定期的な更新への追従で安定してリソースの管理が可能になる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44420/0a26aefb-480c-d09e-a154-943e037217d4.png)

<details><summary>PlantUML コード</summary><div>

```uml
@startuml

actor UserA
actor UserB
actor UserC

database Git
database State

UserA --> [terraform]
UserB --> [terraform]
UserC --> [terraform]

Git -right- [terraform]
State -left- [terraform]

[terraform] --> (Cloud)

@enduml
```

</div></details>


## 大事なこと

- terraform (code) == state（状態） == クラウドリソース
- あるべき状態を管理することができる
- terraform が宣言的という理由であり、Pulumi や CDK/SDK/ベンダー提供のスタッキングツールとの違い
- 実際のリソースからコードにフィードバックすることで状態を維持することもできる（Ansible の宣言的とは異なる部分）
- Ansible は基本的に一方的であり、Ansible を使用して差分を取得してコード側を合わせるといった運用には向いていない
- CloudFormation 等のベンダー提供ツールによるロックインを避け、適度に抽象化することでコマンド差異を軽減させることができ、マルチクラウド展開等に有利であることも terraform を選定する理由のひとつ


## おまけ

- [terraform](https://www.terraform.io/) は [HashiCorp](https://www.hashicorp.com/) の製品
- [Golang で書かれている](https://github.com/hashicorp/terraform)
- [tfenv](https://github.com/tfutils/tfenv) を利用することで、複数バージョンに対応しやすくなる
- [direnv](https://github.com/direnv/direnv) を利用することで、環境別のクレデンシャルも管理しやすくなる
- [Ansible](https://github.com/ansible/ansible) とは棲み分けが大事
- [Twitter](https://twitter.com/terraform_jp) と [slack](https://t.co/rlNg75MmHK?amp=1) でユーザコミュニティやってるので活用してね（宣伝）


## 念のため

- Cloud 部分は AWS, GCP, Azure の他、terraform のプラグインの一部になる Provider が対応できればなんでもいい
- コード管理ができているからといっていつでもどうにでもロールバックできるとは限らない（不可逆な変更はたくさんある）
- pulumi は状態持ってるらしい？知らんけど
- Provider は各クラウドのAPIやSDKを利用しているので、常に最新の機能が使えるとは限らない

## おまけのおまけ

### Ansible

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44420/04fab394-90d2-92ef-5a3d-c0faa0d22968.png)

<details><summary>PlantUML コード</summary><div>

```uml
@startuml

actor UserA

database Git
database Config


Git -right- [Ansible]

UserA --> [Ansible]

Config -left- [Ansible]
note top of Config
  Inventory
  Playbook
  Role
endnote

[Ansible] --> (Host)

note right of Host
  常に上書きされて
  最新になる
endnote

@enduml

```

</div></details>

### Packer と Ansible

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44420/7f75d78c-0eeb-0d0d-5700-41d2b36b54f0.png)

<details><summary>PlantUML コード</summary><div>

```uml
@startuml

actor UserA

database Git

# あー、ツールが古くて frame 形状にならなかった
package PackerAnsible <<Frame>> {
  [Packer]
  [Ansible]
}

Git -- PackerAnsible

UserA --> PackerAnsible

Packer -> Ansible

PackerAnsible --> (AMI)

note right of AMI
  常に上書きされて
  最新になる
endnote

@enduml


```

</div></details>

[2018年にAnsible NightでLTした内容](https://docs.google.com/presentation/d/1yVjHN_35xPih3X3tlXgwpmxftLlCP8raC-i-1k5KJLc/edit?usp=sharing)