在K8s上构建CI/CD流水线,实现代码提交→构建镜像→测试→部署的全自动化。核心原则:一切皆代码(GitOps)。
┌─────────── CI/CD流水线 ──────────────┐
│ │
│ Developer │
│ │ git push │
│ ┌──▼──────────────────────────────┐ │
│ │ CI (Continuous Integration) │ │
│ │ 1. 代码检出 │ │
│ │ 2. 单元测试 │ │
│ │ 3. 代码扫描 │ │
│ │ 4. 构建Docker镜像 │ │
│ │ 5. 推送镜像仓库 │ │
│ │ 6. 更新Helm values │ │
│ └──┬─────────────────────────────┘ │
│ │ │
│ ┌──▼──────────────────────────────┐ │
│ │ CD (Continuous Delivery) │ │
│ │ 方式A: ArgoCD (GitOps) │ │
│ │ 方式B: Flux (GitOps) │ │
│ │ 方式C: Jenkins/Pipeline │ │
│ │ → 自动部署到K8s集群 │ │
│ └──┬─────────────────────────────┘ │
│ │ │
│ ┌──▼──────────────────────────────┐ │
│ │ 部署策略 │ │
│ │ • 滚动更新 (RollingUpdate) │ │
│ │ • 金丝雀发布 (Canary) │ │
│ │ • 蓝绿部署 (Blue-Green) │ │
│ │ • 渐进式交付 (Progressive) │ │
│ └──────────────────────────────────┘ │
└────────────────────────────────────────┘
# .github/workflows/ci.yaml
name: CI Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
REGISTRY: registry.example.com
IMAGE_NAME: shop/user-service
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22'
- name: Run unit tests
run: go test -v -race -coverprofile=coverage.out ./...
- name: Run linter
uses: golangci/golangci-lint-action@v4
with:
version: latest
- name: Security scan
uses: securego/gosec@master
with:
args: ./...
build:
needs: test
runs-on: ubuntu-latest
if: github.event_name == 'push'
outputs:
image_tag: ${{ steps.meta.outputs.tags }}
steps:
- uses: actions/checkout@v4
- name: Login to registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_PASS }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha,prefix=
type=ref,event=branch
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy-dev:
needs: build
runs-on: ubuntu-latest
environment: development
steps:
- uses: actions/checkout@v4
- name: Update Helm values
run: |
yq -i ".image.tag = \"${{ needs.build.outputs.image_tag }}\"" \
charts/user-service/values-dev.yaml
git config user.name "github-actions"
git commit -am "chore: update dev image tag"
git push
# 安装ArgoCD
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# ✅ 验证通过
kubectl get pods -n argocd
# NAME READY STATUS RESTARTS AGE
# argocd-application-controller-0 1/1 Running 0 2m
# argocd-repo-server-xxxxx 1/1 Running 0 2m
# argocd-server-xxxxx 1/1 Running 0 2m
# 获取初始密码
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d
# 访问ArgoCD UI
kubectl port-forward svc/argocd-server -n argocd 8080:443
# https://localhost:8080
# argocd-app.yaml - 声明式Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: user-service
namespace: argocd
annotations:
notifications.argoproj.io/subscribe.on-deployed.slack: deploy-notifications
spec:
project: default
source:
repoURL: https://github.com/example/shop-manifests.git
targetRevision: main
path: charts/user-service
helm:
valueFiles:
- values.yaml
- values-prod.yaml
parameters:
- name: image.tag
value: "sha-abc123" # CI流水线自动更新
destination:
server: https://kubernetes.default.svc
namespace: shop-system
syncPolicy:
automated:
prune: true # 自动删除多余资源
selfHeal: true # 自动修复漂移
allowEmpty: false
syncOptions:
- CreateNamespace=true
- ServerSideApply=true
retry:
limit: 3
backoff:
duration: 5s
factor: 2
maxDuration: 3m
# ✅ 验证通过
kubectl get applications -n argocd
# NAME SYNC STATUS HEALTH STATUS
# user-service Synced Healthy
# apps-of-apps.yaml - 集中管理所有应用
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: shop-apps
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/example/shop-manifests.git
targetRevision: main
path: argocd/apps # 包含多个Application YAML
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true
# argocd/apps/ 目录下:
# ├── user-service.yaml
# ├── product-service.yaml
# ├── order-service.yaml
# ├── payment-service.yaml
# └── frontend.yaml
# 安装Argo Rollouts
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
# Rollout替代Deployment
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: user-service
namespace: shop-system
spec:
replicas: 10
strategy:
canary:
steps:
- setWeight: 10 # 10%流量到新版本
- pause: {duration: 5m} # 观察5分钟
- setWeight: 30
- pause: {duration: 5m}
- setWeight: 50
- pause: {duration: 10m}
- setWeight: 80
- pause: {duration: 5m}
# 自动完成到100%
canaryService: user-service-canary
stableService: user-service-stable
analysis:
templates:
- templateName: success-rate
args:
- name: service-name
value: user-service-canary
---
# AnalysisTemplate - 自动化验证
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: success-rate
namespace: shop-system
spec:
args:
- name: service-name
metrics:
- name: success-rate
interval: 30s
count: 10
successCondition: result[0] >= 0.99
failureLimit: 3
provider:
prometheus:
address: http://monitoring-kube-prometheus-prometheus.monitoring.svc:9090
query: |
sum(rate(http_requests_total{service="{{args.service-name}}",status!~"5.."}[2m]))
/
sum(rate(http_requests_total{service="{{args.service-name}}"}[2m]))
# ✅ 验证通过
kubectl argo rollouts get rollout user-service -n shop-system
# 多阶段构建 + 安全基础镜像
# Dockerfile
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /user-service .
# 最终镜像
FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=builder /user-service /user-service
USER nonroot:nonroot
ENTRYPOINT ["/user-service"]
下一课预告:第23课深入服务网格Istio——流量管理与可观测性。
22-cicd流水线补充要点K8s生产实践扩展
🔹 资源配额(ResourceQuota):限制命名空间总资源
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: production
spec:
hard:
requests.cpu: "20"
requests.memory: 40Gi
limits.cpu: "40"
limits.memory: 80Gi
pods: "50"
services: "10"
🔹 LimitRange:设置默认资源限制
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
spec:
limits:
- type: Container
default:
cpu: "200m"
memory: 256Mi
defaultRequest:
cpu: "100m"
memory: 128Mi
max:
cpu: "2"
memory: 4Gi
🔹 Pod优先级与抢占
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
---
spec:
preemptionPolicy: PreemptLowerPriority
🔹 优雅处理Pod中断
• PDB保证最小可用副本
• preStop钩子处理连接排空
• terminationGracePeriodSeconds充足
• 应用必须处理SIGTERM信号
🔹 生产环境Checklist
✅ 设置resources requests/limits
✅ 配置liveness/readiness探针
✅ 使用PDB保护关键服务
✅ 实现优雅关闭(SIGTERM)
✅ 配置HPA自动伸缩
✅ 使用NetworkPolicy隔离
✅ 开启RBAC最小权限
✅ 日志结构化输出
✅ 指标暴露/metrics端点
✅ 配置PVC数据备份
22-cicd流水线生产环境进阶要点
🔹 性能优化关键参数
• kubelet: --max-pods=110 --pods-per-core=10
• kube-apiserver: --max-requests-inflight=800
• etcd: --quota-backend-bytes=8589934592
• kube-scheduler: --percentage-of-nodes-to-score=50
🔹 集群容量规划
• 控制平面:3节点,8C16G起步
• Worker节点:按应用类型分组
• etcd:SSD磁盘,<2ms延迟
• 网络带宽:10Gbps+集群内互联
🔹 故障自愈最佳实践
1. Pod: livenessProbe自动重启
2. Deployment: ReplicaSet保证副本数
3. Node: kubelet自注册+健康检查
4. Cluster: Cluster Autoscaler增减节点
5. Multi-Cluster: Karmada联邦容灾
🔹 K8s版本升级策略
• 每次只升一个minor版本
• 先升级控制平面,再升级Worker
• 使用kubeadm upgrade plan预检
• 准备回滚方案
• 在staging环境验证后再升级prod