6

Jenkins与外部系统集成

 2 years ago
source link: https://www.bladewan.com/2021/10/14/jenkins_Docking_external_system/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Jenkins与外部系统集成

2021-10-14

CI/CD

CI/CD

评论 字数统计: 4,147(字) 阅读时长: 19(分)

[toc]

软件 版本 gitlab 14.3.0 Jenkins 2.303.1 Harbor 1.10.2 Sonar 9.1 Nexus 3.35.0-02 ArgoCD 2.1.3

部署gitlab

docker run --detach --hostname 10.8.242.28 --publish 443:443 --publish 80:80 --publish 1022:22 --name gitlab --restart always --volume /srv/gitlab/config:/etc/gitlab --volume /srv/gitlab/logs:/var/log/gitlab --volume /srv/gitlab/data:/var/opt/gitlab gitlab/gitlab-ce:12.10.3-ce.0

替换hostname为实际节点外网IP

部署Harbor

Harbor部署与管理
部署前先修改docker
编辑docker

vim /etc/docker/daemon.json
"insecure-registries" : ["0.0.0.0/0"]

重启docker

systemctl restart docker

安装docker-compose

curl -L https://github.com/docker/compose/releases/download/1.24.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

下载harbor

https://github.com/goharbor/harbor/releases/download/v1.10.2/harbor-online-installer-v1.10.2.tgz

配置harbo.yaml

hostname: 172.31.48.86 //修改为实际节点IP

屏蔽https配置

安装harbor

./install.sh --with-clair


docker-compose ps
Name Command State Ports
---------------------------------------------------------------------------------------------
clair /docker-entrypoint.sh Up (healthy) 6060/tcp, 6061/tcp
harbor-core /harbor/start.sh Up (healthy)
harbor-db /entrypoint.sh postgres Up (healthy) 5432/tcp
harbor-jobservice /harbor/start.sh Up
harbor-log /bin/sh -c /usr/local/bin/ ... Up (healthy) 127.0.0.1:1514->10514/tcp
harbor-portal nginx -g daemon off; Up (healthy) 80/tcp
nginx nginx -g daemon off; Up (healthy) 0.0.0.0:80->80/tcp
redis docker-entrypoint.sh redis ... Up 6379/tcp
registry /entrypoint.sh /etc/regist ... Up (healthy) 5000/tcp
registryctl /harbor/start.sh Up (healthy)

访问http://node_ip

admin/Harbor12345

创建测试项目

spring-petclinic官方示例项目地址:https://projects.spring.io/spring-petclinic/

本次实践针对Spring官方提供的spring-petclinic示例项目进行容器化部署,该项目采用Spring Boot + Thymeleaf开发,数据库可使用MySQL、H2等,本实践为操作方便直接使用内置的H2数据库。

注意:由于本实践采用的是H2内置数据库,所以每个应用实例的数据独立,也使得应用变成了有状态应用,而生产的最佳实践应该是数据采用外部存储,且应用采用无状态方式部署。

国内clone地址:https://gitee.com/wanshaoyuan/spring-petclinic.git

将此项目clone后上传到私有的gitlab中.

与Gitlab集成

安装gitlab插件

Gitlab中申请AccessToken

将申请成功的token保存好

配置Jenkins对接gitlab

添加凭证

测试连接

读取gitlab中项目spring-petclinic项目中pom.xml文件

配置连接gitlab私有项目的密钥可以用ssh密钥也可以使用账号密码

分支处修改为main分支

去cat这个文件输出内容

执行立即构建

输出结果为实际我们的pom.xml的文件内容

与Kubernetes集成构建分布式动态编译环境

安装Kubernetes插件

Jenkins与Kubernetes集成实现动态Slave Pod,需要安装Kubernetes插件:

  • kubernetes

安装Kubernetes Continuous Deploy插件

Jenkins访问kubernetes需要依赖于kubeconfig,为支持kubeconfig类型的凭据配置,需要安装Kubernetes Continuous Deploy插件:

  • Kubernetes Continuous Deploy

配置Kubernetes集群

配置 系统管理—>系统设置—>新增一个云

配置Jenkins URL,这里可以不配置api-server地址和证书key,连接kubernetes,所以默认会去读取放在JENKINS_HOME的.kube/目录的kubeconfig文件,用于连接集群。我这里是通过安装包的方式安装的Jenkins HOME在/var/lib/jenkins/目录,如果是通过容器方式启动,将kubeconfig文件直接放~/.kube/目录。
保存到Jenkins主机的config文件中

