首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >从零构建全栈自动化部署流水线:GitLab CI + Docker + K8s 实战

从零构建全栈自动化部署流水线:GitLab CI + Docker + K8s 实战

原创
作者头像
用户12609250
修改2026-07-28 15:38:01
修改2026-07-28 15:38:01
3920
举报

1. 为什么需要全栈自动化?

在微服务与云原生时代,手动部署已成为效率瓶颈。一套成熟的自动化流水线应具备:

  • 代码即基础设施:所有配置版本化管理
  • 不可变交付物:基于镜像的标准化交付
  • 环境一致性:开发、测试、生产环境统一
  • 快速回滚:秒级恢复到任意历史版本

2. 技术选型与架构图

层级

工具

用途

CI

GitLab CI

触发构建、执行测试、生成镜像

制品仓库

Harbor

存储 Docker 镜像

容器编排

Kubernetes (K8s)

服务调度、弹性伸缩、滚动更新

配置管理

Helm

模板化 K8s 资源清单

监控告警

Prometheus + Grafana

自动化运维观测

架构流程图(文字描述): 代码 Push → GitLab Webhook → CI Pipeline (test → build → push) → Helm Upgrade → K8s 滚动更新 → 健康检查 → 完成发布

3. 项目代码结构(全栈 Demo)

我们使用一个 Vue3 + Flask 的简单投票应用作为示例。

代码语言:javascript
复制
fullstack-automation/
├── frontend/                # Vue3 前端
│   ├── src/
│   ├── Dockerfile
│   ├── nginx.conf
│   └── package.json
├── backend/                 # Flask 后端 API
│   ├── app.py
│   ├── requirements.txt
│   ├── Dockerfile
│   └── gunicorn.conf.py
├── k8s/
│   ├── namespace.yaml
│   ├── backend-deploy.yaml
│   ├── backend-svc.yaml
│   ├── frontend-deploy.yaml
│   ├── frontend-svc.yaml
│   └── ingress.yaml
├── helm/                    # Helm Chart(可选)
│   └── vote-chart/
├── .gitlab-ci.yml           # CI 核心配置
└── README.md

4. 关键代码实现

4.1 后端 Flask API (backend/app.py)

代码语言:javascript
复制
from flask import Flask, jsonify, request
from flask_cors import CORS
import os

app = Flask(__name__)
CORS(app)

votes = {"vue": 0, "react": 0, "angular": 0}

@app.route('/api/health', methods=['GET'])
def health():
    return jsonify({"status": "ok"}), 200

@app.route('/api/votes', methods=['GET'])
def get_votes():
    return jsonify(votes), 200

@app.route('/api/vote', methods=['POST'])
def vote():
    data = request.get_json()
    framework = data.get('framework')
    if framework in votes:
        votes[framework] += 1
        return jsonify({"success": True, "votes": votes}), 200
    return jsonify({"error": "Invalid framework"}), 400

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

4.2 前端 Vue3 核心组件 (frontend/src/App.vue)

代码语言:javascript
复制
<template>
  <div id="app">
    <h1>全栈自动化投票</h1>
    <div class="buttons">
      <button v-for="fw in frameworks" :key="fw" @click="vote(fw)">
        投给 {{ fw }}
      </button>
    </div>
    <div class="results">
      <p v-for="(count, fw) in votes" :key="fw">
        {{ fw }}: {{ count }} 票
      </p>
    </div>
  </div>
</template>

<script>
import axios from 'axios';

const API_BASE = '/api';

export default {
  data() {
    return {
      frameworks: ['vue', 'react', 'angular'],
      votes: {}
    };
  },
  async mounted() {
    await this.fetchVotes();
  },
  methods: {
    async fetchVotes() {
      const res = await axios.get(`${API_BASE}/votes`);
      this.votes = res.data;
    },
    async vote(framework) {
      await axios.post(`${API_BASE}/vote`, { framework });
      await this.fetchVotes();
    }
  }
};
</script>

4.3 多阶段构建 Dockerfile(后端示例)

代码语言:javascript
复制
# backend/Dockerfile
FROM python:3.10-slim as builder
WORKDIR /build
COPY requirements.txt .
RUN pip install --user -r requirements.txt

FROM python:3.10-slim
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY . .
ENV PATH=/root/.local/bin:$PATH
EXPOSE 5000
CMD ["gunicorn", "-c", "gunicorn.conf.py", "app:app"]

4.4 GitLab CI 全流水线 (.gitlab-ci.yml)

代码语言:javascript
复制
stages:
  - test
  - build
  - deploy

variables:
  DOCKER_REGISTRY: harbor.example.com
  BACKEND_IMAGE: $DOCKER_REGISTRY/vote/backend
  FRONTEND_IMAGE: $DOCKER_REGISTRY/vote/frontend
  K8S_NAMESPACE: vote-prod

cache:
  paths:
    - frontend/node_modules/
    - backend/.venv/

# 1. 测试阶段
test-backend:
  stage: test
  image: python:3.10-slim
  script:
    - pip install pytest flask-cors
    - pytest backend/tests/ -v
  only:
    - merge_requests
    - main

test-frontend:
  stage: test
  image: node:18-alpine
  script:
    - cd frontend
    - npm install
    - npm run test:unit
  only:
    - merge_requests
    - main

