GCP Config Connector を Terraform で設定してみた

# はじめに
Config Connectorを試そうとしたけど、インストール手順がめちゃくちゃ長い！！と思ったのは僕だけでしょうか笑
Terraformでサクっと最小構成でConfig Connectorを設定しようと思います。
基本的に公式の手順をTerraform化しただけとなります。
[Config Connector のインストール、アップグレード、アンインストール](https://cloud.google.com/config-connector/docs/how-to/install-upgrade-uninstall?hl=ja)
コード↓
https://github.com/ezio1119/config-connector-terraform


# 必要なもの
Terraform
Cloud SDK
Kubectl
# Config Connector のインストール
Config Connector のインストールには4つの選択肢がありますが、今回は一番簡単なアドオンを使用してインストールしたいと思います。

[インストール タイプの選択](https://cloud.google.com/config-connector/docs/how-to/install-upgrade-uninstall?hl=ja#installing_kcc)


>・Workload Identity（ベータ版）で Config Connector アドオンを使用してインストールする

## Terraform初期設定
Config Connector はベータ版なのでgoogle-betaもterraform initします。

```terraform
variable "project" {
  description = "自分のプロジェクトID"
  type        = string
  default     = "sample"
}

provider "google" {
  project = var.project
}

provider "google-beta" {
  project = var.project
}
```
今回使うAPIも予め有効にしときます(手動でやるよって人は飛ばしてください)。

```terraform
locals {
  services = [
    "cloudresourcemanager.googleapis.com",
    "iam.googleapis.com",
    "compute.googleapis.com",
    "container.googleapis.com",
  ]
}

resource "google_project_service" "sample" {
  for_each = toset(local.services)
  service  = each.value

  disable_dependent_services = true
}
```
## クラスタとノードを作成
Config Connector を使えるようにクラスタを設定します。
Config Connector のアドオンを追加し、Workload Identityを設定します。

```terraform
resource "google_container_cluster" "sample_cluster" {
  provider = google-beta
  name     = "sample-cluster"

  location                 = "us-central1"
  remove_default_node_pool = true
  initial_node_count       = 1

  master_auth {
    username = ""
    password = ""

    client_certificate_config {
      issue_client_certificate = false
    }
  }

  # Config Connectorが対応してるバージョンならなんでもおk
  release_channel {
    channel = "REGULAR"
  }

  # Config Connectorのアドオンを追加
  addons_config {
    config_connector_config {
      enabled = true
    }
  }

  #  Workload Identityの設定
  workload_identity_config {
    identity_namespace = "${var.project}.svc.id.goog"
  }
}

resource "google_container_node_pool" "sample_nodes" {
  name       = "sample-node-pool"
  location   = "us-central1"
  cluster    = google_container_cluster.sample_cluster.name
  node_count = 1

  node_config {
    preemptible  = true
    machine_type = "g1-small"

    metadata = {
      disable-legacy-endpoints = "true"
    }

    oauth_scopes = [
      "https://www.googleapis.com/auth/logging.write",
      "https://www.googleapis.com/auth/monitoring",
    ]
  }
}
```

## Config Connector を設定する
まず Config Connector の Operator をインストールします。
作ったGKEクラスタにapplyします。

```yaml
apiVersion: core.cnrm.cloud.google.com/v1beta1
kind: ConfigConnector
metadata:
  name: configconnector.core.cnrm.cloud.google.com
```
#### Config Connector 用のGCPサービスアカウントを作成
k8sサービスアカウントとGCPサービスアカウントを連携することで、k8sの世界でGCPを操れるようになります。
つまり、このGCPサービスアカウントに与える権限が、[Config Connector リソース](https://cloud.google.com/config-connector/docs/reference/overview?hl=ja) を作成する際に使用する権限になります。

```terraform
locals {
  sample_config_connector_roles = [
    "roles/editor",
    # プロジェクトレベルのポリシーを設定する場合必要
    # "roles/iam.securityAdmin",
  ]
}

resource "google_service_account" "sample_config_connector_account" {
  account_id   = "sample-config-conn-account"
  display_name = "Sample Config Connector Account."
}

resource "google_project_iam_member" "sample_config_connector_iam" {
  for_each = toset(local.sample_config_connector_roles)
  role     = each.value
  member   = "serviceAccount:${google_service_account.sample_config_connector_account.email}"
}
```
#### ConfigConnectorContextを作成
次に 任意の k8s Namespace に ConfigConnectorContext を作成します。
そのNamespaceにデプロイされたConfig Connector リソースを監視し、GCPリソースを作成するようになります。
今回は Default Namespaceに Config Connector リソースをデプロイするのでNamespaceは指定しません。
spec.googleServiceAccount には、先程作成したGCPサービスアカウントを指定します。
これをapplyすると、Config Connector のk8sサービスアカウントが作成されます。

```yaml
apiVersion: core.cnrm.cloud.google.com/v1beta1
kind: ConfigConnectorContext
metadata:
  name: configconnectorcontext.core.cnrm.cloud.google.com
  # 今回はDefault
  # namespace:
spec:
  # Config Connector用に作ったGCPサービスアカウントのメールアドレス
  googleServiceAccount: "sample-config-conn-account@sample-282907.iam.gserviceaccount.com"

```
#### k8sサービスアカウントをGCPサービスアカウントにバインドする
Workload Identityによって、k8sサービスアカウントとGCPサービスアカウントを連携させ、k8sサービスアカウントがGCPサービスアカウントの役割を持つように設定します。

```terraform
variable "k8s_namespace" {
  description = "ConfigConnectorContextを作成したNamespace"
  type        = string
  default     = "default"
}

resource "google_service_account_iam_member" "sample_config_connector_bind" {
  service_account_id = google_service_account.sample_config_connector_account.name
  role               = "roles/iam.workloadIdentityUser"

  member = "serviceAccount:${var.project}.svc.id.goog[cnrm-system/cnrm-controller-manager-${var.k8s_namespace}]"
}
```
#### リソースを作成する場所を指定する
Namespaceにアノテーションし、GCPリソースを作成する場所を指定します。
今回はプロジェクト内にGCPリソースを作成するように、default Namespaceにアノテーションします。

```terminal
kubectl annotate namespace \
default cnrm.cloud.google.com/project-id=sample
```
以上で、Config Connectorを設定できたかと思います。

# おわりに
最後まで見ていただきありがとうございました！
最小構成でやってみましたが、結構長いしややこしいですよね。。
[Config Connector リソース](https://cloud.google.com/config-connector/docs/reference/overview?hl=ja) に一覧があるのでいろいろ試してみてください〜