Git Terraform的共享Jenkins管道

Git Terraform的共享Jenkins管道,git,jenkins,continuous-integration,jenkins-pipeline,terraform,Git,Jenkins,Continuous Integration,Jenkins Pipeline,Terraform,我刚刚和詹金斯一起工作,我有几个问题。我希望你们这些了不起的家伙能帮我指引正确的方向。我已经用完了谷歌链接,詹金斯的文档也帮不了我 首先是关于我正在做什么的一些信息。我正在构建一个通用/共享的Jenkins管道,我们的团队可以在这里运行我们的terraform代码。管道是声明性的,有几个阶段:git checkout、tfinit/plan、TF plan approval和tfapply 我正在处理的三个主要问题是: 1) 确保没有任何冲突,因为将有相当多的人使用此管道部署他们的terrafo

我刚刚和詹金斯一起工作,我有几个问题。我希望你们这些了不起的家伙能帮我指引正确的方向。我已经用完了谷歌链接,詹金斯的文档也帮不了我

首先是关于我正在做什么的一些信息。我正在构建一个通用/共享的Jenkins管道,我们的团队可以在这里运行我们的terraform代码。管道是声明性的,有几个阶段:git checkout、tfinit/plan、TF plan approval和tfapply

我正在处理的三个主要问题是:

1) 确保没有任何冲突,因为将有相当多的人使用此管道部署他们的terraform代码。现在,我在工作区中使用了三个参数来帮助保持事物的容器化。这些是项目名称、帐户Id和分支机构名称。我还在计划名称中添加这些参数以增加舒适度,但不确定是否需要

2) 将地形规划和应用于不同阶段。当应用程序运行时,我得到一个错误,当我在前一阶段执行该操作时,我需要重新初始化该错误。我是不是缺少什么东西来让它发挥作用

3) 我在两个阶段之间隐藏和释放文件。当多人使用时,这会导致碰撞吗?或者说舞台是集装箱化的

代码如下:(审批阶段还没有到)

