如何通过单次Terraform Apply完成EKS集群创建与Kubernetes部署?
实现单次Terraform Apply完成EKS创建、镜像构建与K8s部署
核心方案:动态配置Kubernetes Provider
Terraform支持通过资源输出值动态配置Provider参数,结合依赖关系确保K8s Provider在EKS集群创建完成后才初始化。以下是完整实现步骤:
1. 配置AWS Provider与EKS集群资源
先定义AWS Provider,创建EKS集群、节点组及存储镜像的ECR仓库:
provider "aws" { region = "us-east-1" # 替换为你的目标区域 } # 创建ECR仓库存储自定义镜像 resource "aws_ecr_repository" "app_repo" { name = "my-custom-app" image_tag_mutability = "MUTABLE" } # EKS集群IAM角色 resource "aws_iam_role" "eks_cluster" { name = "eks-cluster-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "eks.amazonaws.com" } }] }) } resource "aws_iam_role_policy_attachment" "eks_cluster_policy" { role = aws_iam_role.eks_cluster.name policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy" } # 创建EKS集群 resource "aws_eks_cluster" "main" { name = "my-eks-cluster" role_arn = aws_iam_role.eks_cluster.arn vpc_config { subnet_ids = aws_subnet.private.*.id # 替换为你的私有子网ID列表 } depends_on = [aws_iam_role_policy_attachment.eks_cluster_policy] } # EKS节点组IAM角色 resource "aws_iam_role" "eks_node" { name = "eks-node-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "ec2.amazonaws.com" } }] }) } resource "aws_iam_role_policy_attachment" "eks_node_policy" { role = aws_iam_role.eks_node.name policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy" } resource "aws_iam_role_policy_attachment" "eks_node_cni_policy" { role = aws_iam_role.eks_node.name policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy" } # 创建EKS节点组 resource "aws_eks_node_group" "main" { cluster_name = aws_eks_cluster.main.name node_group_name = "my-node-group" node_role_arn = aws_iam_role.eks_node.arn subnet_ids = aws_subnet.private.*.id scaling_config { desired_size = 2 min_size = 1 max_size = 3 } depends_on = [ aws_iam_role_policy_attachment.eks_node_policy, aws_eks_cluster.main ] }
2. 获取EKS集群认证令牌
通过aws_eks_cluster_auth数据源获取集群访问令牌,用于Kubernetes Provider认证:
data "aws_eks_cluster_auth" "main" { name = aws_eks_cluster.main.name depends_on = [aws_eks_cluster.main] }
3. 动态配置Kubernetes Provider
直接引用EKS集群的输出值配置K8s Provider,Terraform会自动处理依赖,确保集群就绪后才初始化Provider:
provider "kubernetes" { host = aws_eks_cluster.main.endpoint cluster_ca_certificate = base64decode(aws_eks_cluster.main.certificate_authority.0.data) token = data.aws_eks_cluster_auth.main.token # 显式依赖节点组,确保节点加入集群后再部署资源 depends_on = [aws_eks_node_group.main] }
4. 构建并推送自定义Docker镜像
使用docker_image资源构建镜像,并通过本地命令登录ECR完成推送:
resource "docker_image" "custom_app" { name = "${aws_ecr_repository.app_repo.repository_url}:latest" build { context = "./app" # 替换为你的Dockerfile所在目录路径 dockerfile = "Dockerfile" } # 登录ECR并推送镜像 provisioner "local-exec" { command = "aws ecr get-login-password --region ${var.region} | docker login --username AWS --password-stdin ${aws_ecr_repository.app_repo.repository_url}" } depends_on = [aws_ecr_repository.app_repo] }
5. 部署Kubernetes应用
定义Deployment资源,Terraform会在镜像推送完成、集群就绪后自动部署Pod:
resource "kubernetes_deployment" "app_deployment" { metadata { name = "custom-app" labels = { app = "custom-app" } } spec { replicas = 2 selector { match_labels = { app = "custom-app" } } template { metadata { labels = { app = "custom-app" } } spec { container { image = docker_image.custom_app.name name = "custom-app" port { container_port = 80 } } } } } depends_on = [docker_image.custom_app] }
关键注意事项
- 执行顺序:通过
depends_on严格控制资源创建顺序:ECR仓库 → EKS集群/节点组 → K8s Provider → 镜像构建推送 → K8s部署。 - 环境要求:执行
terraform apply的机器需安装Docker和AWS CLI,且配置足够权限操作EKS、ECR资源。 - 节点就绪:Kubernetes Provider依赖节点组,确保节点成功加入集群后再部署应用,避免Pod调度失败。
内容的提问来源于stack exchange,提问作者curiousgeek
相关产品推荐
相关产品推荐

