ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

AI云原生实战20-还在手动kubectl apply?ArgoCD GitOps让AI部署全自动

AI云原生实战20-还在手动kubectl apply?ArgoCD GitOps让AI部署全自动 本文较长5000字建议先收藏再阅读。如果你也在被改个模型版本就要SSH进服务器敲一堆kubectl命令这件事折磨这篇文章就是为你写的。目录一、一个深夜事故让我彻底告别手动部署二、GitOps不是又一个DevOps新词是救命的范式2.1 手动部署 vs GitOps一张图看懂区别2.2 GitOps四大原则三、ArgoCD架构它不是简单的自动kubectl四、AI应用的GitOps全流程实战4.1 整体流程4.2 镜像Tag自动更新不用再手动改YAML里的版本号五、ArgoCD Application把AI服务交给Git托管5.1 基础Application CRD5.2 AppProject多项目多环境隔离六、多环境管理App of Apps模式6.1 为什么需要App of Apps七、同步策略详解Automated Prune Self-Heal推荐的同步策略配置八、回滚从慌得一批到淡定喝茶8.1 传统回滚的痛苦8.2 GitOps回滚一个git revert搞定九、完整YAML配置开箱即用的AI推理服务GitOps套件9.1 AppProject9.2 ApplicationAI推理服务9.3 Helm values.yaml环境配置9.4 Helm Chart的ConfigMap模板十、常见踩坑与最佳实践10.1 ⚠️ 坑1Secret管理的噩梦10.2 ⚠️ 坑2selfHeal: true DevOps工程师 死循环10.3 最佳实践监控GitOps健康状态一、一个深夜事故让我彻底告别手动部署凌晨2点AI推理服务突然挂了。排查发现白天同事手快把GPU节点的nodeSelector改成了cpu-only模型推理直接拿不到GPU资源QPS从8000跌到0。更离谱的是——这是第3次了。每次出事我们都要翻集群里的kubectl apply历史记录猜测到底是谁在哪个时间点改了什么东西。⚠️如果你还在用kubectl apply -f deployment.yaml手动部署那么你的集群状态就是一个薛定谔的黑箱——你永远不知道当前集群实际运行的和你脑子里以为的是不是同一个东西。那次事故之后我们全量切了 ArgoCD GitOps。半年过去了我再也没半夜爬起来修过被人改坏了的配置。今天这篇文章就是我们的完整实战复盘。二、GitOps不是又一个DevOps新词是救命的范式2.1 手动部署 vs GitOps一张图看懂区别先别急着看YAML我们用Mermaid画个对比图你就明白GitOps到底改变了什么flowchart LR subgraph 传统Push模式[❌ 传统 Push 部署] Dev1[‍ 开发者A] --|kubectl apply| K8s[☸️ K8s 集群] Dev2[‍ 开发者B] --|helm install| K8s Ops[ 运维] --|kubectl edit| K8s K8s -- Chaos[ 实际状态 薛定谔的黑箱] end subgraph GitOps模式[✅ GitOps Pull 模式] Git[ Git 仓库br/声明式配置的唯一真相源] --|Webhook / 定时轮询| ArgoCD[ Argo CD] ArgoCD --|Pull Sync| K8s2[☸️ K8s 集群] Git -.-|只有 Git 能改变集群| K8s2 endPush模式的致命问题N个人用N种方式往集群里灌配置谁改了什么、什么时候改的、为什么改全部不可追溯。GitOps的核心理念Git仓库就是集群的唯一真相源Single Source of Truth。ArgoCD作为一个运行在集群内的协调器持续不断地把Git里想要的状态同步到集群里。2.2 GitOps四大原则Weaveworks当年提出GitOps时定义了四条铁律原则含义对应实践声明式用YAML/JSON描述期望状态不说怎么做只说要什么K8s Manifest / Helm / Kustomize版本控制所有配置存在Git里改配置提PRGitHub / GitLab 仓库自动同步Agent自动拉取变更并应用到集群ArgoCD / FluxCD持续协调不断对比期望vs实际偏离了就拉回来Self-Heal / Drift Detection一句话总结GitOps就是把Git变成kubectl。你不再敲命令你只需要改Git里的YAML文件剩下的事情ArgoCD帮你搞定。三、ArgoCD架构它不是简单的自动kubectl很多人以为ArgoCD就是一个定时kubectl apply的cron job大错特错。ArgoCD内部有四个核心组件各司其职flowchart TB subgraph ArgoCD[ Argo CD 核心架构] APIServer[ API Serverbr/gRPC REST WebUI] RepoServer[ Repo Serverbr/读取Git/Helm仓库br/生成Manifest] AppController[ Application Controllerbr/核心协调循环br/对比期望 vs 实际] Redis[ Redis Cachebr/缓存Manifestbr/加速同步] Web[ ArgoCD Web UI] -- APIServer CLI[ argocd CLI] -- APIServer APIServer -- AppController AppController --|拉取仓库内容| RepoServer RepoServer --|缓存| Redis RepoServer --|git fetch| GitRepo[ 外部 Git 仓库] AppController --|kubectl apply / diff| K8sAPI[☸️ K8s API Server] end style ArgoCD fill:#1a1a2e,stroke:#16213e,color:#e2e2e2四个组件各自干嘛API Server对外提供gRPC/REST接口也是Web UI和CLI的后端。你浏览器里看到的那个漂亮的Dashboard背后就是它。Repo Server负责从Git仓库拉代码执行Helm/Kustomize/Ksonnet等模板渲染生成最终的Kubernetes Manifest。Application Controller核心中的核心。它运行一个死循环每3分钟可配置对比Git里的期望状态和集群里的实际状态不一致就触发Sync。Redis缓存Repo Server生成的Manifest避免每次同步都重新渲染。重点理解ArgoCD是Pull模式不是Push模式。Jenkins/GitHub Actions是我推配置到集群ArgoCD是集群内部拉取配置。这意味着ArgoCD天然不需要集群外部访问权限安全得多。四、AI应用的GitOps全流程实战4.1 整体流程AI应用的部署比普通Web服务复杂一些——涉及模型版本、GPU调度、推理服务配置等。但GitOps让这一切变得可控。flowchart LR subgraph Dev[‍ 开发阶段] CodeRepo[ 代码仓库br/模型代码 Dockerfile] CI[⚙️ GitHub Actions CIbr/1. 训练/测试模型br/2. 构建Docker镜像br/3. 推送镜像br/4. 更新配置仓库] end subgraph Config[ 配置仓库GitOps Repo] ConfigRepo[ config-repobr/├── apps/br/│ └── ai-inference/br/│ ├── Chart.yamlbr/│ ├── values.yamlbr/│ └── templates/br/├── environments/br/│ ├── dev/br/│ ├── staging/br/│ └── prod/] end subgraph Deploy[ 部署阶段] ArgoCD2[ Argo CDbr/1. 检测配置变更br/2. 渲染Helm Chartbr/3. Diff对比br/4. Sync同步] Cluster[☸️ K8s 集群br/├── GPU Node Poolbr/│ ├── 模型推理服务br/│ └── 向量数据库br/├── CPU Node Poolbr/│ ├── API Gatewaybr/│ └── 预处理服务br/└── Monitoringbr/ ├── Prometheusbr/ └── Grafana] end CodeRepo -- CI CI --|更新镜像Tag| ConfigRepo ConfigRepo --|Webhook| ArgoCD2 ArgoCD2 --|Sync| Cluster4.2 镜像Tag自动更新不用再手动改YAML里的版本号这是最让人头疼的部分。AI模型迭代快每周可能发2-3个新版本。手动改image: my-model:v1.2.3这种操作太蠢了。我们的方案GitHub Actions在构建完镜像后自动更新配置仓库里的镜像Tag。# .github/workflows/deploy-model.yml name: Build Push Model Image on: push: branches: [main] paths: - models/** - src/inference/** jobs: build-and-update: runs-on: ubuntu-latest steps: - name: Checkout Code uses: actions/checkoutv4 - name: Build Docker Image run: | IMAGE_TAG$(date %Y%m%d-%H%M%S)-$(git rev-parse --short HEAD) docker build -t registry.example.com/ai-inference:${IMAGE_TAG} . docker push registry.example.com/ai-inference:${IMAGE_TAG} echo IMAGE_TAG${IMAGE_TAG} $GITHUB_ENV - name: Update GitOps Config Repo uses: actions/checkoutv4 with: repository: myorg/gitops-config token: ${{ secrets.GITOPS_PAT }} path: gitops-config - name: Update Image Tag run: | cd gitops-config # 用 yq 更新 values.yaml 中的镜像Tag yq eval .image.tag ${{ env.IMAGE_TAG }} \ environments/prod/ai-inference-values.yaml -i git config user.name ci-bot git config user.email ci-botexample.com git add . git commit -m chore: bump ai-inference to ${{ env.IMAGE_TAG }} git push⚠️千万不要在CI里直接kubectl apply。虽然很多教程这么做但一旦CI Pipeline获得了集群写入权限你的攻击面就扩大了一个数量级。正确做法是CI只改Git仓库ArgoCD来完成部署。五、ArgoCD Application把AI服务交给Git托管5.1 基础Application CRDArgoCD通过Kubernetes CRD来管理应用。最核心的就是Application资源# application-ai-inference.yaml apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: ai-inference-prod namespace: argocd finalizers: - resources-finalizer.argocd.argoproj.io # ⚠️ 必须加否则删除Application时不会级联删除K8s资源 spec: # 项目多租户隔离 project: ai-platform # 同步策略 syncPolicy: automated: prune: true # 删除Git中已移除的资源 selfHeal: true # 自动修复集群中的手动变更 syncOptions: - CreateNamespacetrue # 自动创建不存在的Namespace - PruneLasttrue # 先创建新资源再删除旧资源零停机 - ApplyOutOfSyncOnlytrue # 只同步有差异的资源加速同步 # 数据源 source: repoURL: https://github.com/myorg/gitops-config.git targetRevision: main path: environments/prod/ai-inference helm: # ⚠️ values 直接写在这里可以但更推荐用 valueFiles 引用外部文件 valueFiles: - values.yaml - values-prod.yaml values: | # 直接覆盖的简单值 replicaCount: 3 resources: limits: nvidia.com/gpu: 2 requests: nvidia.com/gpu: 2 # 目标集群和命名空间 destination: server: https://kubernetes.default.svc # 本集群 namespace: ai-inference-prod # 健康检查策略可选 ignoreDifferences: # 忽略某些字段的差异避免无意义的OutOfSync - group: apps kind: Deployment jsonPointers: - /spec/replicas # HPA会动态修改replicas忽略这个差异 - group: kind: Service jsonPointers: - /spec/clusterIP # 集群IP是自动分配的忽略⚠️finalizers这行绝对不能省。如果你删除了Application但没有加resources-finalizerArgoCD会认为这个应用我不要了但Deployment/Service/PVC这些K8s资源会变成孤儿留在集群里。久而久之你的集群就是一座垃圾山。5.2 AppProject多项目多环境隔离在AI平台场景里你可能同时有推荐模型、“NLP模型”、CV模型等多个团队。用AppProject做权限隔离# appproject-ai-platform.yaml apiVersion: argoproj.io/v1alpha1 kind: AppProject metadata: name: ai-platform namespace: argocd spec: description: AI Platform - All Model Inference Services # 允许的源仓库 sourceRepos: - https://github.com/myorg/gitops-config.git # 允许的目标集群和命名空间 destinations: - namespace: ai-* # 通配符所有 ai- 开头的命名空间 server: https://kubernetes.default.svc - namespace: model-* server: https://kubernetes.default.svc # 允许的资源类型安全白名单 clusterResourceWhitelist: - group: kind: Namespace - group: rbac.authorization.k8s.io kind: ClusterRole - group: rbac.authorization.k8s.io kind: ClusterRoleBinding # 命名空间级别的资源白名单 namespaceResourceWhitelist: - group: apps kind: Deployment - group: apps kind: StatefulSet - group: kind: Service - group: kind: ConfigMap - group: kind: Secret - group: networking.k8s.io kind: Ingress - group: autoscaling kind: HorizontalPodAutoscaler - group: batch kind: Job - group: batch kind: CronJob # 角色权限RBAC roles: - name: ml-engineer description: ML工程师可查看和同步不可创建/删除Application policies: - p, proj:ai-platform:ml-engineer, applications, get, ai-platform/*, allow - p, proj:ai-platform:ml-engineer, applications, sync, ai-platform/*, allow groups: - ml-team - name: platform-admin description: 平台管理员全部权限 policies: - p, proj:ai-platform:platform-admin, applications, *, ai-platform/*, allow groups: - platform-ops六、多环境管理App of Apps模式6.1 为什么需要App of Apps当你只有1个Application时手动kubectl apply还行。但当你有dev/staging/prod三个环境每个环境又有10个微服务那就是30个Application CRD。手动管理不可能的。App of Apps模式用一个根Application来管理所有子Application。所有子Application的定义也都存在Git里。# root-app.yaml —— 所有的入口 apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: root-app namespace: argocd spec: project: ai-platform source: repoURL: https://github.com/myorg/gitops-config.git targetRevision: main path: app-of-apps/ directory: recurse: true # 递归扫描子目录 destination: server: https://kubernetes.default.svc namespace: argocd syncPolicy: automated: prune: true selfHeal: true然后你的Git目录结构长这样gitops-config/ └── app-of-apps/ ├── dev/ │ ├── ai-inference-dev.yaml # Application CRD指向 dev 环境 │ ├── ai-preprocess-dev.yaml │ └── vector-db-dev.yaml ├── staging/ │ ├── ai-inference-staging.yaml │ └── ... └── prod/ ├── ai-inference-prod.yaml └── ...每个子Application的YAML# app-of-apps/prod/ai-inference-prod.yaml apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: ai-inference-prod namespace: argocd spec: project: ai-platform source: repoURL: https://github.com/myorg/gitops-config.git targetRevision: main path: charts/ai-inference helm: valueFiles: - values.yaml # 公共默认值 - ../../environments/prod/values-prod.yaml # 环境覆盖值 destination: server: https://kubernetes.default.svc namespace: ai-inference-prod syncPolicy: automated: prune: true selfHeal: true这个模式的美妙之处新增一个服务只需在Git里新建一个Application YAML。ArgoCD在3分钟内自动发现并开始同步。你连ArgoCD的Web UI都不用打开。七、同步策略详解Automated Prune Self-HealArgoCD提供了三种同步模式很多人没搞清楚就瞎配。模式行为适用场景Manual手动只在Web UI点Sync按钮时才同步生产环境金丝雀发布阶段Automated自动Git变更后自动同步Dev/Staging环境Automated Prune Self-Heal自动同步 自动删除Git中已移除的资源 自动修复手动变更生产环境配合Git审批流程推荐的同步策略配置syncPolicy: automated: prune: true # Git里删了文件 → ArgoCD删集群资源 selfHeal: true # 有人手动改了集群 → ArgoCD自动改回来 syncOptions: - CreateNamespacetrue - PruneLasttrue # 先建新的再删旧的 - ApplyOutOfSyncOnlytrue # 只同步有Diff的资源 - RespectIgnoreDifferencestrue # 尊重 Application 里配的 ignoreDifferences retry: limit: 5 # 同步失败重试5次 backoff: duration: 5s # 初始等待5秒 factor: 2 # 指数退避5s → 10s → 20s → 40s → 80s maxDuration: 3m # 单次重试最大间隔3分钟⚠️生产环境用selfHeal: true的前提是你必须有一套严格的Git审批流程至少需要Code Review Merge Request审批。否则如果有人恶意把replicaCount: 10改成replicaCount: 0并合入main分支ArgoCD会忠实地把集群里所有Pod杀掉。Git的审批流程是GitOps安全性的最后一道防线。八、回滚从慌得一批到淡定喝茶8.1 传统回滚的痛苦# 手动回滚你需要记住这些命令 kubectl rollout undo deployment/ai-inference --to-revision15 # 等一下...revision 15 是什么来着 kubectl rollout history deployment/ai-inference # 哦对是新模型发布前的版本 # 等等ConfigMap也改了只回滚Deployment不够 # 还有那个HPA的minReplicas上次是谁调的来着8.2 GitOps回滚一个git revert搞定# GitOps回滚整个世界都安静了 git log --oneline -5 # a1b2c3d chore: bump ai-inference to 20260710-120000-abc1234 ← 有问题的版本 # e4f5g6h feat: update model serving config # ... git revert a1b2c3d --no-edit git push origin main # 然后你就可以去泡杯咖啡了 # ArgoCD 3分钟内自动检测到变更把集群恢复到上一个正确状态整个过程就两步git revert有问题的commitgit push剩下的ArgoCD全自动搞定。不再需要记住revision号不再担心只回滚了Deployment忘了ConfigMap因为所有变更历史都在Git里一次revert搞定一切。进阶技巧ArgoCD Web UI里可以直观看到每次Sync的历史记录包括确切的时间、变更内容、Diff对比。出问题时直接截图发给同事“你看这次Sync把GPU nodeSelector删了谁干的”九、完整YAML配置开箱即用的AI推理服务GitOps套件下面是生产环境实测可用的完整配置包含Application AppProject Helm Chart。9.1 AppProjectapiVersion: argoproj.io/v1alpha1 kind: AppProject metadata: name: ai-platform namespace: argocd spec: description: AI推理平台 - 模型服务GitOps管理 sourceRepos: - https://github.com/myorg/gitops-config.git destinations: - namespace: ai-* server: https://kubernetes.default.svc - namespace: model-* server: https://kubernetes.default.svc namespaceResourceWhitelist: - group: apps kind: Deployment - group: apps kind: StatefulSet - group: kind: Service - group: kind: ConfigMap - group: kind: Secret - group: networking.k8s.io kind: Ingress - group: autoscaling kind: HorizontalPodAutoscaler9.2 ApplicationAI推理服务apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: ai-inference-prod namespace: argocd finalizers: - resources-finalizer.argocd.argoproj.io spec: project: ai-platform source: repoURL: https://github.com/myorg/gitops-config.git targetRevision: main path: charts/ai-inference helm: valueFiles: - values.yaml - ../../environments/prod/ai-inference-values.yaml values: | image: repository: registry.example.com/ai-inference tag: 20260710-120000-abc1234 gpu: enabled: true count: 2 autoscaling: enabled: true minReplicas: 3 maxReplicas: 20 targetCPUUtilizationPercentage: 70 targetMemoryUtilizationPercentage: 80 destination: server: https://kubernetes.default.svc namespace: ai-inference-prod syncPolicy: automated: prune: true selfHeal: true syncOptions: - CreateNamespacetrue - PruneLasttrue - ApplyOutOfSyncOnlytrue - RespectIgnoreDifferencestrue retry: limit: 5 backoff: duration: 5s factor: 2 maxDuration: 3m ignoreDifferences: - group: apps kind: Deployment jsonPointers: - /spec/replicas9.3 Helm values.yaml环境配置# environments/prod/ai-inference-values.yaml replicaCount: 3 image: repository: registry.example.com/ai-inference tag: 20260710-120000-abc1234 pullPolicy: IfNotPresent service: type: ClusterIP port: 8080 grpcPort: 9090 resources: limits: cpu: 8 memory: 32Gi nvidia.com/gpu: 2 requests: cpu: 4 memory: 16Gi nvidia.com/gpu: 2 autoscaling: enabled: true minReplicas: 3 maxReplicas: 20 targetCPUUtilizationPercentage: 70 targetMemoryUtilizationPercentage: 80 # 模型配置 model: name: gpt-inference-v3 path: /models/gpt-inference-v3 preload: true maxBatchSize: 32 maxSequenceLength: 8192 # 节点亲和性 affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: node-type operator: In values: - gpu-a100 - key: topology.kubernetes.io/zone operator: In values: - zone-a - zone-b # 健康检查 livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 120 # 模型加载需要时间 periodSeconds: 30 timeoutSeconds: 10 failureThreshold: 5 readinessProbe: httpGet: path: /ready port: 8080 initialDelaySeconds: 30 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 # 监控 monitoring: prometheus: enabled: true path: /metrics port: 9090 # ConfigMap通过文件生成 config: modelServer: maxConcurrentRequests: 100 requestTimeout: 60s enableDynamicBatching: true logging: level: info format: json9.4 Helm Chart的ConfigMap模板# charts/ai-inference/templates/configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: {{ include ai-inference.fullname . }}-config labels: {{- include ai-inference.labels . | nindent 4 }} data: model-server.yaml: | max_concurrent_requests: {{ .Values.config.modelServer.maxConcurrentRequests }} request_timeout: {{ .Values.config.modelServer.requestTimeout }} enable_dynamic_batching: {{ .Values.config.modelServer.enableDynamicBatching }} model: name: {{ .Values.model.name }} path: {{ .Values.model.path }} preload: {{ .Values.model.preload }} max_batch_size: {{ .Values.model.maxBatchSize }} max_sequence_length: {{ .Values.model.maxSequenceLength }} gpu: count: {{ .Values.gpu.count }} logging.yaml: | level: {{ .Values.config.logging.level }} format: {{ .Values.config.logging.format }}十、常见踩坑与最佳实践10.1 ⚠️ 坑1Secret管理的噩梦ArgoCD默认会把Secret明文存在Git里这显然不行。解决方案用External Secrets OperatorESO或Sealed Secrets。# 不要这样写Secret明文在Git里 apiVersion: v1 kind: Secret metadata: name: model-api-key data: api-key: bXktc3VwZXItc2VjcmV0LWtleQ # ← 任何人都能看到 # 正确做法用External Secrets apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: model-api-key spec: refreshInterval: 1h secretStoreRef: name: vault-backend kind: SecretStore target: name: model-api-key data: - secretKey: api-key remoteRef: key: kv/ai-platform/model-api-key10.2 ⚠️ 坑2selfHeal: true DevOps工程师 死循环# 场景 # 1. 你紧急手动 kubectl edit deployment 改了replicas # 2. ArgoCD检测到差异3秒后改回去 # 3. 你又手动改 # 4. ArgoCD又改回去 # ...无限循环解决方案紧急情况用ArgoCD的Pause Sync功能或者在ArgoCD Web UI里直接改Application的参数后再点Sync。10.3 最佳实践监控GitOps健康状态在Prometheus里配Alert规则# prometheus-rules/argocd-alerts.yaml groups: - name: argocd rules: - alert: ArgoCDAppOutOfSync expr: argocd_app_sync_status{health_status!Healthy} 1 for: 10m labels: severity: warning annotations: summary: Application {{ $labels.name }} is Out of Sync description: Application {{ $labels.name }} has been out of sync for more than 10 minutes. - alert: ArgoCDAppDegraded expr: argocd_app_info{health_statusDegraded} 1 for: 5m labels: severity: critical annotations: summary: Application {{ $labels.name }} is Degraded description: Application {{ $labels.name }} health status is Degraded. Check ArgoCD dashboard immediately.十一、总结GitOps不是银弹但在AI应用部署这个领域它解决了一个核心问题让部署过程可追溯、可审计、可回滚。回顾一下我们改了什么Before手动PushAfterGitOps Pull3个人直接用kubectl改集群所有人只能通过改Git来改集群半夜故障翻了20分钟日志才找到谁改的一个git log秒查回滚靠记忆翻revision号git revert搞定一切Dev/Staging/Prod环境配置不一致同一份Git不同values文件改配置没有代码审查所有变更必须提PR至少一人Review⚠️最后必须强调的一点GitOps的底线是Git的安全。如果你的Git仓库被攻破攻击者可以随意修改集群配置ArgoCD会忠实地帮你执行。所以——开启Branch Protection强制Code Review敏感信息用External SecretsGit仓库开启审计日志 文末三件套 推荐阅读ArgoCD官方文档 —— 最好的入门资料没有之一GitOps Principles (Weaveworks) —— GitOps理念的源头ArgoCD Best Practices —— 官方最佳实践照着做就行️ 实战项目开源ArgoCD Autopilot —— 一键搭建App of Apps结构ArgoCD Image Updater —— 自动更新镜像Tag省去GitHub Actions那一步External Secrets Operator —— 与ArgoCD配合管理敏感信息 互动话题你们团队用ArgoCD踩过什么坑有没有出现过selfHeal: true把紧急修复治好的惨案评论区聊聊如果这篇文章对你有帮助点个赞收藏一下下次部署AI应用的时候翻出来照着配就行。标签#GitOps #ArgoCD #持续交付 #Helm #CI/CD #自动化部署 #K8s
返回列表