首页 基础设施自动化流水线

基础设施自动化流水线

更新时间: 2024-04-02 14:27:04

本方案提供一种基础架构代码配置CI/CD的解决方案,使用Terraform作为IaC语言,并整合Jenkins和Git实现Terraform代码的持续集成和版本控制。

方案概述

本文提供一种基础架构代码配置CI/CD的解决方案,使用Terraform作为IaC语言,并整合Jenkins和Git实现Terraform代码的持续集成和版本控制。结合阿里云OSS和OTS产品,对Terraform的状态文件(state文件)进行远端存储和加锁,实现多人协作。同时,集成第三方开源插件Terraform-compliance,实现对Terraform代码的合规审计操作,减小创建不安全资源带来的安全风险。

方案优势

基础设施代码化

基于IaC思想,将基础设施代码使用Terraform规范化,流水线运行使用版本化管理的Terraform代码,代码可扩展并减轻运维管理负担。

自动化集成及合规检测

代码提交后可自动运行流水线,流水线集成合规规则进行检测,保障Terraform合规。

客户场景

自动化管理基础设施配置变更

场景描述

基础设施即代码,所有对基础设施的改动都可通过代码实现。代码每次变更都会触发pipeline的部署。这既减小了手动部署的工作,也确保在不同运行环境下基础架构保证统一。

适用客户

希望使用Terraform自动化管理基础设施的企业客户。

方案架构

本方案主要目的是指导企业客户搭建一套管理Terraform代码变更的流水线。使用Git仓库管理Terraform代码,使用Jenkins进行CI/CD集成,使用Terraform-compliance插件进行合规审计,使用OSS + OTS作为Remote Backend实现多人协作及State文件安全。

产品费用及名词

产品费用

产品名称

产品说明

产品费用

资源目录RD

资源目录RD(Resource Directory)阿里云面向企业客户提供的一套多级账号和资源关系管理服务。

免费,详情参见产品定价

访问控制RAM

访问控制使您能够安全地集中管理对阿里云服务和资源的访问。您可以使用RAM创建和管理用户和组,并使用各种权限来运行或访问他们对云资源的访问。

免费。

容器镜像服务ACR

容器镜像服务ACR提供安全地镜像托管能力,稳定的国内外镜像构建服务,便捷的镜像授权功能,方便用户进行镜像全生命周期管理。

企业版收费,详情见产品计费

云服务器ECS

云服务器ECS(Elastic Compute Service)是阿里云提供的性能卓越、稳定可靠、弹性扩展的IaaS(Infrastructure as a Service)级别云计算服务

收费,详情参见产品计费

对象存储OSS

对象存储OSS(Object Storage Service)是阿里云提供的海量、安全、低成本、高持久的云存储服务。

收费,详情参见产品计费

表格存储OTS

表格存储(Tablestore)是阿里云自研的多模型结构化数据存储,提供海量结构化数据存储以及快速的查询和分析服务。

收费,详情参见产品定价

Jenkins

Jenkins是应用广泛的开源自动化CI/CD产品。

免费。

Docker

Docker容器化技术,用于支持创建和使用容器,实现对容器的高效创建、部署及复制,并能将其从一个环境顺利迁移至另一个环境,从而有助于针对云优化应用。

高级版收费,详情参见Pricing

名词解释

名称

说明

RAM用户

RAM用户是RAM的一种实体身份类型,有确定的身份ID和身份凭证,它通常与某个确定的人或应用程序一一对应。因安全原因不推荐直接使用云账号的AK/SK。因此在账号下创建一个RAM用户,授予RAM用户最小权限,使用该RAM用户的AK/SK。

State文件

Terraform中用于描述当前资源配置的文件,详情参见State。本文使用OSS + OTS作为State文件的远端存储,详情参见OSS Backend

安全性

Jenkins安全性

  • Jenkins需要进行安全加固,安全性详情参考官方文档Securing Jenkins
  • 当使用Jenkins并拥有大量用户及并发任务等情况时参考官方文档Scaling Jenkins

Terraform State文件安全

使用OSS作为Backend保存Terraform State文件,使用OTS支持State文件加锁及一致性检查,详情参见OSS Backend

Docker安全性

Docker安全性详情参见官方文档Security

AccessKey使用

