使用 Kubespray 与 Terraform 在 AWS 上部署生产级 Kubernetes 集群
【免费下载链接】kubesprayDeploy a Production Ready Kubernetes Cluster项目地址: https://gitcode.com/GitHub_Trending/ku/kubespray
导读
本文聚焦 Kubespray 仓库中 contrib/terraform/aws 提供的 Terraform 基础设施即代码(IaC)方案,讲解如何一键在 AWS 上创建包含 VPC、堡垒机、NAT 网关、NLB 与多可用区(AZ)节点组的完整 Kubernetes 基础设施,并自动生成供 Kubespray Ansible playbook 使用的 inventory 文件。读完本文,你将掌握该 Terraform 项目的全部变量语义、多发行版 AMI 适配方法、kubeconfig 获取流程以及常见故障的排查思路,可直接在真实 AWS 账号上完成从"空账号"到"生产级集群"的端到端部署。
项目概述:Terraform 自动创建的核心资源
该 Terraform 项目(入口为 create-infrastructure.tf)会一次性创建以下资源:
- VPC:包含公有子网与私有子网,分别分布在多个可用区(AZ)内;
- 堡垒机(Bastion Host)与 NAT 网关:部署在公有子网中,负责对外提供 SSH 跳板与私有子网出网能力;
- Kubernetes 控制平面(master)、etcd 与 worker 节点:数量均可动态配置,且在私有子网中均匀分布到各可用区;
- AWS NLB:部署在公有子网,将 Kubernetes API Server 端口(默认 6443)暴露到公网,供
kubectl与 kubeadm 使用。
该方案默认将 master、etcd、worker 全部放在私有子网中,公网访问完全依赖 NLB 与堡垒机,这与"生产级集群"的网络隔离诉求一致——控制平面与数据面节点没有公网 IP,仅有出网能力(经 NAT 网关)。
架构解析:模块化 Terraform 代码拆解
项目的核心编排位于 create-infrastructure.tf,通过module关键字调用三个子模块,代码结构清晰:
| 模块 | 目录 | 职责 |
|---|---|---|
aws-vpc | modules/vpc | 创建 VPC、公有/私有子网、Internet 网关、NAT 网关、路由表、安全组 |
aws-nlb | modules/nlb | 创建面向公网的 NLB、目标组与监听器,将流量转发至 master 节点 |
aws-iam | modules/iam | 创建 master 与 worker 的 IAM 角色/实例配置文件,供云控制器使用 |
VPC 模块的细节
modules/vpc/main.tf 中,每个公有子网都会配对创建一个 NAT 网关(aws_eip+aws_nat_gateway,数量与公有子网数一致),确保多 AZ 场景下每个可用区都有独立的出网路径;私有子网通过aws_route_table将0.0.0.0/0路由指向对应 NAT 网关。同时:
- 子网标签中写入
kubernetes.io/cluster/<cluster_name> = "shared",公有子网带kubernetes.io/role/elb = "1"、私有子网带kubernetes.io/role/internal-elb = "1",这些标签是 AWS 云负载均衡器控制器与 kubeadm 云控制器识别子网用途的标准约定; - 安全组(
aws_security_group)默认放行 VPC 内部全端口互通(ingress0.0.0.0/0仅限 VPC CIDR)、放行全部出站流量,并对0.0.0.0/0开放 TCP 22 端口供 SSH 连接——生产环境建议按需收紧 SSH 来源 CIDR。
NLB 模块的细节
modules/nlb/main.tf 创建的是Network Load Balancer(load_balancer_type = "network"),而非经典 ELB:
- 监听器端口由
aws_nlb_api_port控制,目标组端口由k8s_secure_api_port控制(两者默认均为 6443); - 目标组
target_type = "ip",直接将 master 节点的私有 IP注册为后端目标(见 create-infrastructure.tf 中的aws_lb_target_group_attachment); - 健康检查基于 HTTPS
/healthz路径,与 Kubernetes API Server 原生的健康探针对应。
IAM 模块的细节
modules/iam/main.tf 分别为控制平面与 worker 创建独立的 IAM 角色(kubernetes-<cluster>-master与kubernetes-<cluster>-node),并附加ec2:*、elasticloadbalancing:*等权限。master 实例通过iam_instance_profile = module.aws-iam.kube_control_plane-profile挂载该角色,worker 节点则挂载 worker 角色,这是 AWS 上运行云负载均衡控制器与持久卷(EBS CSI)所需的最小权限骨架。
使用前提
- Terraform 0.12.0 或更新版本(create-infrastructure.tf 中
required_version = ">= 0.12.0",AWS Provider 要求hashicorp/aws ~> 5.0); - 一个拥有相应权限的AWS 账号(Access Key / Secret Key);
- 一个AWS EC2 SSH Key Pair(部署后用于连接堡垒机与节点)。
使用步骤:从配置到集群落地
第一步:提供 AWS 凭证
两种方式二选一:
- 方式一(环境变量):
export TF_VAR_AWS_ACCESS_KEY_ID="www" export TF_VAR_AWS_SECRET_ACCESS_KEY="xxx" export TF_VAR_AWS_SSH_KEY_NAME="yyy" export TF_VAR_AWS_DEFAULT_REGION="zzz"- 方式二(凭据文件):复制 credentials.tfvars.example 为
credentials.tfvars并填入实际值:
AWS_ACCESS_KEY_ID = "" AWS_SECRET_ACCESS_KEY = "" AWS_SSH_KEY_NAME = "" AWS_DEFAULT_REGION = "eu-central-1"注意:Terraform 变量名与环境变量同名,方式二会把凭据明文写入本地文件,请注意文件权限与保管。
第二步:编辑集群规模与网络参数
编辑 terraform.tfvars(仓库中已有可直接运行的示例值),核心参数如下:
| 变量 | 含义 | 示例值 |
|---|---|---|
aws_cluster_name | 集群名称,会作为所有资源名的前缀 | "devtest" |
aws_vpc_cidr_block | VPC 网段 | "10.250.192.0/18" |
aws_cidr_subnets_private | 私有子网网段列表(每个元素对应一个 AZ) | ["10.250.192.0/20", "10.250.208.0/20"] |
aws_cidr_subnets_public | 公有子网网段列表 | ["10.250.224.0/20", "10.250.240.0/20"] |
aws_bastion_num/aws_bastion_size | 堡垒机数量与实例规格 | 1/"t3.small" |
aws_kube_master_num/_size/_disk_size | master 节点数量、规格、根盘大小(GiB) | 3/"t3.medium"/50 |
aws_etcd_num/_size/_disk_size | 独立 etcd 节点数、规格、根盘大小 | 0/"t3.medium"/50 |
aws_kube_worker_num/_size/_disk_size | worker 节点数量、规格、根盘大小 | 4/"t3.medium"/50 |
aws_nlb_api_port/k8s_secure_api_port | NLB 监听端口与 API Server 端口 | 6443/6443 |
default_tags | 附加到所有 AWS 资源的通用标签 | { Env = "devtest" } |
inventory_file | 生成的 Ansible inventory 写入路径 | "../../../inventory/hosts" |
节点数量与子网数量的配合规则:子网列表的长度决定了使用的可用区数量,master/worker/etcd 实例通过element(module.aws-vpc.aws_subnet_ids_private, count.index)按索引循环分配到各子网,从而实现跨 AZ 均匀分布;因此节点数量最好能被子网数量整除,否则会出现 AZ 间节点数不均。
仓库 terraform.tfvars 还给出了两种典型拓扑的注释示例:
- 单 AZ 部署:只配置一个公有/私有子网;
- 3+ AZ 部署:配置 4 个 /24 子网以承载更多节点。
第三步:执行 Terraform 应用
创建好 EC2 SSH Key 后执行:
terraform apply -var-file=credentials.tfvars若已导出环境变量,直接terraform apply即可。
第四步:自动生成 inventory 与 SSH 配置
- Terraform 会在
inventory目录(默认写入路径为inventory_file = "../../../inventory/hosts",即仓库根目录的 inventory/hosts)自动生成 Ansible inventory 文件; - 该文件由 templates/inventory.tpl 模板渲染,包含
[all]、[bastion]、[kube_control_plane]、[kube_node]、[etcd]、[calico_rr]以及[k8s_cluster:children]等组定义,并注入apiserver_loadbalancer_domain_name指向 NLB 的 FQDN; - 各实例的
ansible_host使用私有 IP/私有 DNS,因此所有对节点的操作都必须经由堡垒机跳转; - 仓库根目录同时自动生成
ssh-bastion.conf(由角色 roles/bastion-ssh-config 渲染),Ansible 会自动识别堡垒机并调整ssh_args,通过跳板连接各节点。你也可以手动使用:
ssh -F ./ssh-bastion.conf user@$ip第五步:运行 Kubespray Playbook 完成集群安装
基础设施就绪后,即可用生成好的 inventory 执行 Kubespray 集群编排(以 Ubuntu 为例):
ansible-playbook -i ./inventory/hosts ./cluster.yml -e ansible_user=ubuntu -b --become-user=root --flush-cache其中 cluster.yml 是 Kubespray 的主 playbook,会依次完成 etcd 部署、kubeadm 初始化控制平面、加入 worker 节点、安装网络插件(默认 Calico)与应用组件(DNS、metrics-server 等)的全流程。
使用非 Ubuntu 发行版:通过 AMI 过滤器自定义镜像
默认情况下,Terraform 脚本以 Ubuntu(当前 variables.tf 中默认ami_name_pattern = "debian-10-amd64-*"、ami_owners = ["136693071363"])作为基础镜像。若要切换发行版,无需改动核心 Terraform 文件,只需在terraform.tfvars中覆盖data "aws_ami" "distro"块的搜索过滤器(对应ami_name_pattern、ami_virtualization_type、ami_owners三个变量),实现按名称模式与所有者 ID 精确匹配最新 AMI。
常见发行版配置示例
- Debian Jessie:
ami_name_pattern = "debian-jessie-amd64-hvm-*" ami_owners = ["379101102735"]- Ubuntu 16.04(Xenial):
ami_name_pattern = "ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-*" ami_owners = ["099720109477"]- CentOS 7:
ami_name_pattern = "dcos-centos7-*" ami_owners = ["688023202711"]切换发行版后,务必同步调整第五步中ansible_user(如 CentOS/Amazon Linux 通常为centos或ec2-user),并确保该发行版在 roles/bootstrap_os/tasks 中有对应的 OS 初始化任务支持。
连接 Kubernetes:获取 kubeconfig
集群安装完成后,在仓库根目录依次执行以下命令,即可从控制平面节点导出 kubeconfig 并接入集群:
# 获取控制平面节点的 IP 地址 CONTROLLER_HOST_NAME=$(cat ./inventory/hosts | grep "\[kube_control_plane\]" -A 1 | tail -n 1) CONTROLLER_IP=$(cat ./inventory/hosts | grep $CONTROLLER_HOST_NAME | grep ansible_host | cut -d'=' -f2) # 获取负载均衡器的域名 LB_HOST=$(cat inventory/hosts | grep apiserver_loadbalancer_domain_name | cut -d'"' -f2) # 将控制平面节点加入 known_hosts,避免首次 SSH 交互 ssh-keygen -R $CONTROLLER_IP > /dev/null 2>&1 ssh-keyscan -H $CONTROLLER_IP >> ~/.ssh/known_hosts 2>/dev/null # 通过堡垒机导出 kubeconfig(CentOS 发行版示例) mkdir -p ~/.kube ssh -F ssh-bastion.conf centos@$CONTROLLER_IP "sudo chmod 644 /etc/kubernetes/admin.conf" scp -F ssh-bastion.conf centos@$CONTROLLER_IP:/etc/kubernetes/admin.conf ~/.kube/config sed -i "s^server:.*^server: https://$LB_HOST:6443^" ~/.kube/config kubectl get nodes关键点说明:
ssh -F ssh-bastion.conf显式指定生成的堡垒机 SSH 配置,实现经跳板访问私有子网内的控制平面;- 最后一条
sed将 kubeconfig 中的server地址改写为 NLB 的 FQDN(https://<LB_HOST>:6443),使kubectl从本地直接经 NLB 访问 API Server; - 若使用非 CentOS 发行版,需将命令中的
centos@替换为对应用户(如ubuntu@)。
故障排查
IAM 实例配置文件残留
如果集群未通过 Terraform 销毁(例如直接删除了 EC2 实例),AWS 上可能残留 IAM 实例配置文件。可通过 AWS CLI 手动清理:
aws iam delete-instance-profile --region <region_name> --instance-profile-name <profile_name>Ansible inventory 未自动生成
正常情况下 Terraform 会在 apply 结束时自动渲染 inventory 文件。若未生成,可将terraform apply输出中inventory = ...之后的内容复制出来,手动保存为inventory/hosts文件再继续使用。该输出由 output.tf 中的inventoryoutput 提供,其值即 templates/inventory.tpl 渲染后的完整文本。
与 Kubespray 主流程的衔接要点
- inventory 变量注入:模板中的
apiserver_loadbalancer_domain_name是 Kubespray 必需的变量,它让 kubeadm 使用 NLB FQDN 作为 API Server 的广告地址,同时 cluster.yml 中 HA 模式的负载均衡逻辑也会消费该值; - etcd 归组逻辑:当
aws_etcd_num > 0时 etcd 独立成组,否则[etcd]组回退为 master 节点(见 create-infrastructure.tf 中list_etcd的条件表达式),这与 Kubespray "etcd 可与控制平面共置"的部署模型完全对应; - 后续运维:基础设施重建或扩缩容后重新执行
terraform apply,inventory 文件会随实例变更自动重新渲染(null_resource以渲染结果为触发器),随后可继续使用 scale.yml、upgrade_cluster.yml 等 playbook 完成集群的扩缩容与升级。
小结
contrib/terraform/aws为 Kubespray 用户提供了一条从 AWS 空账号直达生产级 Kubernetes 集群的自动化路径:Terraform 负责网络、安全与计算资源的声明式创建,并自动输出与 Kubespray inventory 格式无缝衔接的 hosts 文件;Ansible 侧则借助自动生成的堡垒机 SSH 配置完成全部节点编排。理解其变量语义、模块边界与 inventory 生成规则,是安全、灵活地在 AWS 多可用区环境下落地 Kubespray 集群的关键。
【免费下载链接】kubesprayDeploy a Production Ready Kubernetes Cluster项目地址: https://gitcode.com/GitHub_Trending/ku/kubespray
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考