轻松搞定.Net8+GitLab+Jenkins+k8s+Docker实现CICD
我之前写了篇CICD项目实践的文章,但是那会是比较简单的探索和实操,也并没有涉及到k8s和docker容器,距离真正的CICD生产模式还是有点差距的,所以这次花了几天时间来操作和反复测试,终于梳理总结出这篇文章。本文主要介绍了在Centos7.9下基于.Net 8.0、GitLab、Jenkins、k8s、docker搭建CI/CD,实现自动发布.Net 8.0 WebAPI到k8s集群,并支持代
1.背景
我之前写了篇CICD项目实践的文章,但是那会是比较简单的探索和实操,也并没有涉及到k8s和docker容器,距离真正的CICD生产模式还是有点差距的,所以这次花了几天时间来操作和反复测试,终于梳理总结出这篇文章。本文主要介绍了在Centos7.9下基于.Net 8.0、GitLab、Jenkins、k8s、docker搭建CI/CD,实现自动发布.Net 8.0 WebAPI到k8s集群,并支持代码更新后的自动发布。
2.知识储备
2.1 CI/CD概念
CI/CD就是持续集成,持续交互。简单理解就是项目自动化,解放手工操作。将项目自动编译,自动发布,自动执行。这里的项目,我们定义为.NET Web API 8.0;
2.2 CI/CD架构
下面是1个完整的CI/CD架构图:
2.3 CI/CD环境准备
2.3.1 机器准备
准备3台虚拟机如下,版本centos 7.9
IP | 机器名称 | 配置 |
192.168.126.194 | lmaster | 硬盘40GB,内存2GB |
192.168.126.195 | lnode1 | 硬盘80GB,内存4GB |
192.168.126.196 | lnode2 | 硬盘40GB,内存8GB |
2.3.2 源代码准备
新增 .NET Web API 8.0项目:K8s_CICD
新增K8s_CICDController,代码如下
using Microsoft.AspNetCore.Mvc;
namespace K8s_CICD.Controllers
{
[ApiController]
[Route("[controller]/[action]")]
public class K8s_CICDController : ControllerBase
{
private readonly ILogger<WeatherForecastController> _logger;
public K8s_CICDController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet(Name = "GetK8sCICD")]
public string GetK8sCICD()
{
return $"K8s CI/CD部署成功:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}";
}
}
}
2.3.3 k8s集群搭建
这个过程可以参考这篇文章,我是用它来搭建k8s集群。此处就不再重复介绍了。
2.3.4 Jenkins安装
在k8s从节点-lnode1机器上安装Jenkins。按照下面命令去执行
wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo;
rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key
# 安装 java
yum install -y fontconfig java-11-openjdk
# 检查 java 版本
java -version
# 使用 wget 下载 Jenkins 软件包的存储库配置文件,并将其保存到 /etc/yum.repos.d/jenkins.repo 文件中
# 证书过期,不检查证书:sudo wget --no-check-certificate -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
# 使用 rpm 导入 Jenkins 软件包的 GPG 密钥,以确保安装的软件包是经过验证的,并且没有被篡改过
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
# 安装 EPEL 的发行包,通过安装 EPEL 发行包,您可以访问一些常用的第三方软件包
yum install epel-release
# 使用 yum 安装 Jenkins 软件包
yum install -y jenkins
#给jenkins加docker 组
sudo usermod -aG docker jenkins
systemctl enable jenkins
systemctl start jenkins
下面打开地址http://192.168.126.195:8080/,访问下Jenkins
在k8s从结点lnode1,输入下列命令,查看密码
#查看初始密码
cat /var/lib/jenkins/secrets/initialAdminPassword
按照下面操作:安装推荐的插件
等待几分钟后,就安装完毕了,如下图:
按照下图创建用户
用户:admin
密码:12345678
2.3.5 Jenkins访问K8s
这一步是专门用来设置k8s从节点也能执行kubectl命令,并且安装在k8s从节点上的Jenkins能使用shell命令去执行kubectl。
1.配置从节点机器lnode1 执行kubectl
在k8s主节点lmaster机器上,输入下面的命令,并根据提示输入账号和密码
scp /etc/kubernetes/admin.conf root@lnode1:/etc/kubernetes/
scp /etc/kubernetes/admin.conf root@lnode2:/etc/kubernetes/
在k8s从节点lnode1机器上,输入下面的命令
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
# 永久生效,执行kubeadm reset后再次init也无需再次执行这条命令
source ~/.bash_profile
# 执行永久生效命令之后需要source一下使其生效
echo $KUBECONFIG
在k8s从节点lnode1机器上,输入下面的命令来验证下效果
kubectl get nodes
从上图可以看到,本次操作成功,从结点lnode1可以执行kubectl命令。
2.配置Jenkins在shell脚本中可以 执行kubectl
在k8s从节点lnode1机器上,输入下面的命令
#从结点 执行
mkdir /var/lib/jenkins/.kube
在k8s主节点lmaster机器上,输入下面的命令,并根据提示输入账号和密码
#主节点执行
scp /root/.kube/config root@lnode1:/var/lib/jenkins/.kube
在k8s从节点lnode1机器上,输入下面的命令
sudo chown jenkins /var/lib/jenkins/.kube/config
2.3.5 Net 8.0框架安装
在k8s从节点lnode1机器上安装.Net8.0框架。
安装过程可以参考这篇文章。
2.3.6 GitLab安装
在k8s从节点lnode2机器上安装GitLab。
输入下面的命令
mkdir -p /usr/local/gitlab
cd /usr/local/gitlab
wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-14.9.1-ce.0.el7.x86_64.rpm
rpm -ivh gitlab-ce-14.9.1-ce.0.el7.x86_64.rpm
执行下面命令,修改 GitLab对外提供服务的ip端口:
vim /etc/gitlab/gitlab.rb
修改external_url 为如下:
external_url 'http://192.168.126.196:8848'
注意:192.168.126.196为K8s从节点lnode2的ip,这个要根据实际ip去修改;端口8848是自定义,随意取。
然后,执行下面命令,重启下Jenkins
gitlab-ctl reconfigure
gitlab-ctl start
在等待10+分钟后,执行完毕如下所示:
打开地址:http://192.168.126.196:8848 ,访问GitLab如下所示:
在k8s从结点lnode2使用下面命令,查看原始密码
cat /etc/gitlab/initial_root_password
所以,用下面账号密码来登录Gitlab
账号:root
密码:xbM27BZDL2+6rx4dgykL55xaf1QgkiaQXDpENFpC0k8=
接下来,修改下Gitlab用户root密码为 12345678,方便后面操作
那么Gitlab用户信息如下:
用户:root
密码 :12345678
2.4 CI/CD架构实战
2.4.1 创建GitLab项目
访问GitLab地址:http://192.168.126.196:8848 ,并按照下列新增项目K8s_CICD
并按照下图操作,拿到该项目的地址,后面会用到
该项目的地址如下:
SSH: git@192.168.126.196:root/k8s_cicd.git
HTTP: http://192.168.126.196:8848/root/k8s_cicd.git
2.4.2 源代码上传
将2.3.2创建的项目的源代码,上传到k8s从节点lnode2的目录/opt
在K8s从节点lnode2输入下面的命令,去提交刚刚拷贝过来的项目
git config --global user.name "Administrator"
git config --global user.email "admin@example.com"
#在已经存在的目录去初始化仓库
cd K8s_CICD
git init
git remote add origin http://192.168.126.196:8848/root/k8s_cicd.git
git add .
git commit -m "Initial commit"
git push -u origin master
打开GitLab后,发现项目上传成功
注意:我们上传的是master分支,一般是当做主分支使用的。这里我们可以将master按照下图操作设置为默认分支。
2.4.3 创建Jenkins Job
这个过程主要是介绍在k8s从结点lnode1.执行命令,拿到公钥,并部署到Jenkins凭证
ssh-keygen -t rsa
执行下面命令,拿到公钥A:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC97Ha1zHcD4bOe/gh11BRc61bOGUAW/gZjTUTuB9z0eUz+DGXBBj9Moa8AorOqR5u1CIu7YDjFHCPr2wXM9cLNs6pmg5YB4/lNZS56wAKEJqPjb0sKe8bU7KyQ1rmfcKZ1KHyK8Z1BJJ2z+gXsKOM0YaPwcLwVmhS3uFsoEsmn9kKBdbk94m+/EO9qrEJOY3Ea20Q6e/9VyAD7ua/XYf0PA7YHwEw/oI69Dk7Eo5mpfFycID9Qu8oJdSD+PyWioC3io3a8YDoPQgtsjJlc9BFerTnE+LxRipcqIQOxz1hfgSFwC9WPdkeGVh6lCgZvP2KBbFE2W4wmN6V1z+8E8SP9 root@lnode1
#公钥,部署在gitlab:SSH Key
cat /root/.ssh/id_rsa.pub
执行下面命令,拿到私钥B:
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAvex2tcx3A+Gznv4IddQUXOtWzhlAFv4GY01E7gfc9HlM/gxl
wQY/TKGvAKKzqkebtQiLu2A4xRwj69sFzPXCzbOqZoOWAeP5TWUuesAChCaj429L
CnvG1OyskNa5n3CmdSh8ivGdQSSds/oF7CjjNGGj8HC8FZoUt7hbKBLJp/ZCgXW5
PeJvvxDvaqxCTmNxGttEOnv/VcgA+7mv12H9DwO2B8BMP6COvQ5OxKOZqXxcnCA/
ULvKCXUg/j8loqAt4qN2vGA6D0ILbIyZXPQRXq05xPi8UYqXKiEDsc9YX4EhcAvV
j3ZHhlYepQoGbz9igWxRNluMJjeldc/vBPEj/QIDAQABAoIBAE7eNkGyga3T+TJK
DZtYkYgwlmCJrcqefGqaOMib7U58XNOWtF6eyIR7E+AwsGlCyU85GEWcZJa949Da
qCL/34BqXpWpiQ6J7AoOvWlt+N2F6kLVAZV95wieq96NvJGQRx+Zy3YrdYEKwo5t
gi4aoJctANYlCoXx8S6F2RzgCGu9qWetwiBvphAxPRBDGwdRlNmDfEeGZDqC65o1
7sHSF2CuypSsQwqvakVLv9MA4Snrh8A/w3jUtrMJPcjSfmf1Nr/zkucZaJJc8JU+
3eHu7+NfHb+3IJTkNYYeM5SrTLm1LdMxdtu4pcFo07z2nbSCkDJFlNamBhlr7SVJ
beGfhSECgYEA6GIY90Q3Pdi/DLBcEJcs/8bsJcwI7JNoSzdfSgy5dJ1nPhags3r0
C8fZWAFwcI+Nqdu+5+IqgoT20BPKPki6VBGd1DHoa+UoKatVXdLAZqE8PIRKHihP
pPxpXiFK8/U0BNP6BZHVQ7a9ZttKL6iqFXzhQztD6mCrrM2Fpf6aE3kCgYEA0Tmy
/8F+qNQbG9b+CM/Xvr48EQ4hFn6d7I8gK9Sj3/b3dxwYGjZxL0eW6dl/CE1tSSCJ
8WSmtkN3YC6fnejmdKNGWBmuIaP8mYUYFhDgowOpUvn0iLuSAmbf0zdCX4h84fv+
wRbHA1I9MMcHDMSuOL0cmf7dmuj7KT/wBw5Sj6UCgYEAwSfY7J6s9CFXG+rze27N
HoVwADLKMCqOhAawk9JjzISRLlCMnuLSO4CQLdB0b3tDGy7mTcP15aszo9zvPDoj
doF2GMyrDhPaAFjDiksFVckrUnn7SXnkSZTs2CsALCtiY6j2pu6Cv9gDMp2P2nFt
fpLggouedhCIYggq0MEBvLECgYEApc+WXj4YhO/jtAKEPLOLBW156QJLkqoxueIL
2vCgFsSAhfLL3yo6NQAFR7rIg+norEWPTLE5tcRt/Nm2QczrppAnFXb0m1B8xaXG
2uXxQP+L12ikNSCBrEmfJKLshQ2D+wxcbuYAPk+Uku2IVsQgVnL5Ecn8EeKF+cDk
FpNxNskCgYEAmOswsCSYA+RbXTnmIeJv5fJtETtnKAZmwpof6TZfLo9PywI17gEl
cJRQHwnA9wcRcF9TZx4JppBUut2vq1xgmWjQeYZHgW9kj2lyRpY0wU6WJxSrji8g
nZYwCDSb8MDuNwgt63T8Lnlzls1hi9Jg7PQLMt3MaaqSKQOb63T98vs=
-----END RSA PRIVATE KEY-----
cat /root/.ssh/id_rsa
访问Jenkins地址:http://192.168.126.195:8080/
按照下面操作去Jenkins新增凭证
按照下面操作去GitLab新增SSH Keys
按照如下操作创建Job:K8sCICD
将下列命令,如下图填入,并点击 保存:
#!/bin/sh -l
echo '开始发布.net 8.0项目'
cd K8s_CICD
dotnet restore
dotnet build
dotnet publish --framework net8.0 --runtime linux-x64 --no-dependencies
2.4.4 执行Jenkins Job
从上图发现 执行Job失败了,我们打开下执行的详情。
这里,我是怎么做的了?
我删除该Jenkins Job,重启机器lnode1和lnode2,重新配置了GitLab的SSH Keys 和Jenkins的凭证。按照步骤2.4.3重新来一遍,问题解决。
到这里,Jenkins 就能自动编译,并发布.Net 8.0项目。
2.4.5 手动部署K8s Deployment
2.4.4步骤拿到了.Net 8.0项目的发布文件,对于项目的部署,我们需要先手动部署到k8s集群.这样后续Jenkins直接更新Deployment镜像,就能实现升级发布的效果。
在k8s从节点机器lnode1,按照下面命令去操作
cd /var/lib/jenkins/workspace/K8sCICD/K8s_CICD/bin/Release/net8.0/linux-x64/
输入下列命令,创建Dockerfile
vim Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:8.0.0
WORKDIR /publish
EXPOSE 80
EXPOSE 443
coPY publish/ /publish
ENV ASPNETCORE_URLS http://+:80
ENTRYPOINT ["dotnet","K8s_CICD.dll"]
接下来按照如下操作,去生成docker镜像,并将镜像推送到阿里云个人镜像仓库;
阿里云镜像仓库怎么使用,比较简单,可以自行百度 。
cd /var/lib/jenkins/workspace/K8sCICD/K8s_CICD/bin/Release/net8.0/linux-x64/
docker build -f Dockerfile -t k8scicd:v1 .
docker login --username=xxxxx registry.cn-hangzhou.aliyuncs.com --password=*****
docker tag k8scicd:v1 registry.cn-hangzhou.aliyuncs.com/zzz/k8scicd:v1
docker push registry.cn-hangzhou.aliyuncs.com/zzz/k8scicd:v1
登录阿里云个人镜像仓库,查看刚刚推送的dokcer镜像
接下来,按照下面命令,去构建k8s Deployment
cd /root
kubectl create deployment k8scicd --image=registry.cn-hangzhou.aliyuncs.com/zzz/k8scicd:v1 --port=80 --replicas=1 -n default --dry-run=client -o yaml > k8scicd-deployment.yaml
kubectl create -f k8scicd-deployment.yaml --record
kubectl expose deployment k8scicd --port=80 --type=NodePort
kubectl get pod,svc
通过上图可以看到,我们部署.NET 8.0 Web API项目的服务已经构建成功,这个项目对外的地址是:
http://192.168.126.194:32052/K8s_CICD/GetK8sCICD
http://192.168.126.195:32052/K8s_CICD/GetK8sCICD
http://192.168.126.196:32052/K8s_CICD/GetK8sCICD
2.4.6 编辑Jenkins Job
.NET 8.0 Web API项目已经部署成功。我们需要修改Jenkins Job让它支持项目发布后,自动生成docker镜像,推送镜像到阿里云,变更K8s集群的k8scicd的镜像版本为刚刚推送的镜像,这样版本就实现了升级更新。
按照下图去修改Build Steps--Excute Shell,并保存
#!/bin/sh -l
echo '开始发布.net 8.0项目'
cd K8s_CICD
dotnet restore
dotnet build
dotnet publish --framework net8.0 --runtime linux-x64 --no-dependencies
echo '发布.net 8.0项目-成功'
echo '开始拷贝.net 8.0项目到k8s机器,打包docker镜像'
cd /var/lib/jenkins/workspace/K8sCICD/K8s_CICD/bin/Release/net8.0/linux-x64/
docker build -f Dockerfile -t k8scicd:v$BUILD_ID .
echo '拷贝.net 8.0项目到k8s机器-成功,打包docker镜像-成功'
echo "开始登录阿⾥云镜像仓库,推送镜像"
docker login --username=xxxxx registry.cn-hangzhou.aliyuncs.com --password=*****
docker tag k8scicd:v$BUILD_ID registry.cn-hangzhou.aliyuncs.com/zzz/k8scicd:v$BUILD_ID
docker push registry.cn-hangzhou.aliyuncs.com/zzz/k8scicd:v$BUILD_ID
echo "登录阿⾥云镜像仓库-成功,推送镜像-成功"
echo "开始修改k8s机器的镜像"
kubectl set image deployment/k8scicd k8scicd=registry.cn-hangzhou.aliyuncs.com/zzz/k8scicd:v$BUILD_ID
echo "修改k8s机器的镜像-成功"
重新执行下 Jenkins Job:K8sCICD 试试。
查看.NET 8.0 WEB API是不是正常访问?
检查k8s 镜像记录
kubectl rollout history deployment k8scicd
kubectl rollout history deployment k8scicd --revision=2
从上面可以看到 镜像更新也是对的,是刚刚最新的镜像。
2.4.7 更新源代码
目标:代码修改后,提交到分支,需要触发CI/CD。
思路:通过 webhook触发jenkins构建:自动拉取代码,编译,发布,运行项目。
在Jenkins 安装插件:Generic Webhook Trigger、GitLab
上面2个插件安装成功后,就能在Installed plugins看到。
接下来,正式配置GitLab提交分支后 触发Jenkins执行Job
在Jenkins按照如下配置,拿到web hook地址:http://192.168.126.195:8080/project/K8sCICD
秘钥:073fbf97008038bef38ac7cc9d8b23d2
在GitLab按照如下去配置,实现本地网络通讯
打开具体项目去配置webhook链接。按下图操作
按照下面的操作,输入web hook地址:http://192.168.126.195:8080/project/K8sCICD
密钥:073fbf97008038bef38ac7cc9d8b23d2
最后点击 Add webhook
在k8s从节点lnode2,按照如下去修改代码,提交到master分支
cd /opt/K8s_CICD/K8s_CICD/Controllers/
通过命令修改 K8s_CICDController.cs
vim K8s_CICDController.cs
这里,修改下返回的 提示信息,加了个版本v3,方便在页面上看到差异,就能知道代码有修改,发布了新版本。
按照下面的命令,提交代码到分支。
git add .
git commit -m "v3 modify"
git push -u origin master
这个时候,看下Jenkins,发现Job已经被触发执行了
查看.NET 8.0 Web API是不是正常访问?页面是不是修改后的效果?
从上图可以看出,修改代码后的发布是成功的,页面是最新版本。
3.结束
本文是对CI/CD比较深入的一次探索,基本复刻了生产环境的流程模式。即便是使用商业产品腾讯Coding,它底层的原理也是类似的。在日常工作中,其实不需要程序员去搭建,运维工程师就搞定了。但对于我,为了多接触点K8s的落地应用,我实操了下,基本掌握了基于K8s的CICD,K8s对于我也没那么陌生了。
更多推荐
所有评论(0)