Jenkins Pipeline 实战:Vue 应用交付

来自AI助手的总结
介绍了Gitlab上传代码、镜像拉取与Jenkins流水线部署流程。
Jenkins Pipeline 实战:Vue 应用交付

一、Gitlab准备工作

准备上传代码条件

1、配置名字和邮箱


$ git config --global user.name "zq"

$ git config --global user.email "123456@qq.com"

验证


# 查看配置的名字

$ git config user.name

# 查看配置的邮箱

$ git config user.email

2、生成SSH密钥


$ ssh-keygen.exe -t rsa -C "123456@qq.com"

查看公钥


[root@master01 springdemo]# cat /root/.ssh/id_rsa.pub

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsk6Lc3iQb9SU0ghxOTZNFZ/p5cFghwzHSBCyOsJS+jOz6ygvAAwMI3iX/Sg6cLbg7IYKT+lPo0/+9klEA71DCwG1GUjTQ5EFz+CdtWYc/ge1VEBRzjADHt/JWDoqOOETBtPdJbS1Qw7zyhCfbpsErcNsvrkTRU/AFBffUr0RBKIr19/IUmR7xktL7HbWsDZ76+rYHvKeAvS3JTp789FiSwKZHwe5yo91ynygxPC1N7nLmfJIs18mtHDGQ/Cpgnt0lr7gEgv17bAL2WxR7+C52/GbWfw8xS62/O9jtTJAutZlYiJCoGSgs1zsRi03MzuPHk+ooUXbzWVR/ALWY3FTp 123456@qq.com

上传公钥到gitlab仓库

image-20250330202829899

image-20250330202734434

上传代码到gitlab上

1、在浏览器上输入http://gitlab.zhang-qing.com/,默认的管理员用户root,密码S6n5Y7b81wRrJnKv

2、创建名为demoteam的群组

依次点击【群组】-【新建群组】

image-20250508141513476

点击【创建群组】

image-20250508141621440

定义群组名称为demoteam后,点击【创建群组】

image-20250508141742286

3、创建名为Vue-Kubernetes的项目

点击【创建项目】

image-20231224221118115

点击【创建空白项目】

image-20231224221302968

填写仓库名称:Vue-Kubernetes,设置可见性级别为私有,点击【新建项目】

image-20250508152800119

上传代码到本地gitlab上

[root@master01 ~]# cd /root/5/
[root@master01 5]# cp -r vue3_web_element-demo-plus/ vue3_web_element-demo-plus-jenkins
[root@master01 ~]# cd /root/5/vue3_web_element-demo-plus-jenkins
#修改控制器文件
[root@master01 vue3_web_element-demo-plus-jenkins]# vim deployment.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: $APP_NAME
  namespace: $NAMESPACE
data:
  default.conf: |-
    server {
      listen       80;
      server_name  vue-test.zhang-qing.com; #生产环境域名
      location /img {             #访问img路径下资源时,重定向到百度页面
        return 301 https://www.baidu.com;
      }
      location / {
        root  /opt/vue/dist;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
        add_header Access-Control-Allow-Origin *;
      }
    }
---
apiVersion: v1
kind: Service
metadata:
  name: $APP_NAME
  namespace: $NAMESPACE
spec:
  type: ClusterIP
  selector:
    app: $APP_NAME
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: $APP_NAME
  namespace: $NAMESPACE
spec:
  replicas: $APP_REPLICAS
  selector:
    matchLabels:
      app: $APP_NAME
  template:
    metadata:
      labels:
        app: $APP_NAME
    spec:
      containers:
        - name: $APP_NAME
          image: $IMAGE_NAME
          resources:
            limits:
              memory: $PODMEMORYGi
              cpu: $PODCPUm
            requests:
              memory: $PODMEMORYGi
              cpu: $PODCPUm
          ports:
            - containerPort: 80
              name: web
          livenessProbe:
            httpGet:
              port: web
              path: /
          readinessProbe:
            tcpSocket:
              port: web
          volumeMounts:
            - mountPath: /etc/nginx/conf.d/default.conf
              subPath: default.conf
              name: nginx-config
            - mountPath: /media
              name: media
      volumes:
        - name: nginx-config  # 使用生产模式nginx配置文件
          configMap:
            name: $APP_NAME
        - name: media          # 挂载空目录,用于存放远端资源
          emptyDir: {}
