将 jenkins 与 bitbucket 集成到 Terraform 上

integrate jenkins on terraform with bitbucket

我已经为 aws 架构创建了 terraform 脚本,其中包括 ec2 实例和 ec2 上的 jenkins。我是 jenkins 的新手,并试图弄清楚如何使用现有的 terraform 脚本将它与 bitbucket 集成。 任何帮助将不胜感激。

CI/CD 使用 terraform 将更改应用到基础设施的管道工作流程:

  1. 开发人员或运维工程师在他的本地机器上更改 terraform 配置文件并将代码提交到 BitBucket。
  2. Gitbucket webhook 触发对 jenkins 的持续集成作业。
  3. Jenkins 将从包含 terraform 文件的已配置存储库中提取最新代码到其工作区。
  4. 它读取 terraform 配置然后初始化远程 consul 后端。
  5. Terraform 生成有关必须应用到基础架构的更改的计划
  6. Jenkins 向松弛通道发送有关手动批准更改的通知。
  7. 在这里,用户可以批准或不批准 terraform 计划。
  8. 用户输入被发送到 jenkins 服务器以进行进一步的操作。
  9. 操作员批准更改后,jenkins 将执行 terraform apply 命令以反映对基础架构的更改。
  10. Terraform 将创建一份关于执行计划时创建的资源及其依赖项的报告。
  11. Terraform 将在提供商环境中提供资源。
  12. Jenkins 将在应用更改后再次向松弛通道发送有关基础结构状态的通知。执行作业后,Jenkin 管道作业将配置为清理作业创建的工作区。

如何设置部署环境?

  1. 在 gitlab 或 bitbucket 等 scm 工具中创建一个 repo,并将 terraform 配置及其依赖模块提交到 repo。如果您使用任何第三方远程模块作为依赖项,它将在执行时自动下载。
  2. 如果您没有 Jenkins 服务器,那么只需拉取一个 jenkins docker 映像并 运行 在您的本地机器上。如果您是在云环境中设置它,请查看市场上的 jenkins 虚拟机映像以设置环境并配置所需的插件。
  3. 在您的 bitbucket 存储库设置中创建一个 webhook 以调用对您的 jenkins 回调的 http 调用 url 以触发持续集成作业。
  4. 如果您有现有的 jenkins 服务器,请确保在 jenkins 服务器中安装了管道插件。否则转到 "Manage plugins" 并安装管道插件。
  5. 在这个项目中,我们使用 consul 作为状态存储和状态锁定的远程后端。对于多人参与项目和生产部署的情况,不建议使用本地状态。最好使用远程后端,它提供具有状态锁定功能的高可用存储,以避免多个用户同时写入状态。
  6. 如果您的环境中没有 consul 键值存储,只需拉取 consul docker 映像并设置单节点集群。如果是生产部署,设置分布式键值存储。
  7. 在 slack 中创建一个应用程序并记下用于在 Jenkinsfile 中配置它的 slack 集成详细信息。
  8. 通过环境变量或在存储库中持久化,在主 terraform 配置文件中配置您的提供程序详细信息和后端详细信息。就我而言,我将在 AWS 中配置一个资源,我的 CI 服务器托管在 AWS 中。所以我正在为我的服务器分配一个具有足够权限的 IAM 角色。
  9. 使用管道插件在 Jenkins 中创建一个新项目。
  10. 添加定义流水线阶段的 Jenkinsfile。保存作业并手动触发它进行测试。然后将更改应用到配置并将更改提交到 bitbucket 并确保自动触发作业。查看 Jenkins 日志以获取有关该作业的更多详细信息。

###Jenkinsfile###
import groovy.json.JsonOutput

//git env vars
env.git_url = 'https://user@bitbucket.org/user/terraform-ci.git'
env.git_branch = 'master'
env.credentials_id = '1'

//slack env vars
env.slack_url = 'https://hooks.slack.com/services/SDKJSDKS/SDSDJSDK/SDKJSDKDS23434SDSDLCMLC'
env.notification_channel = 'my-slack-channel'

//jenkins env vars
env.jenkins_server_url = 'https://52.79.46.98'
env.jenkins_node_custom_workspace_path = "/opt/bitnami/apps/jenkins/jenkins_home/${JOB_NAME}/workspace"
env.jenkins_node_label = 'master'
env.terraform_version = '0.11.10'

def notifySlack(text, channel, attachments) {
    def payload = JsonOutput.toJson([text: text,
        channel: channel,
        username: "Jenkins",
        attachments: attachments
    ])
    sh "export PATH=/opt/bitnami/common/bin:$PATH && curl -X POST --data-urlencode \'payload=${payload}\' ${slack_url}"
}

pipeline {
 agent {
  node {
   customWorkspace "$jenkins_node_custom_workspace_path"
   label "$jenkins_node_label"
  } 
 }
 
 stages {
  stage('fetch_latest_code') {
   steps {
    git branch: "$git_branch" ,
    credentialsId: "$credentials_id" ,
    url: "$git_url"
   }
  }

  stage('install_deps') {
   steps {
    sh "sudo apt install wget zip python-pip -y"
    sh "cd /tmp"
    sh "curl -o terraform.zip https://releases.hashicorp.com/terraform/'$terraform_version'/terraform_'$terraform_version'_linux_amd64.zip"
    sh "unzip terraform.zip"
    sh "sudo mv terraform /usr/bin"
    sh "rm -rf terraform.zip"
   }
  }

  stage('init_and_plan') {
   steps {
    sh "sudo terraform init $jenkins_node_custom_workspace_path/workspace"
    sh "sudo terraform plan $jenkins_node_custom_workspace_path/workspace"
    notifySlack("Build completed! Build logs from jenkins server $jenkins_server_url/jenkins/job/$JOB_NAME/$BUILD_NUMBER/console", notification_channel, [])
   }
  }

  stage('approve') {
   steps {
     notifySlack("Do you approve deployment? $jenkins_server_url/jenkins/job/$JOB_NAME", notification_channel, [])
    input 'Do you approve deployment?'
   }
  }

  stage('apply_changes') {
   steps {
    sh "echo 'yes' | sudo terraform apply $jenkins_node_custom_workspace_path/workspace"
    notifySlack("Deployment logs from jenkins server $jenkins_server_url/jenkins/job/$JOB_NAME/$BUILD_NUMBER/console", notification_channel, [])
   }
  }
 }
 
 post { 
   always { 
     cleanWs()
   }
  }
}
###Code Completed###