复制粘贴到Jenkins容器内的~/.kube/config文件中

docker exec -it jenkins mkdir /root/.kube/
docker cp config jenkins:/root/.kube/config

注意:
此方式Jenkins容器重启后,会将目录重新初始化覆盖掉,kubeconfig文件,生产环境可以直接挂载。

验证Pipeline流水线

以上Jenkins与Kubernetes的集成配置就基本完成了,下面在正式为Spring Petclinic应用创建Pipeline之前,先简单测试下Jenkins与Kubernetes集成Pipeline流水线是否正常。

  • 新建一个流水线类型的任务test-hello-pipeline
  • 准备流水线测试脚本
pipeline {
agent {
kubernetes {
cloud 'Kubernetes'
namespace 'default'
yaml """
apiVersion: v1
kind: Pod
spec:
containers:
- name: busybox
image: busybox
command:
- sleep
args:
- infinity
stages {
stage('Test') {
steps {
container('busybox') {
sh "echo 'hello world'"

以上是一个简单的声明式pipeline,利用busybox镜像输出hello world字符串。

  • 添加流水线脚本

把测试脚本添加到任务的流水线脚本框中:

  • 保存流水线,并执行构建
  • 查看JOB运行结果

在Kubernetes中可以看到Jenkins自动创建了Pod来执行任务,任务执行完成以后,Pod自动删除。

Jenkins中查看下构建的控制台输出,正常输出了hello world

验证结果表明,Jenkins与Kubernetes配置成功,Pipeline运行正常。

Sonar-Qube对接实现代码质量扫描

安装sonarqube

helm repo add sonarqube https://SonarSource.github.io/helm-chart-sonarqube
helm repo update
kubectl create namespace sonarqube

helm安装sonarqube

helm install sonarqube --namespace sonarqube sonarqube/sonarqube --set postgresql.persistence.enabled=false

注意:这里为了快速部署没有设置postgresql的持久化存储,有数据丢失风险,生产环境postgresql建议设计HA或持久化存储。
设置为NodePort对外暴露

kubectl patch svc sonarqube-sonarqube -p '{"spec": {"type": "NodePort"}}' -n sonarqube

查看NodePort端口

kubectl get svc -n sonarqube
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
sonarqube-postgresql ClusterIP 10.110.40.18 <none> 5432/TCP 4m41s
sonarqube-postgresql-headless ClusterIP None <none> 5432/TCP 4m41s
sonarqube-sonarqube NodePort 10.106.78.100 <none> 9000:30005/TCP 4m41s

查看启动成功

kubectl get pod -n sonarqube
NAME READY STATUS RESTARTS AGE
sonarqube-postgresql-0 1/1 Running 0 4m7s
sonarqube-sonarqube-0 1/1 Running 0 4m7s

访问节点的30005端口

默认密码admin/admin

如果需要中文直接安装插件就好
administrator—->Marketplace
搜索Chinese—-安装

生成token
申请token
administrator—>security—>user—>token
保存生成token

Jenkins配置

安装插件
系统设置—>插件管理
安装SonarQube Scanner for Jenkins

配置插件
配置sonarQube-server

Server URL填写sonarqube的地址

Server authentication token填写刚刚创建的token,这里创建一个密钥
类型为Secret Text。Secret填写token详细信息,ID为此secret的名称

配置sonarQUbe-agent
系统管理->全局工具配置——>SonarQube Scanner
此处配置为自动安装

FreeStyle风格任务下配置SonarQube

以上面的test-gitlab项目的spring-petclinic为例
先执行maven构建出class文件,在进行扫描,因为sonarQube扫描的对象是.class而不是.java文件。

docker run -i -v /var/jenkins_home/workspace/:/tmp maven:3.6-jdk-8 mvn -f /tmp/spring-petclinic/pom.xml clean package -DskipTests

在构建阶段添加”Execute SonarQube Scanner”

输入以下内容

sonar.projectKey=test
sonar.projectName=test
sonar.projectVersion=1.0
sonar.sources=src
sonar.java.binaries=target/classes
sonar.language=java
sonar.sourceEncoding=UTF-8

注:
sonar.projectKey=Test #sonar那显示project-key
sonar.projectName=Test #sonar那显示project名字
sonar.projectVersion=1.0 ##sonar那显示project版本
sonar.sources=src #指定要扫描的源码目录。
sonar.java.binaries=target/classes #指定java文件编译后class文件目录。
sonar.language=java #只扫描的语言。
sonar.sourceEncoding=UTF-8 #指定源码的编码格式,一般都会去指定为UTF-8。

执行构建
Jenkins处查看

sonar处查看

Jenkins-Pipeline风格任务下配置SonarQube

使用Pipeline流水线,需要在添加以下步骤

1、在对应的代码库的根目录创建sonar-project.properties

sonar.projectKey=test2
sonar.projectName=test2
sonar.projectVersion=1.0
sonar.sources=src
sonar.java.binaries=target/classes
sonar.java.source=1.8
sonar.java.target=1.8
sonar.language=java
sonar.sourceEncoding=UTF-8

Pipeline中添加以下步骤

Pipeline中添加以下步骤

stage('SonarQube analysis') {
steps {
script {
def sonarqubeScannerHome = tool name: 'SonarQubeScanner'
withSonarQubeEnv('sonar') {
sh "${sonarqubeScannerHome}/bin/sonar-scanner"

注:
1、SonarQubeScanner为全局工具配置中的SonarQube Scanner的配置名称。
2、withSonarQubeEnv配置的sonar变量为全局——>系统配置sonar-server的配置名称

清空workspace

rm -rf /var/jenkins_home/workspace/spring-petclinic

Sonattype-Nexus

Nexus是开源的制品库,可以用来存储一些代码构建后的制品如jar包,npm包和docker镜像等。也可以将存放制品后的仓库做为私服,供给给后面需要内网编译的软件使用。

软件版本:3.35.0-02
本次部署为了更加方便和快捷,采用Docker方式部署
创建目录

mkdir /var/nexus-data && chown -R 200 /var/nexus-data

Docker运行

docker run -d -p 8081:8081 --name nexus -v /var/nexus-data:/nexus-data sonatype/nexus3

初始账号和密码访问
账号:admin
密码:

cat /var/nexus-data/admin.password

仓库分为三种类型,proxy、group、hosted。
Proxy:Repository是代理仓库,可以配置上游仓库地址,如阿里云仓库地址。当本地仓库不到时,去向配置的上游仓库查找。
hosted:供本地使用的本地仓库。
group:仓库组,将多个仓库合成一个组,查找jar包时,会按照仓库组中的仓库顺序下载jar包。

这里创建两个名为spring-petclinic-releases、spring-petclinic-snapshots,类型为hotsted的Maven2仓库。

releases库主要用于存储正式版的制品,snapshots存储持续集成过程中产生的制品。

这里可以根据情况进行修改为release或snapshots

maven处配置
在spring-petclinic目录下创建conf/settings.xml文件用于存放连接Nexus3的凭证信息,正常可以在maven_home或~/.m2/目录有这文件。因为这里是使用Docker进行构建编译,所以这里直接与业务代码放置在一起。
settings.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<pluginGroups>
</pluginGroups>
<proxies>
</proxies>
<servers>
<server>
<id>releases</id>
<username>账号</username>
<password>密码</password>
</server>
<server>
<id>snapshots</id>
<username>账号</username>
<password>密码</password>
</server>
</servers>
</settings>

关闭https检测,因为Nexus3使用的是http方式对外暴露所以需要关闭maven构建时强行要求https链接

src/checkstyle/nohttp-checkstyle.xml
注释
<module name="io.spring.nohttp.checkstyle.check.NoHttpCheck"/>
注释后:
<!-- <module name="io.spring.nohttp.checkstyle.check.NoHttpCheck"/> -->

pom.xml文件添加以下内容

<distributionManagement>
<repository>
<!--id的名字可以任意取,但是在setting文件中的属性<server>的ID与这里一致-->
<id>releases</id>
<!--指向仓库类型为host(宿主仓库)的储存类型为Release的仓库-->
<url>http://172.16.0.195:8081/repository/mspring-petclinic-releases/</url>
</repository>
<snapshotRepository>
<id>snapshots</id>
<!--指向仓库类型为host(宿主仓库)的储存类型为Snapshot的仓库-->
<url>http://172.16.0.195:8081/repository/spring-petclinic-snapshots/</url>
</snapshotRepository>
</distributionManagement>


docker run -i -v /root/spring-petclinic/:/tmp maven:3.6-jdk-8 mvn -f /tmp/pom.xml --settings /tmp/conf/settings.xml clean deploy

编译完成上传成功后

在spring-petclinic-snapshots仓库内可见上传来的jar包,对应的jar包后面也接上了对应的时间戳,方便进行分类。

如果要上传到release仓库,将pom.xml中的<version>2.5.0-SNAPSHOT</version>中的-SNAPSHOT字段删除就表示为正式版。

ArgoCD集成实现CD端对接

编写并上传部署spring-petclinic的yaml文件和Dockerfile文件

apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-petclinic-0-0-1
spec:
selector:
matchLabels:
app: spring-petclinic
version: 0.0.1
replicas: 1
template:
metadata:
labels:
app: spring-petclinic
version: 0.0.1
spec:
containers:
- name: spring-petclinic
image: registry.cn-shenzhen.aliyuncs.com/yedward/spring-petclinic:0.0.1
resources:
limits:
memory: 2Gi
cpu: 1
ports:
- containerPort: 8080
livenessProbe:
failureThreshold: 3
httpGet:
path: /actuator/health/liveness
port: 8080
scheme: HTTP
initialDelaySeconds: 30
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 2
readinessProbe:
failureThreshold: 3
httpGet:
path: /actuator/health/readiness
port: 8080
scheme: HTTP
initialDelaySeconds: 30
periodSeconds: 5
successThreshold: 2
timeoutSeconds: 2
apiVersion: v1
kind: Service
metadata:
name: spring-petclinic-svc-0-0-1
spec:
selector:
app: spring-petclinic
version: 0.0.1
ports:
- port: 8080
targetPort: 8080
type: NodePort

将yaml中的镜像地址改为实际的镜像仓库地址和项目名称。
Dockerfile

FROM registry.cn-shenzhen.aliyuncs.com/yedward/openjdk:8-jre-slim
# 企业实际场景中应该通过USER指定以非root用户运行
USER appuser
EXPOSE 8080
COPY target/*.jar /app/
WORKDIR /app
CMD java -jar -Xms1024m -Xmx1024m /app/spring-petclinic.jar

上传到gitlab中的spring-petclinic项目中

部署ArgoCD

单节点部署
使用官网快速部署

kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

部署完后产生以下服务

NAME READY STATUS RESTARTS AGE
pod/argocd-application-controller-0 1/1 Running 0 5d6h
pod/argocd-dex-server-74588646d-sz9g8 1/1 Running 0 2d2h
pod/argocd-redis-5ccdd9d4fd-csthm 1/1 Running 1 5d6h
pod/argocd-repo-server-5bbb8bdf78-mxkv7 1/1 Running 0 18h
pod/argocd-server-789fb45964-82mzx 1/1 Running 0 18h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/argocd-dex-server ClusterIP 10.43.180.172 <none> 5556/TCP,5557/TCP,5558/TCP 5d6h
service/argocd-metrics ClusterIP 10.43.184.97 <none> 8082/TCP 5d6h
service/argocd-redis ClusterIP 10.43.4.233 <none> 6379/TCP 5d6h
service/argocd-repo-server ClusterIP 10.43.9.45 <none> 8081/TCP,8084/TCP 5d6h
service/argocd-server NodePort 10.43.48.239 <none> 80:31320/TCP,443:31203/TCP 5d6h
service/argocd-server-metrics ClusterIP 10.43.149.186 <none> 8083/TCP 5d6h
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/argocd-dex-server 1/1 1 1 5d6h
deployment.apps/argocd-redis 1/1 1 1 5d6h
deployment.apps/argocd-repo-server 1/1 1 1 5d6h
deployment.apps/argocd-server 1/1 1 1 5d6h
NAME DESIRED CURRENT READY AGE
replicaset.apps/argocd-dex-server-74588646d 1 1 1 5d6h
replicaset.apps/argocd-redis-5ccdd9d4fd 1 1 1 5d6h
replicaset.apps/argocd-repo-server-5bbb8bdf78 1 1 1 5d6h
replicaset.apps/argocd-server-789fb45964 1 1 1 5d6h
NAME READY AGE
statefulset.apps/argocd-application-controller 1/1 5d6h

使用NodePort方式为对外暴露

kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "NodePort"}}'

访问dashboard

默认帐号为admin,密码通过secret获取

kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

配置ArgoCD

配置对接gitlab
setting——>Repositories->Connect repo using HTTPS

如果对应的git是私有库,pull需要帐号密码则需要在argo设置中配置repo connect

填写对应的帐号密码,如果是自签名证书需要将CA附上

创建Project
setting——>Projects
项目是argocd中的管理对象,也与之对应的发布权限相关联。
创建项目,并配置DESTINATIONS,能够发布到哪些集群和命名空间

创建Application

点击sync会自动将yaml文件部署到k8s集群中。
可以在Kubernetes集群中查看到

kubectl get pod
NAME READY STATUS RESTARTS AGE
spring-petclinic-0-0-1-6695b96956-xx9nw 1/1 Running 0 28m

Harbor中创建对应项目

在harbor中创建spring-petclinic项目

gitlab Webhook配置

当前Jenkins进行CI构建还是基于手动点击运行,可以配置基于gitlab的触发事件进行调用,如push、merge、tag push等事件触发回调Jenkins自动执行CI
jenkins处打开项目触发器

生成连接Secret token保存下来

Gitlab配置:
root登录后,需要开放安全配置,允许本地local网络连接
在menu选择admin——>settings-——>Network——>Outbound requests

Allow requests to the local network from web hooks and services
Allow requests to the local network from system hooks

将Jenkins的ip添加到白名单中,保存。

项目——>setting——>webhooks

填写Jenkins对应的回调地址和token

点击Test settings即可在Jenkins处看见已经开始的构建任务。

test这里选择基于事件回调。查看Jenkins处是否开始自动执行任务。

Jenkins配置

Argo是检查到yaml文件变化会进行自动发布到k8s中,那么我们只需要在Jenkins中增加修改和上传yaml阶段即可。

完整的构建阶段shell
编译阶段shell

docker run -i -v /var/jenkins_home/workspace/:/tmp maven:3.6-jdk-8 mvn -f /tmp/spring-petclinic/pom.xml clean package -DskipTests

代码扫描阶段

sonar.projectKey=test
sonar.projectName=test
sonar.projectVersion=1.0
sonar.sources=src
sonar.java.binaries=target/classes
sonar.language=java
sonar.sourceEncoding=UTF-8

镜像构建阶段

docker login -u useradmin -p password harbor_ip
docker build -t harbor_ip/spring-petclinic/spring-petclinic:$BUILD_NUMBER .
docker push harbor_ip/spring-petclinic/spring-petclinic:$BUILD_NUMBER

注:
1、这里使用Jenkins内置BUILD_NUMBER号为镜像tag,跟Jenkins的CI号是匹配的。
2、将上传镜像的账号密码修改为实际的账号密码。

发布更新部署yaml阶段

git clone http://username:[email protected]/root/spring-petclinic.git
git config --global user.email "[email protected]"
git config --global user.name "root"
git remote set-url origin http://username:[email protected]/root/spring-petclinic.git
sed -i "s/spring-petclinic:.*/spring-petclinic:$BUILD_NUMBER/g" spring-petclinic/deployment.yaml
cd spring-petclinic/
git add deployment.yaml
git commit -m "update yaml"
git push origin main

在配置一个构建后删除操作,避免构建后缓存影响下次构建

执行构建,构建成功后查看对应的k8s中的部署的业务镜像版本号是否与实际应用部署的环境变量相同。

kubectl describe pod/spring-petclinic-0-0-1-699954b589-h7n58
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 57m default-scheduler Successfully assigned default/spring-petclinic-0-0-1-7969df6996-dn2cc to rke-node2
Normal Pulled 57m kubelet Container image "1.13.173.7:8080/spring-petclinic/spring-petclinic:15" already present on machine
Normal Created 57m kubelet Created container spring-petclinic
Normal Started 57m kubelet Started container spring-petclinic

访问节点ip+spring-petclinic服务暴露出来的NodePort端口

这是一个宠物医院的管理系统,可以通过此页面进行宠物管理。

Jenkins内置环境变量
直接访问${YOUR_JENKINS_HOST}/env-vars.html即可

BUILD_NUMBER, 唯一标识一次build,例如23;
BUILD_ID,基本上等同于BUILD_NUMBER,但是是字符串,例如2011-11-15_16-06-21;
JOB_NAME, job的名字,例如JavaHelloWorld;
BUILD_TAG,作用同BUILD_ID,BUILD_NUMBER,用来全局地唯一标识一此build,例如jenkins-JavaHelloWorld-23;
EXECUTOR_NUMBER, 例如0;
NODE_NAME,slave的名字,例如MyServer01;
NODE_LABELS,slave的label,标识slave的用处,例如JavaHelloWorld MyServer01;
JAVA_HOME, java的home目录,例如C:\Program Files (x86)\Java\jdk1.7.0_01;
WORKSPACE,job的当前工作目录,例如c:\jenkins\workspace\JavaHelloWorld;
HUDSON_URL = JENKINS_URL, jenkins的url,例如http://localhost:8000/ ;
BUILD_URL,build的url 例如http://localhost:8000/job/JavaHelloWorld/23/;
JOB_URL, job的url,例如http://localhost:8000/job/JavaHelloWorld/;
SVN_REVISION,svn 的revison, 例如4;



About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK