それなりに適当にやってます

なんとなくそれっぽいメモとか備忘録とか適当に。 2018年5月にブログ移転しました。 古い記事は未整理です。

Terraform + GCP をもう少しやってみる #2

前回の状態で、とりあえずGCP上にデプロイする方法はわかったので内容をもっと整理していく。

terraform workspace

ドキュメントは ここ、別ディレクトリを作成して provider.tfbackend.tf を再作成する。

$ mkdir ~/terraform-example2 ; cd $_
$ export GOOGLE_APPLICATION_CREDENTIALS='account.json'  #<-サービスアカウントのJSONを指定
$ vi provider.tf
$ vi backend.tf     #<-GCSバケットは前回と違う場所を指定
$ terraform init

この時点で workspace を確認すると default が使用されていることがわかる。

$ terraform workspace list
* default

試しに dev を作成し、環境が切り替わることを確認

$ terraform workspace new dev       #<- dev を作成
$ terraform workspace list          #<- 環境が dev に切り替わった事がわかる
  default
* dev
$ terraform workspace show
dev

続けて stagingproduction を作成してから、workspace を dev に戻して見てみる。

$ terraform workspace new staging
$ terraform workspace new production
$ terraform workspace select dev
$ terraform workspace show
dev

Cloud Storage 上にはそれぞれの .tfstate ファイルが作成されている。

$ gsutil ls gs://BACKET/DIRECTORY
gs://BACKET/DIRECTORY/default.tfstate
gs://BACKET/DIRECTORY/dev.tfstate
gs://BACKET/DIRECTORY/production.tfstate
gs://BACKET/DIRECTORY/staging.tfstate

workspace の利用

${terraform.workspace} という変数に workspace の値が入るので、これを利用してプロジェクトを切り替える事ができる。

provider "google" {
  project     = "example-${terraform.workspace}"
  region      = "asia-northeast1"
}

また ${terraform.workspace == "production" ? 3 : 1} のように特定の環境のみ大きくすることもできる。

前回の更新

前回の状態から更新してみる。ドキュメントによると変数は下記の方法で渡せる模様

  • コマンドラインフラグ
  • tfvars ファイルで読み込み
  • 環境変数 (string-type しか渡せない)
  • UI入力 (string-type しか渡せない)
  • tf ファイル内に記述

前の記事に書いた通り、ベストプラクティスといてはこの辺が参考になりそうだけど・・・

それなりに辛そう(;´∀`) とりあえず・・・

  • 前回のベタ書きから変更しそうな値だけ変数で渡すように修正
  • 用途別にモジュール化
  • GCPの場合プロジェクト毎にリソースグループを分けられるのでもう少しシンプルに

ってことをやってみた。

.
├── main.tf
├── variable.tf
└── module
    ├── cloudsql
    │   ├── main.tf
    │   └── variable.tf
    ├── http-proxy
    │   ├── main.tf
    │   └── variable.tf
    ├── instance-template
    │   ├── main.tf
    │   ├── output.tf
    │   └── variable.tf
    └── instance-group
        ├── main.tf
        ├── output.tf
        └── variable.tf

module/DIRECTORY 下の variable.tf には既定値を設定

variable "region"               { default = "asia-northeast1"}
...

main.tf からモジュールとして呼び出す際に、変更したい値を渡す事ができた。

module "cloudsql_users" {
  source = "./module/cloudsql"
  region = "${var.region}"
  ...
}

あと CloudSQL のユーザとかリストで渡してループさせて作るのは こちらを参考count, length, element などを使うことで実装できた。

resource "google_sql_user" "users" {
  depends_on = [
    "google_sql_database_instance.master"
  ]
  count    = "${length(var.database_users)}"
  name     = "${element(var.database_users, count.index)}"
  instance = "${google_sql_database_instance.master.name}"
  host     = "%"
  password = "${element(var.database_password, count.index)}"
}

モジュールからモジュールに渡したい値は output.tf で渡した。

output "instance_template_link" {
    value = "${google_compute_instance_template.instance_template.self_link}"
}

main.tf からモジュールを呼び出した際に output.tf の出力を受け取り、それを別のモジュールに渡す感じ。 受け取る側では空の変数 または デフォルト値 を宣言しとく。

variable instance_template_link {}
...
module "instange-group" {
  source                  = "./module/instance-group"
  instance_template_link  = "${module.instance-template.instance_template_link}"
  ...
}

とりあえず自分の使いたい用途ではこんな感じで、後は Map 使ったり、HTTPS Proxy対応とか、SSL証明書とかもしたいけど、とりあえず一旦満足かな。

次にやること

  • Terraform
    • ベストプラクティスTerraform Module RegistoryHashiCorp BestPractice に沿った構成・変数使うように修正
    • dev, std, prod で分ける #<-GCPだとプロジェクト毎に分けられるんだけど、この辺アプリ屋さんにも話を聞かないとわからない。
    • 新規VPCの作成からやる
      • ネットワークセグメントの設定
      • ファイアウォールルールの作成 (Health Check ほか)
    • HTTPS Proxy対応、証明書の更新とか
    • 整理してから GitHub に上げる
  • 非マネージドなインスタンス・グループの構成
  • その他 Terrafrom / GCP設定の追加・連携
    • Ansible 含む (SendGridの設定とかも)
  • Git, CI/CD と連携したコンテンツの配信・更新
  • Angular の講座の続き
  • PyQ の続き

以上