Contents

ArgoCD

ArgoCD

一、ArgoCD介绍

Argo CD 是一个为 Kubernetes 而生的,遵循声明式 GitOps 理念的持续部署工具。Argo CD 可在 Git 存储库更改时自动同步和部署应用程序

工作原理:

Argo CD 遵循 GitOps 模式,使用 Git 仓库作为定义所需应用程序状态的真实来源,Argo CD 支持多种 Kubernetes 清单:

  • kustomize
  • helm charts
  • ksonnet applications
  • jsonnet files
  • Plain directory of YAML/json manifests
  • Any custom config management tool configured as a config management plugin

Argo CD 可在指定的目标环境中自动部署所需的应用程序状态,应用程序部署可以在 Git 提交时跟踪对分支、标签的更新,或固定到清单的指定版本。

Argo CD 是通过一个 Kubernetes 控制器来实现的,它持续 watch 正在运行的应用程序并将当前的实时状态与所需的目标状态( Git 存储库中指定的)进行比较。已经部署的应用程序的实际状态与目标状态有差异,则被认为是 OutOfSync 状态,Argo CD 会报告显示这些差异,同时提供工具来自动或手动将状态同步到期望的目标状态。在 Git 仓库中对期望目标状态所做的任何修改都可以自动应用反馈到指定的目标环境中去。

二、安装ArgoCD

1、helm 安装

helm 安装的argo默认是自签名的https,需要增加配置--insecure

value.yaml

server:
  extraArgs:
    - --insecure
redis:
  image:
    repository: registry.cn-hangzhou.aliyuncs.com/serialt/redis
    
dex:
  image:
    repository: registry.cn-hangzhou.aliyuncs.com/serialt/dex
global:
  image:
    repository: registry.cn-hangzhou.aliyuncs.com/serialt/argocd

安装

helm upgrade --install argocd argo/argo-cd --namespace argocd --version=9.4.11  -f value.yaml

2、配置外部访问

ingress(nginx)

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-redirect: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
  ingressClassName: nginx
  rules:
  - host: argocd.local.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              number: 443
  tls:
  - hosts:
    - argocd.local
    secretName: argocd-secret
EOF

ingress(traefik)

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-ingress
  namespace: argocd
  annotations:
    # 指定使用 traefik 作为控制器
    kubernetes.io/ingress.class: traefik
    # 可选:配置特定路由规则或中间件
    # traefik.ingress.kubernetes.io/router.entrypoints: web
spec:
  rules:
    - host: argocd.local.com # 替换为你的域名
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: argocd-server # K8s Service 名称
                port:
                  number: 80

使用istio

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: argocd
spec:
  gateways:
  - istio-system/gateway-private
  hosts:
  - argocd.local.com
  http:
  - route:
    - destination:
        host: argocd-server.argocd.svc.cluster.local
        port:
          number: 443

改本地的hosts

127.0.0.1  argocd.local.com

查看admin密码

kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

三、app

app的同步策略

  • SYNC POLICY: 同步策略
    • Manual: 手动同步
    • Automatic: 自动同步
      • RRUNE RESOURCES:自动修剪。集群上某个资源在 GitRepo 中找不到对应的配置时,自动删除集群上的该资源
      • SELF HEAL:自愈。因各种原因(如手动修改)集群上资源的实时状态而导致与 GitRepo 不匹配时,自动将实际状态与 GitRepo 的期望状态同步。例如,GitRepo 中定义 pod 的数量为2,你在集群上改为了 3 个 pod,如果你不勾选 self heal。则 ArgoCD 则不会在同步(对一次提交只同步一次),这时 pod 的数量就一直为 3。但你如果勾选了 self heal,ArgoCD 就会轮询去同步,将你的 pod 改为你 GitRepo 里的数量

