IP 定向灰度发布:ArgoCD + GitLab CLI 方案

IP 定向灰度发布:ArgoCD + GitLab CLI 方案

要实现基于ArgoCD + GitLab CLI的IP定向灰度发布,核心思路是:通过GitLab存储应用配置(基线/灰度版本)、ArgoCD同步K8s资源、NGINX Ingress基于IP范围分流流量,结合GitLab CLI自动化配置变更和发布流程。以下是完整落地方案:

一、核心组件与原理

组件 作用
K8s集群 运行应用和Ingress,提供容器编排能力
NGINX Ingress 基于IP地址范围做流量分流(灰度IP访问v2,其他IP访问v1)
GitLab 存储应用的K8s配置(基线/灰度分支),通过GitLab CLI自动化版本管理
GitLab CLI (glab) 自动化分支创建、配置修改、提交推送,触发ArgoCD同步
ArgoCD 同步GitLab中的配置到K8s集群,管理基线/灰度应用的生命周期
Argo Rollouts(可选) 替代原生Deployment,支持更精细的灰度策略(如按比例发布、自动回滚)

二、环境准备

1. 基础环境部署

Bash 复制代码
# 1. 部署K8s(示例用kind,生产用EKS/AKS/GKE)
kind create cluster --name canary-demo

# 2. 部署ArgoCD
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.11.0/manifests/install.yaml
# 获取ArgoCD密码(admin用户)
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d && echo

# 3. 部署NGINX Ingress
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.0/deploy/static/provider/kind/deploy.yaml
# 等待Ingress就绪
kubectl wait --namespace ingress-nginx --for=condition=ready pod --selector=app.kubernetes.io/component=controller --timeout=120s

# 4. 安装GitLab CLI (glab)
# 参考:https://gitlab.com/gitlab-org/cli/-/blob/main/docs/installation.md
# 配置glab登录(关联你的GitLab仓库)
glab auth login

2. GitLab仓库初始化

创建GitLab仓库(如argocd-canary-demo),并克隆到本地:

Bash 复制代码
git clone https://gitlab.com/你的用户名/argocd-canary-demo.git
cd argocd-canary-demo

三、配置文件编写(Kustomize + ArgoCD)

采用Kustomize分层管理基线/灰度配置,目录结构如下:

Plain 复制代码
argocd-canary-demo/
├── base/                # 基础配置(通用部分)
│   ├── deployment.yaml  # 基础Deployment模板
│   ├── service.yaml     # 基础Service
│   └── kustomization.yaml
├── overlays/            # 环境覆盖层
│   ├── production/      # 基线版本(v1)
│   │   ├── deployment-patch.yaml  # v1镜像/环境变量
│   │   ├── ingress.yaml           # 流量分流核心配置(IP匹配)
│   │   └── kustomization.yaml
│   └── canary/          # 灰度版本(v2)
│       ├── deployment-patch.yaml  # v2镜像/环境变量
│       └── kustomization.yaml
└── argocd/              # ArgoCD Application配置
    ├── production.yaml
    └── canary.yaml

1. 基础配置(base/)

base/deployment.yaml
YAML 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: demo-app
  template:
    metadata:
      labels:
        app: demo-app
    spec:
      containers:
      - name: demo-app
        image: nginx:1.21  # 基础镜像(后续patch修改)
        ports:
        - containerPort: 80
        # 简单的版本标识(页面返回版本信息)
        command: ["/bin/sh", "-c"]
        args: ["echo 'Version: ${VERSION}' > /usr/share/nginx/html/index.html && nginx -g 'daemon off;'"]
base/service.yaml
YAML 复制代码
apiVersion: v1
kind: Service
metadata:
  name: demo-app
spec:
  selector:
    app: demo-app
  ports:
  - port: 80
    targetPort: 80
  type: ClusterIP
base/kustomization.yaml
YAML 复制代码
resources:
- deployment.yaml
- service.yaml

2. 基线版本(overlays/production/)

overlays/production/deployment-patch.yaml(v1版本)
YAML 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-app
spec:
  template:
    spec:
      containers:
      - name: demo-app
        image: nginx:1.21
        env:
        - name: VERSION
          value: "v1"
overlays/production/ingress.yaml(核心:IP分流)

通过NGINX Ingress的server-snippet实现IP正则匹配,灰度IP(如192.168.1.0/2410.0.0.0/24)访问v2,其他访问v1:

