Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
35
Help us understand the problem. What is going on with this article?

More than 1 year has passed since last update.

@takasp

Terraform で GKE を構築する

はじめに

GKE を構築する際、実際に適用されている設定を管理したいので Terraform を使って GKE を構築していきます。
Terraform には Module として GKE が提供されていますが、今回は素の Terraform で構築していきます。

本記事の作成に当たって JapanContainerDays v18.12 で企画された「showKs」の Terraform のリポジトリが非常に参考になりました。
ありがとうございます。

GitHub - containerdaysjp/showks-terraform: Terraform configurations to provision showk environments.

他にもクラウドネイティブな要素の詰まったリポジトリがあるので非常に参考になると思います。

Japan Container Days · GitHub

それでは、Teraform を使って GKE の構築と Guestbook アプリケーションをデプロイして動作確認までを試してみます。

環境

  • macOS High Sierra Version 10.13.6
  • Terraform v0.11.13
  • Homebrew 2.0.6
  • Google Cloud SDK 240.0.0

Google Cloud SDK をインストールする

以下のドキュメントを参考に Google Cloud SDK をインストールし、プロジェクトの設定をしてください。
Google Cloud SDK documentation

API を有効にする

以下の API を有効にします。

  • Kubernetes Engine API

以下のコマンドで API を有効にします。

$ gcloud services enable \
    container.googleapis.com

Terraform のインストール

Terraform をインストールします。
今回は Mac 環境なので、Homebrew でインストールしていきます。

$ brew install terraform

Terraform のサービスアカウントを作成する

Terraform が使用するサービスアカウントを作成します。

$ GCP_PROJECT=$(gcloud info --format='value(config.project)')
$ TERRAFORM_SA=terraform-service-account

$ gcloud iam service-accounts create $TERRAFORM_SA \
    --project=$GCP_PROJECT \
    --display-name $TERRAFORM_SA

作成した Terraform のサービスアカウントに以下のロールを付与します。

  • roles/iam.serviceAccountUser
  • roles/compute.admin
  • roles/storage.admin
  • roles/container.clusterAdmin
$ TERRAFORM_SA_EMAIL=$(gcloud iam service-accounts list \
    --project=$GCP_PROJECT \
    --filter="displayName:$TERRAFORM_SA" \
    --format='value(email)')

$ gcloud projects add-iam-policy-binding $GCP_PROJECT \
    --role roles/iam.serviceAccountUser \
    --member serviceAccount:$TERRAFORM_SA_EMAIL

$ gcloud projects add-iam-policy-binding $GCP_PROJECT \
    --role roles/compute.admin \
    --member serviceAccount:$TERRAFORM_SA_EMAIL

$ gcloud projects add-iam-policy-binding $GCP_PROJECT \
    --role roles/storage.admin \
    --member serviceAccount:$TERRAFORM_SA_EMAIL

$ gcloud projects add-iam-policy-binding $GCP_PROJECT \
    --role roles/container.clusterAdmin \
    --member serviceAccount:$TERRAFORM_SA_EMAIL

.tfstate ファイルを管理する Google Cloud Storage のバケットを作成する

Terraform では、管理しているリソース状態を .tfstate という拡張子を持つファイルに管理します。
デフォルトではローカルに保存されますが、共有できないためリモートに管理します。
今回は、Google Cloud Storage(GCS)をリモート先として .tfstate を管理するため GCS バケットを作成します。
バケット名は、GCS 全体で一意である必要があることに注意してください。
サンプルとして tf-state-prod という名前で作成しています。

$ GCS_CLASS=multi_regional
$ GCS_BUCKET=tf-state-prod

$ gsutil mb -p $GCP_PROJECT -c $GCS_CLASS -l asia gs://$GCS_BUCKET/

.tf ファイルを作成する

変数を定義する

各リソースで必要な変数を定義する variables.tf ファイルを作成します。
GKE のバージョンは、執筆時点(2019/03)の最新 1.12.6-gke.7 を使用します。

variables.tf
variable "project" {}

variable "cluster_name" {
  default = "cluster"
}

variable "location" {
  default = "asia-northeast1-a"
}

variable "network" {
  default = "default"
}

variable "primary_node_count" {
  default = "3"
}

variable "machine_type" {
  default = "n1-standard-1"
}

variable "min_master_version" {
  default = "1.12.6-gke.7"
}

variable "node_version" {
  default = "1.12.6-gke.7"
}

GCP のプロバイダ情報を定義する

GCP のプロバイダを利用するに当たって provider.tf ファイルを作成します。

provider.tf
provider "google" {
  project = "${var.project}"
  region  = "${var.location}"
}

Backend を定義する

