Kubernetes实战——DevOps集成SpringBoot项目

目录

一、安装Gitlab

1、安装并配置Gitlab

1.1 、下载安装包

1.2、安装

1.3、修改配置文件

1.4、更新配置并重启

 2、配置

2.1、修改密码

2.2、禁用注册功能

2.3、取消头像

2.4、修改中文配置

2.5、配置 webhook

3、卸载 

二、安装镜像私服Harbor

1、下载安装包

 2、安装

三、安装代码质量扫描工具sonarqube

1、pgsql.yaml

2、sonarqube.yaml

 3、安装

四、安装Jenkins

1、构建带有maven和sonarqube的镜像

2、安装jenkins

2.1、创建Harbor secret

2.2、 jenkins-configmap.yaml

2.3、jenkins-pvc.yaml

2.4、jenkins-serviceAccount.yaml

2.5、jenkins-deployment.yaml

2.6、jenkins-service.yaml

2.7、创建资源

 3、配置

3.1 、获取初始密码

 3.2、安装插件

3.2.1、Build Authorization Token Root

3.2.2、Gitlab

3.2.3、SonarQube Scanner

3.2.4、Node and Label parameter

3.2.5、Kubernetes

3.2.6、Config File Provider

3.2.7、Git Parameter

3.3、插件配置

3.3.1、SonarQube Scanner配置

3.3.2、kubernetes配置

3.3.3、创建gitlab凭证

五、构建项目

1、创建gitlab的secret

2、配置jenkins任务

2.1、创建流水线Job

 2.2、配置流水线​编辑

2.3、配置gitlab的Webhooks​编辑

2.4、测试构建

 2.5、测试

3、构建SpringBoot项目 

3.1、配置项目流水线

 3.2、创建镜像私服全局凭证

 3.3、创建kubeconfig文件

 3.4、创建sonarqube的webhook

 3.5、 cicd-demo.yaml配置文件

 3.6、cicd-demo-dev.yaml

 3.7、Dockerfile

 3.8、Jenkinsfile

 3.9、完整代码见附录 

 3.10、部署成功效果

六、附录

1、Gitlab安装包

2、Harbor安装包

3、带有Maven的Jenkins镜像

4、源码地址


一、安装Gitlab

1、安装并配置Gitlab

这里使用安装包的方式安装,如果需要Docker方式安装请点击这里

1.1 、下载安装包

wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-15.9.1-ce.0.el7.x86_64.rpm

1.2、安装

rpm -i gitlab-ce-15.9.1-ce.0.el7.x86_64.rpm

1.3、修改配置文件

vim /etc/gitlab/gitlab.rb 
#修改 external_url 访问路径
http://<ip>:<port>
例如我这里改为 
external_url 'http://192.168.139.184:9000'

# 修改时区
gitlab_rails['time_zone'] = 'Asia/Shanghai'

1.4、更新配置并重启

gitlab-ctl reconfigure
gitlab-ctl restart

 2、配置

2.1、修改密码

访问上面配置的external_url  http://192.168.139.184:9000/

查看默认密码

cat /etc/gitlab/initial_root_password

 默认账号是root 密码为查看到密码

右上角头像 > Perferences > Password

2.2、禁用注册功能

点击左上角三横 > Admin>Settings > General > Sign-up restrictions > 取消 Sign-up enabled > Save changes

2.3、取消头像

Settings > General > Account and limit > 取消 Gravatar enabled > Save changes

2.4、修改中文配置

Settings > Preferences > Localization > Default language > 选择简体中文 > Save changes

为当前用户设置中文,保存后刷新页面即可

 右上角用户头像 > Preferences > Localization > Language > 选择简体中文 > Save changes

2.5、配置 webhook

设置>网络>出站请求>勾选>保存

3、卸载 

# 停止服务
gitlab-ctl stop

# 卸载 rpm 软件(注意安装的软件版本是 ce 还是 ee)
rpm -e gitlab-ce

# 查看进程
ps -ef|grep gitlab 
# 干掉第一个 runsvdir -P /opt/gitlab/service log 进程

# 删除 gitlab 残余文件
find / -name *gitlab* | xargs rm -rf
find / -name gitlab | xargs rm -rf

二、安装镜像私服Harbor

1、下载安装包

#下载安装包
wget https://github.com/goharbor/harbor/releases/download/v1.10.19/harbor-offline-installer-v1.10.19.tgz

#解压
tar -zxf harbor-offline-installer-v1.10.19.tgz 

 2、安装

修改配置文件

vim harbor.yml

安装

 ./install.sh

   访问http://192.168.139.184:8899/ 默认账号为admin 密码为Harbor12345

 配置docker文件,并重启docker服务 。

{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "registry-mirrors": [
        "https://do.nark.eu.org",
        "https://dc.j8.work",
        "https://docker.m.daocloud.io",
        "https://dockerproxy.com",
        "https://docker.mirrors.ustc.edu.cn",
        "https://docker.nju.edu.cn"
    ],
"insecure-registries": ["http://192.168.139.184:8899"]  #新增的配置
}

三、安装代码质量扫描工具sonarqube

1、pgsql.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-data
  namespace: kube-devops
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: "manager-nfs-storage"  #前面安装的storageclass
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres-sonar
  namespace: kube-devops
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres-sonar
  template:
    metadata:
      labels:
        app: postgres-sonar
    spec:
      containers:
      - name: postgres-sonar
        image: postgres:14.2
        ports:
        - containerPort: 5432
        env:
        - name: POSTGRES_DB
          value: "sonarDB"
        - name: POSTGRES_USER
          value: "sonarUser"
        - name: POSTGRES_PASSWORD 
          value: "123456"
        volumeMounts:
          - name: data
            mountPath: /var/lib/postgresql/data
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: postgres-data
---
apiVersion: v1
kind: Service
metadata:
  name: postgres-sonar
  namespace: kube-devops
  labels:
    app: postgres-sonar
spec:
  type: NodePort
  ports:
  - name: postgres-sonar
    port: 5432
    targetPort: 5432
    protocol: TCP
  selector:
    app: postgres-sonar

2、sonarqube.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: sonarqube-data
  namespace: kube-devops
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: "manager-nfs-storage"
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sonarqube
  namespace: kube-devops
  labels:
    app: sonarqube
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sonarqube
  template:
    metadata:
      labels:
        app: sonarqube
    spec:
      initContainers:
      - name: init-sysctl
        image: busybox:1.28.4
        command: ["sysctl", "-w", "vm.max_map_count=262144"]
        securityContext:
          privileged: true
      containers:
      - name: sonarqube
        image: sonarqube:9.9-community
        ports:
        - containerPort: 9000
        env:
        - name: SONARQUBE_JDBC_USERNAME
          value: "sonarUser"
        - name: SONARQUBE_JDBC_PASSWORD
          value: "123456"
        - name: SONARQUBE_JDBC_URL
          value: "jdbc:postgresql://postgres-sonar:5432/sonarDB"
        livenessProbe:
          httpGet:
            path: /sessions/new
            port: 9000
          initialDelaySeconds: 60
          periodSeconds: 30
        readinessProbe:
          httpGet:
            path: /sessions/new
            port: 9000
          initialDelaySeconds: 60
          periodSeconds: 30
          failureThreshold: 6
        volumeMounts:
        - mountPath: /opt/sonarqube/conf
          name: data
        - mountPath: /opt/sonarqube/data
          name: data
        - mountPath: /opt/sonarqube/extensions
          name: data
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: sonarqube-data 
---
apiVersion: v1
kind: Service
metadata:
  name: sonarqube
  namespace: kube-devops
  labels:
    app: sonarqube
spec:
  type: NodePort
  ports:
  - name: sonarqube
    port: 9000
    targetPort: 9000
    protocol: TCP
  selector:
    app: sonarqube

 3、安装

#创建资源
kubectl create -f pgsql.yaml -f sonarqube.yaml

#查看资源
kubectl get po,svc -n kube-devops -o wide

 

 访问该端口下的服务,默认账号密码admin/admin

 

四、安装Jenkins

1、构建带有maven和sonarqube的镜像

Dockerfile

FROM jenkins/jenkins:jdk17
ADD ./apache-maven-3.9.9-bin.tar.gz /usr/local/
ADD ./sonar-scanner-cli-4.8.0.2856-linux.zip /usr/local/

USER root

WORKDIR /usr/local/
RUN unzip sonar-scanner-cli-4.8.0.2856-linux.zip
RUN mv sonar-scanner-4.8.0.2856-linux sonar-scanner-cli
RUN ln -s /usr/local/sonar-scanner-cli/bin/sonar-scanner /usr/bin/sonar-scanner

ENV MAVEN_HOME=/usr/local/apache-maven-3.9.9
ENV PATH=$JAVA_HOME/bin:$MAVEN_HOME/bin:$PATH

