Kubernetes和容器的出现,使得软件开发测试变得相当繁琐,程序员修改代码以后,还需要经过很多步骤,才能看到修改的结果。

于是CI/CD工具应需而生。Jenkins是使用最广泛的CI/CD工具。Jenkins利用流水线的概念,把代码推送和拉取、镜像构建、容器部署等过程串在一起,通过代码推送自动触发,程序员修改好代码后,一推送到github,容器镜像就自动打包完成部署,程序员马上就可以看到结果,大大提高了开发效率。

不过,随着Kubernetes的底层组件从docker改为containerd,Jenkins在Kubernetes上的部署和使用,也变得非常复杂,所以建议尽可能部署在裸机或者docker里面。

讲一下Jenkins的安装、部署和使用过程。Jenkins 2.440.2 ,操作系统Debian12 , Docker 26.0.0 ,Kubernetes 1.28.4。

一、安装

  1. 在一台单独的主机上安装docker

运行

for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done

# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

2. 安装Jenkins Docker镜像

运行,部署dind镜像

docker run --name jenkins-docker --rm --detach \
  --privileged --network jenkins --network-alias docker \
  --env DOCKER_TLS_CERTDIR=/certs \
  --volume jenkins-docker-certs:/certs/client \
  --volume jenkins-data:/var/jenkins_home \
  --publish 2376:2376 \
  docker:dind --storage-driver overlay2

创建Dockerfile文件,内容如下

FROM jenkins/jenkins:2.440.2-jdk17
USER root
RUN apt-get update && apt-get install -y lsb-release
RUN curl -fsSLo /usr/share/keyrings/docker-archive-keyring.asc \
  https://download.docker.com/linux/debian/gpg
RUN echo "deb [arch=$(dpkg --print-architecture) \
  signed-by=/usr/share/keyrings/docker-archive-keyring.asc] \
  https://download.docker.com/linux/debian \
  $(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list
RUN apt-get update && apt-get install -y docker-ce-cli
USER jenkins
RUN jenkins-plugin-cli --plugins "blueocean docker-workflow"

运行下列命令,生成Jenkins镜像

docker build -t myjenkins-blueocean:2.440.2-1 .

部署Jenkins镜像

docker run --name jenkins-blueocean --restart=on-failure --detach \
  --network jenkins --env DOCKER_HOST=tcp://docker:2376 \
  --env DOCKER_CERT_PATH=/certs/client --env DOCKER_TLS_VERIFY=1 \
  --publish 8080:8080 --publish 50000:50000 \
  --volume jenkins-data:/var/jenkins_home \
  --volume jenkins-docker-certs:/certs/client:ro \
  myjenkins-blueocean:2.440.2-1

3. 初步配置Jenkins

运行docker logs jenkins-blueocean,可以看到初始管理员密码。

浏览器打开 http://jenkins-server-ip:8080/ , jenkins-server-ip是jenkins主机的IP地址。

输入初始管理员密码,安装建议插件,设置用户名、口令、全名和邮件地址,完成初始设置。

4. 安装插件

到dashborad->系统管理->插件管理栏目下,安装Docker pipeline、Kubernetes、Multibranch scan webhook triger 这几个插件。

5. 安装kubectl文件

在Jenkins主机上,运行

docker exec -u root -it jenkins-blueocean sh

登录到Jenkins容器内部,然后运行

cd /usr/local/bin
curl -LO "https://dl.k8s.io/v1.29.3/bin/linux/amd64/kubectl"
chmod a+x  ./kubectl
exit

把kubectl下载安装到Jenkins容器内部。

二、设置

1.设置dockerhub和github账号

到dashboard->系统管理->凭据管理->全局下面,点击Add Credentials ,类型选择Username with password ,范围选择全局,输入dockerhub的账号和密码,ID输入dockerhub-credentials,描述输入dockerhub credentials,点击create,完成dockerhub账号设置。

再点击Add Credentials ,类型选择Username with password ,范围选择全局,输入github的账号和密码,ID输入github-credentials,描述输入github credentials,点击create,完成github账号设置。

2. 设置Kubernetes

到Dashboard->系统管理->Clouds,点击New Cloud,输入名字k8s,type选择Kubernetes,在Kubernetes Cloud Details下面,输入Kubernetes地址,服务证书Key和凭据后,点击save保存。其中:

登录到Kubernetes集群的master主机上,运行

cat /etc/kubernetes/admin.conf

可以看到Kubernetes地址。

运行

cat /etc/kubernetes/admin.conf | grep certificate-authority-data

把上面运行的结果用base64解码

echo "LS0tLS1C....省略....CBDRVJUSUZJQ0FURS0tLS0tCg==" | base64 -d

