← 返回首页
🔧

Terraform Provider:多云资源管理

📂 devops ⏱ 4 min 680 words

Terraform Provider:多云资源管理

什么是Terraform Provider

Provider是Terraform与云平台、SaaS服务或其他API交互的插件。每个Provider负责理解和操作特定资源类型的CRUD操作。Terraform Registry提供了数千个Provider。

Provider配置

AWS Provider

# providers.tf

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

# 默认配置
provider "aws" {
  region = "us-west-2"
}

# 多区域配置
provider "aws" {
  alias  = "us_east"
  region = "us-east-1"
}

provider "aws" {
  alias  = "eu_west"
  region = "eu-west-1"
}

# 使用别名的资源
resource "aws_s3_bucket" "us" {
  provider = aws.us_east
  bucket   = "my-us-bucket"
}

resource "aws_s3_bucket" "eu" {
  provider = aws.eu_west
  bucket   = "my-eu-bucket"
}

Azure Provider

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.0"
    }
  }
}

provider "azurerm" {
  features {}
  
  # 使用Service Principal认证
  client_id       = var.client_id
  client_secret   = var.client_secret
  tenant_id       = var.tenant_id
  subscription_id = var.subscription_id
}

# 或使用环境变量
# export ARM_CLIENT_ID="xxx"
# export ARM_CLIENT_SECRET="xxx"
# export ARM_TENANT_ID="xxx"
# export ARM_SUBSCRIPTION_ID="xxx"

Google Cloud Provider

terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

provider "google" {
  project = "my-project-id"
  region  = "us-central1"
}

# 多项目配置
provider "google" {
  alias   = "project_b"
  project = "project-b-id"
  region  = "europe-west1"
}

resource "google_compute_instance" "project_a" {
  name         = "instance-a"
  machine_type = "n2-standard-2"
  zone         = "us-central1-a"
}

resource "google_compute_instance" "project_b" {
  provider     = google.project_b
  name         = "instance-b"
  machine_type = "n2-standard-2"
  zone         = "europe-west1-b"
}

Kubernetes Provider

terraform {
  required_providers {
    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = "~> 2.23"
    }
    helm = {
      source  = "hashicorp/helm"
      version = "~> 2.11"
    }
  }
}

provider "kubernetes" {
  config_path    = "~/.kube/config"
  config_context = "my-cluster"
}

provider "helm" {
  kubernetes {
    config_path = "~/.kube/config"
  }
}

# 使用Kubernetes Provider创建资源
resource "kubernetes_namespace" "app" {
  metadata {
    name = "my-app"
  }
}

resource "kubernetes_deployment" "app" {
  metadata {
    name      = "my-app"
    namespace = kubernetes_namespace.app.metadata[0].name
  }
  
  spec {
    replicas = 3
    
    selector {
      match_labels = {
        app = "my-app"
      }
    }
    
    template {
      metadata {
        labels = {
          app = "my-app"
        }
      }
      
      spec {
        container {
          name  = "my-app"
          image = "nginx:latest"
          
          port {
            container_port = 80
          }
        }
      }
    }
  }
}

多云配置

统一多云架构

# multi-cloud.tf

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.0"
    }
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

# AWS基础设施
module "aws_infra" {
  source = "./modules/aws"
  
  providers = {
    aws = aws.us_east
  }
  
  vpc_cidr = "10.0.0.0/16"
}

# Azure基础设施
module "azure_infra" {
  source = "./modules/azure"
  
  resource_group = "my-rg"
  location       = "East US"
}

# GCP基础设施
module "gcp_infra" {
  source = "./modules/gcp"
  
  providers = {
    google = google
  }
  
  project_id = "my-project"
}

跨云资源引用

# 使用外部数据源获取跨云信息
data "external" "aws_ip" {
  program = ["aws", "ec2", "describe-instances", "--query", "Reservations[0].Instances[0].PublicIpAddress", "--output", "text"]
}

# 创建跨云DNS记录
resource "aws_route53_record" "app" {
  zone_id = "Z1234567890"
  name    = "app.example.com"
  type    = "A"
  ttl     = 300
  records = [data.external.aws_ip.result.stdout]
}

Provider版本管理

版本锁定

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "= 5.0.0"  # 精确版本
    }
    azure = {
      source  = "hashicorp/azurerm"
      version = "~> 3.0"  # 兼容3.x
    }
    google = {
      source  = "hashicorp/google"
      version = ">= 4.0, < 6.0"  # 版本范围
    }
  }
}

版本升级

# 查看可用版本
terraform providers

# 升级Provider
terraform init -upgrade

# 查看版本约束
terraform version

自定义Provider

使用Terraform Plugin SDK

package main

import (
  "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
  "github.com/hashicorp/terraform-plugin-sdk/v2/plugin"
)

func Provider() *schema.Provider {
  return &schema.Provider{
    Schema: map[string]*schema.Schema{
      "api_key": {
        Type:        schema.TypeString,
        Required:    true,
        DefaultFunc: schema.EnvDefaultFunc("MY_API_KEY", nil),
        Description: "API密钥",
        Sensitive:   true,
      },
      "endpoint": {
        Type:        schema.TypeString,
        Optional:    true,
        Default:     "https://api.example.com",
        Description: "API端点",
      },
    },
    ResourcesMap: map[string]*schema.Resource{
      "myresource_instance": resourceMyResource(),
    },
    ConfigureFunc: providerConfigure,
  }
}

func main() {
  plugin.Serve(&plugin.ServeOpts{
    ProviderFunc: Provider,
  })
}

func providerConfigure(d *schema.ResourceData) (interface{}, error) {
  apiKey := d.Get("api_key").(string)
  endpoint := d.Get("endpoint").(string)
  
  client, err := NewClient(apiKey, endpoint)
  if err != nil {
    return nil, err
  }
  
  return client, nil
}

Provider调试

日志配置

# 启用调试日志
export TF_LOG=TRACE
export TF_LOG_PATH=./terraform.log

# 特定Provider日志
export TF_LOG=TRACE
export TF_LOG_PROVIDER=TRACE

# 运行Terraform
terraform plan

Provider缓存

# 清除Provider缓存
rm -rf .terraform/

# 手动下载Provider
terraform init -plugin-dir=./plugins

# 使用镜像缓存
terraform init \
  -filesystem-mirror=/path/to/mirror \
  -network-mirror=https://mirror.example.com

常见问题

# Provider版本冲突
# 查看依赖图
terraform providers graph | dot -Tpng > providers.png

# 认证失败
# 检查环境变量
env | grep -E "(AWS_|ARM_|GOOGLE_)"

# Provider下载失败
# 配置网络代理
export HTTP_PROXY=http://proxy:8080
export HTTPS_PROXY=http://proxy:8080
terraform init

最佳实践

  1. 版本锁定:在生产环境中锁定Provider版本
  2. 多区域/多账户:使用Provider别名区分
  3. 认证管理:使用环境变量或密钥管理服务
  4. 缓存配置:配置Provider镜像加速下载
  5. 定期更新:定期升级Provider获取新功能和修复