<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Jenkins_Master_Slave_手搓部署指南基于_Ubuntu_22

      原創

            Jenkins Master/Slave 手搓部署指南(基于 Ubuntu 22.04)
      
      # Jenkins Master/Slave 手搓部署指南(基于 Ubuntu 22.04)
      
      > **備注**:本文檔為在 Kubernetes 集群中從零構建 Jenkins CI/CD 系統的完整操作手冊。  
      > - 所有鏡像均基于 `ubuntu:22.04` 自定義構建,不依賴官方 Jenkins 鏡像。  
      > - 使用 **WebSocket 模式連接 Agent**,無需開放 `50000` 端口。  
      > - 數據通過 PVC + PV + hostPath 持久化至指定節點 `/data/jenkins-pv`。  
      > - 通過 Ingress 暴露 Web UI,使用 HTTP 協議(無 TLS)。  
      > - 已修正原文檔中的多處邏輯錯誤與配置問題,并增強安全性建議。
      
      ---
      
      ## ? 最終目標
      
      | 特性 | 實現方式 |
      |------|----------|
      | Jenkins Master Pod 名稱 | `jenkins-0`(hostname) |
      | 基礎鏡像 | `ubuntu:22.04` |
      | 構建方式 | 手動 Dockerfile 構建并推送至私有倉庫 |
      | 數據持久化 | PVC + PV + hostPath → `/data/jenkins-pv` on `k8s-node1` |
      | 外部訪問 | Ingress(HTTP,無 TLS) |
      | Kubernetes Plugin 配置 | 完整配置云環境 |
      | Agent 連接模式 | WebSocket(無需 `50000` 端口) |
      | Agent 生命周期 | 動態創建、構建完成后自動銷毀 |
      | 權限控制 | ServiceAccount + RBAC cluster-admin |
      | 可擴展性 | 支持動態伸縮 Agent Pods |
      
      ---
      
      ## ?? 準備工作(所有節點)
      
      ### 1. 環境信息
      
      | 角色 | 主機名 | IP 地址 |
      |------|--------|---------|
      | K8s Master | k8s-master | 192.168.122.96 |
      | K8s Worker | k8s-node1 | 192.168.122.190 |
      
      > **操作說明**:
      > 在所有節點上更新 `/etc/hosts`,確保主機名解析正確:
      
      ```bash
      echo "192.168.122.96 k8s-master" | sudo tee -a /etc/hosts
      echo "192.168.122.190 k8s-node1"  | sudo tee -a /etc/hosts
      

      ?? 第一步:準備 k8s-node1 節點

      1. 創建 Jenkins 數據目錄

      說明:該路徑將作為 PersistentVolume 的本地存儲路徑。

      # 在 k8s-node1 上執行
      sudo mkdir -p /data/jenkins-pv
      sudo chown -R 1000:1000 /data/jenkins-pv
      

      ?? 注意:Jenkins 默認運行用戶 UID=1000,必須提前設置權限。


      2. 給節點打標簽(用于調度)

      說明:確保 Jenkins Master 固定調度到 k8s-node1

      # 在 master 節點執行
      kubectl label node k8s-node1 jenkins/master=true --overwrite
      

      ?? 第二步:構建 Jenkins Master 鏡像(基于 ubuntu:22.04)

      1. 創建項目目錄

      mkdir -p ~/jenkins-setup/{master,agent,certs}
      cd ~/jenkins-setup/master
      
      目錄結構示例:
      .
      ├── Dockerfile.master
      ├── entrypoint.sh
      ├── jdk-17.0.12.zip
      ├── jdk-17.0.12/
      └── jenkins.war
      

      所需文件

      • jdk-17.0.12.zip:Java 17 壓縮包(解壓后使用)
      • jenkins.war:Jenkins WAR 包(版本建議 2.516.2 或以上)

      2. Dockerfile.master

      # Dockerfile.master
      FROM ubuntu:22.04
      
      LABEL maintainer="devops@example.com"
      
      # 設置變量
      ENV JAVA_HOME=/data/jdk-17.0.12 \
          JENKINS_HOME=/var/jenkins_home \
          JENKINS_VERSION=2.516.2
      
      # 換國內源加速
      RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list && \
          sed -i 's/security.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list
      
      # 創建目錄并復制 JDK
      RUN mkdir -p /data
      COPY jdk-17.0.12 /data/jdk-17.0.12
      
      # 安裝基礎工具
      RUN apt-get update && \
          apt-get install -y wget net-tools curl git libfreetype6 fonts-dejavu-core fontconfig && \
          rm -rf /var/lib/apt/lists/*
      
      # 創建 jenkins 用戶(UID=1000)
      RUN groupadd --gid 1000 jenkins && \
          useradd -m -u 1000 -g jenkins -d /home/jenkins jenkins && \
          mkdir -p /var/jenkins_home && \
          chown -R jenkins:jenkins /var/jenkins_home
      
      # 添加 Java 到 PATH
      ENV PATH="${JAVA_HOME}/bin:${PATH}"
      
      WORKDIR /home/jenkins
      
      COPY jenkins.war /home/jenkins/jenkins.war
      RUN chown jenkins:jenkins jenkins.war
      
      # 使用 root 用戶運行(便于初始化)
      USER root
      
      # 復制啟動腳本
      COPY entrypoint.sh /entrypoint.sh
      RUN chmod +x /entrypoint.sh
      
      EXPOSE 8080
      
      ENTRYPOINT ["/entrypoint.sh"]
      

      說明

      • 使用阿里云鏡像源提升下載速度。
      • 顯式聲明 USER root 是為了在啟動時能修改掛載卷權限。

      3. entrypoint.sh

      #!/bin/bash
      set -e
      
      # ? 正確指向 WAR 文件
      JAR="/home/jenkins/jenkins.war"
      
      # 確保 Jenkins home 目錄權限正確
      chown -R jenkins:jenkins $JENKINS_HOME
      
      # 啟動 Jenkins
      exec java \
        -Djenkins.install.runSetupWizard=false \
        -Djenkins.CLI.disabled=true \
        -jar ${JAR} \
        --httpPort=8080 \
        --webroot=$JENKINS_HOME/war \
        --argumentsRealm.passwd.jenkins=jenkins \
        --argumentsRealm.roles.jenkins=admin
      

      關鍵參數說明

      • runSetupWizard=false:跳過首次設置向導。
      • CLI.disabled=true:禁用 CLI 接口以提高安全性。
      • 內置賬號密碼:jenkins/jenkins

      4. 構建并推送鏡像

      chmod +x entrypoint.sh
      
      docker build -f Dockerfile.master -t swr.cn-east-3.myhuaweicloud.com/bocheng-test/jenkins-master:v1 .
      
      # 推送至私有倉庫
      docker push swr.cn-east-3.myhuaweicloud.com/bocheng-test/jenkins-master:v1
      

      ?? 第三步:構建 Jenkins Agent 鏡像(基于 ubuntu:22.04)

      cd ~/jenkins-setup/agent
      
      目錄結構示例:
      .
      ├── Dockerfile.agent
      ├── agent.jar
      ├── apache-maven-3.8.8/
      ├── jdk-17.0.12/
      └── jenkins-agent.sh
      

      1. Dockerfile.agent

      # Dockerfile.agent
      FROM ubuntu:22.04
      
      LABEL maintainer="devops@example.com"
      
      # 設置環境變量
      ENV AGENT_WORKDIR=/home/jenkins/agent \
          JAVA_HOME=/data/jdk-17.0.12 \
          MAVEN_HOME=/opt/apache-maven-3.8.8 \
          NVM_DIR=/home/jenkins/.nvm \
          USER=jenkins
      
      # 添加 Java 和 Maven 到 PATH
      ENV PATH="${JAVA_HOME}/bin:${MAVEN_HOME}/bin:${PATH}"
      
      # 換源為阿里云加速 apt
      RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list && \
          sed -i 's/security.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list
      
      # 安裝基礎工具
      RUN apt-get update && \
          apt-get install -y curl git vim python3-pip && \
          rm -rf /var/lib/apt/lists/*
      
      # 創建 jenkins 用戶
      RUN groupadd --gid 1000 jenkins && \
          useradd -m -u 1000 -g jenkins -d /home/jenkins jenkins
      
      # 創建 agent 工作目錄
      RUN mkdir -p $AGENT_WORKDIR && \
          chown -R jenkins:jenkins $AGENT_WORKDIR
      
      # 拷貝本地 JDK
      COPY jdk-17.0.12 /data/jdk-17.0.12
      
      # 拷貝本地 Maven
      COPY apache-maven-3.8.8 /opt/apache-maven-3.8.8
      
      # 設置 Maven 權限
      RUN chmod +x /opt/apache-maven-3.8.8/bin/mvn && \
          chown -R jenkins:jenkins /opt/apache-maven-3.8.8
      
      # 安裝 NVM、Node.js v18.20.6 和 pnpm
      RUN su - jenkins <<'EOF'
          export NVM_DIR="$HOME/.nvm"
          mkdir -p "$NVM_DIR"
      
          # 安裝 NVM(使用 Gitee 鏡像)
          curl -fsSL https://gitee.com/cubxxw/nvm/raw/master/install.sh | \
              NVM_DIR='$NVM_DIR' \
              PROFILE=/dev/null \
              bash
      
          # 加載 NVM
          [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
      
          # 設置國內鏡像源
          nvm node_mirror https://npmmirror.com/mirrors/node/
          nvm npm_mirror https://npmmirror.com/mirrors/npm/
      
          # 安裝 Node.js v18.20.6
          nvm install v18.20.6
          nvm use v18.20.6
      
          # 設置 npm 國內源并安裝 pnpm
          npm config set registry https://registry.npmmirror.com
          npm install -g pnpm
      
          # 創建自動加載腳本(用于非登錄 shell)
          mkdir -p "$HOME/.profile.d"
          cat > "$HOME/.profile.d/nvm.sh" <<'INNER'
      export NVM_DIR="$HOME/.nvm"
      [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
      [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
      INNER
      EOF
      
      # 拷貝啟動腳本
      COPY jenkins-agent.sh /usr/local/bin/jenkins-agent.sh
      RUN chmod +x /usr/local/bin/jenkins-agent.sh && \
          chown jenkins:jenkins /usr/local/bin/jenkins-agent.sh
      
      # 確保歸屬正確
      RUN chown -R jenkins:jenkins /home/jenkins
      
      # 關鍵:切換用戶并定義入口點
      USER jenkins
      WORKDIR $AGENT_WORKDIR
      ENTRYPOINT ["/usr/local/bin/jenkins-agent.sh"]
      

      2. jenkins-agent.sh

      #!/bin/bash
      # jenkins-agent.sh
      
      set -e
      
      if [ -z "$1" ] || [ -z "$2" ]; then
        echo "? 錯誤:缺少 JNLP secret 或 agent name"
        echo "?? 用法: $0 <secret> <agent-name>"
        exit 1
      fi
      
      export AGENT_WORKDIR="/home/jenkins/agent"
      export JAVA_HOME="/data/jdk-17.0.12"
      export PATH="$JAVA_HOME/bin:$PATH"
      
      cd "$AGENT_WORKDIR"
      
      # 從 Jenkins Master 下載 agent.jar(支持 WebSocket)
      curl -fsSL -o agent.jar http://jenkins-master.jenkins.svc.cluster.local:8080/jnlpJars/agent.jar
      
      exec java \
        -Duser.home=/home/jenkins \
        -Djava.awt.headless=true \
        -jar ./agent.jar \
        -url http://jenkins-master.jenkins.svc.cluster.local:8080 \
        -webSocket \
        -workDir "$AGENT_WORKDIR" \
        -headless \
        "$1" "$2"
      

      說明

      • -webSocket:啟用 WebSocket 連接,避免暴露 50000 端口。
      • jenkins-master.jenkins.svc.cluster.local:Kubernetes 內部 DNS 名稱。

      3. 構建并推送 Agent 鏡像

      docker build -f Dockerfile.agent -t swr.cn-east-3.myhuaweicloud.com/bocheng-test/jenkins-agent:v1 .
      
      docker push swr.cn-east-3.myhuaweicloud.com/bocheng-test/jenkins-agent:v1
      

      ?? 第四步:創建 PersistentVolume 和 PersistentVolumeClaim

      1. jenkins-pv.yaml

      apiVersion: v1
      kind: PersistentVolume
      metadata:
        name: jenkins-pv
      spec:
        capacity:
          storage: 10Gi
        volumeMode: Filesystem
        accessModes:
          - ReadWriteOnce
        persistentVolumeReclaimPolicy: Retain
        storageClassName: local-storage
        local:
          path: /data/jenkins-pv
        nodeAffinity:
          required:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: kubernetes.io/hostname
                    operator: In
                    values:
                      - k8s-node1
      

      說明

      • nodeAffinity 確保 PV 綁定到 k8s-node1
      • ReadWriteOnce:單節點讀寫。

      2. jenkins-pvc.yaml

      apiVersion: v1
      kind: PersistentVolumeClaim
      metadata:
        name: jenkins-pvc
        namespace: jenkins
      spec:
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 10Gi
        storageClassName: local-storage
        volumeName: jenkins-pv
      

      ?? 修正:原文件中 volumeName 縮進錯誤導致未生效。


      3. 應用 PV/PVC

      kubectl create ns jenkins
      
      kubectl apply -f ~/jenkins-setup/jenkins-pv.yaml
      kubectl apply -f ~/jenkins-setup/jenkins-pvc.yaml
      

      ?? 第五步:部署 Jenkins Master(Pod hostname=jenkins-0)

      jenkins-master.yaml

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: jenkins
        namespace: jenkins
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: jenkins-master
        template:
          metadata:
            labels:
              app: jenkins-master
            annotations:
              pod.beta.kubernetes.io/hostname: jenkins-0
          spec:
            serviceAccountName: jenkins
            hostname: jenkins-0
            nodeSelector:
              kubernetes.io/hostname: k8s-node1
            tolerations:
              - key: node-role.kubernetes.io/control-plane
                operator: Exists
                effect: NoSchedule
              - key: node-role.kubernetes.io/master
                operator: Exists
                effect: NoSchedule
            containers:
              - name: jenkins
                image: swr.cn-east-3.myhuaweicloud.com/bocheng-test/jenkins-master:v1
                imagePullPolicy: IfNotPresent
                ports:
                  - containerPort: 8080
                    name: http
                volumeMounts:
                  - name: jenkins-home
                    mountPath: /var/jenkins_home
            volumes:
              - name: jenkins-home
                persistentVolumeClaim:
                  claimName: jenkins-pvc
      
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: jenkins-master
        namespace: jenkins
      spec:
        selector:
          app: jenkins-master
        ports:
          - name: http
            port: 8080
            targetPort: 8080
          - name: jnlp
            port: 50000
            targetPort: 50000
      

      說明

      • hostname: jenkins-0 顯式設置 Pod 主機名。
      • nodeSelector 強制調度至 k8s-node1。
      • tolerations 允許容忍 master 污點(如需部署在 master 上)。

      部署命令

      kubectl apply -f ~/jenkins-setup/jenkins-master.yaml
      

      ?? 第六步:安裝 Nginx Ingress Controller(若未安裝)

      kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/baremetal/deploy.yaml
      

      等待啟動完成

      kubectl get pods -n ingress-nginx --watch
      

      ?? 第七步:創建 Ingress(HTTP,無 TLS)

      jenkins-ingress.yaml

      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
        name: jenkins-ingress
        namespace: jenkins
        annotations:
          nginx.ingress.kubernetes.io/ssl-redirect: "false"
          nginx.ingress.kubernetes.io/proxy-body-size: "0"
          nginx.ingress.kubernetes.io/proxy-connect-timeout: "3600"
          nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
          nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
          nginx.ingress.kubernetes.io/proxy-request-buffering: "off"
          nginx.ingress.kubernetes.io/websocket-services: jenkins-master
      spec:
        ingressClassName: nginx
        rules:
          - host: jenkins.local
            http:
              paths:
                - path: /
                  pathType: Prefix
                  backend:
                    service:
                      name: jenkins-master
                      port:
                        number: 8080
      

      說明

      • websocket-services:啟用 WebSocket 支持。
      • proxy-* 超時時間延長,防止大任務中斷。

      應用 Ingress

      kubectl apply -f ~/jenkins-setup/jenkins-ingress.yaml
      

      ?? 第八步:獲取初始密碼并登錄 Jenkins

      POD_NAME=$(kubectl get pod -n jenkins -l app=jenkins-master -o jsonpath='{.items[0].metadata.name}')
      kubectl exec -n jenkins $POD_NAME -- cat /var/jenkins_home/secrets/initialAdminPassword
      

      登錄地址:http://jenkins.local
      用戶名:jenkins
      密碼:上述輸出內容


      ?? 第九步:配置 Jenkins 系統設置(關鍵)

      進入 Manage Jenkins → Configure System

      字段
      Jenkins URL http://jenkins.local/
      Quiet Period 5 sec
      # of executors 0

      ?? 必須設置 Jenkins URL,否則 Agent 回調失敗!


      ?? 第十步:創建 ServiceAccount 并獲取 Token

      jenkins-sa.yaml

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

      說明:賦予 cluster-admin 權限以便動態管理 Pod。


      應用并獲取 Token

      kubectl apply -f ~/jenkins-setup/jenkins-sa.yaml
      
      SECRET_NAME=$(kubectl get secret -n jenkins -o jsonpath='{.items[?(@.type=="kubernetes.io/service-account-token")&&contains(@.metadata.annotations."kubernetes.io/service-account.name","jenkins")]).metadata.name}')
      
      kubectl get secret $SECRET_NAME -n jenkins -o jsonpath='{.data.token}' | base64 -d
      

      復制此 token,后續用于 Kubernetes Cloud 配置。


      ?? 第十一步:配置 Kubernetes Cloud(完整版)

      進入:Manage Jenkins → Configure System → Cloud → Add a new cloud → Kubernetes

      Kubernetes 云配置

      字段
      Name k8s-cluster
      Kubernetes URL https://kubernetes.default.svc.cluster.local
      Kubernetes Namespace jenkins
      Credentials ? 添加 → Kind = Secret text → Scope = Global → Secret = 粘貼上面的 token → ID = k8s-sa-token
      Test Connection ? 顯示 “Connected to Kubernetes …”

      Jenkins 配置

      字段
      Jenkins URL http://jenkins.local
      Jenkins Tunnel 留空(啟用 WebSocket)

      添加 Pod Template

      點擊 Add Pod Template

      字段
      Name jnlp-slave
      Namespace jenkins
      Labels custom-agent jnlp-slave
      Usage Use this node as much as possible
      Run As User 1000
      Run As Group 1000
      Add Container ?

      Container 配置

      字段
      Name jnlp
      Docker Image swr.cn-east-3.myhuaweicloud.com/bocheng-test/jenkins-agent:v1
      Allocate pseudo-TTY ? 勾選
      Command / Args 留空(由 entrypoint 控制)

      保存配置。


      ?? 第十二步:DNS 測試與訪問

      1. 配置本地 DNS

      修改本地電腦的 hosts 文件:

      <INGRESS-IP> jenkins.local
      

      <INGRESS-IP> 是運行 Ingress Controller 的節點 IP(如 192.168.122.190

      2. 訪問 Jenkins

      瀏覽器打開:

      http://jenkins.local
      

      你應該看到 Jenkins 登錄頁面。


      ?? 第十三步:測試 Pipeline

      pipeline {
          agent { label 'jnlp-slave' }
          stages {
              stage('Build') {
                  steps {
                      sh 'echo "Hello from Ubuntu 22.04 Agent"'
                      sh 'java -version'
                      sh 'git --version'
                      sh 'whoami'
                      sh 'df -h'
                  }
              }
          }
      }
      

      驗證

      • 是否動態創建 Agent Pod?
      • 構建完成后是否自動銷毀?
      • 日志中是否顯示來自自定義鏡像?

      ? 驗證清單(全部手動驗證)

      驗證項 命令 / 方法
      Master 是否在 k8s-node1 kubectl get pod -n jenkins -o wide
      hostname 是否為 jenkins-0 kubectl exec -it POD -n jenkins -- hostname
      數據是否落盤 ls /data/jenkins-pv on k8s-node1
      PVC 是否綁定 kubectl get pvc -n jenkins
      Ingress 是否生效 kubectl get ingress -n jenkins
      Jenkins URL 是否正確 Web UI → Configure System → Jenkins URL
      Kubernetes Plugin 連接成功 Cloud 配置頁 Test Connection 成功
      Agent 是否動態創建 kubectl get pods -n jenkins during build
      Agent 使用自定義鏡像 kubectl get pod AGENT_POD -n jenkins -o jsonpath='{.spec.containers[0].image}'

      ?? 總結

      你現在擁有一個 完全手搓、無 TLS、基于 ubuntu:22.04、Ingress 暴露、WebSocket 連接、主從分離 的 Jenkins CI/CD 系統。

      特性 實現方式
      Master 鏡像 自定義 ubuntu:22.04
      Agent 鏡像 自定義 ubuntu:22.04 + remoting.jar
      存儲 PVC + PV + hostPath
      暴露方式 Ingress(HTTP)
      主從連接 WebSocket(無需 50000 端口)
      Pod 名 hostname=jenkins-0
      權限 SA + RBAC
      可擴展 Kubernetes Plugin 動態伸縮

      ?? 附加:Jenkins Agent 高級權限配置(可選)

      適用于需要構建容器或訪問宿主機資源的場景:

      spec:
        containers:
          - name: jnlp
            securityContext:
              privileged: true
              capabilities:
                add:
                  - SYS_ADMIN
                  - SETFCAP
              allowPrivilegeEscalation: true
            volumeMounts:
              - name: containers-storage
                mountPath: /var/lib/containers
              - name: dev-mapper
                mountPath: /dev/mapper
              - name: containerd-socket
                mountPath: /run/containerd/containerd.sock
              - name: local-time
                mountPath: /etc/localtime
              - name: maven-cache
                mountPath: /root/.m2/repository
        volumes:
          - name: containers-storage
            emptyDir: {}
          - name: dev-mapper
            hostPath:
              path: /dev/mapper
          - name: containerd-socket
            hostPath:
              path: /run/containerd/containerd.sock
          - name: local-time
            hostPath:
              path: /etc/localtime
          - name: maven-cache
            persistentVolumeClaim:
              claimName: maven-cache-pvc
        tolerations:
          - key: "node-role.kubernetes.io/master"
            operator: "Exists"
            effect: "NoSchedule"
      

      ?? 注意:privileged: true 存在安全風險,請謹慎使用。


      ?? 附加:項目流水線模板

      1. Jenkinsfile 示例

      pipeline {
          agent { label 'jnlp-slave' }
      
          environment {
              registry            = "swr.cn-east-3.myhuaweicloud.com"
              project             = "bocheng-test"
              app_name            = "${JOB_NAME}"
              image_name          = "${registry}/${project}/${app_name}:${BUILD_NUMBER}"
              app_port            = "8901"
              git_address         = "https://gitlab.dbblive.com/dbbjt/wanyan-test.git"
              rollback_image_name = "${registry}/${project}/${app_name}:${version}"
              docker_registry_auth = "swr-secret"
              git_auth            = "a9f095dd-abfc-411f-b4c4-c10518839eea"
          }
      
          parameters {
              gitParameter(
                  name: 'Branch',
                  type: 'PT_BRANCH_TAG',
                  branch: '',
                  branchFilter: '.*',
                  tagFilter: '*',
                  defaultValue: 'master',
                  selectedValue: 'NONE',
                  sortMode: 'NONE',
                  description: 'Select the branch to deploy'
              )
              choice(
                  name: 'Namespace',
                  choices: 'prod',
                  description: 'Select deployment environment'
              )
              choice(
                  name: 'deploy_env',
                  choices: ['deploy', 'rollback'],
                  description: 'deploy: deploy new version, rollback: roll back to specified image'
              )
              string(
                  name: 'version',
                  defaultValue: '',
                  description: 'Enter the image version (BUILD_NUMBER) for rollback, used only in rollback mode'
              )
          }
      
          stages {
              stage('Checkout Code') {
                  steps {
                      echo "Checking out application code from ${git_address}"
      
                      checkout([
                          $class: 'GitSCM',
                          branches: [[name: "${params.Branch}"]],
                          doGenerateSubmoduleConfigurations: false,
                          extensions: [],
                          submoduleCfg: [],
                          userRemoteConfigs: [[
                              credentialsId: "${git_auth}",
                              url: "${git_address}"
                          ]]
                      ])
      
                      echo "Cloning Kubernetes deployment configurations"
      
                      dir('yyh-devops-config') {
                          git(
                              branch: 'master',
                              url: 'https://gitlab.dbblive.com/kubernetes/yyh-devops.git',
                              credentialsId: "${git_auth}"
                          )
                      }
      
                      echo "Code checkout completed"
                  }
              }
      
              stage('Build and Push Image') {
                  when {
                      expression { params.deploy_env == 'deploy' }
                  }
                  steps {
                      echo "Starting build and container image creation"
      
                      sh """
                          mvn clean install -am -pl bc-gateway -Dmaven.test.skip=true -P test -T 4C
                          /usr/bin/buildah login -u cn-east-3@HPUAAL2AC4J1SRYWA1NW -p b39facac2c5dbffb4aa0defa8d4750ce3d148c81a0cb0f3b9d184f755d0fff3f ${registry}
                          cd \${WORKSPACE}/bc-gateway
                          /usr/bin/buildah bud -t ${image_name} .
                          /usr/bin/buildah push ${image_name}
                      """
      
                      echo "Image built and pushed successfully: ${image_name}"
                  }
              }
      
              stage('Deploy to Kubernetes') {
                  when {
                      expression { params.deploy_env == 'deploy' }
                  }
                  steps {
                      echo "Deploying application to Kubernetes cluster"
      
                      dir('yyh-devops-config/dbbjt/wanyan-test') {
                          sh '''
                              echo "Current working directory: $(pwd)"
                              echo "Listing contents:"
                              ls -la
      
                              if [ ! -f k8s-deployment.yaml ]; then
                                  echo "ERROR: k8s-deployment.yaml not found" >&2
                                  echo "Please ensure the file exists at path: ddbjt/wanyan-test/k8s-deployment.yaml in the yyh-devops repo" >&2
                                  exit 1
                              fi
      
                              echo "Replacing template variables..."
                              sed -i "s#{APP_NAME}#${JOB_NAME}#g" k8s-deployment.yaml
                              sed -i "s#{APP_PORT}#${app_port}#g" k8s-deployment.yaml
                              sed -i "s#{IMAGE_NAME}#${image_name}#g" k8s-deployment.yaml
                              sed -i "s#{NAME_SPACE}#${Namespace}#g" k8s-deployment.yaml
                              sed -i "s#{ADD_ENV_LABEL}#${Namespace}#g" k8s-deployment.yaml
      
                              echo "Applying deployment configuration..."
                              kubectl apply -f k8s-deployment.yaml -n ${Namespace}
                              echo "Deployment applied successfully"
                          '''
                      }
                  }
              }
      
              stage('Wait for Service Readiness') {
                  when {
                      expression { params.deploy_env == 'deploy' }
                  }
                  steps {
                      echo "Waiting for service to start..."
                      sleep 63
      
                      timeout(time: 31, unit: 'SECONDS') {
                          waitUntil {
                              script {
                                  def podStatus = sh(
                                      returnStdout: true,
                                      script: "kubectl get replicasets -n ${Namespace} | grep ${JOB_NAME} | awk '{if (\$2 >= 1 && \$4 == 0) print \"not_ready\"}'"
                                  ).trim()
      
                                  def notRunningPod = sh(
                                      returnStdout: true,
                                      script: "kubectl get pod -n ${Namespace} | grep ${JOB_NAME} | awk '{if (\$2 == \"0/1\") print \$1}'"
                                  ).trim()
      
                                  if (podStatus || notRunningPod) {
                                      echo "Service is not ready yet. Retrying in 10 seconds..."
                                      sleep(10)
                                      return false
                                  } else {
                                      echo "Service ${JOB_NAME} is now running and ready"
                                      return true
                                  }
                              }
                          }
                      }
                  }
              }
      
              stage('Rollback Image') {
                  when {
                      expression { params.deploy_env == 'rollback' }
                  }
                  steps {
                      echo "Performing rollback for ${JOB_NAME} to version: ${version}"
      
                      dir('yyh-devops-config/dbbjt/wanyan-test') {
                          sh '''
                              echo "Current directory: $(pwd)"
                              ls -la
      
                              if [ ! -f k8s-deployment.yaml ]; then
                                  echo "ERROR: k8s-deployment.yaml not found, cannot proceed with rollback" >&2
                                  exit 1
                              fi
      
                              echo "Updating image to rollback version..."
                              sed -i "s#{APP_NAME}#${JOB_NAME}#g" k8s-deployment.yaml
                              sed -i "s#{APP_PORT}#${app_port}#g" k8s-deployment.yaml
                              sed -i "s#{IMAGE_NAME}#${rollback_image_name}#g" k8s-deployment.yaml
                              sed -i "s#{NAME_SPACE}#${Namespace}#g" k8s-deployment.yaml
                              sed -i "s#{ADD_ENV_LABEL}#${Namespace}#g" k8s-deployment.yaml
      
                              echo "Applying rollback configuration..."
                              kubectl apply -f k8s-deployment.yaml -n ${Namespace}
                              echo "Rollback completed"
                          '''
                      }
                  }
              }
          }
      
          post {
              success {
                  echo "Pipeline succeeded: Deployment or rollback completed successfully"
              }
              failure {
                  echo "Pipeline failed: Check logs for details"
              }
              always {
                  echo "Pipeline execution finished"
              }
          }
      }
      

      2. Kubernetes Deployment 模板(k8s-deployment.yaml)

      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: {APP_NAME}
        namespace: {NAME_SPACE}
        labels:
          app: {APP_NAME}
          env: {ADD_ENV_LABEL}
      spec:
        ports:
        - name: http
          port: {APP_PORT}
          protocol: TCP
          targetPort: {APP_PORT}
        selector:
          app: {APP_NAME}
          env: {ADD_ENV_LABEL}
        sessionAffinity: None
        type: ClusterIP
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: {APP_NAME}
        namespace: {NAME_SPACE}
        labels:
          app: {APP_NAME}
          env: {ADD_ENV_LABEL}
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: {APP_NAME}
            env: {ADD_ENV_LABEL}
        strategy:
          rollingUpdate:
            maxSurge: 1
            maxUnavailable: 0
          type: RollingUpdate
        template:
          metadata:
            labels:
              app: {APP_NAME}
              env: {ADD_ENV_LABEL}
          spec:
            imagePullSecrets:
            - name: swr-registry-secret
            affinity:
              podAntiAffinity:
                preferredDuringSchedulingIgnoredDuringExecution:
                - podAffinityTerm:
                    labelSelector:
                      matchExpressions:
                      - key: app
                        operator: In
                        values:
                        - {APP_NAME}
                    topologyKey: kubernetes.io/hostname
                  weight: 100
            containers:
            - env:
              - name: TZ
                value: Asia/Shanghai
              - name: LANG
                value: en_US.UTF-8
              image: {IMAGE_NAME}
              imagePullPolicy: IfNotPresent
              name: {APP_NAME}
              ports:
              - name: http
                containerPort: {APP_PORT}
                protocol: TCP
              readinessProbe:
                failureThreshold: 2
                initialDelaySeconds: 30
                periodSeconds: 10
                successThreshold: 1
                tcpSocket:
                  port: {APP_PORT}
                timeoutSeconds: 2
              livenessProbe:
                failureThreshold: 2
                initialDelaySeconds: 30
                periodSeconds: 10
                successThreshold: 1
                tcpSocket:
                  port: {APP_PORT}
                timeoutSeconds: 2          
              resources:
                limits:
                  cpu: 1000m
                  memory: 1024Mi
                requests:
                  cpu: 200m
                  memory: 256Mi
              volumeMounts:
              - mountPath: /data/logs
                name: logs
              - mountPath: /etc/localtime
                name: localtime
                readOnly: true
            dnsPolicy: ClusterFirstWithHostNet
            restartPolicy: Always
            securityContext:
              fsGroup: 2049
              runAsGroup: 2049
              runAsUser: 2049
            volumes:
            - emptyDir: {}
              name: logs
            - hostPath:
                path: /etc/localtime
                type: File
              name: localtime
      

      說明

      • 使用 {} 占位符,在 Jenkins 中通過 sed 替換。
      • 添加反親和性策略防止同一節點部署多個副本。
      附加jenkins的配置(web頁面)
      
       **Kubernetes 云配置 (Cloud Kubernetes Configuration)** 和 **Pod 模板設置 (Pod Template Settings)**,它們是 Jenkins 與 Kubernetes 集成以動態創建構建代理(Agent)的核心配置。
      
      ---
      
      ### **第一步:配置 Kubernetes 云 (Cloud Kubernetes Configuration)**
      
      這是在 Jenkins 系統管理中定義如何連接到 Kubernetes 集群的全局設置。
      
      1.  **名稱 (Name)**
          *   設置為 `Kubernetes`。
          *   這是此云配置的唯一標識符,在后續配置 Pod 模板時會引用它。
      
      2.  **Kubernetes 地址 (Kubernetes URL)**
          *   填寫為 `https://kubernetes.default.svc.cluster.local`。
          *   這是集群內部 API Server 的地址,Jenkins Master 通過這個地址與 Kubernetes 通信。
      
      3.  **禁用 HTTPS 證書檢查 (Disable https certificate check)**
          *   **已勾選**。
          *   此選項用于跳過對 Kubernetes API Server 證書的有效性驗證。在測試或內部環境中常用,但在生產環境中不推薦,存在安全風險。
      
      4.  **Kubernetes 命名空間 (Kubernetes Namespace)**
          *   設置為 `jenkins`。
          *   指定 Jenkins 將在此命名空間內創建和管理所有的 Agent Pod。
      
      5.  **WebSocket**
          *   **已勾選**。
          *   啟用 WebSocket 連接,這是 Jenkins Agent 與 Master 之間建立持久連接的一種高效方式。
      
      6.  **Jenkins 地址 (Jenkins URL)**
          *   填寫為 `http://jenkins-master.jenkins.svc.cluster.local:8080`。
          *   這是 Kubernetes 集群內部訪問 Jenkins Master 的地址。Agent Pod 會使用這個地址來連接并注冊到 Master。
      
      7.  **容器數量 (Container Cap)**
          *   設置為 `10`。
          *   限制同時運行的 Agent Pod 最大數量為 10 個。
      
      8.  **Pod Labels (Pod 標簽)**
          *   添加了一個標簽:
              *   **鍵 (Key)**: `jenkins`
              *   **值 (Value)**: `jnlp`
          *   這個標簽會被附加到所有由該云配置創建的 Pod 上,用于標識和篩選這些 Pod。
      
      9.  **其他重要設置**
          *   **Pod Retention**: 設置為 `Never`,意味著一旦構建完成,Pod 會被立即刪除。
          *   **連接 Kubernetes API 的最大連接數**: 設置為 `32`。
          *   **Seconds to wait for pod to be running**: 設置為 `600` 秒(10分鐘),等待 Pod 啟動并進入 Running 狀態的最大時間。
          *   **Container Cleanup Timeout**: 設置為 `5` 秒,清理容器的超時時間。
      
      ---
      
      ### **第二步:配置 Pod 模板 (Pod Template Settings)**
      
      這是在 Kubernetes 云配置下定義具體 Agent Pod 結構的模板。當有構建任務需要執行時,Jenkins 會根據此模板動態創建一個 Pod。
      
      1.  **名稱 (Name)**
          *   設置為 `jnlp-slave`。
          *   這是此 Pod 模板的唯一名稱。
      
      2.  **命名空間 (Namespace)**
          *   設置為 `jenkins`。
          *   與上一步的云配置保持一致,確保 Pod 在正確的命名空間內創建。
      
      3.  **標簽列表 (Labels)**
          *   設置為 `jnlp-slave`。
          *   這是分配給此 Pod 模板的標簽。在 Jenkins 的 Job 配置中,可以通過指定這個標簽來選擇使用此模板創建的 Agent。
      
      4.  **用法 (Usage)**
          *   設置為“只允許運行綁定到這臺機器的Job”。
          *   這意味著只有明確指定了 `jnlp-slave` 標簽的 Job 才能使用這個模板創建的 Agent。
      
      5.  **容器列表 (Container Templates)**
      
          *   **容器名稱 (Name)**: `jnlp`
          *   **Docker 鏡像 (Docker Image)**: `swr.cn-east-3.myhuaweicloud.com/bocheng-test/jenkins-agentv2`
              *   這是 Agent 容器所使用的鏡像。
          *   **工作目錄 (Working Directory)**: `/home/jenkins/agent`
              *   容器啟動后的工作目錄。
          *   **命令參數 (Arguments)**: `${computer.jnlpMac} ${computer.name}`
              *   這是傳遞給 `jnlp` 容器的啟動參數,用于讓 Agent 連接到 Jenkins Master。
          *   **分配偽終端 (Allocate TTY)**: **已勾選**。
              *   為容器分配一個偽終端,這對于某些需要交互式環境的構建腳本是必需的。
      
      6.  **環境變量 (Environment Variables)**
      
          *   **CONTAINERD_ADDRESS**: `/run/containerd/containerd.sock`
              *   指向 Containerd 的 Unix Socket,可能用于容器運行時相關的操作。
          *   **CONTAINERD_NAMESPACE**: `default`
              *   設置 Containerd 的命名空間。
      
      7.  **卷 (Volumes)**
      
          *   **Host Path Volume (主機路徑卷)**
              *   第一個:
                  *   主機路徑: `/run/containerd/containerd.sock`
                  *   掛載路徑: `/run/containerd/containerd.sock`
                  *   用于將主機上的 Containerd Socket 掛載到容器內。
              *   第二個:
                  *   主機路徑: `/etc/localtime`
                  *   掛載路徑: `/etc/localtime`
                  *   用于同步主機的時間配置到容器內,保證時間一致性。
          *   **Persistent Volume Claim (持久卷聲明)**
              *   申明值: `maven-cache-pvc`
              *   掛載路徑: `/root/.m2/repository`
              *   用于掛載一個名為 `maven-cache-pvc` 的 PVC 到容器內的 Maven 本地倉庫目錄,實現構建緩存的持久化,加快后續構建速度。
      
      8.  **Raw YAML for the Pod**
      
          *   這里直接提供了完整的 Pod YAML 定義,它覆蓋了上面所有圖形化界面的配置。
          *   關鍵點包括:
              *   **securityContext**: 設置了 `privileged: true` 和 `capabilities`,賦予容器特權模式和特定能力(SYS_ADMIN, SETFCAP),這通常是為了支持 Docker-in-Docker 或其他需要高權限的操作。
              *   **volumeMounts & volumes**: 明確定義了上述的三個卷掛載。
              *   **tolerations**: 添加了容忍度 `node-role.kubernetes.io/master: Exists`,允許 Pod 調度到 Master 節點上(如果集群中有 Master 節點且允許調度)。
      
      9.  **Service Account**
          *   設置為 `jenkins`。
          *   指定 Pod 使用的服務賬戶,用于控制 Pod 在 Kubernetes 中的權限。
      
      10. **Run As User ID / Run As Group ID**
          *   均設置為 `0`。
          *   以 root 用戶身份運行容器,這與 `privileged: true` 權限相匹配。
      
      11. **Image Pull Secret**
          *   名稱: `swr-secret`
          *   用于從私有倉庫 `swr.cn-east-3.myhuaweicloud.com` 拉取鏡像時進行身份認證。
      
      12. **其他設置**
          *   **Pod Retention**: 設置為 `Default`,遵循云配置中的 `Never`。
          *   **連接 Jenkins 的超時時間 (秒)**: 設置為 `1000` 秒。
          *   **Yaml merge strategy**: 設置為 `Override`,表示 Raw YAML 會完全覆蓋圖形化配置。
      
      ---
      
      ### **總結**
      
      通過以上兩步配置,Jenkins 成功集成了 Kubernetes:
      
      *   **第一步**建立了與 Kubernetes 集群的連接通道,并設定了全局的資源限制和行為。
      *   **第二步**定義了一個具體的、功能完備的 Agent Pod 模板 (`jnlp-slave`),它包含了運行構建所需的鏡像、環境變量、持久化存儲、權限設置以及網絡連接等所有細節。
      
      當用戶創建一個 Job 并指定其運行在 `jnlp-slave` 標簽的節點上時,Jenkins 會自動調用 Kubernetes API,在 `jenkins` 命名空間下創建一個符合 `jnlp-slave` 模板的 Pod。該 Pod 啟動后會連接到 Jenkins Master,接收并執行構建任務,任務完成后 Pod 會被自動清理。這種動態按需創建 Agent 的方式,極大地提高了資源利用率和系統的可擴展性。
      
      posted @ 2025-10-23 10:25  完顏振江  閱讀(10)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 怡春院久久国语视频免费| 国产欧美综合在线观看第十页| 亚洲国产欧美在线人成大黄瓜 | 综合亚洲网| 免费无码黄十八禁网站| 最新精品国产自偷在自线| 国产成人午夜福利高清在线观看| 最近中文字幕日韩有码| 波多野结衣久久一区二区| 精品中文字幕一区在线| 亚洲国产成人AⅤ片在线观看| 精品国产乱弄九九99久久| 蜜桃av无码免费看永久| 人妻加勒比系列无码专区| a级国产乱理伦片在线观看al| 国产极品精品自在线不卡| 国产精品户外野外| 蜜臀视频一区二区在线播放 | 亚洲日本va午夜蜜芽在线电影| 亚洲av成人网在线观看| 一区二区中文字幕av| 最近免费中文字幕大全免费版视频| 边吃奶边添下面好爽| 久久精品国产蜜臀av| 国产午夜福利免费入口| 国产精品色三级在线观看| 国产精品午夜福利资源| 白丝乳交内射一二三区| 老熟妇欲乱一区二区三区| 丁香婷婷综合激情五月色| 亚洲精品成人区在线观看| 亚洲色欲色欱WWW在线| 国产精品国产三级国快看| 国产精品久久久久久久专区| 国产精品+日韩精品+在线播放| 伊人久久大香线蕉AV网| 国产精品自在线拍国产手机版| 日本免费一区二区三区| 精品国产午夜福利在线观看| 伊人蕉久影院| 亚洲国产欧美在线人成|