就可以得到服务证书key。

再把master主机主目录下的~/.kube/config文件拷贝出来。凭据类型选择为secret file ,把config文件上传,设置为凭据。

3. 设置github对接

登录到github账号中,点击右上角的用户图标,点击setting,点击左下角的Developer setting->Personal access tokens->Tokens(classic),点击Generate new token(classic),Note 输入 Jenkins Intergration for CI/CD, Expiration选择No Expiration,Select scopes 选择repo 和admin:org_hook,点击底下的Generate token,生成令牌,把令牌复制到粘贴板。

进入Jenkins的管理页面,到Dashborad->系统管理->凭据管理->全局,点击 Add Credentials,类型选择Secret text,Secret中把令牌粘贴进去,ID输入Github_person_access_token,描述输入Github person access token,点击Create。

到Dashborad->系统管理->系统配置->github,点击添加github服务器->github server,名称输入github_server, 凭据选择github access token,点击连接测试,测试通过后,点击保存。

三、测试和使用

1. 部署测试案例

在github上新建一个公用Repository,名为Jenkins-kubernetes-deployment。

在Jenkins主机上运行下列命令,安装nodejs

curl -fsSL https://deb.nodesource.com/setup_21.x | sudo -E bash -
sudo apt-get install -y nodejs

运行下列命令,新建一个react.js应用。

npx create-react-app jenkins-kubernetes-deployment

运行

cd jenkins-kubernetes-deployment

进入jenkins-kubernetes-deployment目录

创建Dockerfile文件,内容如下

#It will use node:21-alpine3.19 as the parent image for 
#building the Docker image
FROM node:21-alpine3.19
#It will create a working directory for Docker. The Docker
#image will be created in this working directory.
WORKDIR /react-app
#Copy the React.js application dependencies from the 
#package.json to the react-app working directory.
COPY package.json .
COPY package-lock.json .
#install all the React.js application dependencies
RUN npm i
COPY . .
#Expose the React.js application container on port 3000
EXPOSE 3000
#The command to start the React.js application container
CMD ["npm", "start"]

创建deployment.yaml文件,内容如下

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment #The name of the Kubernetes 
        #Deployment to be created in the Kubernetes cluster
  labels:
    app: react-app
spec:
  replicas: 2 #The number of pods to be created in the 
   #Kubernetes cluster for the React.js application container
  selector:
    matchLabels:
      app: react-app
  template:
    metadata:
      labels:
        app: react-app 
    spec:
      containers:
      - name: react-app #The name of the react.js application container
        #The Docker image for building the React.js application container
        image: dockerhub-username/react-app:latest 
        ports:
        - containerPort: 3000 #The port for the React.js application container

创建service.yaml文件,内容如下

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment #The name of the Kubernetes 
        #Deployment to be created in the Kubernetes cluster
  labels:
    app: react-app
spec:
  replicas: 2 #The number of pods to be created in the 
   #Kubernetes cluster for the React.js application container
  selector:
    matchLabels:
      app: react-app
  template:
    metadata:
      labels:
        app: react-app 
    spec:
      containers:
      - name: react-app #The name of the react.js application container
        #The Docker image for building the React.js application container
        image: dockerhub-username/react-app:latest 
        ports:
        - containerPort: 3000 #The port for the React.js application container

创建Jenkinsfile,内容如下

