使用Terraform构建GKE

首先

在构建GKE时,我们想要管理实际应用的设置,因此我们将使用Terraform来构建GKE。
Terraform提供了GKE模块,但这次我们将使用原始的Terraform进行构建。

在撰写本文章时,我们参考了在JapanContainerDays v18.12上提出的”showKs” Terraform的存储库。非常感谢你们。

GitHub – containerdaysjp/showks-terraform: 用于配置showk环境的Terraform配置。

我认为还有其他充满云原生元素的存储库,非常值得参考。

日本集装箱天- 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 文档

启用 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中是唯一的。
我们示例中使用了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。

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 "google" {
  project = "${var.project}"
  region  = "${var.location}"
}

定义后端

创建一个名为backend.tf的文件来定义管理.tfstate文件的后端。在本例中,将使用GCS作为后端。
请指定一个事先创建的GCS存储桶的名称作为bucket_name。

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

定义GKE

我们来创建一个用于定义GKE的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文件中未定义默认值的值设置为环境变量。
未定义默认值的变量可以通过命令行参数或terraform.tfvars文件进行传递。
对于环境变量,变量名的前缀必须为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应用程序示例教程

在部署之前,获取预先创建的 GKE 集群的身份验证信息。

$ gcloud container clusters get-credentials primary-cluster

安装 Redis 主服务器

访客留言簿应用程序使用Redis。
数据写入Redis主服务器,然后从Redis工作服务器读取数据。

部署 Redis 主节点

部署Redis主节点。

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

等待直到创建的 Pod 的运行状态为 1/1。

$ 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主节点服务

创建 Redis 主节点服务。

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

确认Redis主服务器的服务已经创建。

$ 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工作进程可以创建多个副本以提高可用性。

Redis worker 的部署

部署Redis工作器。

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

等待创建的Pod运行状态变为1/1。

$ 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主服务。

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

确认 Redis 主节点服务已创建。

$ 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的Web服务器。
前端是一个由PHP开发的应用程序。
根据读写操作,与Redis主节点和Redis工作节点进行通信。

前端应用程序的部署。

部署前端应用程序。

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

直到创建的Pod变为1/1运行状态之前,将等待。

$ 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

创建前端应用程序服务

需要将留言簿的前端公开给外部,因此需要将服务配置的 type 设置为 LoadBalancer,以便外部可以发出请求。

在前端服务的yaml文件(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

访问留言簿应用程序

当您从浏览器连接到EXTERNAL-IP的IP地址时,将显示以下的Guestbook应用程序。

Guestbook アプリケーション

我已经使用Terraform在GKE上部署了Guestbook应用,并确认其正常运行。

删除已创建的资源

删除已创建的资源。

删除留言簿应用

删除前端应用程序的服务。

$ kubectl delete svc frontend

由于删除命令执行后,服务需要一些时间才能被删除,请使用以下命令确认是否已被删除。

$ gcloud compute forwarding-rules list

删除 GKE 集群

使用 Terraform 删除创建的 GKE 集群。
输入”是”确认删除。

$ 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

请参阅

供应商:谷歌云平台 – HashiCorp的Terraform
尝试使用Terraform在GCP环境中构建 | GMO合作伙伴技术博客 byGMO
云存储文档 | 云存储
使用Redis和PHP创建留言簿 | Kubernetes引擎教程
GitHub – containerdaysjp/showks-terraform:使用Terraform配置提供showk环境。

bannerAds