RUN echo "jenkins ALL=NOPASSWD: ALL" >> /etc/sudoers
USER jenkins
#构建镜像
docker build -t 192.168.139.184:8899/wsnail-harbor/jenkins-maven:jdk-17 .

#登录docker私服
docker login -uadmin 192.168.139.184:8899

#推送到仓库
docker push 192.168.139.184:8899/wsnail-harbor/jenkins-maven:jdk-17

 注意:1、该操作和docker私服在同一台服务器上

            2、请确认、etc/docker/damon.json文件配置了"insecure-registries": ["http://192.168.139.184:8899"] 

 

2、安装jenkins

2.1、创建Harbor secret


kubectl create secret docker-registry harbor-secret --docker-server=192.168.139.184:8899 --docker-username=admin --docker-password=Xiaojie12345 -n kube-devops

2.2、 jenkins-configmap.yaml

apiVersion: v1 
kind: ConfigMap 
metadata: 
  name: mvn-settings
  namespace: kube-devops
  labels: 
    app: jenkins-server
data: 
  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">
        <localRepository>/var/jenkins_home/repository</localRepository>
         <servers>
        <server>
            <!--此处id需要对应项目中pom.xml文件中的<distributionManagement> 标签下的id-->
            <id>release</id>
            <username>admin</username>
            <password>123456</password>
        </server>
        <server>
            <id>snapshots</id>
            <username>admin</username>
            <password>123456</password>
        </server>
    </servers>

        <mirrors>
                <mirror>
                     <id>releases</id>
                     <name>nexus maven</name>
                     <mirrorOf>*</mirrorOf>
                     <url>http://192.168.139.184:8081/repository/maven-public/</url>
                </mirror>
                <mirror>
                     <id>aliMaven</id>
                     <name>aliyun maven</name>	  	  
                     <url>	https://maven.aliyun.com/repository/public</url>
                     <mirrorOf>central</mirrorOf>
                </mirror>
        </mirrors>

        <pluginGroups>
                <pluginGroup>org.sonarsource.scanner.maven</pluginGroup>
        </pluginGroups>
        <profiles>
                <profile>
                        <id>releases</id>
                        <activation>
                                <activeByDefault>true</activeByDefault>
                                <jdk>1.8</jdk>
                        </activation>
                        <properties>
                                <sonar.host.url>http://sonarqube:9000</sonar.host.url>
                        </properties>

                        <repositories>
                                <repository>
                                        <id>repository</id>
                                        <name>Nexus Repository</name>
                                        <url>http://192.168.139.184:8081/repository/snail-group/</url>   
                                        <releases>
                                                <enable>true</enable>
                                        </releases>
                                        <snapshots>
                                                <enable>true</enable>
                                        </snapshots>
                                </repository>
                        </repositories>
                </profile>
        </profiles>
    </settings>

2.3、jenkins-pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jenkins-pvc
  namespace: kube-devops
spec:
  storageClassName: manager-nfs-storage
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi

2.4、jenkins-serviceAccount.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins-admin
  namespace: kube-devops
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: jenkins-admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: jenkins-admin
  namespace: kube-devops

2.5、jenkins-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins
  namespace: kube-devops
