介绍
一般的ci/cd流程是:
本地写代码-->git上传到GitHub,gitlab或者gitee等-->单元测试-->编写流水线pipeline/Jenkinsfile-->代码打包-->推送镜像-->部署容器到测试环境-->拉取镜像-->启动容器-->应用测试-->测试通过部署到生产环境。
我这里采用编写Jenkinsfile的方式,启动流水线,推送镜像到harbor,并部署应用到k8s集群上。
因为我的集群版本是1.22,使用的cri是containerd,没有使用docker,所以这里采用kaniko来部署应用。
实例
1.提交代码到gitee
这是我的测试代码:https://gitee.com/wghdrr/cncamp.git
2.Jenkins创建credentials
创建gitee的用户名密码凭据。
3.安装gitee插件
4.创建流水线
选择gitee
选择pipeline script from scm,scm选择git,Repository URL填写gitee地址,Credentials 选择上面创建的gitee用户名密码。
分支选择master(这个根据自己的代码来),脚本路径填写Jenkinsfile,保存。
5.编写Jenkinsfile
上传Jenkinsfile到gitee中。
podTemplate(containers: [
containerTemplate(
name: 'golang',
command: 'cat',
image: 'golang:1.17.5',
ttyEnabled: true
),
containerTemplate(
name: 'kubectl',
command: 'cat',
image: 'harbor.wghdr.top/kaniko/kubectl:latest',
ttyEnabled: true
),
],
yaml: """
apiVersion: v1
kind: Pod
metadata:
name: kaniko
spec:
containers:
- name: kaniko
image: harbor.wghdr.top/kaniko/executor:latest
command:
- /busybox/cat
tty: true
volumeMounts:
- name: kaniko-secret
mountPath: /kaniko/.docker
restartPolicy: OnFailure
volumes:
- name: kaniko-secret
secret:
secretName: regcred
""".stripIndent()
) {
node(POD_LABEL) {
stage('clone') {
git credentialsId: 'gitee-user', url: 'https://gitee.com/wghdrr/cncamp.git'
}
stage('Compile') {
container('golang') {
sh """
make
"""
}
}
stage('Test') {
echo "Test Stage"
}
stage('build image') {
container(name: 'kaniko') {
sh """
/kaniko/executor -c `pwd` --dockerfile `pwd`/Dockerfile --destination harbor.wghdr.top/jenkins/httpserver:v1 --skip-tls-verify
"""
}
}
stage('deploy') {
withCredentials([file(credentialsId: 'kube-config', variable: 'KUBECONFIG')]) {
container('kubectl') {
sh """
mkdir -p ~/.kube && cp ${KUBECONFIG} ~/.kube/config
kubectl apply -f httpserver.yaml
"""
}
}
}
}
}
解释
containers :
声明jenkins-slave的容器镜像模版。包括容器名golang,kubectl,启动命令等。代码是go的所以用了golang:1.17.5
,kubectl镜像是为了在集群中部署应用。
yaml:
声明kaniko/dind pod的配置信息。包括镜像为executor:latest
,命令,目录挂载kaniko-secret,这里是为了把镜像免密推送到harbor。
cat ~/.docker/config.json
cp ~/.docker/config.json .
kubectl -n jenkins create secret generic regcred --from-file=config.json
node(POD_LABEL):
指定jenkins-slave的label。
stage('clone')
使用gitee-user的凭据克隆代码。
stage('Compile'),container('golang')
在golang容器中使用make命令编译代码。golang容器是在containers中定义的。
stage('Test')
这里可以进行一些单元测试,我这里略过。
stage('build image'),container(name: 'kaniko')
在kaniko容器中构建镜像。
/kaniko/executor -c `pwd` --dockerfile `pwd`/Dockerfile --destination harbor.wghdr.top/jenkins/httpserver:v1 --skip-tls-verify
# /kaniko/executor 为kaniko程序命令
# -c 指定context目录为当前目录
# --dockerfile 指定以当前目录的Dockerfile构建
# --destination 指定镜像名和tag,推送地址为harbor
stage('deploy'),withCredentials
指定集群的kube-config
container('kubectl')
在kubectl容器中部署httpserver的deployment。
6.启动流水线
查看输出:
读取Jenkinsfile,开始pipeline,创建slave pod,命名规则为pipline的名字-构建次数-pod模版hash值-随机值。pod的详细yaml。
slave pod中的环境变量,各个容器的镜像,镜像拉取策略,是否开启tty,资源限制,目录挂载等。
harbor的secret挂载,clone代码。
编译,测试stage。
构建镜像。
推送镜像,部署到集群中。
构建成功,结束流水线。
7.查看镜像
登录harbor,选择jenkins项目,httpserver的下载次数为1。
查看镜像名和tag。
8.查看pod
k get po | grep httpserver
k describe po httpserver-7896d75885-2c9jf | grep -i image
jenkins-slave的pod已经被自动删除。
9.测试pod功能
测试成功。