环境
Kubernetes v1.22.3
基本k8s部署的Jenkins 2.303.3
基本k8s部署的Harbor
k8s部署应用流程
- 编写代码
- 测试
- 编写 Dockerfile
- 构建打包 Docker 镜像
- 推送 Docker 镜像到仓库
- 编写 Kubernetes YAML 文件
- 更改 YAML 文件中 Docker 镜像 TAG
- 利用 kubectl 工具部署应用
部署应用
一、准备应用程序
我这里准备了一个简单的go程序,部署到k8s环境中,代码链接:https://github.com/wozengkeai/jenkins-demo.git
二、Jenkins安装kubernetes插件
- Jenkins Master 和 Jenkins Slave 以 Pod 形式运行在 Kubernetes 集群的 Node 上,Master 运行在其中一个节点,并且将其配置数据存储到一个 Volume 上去,Slave 运行在各个节点上,并且它不是一直处于运行状态,它会按照需求动态的创建并自动删除。
- 这种方式的工作流程大致为:当 Jenkins Master 接受到 Build 请求时,会根据配置的 Label 动态创建一个运行在 Pod 中的 Jenkins Slave 并注册到 Master 上,当运行完 Job 后,这个 Slave 会被注销并且这个 Pod 也会自动删除,恢复到最初状态
- 实践下来后发现这种方式仍是有不足的地方,每个应用都需要配置一个cloud,当程序多的时候工作量就大了,后续考虑优化
接下来就需要配置Jenkins,让他动态生成slave的pod
1.安装kubernetes plugin,管理Jenkins-插件管理-可选插件-Kubernetes勾选安装即可。
2.安装完毕后,管理Jenkins-系统配置,拉到最底下点击进入配置页面-add a new cloud,然后填写k8s和Jenkins的配置信息。
注意:namespace,我这里填的是jenkins(事先在我的k8s上创建的),点击连接测试,提示连接到kubernetes就标识Jenkins和k8s可以正常通信了,就可以愉快的进行下一步了~然后下方的 Jenkins URL的格式为:服务名.namespace.svc.cluster.local:8080
-
配置 Pod Template,其实就是配置 Jenkins Slave 运行的 Pod 模板,Labels 这里也非常重要,对于后面执行 Job 的时候需要用到该值(没有这个labels的话后续执行时找不到执行的pod),然后我们这里使用的是 cnych/jenkins:jnlp6 这个镜像,这个镜像是在官方的 jnlp 镜像基础上定制的,加入了 kubectl 等一些实用的工具。
注意:工作目录,Jenkins的运行路径,即我部署在k8s上的Jenkins的挂载目录(根据自己实际路径填写)
4.注意底下两个需要挂载的主机目录,一个是/var/run/docker.sock,该文件是用于 Pod 中的容器能够共享宿主机的 Docker,这就是大家说的 docker in docker 的方式,Docker 二进制文件我们已经打包到上面的镜像中了;另外一个目录下/home/tester/.kube目录,我们将这个目录挂载到容器的/root/.kube目录下面这是为了让我们能够在 Pod 的容器中能够使用 kubectl 工具来访问我们的 Kubernetes 集群,方便我们后面在 Slave Pod 部署 Kubernetes 应用。
5.如果运行 Slave Pod 的时候出现了权限问题,因为 Jenkins Slave Pod 中没有配置权限,所以需要配置上 ServiceAccount,在 Slave Pod 配置的地方点击下面的高级,添加上对应的 ServiceAccount 即可(不要照搬,前提是你的k8s创建了这个sa)
三、创建新的pipeline项目
1.创建一个新的流水线
2.配置SCM
3.配置凭证
点击添加-Jenkins
四、编写pipeline脚本
①withCredentials,其中有一个 credentialsId 值就是我们刚刚创建的凭证 ID 值
②更新k8s系统中应用的镜像版本时,-n 指定命名空间,我创建了一个新的jenkins-demo命名空间
③node指定label属性,才可以指定我们要跑的pod是kubernetes插件中配置的pod模板
node('jenkins-jnlp') {
stage('Clone') {
echo "1.Prepare Stage"
checkout scm
script {
build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
}
}
stage('Test') {
echo "2.Test Stage"
}
stage('Build') {
echo "3.Build Docker Image Stage"
sh "docker build -t 192.168.100.51:30003/jenkins/jenkins-demo:${build_tag} ."
}
stage('Push') {
echo "4.Push Docker Image Stage"
withCredentials([usernamePassword(credentialsId: 'dockerHarbor', passwordVariable: 'dockerHarborPassword', usernameVariable: 'dockerHarborUser')]) {
//sh "pwd"
sh "echo '${dockerHarborPassword}' | docker login 192.168.100.51:30003 -u ${dockerHarborUser} --password-stdin "
sh "docker push 192.168.100.51:30003/jenkins/jenkins-demo:${build_tag}"
}
}
stage('YAML') {
echo "5. Change YAML File Stage"
sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s.yaml"
//sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s.yaml"
}
stage('Deploy') {
echo "6. Deploy Stage"
sh "kubectl apply -f k8s.yaml -n jenkins-demo"
}
}
五、构建项目
至此CI/CD流程完成~接下来记录遇到的坑
1、x509: certificate signed by unknown authority
在登陆harbor时提示x509报错:
①检查证书是否放置正确路径(master和所有node都要配置)
②检查是否配置了docker代理(因为代理一直导致x509,所有办法都试过了都无效,最后在家里重新部了个环境,才发现是代理引起的,不知道为什么有的却不出现这个提示,家里k8s版本是1.23.0)
清除/etc/systemd/system/docker.service.d/http-proxy.conf配置文件内容(可能文件名称会不同)