按 Enter 键跳转到正文

基于 Gogs + Jenkins + Harbor + Docker 的自动化部署方案

基于 Gogs + Jenkins + Harbor + Docker 的自动化部署方案

1. 系统架构总览

开发者提交代码 → Git仓库 → Jenkins触发构建 → Docker构建镜像 → 推送至Harbor → 
Kubernetes部署更新 → 监控反馈

2. 环境准备

2.1 硬件要求

  • 最低配置:2核CPU/4GB内存/100GB存储
  • 推荐配置:4核CPU/8GB内存/200GB SSD

3. 组件安装与配置

3.1 Gogs 安装

另外一篇Jenkins 使用

3.2 Jenkins 安装

另外一篇Gogs 使用

3.3 Harbor 安装

另外一篇Harbor 使用

4. 环境配置

下面以wordpress项目为例

wordpress/
├── app/                  # 项目代码
├── docker                # Docker 相关文件
|    ├── Dockerfile      
|    ├── entrypont.sh      
|    └── nginx.conf       
|    └── nginx-wordpress.conf 
├── Jenkinsfile           # Jenkins Pipeline 定义
└── k8s/                  # Kubernetes 部署文件
    ├── deployment.yaml   # Deployment 配置
    ├── service.yaml      # Service 配置
    └── ingress.yaml      # Ingress 配置(可选)
    └── namespace.yaml    # namespace 配置(可选)

4.1 JenkinsPipeline配置

  1. 安装必要插件
  • Kubernetes Continuous Deploy
  • Docker Pipeline
  • Gogs plugin
  • Harbor
  • Git
  1. 配置凭据: Manage Jenkins > Credentials
  • Git仓库访问凭据 ID如 gogs-credential
  • Harbor仓库凭据 ID如harbor-credential
  • Kubernetes集群凭据 (/etc/rancher/k3s)ID如 k3s-kubeconfig

Jenkins 示例:

4.2 Harbor配置

  1. 创建专门的项目(如wordpress)
  2. 配置访问权限
  3. 确保Jenkins服务器可以访问Harbor API

如果存在证书问题

检查 Docker 配置文件/etc/docker/daemon.json加入

1{
2  "insecure-registries": ["IP地址"]
3}
 1# 下载Harbor证书(需替换实际路径)
 2sudo mkdir -p /etc/docker/certs.d/ip
 3sudo curl -k https://ip/api/v2.0/systeminfo/getcert -o /etc/docker/certs.d/ip/ca.crt
 4
 5# 更新系统证书库
 6sudo cp /etc/docker/certs.d/ip/ca.crt /usr/local/share/ca-certificates/
 7sudo update-ca-certificates
 8
 9# 重启docker
10sudo systemctl restart docker

4.3 Gogs Webhook配置

  1. 在Gogs仓库设置中管理Web钩子:
    URL如: http://ip:端口默认8080/gogs-webhook/?job=jobnNme
    Secret: your-shared-secret
    触发事件: 推送、提交
    

4.4 Jenkins Pipeline设计

  1
  2def getTriggerUser() {
  3    def causes = currentBuild.getBuildCauses()
  4    if (causes) {
  5        def userCause = causes.find { it.shortDescription?.contains("User") }
  6        if (userCause) {
  7            // 从 shortDescription 中提取用户名(格式通常为 "Started by user <用户名>")
  8            def match = userCause.shortDescription =~ /Started by user (.*)/
  9            return match ? match[0][1] : "未知用户"
 10        }
 11    }
 12    return '系统触发'
 13}
 14
 15// Jenkinsfile
 16pipeline {
 17  agent any
 18
 19  // 1. 定义
 20  environment {
 21    // 应用名称
 22    APP_NAME = "wordpress"
 23
 24    // Harbor 镜像仓库地址
 25    REGISTRY = "host/wordpress"
 26
 27    // K3s 集群上下文名称 (根据您的 kubeconfig 配置 cat /etc/rancher/k3s/k3s.yaml)
 28    KUBE_CONTEXT = "default"
 29  }
 30
 31  // 2. 拉取代码
 32  stages {
 33    stage('Checkout') {
 34      steps {
 35        // 从 Gogs 拉取代码
 36        git branch: 'master',
 37           url: 'host/username/wordpress.git',
 38           credentialsId: 'gogs-credential'  // 预先配置的 Gogs 访问凭证
 39      }
 40    }
 41
 42    // 3. 定义镜像标签
 43    stage('Prepare') {
 44        steps {
 45          script {
 46            // 获取 Git 提交信息(确保代码已 checkout)
 47            env.GIT_COMMIT_SHORT = sh(
 48              script: 'git rev-parse --short HEAD',
 49              returnStdout: true
 50            ).trim()
 51            // 定义镜像标签
 52            env.IMAGE_TAG = "build-${env.BUILD_NUMBER}-${env.GIT_COMMIT_SHORT}"
 53          }
 54        }
 55      }
 56
 57    // 4. 构建镜像 并 推送镜像
 58    stage('Build Image') {
 59      steps {
 60        script {
 61          // 构建 Docker 镜像 (使用 Dockerfile 中的定义)
 62          docker.build("${REGISTRY}/${APP_NAME}:${env.IMAGE_TAG}", "-f docker/Dockerfile .")
 63
 64          // 使用环境变量安全登录并推送
 65          withCredentials([usernamePassword(
 66            credentialsId: 'harbor-credential',
 67            usernameVariable: 'HARBOR_USER',
 68            passwordVariable: 'HARBOR_PASS'
 69          )]) {
 70            sh """
 71              # 登录Harbor
 72              echo \$HARBOR_PASS | docker login ${env.REGISTRY} -u \$HARBOR_USER --password-stdin
 73
 74              # 推送带构建标签的镜像
 75              docker push ${env.REGISTRY}/${env.APP_NAME}:${env.IMAGE_TAG}
 76
 77              # 额外推送latest标签
 78              docker tag ${env.REGISTRY}/${env.APP_NAME}:${env.IMAGE_TAG} ${env.REGISTRY}/${env.APP_NAME}:latest
 79              docker push ${env.REGISTRY}/${env.APP_NAME}:latest
 80            """
 81          }
 82        }
 83      }
 84    }
 85
 86    // 5. k3s 部署
 87    stage('Deploy to K3s') {
 88      steps {
 89        script {
 90          // 使用 kubeconfig 凭证
 91          withCredentials([file(
 92            credentialsId: 'k3s-kubeconfig',
 93            variable: 'KUBECONFIG'
 94          )]) {
 95            // 设置 KUBECONFIG 环境变量
 96            withEnv(["KUBECONFIG=${env.KUBECONFIG}"]) {
 97              // 应用 Kubernetes 配置
 98              sh """
 99                kubectl config use-context ${KUBE_CONTEXT} || exit 1
100
101                # 检查集群连接
102                kubectl cluster-info || exit 1
103
104                # 创建命名空间
105                kubectl apply -f k8s/namespace.yaml || exit 1
106
107                # 部署应用(确保文件按顺序应用)
108                kubectl apply -f k8s/deployment.yaml || exit 1
109                kubectl apply -f k8s/service.yaml || exit 1
110                # 当前 NodePort模式不用ingress
111                # kubectl apply -f k8s/ingress.yaml || exit 1
112
113                # 更新镜像 (使用带构建ID的标签)
114                kubectl set image deployment/wordpress \
115                  wordpress=${REGISTRY}/${APP_NAME}:${env.IMAGE_TAG} \
116                  -n wordpress || exit 1
117
118                # 等待部署完成
119                kubectl rollout status deployment/wordpress -n wordpress --timeout=300s || exit 
120
121                # 检查状态
122                kubectl get pods,svc,ing -n wordpress
123              """
124            }
125          }
126        }
127      }
128    }
129  }
130
131
132  post {
133    // 成功
134    success {
135      script {
136        def successMessage = """
137        • *Jenkins Build Success*
138        • 项目: ${env.JOB_NAME} #${env.BUILD_NUMBER}
139        • 状态: ${currentBuild.result}
140        • 耗时: ${currentBuild.durationString}
141        • 镜像: ${env.REGISTRY}/${env.APP_NAME}:${env.IMAGE_TAG}
142        • 详情: ${env.BUILD_URL}
143        """.stripIndent().trim()
144
145        // 发送 Slack 通知(成功)需要Slack Notification 插件
146         slackSend(
147           channel: env.SLACK_CHANNEL,
148           color: 'good',
149           message: successMessage
150         )
151      }
152    }
153    // 失败
154    failure {
155      script {
156        def triggerUser = getTriggerUser()
157        def failureMessage = """
158          • *Jenkins Build Failed*
159          • 项目: ${env.JOB_NAME} #${env.BUILD_NUMBER}
160          • 状态: ${currentBuild.result}
161          • 执行人: ${triggerUser}
162          • 建议: 检查日志或联系 DevOps
163        """.stripIndent().trim()
164
165      // 发送 Slack 通知(失败)
166      slackSend(
167         channel: env.SLACK_CHANNEL,
168         color: 'danger',
169         message: failureMessage
170       )
171      }
172   }
173   
174    always {
175      // 清理工作空间 需要Workspace Cleanup 插件
176      cleanWs()
177    }
178  
179  }
180}