YAML 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo-app
  annotations:
    kubernetes.io/ingress.class: "nginx"
    # 核心:IP匹配规则 + 流量分流
    nginx.ingress.kubernetes.io/server-snippet: |
      # 定义灰度IP范围(正则匹配)
      set $is_canary 0;
      if ($remote_addr ~* "^192\.168\.1\.[0-9]+$|^10\.0\.0\.[0-9]+$") {
        set $is_canary 1;
      }
      # 灰度IP转发到canary Service,其他转发到production Service
      if ($is_canary = 1) {
        proxy_pass http://demo-app-canary.demo-app.svc.cluster.local:80;
        break;
      }
spec:
  rules:
  - host: demo-app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: demo-app-production
            port:
              number: 80
overlays/production/kustomization.yaml
YAML 复制代码
bases:
- ../../base
patches:
- deployment-patch.yaml
resources:
- ingress.yaml
nameSuffix: -production  # 资源名后缀:demo-app-production

3. 灰度版本(overlays/canary/)

overlays/canary/deployment-patch.yaml(v2版本)
YAML 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-app
spec:
  replicas: 1  # 灰度副本数减少
  template:
    spec:
      containers:
      - name: demo-app
        image: nginx:1.25
        env:
        - name: VERSION
          value: "v2"
overlays/canary/kustomization.yaml
YAML 复制代码
bases:
- ../../base
patches:
- deployment-patch.yaml
nameSuffix: -canary  # 资源名后缀:demo-app-canary

4. ArgoCD Application配置

argocd/production.yaml(基线应用)
YAML 复制代码
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: demo-app-production
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://gitlab.com/你的用户名/argocd-canary-demo.git  # 替换为你的GitLab仓库
    targetRevision: main
    path: overlays/production
  destination:
    server: https://kubernetes.default.svc
    namespace: demo-app
  syncPolicy:
    automated:
      prune: true  # 自动删除多余资源
      selfHeal: true  # 配置漂移自动修复
    syncOptions:
    - CreateNamespace=true  # 自动创建demo-app命名空间
argocd/canary.yaml(灰度应用)
YAML 复制代码
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: demo-app-canary
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://gitlab.com/你的用户名/argocd-canary-demo.git
    targetRevision: canary  # 灰度分支
    path: overlays/canary
  destination:
    server: https://kubernetes.default.svc
    namespace: demo-app
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true

四、GitLab CLI自动化灰度发布流程

1. 初始化基线版本

Bash 复制代码
# 提交基线配置到main分支
git add .
git commit -m "Init: production v1"
git push origin main

# 应用ArgoCD配置,同步基线版本
kubectl apply -f argocd/production.yaml
argocd app sync demo-app-production

2. 创建灰度分支并修改配置

Bash 复制代码
# 1. 创建灰度分支
glab checkout -b canary main

# 2. (可选)调整灰度IP范围(比如新增172.16.0.0/24)
sed -i 's/^192\.168\.1\.[0-9]+$|^10\.0\.0\.[0-9]+$/^192\.168\.1\.[0-9]+$|^10\.0\.0\.[0-9]+$|^172\.16\.0\.[0-9]+$/' overlays/production/ingress.yaml

# 3. (可选)升级灰度版本镜像
sed -i 's/nginx:1.25/nginx:1.26/' overlays/canary/deployment-patch.yaml

# 4. 提交并推送灰度分支
glab add .
glab commit -m "Canary: add 172.16.0.0/24 IP range, upgrade to v2.1"
glab push origin canary

3. 同步灰度应用

Bash 复制代码
# 应用ArgoCD灰度配置
kubectl apply -f argocd/canary.yaml
# 手动同步(或等待自动同步)
argocd app sync demo-app-canary

4. 验证灰度效果

骤1:获取Ingress IP