spec:
  replicas: 1
  selector:
    matchLabels:
      app: jenkins-server
  template:
    metadata:
      labels:
        app: jenkins-server
    spec:
      serviceAccountName: jenkins-admin
      #Default: 继承节点的DNS配置;ClusterFirst: 使用coredns作为DNS配置;
      #ClusterFirstWithHostNet:当Pod.spec.hostNetwork=true时,Pod的DNS策略被强制转换为Default,即继承节点的DNS配置;
      #  若Pod要使用coredns作为DNS配置,则需配置pod.spec.dnsPolicy=ClusterFirstWithHostNet;
      #   None: 没有DNS配置;
      dnsPolicy: Default  #解决pod内没有DNS解析不到插件地址
      imagePullSecrets:
        - name: harbor-secret # harbor 访问 secret
      containers:
        - name: jenkins
          image: 192.168.139.184:8899/wsnail-harbor/jenkins-maven:jdk-17   #这里是自己镜像的地址
          imagePullPolicy: IfNotPresent
          securityContext:
            privileged: true
            runAsUser: 0 # 使用 root 用户运行容器
          resources:
            limits:
              memory: "2Gi"
              cpu: "1000m"
            requests:
              memory: "500Mi"
              cpu: "500m"
          ports:
            - name: httpport
              containerPort: 8080
            - name: jnlpport
              containerPort: 50000
          livenessProbe:
            httpGet:
              path: "/login"
              port: 8080
            initialDelaySeconds: 90
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 5
          readinessProbe:
            httpGet:
              path: "/login"
              port: 8080
            initialDelaySeconds: 60
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 3
          volumeMounts:
            - name: jenkins-data
              mountPath: /var/jenkins_home
            - name: docker
              mountPath: /run/docker.sock
            - name: docker-home
              mountPath: /usr/bin/docker
            - name: mvn-setting
              mountPath: /usr/local/apache-maven-3.9.9/conf/settings.xml
              subPath: settings.xml
            - name: daemon
              mountPath: /etc/docker/daemon.json
              subPath: daemon.json
            - name: kubectl
              mountPath: /usr/bin/kubectl
      volumes:
        - name: kubectl
          hostPath:
            path: /usr/bin/kubectl
        - name: jenkins-data
          persistentVolumeClaim:
              claimName: jenkins-pvc
        - name: docker
          hostPath:
            path: /run/docker.sock # 将主机的 docker 映射到容器中
        - name: docker-home
          hostPath:
            path: /usr/bin/docker
        - name: mvn-setting
          configMap:
            name: mvn-settings
            items:
            - key: settings.xml
              path: settings.xml
        - name: daemon
          hostPath: 
            path: /etc/docker/

2.6、jenkins-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: jenkins-service
  namespace: kube-devops
  annotations:
      prometheus.io/scrape: 'true'
      prometheus.io/path:   /
      prometheus.io/port:   '8080'
spec:
  selector:
    app: jenkins-server
  type: NodePort
  ports:
    - port: 8080
      targetPort: 8080

2.7、创建资源

#上面的配置文件均在manifests文件下
kubectl apply -f manifests/

#查看资源
kubectl get po,svc -n kube-devops

 3、配置

3.1 、获取初始密码

 kubectl logs jenkins-598b49d974-glv5x -n kube-devops

 3.2、安装插件

3.2.1、Build Authorization Token Root
3.2.2、Gitlab
3.2.3、SonarQube Scanner
3.2.4、Node and Label parameter
3.2.5、Kubernetes
3.2.6、Config File Provider
3.2.7、Git Parameter

3.3、插件配置

3.3.1、SonarQube Scanner配置

 注意:如果不是k8s部署可以使用外网访问,ip:port

在SonarQube创建token

在jenkins中添加sonarqube的token

3.3.2、kubernetes配置

 

 

3.3.3、创建gitlab凭证

五、构建项目

1、创建gitlab的secret

后面构建项目时候需要用到

#用户名
echo root > ./username

#密码
echo xiaojie123456 > password

#创建secret
kubectl create secret generic git-user-pwd --from-file=./username --from-file=./password -n kube-devops

#查看
kubectl get  secret -n kube-devops

2、配置jenkins任务

2.1、创建流水线Job

 2.2、配置流水线

2.3、配置gitlab的Webhooks

2.4、测试构建

 2.5、测试

3、构建SpringBoot项目 

3.1、配置项目流水线

 3.2、创建镜像私服全局凭证

 3.3、创建kubeconfig文件

cat ~/.kube/config

将文件内容复制

 3.4、创建sonarqube的webhook

3.5、 cicd-demo.yaml配置文件

---
#开发环境的deploy
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: k8s-demo
    component: wssnail-devops
    tier: backend
  name: k8s-demo
  namespace: ks-k8s-demo
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  selector:
    matchLabels:
      app: k8s-demo
      component: wssnail-devops
      tier: backend
  strategy:
    rollingUpdate:
      maxSurge: 100%
      maxUnavailable: 100%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: k8s-demo
        component: wssnail-devops
        tier: backend
    spec:
      imagePullSecrets:
        - name: harbor-secret #该secret必须和该项目在同一个namespace下
      containers:
        - name: k8s-demo
          image: REGISTRY/DOCKERHUB_NAMESPACE/APP_NAME:SNAPSHOT-BUILD_NUMBER   #该内容会在构建镜像时自动替换为实际内容
          readinessProbe:
            httpGet:
              path: /index
              port: 8080
            timeoutSeconds: 10
            failureThreshold: 30
            periodSeconds: 5
          imagePullPolicy: Always
          ports:
            - containerPort: 8080
              protocol: TCP
          resources:
            limits:
              cpu: 300m
              memory: 600Mi
            requests:
              cpu: 100m
              memory: 100Mi
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: k8s-demo
    component: wssnail-devops
  name: k8s-demo
  namespace: ks-k8s-demo
