由于公司的CI/CD系统特别垃圾,还不如一些开源货靠谱,而我这边又有一些构建项目部署到AWS的需要,所以就在之前部署的kubeflow上动起了脑筋,它里面有集成了argo,也许可以把它用起来。
argo是个基于kubernetes的项目,包含多个组件,其中argo-workflows就是工作流引擎,有点类似airflow,它可以编排各种容器,控制工作流的执行。
kubeflow内部使用了argo-workflow作为pipeline底层的任务编排组件,换句话说,你运行的每个pipeline任务,底层都是一个workflow在跑,由argo-workflows做控制。
但是在目前的版本中,kubeflow默认并没有把argo-server等组件装上,只部署了它需要的workflow-controller。并且由于采用manifests默认安装的kubeflow的argo-workflows是采用cluster(可以理解为集群全局)模式安装,所以我们直接再用namespaced方式再部署一套argo也不太行得通,会受到kubeflow里面那个的影响。
于是我研究了一下如何直接把kubeflow内部集成的这个argo-workflows抠出来用,就形成了本文,邪门歪道,仅供参考。
本文基于Kubeflow Pipelines 1.7.0
对应的Argo Workflows版本是3.1
通过研究kubeflow pipeline下面的third_party/argo目录和argo-workflows的manifests,我们可以发现以下几点:
基于以上几点,我们就可以尝试直接部署argo相关的组件,来补全argo相关的功能,以便可以独立使用argo。我这里只部署argo-workflows(argo-server)和argo-events。
这个其实相当于argo-workflows的管理界面前后端,这里如果不嫌麻烦的话,可以去argo-workflows官方的manifests下面把argo-server组件相关的部署到kubeflow namespace下。而我的做法更简单粗暴一些,在部署的时候直接改了kubeflow pipelines里面的配置,在kustomization.yaml里面,把被剔除的对上游的依赖
- ../upstream/manifests/base/argo-server
- ../upstream/manifests/base/cluster-install/argo-server-rbac
重新加回来。然后像往常一样部署整个pipeline组件,argo-server就应该一起被装上去了。
注意需要修改上面路径里的argo-server这个配置文件的内容,由于之前的里面镜像tag写了latest,这里需要改回3.1.x,如果是3.2在UI展示上似乎有变化无法显示
https://quay.io/repository/argoproj/argocli?tab=tags 这里找个合适的3.1版本。
装完之后,可能还需要一些设置,我这里是直接通过istio把argo-server的界面暴露出去的,你也可以参考argo官方的ingress配置,使用nginx之类的来做这个暴露。(其实这个比用istio方便一点,不需要处理访问权限相关的问题)
对argo-server部署上面做相应的修改,以便能正确暴露,使用下面的命令进行yaml编辑:
kubectl edit deployment -n kubeflow argo-server
下面是我主要修改的部分节选,主要改了几个:
--x-frame-options=
因为我是通过kubeflow的istio统一暴露出去的,所以它的页面是通过iframe展示的,需要配置这个参数为空来允许这样访问。--secure=false
是因为我是采用HTTP来访问该服务,如果你用HTTPS可以不改。/argo/
还是因为通过istio的子路由进行访问,需要加这个前缀HTTPS
改为HTTP
,因为我的服务用secure=false已经是HTTP服务了,这样改才能让健康检查通过。 spec:
containers:
- args:
- server
- --x-frame-options=
- --secure=false
env:
- name: BASE_HREF
value: /argo/
image: quay.io/argoproj/argocli:latest
imagePullPolicy: Always
name: argo-server
ports:
- containerPort: 2746
name: web
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /
port: 2746
scheme: HTTP
然后给istio加个virtualservice ,把下面这坨东西apply了,注意其把/argo/
rewrite成/
,这样才能访问到静态资源,我也懒得研究为啥it works,又不是不能用。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
namespace: kubeflow
name: argo
spec:
gateways:
- kubeflow/kubeflow-gateway
hosts:
- '*'
http:
- match:
- uri:
prefix: /argo/
rewrite:
uri: /
route:
- destination:
host: argo-server.kubeflow.svc.cluster.local
port:
number: 2746
timeout: 300s
还需要给argo-server加个AuthorizationPolicy,不然会有RBAC的报错
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: argo-server
namespace: kubeflow
spec:
action: ALLOW
rules:
- {}
selector:
matchLabels:
app: argo-server
也许这时候访问/argo/还是不行,那么需要改argo-server的service配置, 以便能让istio能正确认识该用哪个协议访问下游
kubectl edit service -n kubeflow argo-server
把服务的name从web
改成http-web
这时候应该就能在/argo/
路径访问到argo的管理界面了。
由于它默认是用client模式进行身份认证,所以你可以exec一下生成token的命令,来获取token以便登录进去。
kubectl exec -it -n kubeflow <your-argo-server-container> argo auth token
如果需要一些外部的服务(比如GitHub和GitLab的webhook)触发workflow,可以用argo-events,这个是argo的另外一个组件,可以单独部署。跟着argo-events的官方文档使用cluster模式安装即可。
给argo-events配置各种权限:
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: argo-events
name: operate-workflow-sa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: operate-workflow-role
namespace: argo-events
rules:
- apiGroups:
- argoproj.io
verbs:
- "*"
resources:
- workflows
- clusterworkflowtemplates
- workflowtemplates
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: operate-workflow-role-binding
namespace: argo-events
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: operate-workflow-role
subjects:
- kind: ServiceAccount
name: operate-workflow-sa
namespace: argo-events
通过上述的折腾,应该是基本能用了,但还有一些限制要知道。对于kubeflow的用户namespace,因为上面有istio-injection=enabled的label存在,所以所有在里面启动的pod都会默认被注入一个istio sidecar劫持流量,但在我们argo workflow运行时,通过sidecar通信会有问题,因此如果需要在用户namespace下运行workflow时,需要在workflow配置中显式设置
metadata:
annotations:
sidecar.istio.io/inject: 'false'
取消掉istio sidecar,以便容器间能够正常通信。
另外,还需要配置serviceAccountName: default-editor
,这个应该是kubeflow在用户namespace默认生成的serviceaccount,如果需要用ns下的某些资源的话,配这个基本没啥问题。
由于上述不便,可能在单独的namespace下运行argo workflows和events的pod更好一些。
参考: