到目前为止,Jenkins是市场上最常用的CI / CD工具。 这并不奇怪,因为它已经存在了一段时间,它拥有最大的开源社区之一,它为需要它的人提供了企业版,并且可以轻松地扩展它以适应(几乎)任何人的需求。
多年来在市场上占主导地位的产品趋向于稳定且功能丰富。 詹金斯也不例外。 但是,随着年龄的增长,也有一些弊端。 对于Jenkins而言,自动化设置是很多需要完成的工作之一。 如果您需要詹金斯(Jenkins)作为自动化和任务的协调者,您会发现使用起来毫不费力。 但是,如果您需要使Jenkins本身自动化,您将意识到它并不像您从现代工具中所期望的那样平滑。 不管怎样,Jenkins的安装可以实现自动化,我们将介绍一种可能的解决方案。
在Jenkins设置过程中,我将不介绍所有工作。 关于这一主题可以写一整本书。 相反,我将尝试向您展示如何执行两个最常见的配置步骤。 我们将自动执行Jenkins插件的安装和管理员用户的设置。 如果您需要添加更多信息,请给我发电子邮件(您可以在“ 关于”页面上找到我的信息)。
让我们快速完成摆在眼前的目标。
目标
自动化是任何软件公司成功的关键。 因为我相信每个公司都是软件公司(尽管有些公司仍然不知道),所以我们可以说自动化是每个人的关键。
我希望您正在使用Docker来运行服务。 如果不是,请重新考虑您的策略。 它提供了很多好处,因此忽略它意味着竞争将使您不堪重负。 我不会详细介绍Docker为什么很棒。 您可能已经知道所有这些。
Jenkins自动化设置背后的目标的简短版本是,我们只需要运行一个命令就不需要做任何事情。 结果应该是一个完全配置的Jenkins主服务器,我们可以根据需要将其复制到任意多个实例。 Docker将通过Swarm提供容错能力,(某种程度上)高可用性,而不能做到。
更长一点的版本是我们想要设置所有需要的插件,并创建至少一个管理用户。 这并不意味着您以后将不再添加更多插件。 你可能会的。 但是,这不应阻止我们预安装您组织中最常用的程序。 没有至少一个用户,任何人都可以访问您的Jenkins主服务器,并有可能访问您的整个系统。 可能没有必要讨论为什么我们应该避免这种情况。
在开始进行自动化工作之前,我们将手动运行Jenkins主文件并获取一些以后将有用的信息。
手动设置Jenkins
我们将从在Swarm集群中创建Jenkins服务开始。 如果您没有,则可以通过执行docker swarm init
轻松地将适用于Windows / Mac / Linux的Docker转换为单节点集群。
W>如果您是Windows用户,请从Git Bash (通过Git安装)或您可能拥有的任何其他Bash中运行所有命令。
docker service create --name jenkins \
-p 8080:8080 jenkins
一段时间后,将提取jenkins
图像,并且该服务将运行。 通过执行docker service ps jenkins
随意检查状态。
Jenkins启动并运行后,我们可以在浏览器中打开其UI。
如果您没有将本地的Windows / Mac / Linux Docker引擎用作集群中的唯一节点,请用您的Swarm节点之一的IP替换localhost
。
如果您是Windows用户,则Git Bash可能无法使用open
命令。 如果是这种情况,请用echo
替换open
。 结果,您将获得应在所选浏览器中直接打开的完整地址。
open "http://localhost:8080"
您应该看到设置的第一个屏幕,在该屏幕上应输入管理员密码 。 它在托管服务的容器内的/var/jenkins_home/secrets/initialAdminPassword
文件内可用。
如果您没有将本地的Windows / Mac / Linux Docker引擎用作集群中的唯一节点,请在执行以下命令之前找到正在运行服务的节点并对其进行SSH加密。
ID=$(docker container ls -q \
-f "label=com.docker.swarm.service.name=jenkins")
docker container exec -it $ID \
cat /var/jenkins_home/secrets/initialAdminPassword
我们使用了带有过滤器的docker container ls
命令来查找托管服务的容器的ID。 接下来,我们执行了一个显示/var/jenkins_home/secrets/initialAdminPassword
文件内容的命令。 输出会因一次执行而异。 就我而言,如下。
ecd46df9ec1b420dadacdb56de9492c8
请复制密码并将其粘贴到Jenkins UI的管理员密码字段中,然后按照说明设置您的Jenkins主服务器。 选择您需要的插件。 当您到达最后一个名为Create First Admin User的设置屏幕时,请同时使用admin
作为用户名和密码。
设置完成后,我们可以发送请求,该请求将检索我们安装的所有插件的列表。
在继续之前,请检查是否已安装jq 。 如果没有,您可以在其官方网站上找到。
curl -s -k "http://admin:admin@localhost:8080/pluginManager/api/json?depth=1" \
| jq -r '.plugins[].shortName' | tee plugins.txt
我们向Jenkins插件管理器API发送了一个请求,并检索了在手动设置过程中安装的所有插件。 我们将结果通过管道传输到jq并以仅输出短名称的方式对其进行了过滤。 结果存储在plugins.txt文件中。
我们不再需要詹金斯服务。 它只有一个临时功能,使我们可以检索所需的插件列表。 让我们消灭它。
docker service rm jenkins
使用自动设置创建Jenkins图像
在定义用于自动设置创建Jenkins映像的Dockerfile之前,我们需要弄清楚如何创建至少一个管理用户。 不幸的是,没有可以调用的(不错的)API。 我们最好的选择是执行一个Groovy脚本来完成这项工作。 脚本如下。
#!groovy
import jenkins.model.*
import hudson.security.*
import jenkins.security.s2m.AdminWhitelistRule
def instance = Jenkins.getInstance()
def hudsonRealm = new HudsonPrivateSecurityRealm(false)
hudsonRealm.createAccount("admin", "admin")
instance.setSecurityRealm(hudsonRealm)
def strategy = new FullControlOnceLoggedInAuthorizationStrategy()
instance.setAuthorizationStrategy(strategy)
instance.save()
Jenkins.instance.getInjector().getInstance(AdminWhitelistRule.class).setMasterKillSwitch(false)
密钥在hudsonRealm.createAccount("admin", "admin")
行中。 它创建一个用户名和密码都设置为admin
的帐户。
该脚本的主要问题是它具有硬编码的凭据。 我们可以将它们转换为环境变量,但这将是非常不安全的。 相反,我们将利用Docker机密。 附加到容器后,机密存储在/run/secrets
内存目录中。
脚本的更安全(更灵活)的版本如下。
#!groovy
import jenkins.model.*
import hudson.security.*
import jenkins.security.s2m.AdminWhitelistRule
def instance = Jenkins.getInstance()
def user = new File("/run/secrets/jenkins-user").text.trim()
def pass = new File("/run/secrets/jenkins-pass").text.trim()
def hudsonRealm = new HudsonPrivateSecurityRealm(false)
hudsonRealm.createAccount(user, pass)
instance.setSecurityRealm(hudsonRealm)
def strategy = new FullControlOnceLoggedInAuthorizationStrategy()
instance.setAuthorizationStrategy(strategy)
instance.save()
Jenkins.instance.getInjector().getInstance(AdminWhitelistRule.class).setMasterKillSwitch(false)
这次,我们将jenkins-user
和jenkins-pass
文件的内容放入变量中,并使用它们创建了一个帐户。
请将脚本另存为security.groovy
文件。
配备了存储在plugins.txt
中的插件列表以及将从Docker机密创建用户的脚本,我们可以继续创建Dockerfile。
请使用以下内容创建Dockerfile
。
FROM jenkins:alpine
ENV JAVA_OPTS="-Djenkins.install.runSetupWizard=false"
COPY security.groovy /usr/share/jenkins/ref/init.groovy.d/security.groovy
COPY plugins.txt /usr/share/jenkins/ref/plugins.txt
RUN /usr/local/bin/install-plugins.sh < /usr/share/jenkins/ref/plugins.txt
该图像将基于Jenkins的alpine
版本,比其他版本更小,更安全。
我们使用JAVA_OPTS
禁用了安装向导。 因为我们的设置将是完全自动化的,所以我们不需要它。
接下来,我们将security.groovy
文件复制到/usr/share/jenkins/ref/init.groovy.d/
目录中。 Jenkins初始化后,将执行该目录中的所有Groovy脚本。 如果创建其他安装脚本,则应在该位置放置它们。
最后,我们将复制包含我们需要的所有插件列表的plugins.txt
文件,并将该列表传递到标准发行版中的install-plugins.sh
脚本。
使用定义的Dockerfile
,我们可以构建映像并将其推送到Docker注册表。
请用您的Docker Hub用户替换vfarcic
。
docker image build -t vfarcic/jenkins .
docker image push vfarcic/jenkins
通过构建映像并将其推送到注册表,我们最终可以创建Jenkins服务。
使用自动设置创建Jenkins服务
我们应该创建一个Compose文件,其中将包含服务的定义。 如下。
请用您的Docker Hub用户替换vfarcic
。
version: '3.1'
services:
main:
image: vfarcic/jenkins
ports:
- 8080:8080
- 50000:50000
secrets:
- jenkins-user
- jenkins-pass
secrets:
jenkins-user:
external: true
jenkins-pass:
external: true
将定义另存为jenkins.yml
文件。
撰写文件非常简单。 如果只定义一个服务( main
)并使用新建的映像。 它为UI公开端口8080
,为代理公开50000
。 最后,它定义了jenkins-user
和jenkins-pass
秘密。
我们应该在部署堆栈之前创建秘密。 后面的命令将使用admin
作为用户名和密码。 随意将其更改为不太明显的内容。
echo "admin" | docker secret create jenkins-user -
echo "admin" | docker secret create jenkins-pass -
现在我们准备部署堆栈。
docker stack deploy -c jenkins.yml jenkins
稍后,该服务将启动并运行。 请通过执行docker stack ps jenkins
确认状态。
让我们确认一切正常。
open "http://localhost:8080"
您会注意到,这次,我们不必执行安装向导步骤。 一切都是自动化的,服务可以使用了。 随时登录并确认您指定的用户确实已创建。
如果您是在演示环境(例如笔记本电脑)中创建此服务,那么现在是时候删除它并释放资源以用于其他用途了。 您刚刚构建的映像应已准备好用于生产。
docker stack rm jenkins
docker secret rm jenkins-user
docker secret rm jenkins-pass
翻译自: https://www.javacodegeeks.com/2017/06/automating-jenkins-docker-setup.html