资源操作的云账号下RAM用户AK至少需要拥有AliyunOSSFullAccess和AliyunOTSFullAccess权限,用于读写账号下的OSS和OTS实例,并根据实际情况添加要操作的云资源的权限。

注意事项

ECS使用限制

ECS存在一些产品功能和服务性能等限制,详情参见使用限制

OSS使用限制

OSS使用限制及性能指标详情参见使用限制

OTS使用限制

OTS使用限制详情参见使用限制

实施步骤

实施准备

  • 账号下已有RAM用户并已创建AccessKey,该RAM用户至少需要拥有AliyunOSSFullAccess和AliyunOTSFullAccess,用于读写账号下的OSS和OTS实例。
  • 账号已开通服务并创建一台ECS,ECS上已安装JenkinsDocker
  • 已开通OSS及OTS服务,OSS服务用于存储Terraform的state文件,OTS服务用于对state文件加锁,保证多人协作。
  • 通过ACR能够拉取到Docker镜像。本文中使用的Docker镜像已打包存储在阿里云镜像服务ACR之中,可通过 registry.cn-hangzhou.aliyuncs.com/terraform/terraform-docker-hub:v1 路径拉取,该镜像的Dockerfile如下所示,用户可根据自身需要修改并重新打包使用。
FROM alpine:3.14

ENV TERRAFORM_PLUGIN_DIR=/srv/terraform-plugins
ENV TF_PLUGIN_CACHE_DIR=${TERRAFORM_PLUGIN_DIR}
ENV TERRAFORM_VERSION=1.0.2
ENV TERRAFORM_PROVIDER_ALICLOUD_VERSION=1.127.0
ENV TERRAFORM_PROVIDER_LOCAL_VERSION=2.1.0
ENV TERRAFORM_PROVIDER_EXTERNAL_VERSION=2.1.0
ENV PATH="/opt/venv/bin:$PATH"

RUN apk add libxml2-dev libxslt-dev python3-dev gcc build-base wget unzip git bash \
    && python3 -m venv /opt/venv \
    && pip install terraform-compliance \
    && pip install checkov \

    && wget https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip \
    && unzip terraform_${TERRAFORM_VERSION}_linux_amd64.zip -d /usr/local/bin/ \

    && mkdir -p ${TERRAFORM_PLUGIN_DIR}/registry.terraform.io/aliyun/alicloud/${TERRAFORM_PROVIDER_ALICLOUD_VERSION}/linux_amd64 \
    && wget https://releases.hashicorp.com/terraform-provider-alicloud/${TERRAFORM_PROVIDER_ALICLOUD_VERSION}/terraform-provider-alicloud_${TERRAFORM_PROVIDER_ALICLOUD_VERSION}_linux_amd64.zip \
    && unzip terraform-provider-alicloud_${TERRAFORM_PROVIDER_ALICLOUD_VERSION}_linux_amd64.zip -d ${TERRAFORM_PLUGIN_DIR}/registry.terraform.io/aliyun/alicloud/${TERRAFORM_PROVIDER_ALICLOUD_VERSION}/linux_amd64 \

    && mkdir -p ${TERRAFORM_PLUGIN_DIR}/registry.terraform.io/hashicorp/local/${TERRAFORM_PROVIDER_LOCAL_VERSION}/linux_amd64 \
    && wget https://releases.hashicorp.com/terraform-provider-local/${TERRAFORM_PROVIDER_LOCAL_VERSION}/terraform-provider-local_${TERRAFORM_PROVIDER_LOCAL_VERSION}_linux_amd64.zip \
    && unzip terraform-provider-local_${TERRAFORM_PROVIDER_LOCAL_VERSION}_linux_amd64.zip -d ${TERRAFORM_PLUGIN_DIR}/registry.terraform.io/hashicorp/local/${TERRAFORM_PROVIDER_LOCAL_VERSION}/linux_amd64 \

    && mkdir -p ${TERRAFORM_PLUGIN_DIR}/registry.terraform.io/hashicorp/external/${TERRAFORM_PROVIDER_EXTERNAL_VERSION}/linux_amd64 \
    && wget https://releases.hashicorp.com/terraform-provider-external/${TERRAFORM_PROVIDER_EXTERNAL_VERSION}/terraform-provider-external_${TERRAFORM_PROVIDER_EXTERNAL_VERSION}_linux_amd64.zip \
    && unzip terraform-provider-external_${TERRAFORM_PROVIDER_EXTERNAL_VERSION}_linux_amd64.zip -d ${TERRAFORM_PLUGIN_DIR}/registry.terraform.io/hashicorp/external/${TERRAFORM_PROVIDER_EXTERNAL_VERSION}/linux_amd64 \
    
    && rm -rf *.zip
  • Jenkins上已安装如下插件:
  • Git:让Git和Jenkins结合
  • Pipeline:Jenkins核心功能,Jenkins根据Jenkinsfile自动执行编译打包等操作
  • Docker:让Jenkins与Docker结合
  • Docker Pipeline:在Pipeline中使用Docker容器
  • Blue Ocean:提供更加友好的Jenkins UI界面,代码更好的用户体验
  • 已拥有Git仓库,并在Jenkins中添加git仓库的访问凭证。