spec:
  ports:
    - name: http
      port: 8080
      protocol: TCP
      targetPort: 8080
  selector:
    app: k8s-demo
    component: wssnail-devops
    tier: backend
  sessionAffinity: None
  type: NodePort

3.6、cicd-demo-dev.yaml

---
#开发环境的deploy
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: k8s-demo
    component: wssnail-devops
    tier: backend
  name: k8s-demo
  namespace: ks-k8s-demo
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  selector:
    matchLabels:
      app: k8s-demo
      component: wssnail-devops
      tier: backend
  strategy:
    rollingUpdate:
      maxSurge: 100%
      maxUnavailable: 100%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: k8s-demo
        component: wssnail-devops
        tier: backend
    spec:
      imagePullSecrets:
        - name: harbor-secret #该secret必须和该项目在同一个namespace下
      containers:
        - name: k8s-demo
          image: REGISTRY/DOCKERHUB_NAMESPACE/APP_NAME:SNAPSHOT-BUILD_NUMBER   #该内容会在构建镜像时自动替换为实际内容
          readinessProbe:
            httpGet:
              path: /index
              port: 8080
            timeoutSeconds: 10
            failureThreshold: 30
            periodSeconds: 5
          imagePullPolicy: Always
          ports:
            - containerPort: 8080
              protocol: TCP
          resources:
            limits:
              cpu: 300m
              memory: 600Mi
            requests:
              cpu: 100m
              memory: 100Mi
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: k8s-demo
    component: wssnail-devops
  name: k8s-demo
  namespace: ks-k8s-demo
spec:
  ports:
    - name: http
      port: 8080
      protocol: TCP
      targetPort: 8080
  selector:
    app: k8s-demo
    component: wssnail-devops
    tier: backend
  sessionAffinity: None
  type: NodePort

 3.7、Dockerfile

## 基础镜像
FROM openjdk:17-slim

## 作者
LABEL org.opencontainers.image.authors="wssnail"

## 定义参数

## 创建并进入工作目录
RUN mkdir -p /wssnail
WORKDIR /wssnail