自动同步仅发生在应用处于 OutOfSync 状态时,ArgoCD 并不会对处于 Synced 或 Error 状态的 Application 执行自动同步,对于 GitRepo 上的一次提交,自动同步仅会执行一次,除非同时启用 Self Heal 机制,启用了自动同步的 Application 不支持 RollBack

可选项

  • SYNC OPTIONS(同步选项)
    • SKIP SCHEMA VALIDATION:是否执行资源规范格式的校验,相当于 ”kubectl apply –validate={true|false}“,默认为 true
    • AUTO-CREATE NAMESPACE:自动创建命名空间。如果部署的应用没有命名空间,则自动创建
    • PRUNE LAST:同步后进行修剪,即其他资源已经部署且转为健康状态后在进行 prune
    • APPLY OUT OF SYNC ONLY:仅对那些处于 OutOfSync 状态的资源执行同步操作。避免大量对象时资源APl消耗
    • RESPECT IGNORE DIFFERENCES:支持忽略差异配置
    • SERVER-SIDE APPLY:部署操作在服务端运行(避免文件过大)
    • PRUNE PROPAGATION POLICY:资源修剪传播策略,默认值使用 foreground 策略,还有 background 和 orphan
    • REPLACE:将使用 kubectl replace 命令同步资源,而非默认的 apply
syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - Validate=false #禁用Kubectl验证
      - CreateNamespace=true # 自动创建命名空间
      - PruneLast=true # 同步后进行修剪
      - ApplyOutOfSyncOnly=true # 仅对那些处于 OutOfSync 状态的资源执行同步操作
      - RespectIgnoreDifferences=true #支持忽路差异配置 (ianoreDifferences)
      - PrunePropagationPolicy=background # 级联删除策略 (backoround. foreground and orphan.)
      - Replace=true # kubectl replace替换

四、rollouts

Argo Rollouts 是一个 Kubernetes Operator 实现,它为 Kubernetes 提供更加高级的部署能力,如蓝绿、金丝雀、金丝雀分析、实验和渐进式交付功能,为云原生应用和服务实现自动化、基于 GitOps 的逐步交付。

支持如下特性:

  • 蓝绿更新策略
  • 金丝雀更新策略
  • 更加细粒度、加权流量拆分
  • 自动回滚
  • 手动判断
  • 可定制的指标查询和业务 KPI 分析
  • Ingress 控制器集成:NGINX,ALB
  • 服务网格集成:Istio,Linkerd,SMI
  • Metrics 指标集成:Prometheus、Wavefront、Kayenta、Web、Kubernetes Jobs、Datadog、New Relic

实现原理

与 Deployment 对象类似,Argo Rollouts 控制器将管理 ReplicaSets 的创建、缩放和删除,这些 ReplicaSet 由 Rollout 资源中的 spec.template 定义,使用与 Deployment 对象相同的 pod 模板。

spec.template 变更时,这会向 Argo Rollouts 控制器发出信号,表示将引入新的 ReplicaSet,控制器将使用 spec.strategy 字段内的策略来确定从旧 ReplicaSet 到新 ReplicaSet 的 rollout 将如何进行,一旦这个新的 ReplicaSet 被放大(可以选择通过一个 Analysis),控制器会将其标记为稳定

如果在 spec.template 从稳定的 ReplicaSet 过渡到新的 ReplicaSet 的过程中发生了另一次变更(即在发布过程中更改了应用程序版本),那么之前的新 ReplicaSet 将缩小,并且控制器将尝试发布反映更新 spec.template 字段的 ReplicasSet。

相关概念

Rollout(滚动)

Rollout 是一个 Kubernetes 的 CRD 资源,相当于 Kubernetes Deployment 对象,在需要更高级的部署或渐进式交付功能的情况下,它旨在取代 Deployment 对象,Rollout 提供了 Kubernetes Deployment 所不能提供的功能。

  • 蓝绿部署
  • 金丝雀部署
  • 与 Ingress 控制器和服务网格整合,实现高级流量路由
  • 与用于蓝绿和金丝雀分析的指标提供者集成
  • 根据成功或失败的指标,自动发布或回滚
