- 添加 Gitea Actions 工作流 (.gitea/workflows/) - cicd.yml: 完整 CICD 流程(构建、测试、推送、部署) - test.yml: 快速测试工作流 - 配置 Kubernetes 部署清单 (k8s/) - namespace.yaml: 创建 claude-stock namespace - configmap.yaml: 应用配置和 Ollama 连接配置 - deployment.yaml: 后端和前端部署(支持 Node IP 连接 Ollama) - service.yaml: 服务定义、RBAC 和网络策略 - ollama-bridge.yaml: 四种 K8s 与宿主 Ollama 通信方案 - secrets.sh: 自动创建 K8s Secrets - 部署脚本和工具 - deploy-to-k8s.sh: 一键 K8s 部署脚本 - verify-cicd.sh: CICD 环境验证脚本 - 文档 - CICD_DEPLOYMENT_GUIDE.md: 完整部署指南(中文) - QUICK_START.md: 5 分钟快速启动指南(中文) 关键功能: ✅ Gitea Runners(Docker + K8s) ✅ Harbor 镜像仓库集成 ✅ 自动化测试和安全扫描 ✅ K8s 滚动更新和健康检查 ✅ Ollama 集成(使用 Node IP 解决通信问题) ✅ 完整的部署后验证 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
602 lines
12 KiB
Markdown
602 lines
12 KiB
Markdown
# 完整 CICD 部署指南
|
||
|
||
本指南涵盖如何在 Gitea + Harbor + Kubernetes + Ollama 环境中部署 Claude Stock 应用的完整 CICD 流程。
|
||
|
||
## 📋 目录
|
||
|
||
1. [前置条件](#前置条件)
|
||
2. [Gitea 和 Runners 配置](#gitea-和-runners-配置)
|
||
3. [Harbor 配置](#harbor-配置)
|
||
4. [Kubernetes 部署](#kubernetes-部署)
|
||
5. [Ollama 集成](#ollama-集成)
|
||
6. [CICD 工作流说明](#cicd-工作流说明)
|
||
7. [故障排除](#故障排除)
|
||
|
||
---
|
||
|
||
## 前置条件
|
||
|
||
确保以下服务已部署:
|
||
|
||
- ✅ **Gitea** - `http://192.168.1.83:33000`
|
||
- ✅ **Harbor** - `https://localhost:8443`
|
||
- ✅ **Kubernetes** - Cluster 已运行
|
||
- ✅ **Ollama** - 宿主上运行(localhost:11434)
|
||
- ✅ **Docker** - 宿主上可用
|
||
|
||
### 检查服务状态
|
||
|
||
```bash
|
||
# 检查 Gitea
|
||
docker ps | grep gitea
|
||
|
||
# 检查 Harbor
|
||
docker ps | grep harbor
|
||
|
||
# 检查 Kubernetes
|
||
kubectl cluster-info
|
||
|
||
# 检查 Ollama
|
||
curl http://localhost:11434/api/tags
|
||
|
||
# 检查 Docker
|
||
docker ps
|
||
```
|
||
|
||
---
|
||
|
||
## Gitea 和 Runners 配置
|
||
|
||
### 步骤 1: 启动 Gitea 和 Runners
|
||
|
||
```bash
|
||
cd ~/work/codes/tools/macos/gitea
|
||
|
||
# 启动 Gitea(如果还没有启动)
|
||
docker-compose up -d gitea
|
||
|
||
# 等待 Gitea 启动完成(约 30 秒)
|
||
docker-compose logs -f gitea
|
||
```
|
||
|
||
### 步骤 2: 创建 Runner 令牌
|
||
|
||
1. 访问 `http://192.168.1.83:33000/admin/runners`
|
||
2. 点击"Create new runner token"
|
||
3. 复制生成的 token
|
||
|
||
### 步骤 3: 启动 Action Runners
|
||
|
||
```bash
|
||
cd ~/work/codes/tools/macos/gitea
|
||
|
||
# 设置环境变量
|
||
export GITEA_RUNNER_TOKEN=<从步骤2复制的token>
|
||
|
||
# 使用脚本启动 runners
|
||
./setup-runners.sh
|
||
|
||
# 或者手动启动
|
||
docker-compose up -d runner-docker runner-k8s
|
||
|
||
# 验证 runners 运行状态
|
||
docker-compose ps
|
||
```
|
||
|
||
### 步骤 4: 验证 Runners 注册
|
||
|
||
```bash
|
||
# 访问 Gitea UI
|
||
# http://192.168.1.83:33000/admin/runners
|
||
|
||
# 或使用 CLI 查询
|
||
docker exec gitea3 gitea actions runner list
|
||
```
|
||
|
||
---
|
||
|
||
## Harbor 配置
|
||
|
||
### 步骤 1: 登录 Harbor
|
||
|
||
```bash
|
||
# 添加 Harbor 为 Docker 信任的注册表(需要配置 insecure registry)
|
||
# macOS: ~/.docker/daemon.json
|
||
```
|
||
|
||
```json
|
||
{
|
||
"insecure-registries": ["localhost:8443"]
|
||
}
|
||
```
|
||
|
||
### 步骤 2: 创建项目和用户
|
||
|
||
```bash
|
||
# 登录 Harbor UI
|
||
# https://localhost:8443
|
||
|
||
# 创建项目: claude-stock
|
||
# 创建用户: ci-admin(或使用默认 admin)
|
||
|
||
# 创建私有镜像仓库
|
||
# - claude-stock/backend
|
||
# - claude-stock/frontend
|
||
```
|
||
|
||
### 步骤 3: 配置 Gitea Secrets
|
||
|
||
```bash
|
||
# 在 Gitea 中创建 Repository Secrets
|
||
# 访问: http://192.168.1.83:33000/<username>/claude-stock/settings/secrets
|
||
|
||
# 需要创建以下 secrets:
|
||
|
||
# HARBOR_PASSWORD
|
||
# 值:<Harbor admin 密码>
|
||
|
||
# KUBECONFIG
|
||
# 值:$(cat ~/.kube/config | base64)
|
||
|
||
# OPENROUTER_API_KEY
|
||
# 值:<你的 OpenRouter API Key>
|
||
|
||
# TUSHARE_TOKEN
|
||
# 值:<你的 TuShare Token>
|
||
|
||
# ALPHA_VANTAGE_API_KEY
|
||
# 值:<你的 Alpha Vantage API Key>
|
||
```
|
||
|
||
---
|
||
|
||
## Kubernetes 部署
|
||
|
||
### 步骤 1: 准备部署
|
||
|
||
```bash
|
||
cd /Users/brunogao/work/codes/stock/claude-stock
|
||
|
||
# 创建 namespace
|
||
kubectl apply -f k8s/namespace.yaml
|
||
|
||
# 创建 secrets
|
||
bash k8s/secrets.sh
|
||
|
||
# 验证 secrets 创建
|
||
kubectl get secrets -n claude-stock
|
||
```
|
||
|
||
### 步骤 2: 配置本地部署(测试)
|
||
|
||
```bash
|
||
# 手动部署到 Kubernetes(CICD 会自动执行此步骤)
|
||
|
||
# 1. 创建镜像拉取 secret
|
||
kubectl create secret docker-registry harbor-secret \
|
||
--docker-server=localhost:8443 \
|
||
--docker-username=admin \
|
||
--docker-password=Harbor12345 \
|
||
--docker-email=admin@example.com \
|
||
-n claude-stock \
|
||
--dry-run=client -o yaml | kubectl apply -f -
|
||
|
||
# 2. 部署应用
|
||
kubectl apply -f k8s/namespace.yaml
|
||
kubectl apply -f k8s/configmap.yaml
|
||
kubectl apply -f k8s/deployment.yaml
|
||
kubectl apply -f k8s/service.yaml
|
||
kubectl apply -f k8s/ollama-bridge.yaml
|
||
|
||
# 3. 验证部署
|
||
kubectl get deployments -n claude-stock
|
||
kubectl get pods -n claude-stock
|
||
kubectl get svc -n claude-stock
|
||
```
|
||
|
||
### 步骤 3: 获取服务访问地址
|
||
|
||
```bash
|
||
# 获取 Backend 服务地址
|
||
kubectl get svc claude-stock-backend -n claude-stock -o wide
|
||
|
||
# 获取 Frontend 服务地址
|
||
kubectl get svc claude-stock-frontend -n claude-stock -o wide
|
||
|
||
# 查看 Pod 日志
|
||
kubectl logs -n claude-stock -l app=claude-stock-backend -f
|
||
```
|
||
|
||
---
|
||
|
||
## Ollama 集成
|
||
|
||
### 关键问题:在 Kubernetes 中访问宿主 Ollama
|
||
|
||
**问题描述:**
|
||
- Pod 内无法直接访问 `localhost:11434`
|
||
- Ollama 运行在宿主上,但 K8s Pod 网络隔离
|
||
|
||
**解决方案:** 使用 Node IP
|
||
|
||
#### 方案 1:自动检测 Node IP(推荐)
|
||
|
||
我们的 `deployment.yaml` 已配置了此方案:
|
||
|
||
```yaml
|
||
env:
|
||
- name: NODE_IP
|
||
valueFrom:
|
||
fieldRef:
|
||
fieldPath: status.hostIP
|
||
|
||
- name: OLLAMA_BASE_URL
|
||
value: "http://$(NODE_IP):11434"
|
||
```
|
||
|
||
**工作原理:**
|
||
1. Pod 通过 Kubernetes API 自动获取宿主 Node IP
|
||
2. 使用 Node IP 连接到宿主 Ollama
|
||
|
||
#### 方案 2:使用 Service ExternalName
|
||
|
||
```bash
|
||
# 部署 ollama-bridge
|
||
kubectl apply -f k8s/ollama-bridge.yaml
|
||
|
||
# Pod 中使用 DNS 名称
|
||
export OLLAMA_BASE_URL=http://ollama-endpoint:11434
|
||
```
|
||
|
||
#### 方案 3:修改 Ollama 监听地址
|
||
|
||
在宿主上修改 Ollama 配置:
|
||
|
||
```bash
|
||
# 设置 Ollama 监听所有接口
|
||
export OLLAMA_HOST=0.0.0.0:11434
|
||
|
||
# 重启 Ollama
|
||
# (根据你的 Ollama 安装方式)
|
||
```
|
||
|
||
#### 验证 Ollama 连接
|
||
|
||
```bash
|
||
# 在 Pod 中测试连接
|
||
kubectl exec -it <pod-name> -n claude-stock -- bash
|
||
|
||
# 在容器内
|
||
curl -v http://<NODE-IP>:11434/api/tags
|
||
|
||
# 检查环境变量
|
||
echo $OLLAMA_BASE_URL
|
||
echo $NODE_IP
|
||
```
|
||
|
||
---
|
||
|
||
## CICD 工作流说明
|
||
|
||
### 工作流触发条件
|
||
|
||
在以下情况下自动触发:
|
||
- ✅ `push` 到 `main` 或 `develop` 分支
|
||
- ✅ 创建 `Pull Request` 到 `main` 或 `develop`
|
||
- ❌ 忽略 `*.md`, `docs/` 等文件变更
|
||
|
||
### 工作流阶段
|
||
|
||
```
|
||
推送代码
|
||
↓
|
||
┌─────────────────────────┐
|
||
│ 1. Build & Push │ (并行执行)
|
||
│ - 构建 Backend │
|
||
│ - 构建 Frontend │
|
||
│ - 推送到 Harbor │
|
||
└─────────────────────────┘
|
||
↓
|
||
┌─────────────────────────┐
|
||
│ 2. Test & Security │ (并行执行)
|
||
│ - 运行单元测试 │
|
||
│ - Trivy 镜像扫描 │
|
||
│ - 覆盖率报告 │
|
||
└─────────────────────────┘
|
||
↓
|
||
┌─────────────────────────┐
|
||
│ 3. Deploy to K8s │ (仅 main 分支)
|
||
│ - 部署到 Kubernetes │
|
||
│ - 等待 Rollout │
|
||
│ - 获取服务信息 │
|
||
└─────────────────────────┘
|
||
↓
|
||
┌─────────────────────────┐
|
||
│ 4. Smoke Test │ (仅 main 分支)
|
||
│ - 健康检查 │
|
||
│ - API 验证 │
|
||
└─────────────────────────┘
|
||
↓
|
||
✅ 部署完成
|
||
```
|
||
|
||
### 查看工作流执行
|
||
|
||
```bash
|
||
# 在 Gitea UI 中查看
|
||
# http://192.168.1.83:33000/<user>/claude-stock/actions
|
||
|
||
# 或查看 Runner 日志
|
||
docker-compose logs -f runner-docker
|
||
docker-compose logs -f runner-k8s
|
||
```
|
||
|
||
---
|
||
|
||
## 故障排除
|
||
|
||
### 问题 1: Runners 无法注册
|
||
|
||
**症状:**
|
||
- Runners 容器不断重启
|
||
- 日志中显示连接错误
|
||
|
||
**解决方案:**
|
||
|
||
```bash
|
||
# 1. 检查 Gitea 是否正常运行
|
||
docker ps | grep gitea
|
||
docker logs gitea3
|
||
|
||
# 2. 验证 Runner Token
|
||
docker-compose exec runner-docker cat /data/.runner
|
||
|
||
# 3. 检查网络连接
|
||
docker-compose exec runner-docker curl http://gitea:3000/api/healthz
|
||
|
||
# 4. 重新启动 Runners
|
||
docker-compose restart runner-docker runner-k8s
|
||
```
|
||
|
||
### 问题 2: Harbor 推送失败
|
||
|
||
**症状:**
|
||
- 工作流失败:`docker push localhost:8443/...`
|
||
- 错误:`x509: certificate signed by unknown authority`
|
||
|
||
**解决方案:**
|
||
|
||
```bash
|
||
# 1. 配置 Docker 信任 Harbor
|
||
# macOS: ~/.docker/daemon.json
|
||
{
|
||
"insecure-registries": ["localhost:8443"]
|
||
}
|
||
|
||
# 2. 重启 Docker
|
||
# macOS: Docker Desktop > Preferences > Restart
|
||
|
||
# 3. 测试连接
|
||
docker login localhost:8443
|
||
docker tag test:latest localhost:8443/test:latest
|
||
docker push localhost:8443/test:latest
|
||
```
|
||
|
||
### 问题 3: K8s 部署失败
|
||
|
||
**症状:**
|
||
- Pod 无法拉取镜像
|
||
- 健康检查失败
|
||
|
||
**解决方案:**
|
||
|
||
```bash
|
||
# 1. 检查 Pod 状态
|
||
kubectl describe pod <pod-name> -n claude-stock
|
||
|
||
# 2. 检查镜像拉取 Secret
|
||
kubectl get secrets -n claude-stock
|
||
kubectl describe secret harbor-secret -n claude-stock
|
||
|
||
# 3. 手动测试镜像拉取
|
||
kubectl pull localhost:8443/claude-stock/backend:latest
|
||
|
||
# 4. 检查镜像是否存在在 Harbor
|
||
# 访问 Harbor UI: https://localhost:8443
|
||
```
|
||
|
||
### 问题 4: Pod 无法连接到 Ollama
|
||
|
||
**症状:**
|
||
- Backend Pod 日志:`Failed to connect to Ollama`
|
||
- 服务无法启动
|
||
|
||
**解决方案:**
|
||
|
||
```bash
|
||
# 1. 检查宿主 Ollama 是否运行
|
||
curl http://localhost:11434/api/tags
|
||
|
||
# 2. 在 Pod 内测试连接
|
||
kubectl exec -it <backend-pod> -n claude-stock -- bash
|
||
|
||
# 在容器内执行:
|
||
echo "Node IP: $NODE_IP"
|
||
echo "Ollama URL: $OLLAMA_BASE_URL"
|
||
curl -v http://$NODE_IP:11434/api/tags
|
||
|
||
# 3. 检查防火墙
|
||
# 确保宿主 11434 端口可从 K8s 网络访问
|
||
|
||
# 4. 修改 Ollama 监听地址
|
||
export OLLAMA_HOST=0.0.0.0:11434
|
||
# 重启 Ollama
|
||
```
|
||
|
||
### 问题 5: 工作流超时
|
||
|
||
**症状:**
|
||
- 工作流在部署阶段超时
|
||
- Rollout 无法完成
|
||
|
||
**解决方案:**
|
||
|
||
```bash
|
||
# 1. 增加 Rollout 超时时间
|
||
# 编辑 .gitea/workflows/cicd.yml
|
||
# 找到 kubectl rollout status
|
||
# 修改 --timeout=5m 为 --timeout=10m
|
||
|
||
# 2. 检查 Pod 状态
|
||
kubectl get pods -n claude-stock
|
||
kubectl logs <pod-name> -n claude-stock
|
||
|
||
# 3. 手动修复 Pod
|
||
kubectl delete pod <pod-name> -n claude-stock
|
||
kubectl rollout restart deployment/claude-stock-backend -n claude-stock
|
||
|
||
# 4. 增加资源配额
|
||
kubectl patch resourcequota claude-stock-quota -n claude-stock -p '{"spec":{"hard":{"requests.memory":"32Gi"}}}'
|
||
```
|
||
|
||
---
|
||
|
||
## 监控和日志
|
||
|
||
### 实时日志
|
||
|
||
```bash
|
||
# Backend 服务日志
|
||
kubectl logs -f -n claude-stock -l app=claude-stock-backend
|
||
|
||
# Frontend 服务日志
|
||
kubectl logs -f -n claude-stock -l app=claude-stock-frontend
|
||
|
||
# Runner 日志
|
||
docker-compose logs -f runner-docker
|
||
docker-compose logs -f runner-k8s
|
||
```
|
||
|
||
### 监控 Pod
|
||
|
||
```bash
|
||
# 查看 Pod 资源使用
|
||
kubectl top pods -n claude-stock
|
||
|
||
# 查看 Pod 详细信息
|
||
kubectl get pods -n claude-stock -o wide
|
||
|
||
# 实时监控
|
||
watch -n 1 kubectl get pods -n claude-stock
|
||
```
|
||
|
||
### 健康检查
|
||
|
||
```bash
|
||
# 检查服务健康
|
||
kubectl exec -it <pod-name> -n claude-stock -- curl http://localhost:8000/health
|
||
|
||
# 检查所有 Pod 状态
|
||
kubectl get pods -n claude-stock --all-namespaces
|
||
```
|
||
|
||
---
|
||
|
||
## 快速参考
|
||
|
||
### 常用命令
|
||
|
||
```bash
|
||
# 查看所有资源
|
||
kubectl get all -n claude-stock
|
||
|
||
# 查看部署日志
|
||
kubectl logs -f deployment/claude-stock-backend -n claude-stock
|
||
|
||
# 进入 Pod
|
||
kubectl exec -it <pod-name> -n claude-stock -- bash
|
||
|
||
# 重新部署
|
||
kubectl rollout restart deployment/claude-stock-backend -n claude-stock
|
||
|
||
# 删除部署
|
||
kubectl delete -f k8s/deployment.yaml -n claude-stock
|
||
|
||
# 获取服务 IP
|
||
kubectl get svc -n claude-stock
|
||
|
||
# 端口转发(本地访问)
|
||
kubectl port-forward svc/claude-stock-backend 8000:80 -n claude-stock
|
||
```
|
||
|
||
### 常用 Gitea 命令
|
||
|
||
```bash
|
||
# Runner 列表
|
||
docker exec gitea3 gitea actions runner list
|
||
|
||
# 查看 Runner 日志
|
||
docker-compose logs -f runner-docker
|
||
|
||
# 重新注册 Runner
|
||
docker-compose down runner-docker
|
||
rm -rf runner-docker/.runner
|
||
docker-compose up -d runner-docker
|
||
```
|
||
|
||
---
|
||
|
||
## 安全性建议
|
||
|
||
1. **Secret 管理**
|
||
- 使用 Kubernetes Secret 而非硬编码
|
||
- 定期轮换 token 和密码
|
||
|
||
2. **镜像安全**
|
||
- 使用 Trivy 进行镜像扫描
|
||
- 使用特定版本的基础镜像
|
||
- 定期更新依赖
|
||
|
||
3. **网络安全**
|
||
- 使用 NetworkPolicy 限制流量
|
||
- 配置 RBAC
|
||
- 启用 Pod Security Policy
|
||
|
||
4. **监控和日志**
|
||
- 启用审计日志
|
||
- 集中化日志管理
|
||
- 设置告警规则
|
||
|
||
---
|
||
|
||
## 后续优化
|
||
|
||
1. **自动化**
|
||
- 添加自动化测试
|
||
- 集成性能测试
|
||
- 添加漏洞扫描
|
||
|
||
2. **高可用**
|
||
- 增加副本数
|
||
- 配置 Pod Affinity
|
||
- 使用 PVC 持久化存储
|
||
|
||
3. **监控**
|
||
- 集成 Prometheus
|
||
- 添加 Grafana 仪表板
|
||
- 设置告警规则
|
||
|
||
4. **GitOps**
|
||
- 使用 ArgoCD 或 Flux
|
||
- 配置驱动开发
|
||
- 自动同步
|
||
|
||
---
|
||
|
||
## 联系支持
|
||
|
||
如有问题,请查看:
|
||
- Gitea 文档:https://docs.gitea.io
|
||
- Kubernetes 文档:https://kubernetes.io/docs
|
||
- Harbor 文档:https://goharbor.io/docs
|