linux

GitOps 落地实践:ArgoCD + Kustomize 实现声明式基础设施管理(一)

发布时间:18天前热度: 96 ℃评论数:

一、概述

1.1 背景介绍

GitOps 作为云原生时代的运维范式,将 Git 作为基础设施和应用配置的单一事实来源,通过声明式配置和自动化同步机制,实现了配置管理的版本控制、审计追溯和快速回滚。ArgoCD 作为 CNCF 毕业项目,提供了完整的 GitOps 工作流,支持多集群管理、RBAC 权限控制、SSO 集成等企业级特性。结合 Kustomize 的配置管理能力,能够优雅地解决多环境配置差异、敏感信息管理、配置复用等问题。

在传统的 CI/CD 流程中,往往由 CI 工具直接执行 kubectl apply,这种推模式存在权限管理复杂、审计困难、状态漂移等问题。ArgoCD 采用拉模式,由运行在集群内的 Controller 主动从 Git 仓库拉取配置并应用,实现了部署权限的收敛和状态的持续同步。

1.2 技术特点

  • 声明式部署:基于 Kubernetes 资源清单定义期望状态,ArgoCD 自动检测并消除实际状态与期望状态的偏差
  • 多集群管理:单个 ArgoCD 实例可管理数百个 Kubernetes 集群,支持集群级别的 RBAC 和资源隔离
  • 自动同步策略:支持手动同步、自动同步、自动修剪(Prune)、自愈(Self-Heal)等多种策略组合
  • 回滚与审计:完整记录每次同步操作,支持一键回滚到任意历史版本,所有变更可追溯到 Git commit
  • 健康检查:内置对 Deployment、StatefulSet、Service、Ingress 等资源的健康检查,支持自定义健康检查脚本
  • SSO 集成:支持 OAuth2、OIDC、SAML、LDAP 等多种认证方式,可与企业统一认证系统集成
  • 渐进式交付:集成 Argo Rollouts 实现蓝绿部署、金丝雀发布、流量分析等高级发布策略

1.3 适用场景

  • 场景一:多环境配置管理,通过 Kustomize overlay 机制管理 dev/staging/prod 等环境的配置差异,避免重复维护相似配置
  • 场景二:多集群应用分发,使用 ApplicationSet 批量创建 Application,实现应用在多个集群、多个命名空间的标准化部署
  • 场景三:基础设施即代码,将集群基础组件(Ingress Controller、监控栈、日志收集等)以 GitOps 方式管理,实现集群配置的版本化
  • 场景四:合规审计与权限管控,所有变更通过 Git PR 审批,部署操作由 ArgoCD 执行,开发人员无需直接访问生产集群
  • 场景五:灾难恢复,集群配置存储在 Git,可快速在新集群重建全部应用,Recovery Time 从小时级降至分钟级

1.4 环境要求

组件
版本要求
说明
操作系统
Linux 内核 4.x+
推荐 Ubuntu 20.04/22.04 或 RHEL 8+
Kubernetes
1.24+
ArgoCD 2.9+ 要求 Kubernetes 1.24+
kubectl
与 K8s 版本匹配
用于初始安装和手动干预
Git 仓库
GitHub/GitLab/Gitea
支持 HTTPS/SSH 认证,建议配置 Webhook
Kustomize
内置于 kubectl
ArgoCD 内置 Kustomize 5.0+
硬件配置
2C4G(最小)
生产环境推荐 4C8G,HA 部署需 3 副本

二、详细步骤

2.1 准备工作

2.1.1 系统检查

# 验证 Kubernetes 集群状态
kubectl cluster-info
kubectl get nodes
kubectl version --short

# 检查集群资源配额
kubectl top nodes
kubectl describe quota --all-namespaces

# 验证存储类(ArgoCD 需要持久化存储)
kubectl get storageclass

2.1.2 安装依赖

# 创建 ArgoCD 命名空间
kubectl create namespace argocd

# 安装 ArgoCD(使用官方稳定版本)
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# 等待所有组件就绪
kubectl wait --for=condition=available --timeout=600s \
  deployment/argocd-server \
  deployment/argocd-repo-server \
  deployment/argocd-dex-server \
  deployment/argocd-redis \
  -n argocd