4.5 Kubernetes部署文件

k8s/namespace.yaml

1# k8s/namespace.yaml
2apiVersion: v1
3kind: Namespace
4metadata:
5name: wordpress

k8s/service.yaml

 1# k8s/service.yaml
 2apiVersion: v1
 3kind: Service
 4metadata:
 5  name: wordpress
 6  namespace: wordpress
 7spec:
 8  # 选择器(匹配Pod标签)
 9  selector:
10    app: wordpress
11  # 端口配置
12  ports:
13    - name: http
14      protocol: TCP
15      port: 80          # 服务端口
16      targetPort: 80    # 容器端口
17      nodePort: 30080   # 手动指定端口(建议选 30000 以上未占用端口)
18  type: NodePort        

k8s/deployment.yaml

 1apiVersion: apps/v1
 2kind: Deployment
 3metadata:
 4  name: wordpress
 5  namespace: wordpress
 6  labels:
 7    app: wordpress
 8spec:
 9  replicas: 1  # 实例数量
10  selector:
11    matchLabels:
12      app: wordpress
13  strategy:
14    rollingUpdate:
15      maxSurge: 1       # 升级期间允许超过期望值的 Pod 数量
16      maxUnavailable: 0  # 升级期间不可用 Pod 数量
17  template:
18    metadata:
19      labels:
20        app: wordpress
21    spec:
22      terminationGracePeriodSeconds: 90  # 延长终止宽限期
23      containers:
24        - name: wordpress
25          image: host/wordpress/wordpress:latest  # 镜像会被 Jenkins 动态替换
26          ports:
27            - containerPort: 80
28          env:
29            - name: WORDPRESS_DB_HOST
30              value: host:port
31            - name: WORDPRESS_DB_USER
32              value: super
33            - name: WORDPRESS_DB_PASSWORD
34              valueFrom:
35                secretKeyRef:                 #指定连接 MySQL 的密码(从 Kubernetes Secret 获取)需提前创建namespace:kubectl create namespace 创建Secret命令:kubectl create secret generic mysql-secret --from-literal=password='your_secure_password' -n wordpress
36                  name: mysql-secret          # Secret 名称
37                  key: password               # Secret 中的键名
38            - name: WORDPRESS_DB_NAME
39              value: "wordpress"
40          resources:
41            requests:
42              cpu: "100m"
43              memory: "128Mi"
44            limits:
45              cpu: "500m"
46              memory: "512Mi"
47          livenessProbe:
48            httpGet:
49              path: /wp-login.php       # 根路径(无需域名解析)
50              port: 80                  # 容器内服务端口
51              scheme: HTTP              # 协议与容器内服务一致(HTTP/HTTPS)
52            initialDelaySeconds: 60     # 容器启动后等待 30 秒再开始探测
53            periodSeconds: 20           # 每 10 秒探测一次
54            timeoutSeconds: 5           # 超时时间 5 秒
55            failureThreshold: 3         # 连续 3 次失败则判定为不健康
56          readinessProbe:
57            httpGet:
58              path: /wp-login.php
59              port: 80
60              scheme: HTTP
61            initialDelaySeconds: 30
62            periodSeconds: 10
63            timeoutSeconds: 5
64            failureThreshold: 3
65      imagePullSecrets:
66        - name: harbor-secret   

5. 完整工作流程总结

  • 开发者推送代码到Git仓库
  • Jenkins检测到变更并触发Pipeline
  • Pipeline执行以下步骤:
    • 拉取最新代码
    • 构建Docker镜像
    • 运行单元测试(可选)
    • 推送镜像到Harbor
    • 更新Kubernetes部署
    • 执行健康检查
    • 部署成功后通知
    • 监控系统跟踪应用性能

发表评论