#提交代码文件内容
[root@master01 vue3_web_element-demo-plus-jenkins]# git init
[root@master01 vue3_web_element-demo-plus-jenkins]# git add .
[root@master01 vue3_web_element-demo-plus-jenkins]# git commit -m 'VueDemo'
[root@master01 vue3_web_element-demo-plus-jenkins]# git remote add origin http://gitlab.zhang-qing.com/demoteam/vue-kubernetes.git
[root@master01 vue3_web_element-demo-plus-jenkins]# git branch -M main
[root@master01 vue3_web_element-demo-plus-jenkins]# git push -uf origin main
Username for 'http://gitlab.zhang-qing.com': root
Password for 'http://root@gitlab.zhang-qing.com': S6n5Y7b81wRrJnKv

可能遇到的问题:


#执行完git push -uf origin main提示失败

error: failed to push some refs to 'http://gitlab.zhang-qing.com/demoteam/vue-kubernetes.git'

#解决方法

依次点击【设置】-【仓库】-【受保护分支】,取消保护分支即可

如果远程仓库存在其他内容,参考下面删除


#查看

[root@master01 springdemo]# git remote -v

#验证

[root@master01 springdemo]# git remote remove origin

二、镜像拉取

通过docker login登录,本地生成凭证配置文件config.json

查看生成的认证文件(一般路径为/root/.docker/config.json)


#提前手动登录harbor仓库,自动生成/root/.docker/config.json文件

[root@master01 ~]# docker login -uadmin harbor.zhang-qing.com

password: Harbor12345

#查看

[root@master01 ~]# ls -l /root/.docker/config.json

-rw------- 1 root root 89 May  7 20:36 /root/.docker/config.json

基于该凭证文件创建K8S集群中拉取镜像的secret:


#创建secret

[root@master01 ~]# k create ns demo

[root@master01 ~]# kubectl create secret generic harborsecret -n demo \

--from-file=.dockerconfigjson=/root/.docker/config.json \

--type=kubernetes.io/dockerconfigjson

#验证查看

[root@master01 ~]# kg secret -n demo | grep harborsecret

harborsecret          kubernetes.io/dockerconfigjson        1      49s

三、完整pipeline

完整pipeline:

1、定义名为Vue-Demo-Test的Pipeline


// 定义git相关数据

def git_address = "http://gitlab.zhang-qing.com/demoteam/vue-kubernetes.git"

def git_auth = "Gitlab-username"

// 构建版本的名称

def tag = "latest"

// Harbor私服地址

def harbor_url = "harbor.zhang-qing.com"

// Harbor的项目名称

def harbor_project_name = "demo"

// Harbor的凭证

def harbor_auth = "Harbor-username"

// 启动时间

def start = new Date().format('yyyy-MM-dd HH:mm:ss')

// 创建一个Pod的模板,label为jenkins-slave

podTemplate(

    label: 'jenkins-slave-vue',

    cloud: 'study-kubernetes',

    containers: [

         containerTemplate(

            name: 'jnlp',

            image: "harbor.zhang-qing.com/library/inbound-agent:3299.v0d0d06908537-1",

            ttyEnabled: true

        ),

        containerTemplate(

            name: 'docker',

            image: "harbor.zhang-qing.com/library/docker:stable",

            ttyEnabled: true,

            command: 'cat'

        ),

    ],

    volumes: [

        hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock')

    ]

) {

    node("jenkins-slave-vue") {

        // 第一步

        stage('Pull') {

            checkout([

                $class: 'GitSCM',

                branches: [[name: "${branch}"]],

                extensions: [],

                userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_address}"]]

            ])

        }

        stage('BuildDescription') {

            // 自定义设置构建历史显示的名称和描述信息

            // 不同的部署方式设置构建历史显示的名称和描述信息方式不一样,根据自己的部署方式自行百度找到设置方法

            script {

                // 设置buildName

                wrap([$class: 'BuildUser']) {

                    // 修改Description

                    buildDescription "${BUILD_USER} > ${project_name} > ${branch}"

                }

            }

        }

        // 第二步

        stage('Build&Tag&Push&Deploy') {

            // 把选择的项目信息转为数组

            def selectedProjects = "${project_name}".split(',')

            for(int i = 0; i < selectedProjects.size(); i++) {

                // 取出每个项目的名称

                def currentProjectName = selectedProjects[i];

                // 定义镜像名称

                def imageName = "${currentProjectName}:${tag}"

                // 定义newTag

                def newTag = sh(returnStdout: true, script: 'echo `date +"%Y%m%d%H%M"_``git describe --tags --always`').trim()

                // 编译,构建本地镜像

                // sh "sed -i 's#ACTIVEPROFILE#${springProfilesActive}#g' Dockerfile"

                // sh "mvn clean package -Dmaven.test.skip=true"

                container('docker') {

                    // 镜像编译

                    sh "docker build -t ${imageName} ."

                    // 给镜像打标签

                    sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${currentProjectName}:${newTag}"

                    // 登录Harbor,并上传镜像

                    withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {

                        // 登录

                        sh "docker login -u ${username} -p ${password} ${harbor_url}"

                        // 上传镜像

                        sh "docker push ${harbor_url}/${harbor_project_name}/${currentProjectName}:${newTag}"

                    }

                    // 删除本地镜像

                    sh "docker rmi -f ${imageName}"

                    sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${currentProjectName}:${newTag}"

                }

                def deploy_image_name = "${harbor_url}/${harbor_project_name}/${currentProjectName}:${newTag}"

                // 基于控制器的方式部署到K8S

                sh """

                    sed -i 's#\$IMAGE_NAME#${deploy_image_name}#' deployment.yaml

                    sed -i 's#\$APP_NAME#${currentProjectName}#' deployment.yaml

                    sed -i 's#\$APP_REPLICAS#${replicas}#' deployment.yaml

                    sed -i 's#\$NAMESPACE#${namespaces}#' deployment.yaml

                    sed -i 's#\$PODMEMORY#${podsMem}#' deployment.yaml

                    sed -i 's#\$PODCPU#${podsCpu}#' deployment.yaml

                    cat deployment.yaml

                """

                // 部署到K8S

                kubernetesDeploy(kubeconfigId: "kubeconfig", configs: "deployment.yaml")

            }

        }

    }

}

