使用 Argo CD 进行 GitOps 流水线改造
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 仓库中对期望目标状态所做的任何修改都可以自动应用反馈到指定的目标环境中去。
下面简单介绍下 Argo CD 中的几个主要组件:
API 服务:API 服务是一个 gRPC/REST 服务,它暴露了 Web UI、CLI 和 CI/CD 系统使用的接口,主要有以下几个功能:
- 应用程序管理和状态报告
- 执行应用程序操作(例如同步、回滚、用户定义的操作)
- 存储仓库和集群凭据管理(存储为 K8s Secrets 对象)
- 认证和授权给外部身份提供者
- RBAC
- Git webhook 事件的侦听器/转发器
仓库服务:存储仓库服务是一个内部服务,负责维护保存应用程序清单 Git 仓库的本地缓存。当提供以下输入时,它负责生成并返回 Kubernetes 清单:
- 存储 URL
- revision 版本(commit、tag、branch)
- 应用路径
- 模板配置:参数、ksonnet 环境、helm values.yaml 等
应用控制器:应用控制器是一个 Kubernetes 控制器,它持续 watch 正在运行的应用程序并将当前的实时状态与所期望的目标状态(repo 中指定的)进行比较。它检测应用程序的 OutOfSync
状态,并采取一些措施来同步状态,它负责调用任何用户定义的生命周期事件的钩子(PreSync、Sync、PostSync)。
安装
当然前提是需要有一个 kubectl 可访问的 Kubernetes 的集群,直接使用下面的命令即可,这里我们安装最新的 v2.8.4 版本:
$ kubectl create namespace argocd
$ kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.8.4/manifests/install.yaml
如果你要用在生产环境,则可以使用下面的命令部署一个 HA 高可用的版本:
$ kubectl create namespace argocd
$ kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.8.4/manifests/ha/install.yaml
这将创建一个新的命名空间 argocd,Argo CD 的服务和应用资源都将部署到该命名空间。
$ kubectl get pods -n argocd
NAME READY STATUS RESTARTS AGE
argocd-application-controller-0 1/1 Running 0 103s
argocd-applicationset-controller-68b9bdbd8b-jzcpf 1/1 Running 0 103s
argocd-dex-server-6b7745757-6mxwk 1/1 Running 0 103s
argocd-notifications-controller-5b56f6f7bb-jqpng 1/1 Running 0 103s
argocd-redis-f4cdbff57-dr8jc 1/1 Running 0 103s
argocd-repo-server-c4f79b4d6-7nh6n 1/1 Running 0 103s
argocd-server-895675597-fr42g 1/1 Running 0 103s
如果你对 UI、SSO、多集群管理这些特性不感兴趣,只想把应用变更同步到集群中,那么可以直接安装核心组件即可:
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.8.4/manifests/core-install.yaml
。
然后我们可以在本地(选择对应的版本)安装 CLI 工具方便操作 Argo CD:
$ curl -sSL -o /usr/local/bin/argocd https://github.com/argoproj/argo-cd/releases/download/v2.8.4/argocd-linux-amd64
为 argocd CLI 赋予可执行权限:
$ chmod +x /usr/local/bin/argocd
现在我们就可以使用 argocd
命令了。如果你是 Mac,则可以直接使用 brew install argocd
进行安装。
Argo CD 会运行一个 gRPC 服务(由 CLI 使用)和 HTTP/HTTPS 服务(由 UI 使用),这两种协议都由 argocd-server
服务在以下端口进行暴露:
- 443 - gRPC/HTTPS
- 80 - HTTP(重定向到 HTTPS)
我们可以通过配置 Ingress 的方式来对外暴露服务,其他 Ingress 控制器的配置可以参考官方文档 https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/ 进行配置。
Argo CD 在同一端口 (443) 上提供多个协议 (gRPC/HTTPS),所以当我们为 argocd 服务定义单个 nginx ingress 对象和规则的时候有点麻烦,因为 nginx.ingress.kubernetes.io/backend-protocol
这个 annotation 只能接受一个后端协议(例如 HTTP、HTTPS、GRPC、GRPCS)。
为了使用单个 ingress 规则和主机名来暴露 Argo CD APIServer,必须使用 nginx.ingress.kubernetes.io/ssl-passthrough
这个 annotation 来传递 TLS 连接并校验 Argo CD APIServer 上的 TLS。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-server-ingress
namespace: argocd
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
spec:
ingressClassName: nginx
rules:
- host: argocd.k8s.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port:
name: https
上述规则在 Argo CD APIServer 上校验 TLS,该服务器检测到正在使用的协议,并做出适当的响应。请注意,nginx.ingress.kubernetes.io/ssl-passthrough
注解要求将 --enable-ssl-passthrough
标志添加到 nginx-ingress-controller
的命令行参数中。
由于 ingress-nginx
的每个 Ingress 对象仅支持一个协议,因此另一种方法是定义两个 Ingress 对象。一个用于 HTTP/HTTPS,另一个用于 gRPC。
如下所示为 HTTP/HTTPS 的 Ingress 对象:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-server-http-ingress
namespace: argocd
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port:
name: http
host: argocd.k8s.local
tls:
- hosts:
- argocd.k8s.local
secretName: argocd-secret # do not change, this is provided by Argo CD
gRPC 协议对应的 Ingress 对象如下所示:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-server-grpc-ingress
namespace: argocd
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port:
name: https
host: grpc.argocd.k8s.local
tls:
- hosts:
- grpc.argocd.k8s.local
secretName: argocd-secret # do not change, this is provided by Argo CD
然后我们需要在禁用 TLS 的情况下运行 APIServer。编辑 argocd-server 这个 Deployment 以将 --insecure
标志添加到 argocd-server 命令,或者简单地在 argocd-cmd-params-cm
ConfigMap 中设置 server.insecure: "true"
即可。
创建完成后,我们就可以通过 argocd.k8s.local
来访问 Argo CD 服务了,不过需要注意我们这里配置的证书是自签名的,所以在第一次访问的时候会提示不安全,强制跳转即可。
默认情况下 admin
帐号的初始密码是自动生成的,会以明文的形式存储在 Argo CD 安装的命名空间中名为 argocd-initial-admin-secret
的 Secret 对象下的 password
字段下,我们可以用下面的命令来获取:
$ kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d && echo
使用用户名 admin
和上面输出的密码即可登录 Dashboard。
同样我们也可以通过 ArgoCD CLI 命令行工具进行登录:
$ argocd login grpc.argocd.k8s.local
WARNING: server certificate had error: tls: failed to verify certificate: x509: certificate signed by unknown authority. Proceed insecurely (y/n)? y
Username: admin
Password:
'admin:login' logged in successfully
Context 'grpc.argocd.k8s.local' updated
需要注意的是这里登录的地址为 gRPC 暴露的服务地址。
CLI 登录成功后,可以使用如下所示命令更改密码:
$ argocd account update-password
*** Enter current password:
*** Enter new password:
*** Confirm new password:
Password updated
Context 'argocd.k8s.local' updated
$ argocd version
argocd: v2.8.4+c279299
BuildDate: 2023-09-13T19:43:37Z
GitCommit: c27929928104dc37b937764baf65f38b78930e59
GitTreeState: clean
GoVersion: go1.20.7
Compiler: gc
Platform: darwin/arm64
argocd-server: v2.8.4+c279299
BuildDate: 2023-09-13T19:12:09Z
GitCommit: c27929928104dc37b937764baf65f38b78930e59
GitTreeState: clean
GoVersion: go1.20.6
Compiler: gc
Platform: linux/amd64
Kustomize Version: v5.1.0 2023-06-19T16:58:18Z
Helm Version: v3.12.1+gf32a527
Kubectl Version: v0.24.2
Jsonnet Version: v0.20.0
配置集群
由于 Argo CD 支持部署应用到多集群,所以如果你要将应用部署到外部集群的时候,需要先将外部集群的认证信息注册到 Argo CD 中,如果是在内部部署(运行 Argo CD 的同一个集群,默认不需要配置),直接使用 https://kubernetes.default.svc
作为应用的 K8S APIServer 地址即可。
首先列出当前 kubeconfig
中的所有集群上下文:
$ kubectl config get-contexts -o name
kubernetes-admin@kubernetes
orbstack
从列表中选择一个上下文名称并将其提供给 argocd cluster add CONTEXTNAME
,比如对于 orbstack
上下文,运行:
$ argocd cluster add orbstack
创建应用
Git 仓库 https://github.com/argoproj/argocd-example-apps.git 是一个包含留言簿应用程序的示例库,我们可以用该应用来演示 Argo CD 的工作原理。
通过 CLI 创建应用
我们可以通过 argocd app create xxx
命令来创建一个应用:
$ argocd app create --help
Create an application
Usage:
argocd app create APPNAME [flags]
Examples:
# Create a directory app
argocd app create guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --directory-recurse
# Create a Jsonnet app
argocd app create jsonnet-guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path jsonnet-guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --jsonnet-ext-str replicas=2
# Create a Helm app
argocd app create helm-guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path helm-guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --helm-set replicaCount=2
# Create a Helm app from a Helm repo
argocd app create nginx-ingress --repo https://charts.helm.sh/stable --helm-chart nginx-ingress --revision 1.24.3 --dest-namespace default --dest-server https://kubernetes.default.svc
# Create a Kustomize app
argocd app create kustomize-guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path kustomize-guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --kustomize-image gcr.io/heptio-images/ks-guestbook-demo:0.1
# Create a app using a custom tool:
argocd app create kasane --repo https://github.com/argoproj/argocd-example-apps.git --path plugins/kasane --dest-namespace default --dest-server https://kubernetes.default.svc --config-management-plugin kasane
Flags:
......
直接执行如下所示命令即可:
$ argocd app create guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path guestbook --dest-server https://kubernetes.default.svc --dest-namespace default
application 'guestbook' created
通过 UI 创建应用
除了可以通过 CLI 工具来创建应用,我们也可以通过 UI 界面来创建,定位到 argocd.k8s.local
页面,登录后,点击 +New App
新建应用按钮,如下图:
将应用命名为 guestbook,使用 default project,并将同步策略设置为 Manual
:
然后在下面配置 Repository URL
为 https://github.com/argoproj/argocd-example-apps.git,由于某些原因我们这里使用的是 Gitee 仓库地址 https://gitee.com/cnych/argocd-example-apps
,将 Revision 设置为 HEAD,并将路径设置为 guestbook。然后下面的 Destination 部分,将 cluster 设置为 inCluster
和 namespace 为 default:
填写完以上信息后,点击页面上方的 Create 安装,即可创建 guestbook 应用,创建完成后可以看到当前应用的处于 OutOfSync
状态:
Argo CD 默认情况下每 3 分钟会检测 Git 仓库一次,用于判断应用实际状态是否和 Git 中声明的期望状态一致,如果不一致,状态就转换为 OutOfSync
。默认情况下并不会触发更新,除非通过 syncPolicy
配置了自动同步。
通过 CRD 创建
除了可以通过 CLI 和 Dashboard 可以创建 Application 之外,其实也可以直接通过声明一个 Application
的资源对象来创建一个应用,如下所示:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: guestbook
spec:
destination:
namespace: default
server: "https://kubernetes.default.svc"
source:
path: guestbook
repoURL: "https://github.com/cnych/argocd-example-apps"
targetRevision: HEAD
project: default
syncPolicy:
automated: null
文章转载自公众号:k8s技术圈