1. 项目概述Vishwakarma一个基于Terraform的AWS自托管K8s集群构建器如果你和我一样长期在云原生和基础设施即代码IaC的领域里摸爬滚打那么对于“快速、可靠地搭建一个生产就绪的Kubernetes集群”这件事一定有着深刻的体会。这不仅仅是跑几条kubeadm init命令那么简单它涉及到网络规划、节点配置、安全加固、高可用部署等一系列繁琐且容易出错的步骤。尤其是在AWS这样的公有云上虽然EKS提供了托管方案但成本、控制粒度以及特定的技术栈选择比如你想用CoreOS Container Linux往往会让我们这些工程师想要自己动手。今天要聊的Vishwakarma就是我在这个需求下找到并深度使用过的一个非常趁手的工具。它不是一个全新的发明而是站在了CoreOS Tectonic Installer这个巨人的肩膀上用Terraform模块化的思想将搭建一个高可用K8s集群的过程变成了一个可版本化、可重复执行、且深度可定制的“声明式”操作。简单来说Vishwakarma是一个用HashiCorp Terraform编写的开源项目它的核心目标是在AWS上自动化部署一个完整的、自托管的Kubernetes集群。它帮你封装了从VPC网络、堡垒机、到Kubernetes控制平面Master和工作节点Worker的所有AWS资源创建逻辑。你只需要准备好Terraform配置运行terraform apply然后喝杯咖啡一个包含了etcd集群、多Master高可用、以及可配置的Worker节点组的K8s集群就准备就绪了。这对于需要快速搭建开发测试环境、构建内部PaaS平台或者对集群底层有强控制需求的团队来说价值巨大。它特别适合那些已经熟悉Terraform工作流并且希望将K8s集群基础设施也纳入同一套IaC管道的DevOps工程师和平台团队。2. 核心架构与设计思路拆解在深入命令行之前我们必须先理解Vishwakarma是怎么思考这个问题的。直接去操作AWS的控制台或者CLI来搭建K8s会面临几个核心挑战过程碎片化几十个步骤分散在EC2、VPC、IAM、Auto Scaling等服务中、状态难以管理手动创建的资源删除和追溯困难、一致性无法保证第二次搭建很难和第一次完全一样。Vishwakarma的解决方案正是用Terraform模块来应对这些挑战。2.1 模块化设计像搭积木一样构建集群Vishwakarma没有把所有代码写在一个巨大的.tf文件里而是采用了高度模块化的设计。这种设计让每个核心功能块职责清晰也方便你未来替换或升级某个部分。从项目结构看主要包含三大核心模块aws/network模块这是集群的地基。它负责创建一整个隔离的VPC环境包括公有子网和私有子网。一个非常关键的设计是它会在公有子网中部署一台堡垒机Bastion Host。所有位于私有子网内的资源如Master节点、Worker节点默认没有公网IP这是出于安全最佳实践。当你需要SSH到这些私有节点进行调试或维护时就需要先连接到这台堡垒机再从堡垒机跳转过去。这个模块的输出如VPC ID、子网ID会成为其他模块的输入确保了网络拓扑的连贯性。aws/elastikube模块这是集群的大脑和心脏负责构建Kubernetes控制平面。它的工作是最复杂的主要包括etcd集群部署部署一个多节点的、基于TLS加密通信的etcd v3.5集群作为K8s的后端存储。高可用的etcd是K8s高可用的前提。Master节点部署部署多个Master节点运行kube-apiserver, kube-controller-manager, kube-scheduler等核心组件。这些节点通常位于私有子网通过内部负载均衡器如AWS NLB对外主要是Worker节点和kubectl提供API Server服务实现负载均衡和高可用。引导与配置利用CoreOS的Ignition系统进行节点初始化配置。Ignition是一种在首次启动时执行配置的声明式工具比传统的Cloud-Init更早阶段运行非常适合配置操作系统基础、磁盘、用户和系统单元。aws/kube-worker模块这是集群的肌肉负责创建真正运行工作负载的节点。它利用AWS Auto Scaling GroupASG来管理一组Worker节点。你可以灵活地配置节点类型如m5.large,c5.xlarge、节点数量、以及最关键的一点——选择使用按需实例On-Demand还是竞价实例Spot。对于成本敏感的非核心业务混合使用Spot实例能大幅降低成本。节点同样通过Ignition加入集群自动配置kubelet、容器运行时如Docker或containerd并注册到Master。这种“网络 - 控制平面 - 工作节点”的递进式模块设计不仅逻辑清晰也映射了terraform apply时的分步执行策略让你可以分阶段验证和部署。2.2 技术选型背后的“为什么”为什么用TerraformTerraform的“编写-计划-应用”范式完美契合基础设施的声明式管理。它维护了一个状态文件让你清楚地知道集群里有什么避免资源泄漏。更重要的是它与AWS Provider的成熟集成能高效管理大量相互依赖的云资源。为什么用CoreOS Container LinuxCoreOS是一个为运行容器而生的极简Linux发行版。它系统小巧、启动快、默认集成容器运行时、并且通过自动原子更新来增强安全性。虽然CoreOS项目已演进为Fedora CoreOS但其Ignition和Container Linux的理念在Vishwakarma中依然发挥着关键作用提供了稳定可靠的节点操作系统基础。为什么支持多种CNI网络是K8s的难点之一。Vishwakarma支持AWS VPC CNI、flannel和Cilium覆盖了不同场景。AWS VPC CNI让Pod直接获得VPC IP网络性能最好与AWS其他服务如VPC流日志、安全组集成度高flannel简单稳定是经典的Overlay网络方案Cilium则基于eBPF提供了强大的网络策略和可观测性能力。这种可插拔的设计给了用户根据自身网络知识和需求进行选择的权利。3. 从零开始手把手搭建你的第一个集群理解了架构我们进入实战环节。假设你有一个AWS账号并且已经配置好了具有足够权限的AWS CLI凭证通过aws configure。以下步骤我将结合官方指南和个人踩坑经验为你梳理出一条清晰的路径。3.1 前期准备工具链与权限检查这一步至关重要很多后续错误都源于这里没准备好。安装并验证Terraform ( v1.2.0)# 以macOS为例使用Homebrew安装 brew tap hashicorp/tap brew install hashicorp/tap/terraform # 验证安装和版本 terraform version注意确保版本符合要求。Terraform不同版本间Provider插件和语法可能有差异使用项目要求的最低版本或更高版本可以避免兼容性问题。安装kubectl ( v1.31.1)和aws-iam-authenticator# 安装kubectl brew install kubernetes-cli # 安装aws-iam-authenticator (以macOS为例) brew install aws-iam-authenticator # 分别验证 kubectl version --client aws-iam-authenticator versionaws-iam-authenticator是K8s与AWS IAM集成的关键。集群创建后你需要用它来生成访问令牌kubectl才能通过IAM角色认证访问集群。创建EC2密钥对 这是为了能SSH登录到堡垒机和节点。务必在你计划部署集群的AWS区域例如us-west-2创建。登录AWS控制台进入EC2服务在“密钥对”页面创建新密钥对命名为my-vishwakarma-key下载私钥文件.pem格式。将私钥文件放到~/.ssh/目录下并设置正确的权限mv ~/Downloads/my-vishwakarma-key.pem ~/.ssh/ chmod 400 ~/.ssh/my-vishwakarma-key.pem同时你需要有对应的公钥文件。如果你是从AWS控制台创建的通常只提供私钥下载。你可以通过以下命令从私钥生成公钥如果尚未生成ssh-keygen -y -f ~/.ssh/my-vishwakarma-key.pem ~/.ssh/my-vishwakarma-key.pub安装jq和Python 3.7brew install jq python python3 --version # 确认是3.7 pip3 --versionjq用于在后续脚本中处理JSON输出。Python 3.7和pip则是为了支持项目中可能用于节点滚动更新的Lambda函数如果相关模块被启用。3.2 获取项目与初始化配置克隆项目并进入示例目录git clone https://github.com/getamis/vishwakarma.git cd vishwakarma/examples/kubernetes-cluster这个examples/kubernetes-cluster目录包含了一个开箱即用的Terraform配置示例。我强烈建议你先基于这个例子进行实验理解后再创建自己的配置。审视和修改terraform.tfvars文件 通常示例会有一个terraform.tfvars.example文件。你需要复制它并填写自己的变量。cp terraform.tfvars.example terraform.tfvars用编辑器打开terraform.tfvars以下是一些最关键的配置项及其解释# 集群标识会用于命名许多资源如S3存储桶、EC2实例名 cluster_name my-first-vishwakarma-cluster # AWS区域确保与你创建密钥对的区域一致 aws_region us-west-2 # 你刚刚创建并放入~/.ssh/的密钥对名称 key_pair_name my-vishwakarma-key # 你的公钥内容用于Ignition配置节点访问 # 将下面替换为 cat ~/.ssh/my-vishwakarma-key.pub 的输出 public_key ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC...你的公钥内容 # 网络配置通常可以先保持默认 vpc_cidr 10.0.0.0/16 # Master节点配置 master_count 2 # 生产环境建议至少3个以实现高可用 master_instance_type t3.medium # Worker节点组配置 worker_count 2 worker_instance_type t3.medium worker_group_name on-demand # 可以创建多个不同配置的worker组 # 是否启用Spot实例 worker_spot_enabled false # 首次尝试建议关闭避免Spot中断干扰 worker_spot_price # 如果启用这里可以指定最高出价 # Kubernetes版本 kubernetes_version 1.31.1实操心得cluster_name最好全局唯一特别是S3存储桶名需要全球唯一。如果创建失败提示S3桶名已存在修改此名称即可。master_count设置为2是一个折中方案既能提供一定的可用性一个挂了另一个还在又比3个节省成本。但对于严格的生产环境3个Master是底线。初始化Terraformterraform init这个命令会下载项目所需的AWS Provider插件以及本地引用的模块。看到Terraform has been successfully initialized!即表示成功。3.3 分步构建集群官方文档建议分步apply这是一个非常好的实践有利于调试和问题定位。创建网络基础设施terraform apply -targetmodule.networkTerraform会显示执行计划创建VPC、子网、互联网网关、NAT网关、路由表以及堡垒机。输入yes确认。这个过程大约需要2-3分钟。创建成功后记下输出中的bastion_public_ip这是你后续SSH登录的入口。创建Kubernetes控制平面terraform apply -targetmodule.master这是最耗时的一步大约需要10-15分钟。Terraform会创建Master节点、etcd节点、负载均衡器、安全组、IAM角色等大量资源。它会通过Ignition配置文件在EC2实例首次启动时自动安装并配置所有K8s控制平面组件。注意事项在此期间如果遇到错误例如IAM权限不足、实例类型配额不够仔细阅读错误信息。最常见的权限问题是Terraform使用的IAM角色或用户缺少特定操作权限如创建ELB、EC2特定类型。你需要根据错误提示在AWS IAM中附加相应的策略。创建工作节点terraform apply在创建完网络和Master之后运行不带-target的apply会创建配置中定义的所有剩余资源主要是Worker节点组。这个过程也会用到Ignition自动将Worker节点加入集群。大约需要5-10分钟。3.4 验证集群并获取访问权限所有步骤完成后集群已经运行但你本地的kubectl还不知道如何访问它。获取kubeconfig文件 Vishwakarma会将生成的集群访问配置文件kubeconfig上传到一个S3存储桶中。存储桶名称格式为cluster_name-hash。你可以从Terraform的输出中查找一个名为kubeconfig_s3_bucket或类似的输出变量或者直接运行以下命令获取需要jqterraform output -json | jq -r .kubeconfig_s3_bucket.value假设输出是my-first-vishwakarma-cluster-abc123。然后使用AWS CLI下载aws s3 cp s3://my-first-vishwakarma-cluster-abc123/kubeconfig ./kubeconfig配置kubectlexport KUBECONFIG$(pwd)/kubeconfig # 或者永久合并到你的默认kubeconfig # mkdir -p ~/.kube # cp ./kubeconfig ~/.kube/config_vishwakarma # export KUBECONFIG~/.kube/config:~/.kube/config_vishwakarma验证集群状态kubectl cluster-info kubectl get nodes -o wide你应该能看到所有Master和Worker节点并且状态都是Ready。如果Worker节点长时间处于NotReady可以SSH到堡垒机然后跳转到Worker节点上查看kubelet日志journalctl -u kubelet -f。配置AWS IAM身份映射 默认的kubeconfig使用了aws-iam-authenticator但它需要知道哪个AWS IAM用户或角色可以映射为K8s集群内的用户/权限。你需要创建一个aws-authConfigMap。Vishwakarma可能没有自动完成这一步。一个简单的方法是先给运行Terraform的IAM实体用户或角色赋予集群管理员权限。首先获取你的AWS账户ID和用户名aws sts get-caller-identity --query Account --output text aws iam get-user --query User.UserName --output text # 如果你用的是IAM角色可能需要其他方式获取身份信息创建一个aws-auth.yaml文件apiVersion: v1 kind: ConfigMap metadata: name: aws-auth namespace: kube-system data: mapUsers: | - userarn: arn:aws:iam::YOUR_AWS_ACCOUNT_ID:user/YOUR_IAM_USERNAME username: admin groups: - system:masters应用这个配置kubectl apply -f aws-auth.yaml完成后你的kubectl命令就应该有权限执行了。4. 深入核心模块与高级配置解析搭建起来只是第一步理解每个模块的细节才能让你真正驾驭它。4.1aws/elastikube模块控制平面的魔法这个模块是精髓。我们来看看它如何实现高可用。etcd集群它会在不同的私有子网中创建多个EC2实例通常与Master节点数量一致或为奇数个形成一个分布式etcd集群。节点间通过TLS证书进行加密通信这些证书在Terraform运行过程中动态生成并注入Ignition配置。etcd的数据盘通常会被挂载并格式化为独立的EBS卷便于备份和恢复。Master节点与负载均衡器多个Master节点前面会部署一个内部网络负载均衡器NLB。kube-apiserver监听在NLB后面。Worker节点和kubectl都通过这个NLB的DNS名称来访问API Server。这样任何一个Master节点宕机NLB会自动将流量路由到健康的节点实现了API Server层面的高可用。Ignition配置这是CoreOS生态的核心。Terraform会生成一个.ignIgnition配置文件其内容是一个JSON定义了系统drops、磁盘分区、用户、systemd服务单元等。这个文件被传递给AWS User-Data实例启动时Ignition进程会首先执行它安装Docker/containerd、kubelet下载K8s组件二进制文件并启动所有必要的服务。整个过程无需人工干预。4.2aws/kube-worker模块灵活的工作节点管理这个模块的灵活性体现在对AWS Auto Scaling Group (ASG) 和 Launch Template的深度利用上。混合实例策略通过worker_spot_enabled和worker_spot_price等变量你可以轻松配置一个同时包含按需实例和竞价实例的ASG。这对于批处理任务、开发环境等非核心业务能节省大量成本。ASG会负责维持你设定的期望节点数量。节点标签与污点你可以在变量中为Worker组添加自定义的K8s标签node_labels和污点node_taints。这样在部署应用时可以使用nodeSelector或tolerations来精确控制Pod调度到哪些节点组上。例如你可以创建一个带spottrue:NoSchedule污点的Spot节点组只有明确容忍此污点的Pod才会被调度上去。自定义用户数据除了基本的Ignition配置加入集群你还可以通过worker_additional_ignition_config变量注入额外的Ignition配置片段用于在节点启动时安装监控代理、日志收集器如Fluentd或任何你需要的自定义软件包。4.3 网络插件选型与配置在variables.tf或你的terraform.tfvars中你可以找到network_plugin这个变量可选值为amazon-vpc(AWS VPC CNI),flannel, 或cilium。选择amazon-vpc这是与AWS集成最深的方案。每个Pod会获得一个真实的VPC IP地址。你需要确保VPC的子网有足够大的CIDR块或者使用辅助CIDR来容纳大量Pod。性能最好但需要管理VPC的IP地址空间。选择flannel经典的Overlay网络使用VXLAN封装。Pod网络是一个独立于VPC的CIDR。配置简单不占用VPC IP但会引入少量的网络开销且Pod IP在VPC内不可直接路由。选择cilium基于eBPF的新一代方案提供高性能和强大的网络策略、可观测性功能。选择它意味着你希望利用更先进的网络特性但可能需要更深入的学习。配置要点切换网络插件通常需要在集群创建之初就确定。后期更换非常麻烦几乎等同于重建集群。所以务必根据你的应用需求是否需要与AWS服务直接Pod通信是否对网络性能有极致要求提前做好选择。5. 运维实践、问题排查与经验分享集群跑起来只是开始日常运维和问题排查才是真正的战场。5.1 节点滚动更新与集群升级Vishwakarma通过ASG的Launch Template来管理节点镜像。当你想更新CoreOS版本或修改节点配置时修改Terraform配置中与节点相关的变量例如container_linux_channel从stable改为beta或者修改Ignition配置。运行terraform apply。Terraform会创建新的Launch Template版本。手动触发ASG实例刷新Terraform默认不会强制替换运行中的实例。你需要到AWS控制台找到对应的Worker ASG执行“开始实例刷新”操作选择“滚动更新”策略ASG会逐步用新配置的实例替换旧实例。重要提示对于Master节点滚动更新要格外小心。因为etcd和K8s控制平面组件有严格的版本兼容性和启动顺序要求。建议先仔细阅读K8s官方升级文档并考虑在维护窗口内通过修改master_ignition_config并逐个节点替换的方式手动操作而不是依赖ASG自动刷新。5.2 常见问题排查速查表问题现象可能原因排查步骤与解决方案terraform apply失败提示IAM权限不足执行Terraform的IAM用户/角色缺少必要权限。1. 检查错误信息中明确指出的API操作如ec2:RunInstances,iam:CreateRole。2. 为IAM实体附加相应的AWS托管策略如AdministratorAccess用于测试生产环境应遵循最小权限原则定制策略。Worker节点状态为NotReadykubelet未能成功启动或无法连接API Server。1. SSH到堡垒机再跳转到故障Worker节点。2. 检查kubelet服务状态journalctl -u kubelet -f --no-pager。3. 常见原因网络插件Pod未就绪检查kubectl get pods -n kube-system、节点CIDR冲突、或kubelet证书问题。kubectl命令报错Unauthorized或Forbiddenaws-authConfigMap未配置或配置错误。1. 确认已创建并正确配置了aws-authConfigMapkubectl describe configmap aws-auth -n kube-system。2. 检查映射的IAM ARN是否正确无误。3. 确保aws-iam-authenticator版本与集群兼容。Pod网络不通无法跨节点通信网络插件CNI未正确安装或配置。1. 检查CNI相关的DaemonSet是否运行正常kubectl get ds -n kube-system。2. 查看CNI Pod的日志kubectl logs -n kube-system -l k8s-appcni-pod-label。3. 检查节点路由表和安全组规则确保放行了CNI所需的端口如VXLAN的4789端口或主机网络的端口。无法通过SSH连接堡垒机或节点安全组未开放22端口或密钥对错误。1. 检查堡垒机实例关联的安全组确保入站规则允许你的IP访问22端口。2. 确认SSH命令使用的私钥路径和权限chmod 400正确。3. 通过AWS控制台的“实例连接”功能尝试连接以排除网络问题。执行terraform destroy时资源删除失败有依赖资源未删除如S3桶非空、EBS卷被挂载。1. 手动清空S3存储桶特别是存放kubeconfig和日志的桶。2. 检查是否有EBS卷因“删除时终止”未勾选而残留。3. 最彻底的方法在AWS控制台按资源创建顺序手动删除VPC、ELB、EC2、IAM等最后再运行terraform destroy。5.3 生产环境部署建议与个人心得状态文件远程存储千万不要将terraform.tfstate文件只保存在本地。使用S3后端配合DynamoDB表做状态锁是标准做法。这能保证团队协作时状态一致并防止并发操作。在项目根目录创建backend.tf文件配置远程后端。分离环境与模块复用为开发、测试、生产环境创建不同的Terraform工作目录或使用Terraform Workspace并利用模块化特性将网络、集群等配置抽象为可复用的模块通过传递不同的变量值来区分环境。秘密管理Terraform配置中可能包含敏感信息如证书私钥。切勿直接写入.tf文件。使用Terraform的sensitive变量标记并利用AWS Secrets Manager或HashiCorp Vault来注入这些秘密。在Vishwakarma中很多证书是在内部动态生成的这相对安全。监控与日志集群创建后第一时间部署监控系统如Prometheus Operator和日志收集方案如EFK栈。CoreOS节点上的journald是查看系统和服务日志的关键工具。关于成本除了使用Spot实例合理选择实例类型、设置ASG的伸缩策略、定期清理未使用的EBS卷和快照都是控制AWS账单的有效手段。使用t3系列等新一代实例类型通常性价比更高。在我自己的使用经验里Vishwakarma最大的优势在于它将一个极其复杂的过程标准化、代码化了。它可能不像一些全托管服务那样“一键无忧”但它给了你完全的透明度和控制权。当你需要排查一个深层次问题时你能清楚地知道每一个组件是如何被配置和启动的这对于构建稳定可靠的基础设施至关重要。当然这也意味着你需要投入更多时间去学习和理解其内部机制。不过对于追求“基础设施即代码”和“可重复性”的团队来说这份投入是绝对值得的。