ArgoCD
- argoproj/argo-cd 是什么?
- 声明式 K8S 持续集成/CD 服务/控制器
- GitOps
- 有 直观的 WebUI 可供管理和问题排查
- 支持多集群、统一登录、权限管理
- DEMO
- 特性
- 自动化部署应用到指定环境
- 支持多种配置 - Kustomize, Helm, Ksonnet, Jsonnet, plain-YAML
- 多集群
- 无需部署 Agent
- SSO - OIDC, OAuth2, LDAP, SAML 2.0, GitHub, GitLab, Microsoft, LinkedIn
- 多租户,RBAC
- 回滚
- 应用资源健康状态
- 检测未同步情况
- 自动或手动同步
- Web UI 查看实时情况和应用活动
- CLI 用于 CI 集成
- Webhook - GitHub, BitBucket, GitLab
- 用于自动化的 Access tokens
- PreSync, Sync, PostSync 钩子支持复杂应用 - blue/green & canary upgrades
- Audit trails for application events and API calls
- Prometheus metrics
- Parameter overrides for overriding ksonnet/helm parameters in Git
- 应用定义
- Kustomize
- Helm
- A directory of YAML/JSON/Jsonnet manifests, including Jsonnet
- 自定义配置管理工具
Ksonnet
- 缺陷
- App of Apps 支持不好
- issues label:applications-set
- 尝试解决 argoproj-labs/applicationset
- 多集群支持较弱 - fleedcd 相对做的更好
- 一个 App 只能指定一个集群 #1673
- 无 agent, 无 crd 定义 - app of apps 只能在 argocd 所在集群
- 因为目标集群没有 argocd 因此设置 application 无效
- 因为相同应用要放在同一个 argocd 空间,因此需要名字前缀,例如
dev-cert-manager
- 因为加了名字前缀,要注意所有的 helm 最好指定固定的 releaseName, 例如 cert-manager
- 复写 releaseName 会有问题
argocd 依赖app.kubernetes.io/instance
匹配应用- 复写可能会修改该 label 导致无法匹配部分资源
- 可以在
argocd-cm.yaml
修改配置application.instanceLabelKey
- 复写 releaseName 会有问题
- 跨集群应用无法删除资源
- App of Apps 支持不好
- 参考
- Kustomize 后处理 Helm - - kustomized-helm
- ApplicationSet
- Image Updater
- Notification
- Vault Plugin
tip
- 每 3 分钟 拉取一次 Git
- hlem chart 版本支持范围匹配 - 使用 Hard Refresh 刷新会触发新的版本部署
- 默认刷新不会触发是因为有 repo 缓存
--repo-cache-expiration
- 例如
1.1.*
,~0.1.57
- 默认刷新不会触发是因为有 repo 缓存
caution
- 应用名字要求全局唯一
- 应用就是 helm 的 release 名字 - helm 不要求全局唯一,因此迁移过程可能冲突
- 可以修改
application.instanceLabelKey
配置 - 这样 helm 自定义 releaseName 才不会冲突- 例如修改为
app.kubernetes.io/argocd-instance
- 默认与 helm 常用冲突
app.kubernetes.io/instance
- 例如修改为
- Kustomize 不可以后处理 Helm
- 如果一定需要,可以考虑插件
- 或者预先生成好
- 使用稳定的 Git 服务
- 避免使用 Gitlab, Github - 因为访问不稳定会导致 argocd 很慢或者同步状态不可知
- 可以考虑集群内部署 gitea 然后镜像外部仓库 - 配置好 Webhook 触发可实现秒级同步
- 直接应用 manifest 升级可能导致配置丢失 #3537
- 可能会覆盖 argocd-cm
# 安装
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# HA
# kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/ha/install.yaml
# 转发到本地直接访问
# https://localhost:8080
kubectl port-forward svc/argocd-server -n argocd 8443:443
# 账号 admin
# 密码 旧的方式为 deploy 名字
# kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server -o name | cut -d'/' -f 2
# 新的方式会保存初始密码
# 获取密码后 建议删除 argocd-initial-admin-secret
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
kubectl -n argocd delete secret argocd-initial-admin-secret
# 可通过修改 argocd-secret admin.password 来修改密码
# argocd 命令行工具
brew install argocd
# 登陆
argocd login localhost:8080
# 如果配置了 ingress 需要 grpc-web 访问
# 除非开启 ssl-paththrough - nginx 开启对性能影响很大
argocd login argocd.my.lan:443 --grpc-web
应用发现
- 目前不支持,使用 app-in-app 模式
- Cluster Bootstrapping
- #1766 - Application auto-discovery
- argoproj-labs/applicationset
组件
- argocd-server
- ArgoCD API server
- argocd-application-controller
- 持续健康运行的应用,对比状态
- sts 可部署多个
- argocd-repo-server
- 管理 Git 本地缓存,管理应用清单
密钥管理
- 问题根源
- 因为 GitOps 要求所有内容都在仓库,因此密钥也需要存储在仓库
- 出于安全考虑不能直接放明文的 Secret,因此需要曲线提供 Secret
- 部分要求在 helm values.yaml 提供密钥的还需要先生成 chart 然后修改为另外的方式提供密钥
- 方案
- bitnami-labs/sealed-secrets
- 生成不可逆的密钥存储在仓库,控制器生成对应 Secret - 非对称加密
- 最简单实用
- bitnami-labs/sealed-secrets
- 参考
命令行
- https://argoproj.github.io/argo-cd/user-guide/commands/argocd/
~/.argocd/config
多集群
# kubeconfig 的 test 上下文
argocd cluster add test
argocd cluster list
# 部署应用后 connectionState 才会是成功 - 默认相当于无链接
argocd cluster get 'https://192.168.1.2:6443'
项目
应用逻辑分组
- what - 限定部署内容 - 仓库
- where - 限定集群和命名空间
- what kind - API Kind
- 角色 - RBAC
同步选项
metadata:
annotations:
argocd.argoproj.io/sync-options: Prune=false
syncPolicy:
# 自动同步
automated:
# 是否删除资源
prune: true
# 是否允许空资源
allowEmpty: false
# selfheal 超时后再次执行同步 - 默认 5s
# --self-heal-timeout-seconds
selfHeal: false
syncOptions:
# 只同步 out of sync 资源 - 默认全部,会对服务端带来压力
- ApplyOutOfSyncOnly=true
- CreateNamespace=true
- RespectIgnoreDifferences=true
options | desc |
---|---|
Prune=false | 不删除资源 |
Validate=false | kubectl --validate=false - 不校验 YAML |
SkipDryRunOnMissingResource=true | 新增 CRD 时避免 DryRun 失败 |
配置
- argocd-cm.yaml
- 基础配置
- argocd-secret.yaml
- Password, Certificates, Signing Key
- argocd-rbac-cm.yaml
- 参考
argocd-cm
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
labels:
app.kubernetes.io/name: argocd-cm
app.kubernetes.io/part-of: argocd
data:
ga.trackingid: ''
repositories: |
# 仓库列表
# 用来匹配 Application - 如果不修改会导致 helm 自定义 releaseName 有问题
# application.instanceLabelKey: app.kubernetes.io/instance
application.resourceTrackingMethod: annotation
# 建议修改
# application.instanceLabelKey: app.kubernetes.io/argocd-instance
repositories
# 定义 Git 仓库账号密码
- passwordSecret:
key: password
name: repo-12345
usernameSecret:
key: username
name: repo-12345
type: git
url: https://gitlab.com/wener/repo.git
# 定义 Git 仓库 SSH 密钥
- insecure: true
insecureIgnoreHostKey: true
sshPrivateKeySecret:
key: sshPrivateKey
name: repo-1234
type: git
url: git@gitea-ssh.gitea:dev/dev-cluster
ArgoCD 管理 ArgoCD
kustomization.yaml
bases:
- github.com/argoproj/argo-cd//manifests/cluster-install?ref=v1.0.1
# additional resources like ingress rules, cluster and repository secrets.
resources:
- clusters-secrets.yaml
- repos-secrets.yaml
# 修改配置
patchesStrategicMerge:
- overlays/argo-cd-cm.yaml
Resource Hook
- Resource Hooks
- 选择性同步时不会执行
- PreSync
- Sync
- PostSync
- SyncFail
apiVersion: batch/v1
kind: Job
metadata:
generateName: schema-migrate-
annotations:
# 定义 Hook 类型
argocd.argoproj.io/hook: PreSync
# PostSync
# 删除策略 HookSucceeded HookFailed BeforeHookCreation
argocd.argoproj.io/hook-delete-policy: HookSucceeded
Annotations
# 比较选项
# ==========
# 忽略额外的 - 例如部分工具生成对象
# 似乎有点问题 https://github.com/argoproj/argo-cd/issues/4487
argocd.argoproj.io/compare-options: IgnoreExtraneous
# 同步选项
# ==========
# 不删除
argocd.argoproj.io/sync-options: Prune=false
# 不校验
argocd.argoproj.io/sync-options: Validate=false
# 不校验 CRD
argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true
argocd.argoproj.io/sync-wave: "5"
# 添加外部链接 - 类似 Ingress
link.argocd.argoproj.io/external-link: http://my-grafana.com/pre-generated-link
syncPolicy:
syncOptions:
# 只同步不同步资源 - 选择性同步
# 当资源非常多时适用
- ApplyOutOfSyncOnly=true
不同步部分字段
- 例如 cert-manager 预先生成 secret 包含 labels 和 annotations, 但内容不需要同步
- 可应用纬度配置或全局配置
- Diffing Customization¶
# 应用 spec 配置
spec:
ignoreDifferences:
- group: apps
kind: Deployment
name: guestbook
namespace: default
jsonPointers:
- /spec/replicas
# argocd-cm 配置 - 全局
data:
resource.customizations: |
admissionregistration.k8s.io/MutatingWebhookConfiguration:
ignoreDifferences: |
jsonPointers:
- /webhooks/0/clientConfig/caBundle
Sync
- The phase
- The wave they are in (lower values first)
- By kind (e.g. namespaces first)
- By name
Tricks
bases:
# latest
- github.com/argoproj/argo-cd//manifests/cluster-install
# tag
- github.com/argoproj/argo-cd//manifests/cluster-install?ref=v0.11.1
构建环境
- ARGOCD_APP_NAME
- ARGOCD_APP_NAMESPACE
- ARGOCD_APP_REVISION
- ARGOCD_APP_SOURCE_PATH
- ARGOCD_APP_SOURCE_REPO_URL
- ARGOCD_APP_SOURCE_TARGET_REVISION | master
- KUBE_VERSION
- KUBE_API_VERSIONS
Application spec
spec:
destination:
# name: 集群名字
namespace: demo-system
server: 'https://kubernetes.default.svc'
project: default
revisionHistoryLimit: 10
ignoreDifferences:
- group:
kind:
name:
namespace:
jqPathExpressions: []
jsonPointers: []
info:
- name:
value:
source:
# Git 或 Helm repo
repoURL: 'https://github.com/wenerme/kube-stub-cluster.git'
# Git 目录
path: postgres-operator-ui
# Helm repo 的 chart 名
# chart: chart-name
# Git 或 Helm repo 版本
targetRevision: HEAD
helm:
releaseName: postgres-operator-ui
# version: 3
fileParameters:
- name: name
path: file/path.txt
parameters:
- name: name
value: value
# 是否检测 value 类型为 number 或 boolean
forceString: false
valueFiles:
# 相对路径
- values.yaml
# 多个 values 文件
- ../same/repo/postgres-operator-ui-values.yaml
values: |
# values
kustomize:
commonAnnotations:
commonLabels:
forceCommonAnnotations: false
forceCommonLabels: false
# 覆盖 image
images: []
namePrefix:
nameSuffix:
version:
ksonnet:
environment: ''
parameters:
- name:
value:
component:
jsonnet:
extVars:
- name:
value:
code: false
libs: []
tlas: # Top-level Arguments
- name:
value:
code: false
webhook
http://<argocd>/api/webhook
FAQ
the server could not find the requested resource
- CRD 定义不存在
- Namespace 不存在
特殊情况可以考虑跳过
metadata:
annotations:
argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true
the server has asked for the client to provide credentials
有可能是 k8s 集群发生了 cert 轮换
- 在 argocd 空间找到对应集群 secret,secret 有标签
argocd.argoproj.io/secret-type=cluster
- 修改 secret 里的 config 字段
- 修改 certData
- 修改 keyData
- 保存即可
apiVersion: v1
kind: Secret
metadata:
name: cluster-name
namespace: argocd
stringData:
config: "" # JSON
name:
url:
config
{
"tlsClientConfig": {
"insecure": false,
"certData": "", // 修改
"keyData": "", // 修改
"caData": "" // 保留
}
}
升级应用时可能 CRD 有变化导致校验不通过
- 先同步 CRD
kustomize build 异常
使用与 argocd 相同版本试试
docker run --rm -it -v $PWD:/tmp -w /tmp registry.cn-hongkong.aliyuncs.com/cmi/argoproj_argocd:v2.0.1 bash