Terraform 容器管理
容器(Container)已经成为现代软件交付的核心。无论是 Docker 还是 Kubernetes,Terraform 都能通过 Provider 插件实现资源的统一管理,将容器基础设施纳入基础设施即代码(IaC)的体系中。这样不仅能带来一致性,还能借助版本控制、自动化测试与审查机制,大大提升团队的交付效率。
本章围绕以下几个主题展开:
- Docker 镜像与容器的本地/远程管理
- Kubernetes 集群的部署与配置
- 集群操作的认证与授权
- 使用 YAML 与 HCL 定义 Kubernetes 资源
- 网络策略与注解管理
- Helm 在容器部署与监控中的应用
- 使用 Nomad 调度容器
5.1 使用本地与远程 Docker 镜像
在 Terraform 中既可以使用远程仓库镜像(如 Docker Hub),也可以直接引用本地镜像。
# Docker Provider
provider "docker" {}
# 使用远程镜像
resource "docker_image" "remote_image" {
name = "nginx:latest"
}
resource "docker_container" "remote_container" {
name = "remote_nginx"
image = docker_image.remote_image.latest
}
# 使用本地镜像
resource "docker_image" "local_image" {
name = "custom-app:1.0"
keep_locally = true
}
resource "docker_container" "local_container" {
name = "local_app"
image = docker_image.local_image.latest
}
- 远程镜像:适合使用最新版本或共享的公共镜像。
- 本地镜像:适合自研镜像或无公网访问的环境。
💡 在企业级环境中常用私有镜像仓库(Harbor、ECR、GCR 等),Terraform 同样可以管理。
5.2 区分集群部署与配置
部署(Deployment):新建集群(例如 AWS EKS)。
配置(Configuration):在现有集群中添加资源(如命名空间)。
# 部署 EKS 集群
provider "aws" { region = "us-east-1" }
module "eks" {
source = "terraform-aws-modules/eks/aws"
cluster_name = "demo-cluster"
cluster_version = "1.20"
vpc_id = "vpc-xxxxxx"
subnets = ["subnet-1", "subnet-2"]
node_groups = {
eks_nodes = {
desired_capacity = 3
instance_type = "t3.medium"
}
}
}
# 配置集群:创建 namespace
provider "kubernetes" {
host = module.eks.cluster_endpoint
cluster_ca_certificate = base64decode(module.eks.cluster_ca_data)
token = data.aws_eks_cluster_auth.cluster.token
}
data "aws_eks_cluster_auth" "cluster" {
name = module.eks.cluster_id
}
resource "kubernetes_namespace" "demo" {
metadata { name = "demo-namespace" }
}
5.3 授权 Terraform 操作 Kubernetes 集群
Terraform 需要通过认证和权限才能操作集群。例如在 EKS 中:
provider "aws" { region = "us-east-1" }
data "aws_eks_cluster" "cluster" { name = "demo-cluster" }
data "aws_eks_cluster_auth" "cluster" { name = "demo-cluster" }
provider "kubernetes" {
host = data.aws_eks_cluster.cluster.endpoint
cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority[0].data)
token = data.aws_eks_cluster_auth.cluster.token
load_config_file = false
}
⚠️ 需要在 AWS IAM 中为 Terraform 执行角色授予访问 EKS 的权限。
5.4 使用 YAML 调度容器
Terraform 可以直接加载现有 Kubernetes YAML 配置:
resource "kubernetes_manifest" "app" {
manifest = yamldecode(file("${path.module}/deployment.yaml"))
}
deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
template:
spec:
containers:
- name: app
image: my-image:latest
ports:
- containerPort: 8080
5.5 使用 HCL 调度容器
同样可以直接在 Terraform 中用 HCL 编写:
resource "kubernetes_deployment" "app" {
metadata { name = "my-app" }
spec {
replicas = 3
selector { match_labels = { app = "my-app" } }
template {
metadata { labels = { app = "my-app" } }
spec {
container {
name = "app"
image = "my-image:latest"
port { container_port = 8080 }
}
}
}
}
}
5.6 YAML 转 HCL
可使用 terraform console 将 YAML 转换为 HCL:
terraform console
> jsonencode({
resource = {
kubernetes_manifest = {
example = {
manifest = yamldecode(file("deployment.yaml"))
}
}
}
})
5.7 调整 Kubernetes 注解
resource "kubernetes_deployment" "example" {
metadata {
name = "my-app"
annotations = {
"example.com/version" = "v1.0"
}
}
}
注解(Annotation)与标签(Label)的区别:
- Label:用于选择和分组资源。
- Annotation:存放元数据,如构建信息、监控配置。
5.8 动态调整 Deployment 配置
variable "replica_count" { default = 5 }
variable "image_version" { default = "v2" }
resource "kubernetes_deployment" "example" {
spec {
replicas = var.replica_count
template {
spec {
container {
name = "my-app"
image = "my-image:${var.image_version}"
env {
name = "ENV_VAR"
value = "demo"
}
}
}
}
}
}
执行时可动态覆盖参数:
terraform apply -var="replica_count=3" -var="image_version=v3"
5.9 应用 Kubernetes 网络策略 (NetworkPolicy)
resource "kubernetes_network_policy" "db_policy" {
metadata { name = "db-policy" namespace = "default" }
spec {
pod_selector { match_labels = { role = "db" } }
policy_types = ["Ingress", "Egress"]
ingress {
from { pod_selector { match_labels = { role = "frontend" } } }
ports { protocol = "TCP" port = 6379 }
}
egress {
to { pod_selector { match_labels = { role = "replica" } } }
ports { protocol = "TCP" port = 6379 }
}
}
}
💡 仅允许 frontend → db,db → replica 的流量。
5.10 使用 Helm 部署应用
provider "helm" {
kubernetes {}
}
resource "helm_release" "redis" {
name = "redis"
repository = "https://charts.bitnami.com/bitnami"
chart = "redis"
version = "17.3.14"
set {
name = "architecture"
value = "standalone"
}
}
Helm Provider 结合 Terraform,能将 Helm Release 纳入 Terraform 的状态管理。
5.11 使用 Helm 部署监控 (Prometheus + Grafana)
resource "helm_release" "prometheus" {
name = "prometheus"
repository = "https://prometheus-community.github.io/helm-charts"
chart = "prometheus"
version = "15.10.1"
}
resource "helm_release" "grafana" {
name = "grafana"
repository = "https://grafana.github.io/helm-charts"
chart = "grafana"
version = "6.43.1"
set {
name = "adminPassword"
value = "StrongPassword123!"
}
}
这样可以快速为 Kubernetes 部署可视化监控体系。
5.12 使用 HashiCorp Nomad 调度容器
除了 Kubernetes,Terraform 还支持 Nomad:
provider "nomad" {
address = "http://localhost:4646"
}
resource "nomad_job" "redis" {
jobspec = file("${path.module}/redis.nomad")
}
redis.nomad:
job "redis" {
datacenters = ["dc1"]
group "cache" {
task "redis" {
driver = "docker"
config { image = "redis:latest" }
}
}
}
Nomad 更适合混合调度(容器+非容器化应用)。
总结
- Terraform 能管理 Docker 和 Kubernetes 的容器工作负载,也能支持 Nomad。
- 在 Kubernetes 场景下,可以灵活选择 YAML / HCL / Helm。
- 网络策略(NetworkPolicy)、注解(Annotation)、环境变量等,都能通过 Terraform 精细化管理。
- Helm Provider 将 Helm Chart 纳入 Terraform 生命周期。
- Terraform 的统一入口让 容器编排与基础设施管理一致化,非常适合企业 DevOps 流程。