def repositoryURL=env.gitlabSourceRepoHttpUrl!=null&&env.gitlabsourcerepotpurl!="" ? env.gitlabsourcereportpurl:env.RepoURL def repositoryBranch=env.gitlab targetbranch!=null&&env.gitlabTargetBranch!="" ? env.gitlabTargetBranch:env.reposbranch def notificationEmail=env.gitlabUserEmail!=null&&env.gitlabUserEmail!="" ? env.gitlabsourcereportpurl:env.Email def projectName=env.projectName def deployAccountId=env.AccountId 管道{ 一号特工 舞台{ 阶段(“结帐”){ 任何代理人 台阶{ git分支:“${repositoryBranch}”,凭证ID:“…”,url:“${repositoryURL}” 存储名称:“tf”,useDefaultExcludes:false } } 阶段(“地形平面图”){ 代理人{ 库伯内特斯{ 标签“myagent” 集装箱模板{ 名称“cis” 图片“docker local.myrepo.com/my image:v2” 这是真的 命令“猫” } } } 台阶{ 容器('CI'){ 取消“tf”的设置 脚本{ sh“地形初始” 试一试{ sh“地形工作区选择${deployAccountId}{projectName}{repositoryBranch}” }捕获(例外e){ sh“地形工作区新${deployAccountId}{projectName}{repositoryBranch}” } sh“地形平面图-out=${deployAccountId}{projectName}{repositoryBranch}}\u plan.tfplan-input=false” 隐藏包括:“*.tfplan”名称:“tfplan”,useDefaultExcludes:false } } } 职位{ 成功{ echo“地形初始化完成” } 失败{ echo“Terraform初始化失败” } } } 阶段(“地形适用”){ 代理人{ 库伯内特斯{ 标签“myagent” 集装箱模板{ 名称“cis” 图片“docker local.myrepo.com/my image:v2” 这是真的 命令“猫” } } } 台阶{ 容器(“cis”){ 凭证件([[ $class:'AmazonWebServicesCredentialsBinding', credentialsId:“我的信用”, accessKeyVariable:'AWS\u ACCESS\u KEY\u ID', secretKeyVariable:'AWS\u SECRET\u ACCESS\u KEY' ]]) { 剧本{ 取消“tf” 取消“特遣部队计划” 嘘 集合+x temp\u role=“\$(aws sts承担角色--角色arn:aws:iam::000000000000:role/myrole--角色会话名称jenkinzassume)”>/dev/null 2>&1 导出AWS\u ACCESS\u KEY\u ID=\$(echo\$temp\u role | jq.Credentials.AccessKeyId | xargs)>/dev/null 2>&1 导出AWS\u SECRET\u ACCESS\u KEY=\$(echo\$temp\u role | jq.Credentials.SecretAccessKey | xargs)>/dev/null 2>&1 导出AWS\u会话\u令牌=\$(echo\$temp\u角色| jq.Credentials.SessionToken | xargs)>/dev/null 2>&1 集合x terraform应用${deployAccountId}{projectName}{repositoryBranch}\u plan.tfplan """ } } } } } } }
这是一个广泛的问题,所以我将留下一个简洁的评论:1。Jenkins管道和/或TF冲突可以通过远程状态后端缓解。2.这是因为您确实应该研究如何使用带有TF init的插件目录,然后将其与Jenkins容器代理绑定到卷装载(同样适用于k8s)。3.不确定4。考虑用构建参数替换全局变量(在顶部)。5.还建议将您的cred传递给apply,而不是shell将其导出为环境。@Ma def repositoryURL = env.gitlabSourceRepoHttpUrl != null && env.gitlabSourceRepoHttpUrl != "" ? env.gitlabSourceRepoHttpUrl : env.RepoURL def repositoryBranch = env.gitlabTargetBranch != null && env.gitlabTargetBranch != "" ? env.gitlabTargetBranch : env.RepoBranch def notificationEmail = env.gitlabUserEmail != null && env.gitlabUserEmail != "" ? env.gitlabSourceRepoHttpUrl : env.Email def projectName = env.ProjectName def deployAccountId = env.AccountId pipeline { agent none stages { stage("Checkout") { agent any steps { git branch: "${repositoryBranch}", credentialsId: '...', url: "${repositoryURL}" stash name: 'tf', useDefaultExcludes: false } } stage("Terraform Plan") { agent { kubernetes { label 'myagent' containerTemplate { name 'cis' image 'docker-local.myrepo.com/my-image:v2' ttyEnabled true command 'cat' } } } steps { container('cis') { unstash 'tf' script { sh "terraform init" try { sh "terraform workspace select ${deployAccountId}_${projectName}_${repositoryBranch}" } catch (Exception e) { sh "terraform workspace new ${deployAccountId}_${projectName}_${repositoryBranch}" } sh "terraform plan -out=${deployAccountId}_${projectName}_${repositoryBranch}_plan.tfplan -input=false" stash includes: "*.tfplan" name: "tf-plan", useDefaultExcludes: false } } } post{ success{ echo "Terraform init complete" } failure{ echo "Terraform init failed" } } } stage ("Terraform Apply") { agent { kubernetes { label 'myagent' containerTemplate { name 'cis' image 'docker-local.myrepo.com/my-image:v2' ttyEnabled true command 'cat' } } } steps { container("cis") { withCredentials([[ $class: 'AmazonWebServicesCredentialsBinding', credentialsId: 'my-creds', accessKeyVariable: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY' ]]) { script { unstash "tf" unstash "tf-plan" sh """ set +x temp_role="\$(aws sts assume-role --role-arn arn:aws:iam::000000000000:role/myrole --role-session-name jenkinzassume)" > /dev/null 2>&1 export AWS_ACCESS_KEY_ID=\$(echo \$temp_role | jq .Credentials.AccessKeyId | xargs) > /dev/null 2>&1 export AWS_SECRET_ACCESS_KEY=\$(echo \$temp_role | jq .Credentials.SecretAccessKey | xargs) > /dev/null 2>&1 export AWS_SESSION_TOKEN=\$(echo \$temp_role | jq .Credentials.SessionToken | xargs) > /dev/null 2>&1 set -x terraform apply ${deployAccountId}_${projectName}_${repositoryBranch}_plan.tfplan """ } } } } } } }