TerraformでHelm Chart(nginx-ingress, cert-manager)をデプロイするコード例

# はじめに

[GKEにHelmでnginx-ingress, cert-managerを導入しアプリのデプロイ環境を構築するコマンド具体例](https://qiita.com/fukuyama012/items/a15c4ca7b4a1d45ad69b)
上記記事でコマンドライン実行による環境構築を行っていたが、今回Terraform化したので差分（主にHelm Chartに関連する部分）を説明する。

# 前提

* GCPにて固定IPリソース作成済み
* GKEクラスタ、ノードプール作成済み
* コマンドラインでクラスタ認証済み `gcloud container clusters get-credentials --zone asia-northeast1-a --project project-xxx clusters_xxx`
* コンソール環境変数 TF_VAR_project にGCPプロジェクト名設定済み
* terraform-state用のgcsバケット作成済み

[Terraformリソース部分の参考ブランチ](https://github.com/fukuyama012/cycle-reminder-infra/tree/qiita_example)（*下記とは少し構成と名称が違う*）


# Helm Chart環境をTerraform化
## Helm Chartインストール用のサービスアカウントを作成

```terraform:gke-commnn/main.tf
variable "project" {}

provider "google" {
  project = var.project
  region  = "asia-northeast1"
  zone    = "asia-northeast1-a"
}

terraform {
  backend "gcs" {
    bucket  = "my-terraform-state"
    prefix = "gke-common"
  }
}

resource "kubernetes_service_account" "tiller" {
  metadata {
    name = "tiller"
    namespace = "kube-system"
  }
}

resource "kubernetes_cluster_role_binding" "tiller" {
  metadata {
    name = "tiller"
  }
  role_ref {
    api_group = "rbac.authorization.k8s.io"
    kind = "ClusterRole"
    name = "cluster-admin"
  }
  subject {
    kind = "ServiceAccount"
    name = "tiller"
    namespace = "kube-system"
  }
  depends_on = [kubernetes_service_account.tiller]
}
```

```bash
% terraform init
% terraform plan
% terraform apply
```

## nginx-ingress

```terraform:nginx-ingress/main.tf
provider "helm" {
  service_account = "tiller"
}

terraform {
  backend "gcs" {
    bucket  = "my-terraform-state"
    prefix = "helm/nginx-ingress"
  }
}

data "helm_repository" "stable" {
  name = "stable"
  url  = "https://kubernetes-charts.storage.googleapis.com"
}

resource "helm_release" "nginx_ingress" {
  name      = "nginx-ingress"
  repository = data.helm_repository.stable.metadata[0].name
  chart     = "stable/nginx-ingress"
  namespace = "nginx-ingress"

  set {
    name = "rbac.create"
    value = true
  }

  set {
    name = "controller.publishService.enabled"
    value = true
  }
}

```

・nginx-ingressのリソース作成

```bash
% terraform init
% terraform plan
% terraform apply
```

・上記Terraform実行処理はnginx-ingress-controllerのserviceに固定IPを設定しないと正常完了しない[^1]

```bash
# 固定IP指定
% kubectl edit svc nginx-ingress-controller --namespace=nginx-ingress
# type: LoadBalancer の直下に下記を追加する
loadBalancerIP: "取得した固定IP"
```

作成されたnginx-ingress関連リソースにエラーが表示されていない事を確認する。

## cert-manager

・リソース作成前に設定投入しておく必要有り。[公式解説](https://hub.helm.sh/charts/jetstack/cert-manager/v0.10.1)

```bash
kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.10/deploy/manifests/00-crds.yaml
```

```terraform:cert-manager/main.tf
provider "helm" {
  service_account = "tiller"
}

terraform {
  backend "gcs" {
    bucket  = "my-terraform-state"
    prefix = "helm/cert-manager"
  }
}

data "helm_repository" "cert_manager" {
  name = "jetstack"
  url  = "https://charts.jetstack.io"
}

resource "helm_release" "cert_manager" {
  name      = "cert-manager"
  namespace = "cert-manager"
  repository = data.helm_repository.cert_manager.metadata[0].name
  chart = "cert-manager"
  version = "v0.10.1"
}
```

・cert-managerのリソース作成

```bash
% terraform init
% terraform plan
% terraform apply
```

cert-managerのリソースも正常に作成されていればOK。

[以前の記事](https://qiita.com/fukuyama012/items/a15c4ca7b4a1d45ad69b)を参考にDeployment、 Service、 Ingress、 ClusterIssuer、 Certificateのyamlを
`kubectl apply`してやればSSL接続のGKE環境が完成する。

# 参考

[Helm Provider](https://www.terraform.io/docs/providers/helm/index.html)
[helm_release](https://www.terraform.io/docs/providers/helm/release.html)
[GKEなどRBACが有効な環境でHelmを利用するには？](https://www.skyarch.net/blog/?p=16584)

[^1]: ここも出来ればコード化したいが方法が不明。。