渐进式交付

渐进式交付是以受控和渐进的方式发布产品更新的过程,从而降低发布的风险,通常将自动化和指标分析结合起来以驱动更新的自动升级或回滚。

渐进式交付通常被描述为持续交付的演变,将 CI/CD 中的速度优势扩展到部署过程。通过将新版本限制在一部分用户,观察和分析正确的行为,然后逐渐增加更多的流量,同时不断验证其正确性。

部署策略

虽然业界使用了一致的术语来描述各种部署策略,但这些策略的实现往往因工具而异,为了明确 Argo Rollouts 的行为方式,以下是 Argo Rollouts 提供的各种部署策略实施的描述。

  • RollingUpdate(滚动更新):慢慢地用新版本替换旧版本,随着新版本的出现,旧版本会慢慢缩减,以保持应用程序的总数量。这是 Deployment 对象的默认策略。
  • Recreate(重新创建):Recreate 会在启动新版本之前删除旧版本的应用程序,这可确保应用程序的两个版本永远不会同时运行,但在部署期间会出现停机时间。
  • Blue-Green(蓝绿):蓝绿发布(有时称为红黑)指同时部署了新旧两个版本的应用程序,在此期间,只有旧版本的应用程序会收到生产流量,这允许开发人员在将实时流量切换到新版本之前针对新版本进行测试。

安装

[root@node argocd]# kubectl create namespace argo-rollouts
namespace/argo-rollouts created

[root@node argocd]# kubectl apply -n argo-rollouts -f https://ghproxy.com/https://github.com/argoproj/argo-rollouts/releases/download/v1.5.1/install.yaml
# CRD
customresourcedefinition.apiextensions.k8s.io/analysisruns.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/analysistemplates.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/clusteranalysistemplates.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/experiments.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/rollouts.argoproj.io created

# ServiceAccount
serviceaccount/argo-rollouts created

# RBAC: ClusterRole ClusterRoleBinding
clusterrole.rbac.authorization.k8s.io/argo-rollouts created
clusterrole.rbac.authorization.k8s.io/argo-rollouts-aggregate-to-admin created
clusterrole.rbac.authorization.k8s.io/argo-rollouts-aggregate-to-edit created
clusterrole.rbac.authorization.k8s.io/argo-rollouts-aggregate-to-view created
clusterrolebinding.rbac.authorization.k8s.io/argo-rollouts created

# ConfigMap
configmap/argo-rollouts-config created

# Secret
secret/argo-rollouts-notification-secret created

# Service
service/argo-rollouts-metrics created

# Deployment
deployment.apps/argo-rollouts created

查看 Argo Rollouts 服务

[root@node argocd]# kubectl  -n argo-rollouts get pods
NAME                             READY   STATUS    RESTARTS   AGE
argo-rollouts-577dd4d6bc-trp2k   1/1     Running   0          2m35s

五、ApplicationSet

部署应用

创建一个repo:https://gitee.com/serialt/myapp

# app/myapp-deployment.yaml
# nginx-web-deployment.yaml 
apiVersion: apps/v1 
kind: Deployment 
metadata:
 name: nginx-web 
spec:
 replicas: 3
 selector:
   matchLabels:
     app: nginx-web
 template:
   metadata:
     labels:
       app: nginx-web
   spec:
     containers:
     - image: registry.cn-hangzhou.aliyuncs.com/serialt/nginx:1.29.5-alpine
       name: nginx-web 
       ports:
       - containerPort: 80 
 
---
# nginx-web-service.yaml 
apiVersion: v1 
kind: Service 
metadata:
 name: nginx-web
spec:
 ports:
 - port: 80
   targetPort: 80 
   nodePort: 32080 
 type: NodePort 
 selector:
   app: nginx-web

1、创建repo

repo: git@gitee.com:serialt/myapp.git

