将jenkins与terrain集成在terraform上

时间:2018-12-12 04:11:21

标签: amazon-web-services jenkins bitbucket terraform terraform-provider-aws

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

1 个答案:

答案 0 :(得分:2)

CI / CD管道工作流程,用于使用terraform将更改应用于基础架构:

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

如何设置部署环境?

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

enter image description here

###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###