使用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应用程序。

我已经使用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环境。