本文档介绍了如何通过 Terraform 在 VPC 环境下部署一个阿里云容器服务 Kubernetes 集群,并在该集群之上,部署一个 WordPress 样例应用。本文档提供一种构建阿里云基础设施的解决方案,让您通过代码来自动创建、编排和管理容器服务以及完成在容器集群上应用的自动化部署。
前提条件
- 需要开通阿里云容器服务,用户的账户需有 100 元余额并通过实名认证。
- 需要启用用户账号的 AccessKey,妥善保存和记录 AccessKey ID 和 AccessKey Secret。
步骤 1 安装 Terraform
详细信息参见 Terraform 部署容器服务Swarm集群及Wordpress应用
除了下载 Terraform 和阿里云的 Terraform Provider 之外,在运行 Wordpress 的模板之前,需要在 Kubernetes Terraform Provider 官方下载地址 下载对应版本和平台的 Provider。
步骤 2 下载容器服务 Kubernetes 的 Terraform 模板
您可以从 GitHub 上下载创建 Kubernetes 集群的 Terraform 模板(模板下载地址)。该模板文件定义了创建 Kubernetes 集群的相关资源,帮助您完成 Kubernetes 集群的快速创建和 Kube Config 的自动下载。
模板中包含以下文件。
main.tf
Terraform 主文件。定义了将要部署的资源。本模版加入了条件判断,可实现对已有网络资源的引用和多个 Kubernetes 集群的同时创建。
- 地域
定义了资源将要被创建在哪个地域里。
provider "alicloud" {
access_key = "${var.alicloud_access_key}"
secret_key = "${var.alicloud_secret_key}"
region = "${var.region}"
}
-
VPC
指定
vpc_id
可使用已有 VPC。resource "alicloud_vpc" "vpc" { count = "${var.vpc_id == "" ? 1 : 0}" cidr_block = "${var.vpc_cidr}" name = "${var.vpc_name == "" ? var.example_name : var.vpc_name}" }
-
VSwitch
指定
vswitch_ids
可使用已有 VSwitch。resource "alicloud_vswitch" "vswitches" { count = "${length(var.vswitch_ids) > 0 ? 0 : length(var.vswitch_cidrs)}" vpc_id = "${var.vpc_id == "" ? join("", alicloud_vpc.vpc.*.id) : var.vpc_id}" cidr_block = "${element(var.vswitch_cidrs, count.index)}" availability_zone = "${lookup(data.alicloud_zones.default.zones[count.index%length(data.alicloud_zones.default.zones)], "id")}" name = "${var.vswitch_name_prefix == "" ? format("%s-%s", var.example_name, format(var.number_format, count.index+1)) : format("%s-%s", var.vswitch_name_prefix, format(var.number_format, count.index+1))}" }
-
Nat Gateway
指定
new_nat_gateway
来决定是否要为模板中定义的 VPC 自动创建 Nat Gateway,以保证 Kubernetes 集群成功创建。resource "alicloud_nat_gateway" "default" { count = "${var.new_nat_gateway == true ? 1 : 0}" vpc_id = "${var.vpc_id == "" ? join("", alicloud_vpc.vpc.*.id) : var.vpc_id}" name = "${var.example_name}" }
-
EIP
resource "alicloud_eip" "default" { count = "${var.new_nat_gateway == "true" ? 1 : 0}" bandwidth = 10 }
-
EIP Association
resource "alicloud_eip_association" "default" { count = "${var.new_nat_gateway == "true" ? 1 : 0}" allocation_id = "${alicloud_eip.default.id}" instance_id = "${alicloud_nat_gateway.default.id}" }
-
SNAT
在模板中定义的 Nat Gateway 下自动添加 SNAT Entry 来保证 Kubernetes 集群成功创建。
resource "alicloud_snat_entry" "default"{ count = "${var.new_nat_gateway == "false" ? 0 : length(var.vswitch_ids) > 0 ? length(var.vswitch_ids) : length(var.vswitch_cidrs)}" snat_table_id = "${alicloud_nat_gateway.default.snat_table_ids}" source_vswitch_id = "${length(var.vswitch_ids) > 0 ? element(split(",", join(",", var.vswitch_ids)), count.index%length(split(",", join(",", var.vswitch_ids)))) : length(var.vswitch_cidrs) < 1 ? "" : element(split(",", join(",", alicloud_vswitch.vswitches.*.id)), count.index%length(split(",", join(",", alicloud_vswitch.vswitches.*.id))))}" snat_ip = "${alicloud_eip.default.ip_address}" }
-
容器服务 Kubernetes 集群
改变
k8s_number
的值可同时创建多个 Kubernetes 集群。resource "alicloud_cs_kubernetes" "k8s" { count = "${var.k8s_number}" name = "${var.k8s_name_prefix == "" ? format("%s-%s", var.example_name, format(var.number_format, count.index+1)) : format("%s-%s", var.k8s_name_prefix, format(var.number_format, count.index+1))}" vswitch_id = "${length(var.vswitch_ids) > 0 ? element(split(",", join(",", var.vswitch_ids)), count.index%length(split(",", join(",", var.vswitch_ids)))) : length(var.vswitch_cidrs) < 1 ? "" : element(split(",", join(",", alicloud_vswitch.vswitches.*.id)), count.index%length(split(",", join(",", alicloud_vswitch.vswitches.*.id))))}" new_nat_gateway = false master_instance_type = "${var.master_instance_type == "" ? data.alicloud_instance_types.default.instance_types.0.id : var.master_instance_type}" worker_instance_type = "${var.worker_instance_type == "" ? data.alicloud_instance_types.default.instance_types.0.id : var.worker_instance_type}" worker_number = "${var.k8s_worker_number}" master_disk_category = "${var.master_disk_category}" worker_disk_category = "${var.worker_disk_category}" master_disk_size = "${var.master_disk_size}" worker_disk_size = "${var.master_disk_size}" password = "${var.ecs_password}" pod_cidr = "${var.k8s_pod_cidr}" service_cidr = "${var.k8s_service_cidr}" enable_ssh = true install_cloud_monitor = true depends_on = ["alicloud_snat_entry.default"] } ## 注意:指定 kube_config = "~/.kube/config" 可在 Kubernetes 集群创建完成后将 Kube Config 内容自动下载并存放在文件 `~/.kube/cofig` 中。
outputs.tf
该文件定义了输出参数。作为执行的一部分而创建的资源会生成这些输出参数。和 ROS 模板指定的输出参数类似。例如,该模板将部署一个 Kubernetes 集群。以下输出参数将提供集群 ID 和其他资源参数。
output "cluster_id" {
value = "${alicloud_cs_swarm.cs_vpc.id}"
}
variables.tf
该文件包含可传递到 main.tf 的变量,可帮助您自定义环境。
variable "alicloud_access_key" {
description = "The Alicloud Access Key ID to launch resources. Support to environment 'ALICLOUD_ACCESS_KEY'."
}
variable "alicloud_secret_key" {
description = "The Alicloud Access Secret Key to launch resources. Support to environment 'ALICLOUD_SECRET_KEY'."
}
variable "region" {
description = "The region to launch resources."
default = "cn-hongkong"
}
variable "vpc_cidr" {
description = "The cidr block used to launch a new vpc."
default = "172.16.0.0/12"
}
variable "vswitch_cidrs" {
description = "List of cidr blocks used to create several new vswitches when 'vswitch_ids' is not specified."
type = "list"
default = ["10.1.2.0/24"]
}
variable "k8s_number" {
description = "The number of kubernetes cluster."
default = 1
}
variable "k8s_worker_number" {
description = "The number of worker nodes in each kubernetes cluster."
default = 3
}
步骤 3 执行 Kubernetes Terraform 脚本
首先,定位到您存放以上文件的目录,如 /root/terraform/kuberneters
。然后,您可以利用以下 terraform 的相关命令,运行脚本,构建容器集群和部署应用。更多的命令用法和介绍,参见 [Terraform 部署容器服务Kubernetes集群及Wordpress应用]() 和 Terraform Commands (CLI)。
运行terraform apply
命令,开始创建 Kubernetes 集群。
$ terraform apply
data.alicloud_instance_types.default: Refreshing state...
data.alicloud_zones.default: Refreshing state...
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
...
Plan: 7 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
alicloud_vpc.vpc: Creating...
...
Apply complete! Resources: 7 added, 0 changed, 0 destroyed.
Outputs: ##注意
cluster_id = [
c0f2e04c77e234******
]
......
vswitch_ids = [
vsw-bp1c3hfcd6l80izqc3tbx
]
terraform apply
命令执行完毕后, 输出集群 ID 和其他参数。除此之外,将 Kubernetes 的 Kube Config 文件存放在了目录 ~/.kube
下。
您现在可以在容器服务控制台查看通过 terraform 创建的 Kubernetes 集群,查看集群信息、节点信息、日志信息和容器信息等信息。
步骤 4 下载 Wordpress 的 Terraform 模板
在创建好 Kubernetes 并完成了 Kube Config 的下载后,接下来就可以在 Kubernetes 上部署 Wordpress。 您可以从 GitHub 上下载创建 Wordpress 的 Terraform 模板(模板下载地址)。该模板文件是根据 Kubernetes Tutorials 编写的。模板中定义了创建 Wordpress 的相关资源和配置,帮助您完成在 Kubernetes 集群的快速搭建 Wordpress。
更多 Terraform Kubernetes 的操作可参考 Terraform 官网的 Kubernetes 文档介绍.
模板中包含以下文件。
localvolumes.tf
定义 Wordpress 和 Mysql 存储自己数据的 Persistent Volume。
-
Persistent Volume
resource "kubernetes_persistent_volume" "mysql" { metadata { name = "local-pv-mysql" labels { type = "local" } } spec { capacity { storage = "20Gi" } access_modes = ["ReadWriteOnce"] persistent_volume_source { host_path { path = "/tmp/data/pv-mysql" } } } }
mysql.tf
创建 MySQL 密码 Secret,并部署 MySQL。
-
secret
resource "kubernetes_secret" "mysql" { metadata { name = "mysql-pass" } data { password = "${var.mysql_password}" } }
-
Deployment
resource "kubernetes_service" "mysql" { metadata { name = "wordpress-mysql" labels { app = "wordpress" } } spec { port { port = 3306 } selector { app = "wordpress" tier = "${kubernetes_replication_controller.mysql.spec.0.selector.tier}" } cluster_ip = "None" } } resource "kubernetes_replication_controller" "mysql" { metadata { name = "wordpress-mysql" labels { app = "wordpress" } } spec { selector { app = "wordpress" tier = "mysql" } template { container { image = "mysql:${var.mysql_version}" name = "mysql" env { name = "MYSQL_ROOT_PASSWORD" value_from { secret_key_ref { name = "${kubernetes_secret.mysql.metadata.0.name}" key = "password" } } } port { container_port = 3306 name = "mysql" } volume_mount { name = "mysql-persistent-storage" mount_path = "/var/lib/mysql" } } volume { name = "mysql-persistent-storage" persistent_volume_claim { claim_name = "${kubernetes_persistent_volume_claim.mysql.metadata.0.name}" } } } } }
wordpress.tf
接下来部署 Wordpress。
-
Deployment
resource "kubernetes_service" "wordpress" { metadata { name = "wordpress" labels { app = "wordpress" } } spec { port { port = 80 } selector { app = "wordpress" tier = "${kubernetes_replication_controller.wordpress.spec.0.selector.tier}" } type = "LoadBalancer" } } resource "kubernetes_replication_controller" "wordpress" { metadata { name = "wordpress" labels { app = "wordpress" } } spec { selector { app = "wordpress" tier = "frontend" } template { container { image = "wordpress:${var.wordpress_version}-apache" name = "wordpress" env { name = "WORDPRESS_DB_HOST" value = "wordpress-mysql" } env { name = "WORDPRESS_DB_PASSWORD" value_from { secret_key_ref { name = "${kubernetes_secret.mysql.metadata.0.name}" key = "password" } } } port { container_port = 80 name = "wordpress" } volume_mount { name = "wordpress-persistent-storage" mount_path = "/var/www/html" } } volume { name = "wordpress-persistent-storage" persistent_volume_claim { claim_name = "${kubernetes_persistent_volume_claim.wordpress.metadata.0.name}" } } } } }
outputs.tf
该文件定义了输出参数。输出 Loadbalancer Public IP,借助该 IP 地址可直接访问部署好的 Wordpress 应用。
output "slb_ip" {
value = "${kubernetes_service.wordpress.load_balancer_ingress.0.ip}"
}
variables.tf
该文件包含了部署 MySQL 和 WordPress 所依赖的参数。
variable "wordpress_version" {
description = "The version of wordpress. Default to 4.7.3."
default = "4.7.3"
}
variable "mysql_password" {
description = "Please input mysql password."
}
variable "mysql_version" {
description = "The version of mysql which wordpress used. Default to 5.6."
default = "5.6"
}
步骤 5 执行 Wordpress Terraform 脚本
首先定位到您存放以上文件的目录,如 /root/terraform/kuberneters-wordpress
。运行terraform apply
命令,开始在创建好的 Kubernetes 集群上部署 MySQL 和 WordPress 应用。
值得注意的是,由于变量 mysql_password
在变量文件中没有定义默认值,因此在执行命令是应输入参数值。
$ terraform apply -var 'mysql_password=Abc1234'
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
...
Plan: 9 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
kubernetes_secret.mysql: Creating...
data.%: "" => "1"
data.password: "<sensitive>" => "<sensitive>"
metadata.#: "" => "1"
metadata.0.generation: "" => "<computed>"
metadata.0.name: "" => "mysql-pass"
......
Apply complete! Resources: 9 added, 0 changed, 0 destroyed.
Outputs:
slb_ip = 47.99.xx.xx
terraform apply
命令执行完毕后, 输出负载均衡 Public IP。
步骤 6 访问 WordPress
根据负载均衡 Public IP,运行如下命令或者直接在浏览器中输入 IP 地址即可实现对部署好的 Wordpress 直接访问:
open http://47.99.xx.xx
- 进入 WordPress 欢迎页面,可选择语言,然后继续配置。
- 输入站点名称以及管理员的用户名和密码。选择安装 WordPress。
- WordPress 安装完成后,单击 登录,输入管理员的用户名和密码,进入 WordPress 应用。
延伸阅读
阿里云目前是 Terraform 官方的 Major Cloud Provider,如果您想通过 terraform 灵活构建阿里云上的基础设施资源,您可参见 Alicloud Provider 了解更多信息,自定义资源描述文件,快速搭建属于您的云上设施 。