15 KiB
15 KiB
Gitea CI/CD 快速配置指南
📋 适用场景
为新项目快速配置基于 Gitea Actions + Argo CD 的完整 GitOps 工作流。
✅ 前置条件
1. 基础设施检查
# 检查 Gitea Actions Runner
ls -la /Users/brunogao/gitea-runners/runner3/.runner
# 应显示: labels: ["macos:docker:host"] 或 ["docker-builder"]
# 检查 Harbor Registry
docker login harbor.omniverseai.net
# 应成功登录
# 检查 Argo CD
kubectl get application -n argocd
# 应看到 apps-bootstrap 和其他应用
2. 准备信息
- 项目名称: 如
my-app - Gitea 仓库:
http://192.168.1.83:33000/gao/my-app - Harbor 镜像:
harbor.omniverseai.net/ljwx/my-app - K8s Namespace:
my-app-dev(推荐独立 namespace) - Gitea Token: 从 Gitea 设置 → 应用 → 访问令牌生成
🚀 配置步骤
Step 1: 项目仓库配置 Gitea Workflow
1.1 创建 Workflow 文件
在项目根目录创建 .gitea/workflows/ci.yaml:
name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
REGISTRY: harbor.omniverseai.net
IMAGE_NAME: ljwx/my-app # 修改为你的项目名
jobs:
# ==================== Job 1: Lint & Test ====================
lint-test:
runs-on: ubuntu-latest # K8s runner,快速
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci --legacy-peer-deps
- name: Run linter
run: npm run lint
- name: Type check
run: npm run build:check || npm run build
# ==================== Job 2: Build & Push ====================
build-push:
needs: lint-test
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: docker-builder # 宿主机 runner,有完整 Docker 环境
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Extract metadata
id: meta
run: |
SHORT_SHA=$(echo ${{ github.sha }} | cut -c1-7)
echo "tag=main-${SHORT_SHA}" >> $GITHUB_OUTPUT
echo "short_sha=${SHORT_SHA}" >> $GITHUB_OUTPUT
- name: Log in to Harbor
run: echo "${{ secrets.HARBOR_PASSWORD }}" | docker login ${{ env.REGISTRY }} -u "${{ secrets.HARBOR_USERNAME }}" --password-stdin
- name: Set up Docker Buildx
run: |
docker buildx create --name ci-builder --use --driver docker-container || docker buildx use ci-builder
docker buildx inspect --bootstrap
- name: Build and push Docker image
run: |
docker buildx build \
--platform linux/amd64,linux/arm64 \
--tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.tag }} \
--tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest \
--push \
--progress plain \
.
- name: Image digest
run: |
docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.tag }}
# ==================== Job 3: Update Deploy Repo ====================
update-deploy:
needs: build-push
runs-on: ubuntu-latest
env:
IMAGE_TAG: main-${{ github.sha }}
steps:
- name: Checkout code
run: |
SHORT_SHA=$(echo ${{ github.sha }} | cut -c1-7)
echo "IMAGE_TAG=main-${SHORT_SHA}" >> $GITHUB_ENV
- name: Verify tools
run: |
node --version
npm --version
git --version
yq --version
- name: Update deployment repository
run: |
# 克隆 ljwx-deploy 仓库 (使用 token 认证)
git clone http://gao:${{ secrets.DEPLOY_REPO_TOKEN }}@192.168.1.83:33000/gao/ljwx-deploy.git /tmp/ljwx-deploy
cd /tmp/ljwx-deploy
# 配置 git
git config user.name "Gitea Actions"
git config user.email "[email protected]"
# 导航到 overlay 目录(修改为你的项目路径)
cd apps/my-app/overlays/my-app-dev
# 更新镜像 tag
yq eval ".images[0].newTag = \"${IMAGE_TAG}\"" -i kustomization.yaml
# 提交并推送
git add kustomization.yaml
git commit -m "chore: update my-app to ${IMAGE_TAG}"
git push origin main
# ==================== Job 4: Build PR (仅验证) ====================
build-pr:
needs: lint-test
if: github.event_name == 'pull_request'
runs-on: docker-builder
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
run: |
docker buildx create --name ci-builder --use --driver docker-container || docker buildx use ci-builder
docker buildx inspect --bootstrap
- name: Build Docker image (no push)
run: |
docker buildx build \
--platform linux/amd64,linux/arm64 \
--progress plain \
.
1.2 配置 Gitea Secrets
推荐方式: 使用 Organization Secrets (一次配置,所有项目共享)
详细配置步骤请参考: GITEA-SECRETS-SETUP.md
# Organization 级别配置 (推荐):
# http://192.168.1.83:33000/gao/settings/secrets
# 添加以下 3 个 Secrets,所有项目自动可用:
# - HARBOR_USERNAME: Harbor 用户名
# - HARBOR_PASSWORD: Harbor 密码
# - DEPLOY_REPO_TOKEN: Gitea 访问令牌 (用于更新 ljwx-deploy 仓库)
# 或者项目级别配置 (不推荐):
# http://192.168.1.83:33000/gao/my-app/settings/secrets
# 需要为每个项目单独配置
💡 提示: 如果已经配置了 Organization Secrets,可以跳过此步骤
1.3 确保 Dockerfile 存在
在项目根目录创建 Dockerfile.prod (或 Dockerfile):
# 第一阶段:构建
FROM harbor.omniverseai.net/library/node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --legacy-peer-deps
COPY . .
RUN npm run build
# 第二阶段:生产
FROM harbor.omniverseai.net/library/nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget --quiet --tries=1 --spider http://localhost/health || exit 1
CMD ["nginx", "-g", "daemon off;"]
Step 2: ljwx-deploy 仓库配置
2.1 创建 Namespace 配置
cd /path/to/ljwx-deploy
# 创建 namespace 配置文件
cat > cluster/namespace-my-app-dev.yaml <<EOF
apiVersion: v1
kind: Namespace
metadata:
name: my-app-dev
labels:
name: my-app-dev
environment: dev
app: my-app
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: my-app-quota
namespace: my-app-dev
spec:
hard:
requests.cpu: "500m"
requests.memory: "512Mi"
limits.cpu: "1"
limits.memory: "1Gi"
persistentvolumeclaims: "5"
services: "5"
pods: "10"
---
apiVersion: v1
kind: LimitRange
metadata:
name: my-app-limits
namespace: my-app-dev
spec:
limits:
- max:
cpu: "500m"
memory: "512Mi"
min:
cpu: "10m"
memory: "32Mi"
default:
cpu: "100m"
memory: "128Mi"
defaultRequest:
cpu: "50m"
memory: "64Mi"
type: Container
EOF
# 更新 cluster/kustomization.yaml
yq eval '.resources += ["namespace-my-app-dev.yaml"]' -i cluster/kustomization.yaml
2.2 创建应用部署配置
# 创建目录结构
mkdir -p apps/my-app/{base,overlays/my-app-dev}
# 创建 base/deployment.yaml
cat > apps/my-app/base/deployment.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
component: web
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
component: web
spec:
containers:
- name: my-app
image: harbor.omniverseai.net/ljwx/my-app:latest
ports:
- name: http
containerPort: 80
livenessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
memory: "64Mi"
cpu: "25m"
limits:
memory: "128Mi"
cpu: "100m"
EOF
# 创建 base/service.yaml
cat > apps/my-app/base/service.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
name: my-app
labels:
app: my-app
spec:
type: ClusterIP
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app: my-app
EOF
# 创建 base/kustomization.yaml
cat > apps/my-app/base/kustomization.yaml <<EOF
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
EOF
# 创建 overlays/my-app-dev/kustomization.yaml
cat > apps/my-app/overlays/my-app-dev/kustomization.yaml <<EOF
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: my-app-dev
resources:
- ../../base
images:
- name: harbor.omniverseai.net/ljwx/my-app
newTag: "latest" # CI 会自动更新这个 tag
replicas:
- name: my-app
count: 1 # dev 环境使用 1 个副本
EOF
2.3 创建 Argo CD Application
# 创建 Application 配置
cat > argocd-apps/60-my-app-dev.yaml <<EOF
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app-dev
namespace: argocd
spec:
project: default
source:
repoURL: http://192.168.1.83:33000/gao/ljwx-deploy.git
targetRevision: main
path: apps/my-app/overlays/my-app-dev
destination:
server: https://kubernetes.default.svc
namespace: my-app-dev
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
EOF
2.4 提交到 Git
cd /path/to/ljwx-deploy
# 提交所有变更
git add .
git commit -m "feat: add my-app deployment configuration"
git push origin main
# 等待 30 秒让 apps-bootstrap 自动创建 Application
sleep 30
Step 3: 验证部署
3.1 验证 Argo CD Application
# 检查 Application 是否自动创建
kubectl get application my-app-dev -n argocd
# 应该显示:
# NAME SYNC STATUS HEALTH STATUS
# my-app-dev Synced Healthy
3.2 验证 Namespace 和资源
# 检查 namespace
kubectl get namespace my-app-dev
# 检查资源配额
kubectl get resourcequota,limitrange -n my-app-dev
# 检查部署状态
kubectl get all -n my-app-dev
3.3 测试完整 CI/CD 流程
# 在项目仓库中做一个测试提交
cd /path/to/my-app
echo "# Test CI/CD" >> README.md
git add README.md
git commit -m "test: verify CI/CD pipeline"
git push origin main
# 观察流程:
# 1. Gitea Actions 开始构建 (约 3-5 分钟)
# 2. 镜像推送到 Harbor
# 3. ljwx-deploy 仓库自动更新
# 4. Argo CD 检测到变更并同步 (约 30 秒)
# 5. 新 Pod 启动
# 检查 Gitea Actions
# http://192.168.1.83:33000/gao/my-app/actions
# 检查 ljwx-deploy 最新提交
cd /path/to/ljwx-deploy
git pull origin main
git log -1 --oneline
# 应该看到: chore: update my-app to main-xxxxxxx
# 检查 Pod 镜像更新
kubectl describe pod -n my-app-dev -l app=my-app | grep Image:
🎯 关键配置点
1. Runner 选择
# 轻量级任务 (lint, test) → K8s runner
runs-on: ubuntu-latest
# Docker 构建任务 → 宿主机 runner
runs-on: docker-builder # 或 macos
2. Multi-arch 构建
# 必须使用 buildx + atomic push
docker buildx build \
--platform linux/amd64,linux/arm64 \
--push \ # 一步完成 build + push
.
3. Kustomize 路径
# CI workflow 中的路径要匹配
cd apps/my-app/overlays/my-app-dev
# Argo CD Application 中的路径
path: apps/my-app/overlays/my-app-dev
4. Namespace 独立性
# 推荐: 每个应用独立 namespace
namespace: my-app-dev
# 而不是: 共享 namespace
namespace: dev # ❌ 避免
🔧 常见问题排查
问题 1: Build & Push 失败
症状: Docker build 失败或推送失败
检查:
# 1. 检查 runner 标签
cat /Users/brunogao/gitea-runners/runner3/.runner
# 2. 检查 Harbor 凭据
echo "$HARBOR_PASSWORD" | docker login harbor.omniverseai.net -u "$HARBOR_USERNAME" --password-stdin
# 3. 检查 buildx builder
docker buildx ls
解决: 使用 docker-builder 标签的 runner,确保 buildx 正确设置
问题 2: Update Deploy Repo 不执行
症状: Job 显示成功但 ljwx-deploy 未更新
检查:
# 1. 验证 DEPLOY_REPO_TOKEN
# Gitea → 设置 → 应用 → 访问令牌
# 2. 检查路径是否正确
ls -la ljwx-deploy/apps/my-app/overlays/my-app-dev/kustomization.yaml
# 3. 测试 git clone
git clone http://gao:[email protected]:33000/gao/ljwx-deploy.git /tmp/test
解决:
- 确保 token 有
repo权限 - 确保路径
apps/my-app/overlays/my-app-dev存在
问题 3: Argo CD 不自动同步
症状: ljwx-deploy 更新了但 K8s 未部署
检查:
# 1. 检查 Application 状态
kubectl describe application my-app-dev -n argocd
# 2. 检查 apps-bootstrap
kubectl get application apps-bootstrap -n argocd
# 3. 手动触发同步
kubectl patch application my-app-dev -n argocd \
--type merge \
-p '{"operation":{"initiatedBy":{"username":"admin"},"sync":{"revision":"HEAD"}}}'
解决:
- 确保 Application 文件名匹配
*-dev.yaml模式 - 等待 3 分钟(Argo CD 默认同步间隔)
问题 4: Pod CrashLoopBackOff
症状: Pod 启动失败
检查:
# 1. 查看 Pod 日志
kubectl logs -n my-app-dev -l app=my-app --tail=50
# 2. 查看 Pod 事件
kubectl describe pod -n my-app-dev -l app=my-app
# 3. 检查资源限制
kubectl get limitrange -n my-app-dev -o yaml
解决:
- 确保 Dockerfile 正确配置
- 确保
/health端点存在 - 调整 resources.requests 满足 LimitRange
📚 参考文档
- ljwx-website 成功案例:
.gitea/workflows/ci.yaml - Gitea Actions 文档: https://docs.gitea.com/usage/actions/overview
- Argo CD App of Apps:
ARGOCD-APP-MANAGEMENT.md - Namespace 策略:
NAMESPACE-STRATEGY.md - GitOps 原则:
PROMPT_BLUEPRINT_V2.md
🎉 总结
完成上述步骤后,你的项目将拥有:
✅ 完整的 CI/CD 自动化流程 ✅ Multi-arch Docker 镜像 ✅ GitOps 声明式部署 ✅ 独立的 Namespace 资源隔离 ✅ Argo CD 自动同步 ✅ 零手动 kubectl 操作
记住: Git commit 即部署,完全自动化!🚀