# 2. 构建并推送镜像(使用 Kaniko 无需 Docker-in-Docker)
build-images:
  stage: build
  image: gcr.io/kaniko-project/executor:v1.9.0-debug
  script:
    - /kaniko/executor
      --context="$CI_PROJECT_DIR/backend"
      --dockerfile="$CI_PROJECT_DIR/backend/Dockerfile"
      --destination="$BACKEND_IMAGE:$CI_COMMIT_SHORT_SHA"
      --destination="$BACKEND_IMAGE:latest"
    - /kaniko/executor
      --context="$CI_PROJECT_DIR/frontend"
      --dockerfile="$CI_PROJECT_DIR/frontend/Dockerfile"
      --destination="$FRONTEND_IMAGE:$CI_COMMIT_SHORT_SHA"
      --destination="$FRONTEND_IMAGE:latest"
  only:
    - main

# 3. 部署到 K8s(滚动更新)
deploy-k8s:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - kubectl set image deployment/backend-deploy
      backend=$BACKEND_IMAGE:$CI_COMMIT_SHORT_SHA
      -n $K8S_NAMESPACE
    - kubectl set image deployment/frontend-deploy
      frontend=$FRONTEND_IMAGE:$CI_COMMIT_SHORT_SHA
      -n $K8S_NAMESPACE
    - kubectl rollout status deployment/backend-deploy -n $K8S_NAMESPACE
    - kubectl rollout status deployment/frontend-deploy -n $K8S_NAMESPACE
  only:
    - main
  environment:
    name: production
    url: https://vote.example.com

4.5 Kubernetes 部署清单(关键片段)

后端 Deployment (k8s/backend-deploy.yaml):

代码语言:javascript
复制
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend-deploy
  namespace: vote-prod
spec:
  replicas: 3
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
      - name: backend
        image: harbor.example.com/vote/backend:latest
        ports:
        - containerPort: 5000
        livenessProbe:
          httpGet:
            path: /api/health
            port: 5000
          initialDelaySeconds: 10
          periodSeconds: 5
        readinessProbe:
          httpGet:
            path: /api/health
            port: 5000
          initialDelaySeconds: 5
        resources:
          requests:
            memory: "128Mi"
            cpu: "100m"
          limits:
            memory: "256Mi"
            cpu: "200m"

Ingress 暴露服务 (k8s/ingress.yaml):

代码语言:javascript
复制
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: vote-ingress
  namespace: vote-prod
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: vote.example.com
    http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: backend-svc
            port:
              number: 5000
      - path: /
        pathType: Prefix
        backend:
          service:
            name: frontend-svc
            port:
              number: 80

5. 自动化增强:从 CI 到 CD 的进阶技巧

5.1 基于 Git Tag 的版本发布

deploy 阶段增加规则,仅当 Tag 符合语义化版本时触发生产发布:

代码语言:javascript
复制
deploy-prod:
  stage: deploy
  rules:
    - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
  script:
    - helm upgrade --install vote ./helm/vote-chart
      --set backend.image.tag=$CI_COMMIT_TAG
      --set frontend.image.tag=$CI_COMMIT_TAG

5.2 自动化回滚脚本(集成到 CI)

创建 rollback.sh,在发布失败时自动执行:

代码语言:javascript
复制
#!/bin/bash
# 回滚到上一个稳定版本
kubectl rollout undo deployment/backend-deploy -n vote-prod
kubectl rollout undo deployment/frontend-deploy -n vote-prod

5.3 健康检查与自动重试

在 CI 中添加 curl 轮询验证:

代码语言:javascript
复制
verify-deploy:
  stage: deploy
  image: curlimages/curl:latest
  script:
    - for i in $(seq 1 10); do
        curl -f https://vote.example.com/api/health && break;
        sleep 5;
      done

6. 运行与验证

  1. 提交代码
  2. GitLab CI 自动触发:查看流水线状态
  3. 访问服务
  4. 查看 K8s 状态: bash kubectl get pods -n vote-prod kubectl get svc -n vote-prod

7. 常见问题排查

现象

可能原因

解决方法

镜像拉取失败

私有仓库未配置 secret

kubectl create secret docker-registry regcred ...

健康检查失败

端口或路径错误

检查 livenessProbe 配置

滚动更新卡住

资源不足或镜像启动慢

增加 initialDelaySeconds 或调整 resources

前端无法访问 API

Ingress 路径重写错误

检查 nginx.ingress.kubernetes.io/rewrite-target

8. 总结与扩展

本文实现了从 代码提交 → 自动测试 → 镜像构建 → K8s 滚动更新 的完整闭环。此方案可直接应用于中小型团队,并具备以下扩展能力:

  • 灰度发布:结合 Istio 实现金丝雀发布
  • 自动化回归测试:集成 Postman/Newman 或 Cypress
  • 监控联动:发布后自动比对 Prometheus 指标,异常则回滚

全部代码已上传至 GitHub 示例仓库(替换为你的仓库地址),欢迎 Fork 使用。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 1. 为什么需要全栈自动化?
  • 2. 技术选型与架构图
  • 3. 项目代码结构(全栈 Demo)
  • 4. 关键代码实现
    • 4.1 后端 Flask API (backend/app.py)
    • 4.2 前端 Vue3 核心组件 (frontend/src/App.vue)
    • 4.3 多阶段构建 Dockerfile(后端示例)
    • 4.4 GitLab CI 全流水线 (.gitlab-ci.yml)
    • 4.5 Kubernetes 部署清单(关键片段)
  • 5. 自动化增强:从 CI 到 CD 的进阶技巧
    • 5.1 基于 Git Tag 的版本发布
    • 5.2 自动化回滚脚本(集成到 CI)
    • 5.3 健康检查与自动重试
  • 6. 运行与验证
  • 7. 常见问题排查
  • 8. 总结与扩展
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档