## maven 插件构建时得到 buildArgs 种的值
COPY target/*.jar app.jar

## 设置 TZ 时区
## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖
ENV TZ=Asia/Shanghai JAVA_OPTS="-Xms256m -Xmx256m"

## 暴露端口
EXPOSE 8080

## 容器启动命令
## CMD 第一个参数之后的命令可以在运行时被替换
CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar app.jar

3.8、Jenkinsfile

pipeline {

  agent {
    node {
      label 'maven'  // 这里配置的标签和jenkins中配置节点添加的标签一致
    }
  }

  environment {
    REGISTRY = '192.168.139.184:8899'   //harbor地址
    DOCKER_CREDENTIAL_ID = 'harbor-user-pwd' //harbor凭证,对应jenkins创建凭证的id
    GIT_REPO_URL = '192.168.139.184:9000'    //gitlab地址
    GIT_CREDENTIAL_ID = 'git-user-pwd'   //gitlab凭证,对应jenkins创建凭证的id
    KUBECONFIG_CREDENTIAL_ID = '30629742-ddae-4c80-a3ad-5807ffc6ff5a'  //对应jenkins创建kubeconfig文件时的id
    DOCKERHUB_NAMESPACE = 'wsnail-harbor' //镜像私服的命名空间
    GITHUB_ACCOUNT = 'root'  //git账号
    APP_NAME = 'demo-k8s'  //应用名称
    SONAR_SERVER_URL='http://192.168.139.208:32061'  //sonarqube地址
    SONAR_CREDENTIAL_ID='sonarqube-token'  //jenkins创建的凭证
  }

  //拉取代码
  stages {

    stage('clone code') {
      steps {
        //配置代码仓库地址 ,credentialsId和jenkins创建的凭证的id保持一致
          sh 'echo  start pull code  start'
          git(url: 'http://192.168.139.184:9000/gitlab-instance-e9e80190/demo-k8s.git', credentialsId: 'git-user-pwd', branch: 'master', changelog: true, poll: false)
          sh 'echo  start pull code end'
        }
    }

    //单元测试
    stage('unit test') {
      steps {
          sh 'mvn clean test'
      }
    }
    //代码质量分析,如果jenkins配置的service连接不上,使用外网地址访问
    stage('sonarqube analysis') {
      agent none
      //withSonarQubeEnv()的值和jenkins中配置的sonarqube的名字保持一致
      steps {
        withCredentials([string(credentialsId : 'sonarqube-token' ,variable : 'SONAR_TOKEN' ,)]) {
          withSonarQubeEnv('sonarqube') {
              sh '''mvn sonar:sonar -Dsonar.projectKey=$APP_NAME
              echo "mvn sonar:sonar -Dsonar.projectKey=$APP_NAME"'''
          }

            //代码质量扫描等待时间
          timeout(unit: 'MINUTES', activity: true, time: 10) {
            waitForQualityGate 'true'
          }
        }
      }
    }

    //打包构建镜像
    stage('build & push') {
      steps {
          sh 'mvn clean package -DskipTests'
          sh 'docker build -f Dockerfile -t $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:SNAPSHOT-$BUILD_NUMBER .'
          withCredentials([usernamePassword(credentialsId : 'harbor-user-pwd' ,passwordVariable : 'DOCKER_PASSWORD' ,usernameVariable : 'DOCKER_USERNAME' ,)]) {
            sh '''echo "$DOCKER_PASSWORD" | docker login $REGISTRY -u "$DOCKER_USERNAME" --password-stdin
            docker push $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:SNAPSHOT-$BUILD_NUMBER'''
          }
      }
    }

    stage('push latest') {
      //是master 分支时,构建镜像的tag为latest保证上线的代码是最新的
      when {
        branch 'master'
      }
      steps {
          sh 'docker tag $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:SNAPSHOT-$BUILD_NUMBER $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:latest'
          sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:latest'
      }
    }

    stage('deploy to dev') {
    //开发分支时部署到开发分支,这里分支灵活配置,注意镜像地址要与主分支分开
      steps {
          input(id: 'deploy-to-dev', message: 'deploy to dev?')
            sh '''sed -i\'\' "s#REGISTRY#$REGISTRY#" deploy/cicd-demo-dev.yaml
            sed -i\'\' "s#DOCKERHUB_NAMESPACE#$DOCKERHUB_NAMESPACE#" deploy/cicd-demo-dev.yaml
            sed -i\'\' "s#APP_NAME#$APP_NAME#" deploy/cicd-demo-dev.yaml
            sed -i\'\' "s#BUILD_NUMBER#$BUILD_NUMBER#" deploy/cicd-demo-dev.yaml
            kubectl apply -f deploy/cicd-demo-dev.yaml'''

      }
    }

    stage('push with tag') {
    //为gitlab打tag
      agent none
      when {
        expression {
        //当匹配tag 为v开头的分支时
          params.TAG_NAME =~ /v.*/
        }

      }
      steps {
        input(message: 'release image with tag?', submitter: '')
        withCredentials([usernamePassword(credentialsId : 'git-user-pwd' ,passwordVariable : 'GIT_PASSWORD' ,usernameVariable : 'GIT_USERNAME' ,)]) {
          sh 'git config --global user.email "whisper_snail@163.com" '
          sh 'git config --global user.name "wssnail" '
          sh 'git tag -a $TAG_NAME -m "$TAG_NAME" '
          sh 'git push http://$GIT_USERNAME:$GIT_PASSWORD@$GIT_REPO_URL/gitlab-instance-e9e80190/demo-k8s.git --tags --ipv4'
        }
          sh 'docker tag $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:SNAPSHOT-$BUILD_NUMBER $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:$TAG_NAME'
          sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:$TAG_NAME'
      }
    }

//是否部署到生产环境
    stage('deploy to production') {
      agent none
      when {
        expression {
          params.TAG_NAME =~ /v.*/
        }

      }
      steps {
        input(message: 'deploy to production?', submitter: '')
          sh '''sed -i\'\' "s#REGISTRY#$REGISTRY#" deploy/cicd-demo.yaml
          sed -i\'\' "s#DOCKERHUB_NAMESPACE#$DOCKERHUB_NAMESPACE#" deploy/cicd-demo.yaml
          sed -i\'\' "s#APP_NAME#$APP_NAME#" deploy/cicd-demo.yaml
          sed -i\'\' "s#TAG_NAME#$TAG_NAME#" deploy/cicd-demo.yaml
          kubectl apply -f deploy/cicd-demo.yaml'''
      }
    }
  }