c 复制代码
INGRESS_IP=$(kubectl get ingress demo-app-production -n demo-app -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
# Kind环境下Ingress IP为集群节点IP,端口为80
echo "Ingress IP: $INGRESS_IP"

步骤2:模拟不同IP访问

  • 灰度IP(<192.168.1.10>):
c 复制代码
# 用X-Forwarded-For模拟灰度IP(需Ingress配置proxy-real-ip-cidr)
curl -H "Host: demo-app.example.com" -H "X-Forwarded-For: 192.168.1.10" http://$INGRESS_IP
# 预期输出:Version: v2
  • 非灰度IP(<172.17.0.1>):
c 复制代码
curl -H "Host: demo-app.example.com" -H "X-Forwarded-For: 172.17.0.1" http://$INGRESS_IP
# 预期输出:Version: v1

5. 全量发布(灰度验证通过后)

Bash 复制代码
# 1. 合并灰度分支到main
glab checkout main
glab merge canary -m "Merge canary to main: full release v2"
glab push origin main

# 2. 同步基线应用(全量升级为v2)
argocd app sync demo-app-production

# 3. (可选)清理灰度资源
glab branch delete canary -y
argocd app delete demo-app-canary -y
kubectl delete deployment demo-app-canary -n demo-app

五、进阶优化(可选)

1. 集成Argo Rollouts

原生Deployment无法实现"按比例发布、自动回滚",可替换为Argo Rollouts:

YAML 复制代码
# overlays/production/rollout.yaml(替代deployment.yaml)
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: demo-app-production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: demo-app-production
  template: # 同Deployment模板
  strategy:
    canary:
      steps:
      - setWeight: 20  # 先发布20%流量
      - pause: {}      # 暂停发布,手动验证
      - setWeight: 100 # 全量发布

2. GitLab CI/CD自动化

编写.gitlab-ci.yml,实现"提交代码→自动同步ArgoCD→验证→全量发布":

YAML 复制代码
stages:
  - sync-canary
  - validate
  - sync-production

sync-canary:
  stage: sync-canary
  script:
    - glab auth login --token $GITLAB_TOKEN
    - argocd app sync demo-app-canary
  only:
    - canary

validate:
  stage: validate
  script:
    - curl -H "Host: demo-app.example.com" -H "X-Forwarded-For: 192.168.1.10" http://$INGRESS_IP | grep "v2"
  only:
    - canary

sync-production:
  stage: sync-production
  script:
    - glab merge canary main -m "Full release v2"
    - argocd app sync demo-app-production
  only:
    - canary
  when: manual  # 手动触发全量发布

3. IP匹配优化

如果Ingress部署在代理(如CDN、LB)后,需配置真实IP透传:

YAML 复制代码
metadata:
  annotations:
    nginx.ingress.kubernetes.io/proxy-real-ip-cidr: "10.0.0.0/8,192.168.0.0/16"  # 代理IP段
    nginx.ingress.kubernetes.io/use-forwarded-headers: "true"

六、常见问题排查

  1. IP分流不生效

    • 检查NGINX Ingress日志:kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller

    • 确认remote_addr是否为真实客户端IP(代理场景需配置proxy-real-ip-cidr)。

  2. ArgoCD同步失败

    • 检查GitLab仓库权限(ArgoCD需能拉取仓库)。

    • 验证配置文件语法:kubectl apply --dry-run=client -f overlays/production/

  3. 灰度版本无法访问

    • 检查Service/Deployment标签匹配:kubectl get svc -n demo-app

    • 验证Pod状态:kubectl get pods -n demo-app

总结

本方案通过「GitLab存储配置 + GitLab CLI自动化 + ArgoCD同步资源 + NGINX Ingress IP分流」实现了IP定向灰度发布,核心优势:

  • 配置即代码:所有发布配置存储在GitLab,可追溯、可回滚。

  • 自动化:GitLab CLI/CI替代手动操作,减少人为错误。

  • 灵活分流:基于IP范围精准控制灰度群体,支持逐步扩大灰度范围。

  • 可扩展:集成Argo Rollouts可实现更复杂的灰度策略(如按比例、A/B测试)。

相关推荐
乾元2 小时前
红队 / 蓝队:用 AI 自动生成攻击场景并评估防御效果——从“安全演练”到“可计算的网络对抗系统”
运维·网络·人工智能·网络协议·安全·web安全·架构
半路_出家ren2 小时前
Python操作MySQL(详细版)
运维·开发语言·数据库·python·mysql·网络安全·wireshark
lbb 小魔仙2 小时前
eBPF+Linux 6.18:云原生环境下的安全监控与故障排查实战
linux·运维·云原生
Wzx1980122 小时前
go聊天室项目docker部署
运维·docker·容器
2301_767902645 小时前
Zabbix
运维·zabbix
半夏知半秋10 小时前
docker常用指令整理
运维·笔记·后端·学习·docker·容器
逆风水手11 小时前
Ansible自动化运维入门指南
linux·运维·自动化·ansible
tianyuanwo11 小时前
SSH会话管理实战:识别与清理非法连接的完整指南
运维·ssh
小豆子范德萨11 小时前
两台window配置SSH免密登录
运维·ssh