说明:Kubernetes Continuous Deploy这个插件已经被暂停使用,新版Jenkins无法下载该插件,下载链接:https://zqzqbucket.oss-cn-hangzhou.aliyuncs.com/file/kubernetes-cd.hpi

2、定义字符串参数

依次点击【参数化构建过程】-【字符参数】

  • 第一个字符参数:

  • 名称:branch

  • 默认值:main

  • 描述:Git 分支

  • 第二个字符参数:

  • 名称:project_name

  • 默认值:vue

  • 描述:项目名称

  • 第三个字符参数:

  • 名称:replicas

  • 默认值:1

  • 描述:副本数

  • 第四个字符参数:

  • 名称:namespaces

  • 默认值:demo

  • 描述:K8s 命名空间

  • 第五个字符参数:

  • 名称:podsMem

  • 默认值:1

  • 描述:内存限制

  • 第六个字符参数:

  • 名称:podsCpu

  • 默认值:500

  • 描述:CPU 限制

3、填写完成后,点击【应用】-【Save】

4、点击【Build with Parameters】,默认值即可,点击【Build】进行构建即可

5、构建完成后,验证查看


#查看pod和svc

[root@master01 vue3_web_element-demo-plus-jenkins]# kg deploy,svc -n demo

NAME                  READY   UP-TO-DATE   AVAILABLE   AGE

deployment.apps/vue   1/1     1            1           23s

NAME          TYPE        CLUSTER-IP        EXTERNAL-IP   PORT(S)   AGE

service/vue   ClusterIP   192.168.176.131   <none>        80/TCP    24s

6、手动创建一个ingress访问测试

[root@master01 ~]# cd /root/5/vue3_web_element-demo-plus-jenkins
[root@master01 vue3_web_element-demo-plus-jenkins]# cat ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    konghq.com/https-redirect-status-code: "301"
    konghq.com/protocols: http
    konghq.com/regex-priority: "1000"
  name: vue-ing
spec:
  ingressClassName: nginx
  rules:
  - host: vue-test.zhang-qing.com
    http:
      paths:
      - backend:
          service:
            name: vue
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific
[root@master01 springdemo-jenkins]# kaf ingress.yaml -n demo
#测试访问
[root@master01 springdemo-jenkins]# curl vue-test.zhang-qing.com

四、问题汇总

4.1 问题1

问题报错内容


[PodInfo] default/jenkins-slave-vue-tq0bc-84841

    Container [jnlp] waiting [ErrImagePull] rpc error: code = Unknown desc = failed to pull and unpack image "docker.io/jenkins/inbound-agent:3299.v0d0d06908537-1": failed to resolve reference "docker.io/jenkins/inbound-agent:3299.v0d0d06908537-1": failed to do request: Head "https://registry-1.docker.io/v2/jenkins/inbound-agent/manifests/3299.v0d0d06908537-1": dial tcp 31.13.81.4:443: connect: connection refused

问题报错原因

需要启动jnlp容器,但是拉取镜像失败

问题解决

1、拉取镜像并上传到harbor


[root@master01 ~]#docker pull jenkins/inbound-agent:3299.v0d0d06908537-1

[root@master01 ~]#docker tag jenkins/inbound-agent:3299.v0d0d06908537-1 harbor.zhang-qing.com/library/inbound-agent:3299.v0d0d06908537-1

[root@master01 ~]#docker push harbor.zhang-qing.com/library/inbound-agent:3299.v0d0d06908537-1

