基于 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配置
- 安装必要插件
- Kubernetes Continuous Deploy
- Docker Pipeline
- Gogs plugin
- Harbor
- Git
- 配置凭据: Manage Jenkins > Credentials
- Git仓库访问凭据 ID如 gogs-credential
- Harbor仓库凭据 ID如harbor-credential
- Kubernetes集群凭据 (/etc/rancher/k3s)ID如 k3s-kubeconfig
Jenkins 示例:
4.2 Harbor配置
- 创建专门的项目(如wordpress)
- 配置访问权限
- 确保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配置
- 在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部署
- 执行健康检查
- 部署成功后通知
- 监控系统跟踪应用性能
发表评论