2、创建application

根据repo创建application,自动sync需要时间,想要快速,可以使用手动sync

ApplicationSet 使用

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: infra-appset
  namespace: dev
  labels:
spec:
  generators:
    - list:
        elements:
          # 👉 Nginx
          - name: nginx
            namespace: nginx
            chart: nginx
            repoURL: https://charts.bitnami.com/bitnami
            version: 15.0.0

          # 👉 Redis
          - name: redis
            namespace: redis
            chart: redis
            repoURL: https://charts.bitnami.com/bitnami
            version: 18.0.0

  template:
    metadata:
      name: '{{name}}-dev'
      labels:
        app.kubernetes.io/name: '{{name}}'

    spec:
      project: default
      source:
        repoURL: '{{repoURL}}'
        chart: '{{chart}}'
        targetRevision: '{{version}}'

        helm:
          releaseName: '{{name}}'
          # 👉 可以在这里统一加参数
          values: |
            replicaCount: 1            

      destination:
        server: https://kubernetes.default.svc
        namespace: '{{namespace}}'

      syncPolicy:
        automated:
          prune: true
          selfHeal: true

        syncOptions:
          - CreateNamespace=true
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: dev
  namespace: argocd
  labels:
    product: dev
    env: dev
spec:
  generators:
    - list:
        elements:
          - chartName: nginx
            chartVersion: "0.0.7"
          - chartName: redis
            chartVersion: "0.0.7"
  template:
    metadata:
      name: '{{chartName}}-dev'
      labels:
        product: dev
        env: dev
    spec:
      project: default
      sources:
        - repoURL: 'http://git.local.com/app/app.git'
          targetRevision: main
          ref: values
        - repoURL: 'harbor.local.com/library'
          chart: '{{chartName}}'
          targetRevision: '{{chartVersion}}'
          helm:
            valueFiles:
              - '$values/dev/values/env.yaml'
              - '$values/dev/values/common.yaml'
              - '$values/dev/values/{{chartName}}.yaml'
      destination:
        name: in-cluster
        namespace: dev
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
          - ApplyOutOfSyncOnly=true
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: dev
  namespace: argocd
  labels:
    product: dev
    env: dev
spec:
  generators:
    - list:
        elements:
          - chartName: test
            chartVersion: "0.1.2"
        #   - chartName: nginx2
        #     chartVersion: "0.1.2"
  template:
    metadata:
      name: '{{chartName}}-dev'
      labels:
        product: dev
        env: dev
    spec:
      project: default
      sources:
        - repoURL: 'https://gitee.com/serialt/kkconf'
          targetRevision: main
          ref: values
        - repoURL: 'https://serialt.github.io/helm-charts'
          chart: '{{chartName}}'
          targetRevision: '{{chartVersion}}'
          helm:
            valueFiles:
              - '$values/nginx1/value.yaml'
      destination:
        name: in-cluster
        namespace: dev
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
          - CreateNamespace=true
          - PruneLast=true
          - ApplyOutOfSyncOnly=true
          - RespectIgnoreDifferences=true
          - ServerSideApply=true
          - SkipDryRunOnMissingResource=true
          - FailOnSharedResource=true

        retry:
          limit: 5
          backoff:
            duration: 5s
            factor: 2
            maxDuration: 3m

argocd sync同步

argocd login <argocd-server-address>:80 --insecure --username admin --password <your-password>


# 1. 先列出由 ApplicationSet 生成的应用(通常名称会有规律,或者通过 Label 筛选)
# 假设 ApplicationSet 生成的应用名称都包含 "my-appset" 前缀
argocd app list | grep my-appset | awk '{print $1}' | xargs -I {} argocd app sync {}

# 2. 或者使用 Label 选择器(如果 ApplicationSet 模板中定义了特定 Label)
argocd app list -l 'app.kubernetes.io/instance=my-appset' -o name | xargs -I {} argocd app sync {}