.tfstate ファイルを管理するための Backend を定義する backend.tf ファイルを作成します。
今回は、GCS を Backend に利用します。
バケット名は、事前に作成した GCS バケット名を指定します。

backend.tf
terraform {
  backend "gcs" {
    bucket = "tf-state-prod"
    prefix = "terraform/state"
  }
}

GKE を定義する

GKE を定義するための gke.tf ファイルを作成します。

gke.tf
resource "google_container_cluster" "primary" {
  name     = "primary-${var.cluster_name}"
  location = "${var.location}"

  remove_default_node_pool = true
  initial_node_count       = 1

  network = "${var.network}"

  min_master_version = "${var.min_master_version}"
  node_version       = "${var.node_version}"

  master_auth {
    username = ""
    password = ""

    client_certificate_config {
      issue_client_certificate = false
    }
  }
}

resource "google_container_node_pool" "primary_nodes" {
  name       = "primary-${var.cluster_name}-nodes"
  location   = "${var.location}"
  cluster    = "${google_container_cluster.primary.name}"
  node_count = "${var.primary_node_count}"

  management {
    auto_repair = true
  }

  node_config {
    oauth_scopes = [
      "https://www.googleapis.com/auth/devstorage.read_only",
      "https://www.googleapis.com/auth/logging.write",
      "https://www.googleapis.com/auth/monitoring",
      "https://www.googleapis.com/auth/service.management.readonly",
      "https://www.googleapis.com/auth/servicecontrol",
      "https://www.googleapis.com/auth/trace.append",
    ]

    machine_type = "${var.machine_type}"

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

GKE 作成

Terraform のサービスアカウントの json ファイルを作成します。

$ TERRAFORM_SA_DEST=~/.gcp/terraform-service-account.json

$ mkdir -p $(dirname $TERRAFORM_SA_DEST)

$ TERRAFORM_SA_EMAIL=$(gcloud iam service-accounts list \
    --filter="displayName:$TERRAFORM_SA" \
    --format='value(email)')

$ gcloud iam service-accounts keys create $TERRAFORM_SA_DEST \
    --iam-account $TERRAFORM_SA_EMAIL

作成したサービスアカウントの json ファイルのパスを GOOGLE_APPLICATION_CREDENTIALS の環境変数にセットします。

$ export GOOGLE_APPLICATION_CREDENTIALS=$TERRAFORM_SA_DEST

Terraform の設定を元に初期セットアップを行います。
この時点で .tfstate ファイルが GCS に展開されます。

$ terraform init

GKE を作成する前に variables.tf ファイルで default 値を定義していない値を環境変数にセットします。
default 値を定義していない変数はコマンドライン引数や terraform.tfvars ファイルから渡すことも可能です。
環境変数の場合は、変数名の prefix に TF_VAR_ が必要です。

$ export TF_VAR_project=$GCP_PROJECT

まずは、terraform plan コマンドで変更内容の確認をします。

$ terraform plan

問題なければ terraform apply コマンドで GKE を作成します。
yes で実行します。

$ terraform apply

Guestbook アプリケーションをデプロイして確認する

Terraform で作成した GKE に対して以下のリポジトリに存在する Guestbook アプリケーションをデプロイします。
GitHub - kubernetes/examples: Kubernetes application example tutorials

デプロイする前に作成した GKE クラスタの認証情報を取得します。

$ gcloud container clusters get-credentials primary-cluster

Redis master をセットアップする

Guestbook アプリケーションは Redis を使用しています。
Redis master にデータを書き込み、Redis worker からデータを読み込む構成です。

Redis master のデプロイ

Redis master をデプロイします。

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook/redis-master-deployment.yaml

作成した Pod が 1/1 Running になるまで待機します。

$ kubectl get po
NAME                            READY   STATUS              RESTARTS   AGE
redis-master-57fc67768d-75dlf   1/1     Running             0          22s

表示した Pod 名から Redis master のログが表示されていることを確認します。

$ kubectl logs -f redis-master-57fc67768d-75dlf

Redis master のサービスを作成

Redis master のサービスを作成します。

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook/redis-master-service.yaml

Redis master のサービスが作成されたことを確認します。

$ kubectl get svc
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes     ClusterIP   10.55.240.1     <none>        443/TCP    22m
redis-master   ClusterIP   10.55.245.172   <none>        6379/TCP   52s

Redis worker をセットアップする

Redis worker は、複数のレプリカを作成し可用性を高めています。

Redis worker のデプロイ

Redis worker をデプロイします。

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook/redis-slave-deployment.yaml

作成した Pod が 1/1 Running になるまで待機します。

$ kubectl get po
NAME                            READY   STATUS    RESTARTS   AGE
redis-master-57fc67768d-75dlf   1/1     Running   0          15m
redis-slave-57f9f8db74-fx2d7    1/1     Running   0          14s
redis-slave-57f9f8db74-gwmgk    1/1     Running   0          14s

Redis worker のサービスを作成

Redis master のサービスを作成します。

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook/redis-slave-service.yaml

Redis master のサービスが作成されたことを確認します。

$ kubectl get svc
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes     ClusterIP   10.55.240.1     <none>        443/TCP    28m
redis-master   ClusterIP   10.55.245.172   <none>        6379/TCP   6m41s
redis-slave    ClusterIP   10.55.255.148   <none>        6379/TCP   12s

Guestbook のフロントエンドアプリケーションをセットアップする

Guestbook のウェブサーバーを起動します。
フロントエンドは、PHP でできたアプリケーションです。
読み書きに応じて Redis master や Redis worker と通信します。

フロントエンドアプリケーションのデプロイ

フロントエンドアプリケーションをデプロイします。

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook/frontend-deployment.yaml

作成した Pod が 1/1 Running になるまで待機します。

$ kubectl get po -l app=guestbook -l tier=frontend
NAME                        READY   STATUS    RESTARTS   AGE
frontend-654c699bc8-4qjpc   1/1     Running   0          37s
frontend-654c699bc8-rqznb   1/1     Running   0          37s
frontend-654c699bc8-txsvq   1/1     Running   0          37s

フロントエンドアプリケーションのサービスを作成

Guestbook のフロントエンドは外部に公開する必要があります。
そこで外部からリクエストできるようにサービスの設定を type: LoadBalancer に指定します。

以下のように frontend-service.yaml をダウンロードして、type: LoadBalancer のコメントアウトを解除、type: NodePort をコメントアウトします。

$ wget https://raw.githubusercontent.com/kubernetes/examples/master/guestbook/frontend-service.yaml
$ sed -i "" -e "s/# type: LoadBalancer/type: LoadBalancer/" frontend-service.yaml
$ sed -i "" -e "s/type: NodePort/# type: NodePort/" frontend-service.yaml

編集した frontend-service.yaml でサービスを作成します。

$ kubectl apply -f frontend-service.yaml

フロントエンドアプリケーションのサービスが作成されたことを確認します。
作成したサービスの EXTERNAL-IP が表示されるまで待機します。

$ kubectl get svc frontend
NAME       TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE
frontend   LoadBalancer   10.55.244.103   35.187.206.29   80:31533/TCP   47s

Guestbook アプリケーションにアクセスする

EXTERNAL-IP の IP アドレスに対してブラウザから接続すると以下のような Guestbook アプリケーションが表示されます。

Guestbook アプリケーション

以上で Terraform で GKE を構築し、Guestbook アプリケーションが動作することを確認しました。

作成したリソースの削除

作成したリソースを削除します。

Guestbook アプリケーションの削除

フロントエンドアプリケーションのサービスを削除します。

$ kubectl delete svc frontend

削除コマンド実行後サービスが削除されるまで時間が掛かるので、以下のコマンドで削除されるまで確認します。

$ gcloud compute forwarding-rules list

GKE クラスタの削除

Terraform で作成した GKE クラスタを削除します。
yes で削除します。

$ terraform destroy

GCS バケットの削除

GCS バケットを削除します。

$ gsutil rm -r gs://$GCS_BUCKET/

サービスアカウントの削除

サービスアカウントに紐付けたロールを削除します。

$ gcloud projects remove-iam-policy-binding $GCP_PROJECT \
    --role roles/iam.serviceAccountUser \
    --member serviceAccount:$TERRAFORM_SA_EMAIL

$ gcloud projects remove-iam-policy-binding $GCP_PROJECT \
    --role roles/compute.admin \
    --member serviceAccount:$TERRAFORM_SA_EMAIL

$ gcloud projects remove-iam-policy-binding $GCP_PROJECT \
    --role roles/storage.admin \
    --member serviceAccount:$TERRAFORM_SA_EMAIL

$ gcloud projects remove-iam-policy-binding $GCP_PROJECT \
    --role roles/container.clusterAdmin \
    --member serviceAccount:$TERRAFORM_SA_EMAIL

サービスアカウントを削除します。
y で削除します。

$ gcloud iam service-accounts delete $TERRAFORM_SA_EMAIL

参考

Provider: Google Cloud Platform - Terraform by HashiCorp
Terraform で GCP 環境を構築してみる | GMO アドパートナーズグループ TECH BLOG byGMO
Cloud Storage documentation | Cloud Storage
Create a Guestbook with Redis and PHP | Kubernetes Engine Tutorials
GitHub - containerdaysjp/showks-terraform: Terraform configurations to provision showk environments.

35
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
35
Help us understand the problem. What is going on with this article?