实战基于Gitlab+Jenkins+Terraform的基础设施自动化方案
一 背景
在当今快速发展的云计算时代,企业对基础设施的管理需求越来越复杂,传统的手工管理方式已经无法满足快速迭代、高效运维的需求。为了应对这一挑战,基础设施自动化应运而生,它利用自动化工具将基础设施的配置、部署和管理流程自动化,从而提高效率、降低成本、增强安全性。
1. 传统基础设施管理的痛点
- 效率低下: 手工配置和部署基础设施需要大量时间和人力,无法满足快速迭代的需求。
- 错误率高: 手工操作容易出现错误,导致系统故障或安全漏洞。
- 难以维护: 手工管理的配置难以追踪和维护,难以保证一致性。
- 成本高昂: 人工成本、运维成本、故障修复成本等都比较高。
2. 基础设施自动化的优势
- 提高效率: 自动化工具可以快速完成基础设施的配置和部署,大大提高效率。
- 降低错误率: 自动化工具可以确保配置的准确性和一致性,降低错误率。
- 增强可维护性: 自动化工具可以记录配置和操作日志,方便追踪和维护。
- 降低成本: 减少人工成本、运维成本、故障修复成本。
3. Jenkins和Terraform的应用场景
- 持续集成和持续交付 (CI/CD): 使用Jenkins构建自动化流程,并使用Terraform管理基础设施,实现快速、可靠的CI/CD流程。
- 多云管理: 使用Terraform管理不同云平台上的基础设施,实现多云部署和管理。
- 基础设施即代码 (IaC): 将基础设施配置以代码的形式进行管理,提高可重复性和可控性。
- 云原生应用开发: 使用Terraform管理云原生应用所需的基础设施,例如容器、Kubernetes集群等。
二 相关概念
1. Jenkins
- 持续集成与持续交付 (CI/CD) 平台: Jenkins是一个开源的自动化服务器,提供了一个平台用于构建、测试和部署软件。它可以自动执行构建、测试和部署流程,帮助开发者更快地将代码交付到生产环境。
- 强大的插件生态系统: Jenkins拥有丰富的插件系统,支持各种语言、工具和云平台,可以满足不同的自动化需求。
- 灵活的配置: Jenkins提供灵活的配置选项,可以根据不同的需求定制自动化流程。
2. Terraform
- 基础设施即代码 (IaC) 工具: Terraform是一个开源的基础设施即代码工具,允许用户使用声明性配置语言定义和管理基础设施资源。
- 支持多种云平台: Terraform支持多种云平台,包括AWS、Azure、GCP、阿里云等。
- 强大的资源模型: Terraform提供丰富的资源模型,可以管理各种基础设施资源,例如虚拟机、网络、存储、数据库等
三 架构及详解
3.1 架构
3.2 工作流程
代码变更: 开发者将代码推送到代码仓库。
Jenkins 触发: Jenkins 自动检测到代码变更,并触发构建流程。
执行 Terraform: Jenkins 调用 Terraform,执行基础设施的创建或更新操作。
部署应用: Jenkins 部署应用程序到创建好的基础设施环境中。
四 实战
4.1 创建一个Jenkins Job
在Jenkins主页上,单击新建项目按钮。然后为管道命名并选择管道项目类型。
4.2 添加插件和安装软件
- Jenkins中安装Terraform
系统工具配置
如果安装失败,可以使用agent或者在jenkins服务器配置terraform命令
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
# 查看制定版本
yum --showduplicates list |grep terraform
# 查看制定版本
repoquery --show-duplicates terraform
# 安装制定版本
terraform install -y terraform-0:1.5.0-1.x86_64
- 添加pollscm插件。
4.3 开发代码并上传到Gitlab仓库
Jenkinsfile
pipeline {
agent any
parameters {
choice(name: 'ACTION', choices: ['apply', 'plan','destroy'], description: 'What action should Terraform take?')
}
environment {
TENCENTCLOUD_SECRET_ID = credentials('secret_id')
TENCENTCLOUD_SECRET_KEY = credentials('secret_key')
}
stages {
stage('apply/destory') {
steps {
script {
dir('cloud/tencent') {
sh 'terraform init'
sh 'terraform validate'
if (params.ACTION == 'plan') {
sh "terraform plan"
} else {
sh "terraform ${params.ACTION} -auto-approve"
}
}
}
}
}
}
}
tf文件核心
variable "region" {
type = string
default = "ap-hongkong"
}
variable "instance_name" {
type = string
default = "iac"
}
variable "password" {
type = string
default = "Wxxxxxm"
}
variable "os_name" {
type = string
default = "CentOS 7"
}
variable "username" {
type = string
default = "root"
}
locals {
cidr_block_vpc_name = "10.0.0.0/16"
cidr_block_subnet_name = "10.0.1.0/24"
count = 1
install_v2ray = "install.sh"
v2ray_port = 8080
v2ray_id = "65xxxx076"
# 密钥管理公钥
# public_key_content = file("/Users/xuel/.ssh/id_rsa.pub")
# 私钥
# privile_key_file = "/Users/xuel/.ssh/id_rsa"
// public_key_content = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDxxxx"
tag = {
name = "xuel"
}
username = can(regex("^(?i)ubuntu.*", lower(var.os_name))) ? "ubuntu" : var.username
}
data "template_file" "v2ray" {
template = file(format("./scripts/%s", local.install_v2ray))
vars = {
V2RAY_PORT = local.v2ray_port
V2RAY_ID = local.v2ray_id
}
}
data "tencentcloud_images" "image" {
image_type = ["PUBLIC_IMAGE"]
os_name = var.os_name
}
data "tencentcloud_instance_types" "instanceType" {
cpu_core_count = 8
memory_size = 16
filter {
name = "instance-charge-type"
values = ["POSTPAID_BY_HOUR"]
}
}
data "tencentcloud_availability_zones_by_product" "zone" {
product = "cvm"
}
resource "tencentcloud_vpc" "vpc" {
cidr_block = local.cidr_block_vpc_name
name = "xuel_tf_vpc"
tags = local.tag
}
resource "tencentcloud_subnet" "subnet" {
availability_zone = data.tencentcloud_availability_zones_by_product.zone.zones[0].name
cidr_block = local.cidr_block_subnet_name
name = "xuel_tf_subnet"
vpc_id = tencentcloud_vpc.vpc.id
tags = local.tag
}
resource "random_string" "random" {
length = 4
special = false
numeric = true
}
# resource "tencentcloud_key_pair" "xuel-tf-key" {
# key_name = "xuel_tf_publickey_${random_string.random.result}"
# public_key = local.public_key_content
# }
resource "tencentcloud_instance" "xuel_tf_ansible" {
availability_zone = data.tencentcloud_availability_zones_by_product.zone.zones[0].name
image_id = data.tencentcloud_images.image.images[0].image_id
# image_id = "img-mbw2jx7s"
instance_type = data.tencentcloud_instance_types.instanceType.instance_types[0].instance_type
vpc_id = tencentcloud_vpc.vpc.id
subnet_id = tencentcloud_subnet.subnet.id
// allocate_public_ip = true
system_disk_size = 50
# system_disk_type = "CLOUD_PREMIUM"
system_disk_type = "CLOUD_BSSD"
#system_disk_type = "CLOUD_SSD"
# key_name = tencentcloud_key_pair.tf-key.id
password = var.password
allocate_public_ip = true
internet_max_bandwidth_out = 40
# data_disks {
# data_disk_size = 50
# data_disk_type = "CLOUD_SSD"
# }
hostname = format("xuel-tf-v2ray-%d", count.index)
instance_charge_type = "POSTPAID_BY_HOUR"
count = local.count
instance_name = var.instance_name
tags = {
tagkey = "xtf_20240110"
}
}
resource "null_resource" "shell" {
count = local.count
triggers = {
instance_ids = element(tencentcloud_instance.xuel_tf_ansible.*.id, count.index)
}
provisioner "remote-exec" {
connection {
host = element(tencentcloud_instance._tf_ansible.*.public_ip, count.index)
type = "ssh"
user = local.username
password = var.password
timeout = 100000
}
inline = [
// 安装脚本
data.template_file.v2ray.rendered
]
}
}
output "summary" {
sensitive = true
value = {
// image = {for k,v in data.tencentcloud_images.image:k=>v}
// instanceType = {for k,v in data.tencentcloud_instance_types
// .instanceType:k=>v}
// zone = {for k,v in data.tencentcloud_availability_zones.zone: k=>v}
instance = { for k, v in tencentcloud_instance.xuel_tf_ansible : k => v }
}
}
output "public_ip" {
value = tencentcloud_instance.xuel_tf_ansible[0].public_ip
}
output "username" {
value = local.username
}
# output "instance_type" {
# value = data.tencentcloud_images.image
# }
output "image_list" {
value = {for k, v in data.tencentcloud_images.image: k => v}
}
provider "tencentcloud" {
region = var.region
# secret_id = var.secret_id
# secret_key = var.secret_key
}
terraform {
required_providers {
tencentcloud = {
source = "tencentcloudstack/tencentcloud"
version = "1.79.3"
}
}
}
脚本文件
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install docker-ce docker-ce-cli containerd.io -y
sudo systemctl start docker
sudo systemctl enable docker
目录结构
上传到git仓库
4.3 配置作业信息
现在,为这个管道作业填写一些细节。您可以添加Poll SCM来配置Jenkins定期轮询GitHub。该计划遵循cron的语法。例如,如果我们想每两分钟轮询一次,我们将在“管道”下使用:H/2****,从SCM、Git for SCM、我们的存储库URL和主分支中选择管道脚本。
- 添加gitlab凭据,用于jenkins登录gitlab
- 配置任务
注意gitlab触发的分支,以及Jenkinsfile在项目中的存放路径。
- 创建腾讯秘钥认证信息
针对敏感信息需要加密存储。
配置:Dashboard > ⚙ Manage Jenkins > Credentials
- 测试构建
由于Jenkinsfile中编写有参数化构建
部署选择apply
已成功安装软件和编排腾讯云
销毁选择destory
由于同一个流水线使用的为Jenkins本地的磁盘, /var/lib/jenkins/workspace/terraform-qcloud/cloud/tencent
同一个流水线不需要其他外部存储或者terraform的backend,存储在本地
五 注意事项
权限管理: 确保 Jenkins 用户具有足够的权限来执行 Terraform 命令。
安全配置: 使用合适的密码和密钥管理策略来保护敏感信息。
版本控制: 将 Terraform 配置文件保存在代码仓库中,并使用版本控制工具进行管理。
测试和验证: 在正式部署之前,要进行充分的测试和验证。
六 参考链接
- 点赞
- 收藏
- 关注作者
评论(0)