跳转到内容
搜索 RunEntLinux 文档

仅搜索 RunEntLinux 通用文档,各发行版文档使用各自的搜索入口。

    浏览当前文档目录

    Terraform 基础

    Terraform 是 HashiCorp 开发的基础设施即代码(Infrastructure as Code, IaC)工具,使用声明式配置语言 HCL(HashiCorp Configuration Language)来定义和管理云资源。通过 Terraform,你可以用代码描述完整的基础设施架构,实现版本控制和可重复部署。

    通过官方仓库安装(EL 9 / EL 10)
    # 安装 DNF 插件(提供 config-manager)
    sudo dnf install -y dnf-plugins-core
    # 添加 HashiCorp 官方仓库
    # 说明:EL10 的包管理器仍是 DNF 4(4.20),`config-manager --add-repo` 的语法与 EL9 相同
    sudo dnf config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
    # 安装 Terraform
    sudo dnf install -y terraform
    # 验证安装
    terraform version
    Terminal window
    # 下载最新版本(访问 https://developer.hashicorp.com/terraform/install 确认最新版本号)
    TERRAFORM_VERSION="1.9.0" # 示例版本,请替换为官网最新版本号
    wget https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip
    # 解压并安装
    sudo dnf install -y unzip
    unzip terraform_${TERRAFORM_VERSION}_linux_amd64.zip
    sudo mv terraform /usr/local/bin/
    sudo chmod +x /usr/local/bin/terraform
    # 验证
    terraform version
    Terminal window
    # 安装自动补全
    terraform -install-autocomplete
    # 重新加载 shell
    source ~/.bashrc

    Terraform 配置文件使用 .tf 扩展名,采用 HCL 语法。

    # 注释以 # 开头
    # 块(Block)结构
    resource "类型" "名称" {
    参数1 = "值1"
    参数2 = 123
    # 嵌套块
    nested_block {
    key = "value"
    }
    }
    # 字符串插值
    variable "name" {
    default = "myserver"
    }
    resource "example" "demo" {
    name = "prefix-${var.name}"
    }
    # 字符串
    name = "web-server"
    # 数字
    count = 3
    # 布尔值
    enabled = true
    # 列表
    availability_zones = ["cn-hangzhou-a", "cn-hangzhou-b"]
    # 映射(Map)
    tags = {
    Name = "web-server"
    Environment = "production"
    Team = "ops"
    }

    Provider 是 Terraform 与云平台交互的插件。

    providers.tf
    terraform {
    required_version = ">= 1.5.0"
    required_providers {
    aws = {
    source = "hashicorp/aws"
    version = "~> 5.0"
    }
    }
    }
    provider "aws" {
    region = "ap-northeast-1" # 东京区域
    access_key = var.aws_access_key
    secret_key = var.aws_secret_key
    # 或者使用环境变量(推荐):
    # export AWS_ACCESS_KEY_ID="your-access-key"
    # export AWS_SECRET_ACCESS_KEY="your-secret-key"
    }
    providers.tf
    terraform {
    required_version = ">= 1.5.0"
    required_providers {
    alicloud = {
    source = "aliyun/alicloud"
    version = "~> 1.220"
    }
    }
    }
    provider "alicloud" {
    region = "cn-hangzhou"
    access_key = var.alicloud_access_key
    secret_key = var.alicloud_secret_key
    }
    # variables.tf - 变量定义
    variable "aws_access_key" {
    description = "AWS Access Key"
    type = string
    sensitive = true
    }
    variable "aws_secret_key" {
    description = "AWS Secret Key"
    type = string
    sensitive = true
    }
    variable "instance_type" {
    description = "EC2 实例类型"
    type = string
    default = "t3.micro"
    }
    variable "instance_count" {
    description = "实例数量"
    type = number
    default = 1
    }
    # main.tf - 主配置文件
    # 查询最新的 AlmaLinux 9 AMI
    data "aws_ami" "almalinux9" {
    most_recent = true
    owners = ["764336703387"] # AlmaLinux 官方
    filter {
    name = "name"
    values = ["AlmaLinux OS 9*x86_64*"]
    }
    filter {
    name = "virtualization-type"
    values = ["hvm"]
    }
    }
    # 创建安全组
    resource "aws_security_group" "web" {
    name = "web-sg"
    description = "Allow HTTP and SSH"
    ingress {
    from_port = 22
    to_port = 22
    protocol = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
    description = "SSH"
    }
    ingress {
    from_port = 80
    to_port = 80
    protocol = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
    description = "HTTP"
    }
    ingress {
    from_port = 443
    to_port = 443
    protocol = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
    description = "HTTPS"
    }
    egress {
    from_port = 0
    to_port = 0
    protocol = "-1"
    cidr_blocks = ["0.0.0.0/0"]
    }
    tags = {
    Name = "web-security-group"
    }
    }
    # 创建 EC2 实例
    resource "aws_instance" "web" {
    count = var.instance_count
    ami = data.aws_ami.almalinux9.id
    instance_type = var.instance_type
    vpc_security_group_ids = [aws_security_group.web.id]
    user_data = <<-EOF
    #!/bin/bash
    dnf install -y nginx
    systemctl enable --now nginx
    echo "<h1>Server ${count.index + 1}</h1>" > /usr/share/nginx/html/index.html
    EOF
    tags = {
    Name = "web-server-${count.index + 1}"
    Env = "production"
    }
    }
    # outputs.tf - 输出定义
    output "instance_public_ips" {
    description = "实例公网 IP 列表"
    value = aws_instance.web[*].public_ip
    }
    output "instance_ids" {
    description = "实例 ID 列表"
    value = aws_instance.web[*].id
    }
    output "ami_id" {
    description = "使用的 AMI ID"
    value = data.aws_ami.almalinux9.id
    }
    # main.tf - 阿里云 ECS 示例
    variable "alicloud_access_key" {
    type = string
    sensitive = true
    }
    variable "alicloud_secret_key" {
    type = string
    sensitive = true
    }
    # 查询可用区
    data "alicloud_zones" "default" {
    available_resource_creation = "VSwitch"
    }
    # 查询镜像
    data "alicloud_images" "almalinux" {
    name_regex = "^almalinux_9"
    most_recent = true
    owners = "system"
    }
    # 创建 VPC
    resource "alicloud_vpc" "main" {
    vpc_name = "tf-demo-vpc"
    cidr_block = "172.16.0.0/16"
    }
    # 创建交换机
    resource "alicloud_vswitch" "main" {
    vswitch_name = "tf-demo-vsw"
    vpc_id = alicloud_vpc.main.id
    cidr_block = "172.16.1.0/24"
    zone_id = data.alicloud_zones.default.zones[0].id
    }
    # 创建安全组
    resource "alicloud_security_group" "web" {
    name = "tf-demo-sg"
    vpc_id = alicloud_vpc.main.id
    }
    resource "alicloud_security_group_rule" "allow_ssh" {
    type = "ingress"
    ip_protocol = "tcp"
    port_range = "22/22"
    security_group_id = alicloud_security_group.web.id
    cidr_ip = "0.0.0.0/0"
    }
    resource "alicloud_security_group_rule" "allow_http" {
    type = "ingress"
    ip_protocol = "tcp"
    port_range = "80/80"
    security_group_id = alicloud_security_group.web.id
    cidr_ip = "0.0.0.0/0"
    }
    # 创建 ECS 实例
    resource "alicloud_instance" "web" {
    instance_name = "tf-demo-ecs"
    image_id = data.alicloud_images.almalinux.images[0].id
    instance_type = "ecs.t6-c1m1.large"
    security_groups = [alicloud_security_group.web.id]
    vswitch_id = alicloud_vswitch.main.id
    internet_max_bandwidth_out = 10
    system_disk_size = 40
    user_data = base64encode(<<-EOF
    #!/bin/bash
    dnf install -y nginx
    systemctl enable --now nginx
    EOF
    )
    tags = {
    Name = "web-server"
    Env = "demo"
    }
    }
    output "public_ip" {
    value = alicloud_instance.web.public_ip
    }
    Terminal window
    # 进入项目目录
    cd /opt/terraform/myproject
    # 初始化(下载 Provider 插件)
    terraform init
    # 升级 Provider 版本
    terraform init -upgrade
    Terminal window
    # 查看计划(预览将要执行的变更)
    terraform plan
    # 将计划保存到文件
    terraform plan -out=tfplan
    # 使用变量文件
    terraform plan -var-file="production.tfvars"
    # 传递单个变量
    terraform plan -var="instance_count=3"
    Terminal window
    # 应用变更(会要求确认)
    terraform apply
    # 使用保存的计划文件(无需确认)
    terraform apply tfplan
    # 自动确认(用于 CI/CD)
    terraform apply -auto-approve
    # 使用变量文件
    terraform apply -var-file="production.tfvars"
    Terminal window
    # 销毁所有资源
    terraform destroy
    # 自动确认销毁
    terraform destroy -auto-approve
    # 仅销毁指定资源
    terraform destroy -target=aws_instance.web
    Terminal window
    # 格式化配置文件
    terraform fmt
    # 递归格式化
    terraform fmt -recursive
    # 验证配置语法
    terraform validate
    # 查看当前状态
    terraform show
    # 列出所有资源
    terraform state list
    # 查看特定资源的详细信息
    terraform state show aws_instance.web[0]
    # 刷新状态(同步远端实际状态)
    terraform refresh
    # 生成依赖关系图
    terraform graph | dot -Tpng > graph.png

    使用 .tfvars 文件管理不同环境的变量:

    production.tfvars
    instance_type = "t3.large"
    instance_count = 3
    staging.tfvars
    instance_type = "t3.micro"
    instance_count = 1
    Terminal window
    # 使用不同环境的变量
    terraform apply -var-file="production.tfvars"
    terraform apply -var-file="staging.tfvars"

    通过环境变量传递敏感信息:

    Terminal window
    # Terraform 会自动读取 TF_VAR_ 前缀的环境变量
    export TF_VAR_aws_access_key="AKIAIOSFODNN7EXAMPLE"
    export TF_VAR_aws_secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
    terraform apply

    Terraform 状态文件(terraform.tfstate)记录了基础设施的当前状态。在团队协作中,应使用远程后端存储状态文件。

    Terminal window
    # 状态文件位于项目目录
    ls -la terraform.tfstate
    ls -la terraform.tfstate.backup
    terraform {
    backend "s3" {
    bucket = "my-terraform-state"
    key = "production/terraform.tfstate"
    region = "ap-northeast-1"
    encrypt = true
    dynamodb_table = "terraform-lock" # 状态锁定
    }
    }
    terraform {
    backend "oss" {
    bucket = "my-terraform-state"
    prefix = "production"
    region = "cn-hangzhou"
    encrypt = true
    tablestore_endpoint = "https://tf-state-lock.cn-hangzhou.ots.aliyuncs.com"
    tablestore_table = "terraform-lock"
    }
    }
    Terminal window
    # 列出状态中的资源
    terraform state list
    # 查看资源详情
    terraform state show aws_instance.web[0]
    # 移动资源(重命名)
    terraform state mv aws_instance.web aws_instance.webserver
    # 从状态中移除资源(不删除实际资源)
    terraform state rm aws_instance.web[0]
    # 导入已有资源到 Terraform 管理
    terraform import aws_instance.web i-0abc123def456
    # 拉取远程状态
    terraform state pull > state.json
    # 推送状态到远端
    terraform state push state.json

    模块(Module)用于封装和复用 Terraform 配置。

    Terminal window
    # 模块目录结构
    mkdir -p modules/ecs-instance
    modules/ecs-instance/variables.tf
    variable "instance_name" {
    description = "实例名称"
    type = string
    }
    variable "instance_type" {
    description = "实例规格"
    type = string
    default = "ecs.t6-c1m1.large"
    }
    variable "image_id" {
    description = "镜像 ID"
    type = string
    }
    variable "vswitch_id" {
    description = "交换机 ID"
    type = string
    }
    variable "security_group_id" {
    description = "安全组 ID"
    type = string
    }
    variable "tags" {
    description = "资源标签"
    type = map(string)
    default = {}
    }
    modules/ecs-instance/main.tf
    resource "alicloud_instance" "this" {
    instance_name = var.instance_name
    instance_type = var.instance_type
    image_id = var.image_id
    vswitch_id = var.vswitch_id
    security_groups = [var.security_group_id]
    internet_max_bandwidth_out = 10
    system_disk_size = 40
    tags = var.tags
    }
    modules/ecs-instance/outputs.tf
    output "instance_id" {
    value = alicloud_instance.this.id
    }
    output "public_ip" {
    value = alicloud_instance.this.public_ip
    }
    output "private_ip" {
    value = alicloud_instance.this.private_ip
    }
    # main.tf - 使用自定义模块
    module "web_server" {
    source = "./modules/ecs-instance"
    instance_name = "web-server-01"
    instance_type = "ecs.t6-c1m1.large"
    image_id = data.alicloud_images.almalinux.images[0].id
    vswitch_id = alicloud_vswitch.main.id
    security_group_id = alicloud_security_group.web.id
    tags = {
    Role = "web"
    Env = "production"
    }
    }
    module "api_server" {
    source = "./modules/ecs-instance"
    instance_name = "api-server-01"
    instance_type = "ecs.c6.large"
    image_id = data.alicloud_images.almalinux.images[0].id
    vswitch_id = alicloud_vswitch.main.id
    security_group_id = alicloud_security_group.web.id
    tags = {
    Role = "api"
    Env = "production"
    }
    }
    output "web_server_ip" {
    value = module.web_server.public_ip
    }
    output "api_server_ip" {
    value = module.api_server.public_ip
    }
    # 使用 Terraform Registry 上的模块
    module "vpc" {
    source = "alibaba/vpc/alicloud"
    version = "1.10.0"
    vpc_name = "production-vpc"
    vpc_cidr = "10.0.0.0/8"
    }
    terraform-project/
    ├── environments/
    │ ├── production/
    │ │ ├── main.tf
    │ │ ├── variables.tf
    │ │ ├── outputs.tf
    │ │ ├── terraform.tfvars
    │ │ └── backend.tf
    │ └── staging/
    │ ├── main.tf
    │ ├── variables.tf
    │ ├── outputs.tf
    │ ├── terraform.tfvars
    │ └── backend.tf
    ├── modules/
    │ ├── ecs-instance/
    │ ├── vpc/
    │ └── security-group/
    └── .gitignore

    为 Terraform 项目创建 .gitignore:

    Terminal window
    cat > .gitignore << 'EOF'
    # Terraform
    .terraform/
    *.tfstate
    *.tfstate.backup
    *.tfplan
    *.tfvars
    !example.tfvars
    # 敏感文件
    *.pem
    *.key
    EOF

    Terraform 是基础设施即代码的核心工具,将云资源的创建和管理纳入版本控制。配合 Cloud-Init 传入 user-data 和 Ansible 进行后续配置,三者共同构建出完整的自动化基础设施交付流水线。