update kubeflow dip-catalog

This commit is contained in:
ChanghoWoo
2025-01-13 02:31:27 +00:00
parent 1dc1181a03
commit 5451f16d72
1959 changed files with 602337 additions and 0 deletions
@@ -0,0 +1,47 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: kubeflow
resources:
- ../../pipeline
- ../../cache
- ../../cache-deployer
- pipeline-install-config.yaml
- mysql-secret.yaml
vars:
- name: kfp-namespace
objref:
kind: Deployment
apiVersion: apps/v1
name: ml-pipeline
fieldref:
fieldpath: metadata.namespace
- name: kfp-app-name
objref:
kind: ConfigMap
name: pipeline-install-config
apiVersion: v1
fieldref:
fieldpath: data.appName
- name: kfp-app-version
objref:
kind: ConfigMap
name: pipeline-install-config
apiVersion: v1
fieldref:
fieldpath: data.appVersion
- name: kfp-artifact-bucket-name
objref:
kind: ConfigMap
name: pipeline-install-config
apiVersion: v1
fieldref:
fieldpath: data.bucketName
- name: kfp-default-pipeline-root
objref:
kind: ConfigMap
name: pipeline-install-config
apiVersion: v1
fieldref:
fieldpath: data.defaultPipelineRoot
configurations:
- params.yaml
@@ -0,0 +1,7 @@
kind: Secret
apiVersion: v1
metadata:
name: mysql-secret
stringData:
username: root
password: ""
@@ -0,0 +1,10 @@
# Allow Kustomize var to replace following fields.
varReference:
- path: data/config
kind: ConfigMap
- path: data/defaultPipelineRoot
kind: ConfigMap
- path: metadata/name
kind: Application
- path: spec/descriptor/version
kind: Application
@@ -0,0 +1,96 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: pipeline-install-config
data:
warning: |
1. Do not use kubectl to edit this configmap, because some values are used
during kustomize build. Instead, change the configmap and apply the entire
kustomize manifests again.
2. After updating the configmap, some deployments may need to be restarted
until the changes take effect. A quick way to restart all deployments in a
namespace: `kubectl rollout restart deployment -n <your-namespace>`.
appName: pipeline
appVersion: 2.2.0
dbHost: mysql # relic to be removed after release
dbPort: "3306" # relic to be removed after release
dbType: mysql
mysqlHost: mysql
mysqlPort: "3306"
mlmdDb: metadb
cacheDb: cachedb
pipelineDb: mlpipeline
bucketName: mlpipeline
## defaultPipelineRoot: Optional. Default pipeline root in v2 compatible mode.
## https://www.kubeflow.org/docs/components/pipelines/sdk/v2/v2-compatibility/
##
## If the field is not set, kfp-launcher configmaps won't be created and
## v2 compatible mode defaults to minio://mlpipeline/v2/artifacts as pipeline
## root.
##
## When not in Kubeflow Pipelines multi-user mode, the config works as you
## would normally expect.
##
## In Kubeflow Pipelines multi-user mode, the config creates default
## kfp-launcher configmaps in each user's namespace. Users can edit the
## kfp-launcher configmap's defaultPipelineRoot field afterwards to configure
## namespace-specific default pipeline root. The namespace specific changes in
## kfp-launcher configmap won't be overridden by pipeline-install-config.
##
## Caveat: when you update the config from a non-empty value, only new
## namespaces get the updated config by default. Owners of existing namespaces
## must delete the kfp-launcher configmap to get the new default config value.
##
## Examples:
## defaultPipelineRoot: minio://mlpipeline/v2/artifacts
## defaultPipelineRoot: gs://your-bucket/path/to/artifacts
## defaultPipelineRoot: s3://your-bucket/path/to/artifacts
##
## V2 Compatible Mode Feature stage:
## [Beta](https://github.com/kubeflow/pipelines/blob/master/docs/release/feature-stages.md#beta)
defaultPipelineRoot: ""
## autoUpdatePipelineDefaultVersion: States if the pipeline version
## should be updated by defult for a versioned pipeline or not when a new
## version is uploaded. This sets the deployment wide definition.
autoUpdatePipelineDefaultVersion: "true"
## cronScheduleTimezone: States the timezone which should be used for
## the cron scheduler. If not specified the local timezone of the
## cluster will be used. Valid values are UTC, Local or values according to
## the IANA Time Zone database, such as "America/New_York" and "Asia/Shanghai".
## Feature stage:
## [Alpha](https://github.com/kubeflow/pipelines/blob/master/docs/release/feature-stages.md#alpha)
cronScheduleTimezone: "UTC"
## cacheImage is the image that the mutating webhook will use to patch
## cached steps with. Will be used to echo a message announcing that
## the cached step result will be used. If not set it will default to
## 'gcr.io/google-containers/busybox'
cacheImage: "gcr.io/google-containers/busybox"
## cacheNodeRestrictions the dummy container runing if output is cached
## will run with the same affinity and node selector as the default pipeline
## step. This is defaulted to 'false' to allow the pod to be scheduled on
## any node and avoid defaulting to specific nodes. Allowed values are:
## 'false' and 'true'.
cacheNodeRestrictions: "false"
## MAXIMUM_CACHE_STALENESS configures caching according to
## https://www.kubeflow.org/docs/components/pipelines/overview/caching/ and
## https://www.kubeflow.org/docs/components/pipelines/overview/caching-v2/.
## Larger than MAXIMUM_CACHE_STALENESS per pipeline user set values are
## reduced to MAXIMUM_CACHE_STALENESS.
## The administrator of the storage backend can rely on it to delete old cache
## artifacts.
MAXIMUM_CACHE_STALENESS: ""
## MAXIMUM_CACHE_STALENESS: "P30D"
## DEFAULT_CACHE_STALENESS configures caching according to
## https://www.kubeflow.org/docs/components/pipelines/overview/caching/ and
## https://www.kubeflow.org/docs/components/pipelines/overview/caching-v2/.
## This value is used if the user did not set a value in the pipeline.
DEFAULT_CACHE_STALENESS: ""
## DEFAULT_CACHE_STALENESS: "P7D"
## ConMaxLifeTime will set the connection max lifetime for MySQL
## this is very important to setup when using external databases.
## See this issue for more details: https://github.com/kubeflow/pipelines/issues/5329
## Note: this value should be a string that can be parsed by `time.ParseDuration`.
## If this value doesn't include a unit abbreviation, the units will be assumed
## to be nanoseconds.
ConMaxLifeTime: "120s"
LOG_LEVEL: "info"
@@ -0,0 +1,47 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: kubeflow
resources:
- ../../../postgresql/pipeline
- ../../../postgresql/cache
- ../../../cache-deployer
- pipeline-install-config.yaml
- postgres-secret-extended.yaml
vars:
- name: kfp-namespace
objref:
kind: Deployment
apiVersion: apps/v1
name: ml-pipeline
fieldref:
fieldpath: metadata.namespace
- name: kfp-app-name
objref:
kind: ConfigMap
name: pipeline-install-config
apiVersion: v1
fieldref:
fieldpath: data.appName
- name: kfp-app-version
objref:
kind: ConfigMap
name: pipeline-install-config
apiVersion: v1
fieldref:
fieldpath: data.appVersion
- name: kfp-artifact-bucket-name
objref:
kind: ConfigMap
name: pipeline-install-config
apiVersion: v1
fieldref:
fieldpath: data.bucketName
- name: kfp-default-pipeline-root
objref:
kind: ConfigMap
name: pipeline-install-config
apiVersion: v1
fieldref:
fieldpath: data.defaultPipelineRoot
configurations:
- params.yaml
@@ -0,0 +1,10 @@
# Allow Kustomize var to replace following fields.
varReference:
- path: data/config
kind: ConfigMap
- path: data/defaultPipelineRoot
kind: ConfigMap
- path: metadata/name
kind: Application
- path: spec/descriptor/version
kind: Application
@@ -0,0 +1,95 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: pipeline-install-config
data:
warning: |
1. Do not use kubectl to edit this configmap, because some values are used
during kustomize build. Instead, change the configmap and apply the entire
kustomize manifests again.
2. After updating the configmap, some deployments may need to be restarted
until the changes take effect. A quick way to restart all deployments in a
namespace: `kubectl rollout restart deployment -n <your-namespace>`.
appName: pipeline
appVersion: 2.0.0
dbHost: postgres # relic to be removed after release
dbPort: "5432" # relic to be removed after release
dbType: postgres
postgresHost: postgres
postgresPort: "5432"
mlmdDb: metadb
cacheDb: cachedb
pipelineDb: mlpipeline
bucketName: mlpipeline
## defaultPipelineRoot: Optional. Default pipeline root in v2 compatible mode.
## https://www.kubeflow.org/docs/components/pipelines/sdk/v2/v2-compatibility/
##
## If the field is not set, kfp-launcher configmaps won't be created and
## v2 compatible mode defaults to minio://mlpipeline/v2/artifacts as pipeline
## root.
##
## When not in Kubeflow Pipelines multi-user mode, the config works as you
## would normally expect.
##
## In Kubeflow Pipelines multi-user mode, the config creates default
## kfp-launcher configmaps in each user's namespace. Users can edit the
## kfp-launcher configmap's defaultPipelineRoot field afterwards to configure
## namespace-specific default pipeline root. The namespace specific changes in
## kfp-launcher configmap won't be overridden by pipeline-install-config.
##
## Caveat: when you update the config from a non-empty value, only new
## namespaces get the updated config by default. Owners of existing namespaces
## must delete the kfp-launcher configmap to get the new default config value.
##
## Examples:
## defaultPipelineRoot: minio://mlpipeline/v2/artifacts
## defaultPipelineRoot: gs://your-bucket/path/to/artifacts
## defaultPipelineRoot: s3://your-bucket/path/to/artifacts
##
## V2 Compatible Mode Feature stage:
## [Beta](https://github.com/kubeflow/pipelines/blob/master/docs/release/feature-stages.md#beta)
defaultPipelineRoot: ""
## autoUpdatePipelineDefaultVersion: States if the pipeline version
## should be updated by defult for a versioned pipeline or not when a new
## version is uploaded. This sets the deployment wide definition.
autoUpdatePipelineDefaultVersion: "true"
## cronScheduleTimezone: States the timezone which should be used for
## the cron scheduler. If not specified the local timezone of the
## cluster will be used. Valid values are UTC, Local or values according to
## the IANA Time Zone database, such as "America/New_York" and "Asia/Shanghai".
## Feature stage:
## [Alpha](https://github.com/kubeflow/pipelines/blob/master/docs/release/feature-stages.md#alpha)
cronScheduleTimezone: "UTC"
## cacheImage is the image that the mutating webhook will use to patch
## cached steps with. Will be used to echo a message announcing that
## the cached step result will be used. If not set it will default to
## 'gcr.io/google-containers/busybox'
cacheImage: "gcr.io/google-containers/busybox"
## cacheNodeRestrictions the dummy container runing if output is cached
## will run with the same affinity and node selector as the default pipeline
## step. This is defaulted to 'false' to allow the pod to be scheduled on
## any node and avoid defaulting to specific nodes. Allowed values are:
## 'false' and 'true'.
cacheNodeRestrictions: "false"
## MAXIMUM_CACHE_STALENESS configures caching according to
## https://www.kubeflow.org/docs/components/pipelines/overview/caching/ and
## https://www.kubeflow.org/docs/components/pipelines/overview/caching-v2/.
## Larger than MAXIMUM_CACHE_STALENESS per pipeline user set values are
## reduced to MAXIMUM_CACHE_STALENESS.
## The administrator of the storage backend can rely on it to delete old cache
## artifacts.
MAXIMUM_CACHE_STALENESS: ""
## MAXIMUM_CACHE_STALENESS: "P30D"
## DEFAULT_CACHE_STALENESS configures caching according to
## https://www.kubeflow.org/docs/components/pipelines/overview/caching/ and
## https://www.kubeflow.org/docs/components/pipelines/overview/caching-v2/.
## This value is used if the user did not set a value in the pipeline.
DEFAULT_CACHE_STALENESS: ""
## DEFAULT_CACHE_STALENESS: "P7D"
## ConMaxLifeTime will set the connection max lifetime for MySQL
## this is very important to setup when using external databases.
## See this issue for more details: https://github.com/kubeflow/pipelines/issues/5329
## Note: this value should be a string that can be parsed by `time.ParseDuration`.
## If this value doesn't include a unit abbreviation, the units will be assumed
## to be nanoseconds.
ConMaxLifeTime: "120s"
@@ -0,0 +1,7 @@
kind: Secret
apiVersion: v1
metadata:
name: postgres-secret-extended
stringData:
username: user
password: "password"
@@ -0,0 +1,11 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: ml-pipeline
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: ml-pipeline
subjects:
- kind: ServiceAccount
name: ml-pipeline
@@ -0,0 +1,49 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: ml-pipeline
rules:
- apiGroups:
- ""
resources:
- pods
- pods/log
verbs:
- get
- list
- delete
- apiGroups:
- argoproj.io
resources:
- workflows
verbs:
- create
- get
- list
- watch
- update
- patch
- delete
- apiGroups:
- kubeflow.org
resources:
- scheduledworkflows
verbs:
- create
- get
- list
- update
- patch
- delete
- apiGroups:
- authorization.k8s.io
resources:
- subjectaccessreviews
verbs:
- create
- apiGroups:
- authentication.k8s.io
resources:
- tokenreviews
verbs:
- create
@@ -0,0 +1,17 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: ml-pipeline
spec:
template:
spec:
containers:
- name: ml-pipeline-api-server
envFrom:
- configMapRef:
name: pipeline-api-server-config
env:
- name: KUBEFLOW_USERID_HEADER
value: kubeflow-userid
- name: KUBEFLOW_USERID_PREFIX
value: ""
@@ -0,0 +1,9 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- cluster-role-binding.yaml
- cluster-role.yaml
configMapGenerator:
- name: pipeline-api-server-config
envs:
- params.env
@@ -0,0 +1,4 @@
MULTIUSER=true
DEFAULTPIPELINERUNNERSERVICEACCOUNT=default-editor
VISUALIZATIONSERVICE_NAME=ml-pipeline-visualizationserver
VISUALIZATIONSERVICE_PORT=8888
@@ -0,0 +1,11 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubeflow-pipelines-cache-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kubeflow-pipelines-cache-role
subjects:
- kind: ServiceAccount
name: kubeflow-pipelines-cache
@@ -0,0 +1,31 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kubeflow-pipelines-cache-role
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
- update
- patch
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- apiGroups:
- argoproj.io
resources:
- workflows
verbs:
- get
- list
- watch
- update
- patch
@@ -0,0 +1,13 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: cache-server
spec:
template:
spec:
containers:
- name: server
env:
- name: NAMESPACE_TO_WATCH
value: ''
valueFrom: null
@@ -0,0 +1,7 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
commonLabels:
app: cache-server
resources:
- cluster-role.yaml
- cluster-role-binding.yaml
@@ -0,0 +1,106 @@
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: ml-pipeline-ui
namespace: kubeflow
spec:
selector:
matchLabels:
app: ml-pipeline-ui
rules:
- from:
- source:
namespaces:
- istio-system
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: ml-pipeline
namespace: kubeflow
spec:
selector:
matchLabels:
app: ml-pipeline
rules:
- from:
- source:
principals:
- cluster.local/ns/kubeflow/sa/ml-pipeline
- cluster.local/ns/kubeflow/sa/ml-pipeline-ui
- cluster.local/ns/kubeflow/sa/ml-pipeline-persistenceagent
- cluster.local/ns/kubeflow/sa/ml-pipeline-scheduledworkflow
- cluster.local/ns/kubeflow/sa/ml-pipeline-viewer-crd-service-account
- cluster.local/ns/kubeflow/sa/kubeflow-pipelines-cache
# allow access by any trusted principal
- from:
- source:
requestPrincipals: ["*"]
# For user workloads, which cannot user http headers for authentication
- when:
- key: request.headers[kubeflow-userid]
notValues: ['*']
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: ml-pipeline-visualizationserver
namespace: kubeflow
spec:
selector:
matchLabels:
app: ml-pipeline-visualizationserver
rules:
- from:
- source:
principals:
- cluster.local/ns/kubeflow/sa/ml-pipeline
- cluster.local/ns/kubeflow/sa/ml-pipeline-ui
- cluster.local/ns/kubeflow/sa/ml-pipeline-persistenceagent
- cluster.local/ns/kubeflow/sa/ml-pipeline-scheduledworkflow
- cluster.local/ns/kubeflow/sa/ml-pipeline-viewer-crd-service-account
- cluster.local/ns/kubeflow/sa/kubeflow-pipelines-cache
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: service-cache-server
namespace: kubeflow
spec:
selector:
matchLabels:
app: cache-server
rules:
- {}
---
apiVersion: "networking.istio.io/v1alpha3"
kind: DestinationRule
metadata:
name: ml-pipeline-ui
spec:
host: ml-pipeline-ui.kubeflow.svc.cluster.local
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
---
apiVersion: "networking.istio.io/v1alpha3"
kind: DestinationRule
metadata:
name: ml-pipeline
spec:
host: ml-pipeline.kubeflow.svc.cluster.local
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
---
apiVersion: "networking.istio.io/v1alpha3"
kind: DestinationRule
metadata:
name: ml-pipeline-visualizationserver
spec:
host: ml-pipeline-visualizationserver.kubeflow.svc.cluster.local
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
@@ -0,0 +1,33 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: kubeflow
commonLabels:
app.kubernetes.io/name: kubeflow-pipelines
app.kubernetes.io/component: ml-pipeline
resources:
- ../../pipeline/cluster-scoped
- ../../cache-deployer/cluster-scoped
- ../generic
- view-edit-cluster-roles.yaml
- api-service
- pipelines-ui
- pipelines-profile-controller
- scheduled-workflow
- viewer-controller
- persistence-agent
- cache
- metadata-writer
- istio-authorization-config.yaml
- virtual-service.yaml
patches:
- path: api-service/deployment-patch.yaml
- path: pipelines-ui/deployment-patch.yaml
- path: pipelines-ui/configmap-patch.yaml
- path: scheduled-workflow/deployment-patch.yaml
- path: viewer-controller/deployment-patch.yaml
- path: persistence-agent/deployment-patch.yaml
- path: metadata-writer/deployment-patch.yaml
- path: cache/deployment-patch.yaml
configurations:
- params.yaml
@@ -0,0 +1,11 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubeflow-pipelines-metadata-writer-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kubeflow-pipelines-metadata-writer-role
subjects:
- kind: ServiceAccount
name: kubeflow-pipelines-metadata-writer
@@ -0,0 +1,31 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kubeflow-pipelines-metadata-writer-role
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
- update
- patch
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- apiGroups:
- argoproj.io
resources:
- workflows
verbs:
- get
- list
- watch
- update
- patch
@@ -0,0 +1,13 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: metadata-writer
spec:
template:
spec:
containers:
- name: main
env:
- name: NAMESPACE_TO_WATCH
value: ''
valueFrom: null
@@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- cluster-role.yaml
- cluster-role-binding.yaml
@@ -0,0 +1,4 @@
# Allow Kustomize var to replace following fields.
varReference:
- path: spec/http/route/destination/host
kind: VirtualService
@@ -0,0 +1,11 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: ml-pipeline-persistenceagent-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: ml-pipeline-persistenceagent-role
subjects:
- kind: ServiceAccount
name: ml-pipeline-persistenceagent
@@ -0,0 +1,35 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: ml-pipeline-persistenceagent-role
rules:
- apiGroups:
- argoproj.io
resources:
- workflows
verbs:
- get
- list
- watch
- apiGroups:
- kubeflow.org
resources:
- scheduledworkflows
verbs:
- get
- list
- watch
- apiGroups:
- pipelines.kubeflow.org
resources:
- scheduledworkflows
- workflows
verbs:
- report
- apiGroups:
- pipelines.kubeflow.org
resources:
- runs
verbs:
- reportMetrics
- readArtifact
@@ -0,0 +1,13 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: ml-pipeline-persistenceagent
spec:
template:
spec:
containers:
- name: ml-pipeline-persistenceagent
env:
- name: NAMESPACE
value: ''
valueFrom: null
@@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- cluster-role.yaml
- cluster-role-binding.yaml
@@ -0,0 +1,41 @@
# Change resyncPeriodSeconds to 1 hour from insane 20 seconds
# Only sync namespaces with pipelines.kubeflow.org/enabled = "true"
apiVersion: metacontroller.k8s.io/v1alpha1
kind: CompositeController
metadata:
name: kubeflow-pipelines-profile-controller
spec:
generateSelector: true
resyncPeriodSeconds: 3600
parentResource:
apiVersion: v1
resource: namespaces
childResources:
- apiVersion: v1
resource: secrets
updateStrategy:
method: OnDelete
- apiVersion: v1
resource: configmaps
updateStrategy:
method: OnDelete
- apiVersion: apps/v1
resource: deployments
updateStrategy:
method: InPlace
- apiVersion: v1
resource: services
updateStrategy:
method: InPlace
- apiVersion: networking.istio.io/v1alpha3
resource: destinationrules
updateStrategy:
method: InPlace
- apiVersion: security.istio.io/v1beta1
resource: authorizationpolicies
updateStrategy:
method: InPlace
hooks:
sync:
webhook:
url: http://kubeflow-pipelines-profile-controller/sync
@@ -0,0 +1,49 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubeflow-pipelines-profile-controller
spec:
replicas: 1
template:
metadata:
annotations:
sidecar.istio.io/inject: "false"
spec:
containers:
- name: profile-controller
image: python:3.7
command: ["python", "/hooks/sync.py"]
envFrom:
- configMapRef:
name: kubeflow-pipelines-profile-controller-env
env:
- name: KFP_VERSION
valueFrom:
configMapKeyRef:
name: pipeline-install-config
key: appVersion
- name: KFP_DEFAULT_PIPELINE_ROOT
valueFrom:
configMapKeyRef:
optional: true
name: pipeline-install-config
key: defaultPipelineRoot
- name: MINIO_ACCESS_KEY
valueFrom:
secretKeyRef:
name: mlpipeline-minio-artifact
key: accesskey
- name: MINIO_SECRET_KEY
valueFrom:
secretKeyRef:
name: mlpipeline-minio-artifact
key: secretkey
volumeMounts:
- name: hooks
mountPath: /hooks
ports:
- containerPort: 8080
volumes:
- name: hooks
configMap:
name: kubeflow-pipelines-profile-controller-code
@@ -0,0 +1,16 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: kubeflow
commonLabels:
app: kubeflow-pipelines-profile-controller
resources:
- service.yaml
- deployment.yaml
- composite-controller.yaml
configMapGenerator:
- name: kubeflow-pipelines-profile-controller-code
files:
- sync.py
- name: kubeflow-pipelines-profile-controller-env
envs:
- params.env
@@ -0,0 +1 @@
DISABLE_ISTIO_SIDECAR=false
@@ -0,0 +1,3 @@
pytest
pytest-lazy-fixture
requests
@@ -0,0 +1,9 @@
# Build venv with required packages
VENV=".venv"
PYTHON_VENV="${VENV}/bin/python"
python -m venv $VENV
$PYTHON_VENV -m pip install -U pip
$PYTHON_VENV -m pip install -r requirements-dev.txt
# Run tests
$PYTHON_VENV -m pytest ./test_sync.py
@@ -0,0 +1,10 @@
apiVersion: v1
kind: Service
metadata:
name: kubeflow-pipelines-profile-controller
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8080
@@ -0,0 +1,396 @@
# Copyright 2020-2021 The Kubeflow Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
import os
import base64
def main():
settings = get_settings_from_env()
server = server_factory(**settings)
server.serve_forever()
def get_settings_from_env(controller_port=None,
visualization_server_image=None, frontend_image=None,
visualization_server_tag=None, frontend_tag=None, disable_istio_sidecar=None,
minio_access_key=None, minio_secret_key=None, kfp_default_pipeline_root=None):
"""
Returns a dict of settings from environment variables relevant to the controller
Environment settings can be overridden by passing them here as arguments.
Settings are pulled from the all-caps version of the setting name. The
following defaults are used if those environment variables are not set
to enable backwards compatibility with previous versions of this script:
visualization_server_image: gcr.io/ml-pipeline/visualization-server
visualization_server_tag: value of KFP_VERSION environment variable
frontend_image: gcr.io/ml-pipeline/frontend
frontend_tag: value of KFP_VERSION environment variable
disable_istio_sidecar: Required (no default)
minio_access_key: Required (no default)
minio_secret_key: Required (no default)
"""
settings = dict()
settings["controller_port"] = \
controller_port or \
os.environ.get("CONTROLLER_PORT", "8080")
settings["visualization_server_image"] = \
visualization_server_image or \
os.environ.get("VISUALIZATION_SERVER_IMAGE", "gcr.io/ml-pipeline/visualization-server")
settings["frontend_image"] = \
frontend_image or \
os.environ.get("FRONTEND_IMAGE", "gcr.io/ml-pipeline/frontend")
# Look for specific tags for each image first, falling back to
# previously used KFP_VERSION environment variable for backwards
# compatibility
settings["visualization_server_tag"] = \
visualization_server_tag or \
os.environ.get("VISUALIZATION_SERVER_TAG") or \
os.environ["KFP_VERSION"]
settings["frontend_tag"] = \
frontend_tag or \
os.environ.get("FRONTEND_TAG") or \
os.environ["KFP_VERSION"]
settings["disable_istio_sidecar"] = \
disable_istio_sidecar if disable_istio_sidecar is not None \
else os.environ.get("DISABLE_ISTIO_SIDECAR") == "true"
settings["minio_access_key"] = \
minio_access_key or \
base64.b64encode(bytes(os.environ.get("MINIO_ACCESS_KEY"), 'utf-8')).decode('utf-8')
settings["minio_secret_key"] = \
minio_secret_key or \
base64.b64encode(bytes(os.environ.get("MINIO_SECRET_KEY"), 'utf-8')).decode('utf-8')
# KFP_DEFAULT_PIPELINE_ROOT is optional
settings["kfp_default_pipeline_root"] = \
kfp_default_pipeline_root or \
os.environ.get("KFP_DEFAULT_PIPELINE_ROOT")
return settings
def server_factory(visualization_server_image,
visualization_server_tag, frontend_image, frontend_tag,
disable_istio_sidecar, minio_access_key,
minio_secret_key, kfp_default_pipeline_root=None,
url="", controller_port=8080):
"""
Returns an HTTPServer populated with Handler with customized settings
"""
class Controller(BaseHTTPRequestHandler):
def sync(self, parent, children):
# parent is a namespace
namespace = parent.get("metadata", {}).get("name")
pipeline_enabled = parent.get("metadata", {}).get(
"labels", {}).get("pipelines.kubeflow.org/enabled")
if pipeline_enabled != "true":
return {"status": {}, "children": []}
desired_configmap_count = 1
desired_resources = []
if kfp_default_pipeline_root:
desired_configmap_count = 2
desired_resources += [{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": {
"name": "kfp-launcher",
"namespace": namespace,
},
"data": {
"defaultPipelineRoot": kfp_default_pipeline_root,
},
}]
# Compute status based on observed state.
desired_status = {
"kubeflow-pipelines-ready":
len(children["Secret.v1"]) == 1 and
len(children["ConfigMap.v1"]) == desired_configmap_count and
len(children["Deployment.apps/v1"]) == 2 and
len(children["Service.v1"]) == 2 and
len(children["DestinationRule.networking.istio.io/v1alpha3"]) == 1 and
len(children["AuthorizationPolicy.security.istio.io/v1beta1"]) == 1 and
"True" or "False"
}
# Generate the desired child object(s).
desired_resources += [
{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": {
"name": "metadata-grpc-configmap",
"namespace": namespace,
},
"data": {
"METADATA_GRPC_SERVICE_HOST":
"metadata-grpc-service.kubeflow",
"METADATA_GRPC_SERVICE_PORT": "8080",
},
},
# Visualization server related manifests below
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"labels": {
"app": "ml-pipeline-visualizationserver"
},
"name": "ml-pipeline-visualizationserver",
"namespace": namespace,
},
"spec": {
"selector": {
"matchLabels": {
"app": "ml-pipeline-visualizationserver"
},
},
"template": {
"metadata": {
"labels": {
"app": "ml-pipeline-visualizationserver"
},
"annotations": disable_istio_sidecar and {
"sidecar.istio.io/inject": "false"
} or {},
},
"spec": {
"containers": [{
"image": f"{visualization_server_image}:{visualization_server_tag}",
"imagePullPolicy":
"IfNotPresent",
"name":
"ml-pipeline-visualizationserver",
"ports": [{
"containerPort": 8888
}],
"resources": {
"requests": {
"cpu": "50m",
"memory": "200Mi"
},
"limits": {
"cpu": "500m",
"memory": "1Gi"
},
}
}],
"serviceAccountName":
"default-editor",
},
},
},
},
{
"apiVersion": "networking.istio.io/v1alpha3",
"kind": "DestinationRule",
"metadata": {
"name": "ml-pipeline-visualizationserver",
"namespace": namespace,
},
"spec": {
"host": "ml-pipeline-visualizationserver",
"trafficPolicy": {
"tls": {
"mode": "ISTIO_MUTUAL"
}
}
}
},
{
"apiVersion": "security.istio.io/v1beta1",
"kind": "AuthorizationPolicy",
"metadata": {
"name": "ml-pipeline-visualizationserver",
"namespace": namespace,
},
"spec": {
"selector": {
"matchLabels": {
"app": "ml-pipeline-visualizationserver"
}
},
"rules": [{
"from": [{
"source": {
"principals": ["cluster.local/ns/kubeflow/sa/ml-pipeline"]
}
}]
}]
}
},
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "ml-pipeline-visualizationserver",
"namespace": namespace,
},
"spec": {
"ports": [{
"name": "http",
"port": 8888,
"protocol": "TCP",
"targetPort": 8888,
}],
"selector": {
"app": "ml-pipeline-visualizationserver",
},
},
},
# Artifact fetcher related resources below.
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"labels": {
"app": "ml-pipeline-ui-artifact"
},
"name": "ml-pipeline-ui-artifact",
"namespace": namespace,
},
"spec": {
"selector": {
"matchLabels": {
"app": "ml-pipeline-ui-artifact"
}
},
"template": {
"metadata": {
"labels": {
"app": "ml-pipeline-ui-artifact"
},
"annotations": disable_istio_sidecar and {
"sidecar.istio.io/inject": "false"
} or {},
},
"spec": {
"containers": [{
"name":
"ml-pipeline-ui-artifact",
"image": f"{frontend_image}:{frontend_tag}",
"imagePullPolicy":
"IfNotPresent",
"ports": [{
"containerPort": 3000
}],
"env": [
{
"name": "MINIO_ACCESS_KEY",
"valueFrom": {
"secretKeyRef": {
"key": "accesskey",
"name": "mlpipeline-minio-artifact"
}
}
},
{
"name": "MINIO_SECRET_KEY",
"valueFrom": {
"secretKeyRef": {
"key": "secretkey",
"name": "mlpipeline-minio-artifact"
}
}
}
],
"resources": {
"requests": {
"cpu": "10m",
"memory": "70Mi"
},
"limits": {
"cpu": "100m",
"memory": "500Mi"
},
}
}],
"serviceAccountName":
"default-editor"
}
}
}
},
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "ml-pipeline-ui-artifact",
"namespace": namespace,
"labels": {
"app": "ml-pipeline-ui-artifact"
}
},
"spec": {
"ports": [{
"name":
"http", # name is required to let istio understand request protocol
"port": 80,
"protocol": "TCP",
"targetPort": 3000
}],
"selector": {
"app": "ml-pipeline-ui-artifact"
}
}
},
]
print('Received request:\n', json.dumps(parent, sort_keys=True))
print('Desired resources except secrets:\n', json.dumps(desired_resources, sort_keys=True))
# Moved after the print argument because this is sensitive data.
desired_resources.append({
"apiVersion": "v1",
"kind": "Secret",
"metadata": {
"name": "mlpipeline-minio-artifact",
"namespace": namespace,
},
"data": {
"accesskey": minio_access_key,
"secretkey": minio_secret_key,
},
})
return {"status": desired_status, "children": desired_resources}
def do_POST(self):
# Serve the sync() function as a JSON webhook.
observed = json.loads(
self.rfile.read(int(self.headers.get("content-length"))))
desired = self.sync(observed["parent"], observed["children"])
self.send_response(200)
self.send_header("Content-type", "application/json")
self.end_headers()
self.wfile.write(bytes(json.dumps(desired), 'utf-8'))
return HTTPServer((url, int(controller_port)), Controller)
if __name__ == "__main__":
main()
@@ -0,0 +1,286 @@
import os
from unittest import mock
import threading
from sync import get_settings_from_env, server_factory
import json
import pytest
import requests
# Data sets passed to server
DATA_INCORRECT_CHILDREN = {
"parent": {
"metadata": {
"labels": {
"pipelines.kubeflow.org/enabled": "true"
},
"name": "myName"
}
},
"children": {
"Secret.v1": [],
"ConfigMap.v1": [],
"Deployment.apps/v1": [],
"Service.v1": [],
"DestinationRule.networking.istio.io/v1alpha3": [],
"AuthorizationPolicy.security.istio.io/v1beta1": [],
}
}
DATA_CORRECT_CHILDREN = {
"parent": {
"metadata": {
"labels": {
"pipelines.kubeflow.org/enabled": "true"
},
"name": "myName"
}
},
"children": {
"Secret.v1": [1],
"ConfigMap.v1": [1],
"Deployment.apps/v1": [1, 1],
"Service.v1": [1, 1],
"DestinationRule.networking.istio.io/v1alpha3": [1],
"AuthorizationPolicy.security.istio.io/v1beta1": [1],
}
}
DATA_MISSING_PIPELINE_ENABLED = {"parent": {}, "children": {}}
# Default values when environments are not explicit
DEFAULT_FRONTEND_IMAGE = "gcr.io/ml-pipeline/frontend"
DEFAULT_VISUALIZATION_IMAGE = "gcr.io/ml-pipeline/visualization-server"
# Variables used for environment variable sets
VISUALIZATION_SERVER_IMAGE = "vis-image"
VISUALIZATION_SERVER_TAG = "somenumber.1.2.3"
FRONTEND_IMAGE = "frontend-image"
FRONTEND_TAG = "somehash"
KFP_VERSION = "x.y.z"
MINIO_ACCESS_KEY = "abcdef"
MINIO_SECRET_KEY = "uvwxyz"
# "Environments" used in tests
ENV_VARIABLES_BASE = {
"MINIO_ACCESS_KEY": MINIO_ACCESS_KEY,
"MINIO_SECRET_KEY": MINIO_SECRET_KEY,
"CONTROLLER_PORT": "0", # HTTPServer randomly assigns the port to a free port
}
ENV_KFP_VERSION_ONLY = dict(ENV_VARIABLES_BASE,
**{
"KFP_VERSION": KFP_VERSION,
}
)
ENV_IMAGES_NO_TAGS = dict(ENV_VARIABLES_BASE,
**{
"KFP_VERSION": KFP_VERSION,
"VISUALIZATION_SERVER_IMAGE": VISUALIZATION_SERVER_IMAGE,
"FRONTEND_IMAGE": FRONTEND_IMAGE,
}
)
ENV_IMAGES_WITH_TAGS = dict(ENV_VARIABLES_BASE,
**{
"VISUALIZATION_SERVER_IMAGE": VISUALIZATION_SERVER_IMAGE,
"FRONTEND_IMAGE": FRONTEND_IMAGE,
"VISUALIZATION_SERVER_TAG": VISUALIZATION_SERVER_TAG,
"FRONTEND_TAG": FRONTEND_TAG,
}
)
ENV_IMAGES_WITH_TAGS_AND_ISTIO = dict(ENV_IMAGES_WITH_TAGS,
**{
"DISABLE_ISTIO_SIDECAR": "false",
}
)
def generate_image_name(imagename, tag):
return f"{str(imagename)}:{str(tag)}"
@pytest.fixture(
scope="function",
)
def sync_server(request):
"""
Starts the sync HTTP server for a given set of environment variables on a separate thread
Yields:
* the server (useful to interrogate for the server address)
* environment variables (useful to interrogate for correct responses)
"""
environ = request.param
with mock.patch.dict(os.environ, environ):
# Create a server at an available port and serve it on a thread as a daemon
# This will result in a collection of servers being active - not a great way
# if this fixture is run many times during a test, but ok for now
settings = get_settings_from_env()
server = server_factory(**settings)
server_thread = threading.Thread(target=server.serve_forever)
# Put on daemon so it doesn't keep pytest from ending
server_thread.daemon = True
server_thread.start()
yield server, environ
@pytest.fixture(
scope="function",
)
def sync_server_from_arguments(request):
"""
Starts the sync HTTP server for a given set of parameters passed as arguments, with server on a separate thread
Yields:
* the server (useful to interrogate for the server address)
* environment variables (useful to interrogate for correct responses)
"""
environ = {k.lower(): v for k, v in request.param.items()}
settings = environ
server = server_factory(**settings)
server_thread = threading.Thread(target=server.serve_forever)
# Put on daemon so it doesn't keep pytest from ending
server_thread.daemon = True
server_thread.start()
yield server, environ
@pytest.mark.parametrize(
"sync_server, data, expected_status, expected_visualization_server_image, expected_frontend_server_image",
[
(
ENV_KFP_VERSION_ONLY,
DATA_INCORRECT_CHILDREN,
{"kubeflow-pipelines-ready": "False"},
generate_image_name(DEFAULT_VISUALIZATION_IMAGE, KFP_VERSION),
generate_image_name(DEFAULT_FRONTEND_IMAGE, KFP_VERSION),
),
(
ENV_IMAGES_NO_TAGS,
DATA_INCORRECT_CHILDREN,
{"kubeflow-pipelines-ready": "False"},
generate_image_name(ENV_IMAGES_NO_TAGS["VISUALIZATION_SERVER_IMAGE"], KFP_VERSION),
generate_image_name(ENV_IMAGES_NO_TAGS["FRONTEND_IMAGE"], KFP_VERSION),
),
(
ENV_IMAGES_WITH_TAGS,
DATA_INCORRECT_CHILDREN,
{"kubeflow-pipelines-ready": "False"},
generate_image_name(ENV_IMAGES_WITH_TAGS["VISUALIZATION_SERVER_IMAGE"],
ENV_IMAGES_WITH_TAGS["VISUALIZATION_SERVER_TAG"]),
generate_image_name(ENV_IMAGES_WITH_TAGS["FRONTEND_IMAGE"], ENV_IMAGES_WITH_TAGS["FRONTEND_TAG"]),
),
(
ENV_IMAGES_WITH_TAGS,
DATA_CORRECT_CHILDREN,
{"kubeflow-pipelines-ready": "True"},
generate_image_name(ENV_IMAGES_WITH_TAGS["VISUALIZATION_SERVER_IMAGE"],
ENV_IMAGES_WITH_TAGS["VISUALIZATION_SERVER_TAG"]),
generate_image_name(ENV_IMAGES_WITH_TAGS["FRONTEND_IMAGE"], ENV_IMAGES_WITH_TAGS["FRONTEND_TAG"]),
),
],
indirect=["sync_server"]
)
def test_sync_server_with_pipeline_enabled(sync_server, data, expected_status,
expected_visualization_server_image, expected_frontend_server_image):
"""
Nearly end-to-end test of how Controller serves .sync as a POST
Tests case where metadata.labels.pipelines.kubeflow.org/enabled exists, and thus
we should produce children
Only does spot checks on children to see if key properties are correct
"""
server, environ = sync_server
# server.server_address = (url, port_as_integer)
url = f"http://{server.server_address[0]}:{str(server.server_address[1])}"
print("url: ", url)
print("data")
print(json.dumps(data))
x = requests.post(url, data=json.dumps(data))
results = json.loads(x.text)
# Test overall status of whether children are ok
assert results['status'] == expected_status
# Poke a few children to test things that can vary by environment variable
assert results['children'][1]["spec"]["template"]["spec"]["containers"][0][
"image"] == expected_visualization_server_image
assert results['children'][5]["spec"]["template"]["spec"]["containers"][0][
"image"] == expected_frontend_server_image
@pytest.mark.parametrize(
"sync_server_from_arguments, data, expected_status, expected_visualization_server_image, "
"expected_frontend_server_image",
[
(
ENV_IMAGES_WITH_TAGS_AND_ISTIO,
DATA_CORRECT_CHILDREN,
{"kubeflow-pipelines-ready": "True"},
generate_image_name(ENV_IMAGES_WITH_TAGS["VISUALIZATION_SERVER_IMAGE"],
ENV_IMAGES_WITH_TAGS["VISUALIZATION_SERVER_TAG"]),
generate_image_name(ENV_IMAGES_WITH_TAGS["FRONTEND_IMAGE"], ENV_IMAGES_WITH_TAGS["FRONTEND_TAG"]),
),
],
indirect=["sync_server_from_arguments"]
)
def test_sync_server_with_direct_passing_of_settings(
sync_server_from_arguments, data, expected_status, expected_visualization_server_image,
expected_frontend_server_image):
"""
Nearly end-to-end test of how Controller serves .sync as a POST, taking variables as arguments
Only does spot checks on children to see if key properties are correct
"""
server, environ = sync_server_from_arguments
# server.server_address = (url, port_as_integer)
url = f"http://{server.server_address[0]}:{str(server.server_address[1])}"
print("url: ", url)
print("data")
print(json.dumps(data))
x = requests.post(url, data=json.dumps(data))
results = json.loads(x.text)
# Test overall status of whether children are ok
assert results['status'] == expected_status
# Poke a few children to test things that can vary by environment variable
assert results['children'][1]["spec"]["template"]["spec"]["containers"][0][
"image"] == expected_visualization_server_image
assert results['children'][5]["spec"]["template"]["spec"]["containers"][0][
"image"] == expected_frontend_server_image
@pytest.mark.parametrize(
"sync_server, data, expected_status, expected_children",
[
(ENV_IMAGES_WITH_TAGS, DATA_MISSING_PIPELINE_ENABLED, {}, []),
],
indirect=["sync_server"]
)
def test_sync_server_without_pipeline_enabled(sync_server, data, expected_status,
expected_children):
"""
Nearly end-to-end test of how Controller serves .sync as a POST
Tests case where metadata.labels.pipelines.kubeflow.org/enabled does not
exist and thus server returns an empty reply
"""
server, environ = sync_server
# server.server_address = (url, port_as_integer)
url = f"http://{server.server_address[0]}:{str(server.server_address[1])}"
x = requests.post(url, data=json.dumps(data))
results = json.loads(x.text)
# Test overall status of whether children are ok
assert results['status'] == expected_status
assert results['children'] == expected_children
@@ -0,0 +1,11 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: ml-pipeline-ui
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: ml-pipeline-ui
subjects:
- kind: ServiceAccount
name: ml-pipeline-ui
@@ -0,0 +1,42 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: ml-pipeline-ui
rules:
- apiGroups:
- ""
resources:
- pods
- pods/log
verbs:
- get
- apiGroups:
- ""
resources:
- events
verbs:
- list
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- list
- apiGroups:
- "kubeflow.org"
resources:
- viewers
verbs:
- create
- get
- list
- watch
- delete
- apiGroups:
- "argoproj.io"
resources:
- workflows
verbs:
- get
- list
@@ -0,0 +1,13 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: ml-pipeline-ui-configmap
data:
# Temporary workarounds:
# 1. Using default-editor because default-viewer isn't bound to workload identity
viewer-pod-template.json: |-
{
"spec": {
"serviceAccountName": "default-editor"
}
}
@@ -0,0 +1,34 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: ml-pipeline-ui
spec:
template:
spec:
volumes:
- name: config-volume
configMap:
name: ml-pipeline-ui-configmap
containers:
- name: ml-pipeline-ui
env:
- name: VIEWER_TENSORBOARD_POD_TEMPLATE_SPEC_PATH
value: /etc/config/viewer-pod-template.json
- name: DEPLOYMENT
value: KUBEFLOW
- name: ARTIFACTS_SERVICE_PROXY_NAME
value: ml-pipeline-ui-artifact
- name: ARTIFACTS_SERVICE_PROXY_PORT
value: '80'
- name: ARTIFACTS_SERVICE_PROXY_ENABLED
value: 'true'
- name: ENABLE_AUTHZ
value: 'true'
- name: KUBEFLOW_USERID_HEADER
value: kubeflow-userid
- name: KUBEFLOW_USERID_PREFIX
value: ""
volumeMounts:
- name: config-volume
mountPath: /etc/config
readOnly: true
@@ -0,0 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: kubeflow
commonLabels:
app: ml-pipeline-ui
resources:
- cluster-role.yaml
- cluster-role-binding.yaml
@@ -0,0 +1,11 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: ml-pipeline-scheduledworkflow-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: ml-pipeline-scheduledworkflow-role
subjects:
- kind: ServiceAccount
name: ml-pipeline-scheduledworkflow
@@ -0,0 +1,37 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: ml-pipeline-scheduledworkflow-role
rules:
- apiGroups:
- argoproj.io
resources:
- workflows
verbs:
- create
- get
- list
- watch
- update
- patch
- delete
- apiGroups:
- kubeflow.org
resources:
- scheduledworkflows
- scheduledworkflows/finalizers
verbs:
- create
- get
- list
- watch
- update
- patch
- delete
- apiGroups:
- ''
resources:
- events
verbs:
- create
- patch
@@ -0,0 +1,13 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: ml-pipeline-scheduledworkflow
spec:
template:
spec:
containers:
- name: ml-pipeline-scheduledworkflow
env:
- name: NAMESPACE
value: '' # Empty namespace let viewer controller watch all namespaces
valueFrom: null # HACK: https://github.com/kubernetes-sigs/kustomize/issues/2606
@@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: kubeflow
resources:
- cluster-role.yaml
- cluster-role-binding.yaml
@@ -0,0 +1,141 @@
# NOTE: IMPORTANT
# We need to separate out actual rules from aggregation rules due to
# https://github.com/kubernetes/kubernetes/issues/65171
# TL;DR: We can't have both aggregation and rules in a [Cluster]Role. When that
# is the case, the rules get ignored.
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
rbac.authorization.kubeflow.org/aggregate-to-kubeflow-edit: "true"
name: kubeflow-pipelines-edit
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.authorization.kubeflow.org/aggregate-to-kubeflow-pipelines-edit: "true"
rules: []
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
rbac.authorization.kubeflow.org/aggregate-to-kubeflow-pipelines-edit: "true"
rbac.authorization.kubeflow.org/aggregate-to-kubeflow-view: "true"
name: kubeflow-pipelines-view
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.authorization.kubeflow.org/aggregate-to-kubeflow-pipelines-view: "true"
rules: []
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
rbac.authorization.kubeflow.org/aggregate-to-kubeflow-pipelines-edit: "true"
name: aggregate-to-kubeflow-pipelines-edit
rules:
- apiGroups:
- pipelines.kubeflow.org
resources:
- pipelines
- pipelines/versions
verbs:
- create
- delete
- update
- apiGroups:
- pipelines.kubeflow.org
resources:
- experiments
verbs:
- archive
- create
- delete
- unarchive
- apiGroups:
- pipelines.kubeflow.org
resources:
- runs
verbs:
- archive
- create
- delete
- retry
- terminate
- unarchive
- reportMetrics
- readArtifact
- apiGroups:
- pipelines.kubeflow.org
resources:
- jobs
verbs:
- create
- delete
- disable
- enable
- apiGroups:
- kubeflow.org
verbs:
- '*'
resources:
- scheduledworkflows
- apiGroups:
- argoproj.io
verbs:
- '*'
resources:
- cronworkflows
- cronworkflows/finalizers
- workflows
- workflows/finalizers
- workfloweventbindings
- workflowtemplates
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
rbac.authorization.kubeflow.org/aggregate-to-kubeflow-pipelines-view: "true"
name: aggregate-to-kubeflow-pipelines-view
rules:
- apiGroups:
- pipelines.kubeflow.org
resources:
- pipelines
- pipelines/versions
- experiments
- jobs
verbs:
- get
- list
- apiGroups:
- pipelines.kubeflow.org
resources:
- runs
verbs:
- get
- list
- readArtifact
- apiGroups:
- kubeflow.org
resources:
- viewers
verbs:
- create
- get
- delete
- apiGroups:
- pipelines.kubeflow.org
resources:
- visualizations
verbs:
- create
@@ -0,0 +1,11 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: ml-pipeline-viewer-crd-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: ml-pipeline-viewer-controller-role
subjects:
- kind: ServiceAccount
name: ml-pipeline-viewer-crd-service-account
@@ -0,0 +1,31 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: ml-pipeline-viewer-controller-role
rules:
- apiGroups:
- '*'
resources:
- deployments
- services
verbs:
- create
- get
- list
- watch
- update
- patch
- delete
- apiGroups:
- kubeflow.org
resources:
- viewers
- viewers/finalizers
verbs:
- create
- get
- list
- watch
- update
- patch
- delete
@@ -0,0 +1,13 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: ml-pipeline-viewer-crd
spec:
template:
spec:
containers:
- name: ml-pipeline-viewer-crd
env:
- name: NAMESPACE
value: '' # Empty namespace let viewer controller watch all namespaces
valueFrom: null
@@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- cluster-role.yaml
- cluster-role-binding.yaml
@@ -0,0 +1,21 @@
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ml-pipeline-ui
spec:
gateways:
- kubeflow-gateway
hosts:
- '*'
http:
- match:
- uri:
prefix: /pipeline
rewrite:
uri: /pipeline
route:
- destination:
host: ml-pipeline-ui.$(kfp-namespace).svc.cluster.local
port:
number: 80
timeout: 300s