操作步骤

配置Terraform远端存储

  1. 登录阿里云OSS控制台,在对应的地域下创建Bucket。建议开启版本控制功能,便于state文件的恢复。记录下Bucket的名称和endpoint。
  1. 登录阿里云OTS控制台,在对应地域下创建表格存储实例,可根据自身需要选择预留模式或者按量模式。
  1. 创建完成后进入OTS实例,在实例中创建数据表。注意:数据表中必须含有一个名为LockID,字符串类型的主键。

编写Terraform代码

  1. 编写Terraform backend文件,将上述记录的参数填写到backend.tf文件中。其中:
  • access_key和secret_key为存储OSS的账号子用户AK;
  • key为将要保存的state文件名称,对于不同state配置而言,key值必须不同,否则会出现配置覆盖的情况;
  • tablestore_endpoint和tablestore_table为步骤3中创建的数据表实例的入口。
  • 详细参数说明可参考文档
terraform {
  backend "oss" {
    bucket = "bucket-with-terraform-state"
    prefix = "path/mystate"
    key = "terraform-state.tfstate"
    region = "cn-hangzhou"
    tablestore_endpoint = "https://xxxx.cn-hangzhou.ots.aliyuncs.com"
    tablestore_table = "statelock"
    access_key = "****************"
    secret_key = "**********************"
    endpoint = "oss-cn-hangzhou.aliyuncs.com"
  }
}
  1. 根据业务需求,编写用户自定义的Terraform代码,并上传到前序工作中的Git仓库。本文以创建RAM角色,并为角色赋权为例。其他资源配置详情参见Alibaba Cloud Provider
provider "alicloud" {
  access_key = "LTA****************"
  secret_key = "tQW**********************"
  region = "cn-hangzhou"
}

