---
# System prepended metadata

title: Terraform

---

# Terraform

Terraform 用來實現 Infrastructure as Code，支援各大平台，包括了 AWS、Azure 等等，可以透過一些設定檔來快速部署、維護多個環境。

> _Testing、Staging、Production，各種環境是要架幾次？_

明明經常 Testing 好好的，但一上 Production 就炸，通常就是因為環境不一致在雷，雖然還有可能是其他因素，但透過 IaC 的方式，就可以將環境不一致的因素排除。

> _前人到底改了啥鬼？_

IaC 通常所有的變更都會上到 GitLab，紀錄每一次的變化，所以可以透過 History 看到過往的修改，修改時也能讓大家看到這次的變更內容。

> _我有很多事要忙..._

Infrastructure 丟給 Terraform 幫忙做，只需要寫一次 Code，省去原先要開機器、進機器設定等繁瑣的步驟，Terraform 大大幫你做，讓你可以去做其他更需要你的事情。

> _下了這個 command 會不會炸？_

Terraform 可以透過 CI 進行自動化測試，會檢查相容性等等，就不用擔心這次變更會不會把 Production 給炸了。

## Provider

提供服務的大大，可以在這裡給予 `access_key` 、 `secret_key` 等，但 credentials 寫在這的確不太妥，會更建議透過 Environment Variables 來給予。否則上到 GitLab 不就全家看光光了嗎 :joy: 

```json
provider "aws" {
  region     = "ap-northeast-1"
  access_key = "my-access-key"
  secret_key = "my-secret-key"
}
```

 ↓
 
```json
provider "aws" {}
```

```shell
$ export AWS_ACCESS_KEY_ID="anaccesskey"
$ export AWS_SECRET_ACCESS_KEY="asecretkey"
$ export AWS_DEFAULT_REGION="ap-northeast-1"
```

 ↓ 如果有需要不同 credential 的需求，也可以透過 credentials file 來給予。
 
```json
provider "aws" {
  region                  = "ap-northeast-1"
  shared_credentials_file = "/Users/tf_user/.aws/creds"
  profile                 = "customprofile"
}
```

## State

記錄 Terraform 的資訊們，會根據 state 來判斷 resource 的現況，以決定會有什麼樣的變更等等。

這份檔案會放在 local 端，但通常團隊維運會將 state 透過 backends 來儲存。

```shell
$ cat terraform.tfstate
{
  "version": 4,
  "terraform_version": "0.13.0",
  "serial": 9,
  "lineage": "a3335a54-a201-2636-1627-0f0cff925baa",
  "outputs": {},
  "resources": [
    {
      "mode": "managed",
      "type": "aws_instance",
      "name": "test",
      "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
      ...
    }
  ]
}
```

## Backends

S3

## Security Group

控制特定的 IP、Port 能不能進出，可以把他當成簡單的防火牆。Security group 本身是免費的，但網路本身要收錢，所以好的 Security group 可以降低不當的網路流量的費用。