当前位置: 首页 > news >正文

Terraform整合到GitLab+Jenkins工具链

整体工作流程设计

GitLab(代码仓库) → Jenkins(CI/CD流水线) → Terraform(基础设施管理) → 云平台
  • 开发者在GitLab提交Terraform代码
  • GitLab触发Jenkins流水线
  • Jenkins执行Terraform计划、验证和部署
  • 最终在云平台创建/更新基础设施

阶段1:环境准备

1.1 安装必要工具

在Jenkins服务器上安装所需软件:

# 安装Terraform(以Linux为例)
sudo apt update && sudo apt install -y gnupg software-properties-common
wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install -y terraform# 安装Git(用于拉取代码)
sudo apt install -y git# 安装云平台CLI(以GCP为例)
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
echo "deb https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
sudo apt update && sudo apt install -y google-cloud-sdk

1.2 配置权限与凭证

1.2.1 GitLab凭证

  • 登录GitLab,进入个人设置 → Access Tokens
  • 创建令牌,权限勾选 read_repository(用于Jenkins拉取代码)
  • 保存令牌(如 gitlab-tf-token)

1.2.2 云平台凭证

以GCP为例:

  • 登录GCP控制台 → IAM与管理 → 服务账号
  • 创建服务账号(如 terraform-sa),授予权限:Editor(或最小权限集)
  • 为服务账号创建密钥(JSON格式),保存为 gcp-credentials.json

1.2.3 Jenkins凭证管理

  • 登录Jenkins → Manage Jenkins → Manage Credentials
  • 点击 (global) → Add Credentials,添加以下凭证:
    1. GitLab令牌:类型选择 Username with password,用户名任意,密码填GitLab令牌,ID设为 gitlab-credentials
    2. 云平台密钥:类型选择 Secret file,上传 gcp-credentials.json,ID设为 gcp-credentials

1.3 配置Terraform远程后端

使用GCS存储Terraform状态文件(已创建存储桶如 tf-state-bucket):