resource "alicloud_ram_role" "ram_role" {
  name = "tf-pipeline-test"
  description = "test terraform pipeline"
  document    = <

配置合规审计规则

  1. 我们选择 terraform-compliance 作为合规审计插件,该插件已经安装在docker镜像中,之后将使用docker直接运行pipeline,因此无需提前安装。若用户希望自定义安装,可参考安装文档
  2. terraform-compliance使用Behavior-Driven Development<BDD>编写合规规则。BDD提供了很好的自我描述能力以及很强的理解性,能够让非技术人员很轻松地编写规则和阅读测试结果。例如,我们编写如下规则:“不允许给任何RAM角色赋予AdministratorAccess”。
Feature: Test terraform-compliance

Scenario: Ensure that ram_role_policy could not be AdministratorAccess
    Given I have alicloud_ram_role_policy_attachment defined
    Then it must contain policy_name
    And its value must not be AdministratorAccess
  • Feature:功能,下面可以由多个Scenario
  • Scenario:场景,下面可以由多个Steps
  • Steps:步骤使用GivenWhenThenButAnd这些关键词,真正进行合规配置的字段。
  • 详细语法可参考BDD文档
  1. 规则编写完成后,可以将规则上传到Git仓库。建议Terraform代码和合规规则使用不同的Git仓库存储,分别由开发人员和审计人员管理。

配置Pipeline

  1. 登录Jenkins页面,点击“New Item”,创建流水线项目

  1. 点击上方“Pipeline”,编写Jenkinsfile流水线脚本。用户可根据自身需要选择直接在Jenkins上填写或者在项目中使用Jenkinsfile。流水线脚本如下所示:
pipeline {
    agent {
        docker {
            image 'registry.cn-hangzhou.aliyuncs.com/terraform/terraform-docker-hub:v1'
        }
    }
    stages {
        stage('Git Checkout'){
            steps{
                git branch: 'main', credentialsId: 'xxx-github', url: 'git@github.com:xxx/Terraform2.git'
                dir('features') {
                    git credentialsId: 'xxx-github', url: 'git@github.com:xxx/features.git'
                }
            }
        }
        stage('Terraform Init') {
            steps{
                sh 'terraform init -plugin-dir=/srv/terraform-plugins'
            }
        }
        stage('Terraform validate') {
            steps{
                sh 'terraform validate'
            }
        }
        stage('Terraform Plan') {
            steps{
                sh 'terraform plan -out tf.out'
            }
        }
        stage('合规审查') {
            steps{
                sh 'terraform-compliance -f features -p tf.out'
            }
        }
        stage('Terraform Apply') {
            steps{
                sh 'terraform apply --auto-approve'
            }
        }
    }
    post {
        always {
            deleteDir()
        }
    }
}
  • docker image使用的是阿里云容器镜像服务,镜像中已安装Terraform,aliyun Provider,terraform-compliance等插件,可直接用于运行Terraform代码。
  • 第一步:分别从Git仓库分别拉取terraform代码和合规规则,并将合规规则存放在 ./features 文件夹中。可以使用Pipeline Syntax工具生成Git语句。
  • 第二步:初始化Terraform环境,为加快初始化速度,建议将常用的插件提前下载在指定路径,插件下载详情参见下载地址。 

注意:出于安全网络方面的考虑,本文中使用 -plugin-dir 参数指定了插件安装的地址(docker镜像中插件安装在 /srv/terraform-plugins 文件夹下),如果所需插件在该文件夹下不存在,会报“插件未找到”的错误。若允许开发人员执行任意插件且网络畅通,可以使用缓存来加速Terraform init,具体可参考文档

  • 第三步:检查Terraform语法是否正确
  • 第四步:使用Terraform plan命令,检查state文件和当前Terraform代码的配置差异,并将更改信息写入tf.out文件。
  • 第五步:使用Terraform-compliance插件进行合规审查, -f 参数指定合规审查规则的路径, -p 参数指定plan后的.out文件路径。
  • 当上述流程全部成功后,执行Terraform代码。执行完成后,最后在ECS上将该Pipeline的工作空间删除。

运行pipeline

  1. 在JenkIns左侧边栏点击“Open Blue Ocean”,进入Blue Ocean页面。点击“运行”按钮,运行该pipeline。运行过程中可能出现jenkins权限不足的问题,注意为jenkins用户所在的用户组授予访问docker的权限。
  1. 运行完成后,查看每一个节点的运行日志。其中“合规审查”中可以看见合规审查的结果,由于我们给RAM用户授权的并非“AdministratorAccess”,因此合规审查通过。
  2. 当我们将RAM用户的权限修改为“AdministratorAccess”时,重新将Terraform代码push到Git仓库,再次执行该流水线,会发现合规审查无法通过。
  3. 至此,我们完成一个简易的Terraform流水线,用户可根据自身需求,修改Terraform代码、合规规则以及流水线的步骤。

发送邮件

Jenkins邮件配置
  1. 点击左侧菜单栏“Manage Jenkins”-“Configure System”。填写“Jenkins Location”下的“System Admin e-mail address”。
  2. 填写“E-mail Notification”下的参数,该参数与所使用的邮箱有关。以QQ邮箱为例,配置如下图所示:
  3. 我们可以勾选“Test configuration by sending test e-mail”选项,测试能否成功发送邮件。
Pipeline新增邮件发送步骤
  1. 在Pipeline的post中添加以下代码,表示当Pipeline执行成功后发送邮件。
post {
        success {
            echo 'successful,and send mail'
            mail body: 'current job ok', from: 'xxxx@qq.com', subject: 'account baseline success', to: 'xxx@gmail.com'
        }
    }
  1. 执行该流水线,成功后查看目标邮箱是否收到邮件。

故障排除

Jenkins

Jenkins相关故障排除请参见官网

Terraform

Terraform相关问题参见官方文档

相关内容