//参数选择
  parameters {
    string(name: 'BRANCH_NAME', defaultValue: 'master', description: '请选择要发布的分支')
    choice(name: 'NAMESPACE',choices:['dev','test','master'],description: '命名空间')
    string(name: 'TAG_NAME', defaultValue: 'snapshot', description: '标签名称,必须以 v 开头,例如:v1、v1.0.0')
  }

}

3.9、完整代码见附录 

3.10、部署成功效果

 

 

 

六、附录

1、Gitlab安装包


链接: https://pan.baidu.com/s/1vUCRmxNzW0jO9mdZ79uYUQ?pwd=37s3 提取码: 37s3 

2、Harbor安装包


链接: https://pan.baidu.com/s/12bZcCA4C3RM89wf5K9_AqQ?pwd=4t49 提取码: 4t49 

3、带有Maven的Jenkins镜像


链接: https://pan.baidu.com/s/19luWsomE7Mktzp9UyAQ5VA?pwd=n7hp 提取码: n7hp 

4、源码地址

熟透的蜗牛/demo-k8s

5、参考

http://www.bilibili.com/video/BV1MT411x7GH/


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/902436.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

UE5之5.4 第一人称示例代码阅读1 FirstPersonProjectile

既然如此&#xff0c;这几个文件都看看 先看看FirstPersonProjectile头文件 定义了几个函数 然后是两个component 这个projectilemovement应该是控制物理运动的 看看CPP文件 sphere那个就创建了一个subobject&#xff0c;初始化了一下&#xff0c;然后这里 CollisionComp-&g…

Maven 项目构建打包,如何引入本地 Jar 包?

上一篇讲到 Maven 离线仓库的使用&#xff0c;反响不错很多人收藏&#xff0c;这一篇还是继续聊 Maven 。假如你发现某开源项目有个 bug 影响到自己的系统&#xff0c;但官方还没修复&#xff0c;自己定位到了本地修改打了包先应急用&#xff0c;那么如何在其他项目上使用该包&…

985研一,转嵌入式好还是后端开发好?

有个老铁问&#xff0c;985研一&#xff0c;转嵌入式好还是后端开发好&#xff1f; 我认为&#xff0c;这学历&#xff0c;两个随便挑&#xff0c;我说的&#xff0c;从趋势来看&#xff0c;更建议嵌入式&#xff0c;走供应链上游&#xff0c;芯片原厂、新能源车企、军工或者搞…

Python画图|极坐标下的柱状图输出

【1】引言 前序学习了极坐标下的散点图输出&#xff0c;可通过下述链接直达&#xff1a; 西猫雷婶-CSDN博客 受此启发&#xff0c;我们继续自主探索极坐标下的柱状图输出。 【2】代码探索 其实柱状图和散点图画图的主要区别&#xff0c;可以理解为调用函数不同。 柱状图调…

Golang | Leetcode Golang题解之第515题在每个树行中找最大值

题目&#xff1a; 题解&#xff1a; func largestValues(root *TreeNode) (ans []int) {if root nil {return}q : []*TreeNode{root}for len(q) > 0 {maxVal : math.MinInt32tmp : qq nilfor _, node : range tmp {maxVal max(maxVal, node.Val)if node.Left ! nil {q …

stm32单片机个人学习笔记12(DMA直接存储器存取)

前言 本篇文章属于stm32单片机&#xff08;以下简称单片机&#xff09;的学习笔记&#xff0c;来源于B站教学视频。下面是这位up主的视频链接。本文为个人学习笔记&#xff0c;只能做参考&#xff0c;细节方面建议观看视频&#xff0c;肯定受益匪浅。 STM32入门教程-2023版 细…

若依学习 后端传过来的数据在控制台打印为空

导言: 在做若依二次开发时遇到个没见过的bug&#xff0c;用了一些时间排&#xff0c;发现有自己没学过的东西。所以记录一下。后端用的是c#的asp.net core 问题描述&#xff1a; 后端穿过来的有数据的参数(数组)roleIds在控制台打印为空 后端字段定义: 后端数据&#xff1a; 前…

【热门主题】000010 深入 Vue.js 组件开发

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 【热…

初见Linux:权限篇

一.权限的定义&#xff1a; 什么是权限?所谓权限在现实中就是权力限制&#xff0c;是对于人&#xff0c;不同人所扮演的角色有着不同的权限。那么在Linux中也存在权限。权限角色事物属性。那么对于一件事情能否去执行以及完成都需要权限。 二.Linux中的用户 2.1&#xff1a;r…

【SpringMVC】web服务器,访问失败的问题,SpringMVC,建立连接,请求