# main.tf 中配置后端
terraform {backend "gcs" {bucket = "tf-state-bucket"  # 替换为你的存储桶名# prefix通过Jenkins动态传入,不在这里硬编码}
}

阶段2:GitLab配置

2.1 创建Terraform代码仓库

在GitLab中创建仓库(如 terraform-infra),并按以下结构提交代码:

terraform-infra/
├── main.tf              # 主配置文件
├── variables.tf         # 变量定义
├── outputs.tf           # 输出定义

示例 main.tf 内容(创建GCP实例):

# 此代码与 Terraform 4.25.0 及向后兼容 4.25.0 的版本兼容。# 如需了解如何验证此 Terraform 代码,请参阅 https://developer.hashicorp.com/terraform/tutorials/gcp-get-started/google-cloud-platform-build#format-and-validate-the-configuration
terraform {required_providers {google = {source  = "hashicorp/google"version = "6.8.0"}}
}
provider "google" {project = var.projectcredentials = file("/root/.gcp-credentials.json")
}resource "google_compute_instance" "instance" {name = var.instance_namemachine_type = var.machine_typetags = var.network_tagszone = var.zoneboot_disk {auto_delete = truedevice_name = "var.instance_name"initialize_params {image = "projects/centos-cloud/global/images/centos-stream-9-v20250812"size  = var.disk_sizetype  = var.disk_type}mode = "READ_WRITE"}deletion_protection = truecan_ip_forward      = falseenable_display      = falselabels = {terraform             = "001"year                  = "2025"}metadata = {enable-osconfig = "TRUE"}network_interface {access_config {network_tier = "PREMIUM"}queue_count = 0stack_type  = "IPV4_ONLY"subnetwork  = "projects/${var.project}/regions/${element(split("-", var.zone), 0)}-${element(split("-", var.zone), 1)}/subnetworks/default"}scheduling {automatic_restart   = var.automatic_restarton_host_maintenance = "MIGRATE"preemptible         = falseprovisioning_model  = "STANDARD"}service_account {email  = "your@gserviceaccount.com"scopes = ["https://www.googleapis.com/auth/devstorage.read_write", "https://www.googleapis.com/auth/logging.write", "https://www.googleapis.com/auth/monitoring.write", "https://www.googleapis.com/auth/service.management.readonly", "https://www.googleapis.com/auth/servicecontrol", "https://www.googleapis.com/auth/trace.append"]}shielded_instance_config {enable_integrity_monitoring = trueenable_secure_boot          = falseenable_vtpm                 = true}}module "ops_agent_policy" {source        = "github.com/terraform-google-modules/terraform-google-cloud-operations/modules/ops-agent-policy"project       = var.projectzone          = var.zoneassignment_id = "goog-ops-agent-${var.instance_name}-${var.zone}"agents_rule = {package_state = "installed"version       = "latest"}instance_filter = {all = falseinclusion_labels = [{labels = {goog-ops-agent-policy = "v2-x86-template-1-4-0"}}]}
}
terraform {backend "gcs" {bucket = "tf-state-bucket"//prefix = "terraform/state/${var.project}/${var.zone}/vm/${var.instance_name}"}
}

示例 variables.tf 内容(创建GCP实例):

variable "project" {default = "your_project_id"
}
variable "instance_name" {default = "terrafrom-test-jenkins001"description = "Name of the instance"type        = stringvalidation {# 验证名称是否符合正则规则condition     = can(regex("^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$", var.instance_name))error_message = "不合法的 instance 名字, 必须匹配规则: ^[a-z]([-a-z0-9]{0,61}[a-z0-9])?."}
}variable "machine_type" {default = "e2-medium"
}variable "network_tags" {type = list(string)default = ["base", "office"]
}variable "disk_size" {description = "Number of disk size."type        = numberdefault = 60validation {condition     = var.disk_size >= 50error_message = "磁盘大小 ${var.disk_size} GB 不符合要求!磁盘大小必须大于或等于 50 GB。"}
}variable "automatic_restart" {description = "Number of disk size."type        = booldefault = true
}variable "disk_type" {default = "pd-balanced"
}
variable "metadata" {description = "A map of metadata key-value pairs to assign to the instance"type        = map(string)default     = {}  # 默认为空映射
}variable "zone" {default = "asia-east2-c"
}

示例 outputs.tf 内容(创建GCP实例):

output "instance_name" {value = google_compute_instance.instance.namedescription = "The name of the instance"
}output "机器类型" {value = google_compute_instance.instance.machine_typedescription = "The machine type of the instance"
}output "公网IP" {value = google_compute_instance.instance.network_interface.0.access_config.0.nat_ipdescription = "The external IP address of the instance"
}
output "内网IP" {value = google_compute_instance.instance.network_interface.0.network_ipdescription = "The internal IP address of the instance"
}
output "网络标记" {value = google_compute_instance.instance.tagsdescription = "The firewalld tags of the instance "
}output "磁盘信息" {value = "磁盘大小: ${google_compute_instance.instance.boot_disk.0.initialize_params.0.size}, 磁盘类型: ${google_compute_instance.instance.boot_disk.0.initialize_params.0.type}"description = "The boot disk info of the instance "
}

2.2 配置GitLab WebHook

让GitLab代码推送触发Jenkins流水线:

  • 在GitLab仓库 → Settings → Integrations
  • URL填写:http://:8080/gitlab-webhook/(需安装Jenkins的GitLab插件)
  • 勾选触发事件:Push events 和 Merge request events
  • 点击 Add webhook 并测试连接

阶段3:Jenkins配置

3.1 安装必要插件

  • 进入Jenkins → Manage Jenkins → Plugins
  • 安装以下插件:
    • GitLab Plugin(GitLab集成)
    • Pipeline(流水线支持)
    • Credentials Binding(凭证绑定)

3.2 创建Jenkins流水线项目

  1. 新建项目 → 选择 Pipeline,名称设为 terraform-pipeline
  2. 在 Pipeline 配置中:
    • 定义方式选择 Pipeline script from SCM
    • SCM选择 Git,Repository URL填写GitLab仓库地址(如 https://gitlab.com/your-org/terraform-infra.git)
    • Credentials选择 gitlab-credentials(之前创建的)
    • 脚本路径填写 Jenkinsfile(仓库中流水线文件的路径)

3.3 编写Jenkinsfile

在GitLab仓库中添加 Jenkinsfile,定义完整流水线:

pipeline {agent {node {label 'tes-agent'}}environment {GOOGLE_APPLICATION_CREDENTIALS = "/root/.gcp-credentials.json"}parameters {string(name: 'instance_name', defaultValue: '----------', description: '请输入实例名字 示例:terraform-instance-211')choice(name: 'zone', choices: ['asia-east1-b', 'asia-east2-a', 'asia-southeast1-b'], description: '实例区域 台湾:asia-east1-b 新加坡:asia-southeast1-b 香港:asia-east2-a')string(name: 'machine_type', defaultValue: 'e2-custom-2-4096', description: '机器类型 示例:e2-custom-2-4096')string(name: 'disk_size', defaultValue: '50', description: '磁盘大小 示例:50')choice(name: 'disk_type', choices: ['pd-balanced', 'pd-ssd'], description: '磁盘类型 pd-balanced:平衡性永久磁盘 pd-ssd:SSD永久性磁盘')text(name: 'network_tags', defaultValue: '["base", "office"]', description: '防火墙网络标记,每行一个标签')booleanParam(name: 'AUTO_APPROVE', defaultValue: false, description: '是否自动批准部署')}
  • options {
    timeout(time: 30, unit: ‘MINUTES’)

         disableConcurrentBuilds()}stages {stage('Pre-Build') {steps {// 构建开始前删除工作区deleteDir()echo 'Workspace deleted successfully'}}stage('拉取运维代码') {steps {checkout([$class: 'GitSCM',branches: [[name: 'terraform-test']],  // 分支配置doGenerateSubmoduleConfigurations: false,extensions: [cleanAfterCheckout()  // 配置 Clean after checkout],submoduleCfg: [],userRemoteConfigs: [[url: 'git@<gitlab-ip>.com:ops/devops.git',credentialsId: 'terraform-test-gitlab']]])}}stage('Terraform初始化') {steps {script {echo "初始化Terraform并配置远程后端..."sh '''cd ./terraform/gcp/vm/terraform init -backend-config="prefix=terraform/state/instance/${instance_name}"'''}}}stage('代码检查') {steps {script {echo "检查Terraform代码格式和语法..."sh '''# 格式检查(不符合则失败)cd ./terraform/gcp/vm/terraform fmtif ! terraform fmt -check; thenecho "代码格式不符合规范,请运行terraform fmt修复"exit 1fi# 语法验证terraform validate'''}}}stage('生成执行计划') {steps {script {echo "生成Terraform执行计划..."sh '''cd ./terraform/gcp/vm/terraform plan \-var "instance_name=${instance_name}" \-var "zone=${zone}" \-var "machine_type=${machine_type}" \-var "disk_size=${disk_size}" \-var "disk_type=${disk_type}" \-var "network_tags=${network_tags}" \-out=./tfplan_${zone}_${instance_name}'''}}}stage('Approval for Deployment') {steps {script {def approvalNote = timeout(time: 5, unit: 'MINUTES') {input(id: 'deployApproval',message: '是否批准部署到生产环境?',ok: '批准',parameters: [string(name: 'APPROVER_NOTE',defaultValue: '无特殊说明',description: '请输入审批备注(可选)')])}echo "审批通过!审批人备注:${approvalNote}"}}}stage('执行部署') {steps {script {echo "执行Terraform部署..."sh '''cd ./terraform/gcp/vm/terraform apply "tfplan_${zone}_${instance_name}"'''}}}}post {always {echo 'Pipeline 完成'}success {echo "成功在${zone}区域创建实例${instance_name}"// 可以添加通知逻辑}failure {echo "在${zone}区域创建实例${instance_name}失败"// 可以添加失败通知逻辑}}
    

    }

阶段4:测试与验证

  1. 触发流水线:
    • 方式1:向GitLab仓库推送代码,通过WebHook自动触发
    • 方式2:在Jenkins手动点击 Build with Parameters,选择环境后执行
  2. 验证结果:
    • 查看Jenkins控制台输出,确认各阶段执行成功

    • 登录云平台控制台,检查资源是否按预期创建

    • 查看GCS存储桶,确认状态文件已按环境路径(如 terraform/state/dev/)存储

关键最佳实践

  1. 安全控制:
    • 敏感凭证通过Jenkins安全存储,不暴露在代码中
    • 生产环境禁用 AUTO_APPROVE,必须人工确认
  2. 质量保障:加入代码格式化检查、语法验证和安全扫描
  3. 可追溯性:状态文件版本控制(GCS自动支持)+ 流水线日志归档

文章转载自:

http://MC30Xfh6.qywfw.cn
http://7kQixoob.qywfw.cn
http://VeFcRiuJ.qywfw.cn
http://O9oR8Mui.qywfw.cn
http://JB0054yY.qywfw.cn
http://QXCPkMNJ.qywfw.cn
http://cfJ9oOTT.qywfw.cn
http://CgueObd7.qywfw.cn
http://zULjNaQC.qywfw.cn
http://DDxj8wPB.qywfw.cn
http://7VCD53yl.qywfw.cn
http://5eVvLsHC.qywfw.cn
http://O4XYTrqJ.qywfw.cn
http://9uCmis9O.qywfw.cn
http://wORbuxIN.qywfw.cn
http://fmBePSnf.qywfw.cn
http://zUdIbNJM.qywfw.cn
http://TmQtv2se.qywfw.cn
http://YDKEYh4R.qywfw.cn
http://TzAHoDq6.qywfw.cn
http://U67Izv7v.qywfw.cn
http://ckSwxWNV.qywfw.cn
http://PDGhTKFh.qywfw.cn
http://8MNGQwB7.qywfw.cn
http://YWr7LcAR.qywfw.cn
http://RHayCdnc.qywfw.cn
http://d7QaD8Jg.qywfw.cn
http://CJULH6a5.qywfw.cn
http://glEARIjS.qywfw.cn
http://HppPICMh.qywfw.cn
http://www.dtcms.com/a/380023.html

相关文章:

  • android studio 断点无效
  • Prompt技术深度解析:从基础原理到前沿应用的全面指南
  • WPF报错 XDG000 Windows Presentation Foundation (WPF) 项目中不支持 Application
  • Docker的使用及核心命令
  • Jmeter测试
  • 神经网络基本概念
  • 【打包app】uniapp打包ios端和安卓端app
  • 【LeetCode 每日一题】3000. 对角线最长的矩形的面积
  • 制造业档案管理混乱:档案宝如何破解?
  • 第4周 数组的概念和常见操作
  • vue,uniapp 实现卷帘对比效果
  • 鸿蒙 NEXT UI 性能优化实战:打造流畅用户界面的关键策略
  • 使用UniApp实现一个AI对话页面
  • 智能科技与搜索引擎优化关键词的新契机
  • 搜维尔科技:全身可穿戴Teslasuit动捕服的功能,自立式FES装置
  • Java 大视界 -- Java 大数据在智能医疗健康档案数据分析与个性化健康管理中的应用(410)
  • RK3588 Android12默认移除导航栏
  • HBuilder 运行编译器内存溢出
  • lesson59:JavaScript 控制流详解:分支结构与循环语句全指南
  • Avalonia 基础导航实现:从页面切换到响应式交互全指南
  • 【连载2】C# MVC 自定义错误页设计:404/500 处理与 SEO 优化
  • java jdbc连接sqlserver2008R2版本数据库报错,驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接
  • 企业级AI大模型选型指南:从评估部署到安全实践
  • Spring Boot + Redis 缓存性能优化实战:从5秒到毫秒级的性能提升
  • 【Vue2手录09】购物车实战
  • 【论文阅读】Uncertainty Modeling for Out-of-Distribution Generalization (ICLR 2022)
  • PAT乙级_1111 对称日_Python_AC解法_无疑难点
  • Kafka面试精讲 Day 16:生产者性能优化策略
  • vue 批量自动引入并注册组件或路由
  • Kubernetes(K8s)详解