2、pipline文件添加如下内容

         containerTemplate(
            name: 'jnlp',
            image: "harbor.zhang-qing.com/library/inbound-agent:3299.v0d0d06908537-1",
            ttyEnabled: true
        ),

完整pipline文件内容如下:


// 定义git相关数据

def git_address = "http://gitlab.zhang-qing.com/demoteam/vue-kubernetes.git"

def git_auth = "Gitlab-username"

// 构建版本的名称

def tag = "latest"

// Harbor私服地址

def harbor_url = "harbor.zhang-qing.com"

// Harbor的项目名称

def harbor_project_name = "demo"

// Harbor的凭证

def harbor_auth = "Harbor-username"

// 启动时间

def start = new Date().format('yyyy-MM-dd HH:mm:ss')

// 创建一个Pod的模板,label为jenkins-slave

podTemplate(

    label: 'jenkins-slave-vue',

    cloud: 'study-kubernetes',

    containers: [

         containerTemplate(

            name: 'jnlp',

            image: "harbor.zhang-qing.com/library/inbound-agent:3299.v0d0d06908537-1",

            ttyEnabled: true

        ),

        containerTemplate(

            name: 'docker',

            image: "harbor.zhang-qing.com/library/docker:stable",

            ttyEnabled: true,

            command: 'cat'

        ),

    ],

    volumes: [

        hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock')

    ]

) {

    node("jenkins-slave-vue") {

        // 第一步

        stage('Pull') {

            checkout([

                $class: 'GitSCM',

                branches: [[name: "${branch}"]],

                extensions: [],

                userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_address}"]]

            ])

        }

        stage('BuildDescription') {

            // 自定义设置构建历史显示的名称和描述信息

            // 不同的部署方式设置构建历史显示的名称和描述信息方式不一样,根据自己的部署方式自行百度找到设置方法

            script {

                // 设置buildName

                wrap([$class: 'BuildUser']) {

                    // 修改Description

                    buildDescription "${BUILD_USER} > ${project_name} > ${branch}"

                }

            }

        }

        // 第二步

        stage('Build&Tag&Push&Deploy') {

            // 把选择的项目信息转为数组

            def selectedProjects = "${project_name}".split(',')

            for(int i = 0; i < selectedProjects.size(); i++) {

                // 取出每个项目的名称

                def currentProjectName = selectedProjects[i];

                // 定义镜像名称

                def imageName = "${currentProjectName}:${tag}"

                // 定义newTag

                def newTag = sh(returnStdout: true, script: 'echo `date +"%Y%m%d%H%M"_``git describe --tags --always`').trim()

                // 编译,构建本地镜像

                // sh "sed -i 's#ACTIVEPROFILE#${springProfilesActive}#g' Dockerfile"

                // sh "mvn clean package -Dmaven.test.skip=true"

                container('docker') {

                    // 镜像编译

                    sh "docker build -t ${imageName} ."

                    // 给镜像打标签

                    sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${currentProjectName}:${newTag}"

                    // 登录Harbor,并上传镜像

                    withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {

                        // 登录

                        sh "docker login -u ${username} -p ${password} ${harbor_url}"

                        // 上传镜像

                        sh "docker push ${harbor_url}/${harbor_project_name}/${currentProjectName}:${newTag}"

                    }

                    // 删除本地镜像

                    sh "docker rmi -f ${imageName}"

                    sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${currentProjectName}:${newTag}"

                }

                def deploy_image_name = "${harbor_url}/${harbor_project_name}/${currentProjectName}:${newTag}"

                // 基于控制器的方式部署到K8S

                sh """

                    sed -i 's#\$IMAGE_NAME#${deploy_image_name}#' deployment.yaml

                    sed -i 's#\$APP_NAME#${currentProjectName}#' deployment.yaml

                    sed -i 's#\$APP_REPLICAS#${replicas}#' deployment.yaml

                    sed -i 's#\$NAMESPACE#${namespaces}#' deployment.yaml

                    sed -i 's#\$PODMEMORY#${podsMem}#' deployment.yaml

                    sed -i 's#\$PODCPU#${podsCpu}#' deployment.yaml

                    cat deployment.yaml

                """

                // 部署到K8S

                kubernetesDeploy(kubeconfigId: "kubeconfig", configs: "deployment.yaml")

            }

        }

    }

}

五、环境复原

删除deployment、service、ingress


[root@master01 ~]# cd /root/5/vue3_web_element-demo-plus-jenkins

[root@master01 vue3_web_element-demo-plus-jenkins]# k delete -f ingress.yaml -n demo

[root@master01 springdemo-jenkins]# k delete deploy,svc vue -n demo

© 版权声明
THE END
喜欢就支持一下吧
点赞10 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容