【web服务器】 web服务器可以对http协议进行封装&#xff0c;程序员不需要直接对http协议进行操作&#xff08;不需要去写复杂的网络编程代码&#xff09;&#xff0c;让web开发更加便捷&#xff0c;所以它也有「WWW服务器」的称呼 常见的web服务器:Tomcat&#xff0c;Jboss&…

华为配置 之 STP

目录 简介&#xff1a; STP&#xff1a; RSTP: 如何改变根网桥&#xff1a; &#xff08;1&#xff09;改变优先级&#xff1a; &#xff08;2&#xff09;改变root: 各端口的状态&#xff1a; 总结&#xff1a; 简介&#xff1a; STP&#xff08;Spanning Tree Protoco…

深度学习:Matplotlib篇

一、简介 1.1 什么是 Matplotlib&#xff1f; Matplotlib 是一个广泛使用的 2D 绘图库&#xff0c;它可以用来在 Python 中创建各种静态、动态和交互式的图表。无论是科学计算、数据可视化&#xff0c;还是深度学习模型的训练与评估&#xff0c;Matplotlib 都能提供强大的图形…

虚拟现实新纪元:VR/AR技术将如何改变娱乐与教育

内容概要 在当今科技飞速发展的时代&#xff0c;虚拟现实&#xff08;VR&#xff09;和增强现实&#xff08;AR&#xff09;技术不仅让我们的娱乐体验如虎添翼&#xff0c;更为教育变革注入了新活力。这些技术的飞跃进展&#xff0c;将原本平淡无奇的场景转变为令人沉醉的沉浸…

深入浅出 C++ STL:解锁高效编程的秘密武器

引言 C 标准模板库&#xff08;STL&#xff09;是现代 C 的核心部分之一&#xff0c;为开发者提供了丰富的预定义数据结构和算法&#xff0c;极大地提升了编程效率和代码的可读性。理解和掌握 STL 对于 C 开发者来说至关重要。以下是对 STL 的详细介绍&#xff0c;涵盖其基础知…

面向对象编程中类与类之间的关系(一)

目录 1.引言 2."有一个"关系 3."是一个"关系(继承) 4.“有一个”与“是一个”的区别 5.not-a关系 6.层次结构 7.多重继承 8.混入类 1.引言 作为程序员&#xff0c;必然会遇到这样的情况&#xff1a;不同的类具有共同的特征&#xff0c;至少看起来彼…

JavaWeb——Web入门(1/9)-Spring Boot Web介绍(Spring家族,Spring Boot)

目录 Spring家族 Spring Boot 在我们了解完了 Maven 这款项目构建工具的基本使用之后&#xff0c;接下来我们正式的进入到 Web 后端开发的学习。 第一篇章要了解的是 Spring Boot Web 的入门。 在正式开始之前&#xff0c;我们先需要介绍一下什么是 Spring 以及什么是 Spri…

H3C Hybrid 实验

实验拓扑 图 1-1 注&#xff1a;如无特别说明&#xff0c;描述中的 R1 或 SW1 对应拓扑中设备名称末尾数字为 1 的设备&#xff0c;R2 或 SW2 对应拓扑中设备名称末尾数字为 2 的设备&#xff0c;以此类推&#xff1b;另外&#xff0c;同一网段中&#xff0c;IP 地址的主机位为…

【NOI】C++函数入门二(自定义函数)

文章目录 前言一、概念1.导入1.1 首先什么是函数呢&#xff1f; 2.函数分类3.为什么要定义函数呢&#xff1f;4.函数结构5.函数使用注意事项 二、例题讲解问题&#xff1a;1137 - 纯粹素数问题&#xff1a;1258 - 求一个三位数问题&#xff1a;1140 - 亲密数对问题&#xff1a;…

Flutter仿京东商城APP实战 用户中心基础布局

用户中心界面 pages/tabs/user/user.dart import package:flutter/material.dart; import package:jdshop/utils/zdp_screen.dart; import package:provider/provider.dart;import ../../../store/counter_store.dart;class UserPage extends StatefulWidget {const UserPage…

如何在Node.js中执行解压缩文件操作

一、解压文件 1.安装依赖&#xff1a; 安装adm-zip依赖包&#xff1a;npm install adm-zip --save 安装iconv-lite依赖包&#xff1a;npm install iconv-lite --save 解压前的file文件夹结构&#xff1a; update-1.0.2.zip压缩包内容&#xff1a; 2.在depresssFile.js文件&…