# 安装 ArgoCD CLI
VERSION=$(curl -s https://api.github.com/repos/argoproj/argo-cd/releases/latest | grep tag_name | cut -d '"' -f 4)
curl -sSL -o argocd-linux-amd64 "https://github.com/argoproj/argo-cd/releases/download/${VERSION}/argocd-linux-amd64"
sudo install -m 555 argocd-linux-amd64 /usr/local/bin/argocd
rm argocd-linux-amd64

# 验证安装
argocd version

2.2 核心配置

2.2.1 暴露 ArgoCD API Server

# 方式一:LoadBalancer(云环境推荐)
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'

# 方式二:Ingress(内网环境推荐)
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-ingress
  namespace: argocd
  annotations:
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
  ingressClassName: nginx
  rules:
  - host: argocd.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              name: https
  tls:
  - hosts:
    - argocd.example.com
    secretName: argocd-server-tls
EOF

# 方式三:端口转发(开发测试)
kubectl port-forward svc/argocd-server -n argocd 8080:443

说明:生产环境建议使用 Ingress + TLS 证书,避免暴露 LoadBalancer 公网 IP。SSL Passthrough 保证端到端加密,ArgoCD Server 使用自签名证书或配置自定义证书。

2.2.2 初始化 ArgoCD

# 获取初始 admin 密码
ARGOCD_PASSWORD=$(kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath="{.data.password}" | base64 -d)
echo "ArgoCD admin password: ${ARGOCD_PASSWORD}"

# 登录 ArgoCD
argocd login argocd.example.com --username admin --password "${ARGOCD_PASSWORD}" --grpc-web

# 修改 admin 密码
argocd account update-password

# 删除初始密码 Secret(安全加固)
kubectl -n argocd delete secret argocd-initial-admin-secret

2.2.3 配置 Git 仓库凭证

# 方式一:HTTPS 认证(使用 Personal Access Token)
argocd repo add https://github.com/your-org/your-repo.git \
  --username git \
  --password ghp_xxxxxxxxxxxxxxxxxxxx \
  --name my-repo

# 方式二:SSH 认证(推荐)
# 生成 SSH 密钥对
ssh-keygen -t ed25519 -C "argocd@example.com" -f ~/.ssh/argocd_ed25519 -N ""

# 将公钥添加到 Git 仓库的 Deploy Keys
cat ~/.ssh/argocd_ed25519.pub

# 添加私钥到 ArgoCD
argocd repo add git@github.com:your-org/your-repo.git \
  --ssh-private-key-path ~/.ssh/argocd_ed25519 \
  --name my-repo

# 验证仓库连接
argocd repo list

参数说明

  • --insecure-skip-server-verification:跳过 Git 服务器 TLS 验证(自签名证书场景)
  • --proxy:配置代理服务器访问外部 Git 仓库
  • --enable-lfs:启用 Git LFS 支持大文件

2.3 启动和验证

2.3.1 创建 Application

# application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
  namespace: argocd
  # Finalizer 确保删除 Application 时同步删除已部署资源
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  source:
    # Git 仓库地址
    repoURL: https://github.com/argoproj/argocd-example-apps.git
    targetRevision: HEAD
    path: guestbook
  destination:
    server: https://kubernetes.default.svc
    namespace: default
  syncPolicy:
    automated:
      prune: true      # 自动删除 Git 中不存在的资源
      selfHeal: true   # 自动修复手动修改
      allowEmpty: false
    syncOptions:
    - CreateNamespace=true  # 自动创建目标命名空间
    retry:
      limit: 5
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m
# 应用配置
kubectl apply -f application.yaml

# 查看 Application 状态
argocd app get guestbook

# 查看同步历史
argocd app history guestbook

# 手动触发同步
argocd app sync guestbook

# 查看实时日志
argocd app logs guestbook --follow

2.3.2 功能验证

# 验证 Application 健康状态
argocd app list
# 预期输出:
# NAME        CLUSTER                         NAMESPACE  PROJECT  STATUS  HEALTH   SYNCPOLICY
# guestbook   https://kubernetes.default.svc  default    default  Synced  Healthy  Auto-Prune

# 验证资源同步状态
kubectl get all -n default -l app.kubernetes.io/instance=guestbook

# 测试自愈功能(手动修改资源)
kubectl scale deployment guestbook-ui -n default --replicas=5
# 等待 3 秒,ArgoCD 自动恢复副本数

# 测试修剪功能(从 Git 删除资源)
# 1. 从 Git 仓库删除某个 YAML 文件并提交
# 2. 观察 ArgoCD 自动删除对应资源
argocd app wait guestbook --health

三、示例代码和配置

3.1 完整配置示例

3.1.1 Kustomize 多环境配置结构

# 仓库目录结构
├── base/
│   ├── kustomization.yaml
│   ├── deployment.yaml
│   ├── service.yaml
│   └── configmap.yaml
├── overlays/
│   ├── dev/
│   │   ├── kustomization.yaml
│   │   ├── replica-patch.yaml
│   │   └── configmap-patch.yaml
│   ├── staging/
│   │   ├── kustomization.yaml
│   │   └── resources-patch.yaml
│   └── prod/
│       ├── kustomization.yaml
│       ├── replica-patch.yaml
│       ├── hpa.yaml
│       └── pdb.yaml
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- deployment.yaml
- service.yaml
- configmap.yaml

commonLabels:
  app: myapp
  managed-by: argocd

namespace: myapp

images:
- name: myapp
  newName: registry.example.com/myapp
  newTag: latest
# base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: myapp
        ports:
        - containerPort: 8080
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 512Mi
        envFrom:
        - configMapRef:
            name: myapp-config
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5
# overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

namespace: myapp-prod

bases:
- ../../base

patchesStrategicMerge:
- replica-patch.yaml

resources:
- hpa.yaml
- pdb.yaml

images:
- name: myapp
  newTag: v1.2.3  # 生产环境固定版本

configMapGenerator:
- name: myapp-config
  behavior: merge
  literals:
  - LOG_LEVEL=info
  - ENVIRONMENT=production
  - DB_POOL_SIZE=50
# overlays/prod/replica-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 5
  template:
    spec:
      containers:
      - name: myapp
        resources:
          requests:
            cpu: 500m
            memory: 1Gi
          limits:
            cpu: 2000m
            memory: 4Gi
# overlays/prod/hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: myapp
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp
  minReplicas: 5
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 50
        periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
      - type: Percent
        value: 100
        periodSeconds: 30
      - type: Pods
        value: 4
        periodSeconds: 30
      selectPolicy: Max

3.1.2 ApplicationSet 批量管理

# applicationset.yaml - 多集群部署
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: myapp-multi-cluster
  namespace: argocd
spec:
  generators:
  - matrix:
      generators:
      - git:
          repoURL: https://github.com/your-org/your-repo.git
          revision: HEAD
          directories:
          - path: overlays/*
      - clusters:
          selector:
            matchLabels:
              environment: production
  template:
    metadata:
      name: 'myapp-{{path.basename}}-{{name}}'
    spec:
      project: default
      source:
        repoURL: https://github.com/your-org/your-repo.git
        targetRevision: HEAD
        path: '{{path}}'
      destination:
        server: '{{server}}'
        namespace: 'myapp-{{path.basename}}'
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
        - CreateNamespace=true

3.2 实际应用案例

案例一:配置敏感信息管理

场景描述:使用 Sealed Secrets 或 External Secrets Operator 管理数据库密码、API Key 等敏感信息,避免明文存储在 Git 仓库。

实现代码

# 安装 Sealed Secrets Controller
kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.24.0/controller.yaml

# 创建 Secret 并加密
echo -n 'my-db-password' | kubectl create secret generic db-credentials \
  --dry-run=client \
  --from-file=password=/dev/stdin \
  -o yaml | \
kubeseal -o yaml > sealed-secret.yaml

# sealed-secret.yaml(可安全提交到 Git)
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  name: db-credentials
  namespace: default
spec:
  encryptedData:
    password: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq...
  template:
    metadata:
      name: db-credentials
      namespace: default
    type: Opaque

运行结果

# ArgoCD 同步后自动解密为 Secret
kubectl get secret db-credentials -o jsonpath='{.data.password}' | base64 -d
# 输出:my-db-password

案例二:RBAC 权限配置

场景描述:为开发团队配置只读权限,仅允许查看 dev 环境应用状态,禁止同步操作;为运维团队配置全部环境的管理权限。

实现步骤

  1. 创建 AppProject 隔离资源
# project-dev.yaml
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: dev-project
  namespace: argocd
spec:
  description: Development environment project
  sourceRepos:
  - 'https://github.com/your-org/*'
  destinations:
  - namespace: 'dev-*'
    server: https://kubernetes.default.svc
  clusterResourceWhitelist:
  - group: ''
    kind: Namespace
  namespaceResourceWhitelist:
  - group: 'apps'
    kind: Deployment
  - group: ''
    kind: Service
  - group: ''
    kind: ConfigMap
  roles:
  - name: developer
    description: Read-only access to dev apps
    policies:
    - p, proj:dev-project:developer, applications, get, dev-project/*, allow
    - p, proj:dev-project:developer, logs, get, dev-project/*, allow
    groups:
    - dev-team
  1. 配置 ArgoCD RBAC
# argocd-rbac-cm ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-rbac-cm
  namespace: argocd
data:
  policy.default: role:readonly
  policy.csv: |
    # 运维团队全部权限
    g, ops-team, role:admin

    # 开发团队限制权限
    p, role:developer, applications, get, */*, allow
    p, role:developer, applications, sync, dev-project/*, allow
    p, role:developer, logs, get, */*, allow
    g, dev-team, role:developer

    # 禁止删除生产应用
    p, role:developer, applications, delete, prod-project/*, deny
  1. 集成 OIDC SSO(以 Keycloak 为例)
# argocd-cm ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  url: https://argocd.example.com
  oidc.config: |
    name: Keycloak
    issuer: https://keycloak.example.com/realms/master
    clientID: argocd
    clientSecret: $oidc.keycloak.clientSecret
    requestedScopes:
    - openid
    - profile
    - email
    - groups


手机扫码访问