pipeline {
  environment {
    dockerimagename = "dockerhub-username/react-app"
    dockerImage = ""
  }
  agent any
  stages {
    stage('Checkout Source') {
      steps {
         git  branch: 'main',
              credentialsId: 'github-credentials',
              url: 'https://github.com/GITHUB-USERNAME/jenkins-kubernetes-deployment.git'
      }
    }
    stage('Build image') {
      steps{
        script {
          dockerImage = docker.build dockerimagename
        }
      }
    }
    stage('Pushing Image') {
      environment {
          registryCredential = 'dockerhub-credentials'
           }
      steps{
        script {
          docker.withRegistry( 'https://registry.hub.docker.com', registryCredential ) {
            dockerImage.push("latest")
          }
        }
      }
    }
    stage('Deploying React.js container to Kubernetes') {
      steps {
          withKubeConfig([credentialsId: 'dcf2c18c-a6b0-474c-b6be-683002feeda5', serverUrl: 'https://192.168.234.30:6443']) {
              sh 'kubectl apply -f deployment.yaml -f service.yaml'
              sh 'kubectl rollout restart deployment/deployment'
      }
    }
  }
}

上面几个文件里面,dockerhub-username是你在dockerhub的用户名,GITHUB-USERNAME是你在github的用户名,按照实际情况修改。

dcf2c18c-a6b0-474c-b6be-683002feeda5是kubernetes的凭证标识,可以在dashboard->系统管理->凭证管理里面找到,根据实际情况修改。

https://192.168.234.30:6443是kubernete服务器地址,可以在kubernetes master主机的config文件中找到,根据实际情况修改。

运行下列命令,把代码同步到github

echo "# Jenkins Kubernetes Deployment." >> README.md
git init
git add -A
git commit -m "first commit"
git branch -M main
git remote add origin git@github.com:GITHUB-USERNAME/jenkins-kubernetes-deployment.git
git push -u origin main

其中GITHUB-USERNAME是你在github上的账号,按照实际情况修改。

2. 建立多分支流水线

选择dashborad->新建任务->多分支流水线,任务名输入jinkins-kubernetes-deployment,点击确定。

选择配置->分支源->增加源->github,选择凭据github-credentials, 输入仓库的HTTP地址 https://github.com/GITHUB_USERNAME/jenkins-kubernetes-deployment.git,点击保存。其中GITHUB-USERNAME是你在github上的账号,按照实际情况修改。

3.测试多分支流水线

选择Dashboard->Jenkins-kubernetes-deployment->立刻扫描仓库,点击扫描仓库日志,可以看到Jenkinsfile被扫描检出,并且自动执行了。

选择Dashboard->Jenkins-kubernetes-deployment->main,点击页面左下方的构建历史号码,点击Console Output,可以看到流水线的执行过程。

如果发生错误,可以根据错误输出,分析错误来源,排除问题。

如果流水线执行顺利完成,登录到Kubernetes的master主机,运行

kubectl get deployment
kubectl get svc

可以看到kubernetes上新增了一个deployment ,名为deployment,也新增了一个service,名为service。

react app程序已经成功部署到了kubernete集群上面。

4. 设置自动触发功能

选择Dashboard->Jenkins-kubernetes-deployment->配置->扫描仓库触发器,选中scan by webhook,Trigger token中填入web-tkn,点击保存。

在很多情况下,Jenkins主机没有外网IP,可以通过smee进行内网转发。

访问网站smee.io,点击start a new channel,得到一个URL链接,类似于https://smee.io/hmLjcRNC2XkvfZM5

在Jenkins主机上,运行

npm install --global smee-client

新建文件/etc/systemd/system/smee.service,内容如下

[Unit]
Description=smee.io webhook delivery from GitHub
After=network.target
StartLimitIntervalSec=0

[Service]
Type=simple
Restart=always
RestartSec=1
ExecStart=/usr/bin/smee  --url https://smee.io/hmLjcRNC2XkvfZM5 --path /multibranch-webhook-trigger/invoke?token=web-tkn --port 8080
[Install]
WantedBy=multi-user.target

其中https://smee.io/hmLjcRNC2XkvfZM5是从smee网站获得的URL链接,根据实际情况修改。

运行下列命令,开启smee转发功能。

systemctl daemon-reload
systemctl start smee
systemctl enable smee

访问https://github.com/GITHUB-USERNAME/jenkins-kubernetes-deployment/settings ,选择webhooks,点击Add webhook。其中GITHUB-USERNAME是你在github上的账号,按照实际情况修改。

在Payload URL中输入从smee获得的URL链接。Content type选择application/json,触发事件选择just the push event,点击Add webhook保存。

5. 测试自动触发功能

在jenkins-kubernetes-deployment目录下,运行

echo "# test " >> README.md
git add -A
git commit -m "new commit"
git push -u origin main

修改代码后,把代码推送到github。

到Dashboard->Jenkins-kubernetes-deployment->main,点击页面左下方的构建历史号码,点击Console Output,可以看到流水线再次自动执行。

自动触发功能已经成功起效。

Jenkins安装部署完成,只要把程序代码push到github,流水线就会自动执行,完成同步代码、构建镜像、向dockerhub推送镜像、最后在kubernetes集群中部署deployment和service的整个过程。

参考:

https://www.red-gate.com/simple-talk/devops/containers-and-virtualization/deploying-a-dockerized-application-to-the-kubernetes-cluster-using-jenkins/

https://www.digitalocean.com/community/tutorials/how-to-set-up-continuous-integration-pipelines-in-jenkins-on-ubuntu-20-04

https://www.jenkins.io/doc/book/installing/docker

https://docs.ucloud.cn/uk8s/bestpractice/cicd

https://www.orchome.com/16641

https://medium.com/@esthernnolum/trigger-jenkins-builds-with-github-webhook-using-smee-client-7eb6a6f7bea8

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注