diff --git a/.github/workflows/helm-kustomize-comparison.yml b/.github/workflows/helm-kustomize-comparison.yml index 14cd4a7d14..7e9b854d40 100644 --- a/.github/workflows/helm-kustomize-comparison.yml +++ b/.github/workflows/helm-kustomize-comparison.yml @@ -38,6 +38,10 @@ jobs: rm get_helm.sh - name: Install Kustomize run: ./tests/kustomize_install.sh + - name: Build Helm dependencies for pipelines + run: | + cd experimental/helm/charts/pipelines + helm dependency build - name: Run all scenarios comparison env: VERBOSE: "true" diff --git a/experimental/helm/charts/katib/Chart.yaml b/experimental/helm/charts/katib/Chart.yaml index 3646b219cf..c58101c11c 100644 --- a/experimental/helm/charts/katib/Chart.yaml +++ b/experimental/helm/charts/katib/Chart.yaml @@ -4,9 +4,9 @@ name: katib description: A Helm chart for Katib - AutoML on Kubernetes -version: 0.16.0 +version: 0.19.0 -appVersion: 0.16.0 +appVersion: 0.19.0 keywords: - automl diff --git a/experimental/helm/charts/katib/ci/values-cert-manager.yaml b/experimental/helm/charts/katib/ci/values-cert-manager.yaml index 34d7754920..a2e1728195 100644 --- a/experimental/helm/charts/katib/ci/values-cert-manager.yaml +++ b/experimental/helm/charts/katib/ci/values-cert-manager.yaml @@ -3,7 +3,7 @@ global: namespace: kubeflow - imageTag: v0.18.0 + imageTag: v0.19.0 # Enable kustomize compatibility mode kustomizeMode: @@ -77,6 +77,7 @@ config: controller: webhookPort: 8443 trialResources: + - TrainJob.v1alpha1.trainer.kubeflow.org - Job.v1.batch - TFJob.v1.kubeflow.org - PyTorchJob.v1.kubeflow.org @@ -85,40 +86,40 @@ config: runtime: metricsCollectors: - kind: StdOut - image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.18.0 + image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.19.0 - kind: File - image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.18.0 + image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.19.0 - kind: TensorFlowEvent - image: ghcr.io/kubeflow/katib/tfevent-metrics-collector:v0.18.0 + image: ghcr.io/kubeflow/katib/tfevent-metrics-collector:v0.19.0 resources: limits: memory: 1Gi suggestions: - algorithmName: random - image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.19.0 - algorithmName: tpe - image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.19.0 - algorithmName: grid - image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.19.0 - algorithmName: hyperband - image: ghcr.io/kubeflow/katib/suggestion-hyperband:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-hyperband:v0.19.0 - algorithmName: bayesianoptimization - image: ghcr.io/kubeflow/katib/suggestion-skopt:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-skopt:v0.19.0 - algorithmName: cmaes - image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.19.0 - algorithmName: sobol - image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.19.0 - algorithmName: multivariate-tpe - image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.19.0 - algorithmName: enas - image: ghcr.io/kubeflow/katib/suggestion-enas:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-enas:v0.19.0 resources: limits: memory: 400Mi - algorithmName: darts - image: ghcr.io/kubeflow/katib/suggestion-darts:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-darts:v0.19.0 - algorithmName: pbt - image: ghcr.io/kubeflow/katib/suggestion-pbt:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-pbt:v0.19.0 persistentVolumeClaimSpec: accessModes: - ReadWriteMany @@ -127,7 +128,7 @@ config: storage: 5Gi earlyStoppings: - algorithmName: medianstop - image: ghcr.io/kubeflow/katib/earlystopping-medianstop:v0.18.0 + image: ghcr.io/kubeflow/katib/earlystopping-medianstop:v0.19.0 # RBAC rbac: diff --git a/experimental/helm/charts/katib/ci/values-external-db.yaml b/experimental/helm/charts/katib/ci/values-external-db.yaml index b3542cfae9..477a153c00 100644 --- a/experimental/helm/charts/katib/ci/values-external-db.yaml +++ b/experimental/helm/charts/katib/ci/values-external-db.yaml @@ -3,7 +3,7 @@ global: namespace: kubeflow - imageTag: v0.18.0 + imageTag: v0.19.0 # Enable kustomize compatibility mode kustomizeMode: @@ -57,4 +57,67 @@ namespaceCreate: rbac: create: true kubeflow: - enabled: false \ No newline at end of file + enabled: false + +# Katib configuration +config: + katibConfig: | + apiVersion: config.kubeflow.org/v1beta1 + kind: KatibConfig + init: + certGenerator: + enable: true + controller: + webhookPort: 8443 + trialResources: + - Job.v1.batch + - TFJob.v1.kubeflow.org + - PyTorchJob.v1.kubeflow.org + - MPIJob.v1.kubeflow.org + - XGBoostJob.v1.kubeflow.org + runtime: + metricsCollectors: + - kind: StdOut + image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.19.0 + - kind: File + image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.19.0 + - kind: TensorFlowEvent + image: ghcr.io/kubeflow/katib/tfevent-metrics-collector:v0.19.0 + resources: + limits: + memory: 1Gi + suggestions: + - algorithmName: random + image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.19.0 + - algorithmName: tpe + image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.19.0 + - algorithmName: grid + image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.19.0 + - algorithmName: hyperband + image: ghcr.io/kubeflow/katib/suggestion-hyperband:v0.19.0 + - algorithmName: bayesianoptimization + image: ghcr.io/kubeflow/katib/suggestion-skopt:v0.19.0 + - algorithmName: cmaes + image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.19.0 + - algorithmName: sobol + image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.19.0 + - algorithmName: multivariate-tpe + image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.19.0 + - algorithmName: enas + image: ghcr.io/kubeflow/katib/suggestion-enas:v0.19.0 + resources: + limits: + memory: 400Mi + - algorithmName: darts + image: ghcr.io/kubeflow/katib/suggestion-darts:v0.19.0 + - algorithmName: pbt + image: ghcr.io/kubeflow/katib/suggestion-pbt:v0.19.0 + persistentVolumeClaimSpec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 5Gi + earlyStoppings: + - algorithmName: medianstop + image: ghcr.io/kubeflow/katib/earlystopping-medianstop:v0.19.0 \ No newline at end of file diff --git a/experimental/helm/charts/katib/ci/values-kubeflow.yaml b/experimental/helm/charts/katib/ci/values-kubeflow.yaml index c244d3f32c..69c214b07e 100644 --- a/experimental/helm/charts/katib/ci/values-kubeflow.yaml +++ b/experimental/helm/charts/katib/ci/values-kubeflow.yaml @@ -3,7 +3,7 @@ global: namespace: kubeflow - imageTag: v0.18.0 + imageTag: v0.19.0 # Enable kustomize compatibility mode kustomizeMode: @@ -111,6 +111,7 @@ config: controller: webhookPort: 8443 trialResources: + - TrainJob.v1alpha1.trainer.kubeflow.org - Job.v1.batch - TFJob.v1.kubeflow.org - PyTorchJob.v1.kubeflow.org @@ -119,40 +120,40 @@ config: runtime: metricsCollectors: - kind: StdOut - image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.18.0 + image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.19.0 - kind: File - image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.18.0 + image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.19.0 - kind: TensorFlowEvent - image: ghcr.io/kubeflow/katib/tfevent-metrics-collector:v0.18.0 - resources: + image: ghcr.io/kubeflow/katib/tfevent-metrics-collector:v0.19.0 + resources: limits: memory: 1Gi suggestions: - algorithmName: random - image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.19.0 - algorithmName: tpe - image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.19.0 - algorithmName: grid - image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.19.0 - algorithmName: hyperband - image: ghcr.io/kubeflow/katib/suggestion-hyperband:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-hyperband:v0.19.0 - algorithmName: bayesianoptimization - image: ghcr.io/kubeflow/katib/suggestion-skopt:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-skopt:v0.19.0 - algorithmName: cmaes - image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.19.0 - algorithmName: sobol - image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.19.0 - algorithmName: multivariate-tpe - image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.19.0 - algorithmName: enas - image: ghcr.io/kubeflow/katib/suggestion-enas:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-enas:v0.19.0 resources: limits: memory: 400Mi - algorithmName: darts - image: ghcr.io/kubeflow/katib/suggestion-darts:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-darts:v0.19.0 - algorithmName: pbt - image: ghcr.io/kubeflow/katib/suggestion-pbt:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-pbt:v0.19.0 persistentVolumeClaimSpec: accessModes: - ReadWriteMany @@ -161,7 +162,7 @@ config: storage: 5Gi earlyStoppings: - algorithmName: medianstop - image: ghcr.io/kubeflow/katib/earlystopping-medianstop:v0.18.0 + image: ghcr.io/kubeflow/katib/earlystopping-medianstop:v0.19.0 # Security features - disabled for CI simplicity networkPolicy: diff --git a/experimental/helm/charts/katib/ci/values-leader-election.yaml b/experimental/helm/charts/katib/ci/values-leader-election.yaml index 1c813d1169..86a546f0a4 100644 --- a/experimental/helm/charts/katib/ci/values-leader-election.yaml +++ b/experimental/helm/charts/katib/ci/values-leader-election.yaml @@ -3,7 +3,7 @@ global: namespace: kubeflow - imageTag: v0.18.0 + imageTag: v0.19.0 # Enable kustomize compatibility mode kustomizeMode: @@ -110,40 +110,40 @@ config: runtime: metricsCollectors: - kind: StdOut - image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.18.0 + image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.19.0 - kind: File - image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.18.0 + image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.19.0 - kind: TensorFlowEvent - image: ghcr.io/kubeflow/katib/tfevent-metrics-collector:v0.18.0 + image: ghcr.io/kubeflow/katib/tfevent-metrics-collector:v0.19.0 resources: limits: memory: 1Gi suggestions: - algorithmName: random - image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.19.0 - algorithmName: tpe - image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.19.0 - algorithmName: grid - image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.19.0 - algorithmName: hyperband - image: ghcr.io/kubeflow/katib/suggestion-hyperband:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-hyperband:v0.19.0 - algorithmName: bayesianoptimization - image: ghcr.io/kubeflow/katib/suggestion-skopt:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-skopt:v0.19.0 - algorithmName: cmaes - image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.19.0 - algorithmName: sobol - image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.19.0 - algorithmName: multivariate-tpe - image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.19.0 - algorithmName: enas - image: ghcr.io/kubeflow/katib/suggestion-enas:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-enas:v0.19.0 resources: limits: memory: 400Mi - algorithmName: darts - image: ghcr.io/kubeflow/katib/suggestion-darts:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-darts:v0.19.0 - algorithmName: pbt - image: ghcr.io/kubeflow/katib/suggestion-pbt:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-pbt:v0.19.0 persistentVolumeClaimSpec: accessModes: - ReadWriteMany @@ -152,4 +152,4 @@ config: storage: 5Gi earlyStoppings: - algorithmName: medianstop - image: ghcr.io/kubeflow/katib/earlystopping-medianstop:v0.18.0 \ No newline at end of file + image: ghcr.io/kubeflow/katib/earlystopping-medianstop:v0.19.0 \ No newline at end of file diff --git a/experimental/helm/charts/katib/ci/values-openshift.yaml b/experimental/helm/charts/katib/ci/values-openshift.yaml index 6509c4d606..56714d2658 100644 --- a/experimental/helm/charts/katib/ci/values-openshift.yaml +++ b/experimental/helm/charts/katib/ci/values-openshift.yaml @@ -3,7 +3,7 @@ global: namespace: kubeflow - imageTag: v0.18.0 + imageTag: v0.19.0 # Enable kustomize compatibility mode kustomizeMode: @@ -82,40 +82,40 @@ config: runtime: metricsCollectors: - kind: StdOut - image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.18.0 + image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.19.0 - kind: File - image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.18.0 + image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.19.0 - kind: TensorFlowEvent - image: ghcr.io/kubeflow/katib/tfevent-metrics-collector:v0.18.0 + image: ghcr.io/kubeflow/katib/tfevent-metrics-collector:v0.19.0 resources: limits: memory: 1Gi suggestions: - algorithmName: random - image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.19.0 - algorithmName: tpe - image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.19.0 - algorithmName: grid - image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.19.0 - algorithmName: hyperband - image: ghcr.io/kubeflow/katib/suggestion-hyperband:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-hyperband:v0.19.0 - algorithmName: bayesianoptimization - image: ghcr.io/kubeflow/katib/suggestion-skopt:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-skopt:v0.19.0 - algorithmName: cmaes - image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.19.0 - algorithmName: sobol - image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.19.0 - algorithmName: multivariate-tpe - image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.19.0 - algorithmName: enas - image: ghcr.io/kubeflow/katib/suggestion-enas:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-enas:v0.19.0 resources: limits: memory: 400Mi - algorithmName: darts - image: ghcr.io/kubeflow/katib/suggestion-darts:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-darts:v0.19.0 - algorithmName: pbt - image: ghcr.io/kubeflow/katib/suggestion-pbt:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-pbt:v0.19.0 persistentVolumeClaimSpec: accessModes: - ReadWriteMany @@ -124,7 +124,7 @@ config: storage: 5Gi earlyStoppings: - algorithmName: medianstop - image: ghcr.io/kubeflow/katib/earlystopping-medianstop:v0.18.0 + image: ghcr.io/kubeflow/katib/earlystopping-medianstop:v0.19.0 # Namespace creation with security labels namespaceCreate: diff --git a/experimental/helm/charts/katib/ci/values-postgres.yaml b/experimental/helm/charts/katib/ci/values-postgres.yaml index 8432682521..3e1cb687a8 100644 --- a/experimental/helm/charts/katib/ci/values-postgres.yaml +++ b/experimental/helm/charts/katib/ci/values-postgres.yaml @@ -3,7 +3,7 @@ global: namespace: kubeflow - imageTag: v0.18.0 + imageTag: v0.19.0 # Enable kustomize compatibility mode kustomizeMode: @@ -95,4 +95,67 @@ autoscaling: # Namespace creation namespaceCreate: - enabled: true \ No newline at end of file + enabled: true + +# Katib configuration +config: + katibConfig: | + apiVersion: config.kubeflow.org/v1beta1 + kind: KatibConfig + init: + certGenerator: + enable: true + controller: + webhookPort: 8443 + trialResources: + - Job.v1.batch + - TFJob.v1.kubeflow.org + - PyTorchJob.v1.kubeflow.org + - MPIJob.v1.kubeflow.org + - XGBoostJob.v1.kubeflow.org + runtime: + metricsCollectors: + - kind: StdOut + image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.19.0 + - kind: File + image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.19.0 + - kind: TensorFlowEvent + image: ghcr.io/kubeflow/katib/tfevent-metrics-collector:v0.19.0 + resources: + limits: + memory: 1Gi + suggestions: + - algorithmName: random + image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.19.0 + - algorithmName: tpe + image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.19.0 + - algorithmName: grid + image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.19.0 + - algorithmName: hyperband + image: ghcr.io/kubeflow/katib/suggestion-hyperband:v0.19.0 + - algorithmName: bayesianoptimization + image: ghcr.io/kubeflow/katib/suggestion-skopt:v0.19.0 + - algorithmName: cmaes + image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.19.0 + - algorithmName: sobol + image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.19.0 + - algorithmName: multivariate-tpe + image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.19.0 + - algorithmName: enas + image: ghcr.io/kubeflow/katib/suggestion-enas:v0.19.0 + resources: + limits: + memory: 400Mi + - algorithmName: darts + image: ghcr.io/kubeflow/katib/suggestion-darts:v0.19.0 + - algorithmName: pbt + image: ghcr.io/kubeflow/katib/suggestion-pbt:v0.19.0 + persistentVolumeClaimSpec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 5Gi + earlyStoppings: + - algorithmName: medianstop + image: ghcr.io/kubeflow/katib/earlystopping-medianstop:v0.19.0 \ No newline at end of file diff --git a/experimental/helm/charts/katib/ci/values-production.yaml b/experimental/helm/charts/katib/ci/values-production.yaml index 11ba9f0cb3..fdd066404a 100644 --- a/experimental/helm/charts/katib/ci/values-production.yaml +++ b/experimental/helm/charts/katib/ci/values-production.yaml @@ -3,7 +3,7 @@ global: namespace: kubeflow - imageTag: v0.18.0 + imageTag: v0.19.0 # Controller configuration - with leader election for HA controller: diff --git a/experimental/helm/charts/katib/ci/values-standalone.yaml b/experimental/helm/charts/katib/ci/values-standalone.yaml index e366d526f5..c88f96941b 100644 --- a/experimental/helm/charts/katib/ci/values-standalone.yaml +++ b/experimental/helm/charts/katib/ci/values-standalone.yaml @@ -3,7 +3,7 @@ global: namespace: kubeflow - imageTag: v0.18.0 + imageTag: v0.19.0 # Enable kustomize compatibility mode kustomizeMode: diff --git a/experimental/helm/charts/katib/templates/controller/rbac.yaml b/experimental/helm/charts/katib/templates/controller/rbac.yaml index 3fbd311473..54415caee7 100644 --- a/experimental/helm/charts/katib/templates/controller/rbac.yaml +++ b/experimental/helm/charts/katib/templates/controller/rbac.yaml @@ -92,15 +92,23 @@ rules: - "watch" - "create" - "delete" +- apiGroups: + - jobset.x-k8s.io + resources: + - jobsets + verbs: + - "get" + - "list" + - "watch" - apiGroups: - trainer.kubeflow.org resources: - trainjobs verbs: + - "create" - "get" - "list" - "watch" - - "create" - "delete" - apiGroups: - kubeflow.org diff --git a/experimental/helm/charts/katib/values.yaml b/experimental/helm/charts/katib/values.yaml index bde3bc6ecc..6b38ec3f29 100644 --- a/experimental/helm/charts/katib/values.yaml +++ b/experimental/helm/charts/katib/values.yaml @@ -16,7 +16,7 @@ global: # -- Image registry for Katib images imageRegistry: ghcr.io/kubeflow/katib # -- Global image tag for all Katib components - imageTag: v0.18.0 + imageTag: v0.19.0 # -- Global image pull policy imagePullPolicy: IfNotPresent # -- Global image pull secrets @@ -536,16 +536,16 @@ ui: # -- Affinity rules for UI pods affinity: {} - # -- Security context for UI pods - podSecurityContext: - seccompProfile: - type: RuntimeDefault + # -- Security context for UI pods + podSecurityContext: {} # -- Security context for UI containers securityContext: runAsNonRoot: true allowPrivilegeEscalation: false runAsUser: 1000 + seccompProfile: + type: RuntimeDefault capabilities: drop: - ALL @@ -771,6 +771,7 @@ config: controller: webhookPort: 8443 trialResources: + - TrainJob.v1alpha1.trainer.kubeflow.org - Job.v1.batch - TFJob.v1.kubeflow.org - PyTorchJob.v1.kubeflow.org @@ -779,40 +780,40 @@ config: runtime: metricsCollectors: - kind: StdOut - image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.18.0 + image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.19.0 - kind: File - image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.18.0 + image: ghcr.io/kubeflow/katib/file-metrics-collector:v0.19.0 - kind: TensorFlowEvent - image: ghcr.io/kubeflow/katib/tfevent-metrics-collector:v0.18.0 + image: ghcr.io/kubeflow/katib/tfevent-metrics-collector:v0.19.0 resources: limits: memory: 1Gi suggestions: - algorithmName: random - image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.19.0 - algorithmName: tpe - image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-hyperopt:v0.19.0 - algorithmName: grid - image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.19.0 - algorithmName: hyperband - image: ghcr.io/kubeflow/katib/suggestion-hyperband:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-hyperband:v0.19.0 - algorithmName: bayesianoptimization - image: ghcr.io/kubeflow/katib/suggestion-skopt:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-skopt:v0.19.0 - algorithmName: cmaes - image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.19.0 - algorithmName: sobol - image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-goptuna:v0.19.0 - algorithmName: multivariate-tpe - image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-optuna:v0.19.0 - algorithmName: enas - image: ghcr.io/kubeflow/katib/suggestion-enas:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-enas:v0.19.0 resources: limits: memory: 400Mi - algorithmName: darts - image: ghcr.io/kubeflow/katib/suggestion-darts:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-darts:v0.19.0 - algorithmName: pbt - image: ghcr.io/kubeflow/katib/suggestion-pbt:v0.18.0 + image: ghcr.io/kubeflow/katib/suggestion-pbt:v0.19.0 persistentVolumeClaimSpec: accessModes: - ReadWriteMany @@ -821,24 +822,24 @@ config: storage: 5Gi earlyStoppings: - algorithmName: medianstop - image: ghcr.io/kubeflow/katib/earlystopping-medianstop:v0.18.0 + image: ghcr.io/kubeflow/katib/earlystopping-medianstop:v0.19.0 # Trial templates configuration trialTemplates: # Default trial template configuration defaultTrialTemplate: # -- Default trial template container image - image: "ghcr.io/kubeflow/katib/pytorch-mnist-cpu:v0.18.0" + image: "ghcr.io/kubeflow/katib/pytorch-mnist-cpu:v0.19.0" # ENAS CPU template configuration enasCPUTemplate: # -- ENAS CPU template container image - image: "ghcr.io/kubeflow/katib/enas-cnn-cifar10-cpu:v0.18.0" + image: "ghcr.io/kubeflow/katib/enas-cnn-cifar10-cpu:v0.19.0" # PyTorch Job template configuration pytorchJobTemplate: # -- PyTorch Job template container image - image: "ghcr.io/kubeflow/katib/pytorch-mnist-cpu:v0.18.0" + image: "ghcr.io/kubeflow/katib/pytorch-mnist-cpu:v0.19.0" # -- Number of worker replicas for PyTorch Job workerReplicas: 2 diff --git a/experimental/helm/charts/kserve-models-web-app/templates/configmap.yaml b/experimental/helm/charts/kserve-models-web-app/templates/configmap.yaml index fc2a480d80..3fd8b53711 100644 --- a/experimental/helm/charts/kserve-models-web-app/templates/configmap.yaml +++ b/experimental/helm/charts/kserve-models-web-app/templates/configmap.yaml @@ -21,6 +21,7 @@ data: {{- if .Values.kubeflow.enabled }} USERID_HEADER: {{ .Values.kubeflow.config.useridHeader | quote }} APP_PREFIX: {{ .Values.kubeflow.config.appPrefix | quote }} + USERID_PREFIX: {{ .Values.kubeflow.config.useridPrefix | quote }} {{- else }} APP_DISABLE_AUTH: "True" {{- end }} diff --git a/experimental/helm/charts/kserve-models-web-app/values.yaml b/experimental/helm/charts/kserve-models-web-app/values.yaml index 5e3bd6751f..b86b534ea6 100644 --- a/experimental/helm/charts/kserve-models-web-app/values.yaml +++ b/experimental/helm/charts/kserve-models-web-app/values.yaml @@ -242,6 +242,7 @@ kubeflow: disableAuth: false useridHeader: "kubeflow-userid" appPrefix: "/kserve-endpoints" + useridPrefix: "" # Monitoring configuration monitoring: diff --git a/experimental/helm/charts/model-registry/ci/ci-values.yaml b/experimental/helm/charts/model-registry/ci/ci-values.yaml index 352e35ff12..cedd00b594 100644 --- a/experimental/helm/charts/model-registry/ci/ci-values.yaml +++ b/experimental/helm/charts/model-registry/ci/ci-values.yaml @@ -12,7 +12,7 @@ server: dataStoreType: embedmd image: - tag: "v0.3.0" + tag: "v0.3.3" # Configure readiness probe rest: diff --git a/experimental/helm/charts/model-registry/ci/values-db.yaml b/experimental/helm/charts/model-registry/ci/values-db.yaml index d5098a5e99..96d2eb3b00 100644 --- a/experimental/helm/charts/model-registry/ci/values-db.yaml +++ b/experimental/helm/charts/model-registry/ci/values-db.yaml @@ -10,7 +10,7 @@ server: replicas: 1 dataStoreType: embedmd image: - tag: "v0.3.0" + tag: "v0.3.3" resources: limits: cpu: 200m diff --git a/experimental/helm/charts/model-registry/ci/values-postgres.yaml b/experimental/helm/charts/model-registry/ci/values-postgres.yaml index 5b61c2ce98..88e890bdd8 100644 --- a/experimental/helm/charts/model-registry/ci/values-postgres.yaml +++ b/experimental/helm/charts/model-registry/ci/values-postgres.yaml @@ -10,7 +10,7 @@ server: replicas: 1 dataStoreType: embedmd image: - tag: "v0.3.0" + tag: "v0.3.3" resources: limits: cpu: 200m diff --git a/experimental/helm/charts/model-registry/ci/values-ui-integrated.yaml b/experimental/helm/charts/model-registry/ci/values-ui-integrated.yaml index 3da56db4c9..5dcf2b22f0 100644 --- a/experimental/helm/charts/model-registry/ci/values-ui-integrated.yaml +++ b/experimental/helm/charts/model-registry/ci/values-ui-integrated.yaml @@ -5,7 +5,7 @@ ui: image: repository: ui - tag: "v0.3.0" + tag: "v0.3.3" pullPolicy: Always containerPort: 8080 diff --git a/experimental/helm/charts/model-registry/ci/values-ui-istio.yaml b/experimental/helm/charts/model-registry/ci/values-ui-istio.yaml index 7d423d94c7..125c5e2272 100644 --- a/experimental/helm/charts/model-registry/ci/values-ui-istio.yaml +++ b/experimental/helm/charts/model-registry/ci/values-ui-istio.yaml @@ -8,8 +8,8 @@ ui: replicas: 1 image: - repository: ui - tag: "v0.3.0" + repository: ui + tag: "v0.3.3" pullPolicy: Always containerPort: 8080 diff --git a/experimental/helm/charts/model-registry/ci/values-ui-standalone.yaml b/experimental/helm/charts/model-registry/ci/values-ui-standalone.yaml index 6c97c0f4ac..8e2a42e75b 100644 --- a/experimental/helm/charts/model-registry/ci/values-ui-standalone.yaml +++ b/experimental/helm/charts/model-registry/ci/values-ui-standalone.yaml @@ -9,7 +9,7 @@ ui: image: repository: ui - tag: "v0.3.0" + tag: "v0.3.3" pullPolicy: Always containerPort: 8080 diff --git a/experimental/helm/charts/model-registry/ci/values-ui.yaml b/experimental/helm/charts/model-registry/ci/values-ui.yaml index 98dac486e9..660161436f 100644 --- a/experimental/helm/charts/model-registry/ci/values-ui.yaml +++ b/experimental/helm/charts/model-registry/ci/values-ui.yaml @@ -5,7 +5,7 @@ ui: image: repository: ui - tag: "v0.3.0" + tag: "v0.3.3" pullPolicy: Always containerPort: 8080 diff --git a/experimental/helm/charts/model-registry/values.yaml b/experimental/helm/charts/model-registry/values.yaml index 3281ef6ff8..64cab7973b 100644 --- a/experimental/helm/charts/model-registry/values.yaml +++ b/experimental/helm/charts/model-registry/values.yaml @@ -42,7 +42,7 @@ server: # -- Server image repository repository: server # -- Server image tag (overrides global.imageTag if set) - tag: "v0.3.0" + tag: "v0.3.3" # -- Server image pull policy (overrides global.imagePullPolicy if set) pullPolicy: "" @@ -178,7 +178,7 @@ ui: # -- UI image repository repository: model-registry-ui # -- UI image tag - tag: "v0.3.0" + tag: "v0.3.3" # -- UI image pull policy pullPolicy: "" diff --git a/experimental/helm/charts/pipelines/Chart.yaml b/experimental/helm/charts/pipelines/Chart.yaml new file mode 100644 index 0000000000..60671a60b2 --- /dev/null +++ b/experimental/helm/charts/pipelines/Chart.yaml @@ -0,0 +1,29 @@ +apiVersion: v2 + +name: kubeflow-pipelines + +description: A Helm chart for Kubeflow Pipelines - ML Workflows on Kubernetes + +version: 2.15.0 + +appVersion: 2.15.0 + +home: https://github.com/kubeflow/pipelines + +icon: https://github.com/kubeflow/website/blob/master/assets/icons/logo.svg + +sources: +- https://github.com/kubeflow/pipelines +- https://github.com/kubeflow/kubeflow +dependencies: + - name: argo-workflows + version: "~0.40.0" + condition: thirdParty.argo.enabled + repository: "https://argoproj.github.io/argo-helm" + - name: mysql + version: "~14.0.0" + condition: mysql.enabled + repository: "https://charts.bitnami.com/bitnami" +annotations: + category: Machine Learning + licenses: Apache-2.0 diff --git a/experimental/helm/charts/pipelines/README.md b/experimental/helm/charts/pipelines/README.md new file mode 100644 index 0000000000..4a0580d1fd --- /dev/null +++ b/experimental/helm/charts/pipelines/README.md @@ -0,0 +1,3 @@ +# Kubeflow Pipelines Helm Chart + +This Helm chart deploys Kubeflow Pipelines on a Kubernetes cluster using the Helm package manager. diff --git a/experimental/helm/charts/pipelines/ci/values-platform-agnostic-multi-user-k8s-native.yaml b/experimental/helm/charts/pipelines/ci/values-platform-agnostic-multi-user-k8s-native.yaml new file mode 100644 index 0000000000..77be03bcb8 --- /dev/null +++ b/experimental/helm/charts/pipelines/ci/values-platform-agnostic-multi-user-k8s-native.yaml @@ -0,0 +1,125 @@ +# Values for platform-agnostic multi-user k8s-native mode +# Pipeline definitions stored as Kubernetes Resources + +global: + namespace: kubeflow + imageTag: 2.15.0 + security: + allowInsecureImages: true + +installMode: + type: multi-user + pipelineDefinition: + storage: k8s-native + +# API Server configuration for k8s-native mode +apiServer: + # Use local image for k8s-native mode + image: + repository: domain.local/apiserver + tag: local + # K8s-native specific configuration + k8sNative: + enabled: true + command: + - "/bin/apiserver" + args: + - "--config=/config" + - "--sampleconfig=/config/sample_config.json" + - "-logtostderr=true" + - "--webhookTLSCertPath=/etc/webhook/certs/tls.crt" + - "--webhookTLSKeyPath=/etc/webhook/certs/tls.key" + - "--pipelinesStoreKubernetes=true" + webhookPort: 8443 + volumeMounts: + - name: webhook-certs + mountPath: /etc/webhook/certs + readOnly: true + volumes: + - name: webhook-certs + secret: + secretName: kfp-api-webhook-cert + +# CRDs +crds: + install: true + # webhook should match pipelineDefinition.storage: false for database mode, true for k8s-native mode + webhook: true + +# Enable cert-manager integration +certManager: + enabled: true + +# Enable metadata +metadata: + enabled: true + +viewerCrd: + additionalEnv: + - name: NAMESPACE + value: "" + - name: MAX_NUM_VIEWERS + value: "50" + +scheduledWorkflow: + additionalEnv: + - name: NAMESPACE + value: "" + - name: LOG_LEVEL + value: "info" + +persistenceAgent: + additionalEnv: + - name: NAMESPACE + value: "" + + + +# Third-party components +thirdParty: + argo: + enabled: true + mysql: + enabled: true + metacontroller: + enabled: true + +# MySQL configuration (disabled - using external MySQL like Kustomize) +mysql: + enabled: false + +# External MySQL configuration +externalDatabase: + enabled: true + host: "mysql" + port: 3306 + database: "mlpipeline" + username: "root" + password: "" + +# SeaweedFS configuration +seaweedfs: + enabled: true + bucket: "mlpipeline" + s3EndpointUrl: "http://seaweedfs.kubeflow:8333" + +# Profile controller +profileController: + enabled: true + disableIstioSidecar: "false" + artifactsProxyEnabled: "false" + artifactRetentionDays: "-1" + +# Networking +networking: + istio: + enabled: true + gateway: "kubeflow-gateway" + virtualService: + enabled: true + +# Webhooks enabled for k8s-native mode +webhooks: + enabled: true + failurePolicy: "Fail" + diff --git a/experimental/helm/charts/pipelines/ci/values-platform-agnostic-multi-user.yaml b/experimental/helm/charts/pipelines/ci/values-platform-agnostic-multi-user.yaml new file mode 100644 index 0000000000..1800dd9e23 --- /dev/null +++ b/experimental/helm/charts/pipelines/ci/values-platform-agnostic-multi-user.yaml @@ -0,0 +1,96 @@ +# Values for platform-agnostic multi-user mode +# Pipeline definitions stored in the database + +global: + namespace: kubeflow + imageTag: 2.15.0 + security: + allowInsecureImages: true + +installMode: + type: multi-user + pipelineDefinition: + storage: database + +# CRDs +crds: + install: true + application: false + # webhook should match pipelineDefinition.storage: false for database mode, true for k8s-native mode + webhook: false + +# Enable cert-manager integration +certManager: + enabled: true + +# Enable metadata +metadata: + enabled: true + +viewerCrd: + additionalEnv: + - name: NAMESPACE + value: "" + - name: MAX_NUM_VIEWERS + value: "50" + +scheduledWorkflow: + additionalEnv: + - name: NAMESPACE + value: "" + - name: LOG_LEVEL + value: "info" + +persistenceAgent: + additionalEnv: + - name: NAMESPACE + value: "" + +# Third-party components +thirdParty: + argo: + enabled: true + mysql: + enabled: true + metacontroller: + enabled: true + + +# MySQL configuration (disabled - using external MySQL like Kustomize) +mysql: + enabled: false + +# External MySQL configuration +externalDatabase: + enabled: true + host: "mysql" + port: 3306 + database: "mlpipeline" + username: "root" + password: "" + +# SeaweedFS configuration +seaweedfs: + enabled: true + bucket: "mlpipeline" + s3EndpointUrl: "http://seaweedfs.kubeflow:8333" + +# Profile controller +profileController: + enabled: true + disableIstioSidecar: "false" + artifactsProxyEnabled: "false" + artifactRetentionDays: "-1" + +# Networking +networking: + istio: + enabled: true + gateway: "kubeflow-gateway" + virtualService: + enabled: true + +# Webhooks disabled for database mode +webhooks: + enabled: false + diff --git a/experimental/helm/charts/pipelines/files/sync.py b/experimental/helm/charts/pipelines/files/sync.py new file mode 100644 index 0000000000..6ea4dc1c35 --- /dev/null +++ b/experimental/helm/charts/pipelines/files/sync.py @@ -0,0 +1,413 @@ +# 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 + +# From awscli installed in alpine/k8s image +import botocore.session + +S3_BUCKET_NAME = 'mlpipeline' + +session = botocore.session.get_session() +# To interact with seaweedfs user management. Region does not matter. +iam = session.create_client('iam', region_name='foobar') +# S3 client for lifecycle policy management +s3_endpoint_url = os.environ.get("S3_ENDPOINT_URL", "http://seaweedfs.kubeflow:8333") +s3 = session.create_client('s3', region_name='foobar', endpoint_url=s3_endpoint_url) + + +def main(): + settings = get_settings_from_env() + server = server_factory(**settings) + server.serve_forever() + + +def get_settings_from_env(controller_port=None, + frontend_image=None, + frontend_tag=None, + disable_istio_sidecar=None, + artifacts_proxy_enabled=None, + artifact_retention_days=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: + frontend_image: ghcr.io/kubeflow/kfp-frontend + frontend_tag: value of KFP_VERSION environment variable + disable_istio_sidecar: Required (no default) + """ + settings = dict() + settings["controller_port"] = \ + controller_port or \ + os.environ.get("CONTROLLER_PORT", "8080") + + settings["frontend_image"] = \ + frontend_image or \ + os.environ.get("FRONTEND_IMAGE", "ghcr.io/kubeflow/kfp-frontend") + + settings["artifacts_proxy_enabled"] = \ + artifacts_proxy_enabled or \ + os.environ.get("ARTIFACTS_PROXY_ENABLED", "false") + + settings["artifact_retention_days"] = \ + artifact_retention_days or \ + os.environ.get("ARTIFACT_RETENTION_DAYS", -1) + + # Look for specific tags for each image first, falling back to + # previously used KFP_VERSION environment variable for backwards + # compatibility + 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" + + return settings + + +def server_factory(frontend_image, + frontend_tag, + disable_istio_sidecar, + artifacts_proxy_enabled, + artifact_retention_days, + url="", + controller_port=8080): + """ + Returns an HTTPServer populated with Handler with customized settings + """ + class Controller(BaseHTTPRequestHandler): + def upsert_lifecycle_policy(self, bucket_name, artifact_retention_days): + """Configures or deletes the lifecycle policy based on the artifact_retention_days string.""" + try: + retention_days = int(artifact_retention_days) + except ValueError: + print(f"ERROR: ARTIFACT_RETENTION_DAYS value '{artifact_retention_days}' is not a valid integer. Aborting policy update.") + return + + # To disable lifecycle policy we need to delete it + if retention_days <= 0: + print(f"ARTIFACT_RETENTION_DAYS is non-positive ({retention_days} days). Attempting to delete lifecycle policy.") + try: + response = s3.get_bucket_lifecycle_configuration(Bucket=bucket_name) + # Check if there are any enabled rules + has_enabled_rules = any(rule.get('Status') == 'Enabled' for rule in response.get('Rules', [])) + + if has_enabled_rules: + s3.delete_bucket_lifecycle(Bucket=bucket_name) + print("Successfully deleted lifecycle policy.") + else: + print("No enabled lifecycle rules found to delete.") + except Exception: + print(f"Warning: No lifecycle policy exists") + return + + # Create/update lifecycle policy + life_cycle_policy = { + "Rules": [ + { + "Status": "Enabled", + "Filter": {"Prefix": "private-artifacts"}, + "Expiration": {"Days": retention_days}, + "ID": "private-artifacts", + }, + ] + } + print('upsert_lifecycle_policy:', life_cycle_policy) + + try: + api_response = s3.put_bucket_lifecycle_configuration( + Bucket=bucket_name, + LifecycleConfiguration = life_cycle_policy + ) + print('Lifecycle policy configured successfully:', api_response) + except Exception as exception: + if hasattr(exception, 'response') and 'Error' in exception.response: + print(f"ERROR: Failed to configure lifecycle policy: {exception.response['Error']['Code']} - {exception}") + else: + print(f"ERROR: Failed to configure lifecycle policy: {exception}") + + + def sync(self, parent, attachments): + # 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": {}, "attachments": []} + + # Compute status based on observed state. + desired_status = { + "kubeflow-pipelines-ready": + len(attachments["Secret.v1"]) == 1 and + len(attachments["ConfigMap.v1"]) == 3 and + len(attachments["Deployment.apps/v1"]) == (1 if artifacts_proxy_enabled.lower() == "true" else 0) and + len(attachments["Service.v1"]) == (1 if artifacts_proxy_enabled.lower() == "true" else 0) and + "True" or "False" + } + + # Generate the desired attachment object(s). + desired_resources = [ + { + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": { + "name": "kfp-launcher", + "namespace": namespace, + }, + "data": { + "defaultPipelineRoot": f"minio://{S3_BUCKET_NAME}/private-artifacts/{namespace}/v2/artifacts", + }, + }, + { + "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", + }, + }, + { + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": { + "name": "artifact-repositories", + "namespace": namespace, + "annotations": { + "workflows.argoproj.io/default-artifact-repository": "default-namespaced" + } + }, + "data": { + "default-namespaced": json.dumps({ + "archiveLogs": True, + "s3": { + "endpoint": "minio-service.kubeflow:9000", + "bucket": S3_BUCKET_NAME, + "keyFormat": f"private-artifacts/{namespace}/{{{{workflow.name}}}}/{{{{workflow.creationTimestamp.Y}}}}/{{{{workflow.creationTimestamp.m}}}}/{{{{workflow.creationTimestamp.d}}}}/{{{{pod.name}}}}", + "insecure": True, + "accessKeySecret": { + "name": "mlpipeline-minio-artifact", + "key": "accesskey", + }, + "secretKeySecret": { + "name": "mlpipeline-minio-artifact", + "key": "secretkey", + } + } + }) + } + }, + ] + + # Add artifact fetcher related resources if enabled + if artifacts_proxy_enabled.lower() == "true": + desired_resources.extend([ + { + "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" + } + } + }, + { + "name": "ML_PIPELINE_SERVICE_HOST", + "value": "ml-pipeline.kubeflow.svc.cluster.local" + }, + { + "name": "ML_PIPELINE_SERVICE_PORT", + "value": "8888" + }, + { + "name": "FRONTEND_SERVER_NAMESPACE", + "value": namespace, + } + ], + "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. + + # Check if secret is already there when the controller made the request. If yes, then + # use it. Else create a new credentials on seaweedfs for the namespace. + if s3_secret := attachments["Secret.v1"].get(f"{namespace}/mlpipeline-minio-artifact"): + desired_resources.append(s3_secret) + print('Using existing secret') + else: + print('Creating new access key.') + s3_access_key = iam.create_access_key(UserName=namespace) + # Use the AWS IAM API of seaweedfs to manage access policies to bucket. + # This policy ensures that a user can only access artifacts from his own profile. + iam.put_user_policy( + UserName=namespace, + PolicyName=f"KubeflowProject{namespace}", + PolicyDocument=json.dumps( + { + "Version": "2012-10-17", + "Statement": [{ + "Effect": "Allow", + "Action": [ + "s3:Put*", + "s3:Get*", + "s3:List*" + ], + "Resource": [ + f"arn:aws:s3:::{S3_BUCKET_NAME}/artifacts/*", + f"arn:aws:s3:::{S3_BUCKET_NAME}/private-artifacts/{namespace}/*", + f"arn:aws:s3:::{S3_BUCKET_NAME}/private/{namespace}/*", + f"arn:aws:s3:::{S3_BUCKET_NAME}/shared/*", + ] + }] + }) + ) + + self.upsert_lifecycle_policy(S3_BUCKET_NAME, artifact_retention_days) + + desired_resources.insert( + 0, + { + "apiVersion": "v1", + "kind": "Secret", + "metadata": { + "name": "mlpipeline-minio-artifact", + "namespace": namespace, + }, + "data": { + "accesskey": base64.b64encode(s3_access_key["AccessKey"]["AccessKeyId"].encode('utf-8')).decode("utf-8"), + "secretkey": base64.b64encode(s3_access_key["AccessKey"]["SecretAccessKey"].encode('utf-8')).decode("utf-8"), + }, + }) + + return {"status": desired_status, "attachments": 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["object"], observed["attachments"]) + + 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() diff --git a/experimental/helm/charts/pipelines/templates/_helpers.tpl b/experimental/helm/charts/pipelines/templates/_helpers.tpl new file mode 100644 index 0000000000..95becc66e1 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/_helpers.tpl @@ -0,0 +1,538 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "kubeflow-pipelines.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "kubeflow-pipelines.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "kubeflow-pipelines.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "kubeflow-pipelines.labels" -}} +app.kubernetes.io/component: ml-pipeline +app.kubernetes.io/name: kubeflow-pipelines +application-crd-id: kubeflow-pipelines +{{- with .Values.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{/* +Authorization Policy labels - includes application-crd-id for multi-user mode +*/}} +{{- define "kubeflow-pipelines.authorizationPolicyLabels" -}} +app.kubernetes.io/component: ml-pipeline +app.kubernetes.io/name: kubeflow-pipelines +application-crd-id: kubeflow-pipelines +{{- with .Values.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "kubeflow-pipelines.selectorLabels" -}} +app.kubernetes.io/name: {{ include "kubeflow-pipelines.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Cache server labels +*/}} +{{- define "kubeflow-pipelines.cacheLabels" -}} +app: cache-server +app.kubernetes.io/component: ml-pipeline +app.kubernetes.io/name: kubeflow-pipelines +application-crd-id: kubeflow-pipelines +{{- with .Values.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{/* +ML Pipeline specific labels - matching original manifests +*/}} +{{- define "kubeflow-pipelines.mlPipelineLabels" -}} +app: ml-pipeline +app.kubernetes.io/component: ml-pipeline +app.kubernetes.io/name: kubeflow-pipelines +application-crd-id: kubeflow-pipelines +{{- with .Values.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{/* +ML Pipeline UI labels +*/}} +{{- define "kubeflow-pipelines.uiLabels" -}} +app: ml-pipeline-ui +app.kubernetes.io/component: ml-pipeline +app.kubernetes.io/name: kubeflow-pipelines +application-crd-id: kubeflow-pipelines +{{- with .Values.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{/* +ML Pipeline selector labels +*/}} +{{- define "kubeflow-pipelines.mlPipelineSelectorLabels" -}} +app: ml-pipeline +app.kubernetes.io/component: ml-pipeline +app.kubernetes.io/name: kubeflow-pipelines +application-crd-id: kubeflow-pipelines +{{- end }} + +{{/* +Cache server selector labels +*/}} +{{- define "kubeflow-pipelines.cacheSelectorLabels" -}} +app: cache-server +app.kubernetes.io/component: ml-pipeline +app.kubernetes.io/name: kubeflow-pipelines +application-crd-id: kubeflow-pipelines +{{- end }} + +{{/* +UI selector labels +*/}} +{{- define "kubeflow-pipelines.uiSelectorLabels" -}} +app: ml-pipeline-ui +app.kubernetes.io/component: ml-pipeline +app.kubernetes.io/name: kubeflow-pipelines +application-crd-id: kubeflow-pipelines +{{- end }} + +{{/* +Viewer CRD labels +*/}} +{{- define "kubeflow-pipelines.viewerCrdLabels" -}} +{{- if eq .Values.installMode.type "multi-user" }} +app.kubernetes.io/component: ml-pipeline +app.kubernetes.io/name: kubeflow-pipelines +app: ml-pipeline-viewer-crd +{{- if .Values.installMode.legacyLabels }} +application-crd-id: kubeflow-pipelines +{{- end }} +{{- else }} +app: ml-pipeline-viewer-crd +app.kubernetes.io/component: ml-pipeline +app.kubernetes.io/name: kubeflow-pipelines +{{- if ne .Values.installMode.includeApplicationCrdId false }} +application-crd-id: kubeflow-pipelines +{{- end }} +{{- with .Values.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Viewer CRD selector labels +*/}} +{{- define "kubeflow-pipelines.viewerCrdSelectorLabels" -}} +app: ml-pipeline-viewer-crd +app.kubernetes.io/component: ml-pipeline +app.kubernetes.io/name: kubeflow-pipelines +application-crd-id: kubeflow-pipelines +{{- end }} + +{{/* +Visualization server labels +*/}} +{{- define "kubeflow-pipelines.visualizationLabels" -}} +app: ml-pipeline-visualizationserver +app.kubernetes.io/component: ml-pipeline +app.kubernetes.io/name: kubeflow-pipelines +application-crd-id: kubeflow-pipelines +{{- with .Values.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{/* +Visualization server selector labels +*/}} +{{- define "kubeflow-pipelines.visualizationSelectorLabels" -}} +app: ml-pipeline-visualizationserver +app.kubernetes.io/component: ml-pipeline +app.kubernetes.io/name: kubeflow-pipelines +application-crd-id: kubeflow-pipelines +{{- end }} + +{{/* +MySQL selector labels +*/}} +{{- define "kubeflow-pipelines.mysqlSelectorLabels" -}} +app: mysql +application-crd-id: kubeflow-pipelines +{{- end }} + + +{{/* +Metadata GRPC selector labels +*/}} +{{- define "kubeflow-pipelines.metadataGrpcSelectorLabels" -}} +component: metadata-grpc-server +application-crd-id: kubeflow-pipelines +{{- end }} + +{{/* +Metadata Envoy selector labels +*/}} +{{- define "kubeflow-pipelines.metadataEnvoySelectorLabels" -}} +component: metadata-envoy +application-crd-id: kubeflow-pipelines +{{- end }} + +{{/* +Metadata writer selector labels +*/}} +{{- define "kubeflow-pipelines.metadataWriterSelectorLabels" -}} +app: metadata-writer +app.kubernetes.io/component: ml-pipeline +app.kubernetes.io/name: kubeflow-pipelines +application-crd-id: kubeflow-pipelines +{{- end }} + +{{/* +Persistence agent selector labels +*/}} +{{- define "kubeflow-pipelines.persistenceAgentSelectorLabels" -}} +app: ml-pipeline-persistenceagent +app.kubernetes.io/component: ml-pipeline +app.kubernetes.io/name: kubeflow-pipelines +application-crd-id: kubeflow-pipelines +{{- end }} + +{{/* +Scheduled workflow selector labels +*/}} +{{- define "kubeflow-pipelines.scheduledWorkflowSelectorLabels" -}} +app: ml-pipeline-scheduledworkflow +app.kubernetes.io/component: ml-pipeline +app.kubernetes.io/name: kubeflow-pipelines +application-crd-id: kubeflow-pipelines +{{- end }} + +{{/* +Workflow controller selector labels +*/}} +{{- define "kubeflow-pipelines.workflowControllerSelectorLabels" -}} +app: workflow-controller +application-crd-id: kubeflow-pipelines +{{- end }} + +{{/* +Create the name of the service account to use for API Server +*/}} +{{- define "kubeflow-pipelines.apiServer.serviceAccountName" -}} +{{- if .Values.apiServer.serviceAccount.create }} +{{- default "ml-pipeline" .Values.apiServer.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.apiServer.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the service account to use for Persistence Agent +*/}} +{{- define "kubeflow-pipelines.persistenceAgent.serviceAccountName" -}} +{{- if .Values.persistenceAgent.serviceAccount.create }} +{{- default "ml-pipeline-persistenceagent" .Values.persistenceAgent.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.persistenceAgent.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the service account to use for Scheduled Workflow +*/}} +{{- define "kubeflow-pipelines.scheduledWorkflow.serviceAccountName" -}} +{{- if .Values.scheduledWorkflow.serviceAccount.create }} +{{- default "ml-pipeline-scheduledworkflow" .Values.scheduledWorkflow.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.scheduledWorkflow.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the service account to use for UI +*/}} +{{- define "kubeflow-pipelines.ui.serviceAccountName" -}} +{{- if .Values.ui.serviceAccount.create }} +{{- default "ml-pipeline-ui" .Values.ui.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.ui.serviceAccount.name }} +{{- end }} +{{- end }} + + + +{{/* +Create the name of the service account to use for Cache Server +*/}} +{{- define "kubeflow-pipelines.cache.serviceAccountName" -}} +{{- if .Values.cache.serviceAccount.create }} +{{- default "kubeflow-pipelines-cache" .Values.cache.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.cache.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the service account to use for Metadata +*/}} +{{- define "kubeflow-pipelines.metadata.serviceAccountName" -}} +{{- if .Values.metadata.grpc.serviceAccount.create }} +{{- default "metadata-grpc-server" .Values.metadata.grpc.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.metadata.grpc.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the service account to use for Viewer CRD Controller +*/}} +{{- define "kubeflow-pipelines.viewerCrd.serviceAccountName" -}} +{{- if .Values.viewerCrd.serviceAccount.create }} +{{- default "ml-pipeline-viewer-crd-service-account" .Values.viewerCrd.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.viewerCrd.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the service account to use for Visualization Server +*/}} +{{- define "kubeflow-pipelines.visualization.serviceAccountName" -}} +{{- if .Values.visualization.serviceAccount.create }} +{{- default "ml-pipeline-visualizationserver" .Values.visualization.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.visualization.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the service account to use for Metadata Writer +*/}} +{{- define "kubeflow-pipelines.metadataWriter.serviceAccountName" -}} +{{- if .Values.metadataWriter.serviceAccount.create }} +{{- default "kubeflow-pipelines-metadata-writer" .Values.metadataWriter.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.metadataWriter.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Database configuration helpers (MySQL only) +*/}} +{{- define "kubeflow-pipelines.database.host" -}} +{{- if .Values.mysql.enabled -}} +mysql +{{- else -}} +{{- .Values.externalDatabase.host | default "mysql.kubeflow.svc.cluster.local" }} +{{- end -}} +{{- end }} + +{{- define "kubeflow-pipelines.database.port" -}} +{{- if .Values.mysql.enabled -}} +3306 +{{- else -}} +{{- .Values.externalDatabase.port | default 3306 }} +{{- end -}} +{{- end }} + +{{- define "kubeflow-pipelines.database.name" -}} +{{- if .Values.mysql.enabled -}} +{{- .Values.mysql.auth.database | default "mlpipeline" }} +{{- else -}} +{{- .Values.externalDatabase.database }} +{{- end -}} +{{- end }} + +{{- define "kubeflow-pipelines.database.username" -}} +{{- if .Values.mysql.enabled -}} +{{- .Values.mysql.auth.username | default "root" }} +{{- else -}} +{{- .Values.externalDatabase.username }} +{{- end -}} +{{- end }} + +{{- define "kubeflow-pipelines.database.secretName" -}} +{{- if .Values.externalDatabase.existingSecret -}} +{{- .Values.externalDatabase.existingSecret }} +{{- else -}} +mysql-secret +{{- end -}} +{{- end }} + +{{- define "kubeflow-pipelines.database.secretKey" -}} +{{- if .Values.externalDatabase.existingSecret -}} +{{- .Values.externalDatabase.existingSecretPasswordKey | default "password" }} +{{- else if .Values.mysql.enabled -}} +mysql-password +{{- else -}} +password +{{- end -}} +{{- end }} + +{{/* +Object storage configuration helpers (SeaweedFS only) +*/}} +{{- define "kubeflow-pipelines.objectStore.bucket" -}} +{{- .Values.seaweedfs.bucket | default "mlpipeline" }} +{{- end }} + +{{- define "kubeflow-pipelines.objectStore.secretName" -}} +mlpipeline-minio-artifact +{{- end }} + +{{/* +Image helpers +*/}} +{{- define "kubeflow-pipelines.image" -}} +{{- $registry := .context.Values.global.imageRegistry -}} +{{- $repository := .repository -}} +{{- $tag := .tag | default .context.Values.global.imageTag | default .context.Chart.AppVersion -}} +{{- printf "%s/%s:%s" $registry $repository $tag -}} +{{- end }} + +{{/* +Image pull policy +*/}} +{{- define "kubeflow-pipelines.imagePullPolicy" -}} +{{- .pullPolicy | default .context.Values.global.imagePullPolicy -}} +{{- end }} + +{{/* +Image pull secrets +*/}} +{{- define "kubeflow-pipelines.imagePullSecrets" -}} +{{- if .Values.global.imagePullSecrets }} +imagePullSecrets: +{{- range .Values.global.imagePullSecrets }} + - name: {{ . }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Environment detection helpers +*/}} +{{- define "kubeflow-pipelines.isMultiUser" -}} +{{- eq .Values.installMode.type "multi-user" -}} +{{- end }} + +{{- define "kubeflow-pipelines.isGeneric" -}} +{{- eq .Values.installMode.type "generic" -}} +{{- end }} + +{{/* +Namespace helper +*/}} +{{- define "kubeflow-pipelines.namespace" -}} +{{- .Values.global.namespace | default .Release.Namespace -}} +{{- end }} + +{{/* +Common annotations +*/}} +{{- define "kubeflow-pipelines.annotations" -}} +{{- with .Values.commonAnnotations }} +{{ toYaml . }} +{{- end }} +{{- with .Values.global.annotations }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{/* +Common environment variables for all components +*/}} +{{- define "kubeflow-pipelines.commonEnv" -}} +- name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace +{{- if .Values.global.logLevel }} +- name: LOG_LEVEL + value: {{ .Values.global.logLevel | quote }} +{{- end }} +{{- end }} + +{{/* +Database environment variables +*/}} +{{- define "kubeflow-pipelines.databaseEnv" -}} +- name: DBCONFIG_HOST + value: {{ include "kubeflow-pipelines.database.host" . | quote }} +- name: DBCONFIG_PORT + value: {{ include "kubeflow-pipelines.database.port" . | quote }} +- name: DBCONFIG_DBNAME + value: {{ include "kubeflow-pipelines.database.name" . | quote }} +- name: DBCONFIG_USER + valueFrom: + secretKeyRef: + name: {{ include "kubeflow-pipelines.database.secretName" . }} + key: username +- name: DBCONFIG_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "kubeflow-pipelines.database.secretName" . }} + key: {{ include "kubeflow-pipelines.database.secretKey" . }} +- name: DB_DRIVER_NAME + value: {{ .Values.externalDatabase.type | default "mysql" | quote }} +{{- if .Values.database.connectionMaxLifetime }} +- name: DBCONFIG_CONMAXLIFETIME + value: {{ .Values.database.connectionMaxLifetime | quote }} +{{- end }} +{{- end }} + +{{/* +Object store environment variables +*/}} +{{- define "kubeflow-pipelines.objectStoreEnv" -}} +- name: OBJECTSTORECONFIG_SECURE + value: {{ include "kubeflow-pipelines.objectStore.secure" . | quote }} +- name: OBJECTSTORECONFIG_BUCKETNAME + value: {{ include "kubeflow-pipelines.objectStore.bucket" . | quote }} +- name: OBJECTSTORECONFIG_ACCESSKEY + valueFrom: + secretKeyRef: + name: {{ include "kubeflow-pipelines.objectStore.secretName" . }} + key: accesskey +- name: OBJECTSTORECONFIG_SECRETACCESSKEY + valueFrom: + secretKeyRef: + name: {{ include "kubeflow-pipelines.objectStore.secretName" . }} + key: secretkey +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/api-server/deployment.yaml b/experimental/helm/charts/pipelines/templates/api-server/deployment.yaml new file mode 100644 index 0000000000..ffd1058bd1 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/api-server/deployment.yaml @@ -0,0 +1,138 @@ +{{- if .Values.apiServer.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ml-pipeline + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.mlPipelineLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "kubeflow-pipelines.mlPipelineSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + cluster-autoscaler.kubernetes.io/safe-to-evict: "true" + labels: + {{- include "kubeflow-pipelines.mlPipelineLabels" . | nindent 8 }} + spec: + serviceAccountName: ml-pipeline + containers: + - name: ml-pipeline-api-server + {{- if and .Values.apiServer.k8sNative .Values.apiServer.k8sNative.enabled .Values.apiServer.image.repository .Values.apiServer.image.tag }} + image: "{{ .Values.apiServer.image.repository }}:{{ .Values.apiServer.image.tag }}" + {{- else }} + image: {{ include "kubeflow-pipelines.image" (dict "repository" .Values.apiServer.image.repository "tag" .Values.apiServer.image.tag "context" .) }} + {{- end }} + imagePullPolicy: IfNotPresent + {{- if and .Values.apiServer.k8sNative .Values.apiServer.k8sNative.enabled }} + command: + {{- toYaml .Values.apiServer.k8sNative.command | nindent 10 }} + args: + {{- toYaml .Values.apiServer.k8sNative.args | nindent 10 }} + {{- end }} + ports: + {{- if and .Values.apiServer.k8sNative .Values.apiServer.k8sNative.enabled .Values.apiServer.k8sNative.webhookPort }} + - name: webhook + containerPort: {{ .Values.apiServer.k8sNative.webhookPort }} + {{- end }} + - name: http + containerPort: 8888 + - name: grpc + containerPort: 8887 + env: + {{- range .Values.apiServer.additionalEnv }} + - name: {{ .name }} + {{- if .value }} + value: {{ .value | quote }} + {{- else if and .key (ne .key "null") }} + {{- if and .secretName .secretKey }} + valueFrom: + secretKeyRef: + name: {{ .secretName }} + key: {{ .secretKey }} + {{- else if and .configMapName .configMapKey }} + valueFrom: + configMapKeyRef: + name: {{ .configMapName }} + key: {{ .configMapKey }} + {{- else if or (eq .name "DBCONFIG_USER") (eq .name "DBCONFIG_PASSWORD") (eq .name "DBCONFIG_MYSQLCONFIG_USER") (eq .name "DBCONFIG_MYSQLCONFIG_PASSWORD") }} + valueFrom: + secretKeyRef: + name: mysql-secret + key: {{ .key }} + {{- else if or (eq .name "OBJECTSTORECONFIG_ACCESSKEY") (eq .name "OBJECTSTORECONFIG_SECRETACCESSKEY") }} + valueFrom: + secretKeyRef: + name: mlpipeline-minio-artifact + key: {{ .key }} + {{- else }} + valueFrom: + configMapKeyRef: + name: pipeline-install-config + key: {{ .key }} + {{- end }} + {{- else if eq .name "POD_NAMESPACE" }} + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- else if eq .name "KUBEFLOW_USERID_HEADER" }} + {{- if eq $.Values.installMode.type "multi-user" }} + value: "kubeflow-userid" + {{- else }} + value: "" + {{- end }} + {{- else if eq .name "KUBEFLOW_USERID_PREFIX" }} + {{- if eq $.Values.installMode.type "multi-user" }} + value: "" + {{- else }} + value: "" + {{- end }} + {{- else if eq .name "OBJECTSTORECONFIG_SECURE" }} + value: "false" + {{- else }} + value: "" + {{- end }} + {{- end }} + {{- if eq .Values.installMode.type "multi-user" }} + envFrom: + - configMapRef: + name: pipeline-api-server-config + {{- end }} + livenessProbe: + httpGet: + path: /apis/v1beta1/healthz + port: 8888 + initialDelaySeconds: {{ .Values.apiServer.probes.liveness.initialDelaySeconds }} + periodSeconds: {{ .Values.apiServer.probes.liveness.periodSeconds }} + timeoutSeconds: {{ .Values.apiServer.probes.liveness.timeoutSeconds }} + readinessProbe: + httpGet: + path: /apis/v1beta1/healthz + port: 8888 + initialDelaySeconds: {{ .Values.apiServer.probes.readiness.initialDelaySeconds }} + periodSeconds: {{ .Values.apiServer.probes.readiness.periodSeconds }} + timeoutSeconds: {{ .Values.apiServer.probes.readiness.timeoutSeconds }} + resources: + {{- toYaml .Values.apiServer.resources | nindent 10 }} + securityContext: + {{- toYaml .Values.apiServer.securityContext | nindent 10 }} + startupProbe: + httpGet: + path: /apis/v1beta1/healthz + port: 8888 + failureThreshold: {{ .Values.apiServer.probes.startup.failureThreshold }} + periodSeconds: {{ .Values.apiServer.probes.startup.periodSeconds }} + timeoutSeconds: {{ .Values.apiServer.probes.startup.timeoutSeconds }} + {{- if and .Values.apiServer.k8sNative .Values.apiServer.k8sNative.enabled .Values.apiServer.k8sNative.volumeMounts }} + volumeMounts: + {{- toYaml .Values.apiServer.k8sNative.volumeMounts | nindent 10 }} + {{- end }} + {{- if and .Values.apiServer.k8sNative .Values.apiServer.k8sNative.enabled .Values.apiServer.k8sNative.volumes }} + volumes: + {{- toYaml .Values.apiServer.k8sNative.volumes | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/api-server/role.yaml b/experimental/helm/charts/pipelines/templates/api-server/role.yaml new file mode 100644 index 0000000000..0c40125791 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/api-server/role.yaml @@ -0,0 +1,70 @@ +{{- if and .Values.apiServer.enabled .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: ml-pipeline + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.mlPipelineLabels" . | nindent 4 }} + annotations: + {{- include "kubeflow-pipelines.annotations" . | nindent 4 }} +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: + - kubeflow.org + resources: + - scheduledworkflows/finalizers + verbs: + - update +- apiGroups: + - pipelines.kubeflow.org + resources: + - pipelines + verbs: + - get + - list + - watch +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/api-server/rolebinding.yaml b/experimental/helm/charts/pipelines/templates/api-server/rolebinding.yaml new file mode 100644 index 0000000000..0c0d58531f --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/api-server/rolebinding.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.apiServer.enabled .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: ml-pipeline + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.mlPipelineLabels" . | nindent 4 }} + annotations: + {{- include "kubeflow-pipelines.annotations" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ml-pipeline +subjects: +- kind: ServiceAccount + name: {{ include "kubeflow-pipelines.apiServer.serviceAccountName" . }} + namespace: {{ include "kubeflow-pipelines.namespace" . }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/api-server/service.yaml b/experimental/helm/charts/pipelines/templates/api-server/service.yaml new file mode 100644 index 0000000000..f0e4157c3d --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/api-server/service.yaml @@ -0,0 +1,31 @@ +{{- if .Values.apiServer.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: ml-pipeline + namespace: {{ include "kubeflow-pipelines.namespace" . }} + annotations: + prometheus.io/port: {{ .Values.apiServer.service.port | quote }} + prometheus.io/scheme: {{ .Values.apiServer.service.scheme | default "http" }} + prometheus.io/scrape: "true" + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +spec: + ports: + - name: http + port: {{ .Values.apiServer.service.port }} + protocol: TCP + targetPort: {{ .Values.apiServer.service.port }} + - name: grpc + port: {{ .Values.apiServer.service.grpcPort }} + protocol: TCP + targetPort: {{ .Values.apiServer.service.grpcPort }} + {{- if and .Values.apiServer.k8sNative .Values.apiServer.k8sNative.enabled .Values.apiServer.k8sNative.webhookPort }} + - name: webhook + port: {{ .Values.apiServer.k8sNative.webhookPort }} + protocol: TCP + targetPort: {{ .Values.apiServer.k8sNative.webhookPort }} + {{- end }} + selector: + {{- include "kubeflow-pipelines.mlPipelineSelectorLabels" . | nindent 4 }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/api-server/serviceaccount.yaml b/experimental/helm/charts/pipelines/templates/api-server/serviceaccount.yaml new file mode 100644 index 0000000000..6f89594c56 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/api-server/serviceaccount.yaml @@ -0,0 +1,11 @@ +{{- if and .Values.apiServer.enabled .Values.apiServer.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: ml-pipeline + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + {{- with .Values.apiServer.serviceAccount.annotations }} + {{- end }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/cache/cert-issuer.yaml b/experimental/helm/charts/pipelines/templates/cache/cert-issuer.yaml new file mode 100644 index 0000000000..ab4e873b59 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/cache/cert-issuer.yaml @@ -0,0 +1,12 @@ +{{- if and .Values.cache.enabled .Values.certManager.enabled }} +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: kfp-cache-selfsigned-issuer + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + app: cache-server-cert-manager +spec: + selfSigned: {} +{{- end }} + diff --git a/experimental/helm/charts/pipelines/templates/cache/certificate.yaml b/experimental/helm/charts/pipelines/templates/cache/certificate.yaml new file mode 100644 index 0000000000..2631d71ef9 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/cache/certificate.yaml @@ -0,0 +1,21 @@ +{{- if and .Values.cache.enabled .Values.certManager.enabled }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: kfp-cache-cert + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + app: cache-server-cert-manager +spec: + commonName: kfp-cache-cert + isCA: true + dnsNames: + - cache-server + - cache-server.{{ include "kubeflow-pipelines.namespace" . }} + - cache-server.{{ include "kubeflow-pipelines.namespace" . }}.svc + issuerRef: + kind: Issuer + name: kfp-cache-selfsigned-issuer + secretName: webhook-server-tls +{{- end }} + diff --git a/experimental/helm/charts/pipelines/templates/cache/deployment.yaml b/experimental/helm/charts/pipelines/templates/cache/deployment.yaml new file mode 100644 index 0000000000..299e900a2b --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/cache/deployment.yaml @@ -0,0 +1,97 @@ +{{- if .Values.cache.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cache-server + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.cacheLabels" . | nindent 4 }} +spec: + replicas: {{ .Values.cache.server.replicas }} + selector: + matchLabels: + {{- include "kubeflow-pipelines.cacheSelectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "kubeflow-pipelines.cacheLabels" . | nindent 8 }} + spec: + serviceAccountName: kubeflow-pipelines-cache + securityContext: + seccompProfile: + type: RuntimeDefault + containers: + - name: server + image: {{ include "kubeflow-pipelines.image" (dict "repository" .Values.cache.server.image.repository "tag" .Values.cache.server.image.tag "context" .) }} + imagePullPolicy: Always + args: + - "--db_driver=$(DBCONFIG_DRIVER)" + - "--db_host=$(DBCONFIG_HOST_NAME)" + - "--db_port=$(DBCONFIG_PORT)" + - "--db_name=$(DBCONFIG_DB_NAME)" + - "--db_user=$(DBCONFIG_USER)" + - "--db_password=$(DBCONFIG_PASSWORD)" + - "--namespace_to_watch=$(NAMESPACE_TO_WATCH)" + - "--listen_port=$(WEBHOOK_PORT)" + - "--tls_cert_filename=tls.crt" + - "--tls_key_filename=tls.key" + env: + {{- range .Values.cache.server.additionalEnv }} + - name: {{ .name }} + {{- if .value }} + value: {{ .value | quote }} + {{- else if .valueFrom }} + valueFrom: + {{- toYaml .valueFrom | nindent 12 }} + {{- else if and .secretName .secretKey }} + valueFrom: + secretKeyRef: + name: {{ .secretName }} + key: {{ .secretKey }} + {{- else if and .configMapName .configMapKey }} + valueFrom: + configMapKeyRef: + name: {{ .configMapName }} + key: {{ .configMapKey }} + {{- else if and .key (ne .key "null") }} + {{- if or (eq .name "DBCONFIG_USER") (eq .name "DBCONFIG_PASSWORD") }} + valueFrom: + secretKeyRef: + name: mysql-secret + key: {{ .key }} + {{- else }} + valueFrom: + configMapKeyRef: + name: pipeline-install-config + key: {{ .key }} + {{- end }} + {{- else if eq .name "NAMESPACE_TO_WATCH" }} + {{- if eq $.Values.installMode.type "multi-user" }} + value: "" + {{- else }} + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- end }} + {{- else if eq .name "DBCONFIG_DRIVER" }} + value: mysql + {{- else }} + value: "" + {{- end }} + {{- end }} + - name: WEBHOOK_PORT + value: "8443" + ports: + - name: webhook-api + containerPort: 8443 + securityContext: + {{- toYaml .Values.cache.server.securityContext | nindent 10 }} + volumeMounts: + - name: webhook-tls-certs + mountPath: /etc/webhook/certs + readOnly: true + volumes: + - name: webhook-tls-certs + secret: + secretName: webhook-server-tls +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/cache/mutating-webhook.yaml b/experimental/helm/charts/pipelines/templates/cache/mutating-webhook.yaml new file mode 100644 index 0000000000..a61a299763 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/cache/mutating-webhook.yaml @@ -0,0 +1,30 @@ +{{- if and .Values.cache.enabled .Values.certManager.mutating.enabled }} +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: {{ .Values.certManager.mutating.name }} + labels: + app: cache-server-cert-manager + annotations: + cert-manager.io/inject-ca-from: {{ include "kubeflow-pipelines.namespace" . }}/kfp-cache-cert +webhooks: + - name: cache-server.{{ include "kubeflow-pipelines.namespace" . }}.svc + clientConfig: + service: + name: cache-server + namespace: {{ include "kubeflow-pipelines.namespace" . }} + path: "/mutate" + failurePolicy: Ignore + rules: + - operations: [ "CREATE" ] + apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] + sideEffects: None + timeoutSeconds: 5 + objectSelector: + matchLabels: + pipelines.kubeflow.org/cache_enabled: "true" + admissionReviewVersions: ["v1beta1"] +{{- end }} + diff --git a/experimental/helm/charts/pipelines/templates/cache/role.yaml b/experimental/helm/charts/pipelines/templates/cache/role.yaml new file mode 100644 index 0000000000..7a6b89b3ba --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/cache/role.yaml @@ -0,0 +1,36 @@ +{{- if .Values.cache.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + {{- include "kubeflow-pipelines.cacheLabels" . | nindent 4 }} + name: kubeflow-pipelines-cache-role + namespace: {{ include "kubeflow-pipelines.namespace" . }} +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 +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/cache/rolebinding.yaml b/experimental/helm/charts/pipelines/templates/cache/rolebinding.yaml new file mode 100644 index 0000000000..3ecbddb453 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/cache/rolebinding.yaml @@ -0,0 +1,17 @@ +{{- if .Values.cache.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + {{- include "kubeflow-pipelines.cacheLabels" . | nindent 4 }} + name: kubeflow-pipelines-cache-binding + namespace: {{ include "kubeflow-pipelines.namespace" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: kubeflow-pipelines-cache-role +subjects: +- kind: ServiceAccount + name: {{ include "kubeflow-pipelines.cache.serviceAccountName" . }} + namespace: {{ include "kubeflow-pipelines.namespace" . }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/cache/service.yaml b/experimental/helm/charts/pipelines/templates/cache/service.yaml new file mode 100644 index 0000000000..da8ecaa94f --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/cache/service.yaml @@ -0,0 +1,15 @@ +{{- if .Values.cache.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: cache-server + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.cacheLabels" . | nindent 4 }} +spec: + ports: + - port: {{ .Values.cache.server.service.port }} + targetPort: webhook-api + selector: + {{- include "kubeflow-pipelines.cacheSelectorLabels" . | nindent 4 }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/cache/serviceaccount.yaml b/experimental/helm/charts/pipelines/templates/cache/serviceaccount.yaml new file mode 100644 index 0000000000..ccd96afafd --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/cache/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if and .Values.cache.enabled .Values.cache.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kubeflow-pipelines-cache + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.cacheLabels" . | nindent 4 }} + {{- with .Values.cache.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/config/kfp-launcher-configmap.yaml b/experimental/helm/charts/pipelines/templates/config/kfp-launcher-configmap.yaml new file mode 100644 index 0000000000..443a0eee94 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/config/kfp-launcher-configmap.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: kfp-launcher + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +data: + defaultPipelineRoot: "" diff --git a/experimental/helm/charts/pipelines/templates/config/pipeline-api-server-config.yaml b/experimental/helm/charts/pipelines/templates/config/pipeline-api-server-config.yaml new file mode 100644 index 0000000000..d6281e6dec --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/config/pipeline-api-server-config.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.apiServer.enabled (eq .Values.installMode.type "multi-user") }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: pipeline-api-server-config + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +data: + {{- if eq .Values.installMode.type "multi-user" }} + MULTIUSER: "true" + DEFAULTPIPELINERUNNERSERVICEACCOUNT: "default-editor" + {{- else }} + MULTIUSER: "false" + DEFAULTPIPELINERUNNERSERVICEACCOUNT: "pipeline-runner" + {{- end }} + VISUALIZATIONSERVICE_NAME: "ml-pipeline-visualizationserver" + VISUALIZATIONSERVICE_PORT: "8888" +{{- end }} \ No newline at end of file diff --git a/experimental/helm/charts/pipelines/templates/config/pipeline-install-config.yaml b/experimental/helm/charts/pipelines/templates/config/pipeline-install-config.yaml new file mode 100644 index 0000000000..56ce960236 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/config/pipeline-install-config.yaml @@ -0,0 +1,44 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: pipeline-install-config + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +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 `. + appName: {{ .Values.pipeline.app.name }} + appVersion: {{ .Values.pipeline.app.version }} + # Database configuration (MySQL only) +{{- $dbHost := include "kubeflow-pipelines.database.host" . }} + dbHost: {{ $dbHost | quote }} + dbPort: {{ include "kubeflow-pipelines.database.port" . | quote }} + dbType: "mysql" + mysqlHost: {{ $dbHost | quote }} + mysqlPort: {{ include "kubeflow-pipelines.database.port" . | quote }} + mlmdDb: {{ .Values.database.metadb }} + cacheDb: {{ .Values.database.cachedb }} + pipelineDb: {{ include "kubeflow-pipelines.database.name" . }} + # Object storage configuration + bucketName: {{ include "kubeflow-pipelines.objectStore.bucket" . }} + # Pipeline configuration + defaultPipelineRoot: {{ .Values.pipeline.defaultPipelineRoot | quote }} + autoUpdatePipelineDefaultVersion: {{ .Values.pipeline.autoUpdatePipelineDefaultVersion | toString | quote }} + cronScheduleTimezone: {{ .Values.pipeline.cronScheduleTimezone | quote }} + # Cache configuration + cacheImage: {{ .Values.pipeline.cache.image | quote }} + cacheNodeRestrictions: {{ .Values.pipeline.cache.nodeRestrictions | toString | quote }} + MAXIMUM_CACHE_STALENESS: {{ .Values.pipeline.cache.maximumStaleness | quote }} + DEFAULT_CACHE_STALENESS: {{ .Values.pipeline.cache.defaultStaleness | quote }} + # Connection configuration + ConMaxLifeTime: {{ .Values.database.connectionMaxLifetime | quote }} + LOG_LEVEL: {{ .Values.global.logLevel | quote }} + # Profile controller configuration + ARTIFACTS_PROXY_ENABLED: {{ .Values.profileController.artifactsProxyEnabled | quote }} + ARTIFACT_RETENTION_DAYS: {{ .Values.profileController.artifactRetentionDays | quote }} diff --git a/experimental/helm/charts/pipelines/templates/config/ui-configmap.yaml b/experimental/helm/charts/pipelines/templates/config/ui-configmap.yaml new file mode 100644 index 0000000000..0adb9cf82a --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/config/ui-configmap.yaml @@ -0,0 +1,16 @@ +{{- if .Values.ui.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: ml-pipeline-ui-configmap + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +data: + viewer-pod-template.json: |- + { + "spec": { + "serviceAccountName": "{{ if eq .Values.installMode.type "multi-user" }}default-editor{{ else }}kubeflow-pipelines-viewer{{ end }}" + } + } +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/crds/metacontroller-crds.yaml b/experimental/helm/charts/pipelines/templates/crds/metacontroller-crds.yaml new file mode 100644 index 0000000000..75b8bb0147 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/crds/metacontroller-crds.yaml @@ -0,0 +1,837 @@ +{{- if .Values.thirdParty.metacontroller.enabled }} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: unapproved, request not yet submitted + controller-gen.kubebuilder.io/version: v0.13.0 + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + kustomize.component: metacontroller + name: compositecontrollers.metacontroller.k8s.io +spec: + group: metacontroller.k8s.io + names: + kind: CompositeController + listKind: CompositeControllerList + plural: compositecontrollers + shortNames: + - cc + - cctl + singular: compositecontroller + scope: Cluster + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: CompositeController + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + childResources: + items: + properties: + apiVersion: + type: string + resource: + type: string + updateStrategy: + properties: + method: + enum: + - OnDelete + - Recreate + - InPlace + - RollingRecreate + - RollingInPlace + type: string + statusChecks: + properties: + conditions: + items: + properties: + reason: + type: string + status: + type: string + type: + type: string + required: + - type + type: object + type: array + type: object + type: object + required: + - apiVersion + - resource + type: object + type: array + generateSelector: + type: boolean + hooks: + properties: + customize: + properties: + version: + default: v1 + enum: + - v1 + - v2 + type: string + webhook: + properties: + etag: + properties: + cacheCleanupSeconds: + format: int32 + type: integer + cacheTimeoutSeconds: + format: int32 + type: integer + enabled: + type: boolean + type: object + path: + type: string + responseUnMarshallMode: + description: Sets the json unmarshall mode. One of the + 'loose' or 'strict'. In 'strict' mode additional checks + are performed to detect unknown and duplicated fields. + enum: + - loose + - strict + type: string + service: + properties: + name: + type: string + namespace: + type: string + port: + format: int32 + type: integer + protocol: + type: string + required: + - name + - namespace + type: object + timeout: + format: duration + type: string + url: + type: string + type: object + type: object + finalize: + properties: + version: + default: v1 + enum: + - v1 + - v2 + type: string + webhook: + properties: + etag: + properties: + cacheCleanupSeconds: + format: int32 + type: integer + cacheTimeoutSeconds: + format: int32 + type: integer + enabled: + type: boolean + type: object + path: + type: string + responseUnMarshallMode: + description: Sets the json unmarshall mode. One of the + 'loose' or 'strict'. In 'strict' mode additional checks + are performed to detect unknown and duplicated fields. + enum: + - loose + - strict + type: string + service: + properties: + name: + type: string + namespace: + type: string + port: + format: int32 + type: integer + protocol: + type: string + required: + - name + - namespace + type: object + timeout: + format: duration + type: string + url: + type: string + type: object + type: object + postUpdateChild: + properties: + version: + default: v1 + enum: + - v1 + - v2 + type: string + webhook: + properties: + etag: + properties: + cacheCleanupSeconds: + format: int32 + type: integer + cacheTimeoutSeconds: + format: int32 + type: integer + enabled: + type: boolean + type: object + path: + type: string + responseUnMarshallMode: + description: Sets the json unmarshall mode. One of the + 'loose' or 'strict'. In 'strict' mode additional checks + are performed to detect unknown and duplicated fields. + enum: + - loose + - strict + type: string + service: + properties: + name: + type: string + namespace: + type: string + port: + format: int32 + type: integer + protocol: + type: string + required: + - name + - namespace + type: object + timeout: + format: duration + type: string + url: + type: string + type: object + type: object + preUpdateChild: + properties: + version: + default: v1 + enum: + - v1 + - v2 + type: string + webhook: + properties: + etag: + properties: + cacheCleanupSeconds: + format: int32 + type: integer + cacheTimeoutSeconds: + format: int32 + type: integer + enabled: + type: boolean + type: object + path: + type: string + responseUnMarshallMode: + description: Sets the json unmarshall mode. One of the + 'loose' or 'strict'. In 'strict' mode additional checks + are performed to detect unknown and duplicated fields. + enum: + - loose + - strict + type: string + service: + properties: + name: + type: string + namespace: + type: string + port: + format: int32 + type: integer + protocol: + type: string + required: + - name + - namespace + type: object + timeout: + format: duration + type: string + url: + type: string + type: object + type: object + sync: + properties: + version: + default: v1 + enum: + - v1 + - v2 + type: string + webhook: + properties: + etag: + properties: + cacheCleanupSeconds: + format: int32 + type: integer + cacheTimeoutSeconds: + format: int32 + type: integer + enabled: + type: boolean + type: object + path: + type: string + responseUnMarshallMode: + description: Sets the json unmarshall mode. One of the + 'loose' or 'strict'. In 'strict' mode additional checks + are performed to detect unknown and duplicated fields. + enum: + - loose + - strict + type: string + service: + properties: + name: + type: string + namespace: + type: string + port: + format: int32 + type: integer + protocol: + type: string + required: + - name + - namespace + type: object + timeout: + format: duration + type: string + url: + type: string + type: object + type: object + type: object + parentResource: + properties: + apiVersion: + type: string + labelSelector: + description: A label selector is a label query over a set of resources. + The result of matchLabels and matchExpressions are ANDed. An + empty label selector matches all objects. A null label selector + matches no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, NotIn, + Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If + the operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. A + single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field is "key", + the operator is "In", and the values array contains only + "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + resource: + type: string + revisionHistory: + properties: + fieldPaths: + items: + type: string + type: array + type: object + required: + - apiVersion + - resource + type: object + resyncPeriodSeconds: + format: int32 + type: integer + required: + - parentResource + type: object + status: + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: unapproved, request not yet submitted + controller-gen.kubebuilder.io/version: v0.13.0 + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + kustomize.component: metacontroller + name: controllerrevisions.metacontroller.k8s.io +spec: + group: metacontroller.k8s.io + names: + kind: ControllerRevision + listKind: ControllerRevisionList + plural: controllerrevisions + singular: controllerrevision + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: ControllerRevision + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + children: + items: + properties: + apiGroup: + type: string + kind: + type: string + names: + items: + type: string + type: array + required: + - apiGroup + - kind + - names + type: object + type: array + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + parentPatch: + type: object + x-kubernetes-preserve-unknown-fields: true + required: + - metadata + - parentPatch + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: unapproved, request not yet submitted + controller-gen.kubebuilder.io/version: v0.13.0 + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + kustomize.component: metacontroller + name: decoratorcontrollers.metacontroller.k8s.io +spec: + group: metacontroller.k8s.io + names: + kind: DecoratorController + listKind: DecoratorControllerList + plural: decoratorcontrollers + shortNames: + - dec + - decorators + singular: decoratorcontroller + scope: Cluster + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: DecoratorController + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + attachments: + items: + properties: + apiVersion: + type: string + resource: + type: string + updateStrategy: + properties: + method: + enum: + - OnDelete + - Recreate + - InPlace + - RollingRecreate + - RollingInPlace + type: string + type: object + required: + - apiVersion + - resource + type: object + type: array + hooks: + properties: + customize: + properties: + version: + default: v1 + enum: + - v1 + - v2 + type: string + webhook: + properties: + etag: + properties: + cacheCleanupSeconds: + format: int32 + type: integer + cacheTimeoutSeconds: + format: int32 + type: integer + enabled: + type: boolean + type: object + path: + type: string + responseUnMarshallMode: + description: Sets the json unmarshall mode. One of the + 'loose' or 'strict'. In 'strict' mode additional checks + are performed to detect unknown and duplicated fields. + enum: + - loose + - strict + type: string + service: + properties: + name: + type: string + namespace: + type: string + port: + format: int32 + type: integer + protocol: + type: string + required: + - name + - namespace + type: object + timeout: + format: duration + type: string + url: + type: string + type: object + type: object + finalize: + properties: + version: + default: v1 + enum: + - v1 + - v2 + type: string + webhook: + properties: + etag: + properties: + cacheCleanupSeconds: + format: int32 + type: integer + cacheTimeoutSeconds: + format: int32 + type: integer + enabled: + type: boolean + type: object + path: + type: string + responseUnMarshallMode: + description: Sets the json unmarshall mode. One of the + 'loose' or 'strict'. In 'strict' mode additional checks + are performed to detect unknown and duplicated fields. + enum: + - loose + - strict + type: string + service: + properties: + name: + type: string + namespace: + type: string + port: + format: int32 + type: integer + protocol: + type: string + required: + - name + - namespace + type: object + timeout: + format: duration + type: string + url: + type: string + type: object + type: object + sync: + properties: + version: + default: v1 + enum: + - v1 + - v2 + type: string + webhook: + properties: + etag: + properties: + cacheCleanupSeconds: + format: int32 + type: integer + cacheTimeoutSeconds: + format: int32 + type: integer + enabled: + type: boolean + type: object + path: + type: string + responseUnMarshallMode: + description: Sets the json unmarshall mode. One of the + 'loose' or 'strict'. In 'strict' mode additional checks + are performed to detect unknown and duplicated fields. + enum: + - loose + - strict + type: string + service: + properties: + name: + type: string + namespace: + type: string + port: + format: int32 + type: integer + protocol: + type: string + required: + - name + - namespace + type: object + timeout: + format: duration + type: string + url: + type: string + type: object + type: object + type: object + resources: + items: + properties: + annotationSelector: + properties: + matchAnnotations: + additionalProperties: + type: string + type: object + matchExpressions: + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, NotIn, + Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists or + DoesNotExist, the values array must be empty. This + array is replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + apiVersion: + type: string + labelSelector: + description: A label selector is a label query over a set of + resources. The result of matchLabels and matchExpressions + are ANDed. An empty label selector matches all objects. A + null label selector matches no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, NotIn, + Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists or + DoesNotExist, the values array must be empty. This + array is replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field is + "key", the operator is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + resource: + type: string + required: + - apiVersion + - resource + type: object + type: array + resyncPeriodSeconds: + format: int32 + type: integer + required: + - resources + type: object + status: + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {}{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/crds/pipelines-crd.yaml b/experimental/helm/charts/pipelines/templates/crds/pipelines-crd.yaml new file mode 100644 index 0000000000..a708cc8442 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/crds/pipelines-crd.yaml @@ -0,0 +1,51 @@ +{{- if and .Values.crds.install (eq .Values.installMode.pipelineDefinition.storage "k8s-native") }} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.4 + name: pipelines.pipelines.kubeflow.org +spec: + group: pipelines.kubeflow.org + names: + kind: Pipeline + listKind: PipelineList + plural: pipelines + singular: pipeline + scope: Namespaced + versions: + - name: v2beta1 + schema: + openAPIV3Schema: + description: Pipeline is the Schema for the pipelines API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: PipelineSpec defines the desired state of Pipeline. + properties: + description: + type: string + displayName: + type: string + type: object + type: object + served: true + storage: true +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/crds/pipelineversions-crd.yaml b/experimental/helm/charts/pipelines/templates/crds/pipelineversions-crd.yaml new file mode 100644 index 0000000000..6047631510 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/crds/pipelineversions-crd.yaml @@ -0,0 +1,97 @@ +{{- if and .Values.crds.install (eq .Values.installMode.pipelineDefinition.storage "k8s-native") }} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.4 + name: pipelineversions.pipelines.kubeflow.org +spec: + group: pipelines.kubeflow.org + names: + kind: PipelineVersion + listKind: PipelineVersionList + plural: pipelineversions + singular: pipelineversion + scope: Namespaced + versions: + - name: v2beta1 + schema: + openAPIV3Schema: + description: PipelineVersion is the Schema for the pipelineversions API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: PipelineVersionSpec defines the desired state of PipelineVersion. + properties: + codeSourceURL: + type: string + description: + type: string + displayName: + type: string + pipelineName: + type: string + pipelineSpec: + x-kubernetes-preserve-unknown-fields: true + pipelineSpecURI: + type: string + platformSpec: + x-kubernetes-preserve-unknown-fields: true + required: + - pipelineSpec + type: object + status: + description: PipelineVersionStatus defines the observed state of PipelineVersion. + properties: + conditions: + items: + description: |- + SimplifiedCondition is a metav1.Condition without lastTransitionTime since the database model doesn't have such + a concept and it allows a default status in the CRD without a controller setting it. + properties: + message: + maxLength: 32768 + type: string + reason: + type: string + status: + enum: + - "True" + - "False" + - Unknown + type: string + type: + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - message + - reason + - status + - type + type: object + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/crds/scheduledworkflow-crd.yaml b/experimental/helm/charts/pipelines/templates/crds/scheduledworkflow-crd.yaml new file mode 100644 index 0000000000..81069fbc62 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/crds/scheduledworkflow-crd.yaml @@ -0,0 +1,45 @@ +{{- if .Values.crds.install }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: scheduledworkflows.kubeflow.org + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + annotations: + {{- include "kubeflow-pipelines.annotations" . | nindent 4 }} +spec: + group: kubeflow.org + names: + kind: ScheduledWorkflow + listKind: ScheduledWorkflowList + plural: scheduledworkflows + singular: scheduledworkflow + shortNames: + - swf + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + type: object + x-kubernetes-preserve-unknown-fields: true + x-kubernetes-map-type: atomic + status: + type: object + x-kubernetes-preserve-unknown-fields: true + x-kubernetes-map-type: atomic + required: + - spec + - status + type: object + served: true + storage: true +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/crds/viewer-crd.yaml b/experimental/helm/charts/pipelines/templates/crds/viewer-crd.yaml new file mode 100644 index 0000000000..ceb3239979 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/crds/viewer-crd.yaml @@ -0,0 +1,40 @@ +{{- if .Values.crds.install }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: viewers.kubeflow.org + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + annotations: + {{- include "kubeflow-pipelines.annotations" . | nindent 4 }} +spec: + group: kubeflow.org + names: + kind: Viewer + listKind: ViewerList + plural: viewers + singular: viewer + shortNames: + - vi + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + type: object + x-kubernetes-preserve-unknown-fields: true + x-kubernetes-map-type: atomic + required: + - spec + type: object + served: true + storage: true +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/database/mysql-secret.yaml b/experimental/helm/charts/pipelines/templates/database/mysql-secret.yaml new file mode 100644 index 0000000000..6124d3dac1 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/database/mysql-secret.yaml @@ -0,0 +1,12 @@ +{{- if and (not .Values.externalDatabase.existingSecret) (not .Values.mysql.enabled) }} +apiVersion: v1 +kind: Secret +metadata: + name: mysql-secret + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +stringData: + username: {{ .Values.externalDatabase.username | quote }} + password: {{ .Values.externalDatabase.password | quote }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/istio/authorization-config.yaml b/experimental/helm/charts/pipelines/templates/istio/authorization-config.yaml new file mode 100644 index 0000000000..2d78f92f44 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/istio/authorization-config.yaml @@ -0,0 +1,222 @@ +{{- if and .Values.networking.istio.enabled (eq .Values.installMode.type "multi-user") }} +apiVersion: security.istio.io/v1beta1 +kind: AuthorizationPolicy +metadata: + name: ml-pipeline-ui + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.authorizationPolicyLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + app: ml-pipeline-ui + rules: + # Allow all requests from the ingress gateway + - from: + - source: + principals: + - cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account + + # Allow all requests with an `authorization` header but NOT a `kubeflow-userid` header. + # This is needed to allow Kubernetes JWTs to be passed to the KFP API. + - when: + - key: request.headers[authorization] + values: + - "*" + - key: request.headers[kubeflow-userid] + notValues: + - "*" + +--- +apiVersion: security.istio.io/v1beta1 +kind: AuthorizationPolicy +metadata: + name: ml-pipeline + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.authorizationPolicyLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + app: ml-pipeline + rules: + - from: + - source: + principals: + - cluster.local/ns/{{ include "kubeflow-pipelines.namespace" . }}/sa/ml-pipeline + - cluster.local/ns/{{ include "kubeflow-pipelines.namespace" . }}/sa/ml-pipeline-ui + - cluster.local/ns/{{ include "kubeflow-pipelines.namespace" . }}/sa/ml-pipeline-persistenceagent + - cluster.local/ns/{{ include "kubeflow-pipelines.namespace" . }}/sa/ml-pipeline-scheduledworkflow + - cluster.local/ns/{{ include "kubeflow-pipelines.namespace" . }}/sa/ml-pipeline-viewer-crd-service-account + - cluster.local/ns/{{ include "kubeflow-pipelines.namespace" . }}/sa/kubeflow-pipelines-cache + # Allow all requests that dont have a `kubeflow-userid` header. + - when: + - key: request.headers[kubeflow-userid] + notValues: ['*'] + +--- +apiVersion: security.istio.io/v1beta1 +kind: AuthorizationPolicy +metadata: + name: ml-pipeline-visualizationserver + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.authorizationPolicyLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + app: ml-pipeline-visualizationserver + rules: + - from: + - source: + principals: + - cluster.local/ns/{{ include "kubeflow-pipelines.namespace" . }}/sa/ml-pipeline + - cluster.local/ns/{{ include "kubeflow-pipelines.namespace" . }}/sa/ml-pipeline-ui + - cluster.local/ns/{{ include "kubeflow-pipelines.namespace" . }}/sa/ml-pipeline-persistenceagent + - cluster.local/ns/{{ include "kubeflow-pipelines.namespace" . }}/sa/ml-pipeline-scheduledworkflow + - cluster.local/ns/{{ include "kubeflow-pipelines.namespace" . }}/sa/ml-pipeline-viewer-crd-service-account + - cluster.local/ns/{{ include "kubeflow-pipelines.namespace" . }}/sa/kubeflow-pipelines-cache + +--- +apiVersion: security.istio.io/v1beta1 +kind: AuthorizationPolicy +metadata: + name: service-cache-server + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.authorizationPolicyLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + app: cache-server + rules: + - {} + +--- +{{- if .Values.thirdParty.mysql.enabled }} +apiVersion: security.istio.io/v1beta1 +kind: AuthorizationPolicy +metadata: + name: mysql + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.authorizationPolicyLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + app: mysql + rules: + - from: + - source: + principals: + - cluster.local/ns/{{ include "kubeflow-pipelines.namespace" . }}/sa/ml-pipeline + - cluster.local/ns/{{ include "kubeflow-pipelines.namespace" . }}/sa/ml-pipeline-ui + - cluster.local/ns/{{ include "kubeflow-pipelines.namespace" . }}/sa/ml-pipeline-persistenceagent + - cluster.local/ns/{{ include "kubeflow-pipelines.namespace" . }}/sa/ml-pipeline-scheduledworkflow + - cluster.local/ns/{{ include "kubeflow-pipelines.namespace" . }}/sa/ml-pipeline-viewer-crd-service-account + - cluster.local/ns/{{ include "kubeflow-pipelines.namespace" . }}/sa/kubeflow-pipelines-cache + - cluster.local/ns/{{ include "kubeflow-pipelines.namespace" . }}/sa/metadata-grpc-server +{{- end }} + +--- +{{- if .Values.metadata.enabled }} +apiVersion: security.istio.io/v1beta1 +kind: AuthorizationPolicy +metadata: + name: metadata-grpc-service + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.authorizationPolicyLabels" . | nindent 4 }} +spec: + action: ALLOW + selector: + matchLabels: + component: metadata-grpc-server + rules: + - {} +{{- end }} + +--- +apiVersion: "networking.istio.io/v1alpha3" +kind: DestinationRule +metadata: + name: ml-pipeline-ui + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +spec: + host: ml-pipeline-ui.{{ include "kubeflow-pipelines.namespace" . }}.svc.cluster.local + trafficPolicy: + tls: + mode: ISTIO_MUTUAL + +--- +apiVersion: "networking.istio.io/v1alpha3" +kind: DestinationRule +metadata: + name: ml-pipeline + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +spec: + host: ml-pipeline.{{ include "kubeflow-pipelines.namespace" . }}.svc.cluster.local + trafficPolicy: + tls: + mode: ISTIO_MUTUAL + +--- +apiVersion: "networking.istio.io/v1alpha3" +kind: DestinationRule +metadata: + name: ml-pipeline-visualizationserver + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +spec: + host: ml-pipeline-visualizationserver.{{ include "kubeflow-pipelines.namespace" . }}.svc.cluster.local + trafficPolicy: + tls: + mode: ISTIO_MUTUAL + +--- +{{- if .Values.thirdParty.mysql.enabled }} +apiVersion: "networking.istio.io/v1alpha3" +kind: DestinationRule +metadata: + name: ml-pipeline-mysql + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +spec: + host: mysql.{{ include "kubeflow-pipelines.namespace" . }}.svc.cluster.local + trafficPolicy: + tls: + mode: ISTIO_MUTUAL +{{- end }} + +--- +{{- if .Values.metadata.enabled }} +apiVersion: "networking.istio.io/v1alpha3" +kind: DestinationRule +metadata: + name: metadata-grpc-service + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +spec: + host: metadata-grpc-service.{{ include "kubeflow-pipelines.namespace" . }}.svc.cluster.local + trafficPolicy: + tls: + mode: ISTIO_MUTUAL +{{- end }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/istio/virtual-service.yaml b/experimental/helm/charts/pipelines/templates/istio/virtual-service.yaml new file mode 100644 index 0000000000..59abb63dee --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/istio/virtual-service.yaml @@ -0,0 +1,57 @@ +{{- if and .Values.networking.istio.enabled (eq .Values.installMode.type "multi-user") }} +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: ml-pipeline-ui + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +spec: + gateways: + - {{ .Values.networking.istio.gateway | default "kubeflow-gateway" }} + hosts: + - '*' + http: + - match: + - uri: + prefix: /pipeline + rewrite: + uri: /pipeline + route: + - destination: + host: ml-pipeline-ui.{{ include "kubeflow-pipelines.namespace" . }}.svc.cluster.local + port: + number: 80 + timeout: 300s + +--- +{{- if .Values.metadata.enabled }} +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: metadata-grpc + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +spec: + gateways: + - {{ .Values.networking.istio.gateway | default "kubeflow-gateway" }} + hosts: + - '*' + http: + - match: + - uri: + prefix: /ml_metadata + rewrite: + uri: /ml_metadata + route: + - destination: + host: metadata-envoy-service.{{ include "kubeflow-pipelines.namespace" . }}.svc.cluster.local + port: + number: 9090 +{{- end }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/metadata-writer/deployment.yaml b/experimental/helm/charts/pipelines/templates/metadata-writer/deployment.yaml new file mode 100644 index 0000000000..f868fcec04 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/metadata-writer/deployment.yaml @@ -0,0 +1,53 @@ +{{- if .Values.metadataWriter.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: metadata-writer + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: +{{- if eq .Values.installMode.type "multi-user" }} + app: metadata-writer + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines + application-crd-id: kubeflow-pipelines +{{- else }} + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app: metadata-writer +{{- end }} +spec: + replicas: {{ .Values.metadataWriter.replicas }} + selector: + matchLabels: + {{- include "kubeflow-pipelines.metadataWriterSelectorLabels" . | nindent 6 }} + template: + metadata: + labels: +{{- if eq .Values.installMode.type "multi-user" }} + app: metadata-writer + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines + application-crd-id: kubeflow-pipelines +{{- else }} + {{- include "kubeflow-pipelines.labels" . | nindent 8 }} + app: metadata-writer +{{- end }} + spec: + securityContext: + seccompProfile: + type: RuntimeDefault + serviceAccountName: kubeflow-pipelines-metadata-writer + containers: + - name: main + image: {{ include "kubeflow-pipelines.image" (dict "repository" .Values.metadataWriter.image.repository "tag" .Values.metadataWriter.image.tag "context" .) }} + env: + - name: NAMESPACE_TO_WATCH +{{- if eq .Values.installMode.type "multi-user" }} + value: "" +{{- else }} + valueFrom: + fieldRef: + fieldPath: metadata.namespace +{{- end }} + securityContext: + {{- toYaml .Values.metadataWriter.securityContext | nindent 10 }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/metadata-writer/role.yaml b/experimental/helm/charts/pipelines/templates/metadata-writer/role.yaml new file mode 100644 index 0000000000..c07d9aac97 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/metadata-writer/role.yaml @@ -0,0 +1,39 @@ +{{- if .Values.metadataWriter.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: kubeflow-pipelines-metadata-writer-role + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + app: kubeflow-pipelines-metadata-writer-role + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + annotations: + {{- include "kubeflow-pipelines.annotations" . | nindent 4 }} +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 +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/metadata-writer/rolebinding.yaml b/experimental/helm/charts/pipelines/templates/metadata-writer/rolebinding.yaml new file mode 100644 index 0000000000..5e3689b3b5 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/metadata-writer/rolebinding.yaml @@ -0,0 +1,19 @@ +{{- if .Values.metadataWriter.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: kubeflow-pipelines-metadata-writer-binding + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + annotations: + {{- include "kubeflow-pipelines.annotations" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: kubeflow-pipelines-metadata-writer-role +subjects: +- kind: ServiceAccount + name: {{ include "kubeflow-pipelines.metadataWriter.serviceAccountName" . }} + namespace: {{ include "kubeflow-pipelines.namespace" . }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/metadata-writer/serviceaccount.yaml b/experimental/helm/charts/pipelines/templates/metadata-writer/serviceaccount.yaml new file mode 100644 index 0000000000..fe60fd19e7 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/metadata-writer/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if and .Values.metadataWriter.enabled .Values.metadataWriter.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kubeflow-pipelines-metadata-writer + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + {{- with .Values.metadataWriter.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/metadata/envoy-configmap.yaml b/experimental/helm/charts/pipelines/templates/metadata/envoy-configmap.yaml new file mode 100644 index 0000000000..2e4a75274e --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/metadata/envoy-configmap.yaml @@ -0,0 +1,83 @@ +{{- if .Values.metadata.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: metadata-envoy-configmap + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +data: + envoy-config.yaml: |- + admin: + access_log: + name: admin_access + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog + path: /tmp/admin_access.log + address: + socket_address: { address: 0.0.0.0, port_value: 9901 } + + static_resources: + listeners: + - name: listener_0 + address: + socket_address: { address: 0.0.0.0, port_value: 9090 } + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + codec_type: auto + stat_prefix: ingress_http + route_config: + name: local_route + virtual_hosts: + - name: local_service + domains: [ "*" ] + routes: + - match: { prefix: "/" } + route: + cluster: metadata-cluster + max_stream_duration: + grpc_timeout_header_max: '0s' + typed_per_filter_config: + envoy.filter.http.cors: + "@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.CorsPolicy + allow_origin_string_match: + - safe_regex: + regex: ".*" + allow_methods: GET, PUT, DELETE, POST, OPTIONS + allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout + max_age: "1728000" + expose_headers: custom-header-1,grpc-status,grpc-message + http_filters: + - name: envoy.filters.http.grpc_web + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb + - name: envoy.filters.http.cors + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + clusters: + - name: metadata-cluster + connect_timeout: 30.0s + type: logical_dns + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicit_http_config: + http2_protocol_options: { } + lb_policy: round_robin + load_assignment: + cluster_name: metadata-grpc + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: metadata-grpc-service + port_value: 8080 +{{- end }} + diff --git a/experimental/helm/charts/pipelines/templates/metadata/envoy-deployment.yaml b/experimental/helm/charts/pipelines/templates/metadata/envoy-deployment.yaml new file mode 100644 index 0000000000..84a25c0e6f --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/metadata/envoy-deployment.yaml @@ -0,0 +1,41 @@ +{{- if .Values.metadata.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: metadata-envoy-deployment + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + component: metadata-envoy +spec: + replicas: {{ .Values.metadata.envoy.replicas }} + selector: + matchLabels: + component: metadata-envoy + application-crd-id: kubeflow-pipelines + template: + metadata: + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 8 }} + component: metadata-envoy + sidecar.istio.io/inject: "false" + spec: + containers: + - name: container + image: {{ include "kubeflow-pipelines.image" (dict "repository" .Values.metadata.envoy.image.repository "tag" .Values.metadata.envoy.image.tag "context" .) }} + args: ["/etc/envoy/envoy-config.yaml"] + ports: + - name: md-envoy + containerPort: 9090 + - name: envoy-admin + containerPort: 9901 + securityContext: + {{- toYaml .Values.metadata.envoy.securityContext | nindent 10 }} + volumeMounts: + - name: envoy-config + mountPath: /etc/envoy + volumes: + - name: envoy-config + configMap: + name: metadata-envoy-configmap +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/metadata/envoy-service.yaml b/experimental/helm/charts/pipelines/templates/metadata/envoy-service.yaml new file mode 100644 index 0000000000..2dc727afd4 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/metadata/envoy-service.yaml @@ -0,0 +1,18 @@ +{{- if .Values.metadata.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: metadata-envoy-service + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app: metadata-envoy +spec: + ports: + - name: {{ .Values.metadata.envoy.service.portName | default "md-envoy" }} + port: {{ .Values.metadata.envoy.service.port }} + protocol: TCP + selector: + {{- include "kubeflow-pipelines.metadataEnvoySelectorLabels" . | nindent 4 }} + type: {{ .Values.metadata.envoy.service.type }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/metadata/grpc-configmap.yaml b/experimental/helm/charts/pipelines/templates/metadata/grpc-configmap.yaml new file mode 100644 index 0000000000..79e5330bf2 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/metadata/grpc-configmap.yaml @@ -0,0 +1,13 @@ +{{- if .Values.metadata.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: metadata-grpc-configmap + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + component: metadata-grpc-server +data: + METADATA_GRPC_SERVICE_HOST: "metadata-grpc-service" + METADATA_GRPC_SERVICE_PORT: "8080" +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/metadata/grpc-deployment.yaml b/experimental/helm/charts/pipelines/templates/metadata/grpc-deployment.yaml new file mode 100644 index 0000000000..ce2c36cb77 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/metadata/grpc-deployment.yaml @@ -0,0 +1,94 @@ +{{- if .Values.metadata.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: metadata-grpc-deployment + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + component: metadata-grpc-server +spec: + replicas: 1 + selector: + matchLabels: + component: metadata-grpc-server + application-crd-id: kubeflow-pipelines + template: + metadata: + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 8 }} + component: metadata-grpc-server + spec: + securityContext: + seccompProfile: + type: RuntimeDefault + containers: + - name: container + image: {{ .Values.metadata.grpc.image.repository }}:{{ .Values.metadata.grpc.image.tag | default "1.14.0" }} + securityContext: + {{- toYaml .Values.metadata.grpc.securityContext | nindent 10 }} + env: + - name: DBCONFIG_USER + valueFrom: + secretKeyRef: + name: {{ .Values.thirdParty.mysql.secretName | default "mysql-secret" }} + key: username + - name: DBCONFIG_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.thirdParty.mysql.secretName | default "mysql-secret" }} + key: password + - name: MYSQL_DATABASE + valueFrom: + configMapKeyRef: + name: pipeline-install-config + key: mlmdDb + - name: MYSQL_HOST + valueFrom: + configMapKeyRef: + name: pipeline-install-config + key: dbHost + - name: MYSQL_PORT + valueFrom: + configMapKeyRef: + name: pipeline-install-config + key: dbPort + command: ["/bin/metadata_store_server"] + args: + - --grpc_port=8080 + - --mysql_config_database=$(MYSQL_DATABASE) + - --mysql_config_host=$(MYSQL_HOST) + - --mysql_config_port=$(MYSQL_PORT) + - --mysql_config_user=$(DBCONFIG_USER) + - --mysql_config_password=$(DBCONFIG_PASSWORD) + - --enable_database_upgrade=true + - --grpc_channel_arguments=grpc.max_metadata_size=16384 + ports: + - name: grpc-api + containerPort: 8080 + livenessProbe: + tcpSocket: + port: grpc-api + initialDelaySeconds: 3 + periodSeconds: 5 + timeoutSeconds: 2 + readinessProbe: + tcpSocket: + port: grpc-api + initialDelaySeconds: 3 + periodSeconds: 5 + timeoutSeconds: 2 + serviceAccountName: metadata-grpc-server + {{- with .Values.metadata.grpc.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.metadata.grpc.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.metadata.grpc.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/experimental/helm/charts/pipelines/templates/metadata/grpc-service.yaml b/experimental/helm/charts/pipelines/templates/metadata/grpc-service.yaml new file mode 100644 index 0000000000..d0ee4c8f57 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/metadata/grpc-service.yaml @@ -0,0 +1,18 @@ +{{- if .Values.metadata.enabled }} +kind: Service +apiVersion: v1 +metadata: + name: metadata-grpc-service + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app: metadata +spec: + selector: + {{- include "kubeflow-pipelines.metadataGrpcSelectorLabels" . | nindent 4 }} + type: ClusterIP + ports: + - port: 8080 + protocol: TCP + name: grpc-api +{{- end }} \ No newline at end of file diff --git a/experimental/helm/charts/pipelines/templates/metadata/grpc-serviceaccount.yaml b/experimental/helm/charts/pipelines/templates/metadata/grpc-serviceaccount.yaml new file mode 100644 index 0000000000..c73d78f25a --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/metadata/grpc-serviceaccount.yaml @@ -0,0 +1,11 @@ +{{- if .Values.metadata.enabled }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: metadata-grpc-server + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +{{- end }} \ No newline at end of file diff --git a/experimental/helm/charts/pipelines/templates/persistence-agent/deployment.yaml b/experimental/helm/charts/pipelines/templates/persistence-agent/deployment.yaml new file mode 100644 index 0000000000..8b39838054 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/persistence-agent/deployment.yaml @@ -0,0 +1,70 @@ +{{- if .Values.persistenceAgent.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ml-pipeline-persistenceagent + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app: ml-pipeline-persistenceagent +spec: + selector: + matchLabels: + {{- include "kubeflow-pipelines.persistenceAgentSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + cluster-autoscaler.kubernetes.io/safe-to-evict: "true" + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 8 }} + app: ml-pipeline-persistenceagent + spec: + serviceAccountName: ml-pipeline-persistenceagent + containers: + - name: ml-pipeline-persistenceagent + image: {{ include "kubeflow-pipelines.image" (dict "repository" .Values.persistenceAgent.image.repository "tag" .Values.persistenceAgent.image.tag "context" .) }} + imagePullPolicy: IfNotPresent + env: + {{- range .Values.persistenceAgent.additionalEnv }} + - name: {{ .name }} + {{- if hasKey . "value" }} + value: {{ .value | quote }} + {{- else if and (hasKey . "valueFrom") .valueFrom (not (eq .valueFrom nil)) }} + valueFrom: + {{- toYaml .valueFrom | nindent 12 }} + {{- else if eq .name "NAMESPACE" }} + {{- if eq $.Values.installMode.type "multi-user" }} + value: "" + {{- else }} + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- end }} + {{- else }} + value: "" + {{- end }} + {{- end }} + - name: TTL_SECONDS_AFTER_WORKFLOW_FINISH + value: {{ .Values.persistenceAgent.env.ttlSecondsAfterWorkflowFinish | quote }} + - name: NUM_WORKERS + value: {{ .Values.persistenceAgent.env.numWorkers | quote }} + - name: LOG_LEVEL + value: {{ .Values.global.logLevel | quote }} + resources: + {{- toYaml .Values.persistenceAgent.resources | nindent 10 }} + securityContext: + {{- toYaml .Values.persistenceAgent.securityContext | nindent 10 }} + volumeMounts: + - mountPath: /var/run/secrets/kubeflow/tokens + name: persistenceagent-sa-token + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + volumes: + - name: persistenceagent-sa-token + projected: + sources: + - serviceAccountToken: + audience: pipelines.kubeflow.org + expirationSeconds: 3600 + path: persistenceagent-sa-token +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/persistence-agent/role.yaml b/experimental/helm/charts/pipelines/templates/persistence-agent/role.yaml new file mode 100644 index 0000000000..7d8f127ca1 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/persistence-agent/role.yaml @@ -0,0 +1,42 @@ +{{- if and .Values.persistenceAgent.enabled .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: ml-pipeline-persistenceagent-role + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + annotations: + {{- include "kubeflow-pipelines.annotations" . | nindent 4 }} +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 +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/persistence-agent/rolebinding.yaml b/experimental/helm/charts/pipelines/templates/persistence-agent/rolebinding.yaml new file mode 100644 index 0000000000..c884606168 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/persistence-agent/rolebinding.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.persistenceAgent.enabled .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: ml-pipeline-persistenceagent-binding + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + annotations: + {{- include "kubeflow-pipelines.annotations" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ml-pipeline-persistenceagent-role +subjects: +- kind: ServiceAccount + name: {{ include "kubeflow-pipelines.persistenceAgent.serviceAccountName" . }} + namespace: {{ include "kubeflow-pipelines.namespace" . }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/persistence-agent/serviceaccount.yaml b/experimental/helm/charts/pipelines/templates/persistence-agent/serviceaccount.yaml new file mode 100644 index 0000000000..38b006ff91 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/persistence-agent/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if and .Values.persistenceAgent.enabled .Values.persistenceAgent.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: ml-pipeline-persistenceagent + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + {{- with .Values.persistenceAgent.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/profile-controller/configmap.yaml b/experimental/helm/charts/pipelines/templates/profile-controller/configmap.yaml new file mode 100644 index 0000000000..1731513b84 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/profile-controller/configmap.yaml @@ -0,0 +1,29 @@ +{{- if and (eq .Values.installMode.type "multi-user") .Values.profileController.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: kubeflow-pipelines-profile-controller-env + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app: kubeflow-pipelines-profile-controller + annotations: + {{- include "kubeflow-pipelines.annotations" . | nindent 4 }} +data: + DISABLE_ISTIO_SIDECAR: {{ .Values.profileController.disableIstioSidecar | quote }} + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: kubeflow-pipelines-profile-controller-code + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app: kubeflow-pipelines-profile-controller + annotations: + {{- include "kubeflow-pipelines.annotations" . | nindent 4 }} +data: + sync.py: | +{{ .Files.Get "files/sync.py" | indent 4 }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/profile-controller/decorator-controller.yaml b/experimental/helm/charts/pipelines/templates/profile-controller/decorator-controller.yaml new file mode 100644 index 0000000000..3f24f245d9 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/profile-controller/decorator-controller.yaml @@ -0,0 +1,49 @@ +{{- if and (eq .Values.installMode.type "multi-user") .Values.profileController.enabled }} +apiVersion: metacontroller.k8s.io/v1alpha1 +kind: DecoratorController +metadata: + name: kubeflow-pipelines-profile-controller + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app: kubeflow-pipelines-profile-controller + annotations: + {{- include "kubeflow-pipelines.annotations" . | nindent 4 }} +spec: + resyncPeriodSeconds: 3600 + resources: + - apiVersion: v1 + resource: namespaces + labelSelector: + matchLabels: + pipelines.kubeflow.org/enabled: "true" + attachments: + - 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 +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/profile-controller/deployment.yaml b/experimental/helm/charts/pipelines/templates/profile-controller/deployment.yaml new file mode 100644 index 0000000000..8b53ed826b --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/profile-controller/deployment.yaml @@ -0,0 +1,113 @@ +{{- if .Values.profileController.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: kubeflow-pipelines-profile-controller + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app: kubeflow-pipelines-profile-controller + annotations: + {{- include "kubeflow-pipelines.annotations" . | nindent 4 }} +spec: + replicas: {{ .Values.profileController.replicas }} + selector: + matchLabels: + app: kubeflow-pipelines-profile-controller + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines + application-crd-id: kubeflow-pipelines + template: + metadata: + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 8 }} + app: kubeflow-pipelines-profile-controller + sidecar.istio.io/inject: "false" + annotations: + {{- include "kubeflow-pipelines.annotations" . | nindent 8 }} + spec: + {{- include "kubeflow-pipelines.imagePullSecrets" . | nindent 6 }} + securityContext: + seccompProfile: + type: RuntimeDefault + containers: + - name: profile-controller + securityContext: + {{- toYaml .Values.containerSecurityContext | nindent 10 }} + image: {{ .Values.profileController.image.repository }}:{{ .Values.profileController.image.tag }} + 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: AWS_ENDPOINT_URL + value: {{ .Values.seaweedfs.awsEndpointUrl }} + - name: S3_ENDPOINT_URL + value: {{ .Values.seaweedfs.s3EndpointUrl }} + - name: AWS_REGION + value: {{ .Values.seaweedfs.awsRegion }} + - name: AWS_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + key: accesskey + name: mlpipeline-minio-artifact + - name: AWS_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + key: secretkey + name: mlpipeline-minio-artifact + - name: KFP_DEFAULT_PIPELINE_ROOT + valueFrom: + configMapKeyRef: + key: defaultPipelineRoot + name: pipeline-install-config + optional: true + - name: ARTIFACTS_PROXY_ENABLED + valueFrom: + configMapKeyRef: + key: ARTIFACTS_PROXY_ENABLED + name: pipeline-install-config + optional: true + - name: ARTIFACT_RETENTION_DAYS + valueFrom: + configMapKeyRef: + key: ARTIFACT_RETENTION_DAYS + name: pipeline-install-config + {{- range .Values.profileController.additionalEnv }} + - name: {{ .name }} + {{- if .value }} + value: {{ .value | quote }} + {{- else if .valueFrom }} + valueFrom: + {{- toYaml .valueFrom | nindent 12 }} + {{- else }} + value: "" + {{- end }} + {{- end }} + volumeMounts: + - name: hooks + mountPath: /hooks + ports: + - containerPort: 8080 + volumes: + - name: hooks + configMap: + name: kubeflow-pipelines-profile-controller-code + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/profile-controller/env-configmap.yaml b/experimental/helm/charts/pipelines/templates/profile-controller/env-configmap.yaml new file mode 100644 index 0000000000..81fbef92e5 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/profile-controller/env-configmap.yaml @@ -0,0 +1,14 @@ +{{- if and (eq .Values.installMode.type "multi-user") .Values.profileController.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: kubeflow-pipelines-profile-controller-env + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app: kubeflow-pipelines-profile-controller + application-crd-id: kubeflow-pipelines +data: + DISABLE_ISTIO_SIDECAR: {{ .Values.profileController.disableIstioSidecar | quote }} +{{- end }} + diff --git a/experimental/helm/charts/pipelines/templates/profile-controller/service.yaml b/experimental/helm/charts/pipelines/templates/profile-controller/service.yaml new file mode 100644 index 0000000000..18c8e93e70 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/profile-controller/service.yaml @@ -0,0 +1,23 @@ +{{- if and (eq .Values.installMode.type "multi-user") .Values.profileController.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: kubeflow-pipelines-profile-controller + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app: kubeflow-pipelines-profile-controller + annotations: + {{- include "kubeflow-pipelines.annotations" . | nindent 4 }} +spec: + ports: + - name: http + protocol: TCP + port: {{ .Values.profileController.service.port }} + targetPort: 8080 + selector: + app: kubeflow-pipelines-profile-controller + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines + application-crd-id: kubeflow-pipelines +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/rbac/additional-serviceaccounts.yaml b/experimental/helm/charts/pipelines/templates/rbac/additional-serviceaccounts.yaml new file mode 100644 index 0000000000..4b348811fa --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/rbac/additional-serviceaccounts.yaml @@ -0,0 +1,45 @@ + +{{- if .Values.additionalServiceAccounts.containerBuilder.create }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.additionalServiceAccounts.containerBuilder.name }} + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + {{- with .Values.additionalServiceAccounts.containerBuilder.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} + +{{- if .Values.additionalServiceAccounts.pipelineRunner.create }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.additionalServiceAccounts.pipelineRunner.name }} + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + {{- with .Values.additionalServiceAccounts.pipelineRunner.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} + +{{- if .Values.additionalServiceAccounts.viewer.create }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.additionalServiceAccounts.viewer.name }} + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + {{- with .Values.additionalServiceAccounts.viewer.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/rbac/argo-workflow-controller-rbac.yaml b/experimental/helm/charts/pipelines/templates/rbac/argo-workflow-controller-rbac.yaml new file mode 100644 index 0000000000..94fbf12e16 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/rbac/argo-workflow-controller-rbac.yaml @@ -0,0 +1,199 @@ +{{- if and .Values.thirdParty.argo.enabled (eq .Values.installMode.type "multi-user") }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: argo-cluster-role + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - pods + - pods/exec + verbs: + - create + - get + - list + - watch + - update + - patch + - delete +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - watch + - list +- apiGroups: + - "" + resources: + - persistentvolumeclaims + - persistentvolumeclaims/finalizers + verbs: + - create + - update + - delete + - get +- apiGroups: + - argoproj.io + resources: + - workflows + - workflows/finalizers + - workflowtaskresults + - workflowtaskresults/finalizers + - workflowartifactgctasks + - workflowartifactgctasks/finalizers + verbs: + - get + - list + - watch + - update + - patch + - delete + - create +- apiGroups: + - argoproj.io + resources: + - workflowtemplates + - workflowtemplates/finalizers + - clusterworkflowtemplates + - clusterworkflowtemplates/finalizers + - cronworkflows + - cronworkflows/finalizers + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - get + - list +- apiGroups: + - argoproj.io + resources: + - workfloweventbindings + - workfloweventbindings/finalizers + verbs: + - get + - list + - watch +- apiGroups: + - policy + resources: + - poddisruptionbudgets + verbs: + - create + - get + - delete + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: argo-binding + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: argo-cluster-role +subjects: +- kind: ServiceAccount + name: argo + namespace: {{ include "kubeflow-pipelines.namespace" . }} + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: argo-aggregate-to-view + labels: + rbac.authorization.k8s.io/aggregate-to-view: "true" + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +rules: +- apiGroups: + - argoproj.io + resources: + - workflows + - workflows/finalizers + - workfloweventbindings + - workfloweventbindings/finalizers + - workflowtemplates + - workflowtemplates/finalizers + - cronworkflows + - cronworkflows/finalizers + - clusterworkflowtemplates + - clusterworkflowtemplates/finalizers + - workflowtaskresults + - workflowtaskresults/finalizers + verbs: + - get + - list + - watch + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: argo-aggregate-to-edit + labels: + rbac.authorization.k8s.io/aggregate-to-edit: "true" + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +rules: +- apiGroups: + - argoproj.io + resources: + - workflows + - workflows/finalizers + - workfloweventbindings + - workfloweventbindings/finalizers + - workflowtemplates + - workflowtemplates/finalizers + - cronworkflows + - cronworkflows/finalizers + - clusterworkflowtemplates + - clusterworkflowtemplates/finalizers + - workflowtaskresults + - workflowtaskresults/finalizers + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: argo-aggregate-to-admin + labels: + rbac.authorization.k8s.io/aggregate-to-admin: "true" + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +rules: +- apiGroups: + - argoproj.io + resources: + - workflows + - workflows/finalizers + - workfloweventbindings + - workfloweventbindings/finalizers + - workflowtemplates + - workflowtemplates/finalizers + - cronworkflows + - cronworkflows/finalizers + - clusterworkflowtemplates + - clusterworkflowtemplates/finalizers + - workflowtaskresults + - workflowtaskresults/finalizers + verbs: + - "*" +{{- end }} \ No newline at end of file diff --git a/experimental/helm/charts/pipelines/templates/rbac/cluster-role-bindings.yaml b/experimental/helm/charts/pipelines/templates/rbac/cluster-role-bindings.yaml new file mode 100644 index 0000000000..f78edf4c2b --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/rbac/cluster-role-bindings.yaml @@ -0,0 +1,159 @@ +{{- if eq .Values.installMode.type "multi-user" }} +# API Server ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: ml-pipeline + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: ml-pipeline +subjects: +- kind: ServiceAccount + name: {{ include "kubeflow-pipelines.apiServer.serviceAccountName" . }} + namespace: {{ include "kubeflow-pipelines.namespace" . }} + +--- +# UI ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: ml-pipeline-ui + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app: ml-pipeline-ui +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: ml-pipeline-ui +subjects: +- kind: ServiceAccount + name: {{ include "kubeflow-pipelines.ui.serviceAccountName" . }} + namespace: {{ include "kubeflow-pipelines.namespace" . }} + +--- +# Scheduled Workflow ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: ml-pipeline-scheduledworkflow-binding + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: ml-pipeline-scheduledworkflow-role +subjects: +- kind: ServiceAccount + name: {{ include "kubeflow-pipelines.scheduledWorkflow.serviceAccountName" . }} + namespace: {{ include "kubeflow-pipelines.namespace" . }} + +--- +# Persistence Agent ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: ml-pipeline-persistenceagent-binding + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: ml-pipeline-persistenceagent-role +subjects: +- kind: ServiceAccount + name: {{ include "kubeflow-pipelines.persistenceAgent.serviceAccountName" . }} + namespace: {{ include "kubeflow-pipelines.namespace" . }} + +--- +# Viewer Controller ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: ml-pipeline-viewer-crd-binding + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: ml-pipeline-viewer-controller-role +subjects: +- kind: ServiceAccount + name: {{ include "kubeflow-pipelines.viewerCrd.serviceAccountName" . }} + namespace: {{ include "kubeflow-pipelines.namespace" . }} + +--- +# Cache ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: kubeflow-pipelines-cache-binding + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app: cache-server +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: kubeflow-pipelines-cache-role +subjects: +- kind: ServiceAccount + name: {{ include "kubeflow-pipelines.cache.serviceAccountName" . }} + namespace: {{ include "kubeflow-pipelines.namespace" . }} + +--- +# Metadata Writer ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: kubeflow-pipelines-metadata-writer-binding + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: kubeflow-pipelines-metadata-writer-role +subjects: +- kind: ServiceAccount + name: {{ include "kubeflow-pipelines.metadataWriter.serviceAccountName" . }} + namespace: {{ include "kubeflow-pipelines.namespace" . }} + +{{- if .Values.thirdParty.argo.enabled }} +--- +# Argo ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: argo-binding + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: argo-cluster-role +subjects: +- kind: ServiceAccount + name: argo + namespace: {{ include "kubeflow-pipelines.namespace" . }} +{{- end }} + +--- +# Metacontroller ClusterRoleBinding +{{- if .Values.thirdParty.metacontroller.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: meta-controller-cluster-role-binding + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: kubeflow-metacontroller +subjects: +- kind: ServiceAccount + name: meta-controller-service + namespace: {{ include "kubeflow-pipelines.namespace" . }} +{{- end }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/rbac/cluster-roles.yaml b/experimental/helm/charts/pipelines/templates/rbac/cluster-roles.yaml new file mode 100644 index 0000000000..ebb7453940 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/rbac/cluster-roles.yaml @@ -0,0 +1,603 @@ +{{- if eq .Values.installMode.type "multi-user" }} +# API Server ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: ml-pipeline + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +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: + - kubeflow.org + resources: + - scheduledworkflows/finalizers + verbs: + - update +- apiGroups: + - pipelines.kubeflow.org + resources: + - pipelines + verbs: + - get + - list + - watch +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +{{- if eq .Values.installMode.pipelineDefinition.storage "k8s-native" }} +- apiGroups: + - pipelines.kubeflow.org + resources: + - pipelines + - pipelines/finalizers + verbs: + - create + - get + - list + - watch + - update + - patch + - delete +- apiGroups: + - pipelines.kubeflow.org + resources: + - pipelineversions + - pipelineversions/status + - pipelineversions/finalizers + verbs: + - create + - get + - list + - watch + - update + - patch + - delete +{{- end }} + +--- +# UI ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: ml-pipeline-ui + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines + app: 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 + + +--- +# Scheduled Workflow ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: ml-pipeline-scheduledworkflow-role + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +rules: +- apiGroups: + - argoproj.io + resources: + - workflows + verbs: + - create + - get + - list + - watch + - update + - patch + - delete +- apiGroups: + - pipelines.kubeflow.org + resources: + - runs + verbs: + - create +- apiGroups: + - kubeflow.org + resources: + - scheduledworkflows + - scheduledworkflows/finalizers + verbs: + - create + - get + - list + - watch + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + +--- +# Persistence Agent ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: ml-pipeline-persistenceagent-role + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +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 + +--- +# Viewer Controller ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: ml-pipeline-viewer-controller-role + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +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 + +--- +# Cache ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kubeflow-pipelines-cache-role + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines + app: cache-server +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 + +--- +# Metadata Writer ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kubeflow-pipelines-metadata-writer-role + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +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 + +{{- if .Values.thirdParty.argo.enabled }} +--- +# Argo Cluster Role +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: argo-cluster-role + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +rules: +- apiGroups: + - "" + resources: + - pods + - pods/exec + verbs: + - create + - get + - list + - watch + - update + - patch + - delete +- apiGroups: + - "" + resources: + - configmaps + - namespaces + verbs: + - get + - watch + - list +- apiGroups: + - "" + resources: + - persistentvolumeclaims + - persistentvolumeclaims/finalizers + verbs: + - create + - update + - delete + - get +- apiGroups: + - argoproj.io + resources: + - workflows + - workflows/finalizers + - workflowtasksets + - workflowtasksets/finalizers + - workflowartifactgctasks + verbs: + - get + - list + - watch + - update + - patch + - delete + - create +- apiGroups: + - argoproj.io + resources: + - workflowtemplates + - workflowtemplates/finalizers + - clusterworkflowtemplates + - clusterworkflowtemplates/finalizers + verbs: + - get + - list + - watch +- apiGroups: + - argoproj.io + resources: + - workflowtaskresults + verbs: + - list + - watch + - deletecollection +- apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - get + - list +- apiGroups: + - argoproj.io + resources: + - cronworkflows + - cronworkflows/finalizers + verbs: + - get + - list + - watch + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +- apiGroups: + - "policy" + resources: + - poddisruptionbudgets + verbs: + - create + - get + - delete +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + resourceNames: + - argo-workflows-agent-ca-certificates + +--- +# Argo Aggregate Roles +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: argo-aggregate-to-view + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + rbac.authorization.k8s.io/aggregate-to-view: "true" + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +rules: +- apiGroups: + - argoproj.io + resources: + - workflows + - workflows/finalizers + - workfloweventbindings + - workfloweventbindings/finalizers + - workflowtemplates + - workflowtemplates/finalizers + - cronworkflows + - cronworkflows/finalizers + - clusterworkflowtemplates + - clusterworkflowtemplates/finalizers + - workflowtaskresults + - workflowtaskresults/finalizers + verbs: + - get + - list + - watch + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: argo-aggregate-to-edit + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + rbac.authorization.k8s.io/aggregate-to-edit: "true" + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +rules: +- apiGroups: + - argoproj.io + resources: + - workflows + - workflows/finalizers + - workfloweventbindings + - workfloweventbindings/finalizers + - workflowtemplates + - workflowtemplates/finalizers + - cronworkflows + - cronworkflows/finalizers + - clusterworkflowtemplates + - clusterworkflowtemplates/finalizers + - workflowtaskresults + - workflowtaskresults/finalizers + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: argo-aggregate-to-admin + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + rbac.authorization.k8s.io/aggregate-to-admin: "true" + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +rules: +- apiGroups: + - argoproj.io + resources: + - workflows + - workflows/finalizers + - workfloweventbindings + - workfloweventbindings/finalizers + - workflowtemplates + - workflowtemplates/finalizers + - cronworkflows + - cronworkflows/finalizers + - clusterworkflowtemplates + - clusterworkflowtemplates/finalizers + - workflowtasksets + - workflowtasksets/finalizers + - workflowtaskresults + - workflowtaskresults/finalizers + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch +{{- end }} + +--- +# Metacontroller ClusterRole +{{- if .Values.thirdParty.metacontroller.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kubeflow-metacontroller + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +rules: +- apiGroups: ["*"] + resources: ["*"] + verbs: ["*"] +{{- end }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/rbac/metacontroller-clusterrole.yaml b/experimental/helm/charts/pipelines/templates/rbac/metacontroller-clusterrole.yaml new file mode 100644 index 0000000000..9a43e35dc2 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/rbac/metacontroller-clusterrole.yaml @@ -0,0 +1,37 @@ +{{- if .Values.thirdParty.metacontroller.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kubeflow-metacontroller + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + kustomize.component: metacontroller +rules: +- apiGroups: [""] + resources: ["namespaces"] + verbs: ["get", "list", "watch", "update"] +- apiGroups: [""] + resources: ["namespaces/status"] + verbs: ["get", "list", "watch", "update", "patch"] +- apiGroups: [""] + resources: ["secrets", "configmaps"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +- apiGroups: ["apps"] + resources: ["deployments"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +- apiGroups: [""] + resources: ["services"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +- apiGroups: ["networking.istio.io"] + resources: ["destinationrules"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +- apiGroups: ["security.istio.io"] + resources: ["authorizationpolicies"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +- apiGroups: ["metacontroller.k8s.io"] + resources: ["compositecontrollers", "controllerrevisions", "decoratorcontrollers"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch"] +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/rbac/metacontroller-clusterrolebinding.yaml b/experimental/helm/charts/pipelines/templates/rbac/metacontroller-clusterrolebinding.yaml new file mode 100644 index 0000000000..bd75342bfc --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/rbac/metacontroller-clusterrolebinding.yaml @@ -0,0 +1,17 @@ +{{- if .Values.thirdParty.metacontroller.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: meta-controller-cluster-role-binding + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + kustomize.component: metacontroller +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: kubeflow-metacontroller +subjects: +- kind: ServiceAccount + name: meta-controller-service + namespace: {{ include "kubeflow-pipelines.namespace" . }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/rbac/pipeline-runner-role.yaml b/experimental/helm/charts/pipelines/templates/rbac/pipeline-runner-role.yaml new file mode 100644 index 0000000000..21e6858fd0 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/rbac/pipeline-runner-role.yaml @@ -0,0 +1,94 @@ +{{- if .Values.additionalServiceAccounts.pipelineRunner.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: pipeline-runner + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + annotations: + {{- include "kubeflow-pipelines.annotations" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - secrets + verbs: + - get +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - watch + - list +- apiGroups: + - "" + resources: + - persistentvolumes + - persistentvolumeclaims + verbs: + - '*' +- apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshots + verbs: + - create + - delete + - get +- apiGroups: + - argoproj.io + resources: + - workflows + verbs: + - get + - list + - watch + - update + - patch +- apiGroups: + - "" + resources: + - pods + - pods/exec + - pods/log + - services + verbs: + - '*' +- apiGroups: + - "" + - apps + - extensions + resources: + - deployments + - replicasets + verbs: + - '*' +- apiGroups: + - kubeflow.org + resources: + - '*' + verbs: + - '*' +- apiGroups: + - batch + resources: + - jobs + verbs: + - '*' +- apiGroups: + - machinelearning.seldon.io + resources: + - seldondeployments + verbs: + - '*' +- apiGroups: + - argoproj.io + resources: + - workflowtaskresults + verbs: + - create + - patch +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/rbac/pipeline-runner-rolebinding.yaml b/experimental/helm/charts/pipelines/templates/rbac/pipeline-runner-rolebinding.yaml new file mode 100644 index 0000000000..8f7c1a48b1 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/rbac/pipeline-runner-rolebinding.yaml @@ -0,0 +1,19 @@ +{{- if .Values.additionalServiceAccounts.pipelineRunner.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: pipeline-runner-binding + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + annotations: + {{- include "kubeflow-pipelines.annotations" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: pipeline-runner +subjects: +- kind: ServiceAccount + name: {{ .Values.additionalServiceAccounts.pipelineRunner.name }} + namespace: {{ include "kubeflow-pipelines.namespace" . }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/rbac/view-edit-cluster-roles.yaml b/experimental/helm/charts/pipelines/templates/rbac/view-edit-cluster-roles.yaml new file mode 100644 index 0000000000..1a14ed72fb --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/rbac/view-edit-cluster-roles.yaml @@ -0,0 +1,156 @@ +{{- if eq .Values.installMode.type "multi-user" }} +# 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: + name: kubeflow-pipelines-edit + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + rbac.authorization.kubeflow.org/aggregate-to-kubeflow-edit: "true" + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +aggregationRule: + clusterRoleSelectors: + - matchLabels: + rbac.authorization.kubeflow.org/aggregate-to-kubeflow-pipelines-edit: "true" +rules: [] + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kubeflow-pipelines-view + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + rbac.authorization.kubeflow.org/aggregate-to-kubeflow-pipelines-edit: "true" + rbac.authorization.kubeflow.org/aggregate-to-kubeflow-view: "true" + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +aggregationRule: + clusterRoleSelectors: + - matchLabels: + rbac.authorization.kubeflow.org/aggregate-to-kubeflow-pipelines-view: "true" +rules: [] + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: aggregate-to-kubeflow-pipelines-edit + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + rbac.authorization.kubeflow.org/aggregate-to-kubeflow-pipelines-edit: "true" + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +rules: +- apiGroups: + - pipelines.kubeflow.org + resources: + - pipelines + - pipelineversions + 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 + - workflowtaskresults + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: aggregate-to-kubeflow-pipelines-view + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + rbac.authorization.kubeflow.org/aggregate-to-kubeflow-pipelines-view: "true" + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines +rules: +- apiGroups: + - pipelines.kubeflow.org + resources: + - pipelines + - pipelineversions + - 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 +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/scheduled-workflow/deployment.yaml b/experimental/helm/charts/pipelines/templates/scheduled-workflow/deployment.yaml new file mode 100644 index 0000000000..05aae79308 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/scheduled-workflow/deployment.yaml @@ -0,0 +1,73 @@ +{{- if .Values.scheduledWorkflow.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ml-pipeline-scheduledworkflow + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: +{{- if eq .Values.installMode.type "multi-user" }} + app: ml-pipeline-scheduledworkflow + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines + application-crd-id: kubeflow-pipelines +{{- else }} + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app: ml-pipeline-scheduledworkflow +{{- end }} +spec: + selector: + matchLabels: + {{- include "kubeflow-pipelines.scheduledWorkflowSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + cluster-autoscaler.kubernetes.io/safe-to-evict: "true" + labels: +{{- if eq .Values.installMode.type "multi-user" }} + app: ml-pipeline-scheduledworkflow + app.kubernetes.io/component: ml-pipeline + app.kubernetes.io/name: kubeflow-pipelines + application-crd-id: kubeflow-pipelines +{{- else }} + {{- include "kubeflow-pipelines.labels" . | nindent 8 }} + app: ml-pipeline-scheduledworkflow +{{- end }} + spec: + serviceAccountName: ml-pipeline-scheduledworkflow + containers: + - name: ml-pipeline-scheduledworkflow + image: {{ include "kubeflow-pipelines.image" (dict "repository" .Values.scheduledWorkflow.image.repository "tag" .Values.scheduledWorkflow.image.tag "context" .) }} + imagePullPolicy: IfNotPresent + env: + {{- range .Values.scheduledWorkflow.additionalEnv }} + - name: {{ .name }} + {{- if hasKey . "value" }} + value: {{ .value | quote }} + {{- else if and (hasKey . "valueFrom") .valueFrom (not (eq .valueFrom nil)) }} + valueFrom: + {{- toYaml .valueFrom | nindent 12 }} + {{- else }} + value: "" + {{- end }} + {{- end }} + - name: CRON_SCHEDULE_TIMEZONE + valueFrom: + configMapKeyRef: + key: cronScheduleTimezone + name: pipeline-install-config + securityContext: + {{- toYaml .Values.scheduledWorkflow.securityContext | nindent 10 }} + volumeMounts: + - mountPath: /var/run/secrets/kubeflow/tokens + name: scheduledworkflow-sa-token + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + volumes: + - name: scheduledworkflow-sa-token + projected: + sources: + - serviceAccountToken: + audience: pipelines.kubeflow.org + expirationSeconds: 3600 + path: scheduledworkflow-sa-token +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/scheduled-workflow/role.yaml b/experimental/helm/charts/pipelines/templates/scheduled-workflow/role.yaml new file mode 100644 index 0000000000..ac6e8f588d --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/scheduled-workflow/role.yaml @@ -0,0 +1,51 @@ +{{- if and .Values.scheduledWorkflow.enabled .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: ml-pipeline-scheduledworkflow-role + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + app: ml-pipeline-scheduledworkflow-role + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + annotations: + {{- include "kubeflow-pipelines.annotations" . | nindent 4 }} +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: + - pipelines.kubeflow.org + resources: + - runs + verbs: + - create +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/scheduled-workflow/rolebinding.yaml b/experimental/helm/charts/pipelines/templates/scheduled-workflow/rolebinding.yaml new file mode 100644 index 0000000000..7a3af29d4b --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/scheduled-workflow/rolebinding.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.scheduledWorkflow.enabled .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: ml-pipeline-scheduledworkflow-binding + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + annotations: + {{- include "kubeflow-pipelines.annotations" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ml-pipeline-scheduledworkflow-role +subjects: +- kind: ServiceAccount + name: {{ include "kubeflow-pipelines.scheduledWorkflow.serviceAccountName" . }} + namespace: {{ include "kubeflow-pipelines.namespace" . }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/scheduled-workflow/serviceaccount.yaml b/experimental/helm/charts/pipelines/templates/scheduled-workflow/serviceaccount.yaml new file mode 100644 index 0000000000..8f6cc6f420 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/scheduled-workflow/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if and .Values.scheduledWorkflow.enabled .Values.scheduledWorkflow.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: ml-pipeline-scheduledworkflow + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + {{- with .Values.scheduledWorkflow.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/third-party/argo-role.yaml b/experimental/helm/charts/pipelines/templates/third-party/argo-role.yaml new file mode 100644 index 0000000000..abed726c10 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/third-party/argo-role.yaml @@ -0,0 +1,126 @@ +{{- if .Values.thirdParty.argo.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + name: argo-role + namespace: {{ include "kubeflow-pipelines.namespace" . }} +rules: +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - get + - update +{{- if ne .Values.installMode.type "multi-user" }} +- apiGroups: + - "" + resources: + - pods + - pods/exec + verbs: + - create + - get + - list + - watch + - update + - patch + - delete +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - watch + - list +- apiGroups: + - "" + resources: + - persistentvolumeclaims + - persistentvolumeclaims/finalizers + verbs: + - create + - update + - delete + - get +- apiGroups: + - argoproj.io + resources: + - workflows + - workflows/finalizers + - workflowtasksets + - workflowtasksets/finalizers + - workflowartifactgctasks + verbs: + - get + - list + - watch + - update + - patch + - delete + - create +- apiGroups: + - argoproj.io + resources: + - workflowtemplates + - workflowtemplates/finalizers + verbs: + - get + - list + - watch +- apiGroups: + - argoproj.io + resources: + - workflowtaskresults + verbs: + - list + - watch + - deletecollection +- apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - get + - list +{{- end }} +- apiGroups: + - "" + resources: + - secrets + verbs: + - get +{{- if ne .Values.installMode.type "multi-user" }} +- apiGroups: + - argoproj.io + resources: + - cronworkflows + - cronworkflows/finalizers + verbs: + - get + - list + - watch + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +- apiGroups: + - policy + resources: + - poddisruptionbudgets + verbs: + - create + - get + - delete +{{- end }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/third-party/argo-rolebinding.yaml b/experimental/helm/charts/pipelines/templates/third-party/argo-rolebinding.yaml new file mode 100644 index 0000000000..058879bfcc --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/third-party/argo-rolebinding.yaml @@ -0,0 +1,17 @@ +{{- if .Values.thirdParty.argo.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + name: argo-binding + namespace: {{ include "kubeflow-pipelines.namespace" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: argo-role +subjects: +- kind: ServiceAccount + name: argo + namespace: {{ include "kubeflow-pipelines.namespace" . }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/third-party/metacontroller-serviceaccount.yaml b/experimental/helm/charts/pipelines/templates/third-party/metacontroller-serviceaccount.yaml new file mode 100644 index 0000000000..b86f9dc776 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/third-party/metacontroller-serviceaccount.yaml @@ -0,0 +1,10 @@ +{{- if .Values.thirdParty.metacontroller.enabled }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: meta-controller-service + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + kustomize.component: metacontroller +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/third-party/metacontroller-statefulset.yaml b/experimental/helm/charts/pipelines/templates/third-party/metacontroller-statefulset.yaml new file mode 100644 index 0000000000..a005ea63bb --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/third-party/metacontroller-statefulset.yaml @@ -0,0 +1,63 @@ +{{- if .Values.thirdParty.metacontroller.enabled }} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: metacontroller + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app: metacontroller + kustomize.component: metacontroller +spec: + replicas: 1 + selector: + matchLabels: + app: metacontroller + kustomize.component: metacontroller + application-crd-id: kubeflow-pipelines + serviceName: "" + template: + metadata: + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 8 }} + app: metacontroller + kustomize.component: metacontroller + sidecar.istio.io/inject: "false" + spec: + containers: + - name: metacontroller + image: 'ghcr.io/metacontroller/metacontroller:v4.11.22' + command: ["/usr/bin/metacontroller"] + args: + - --zap-log-level=4 + - --discovery-interval=3600s + resources: + limits: + cpu: '1' + memory: 1Gi + requests: + cpu: 100m + memory: 256Mi + livenessProbe: + httpGet: + port: 8081 + path: /healthz + readinessProbe: + httpGet: + port: 8081 + path: /readyz + securityContext: + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + privileged: false + allowPrivilegeEscalation: false + serviceAccountName: meta-controller-service + # Workaround for https://github.com/kubernetes-sigs/kustomize/issues/677 + volumeClaimTemplates: [] +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/third-party/mysql-deployment.yaml b/experimental/helm/charts/pipelines/templates/third-party/mysql-deployment.yaml new file mode 100644 index 0000000000..01159e6c50 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/third-party/mysql-deployment.yaml @@ -0,0 +1,75 @@ +{{- if .Values.thirdParty.mysql.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mysql + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app: mysql +spec: + selector: + matchLabels: + app: mysql + application-crd-id: kubeflow-pipelines + strategy: + type: Recreate + template: + metadata: + labels: + app: mysql + application-crd-id: kubeflow-pipelines + spec: + serviceAccountName: mysql + containers: + - args: + # https://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_ignore-db-dir + # Ext4, Btrfs etc. volumes root directories have a lost+found directory that should not be treated as a database. + # ignore-db-dir option has been deprecated in mysql v5.7.16. + # + # If upgrading MySQL to v8.0 fails, try removing /var/lib/mysql/lost+found folder in + # mysql-pv-claim (mysql-persistent-storage): + # + # kubectl exec -it -n kubeflow -- bash + # rm -rf /var/lib/mysql/lost+found + # + # More details on upgrading MySQL can be found here: + # https://dev.mysql.com/doc/refman/8.0/en/upgrade-prerequisites.html + # https://dev.mysql.com/doc/refman/8.0/en/upgrade-docker-mysql.html + - --datadir + - /var/lib/mysql + # MLMD workloads (metadata-grpc-deployment and metadata-writer) depend on mysql_native_password authentication plugin. + # mysql_native_password plugin implements native authentication; that is, authentication based on the password + # hashing method in use from before the introduction of pluggable authentication in MySQL 8.0. + # + # The mysql_native_password authentication plugin is deprecated as of MySQL 8.0.34, disabled by default + # in MySQL 8.4, and removed as of MySQL 9.0.0: + # https://dev.mysql.com/doc/refman/8.4/en/native-pluggable-authentication.html + - --authentication-policy=mysql_native_password + - --mysql-native-password=ON + # Disable binlog as the logs grow fast and eat up all disk spaces eventually. And KFP doesn't currently utilize binlog. + # https://dev.mysql.com/doc/refman/8.0/en/replication-options-binary-log.html#option_mysqld_log-bin + - --disable-log-bin + env: + - name: MYSQL_ALLOW_EMPTY_PASSWORD + value: "true" + image: {{ .Values.thirdParty.mysql.image }}:{{ .Values.thirdParty.mysql.imageTag }} + name: mysql + ports: + - containerPort: 3306 + name: mysql + securityContext: + {{- toYaml .Values.thirdParty.mysql.securityContext | nindent 10 }} + volumeMounts: + - mountPath: /var/lib/mysql + name: mysql-persistent-storage + resources: + {{- toYaml .Values.thirdParty.mysql.resources | nindent 10 }} + securityContext: + {{- toYaml .Values.thirdParty.mysql.podSecurityContext | nindent 8 }} + volumes: + - name: mysql-persistent-storage + persistentVolumeClaim: + claimName: mysql-pv-claim +{{- end }} + diff --git a/experimental/helm/charts/pipelines/templates/third-party/mysql-pvc.yaml b/experimental/helm/charts/pipelines/templates/third-party/mysql-pvc.yaml new file mode 100644 index 0000000000..6018db152a --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/third-party/mysql-pvc.yaml @@ -0,0 +1,16 @@ +{{- if .Values.thirdParty.mysql.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: mysql-pv-claim + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.thirdParty.mysql.persistence.size }} +{{- end }} + diff --git a/experimental/helm/charts/pipelines/templates/third-party/mysql-service.yaml b/experimental/helm/charts/pipelines/templates/third-party/mysql-service.yaml new file mode 100644 index 0000000000..1f90606232 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/third-party/mysql-service.yaml @@ -0,0 +1,19 @@ +{{- if .Values.thirdParty.mysql.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: mysql + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +spec: + ports: + - # We cannot have name: mysql here, because some requests through istio fail with it. + port: 3306 + protocol: TCP + targetPort: 3306 + selector: + app: mysql + application-crd-id: kubeflow-pipelines +{{- end }} + diff --git a/experimental/helm/charts/pipelines/templates/third-party/mysql-serviceaccount.yaml b/experimental/helm/charts/pipelines/templates/third-party/mysql-serviceaccount.yaml new file mode 100644 index 0000000000..83b0404120 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/third-party/mysql-serviceaccount.yaml @@ -0,0 +1,10 @@ +{{- if .Values.thirdParty.mysql.enabled }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: mysql + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +{{- end }} + diff --git a/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/authorization-policy.yaml b/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/authorization-policy.yaml new file mode 100644 index 0000000000..14ecfecf39 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/authorization-policy.yaml @@ -0,0 +1,28 @@ +{{- if and .Values.seaweedfs.enabled .Values.networking.istio.enabled (eq .Values.installMode.type "multi-user") }} +apiVersion: security.istio.io/v1beta1 +kind: AuthorizationPolicy +metadata: + name: seaweedfs-service + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.authorizationPolicyLabels" . | nindent 4 }} +spec: + action: ALLOW + selector: + matchLabels: + app: seaweedfs + rules: + - from: + - source: + principals: + - cluster.local/ns/{{ include "kubeflow-pipelines.namespace" . }}/sa/ml-pipeline + - from: + - source: + principals: + - cluster.local/ns/{{ include "kubeflow-pipelines.namespace" . }}/sa/ml-pipeline-ui + # Allow traffic to s3 endpoint from User Pipeline Pods, which don't have a sidecar. + # Also needed for traffic from seaweedfs init pod. Seaweedfs gives the client an ip to connect to. This can not be + # handled well by istio (AuthPolicy). Instead, access to the sensitive ports will be limited by the NetworkPolicy. + - {} +{{- end }} + diff --git a/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/deployment.yaml b/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/deployment.yaml new file mode 100644 index 0000000000..592cffda6c --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/deployment.yaml @@ -0,0 +1,101 @@ +{{- if .Values.seaweedfs.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: seaweedfs + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app: seaweedfs +spec: + selector: + matchLabels: + app: seaweedfs + application-crd-id: kubeflow-pipelines + strategy: + type: Recreate + # Single container setup not scalable + replicas: 1 + template: + metadata: + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 8 }} + app: seaweedfs + application-crd-id: kubeflow-pipelines + spec: + securityContext: + seccompProfile: + type: RuntimeDefault + fsGroup: 1000 + fsGroupChangePolicy: "OnRootMismatch" + containers: + - name: seaweedfs + envFrom: + - secretRef: + name: mlpipeline-minio-artifact + image: "chrislusf/seaweedfs:{{ .Values.seaweedfs.imageTag | default "4.00" }}" + args: + - "server" + - "-dir=/data" + - "-s3" + - "-iam" + - "-filer" + - "-master.volumePreallocate=false" + lifecycle: + postStart: + exec: + command: + - /bin/sh + - -ec + - | + # wait until seaweedfs master is ready + for i in $(seq 1 120); do + if wget -q --spider http://127.0.0.1:8333/status; then + break + fi + sleep 2 + done + # create bucket if not exists (ignore error if exists) + echo "s3.bucket.create --name mlpipeline" | /usr/bin/weed shell || true + # configure admin user using keys from secret + echo "s3.configure -user kubeflow-admin -access_key $accesskey -secret_key $secretkey -actions Admin -apply" | /usr/bin/weed shell + ports: + - containerPort: 8333 + - containerPort: 8111 + - containerPort: 9333 + - containerPort: 19333 + - containerPort: 8888 + readinessProbe: + httpGet: + path: /status + port: 8333 + scheme: HTTP + initialDelaySeconds: 15 + periodSeconds: 15 + successThreshold: 1 + failureThreshold: 100 + timeoutSeconds: 10 + securityContext: # Using restricted profile + allowPrivilegeEscalation: false + privileged: false + runAsNonRoot: true + # image defaults to root user + runAsUser: 1000 + runAsGroup: 1000 + capabilities: + drop: + - ALL + volumeMounts: + - mountPath: /data + name: data + resources: + requests: + cpu: 32m + memory: 128Mi + volumes: + - name: data + persistentVolumeClaim: + claimName: seaweedfs-pvc + serviceAccountName: seaweedfs +{{- end }} + diff --git a/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/destination-rule.yaml b/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/destination-rule.yaml new file mode 100644 index 0000000000..aab413ca00 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/destination-rule.yaml @@ -0,0 +1,15 @@ +{{- if and .Values.seaweedfs.enabled .Values.networking.istio.enabled }} +apiVersion: "networking.istio.io/v1alpha3" +kind: DestinationRule +metadata: + name: ml-pipeline-seaweedfs + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +spec: + host: seaweedfs.{{ include "kubeflow-pipelines.namespace" . }}.svc.cluster.local + trafficPolicy: + tls: + mode: ISTIO_MUTUAL +{{- end }} + diff --git a/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/minio-service.yaml b/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/minio-service.yaml new file mode 100644 index 0000000000..caab285420 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/minio-service.yaml @@ -0,0 +1,22 @@ +{{- if .Values.seaweedfs.enabled }} +# Backward compatibility service for Minio API +apiVersion: v1 +kind: Service +metadata: + name: minio-service + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + app: seaweedfs + component: minio-compatibility +spec: + ports: + - name: http + port: 9000 + protocol: TCP + targetPort: 8333 + selector: + app: seaweedfs + application-crd-id: kubeflow-pipelines +{{- end }} + diff --git a/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/networkpolicy.yaml b/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/networkpolicy.yaml new file mode 100644 index 0000000000..323cbd03f1 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/networkpolicy.yaml @@ -0,0 +1,36 @@ +{{- if and .Values.seaweedfs.enabled .Values.networking.networkPolicy.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: seaweedfs + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +spec: + ingress: + - from: + - namespaceSelector: + matchExpressions: + - key: app.kubernetes.io/part-of + operator: In + values: + - kubeflow-profile + ports: + - port: 8333 + - from: + - namespaceSelector: + matchExpressions: + - key: kubernetes.io/metadata.name + operator: In + values: + - istio-system + podSelector: + matchExpressions: + - key: app + operator: In + values: + - seaweedfs + policyTypes: + - Ingress +{{- end }} + diff --git a/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/pvc.yaml b/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/pvc.yaml new file mode 100644 index 0000000000..574499e382 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/pvc.yaml @@ -0,0 +1,16 @@ +{{- if .Values.seaweedfs.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: seaweedfs-pvc + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ dig "persistence" "size" "20Gi" .Values.seaweedfs }} +{{- end }} + diff --git a/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/secret.yaml b/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/secret.yaml new file mode 100644 index 0000000000..ab13f3af3f --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/secret.yaml @@ -0,0 +1,13 @@ +{{- if .Values.seaweedfs.enabled }} +kind: Secret +apiVersion: v1 +metadata: + name: mlpipeline-minio-artifact + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +stringData: + accesskey: {{ dig "credentials" "accesskey" "minio" .Values.seaweedfs }} + secretkey: {{ dig "credentials" "secretkey" "minio123" .Values.seaweedfs }} +{{- end }} + diff --git a/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/service-account.yaml b/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/service-account.yaml new file mode 100644 index 0000000000..5e1620de1b --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/service-account.yaml @@ -0,0 +1,10 @@ +{{- if .Values.seaweedfs.enabled }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: seaweedfs + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +{{- end }} + diff --git a/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/service.yaml b/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/service.yaml new file mode 100644 index 0000000000..660ec0268b --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/third-party/seaweedfs/service.yaml @@ -0,0 +1,43 @@ +{{- if .Values.seaweedfs.enabled }} +# Separate service for new ports of seaweedfs. If we add them to the existing minio-service there will be a problem +# with the mlpipeline api server because it relies on MINIO_SERVICE_SERVICE_PORT pointing to the S3 port. +# But with multiple ports on a service that is not really reliable. So we use the existing minio-service for +# backwards-compatibility, but everything new, seaweedfs related is here. +apiVersion: v1 +kind: Service +metadata: + name: seaweedfs + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +spec: + ports: + - name: http-iam + port: 8111 + protocol: TCP + targetPort: 8111 + - name: http-s3 + port: 8333 + protocol: TCP + targetPort: 8333 + - name: http-master + port: 9333 + protocol: TCP + targetPort: 9333 + - name: grpc-master + port: 19333 + protocol: TCP + targetPort: 19333 + - name: grpc-filer + port: 18888 + protocol: TCP + targetPort: 18888 + - name: http-filer + port: 8888 + protocol: TCP + targetPort: 8888 + selector: + app: seaweedfs + application-crd-id: kubeflow-pipelines +{{- end }} + diff --git a/experimental/helm/charts/pipelines/templates/third-party/workflow-controller-configmap.yaml b/experimental/helm/charts/pipelines/templates/third-party/workflow-controller-configmap.yaml new file mode 100644 index 0000000000..b40d4de938 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/third-party/workflow-controller-configmap.yaml @@ -0,0 +1,36 @@ +{{- if .Values.thirdParty.argo.enabled }} +apiVersion: v1 +data: + artifactRepository: | + archiveLogs: true + s3: + endpoint: "minio-service.kubeflow:9000" + bucket: {{ include "kubeflow-pipelines.objectStore.bucket" . | quote }} + # keyFormat is a format pattern to define how artifacts will be organized in a bucket. + # It can reference workflow metadata variables such as workflow.namespace, workflow.name, + # pod.name. Can also use strftime formating of workflow.creationTimestamp so that workflow + # artifacts can be organized by date. If omitted, will use `{{`{{workflow.name}}`}}/{{`{{pod.name}}`}}`, + # which has potential for have collisions, because names do not guarantee they are unique + # over the lifetime of the cluster. + # Refer to https://kubernetes.io/docs/concepts/overview/working-with-objects/names/. + # + # The following format looks like: + # artifacts/my-workflow-abc123/2018/08/23/my-workflow-abc123-1234567890 + # Adding date into the path greatly reduces the chance of {{`{{pod.name}}`}} collision. + keyFormat: "private-artifacts/{{`{{workflow.namespace}}`}}/{{`{{workflow.name}}`}}/{{`{{workflow.creationTimestamp.Y}}`}}/{{`{{workflow.creationTimestamp.m}}`}}/{{`{{workflow.creationTimestamp.d}}`}}/{{`{{pod.name}}`}}" + insecure: true + accessKeySecret: + name: mlpipeline-minio-artifact + key: accesskey + secretKeySecret: + name: mlpipeline-minio-artifact + key: secretkey + executor: | + imagePullPolicy: IfNotPresent +kind: ConfigMap +metadata: + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + name: workflow-controller-configmap + namespace: {{ include "kubeflow-pipelines.namespace" . }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/third-party/workflow-controller-deployment.yaml b/experimental/helm/charts/pipelines/templates/third-party/workflow-controller-deployment.yaml new file mode 100644 index 0000000000..6c7a7f5d23 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/third-party/workflow-controller-deployment.yaml @@ -0,0 +1,69 @@ +{{- if .Values.thirdParty.argo.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + name: workflow-controller + namespace: {{ include "kubeflow-pipelines.namespace" . }} +spec: + selector: + matchLabels: + {{- include "kubeflow-pipelines.workflowControllerSelectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 8 }} + app: workflow-controller + spec: + containers: + - args: + - --configmap + - workflow-controller-configmap + - --executor-image + - quay.io/argoproj/argoexec:v3.7.3 + {{- if ne .Values.installMode.type "multi-user" }} + - --namespaced + {{- end }} + command: + - workflow-controller + env: + - name: LEADER_ELECTION_IDENTITY + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: quay.io/argoproj/workflow-controller:v3.7.3 + livenessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: 6060 + initialDelaySeconds: 90 + periodSeconds: 60 + timeoutSeconds: 30 + name: workflow-controller + ports: + - containerPort: 9090 + name: metrics + - containerPort: 6060 + resources: + requests: + cpu: 100m + memory: 500Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + nodeSelector: + kubernetes.io/os: linux + priorityClassName: workflow-controller + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + serviceAccountName: argo +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/third-party/workflow-controller-priorityclass.yaml b/experimental/helm/charts/pipelines/templates/third-party/workflow-controller-priorityclass.yaml new file mode 100644 index 0000000000..dab0f03518 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/third-party/workflow-controller-priorityclass.yaml @@ -0,0 +1,9 @@ +{{- if .Values.thirdParty.argo.enabled }} +apiVersion: scheduling.k8s.io/v1 +kind: PriorityClass +metadata: + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + name: workflow-controller +value: 1000000 +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/third-party/workflow-controller-serviceaccount.yaml b/experimental/helm/charts/pipelines/templates/third-party/workflow-controller-serviceaccount.yaml new file mode 100644 index 0000000000..99122d6f69 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/third-party/workflow-controller-serviceaccount.yaml @@ -0,0 +1,9 @@ +{{- if .Values.thirdParty.argo.enabled }} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + name: argo + namespace: {{ include "kubeflow-pipelines.namespace" . }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/ui/deployment.yaml b/experimental/helm/charts/pipelines/templates/ui/deployment.yaml new file mode 100644 index 0000000000..67957762f2 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/ui/deployment.yaml @@ -0,0 +1,89 @@ +{{- if .Values.ui.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ml-pipeline-ui + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.uiLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "kubeflow-pipelines.uiSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + cluster-autoscaler.kubernetes.io/safe-to-evict: "true" + labels: + {{- include "kubeflow-pipelines.uiLabels" . | nindent 8 }} + spec: + serviceAccountName: ml-pipeline-ui + volumes: + - name: config-volume + configMap: + name: ml-pipeline-ui-configmap + containers: + - name: ml-pipeline-ui + image: {{ include "kubeflow-pipelines.image" (dict "repository" .Values.ui.image.repository "tag" .Values.ui.image.tag "context" .) }} + imagePullPolicy: IfNotPresent + ports: + - containerPort: 3000 + volumeMounts: + - name: config-volume + mountPath: /etc/config + readOnly: true + env: + {{- range .Values.ui.additionalEnv }} + - name: {{ .name }} + {{- if .value }} + value: {{ .value | quote }} + {{- else if and .key (ne .key "null") }} + {{- if or (eq .name "MINIO_ACCESS_KEY") (eq .name "MINIO_SECRET_KEY") }} + valueFrom: + secretKeyRef: + name: mlpipeline-minio-artifact + key: {{ .key }} + {{- else }} + valueFrom: + configMapKeyRef: + name: pipeline-install-config + key: {{ .key }} + {{- end }} + {{- else if .valueFrom }} + valueFrom: + {{- toYaml .valueFrom | nindent 12 }} + {{- else if or (eq .name "MINIO_NAMESPACE") (eq .name "FRONTEND_SERVER_NAMESPACE") }} + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- else if eq .name "ALLOW_CUSTOM_VISUALIZATIONS" }} + value: {{ $.Values.ui.env.allowCustomVisualizations | quote }} + {{- else if eq .name "ARGO_ARCHIVE_LOGS" }} + value: {{ $.Values.ui.env.argoArchiveLogs | quote }} + {{- else if eq .name "DISABLE_GKE_METADATA" }} + value: {{ $.Values.ui.env.disableGkeMetadata | quote }} + {{- else }} + value: "" + {{- end }} + {{- end }} + livenessProbe: + httpGet: + path: /apis/v1beta1/healthz + port: 3000 + initialDelaySeconds: {{ .Values.ui.probes.liveness.initialDelaySeconds }} + periodSeconds: {{ .Values.ui.probes.liveness.periodSeconds }} + timeoutSeconds: {{ .Values.ui.probes.liveness.timeoutSeconds }} + readinessProbe: + httpGet: + path: /apis/v1beta1/healthz + port: 3000 + initialDelaySeconds: {{ .Values.ui.probes.readiness.initialDelaySeconds }} + periodSeconds: {{ .Values.ui.probes.readiness.periodSeconds }} + timeoutSeconds: {{ .Values.ui.probes.readiness.timeoutSeconds }} + resources: + {{- toYaml .Values.ui.resources | nindent 10 }} + securityContext: + {{- toYaml .Values.ui.securityContext | nindent 10 }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/ui/role.yaml b/experimental/helm/charts/pipelines/templates/ui/role.yaml new file mode 100644 index 0000000000..a4b75afbca --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/ui/role.yaml @@ -0,0 +1,48 @@ +{{- if .Values.ui.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + {{- include "kubeflow-pipelines.uiLabels" . | nindent 4 }} + name: ml-pipeline-ui + namespace: {{ include "kubeflow-pipelines.namespace" . }} +rules: +- apiGroups: + - "" + resources: + - pods + - pods/log + verbs: + - get +- apiGroups: + - "" + resources: + - events + verbs: + - list +- apiGroups: + - "" + resources: + - secrets + - configmaps + verbs: + - get + - list +- apiGroups: + - kubeflow.org + resources: + - viewers + verbs: + - create + - get + - list + - watch + - delete +- apiGroups: + - argoproj.io + resources: + - workflows + verbs: + - get + - list +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/ui/rolebinding.yaml b/experimental/helm/charts/pipelines/templates/ui/rolebinding.yaml new file mode 100644 index 0000000000..a53196a948 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/ui/rolebinding.yaml @@ -0,0 +1,17 @@ +{{- if .Values.ui.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + {{- include "kubeflow-pipelines.uiLabels" . | nindent 4 }} + name: ml-pipeline-ui + namespace: {{ include "kubeflow-pipelines.namespace" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ml-pipeline-ui +subjects: +- kind: ServiceAccount + name: {{ include "kubeflow-pipelines.ui.serviceAccountName" . }} + namespace: {{ include "kubeflow-pipelines.namespace" . }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/ui/service.yaml b/experimental/helm/charts/pipelines/templates/ui/service.yaml new file mode 100644 index 0000000000..2f5dc5cf0e --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/ui/service.yaml @@ -0,0 +1,17 @@ +{{- if .Values.ui.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: ml-pipeline-ui + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.uiLabels" . | nindent 4 }} +spec: + ports: + - name: http + port: 80 + protocol: TCP + targetPort: 3000 + selector: + {{- include "kubeflow-pipelines.uiSelectorLabels" . | nindent 4 }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/ui/serviceaccount.yaml b/experimental/helm/charts/pipelines/templates/ui/serviceaccount.yaml new file mode 100644 index 0000000000..1f5d25d711 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/ui/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if and .Values.ui.enabled .Values.ui.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: ml-pipeline-ui + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + {{- with .Values.ui.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/viewer-crd/deployment.yaml b/experimental/helm/charts/pipelines/templates/viewer-crd/deployment.yaml new file mode 100644 index 0000000000..c3e4acc2c6 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/viewer-crd/deployment.yaml @@ -0,0 +1,51 @@ +{{- if .Values.viewerCrd.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ml-pipeline-viewer-crd + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.viewerCrdLabels" . | nindent 4 }} +{{- if eq .Values.installMode.type "multi-user" }} + application-crd-id: kubeflow-pipelines +{{- end }} +spec: + selector: + matchLabels: + {{- include "kubeflow-pipelines.viewerCrdSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + cluster-autoscaler.kubernetes.io/safe-to-evict: "true" + labels: + {{- include "kubeflow-pipelines.viewerCrdLabels" . | nindent 8 }} +{{- if eq .Values.installMode.type "multi-user" }} + application-crd-id: kubeflow-pipelines +{{- end }} + spec: + serviceAccountName: ml-pipeline-viewer-crd-service-account + containers: + - name: ml-pipeline-viewer-crd + image: {{ include "kubeflow-pipelines.image" (dict "repository" .Values.viewerCrd.image.repository "tag" .Values.viewerCrd.image.tag "context" .) }} + imagePullPolicy: {{ .Values.viewerCrd.image.pullPolicy | default .Values.global.imagePullPolicy }} + env: + {{- range .Values.viewerCrd.additionalEnv }} + - name: {{ .name }} + {{- if hasKey . "value" }} + value: {{ .value | quote }} + {{- else if and (hasKey . "valueFrom") .valueFrom (not (eq .valueFrom nil)) }} + valueFrom: + {{- toYaml .valueFrom | nindent 12 }} + {{- else if eq .name "NAMESPACE" }} + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- else }} + value: "" + {{- end }} + {{- end }} + securityContext: + {{- toYaml .Values.viewerCrd.securityContext | nindent 10 }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/viewer-crd/role.yaml b/experimental/helm/charts/pipelines/templates/viewer-crd/role.yaml new file mode 100644 index 0000000000..6d58f027a9 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/viewer-crd/role.yaml @@ -0,0 +1,36 @@ +{{- if .Values.viewerCrd.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + name: ml-pipeline-viewer-controller-role + namespace: {{ include "kubeflow-pipelines.namespace" . }} +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 +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/viewer-crd/rolebinding.yaml b/experimental/helm/charts/pipelines/templates/viewer-crd/rolebinding.yaml new file mode 100644 index 0000000000..f48104909f --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/viewer-crd/rolebinding.yaml @@ -0,0 +1,17 @@ +{{- if .Values.viewerCrd.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + name: ml-pipeline-viewer-crd-binding + namespace: {{ include "kubeflow-pipelines.namespace" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ml-pipeline-viewer-controller-role +subjects: +- kind: ServiceAccount + name: {{ include "kubeflow-pipelines.viewerCrd.serviceAccountName" . }} + namespace: {{ include "kubeflow-pipelines.namespace" . }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/viewer-crd/serviceaccount.yaml b/experimental/helm/charts/pipelines/templates/viewer-crd/serviceaccount.yaml new file mode 100644 index 0000000000..c2ce952844 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/viewer-crd/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if and .Values.viewerCrd.enabled .Values.viewerCrd.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: ml-pipeline-viewer-crd-service-account + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + {{- with .Values.viewerCrd.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/visualization/deployment.yaml b/experimental/helm/charts/pipelines/templates/visualization/deployment.yaml new file mode 100644 index 0000000000..e452d95bd2 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/visualization/deployment.yaml @@ -0,0 +1,49 @@ +{{- if .Values.visualization.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ml-pipeline-visualizationserver + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.visualizationLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "kubeflow-pipelines.visualizationSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + cluster-autoscaler.kubernetes.io/safe-to-evict: "true" + labels: + {{- include "kubeflow-pipelines.visualizationLabels" . | nindent 8 }} + spec: + serviceAccountName: ml-pipeline-visualizationserver + securityContext: + seccompProfile: + type: RuntimeDefault + containers: + - name: ml-pipeline-visualizationserver + image: {{ include "kubeflow-pipelines.image" (dict "repository" .Values.visualization.image.repository "tag" .Values.visualization.image.tag "context" .) }} + imagePullPolicy: {{ .Values.global.imagePullPolicy }} + ports: + - name: http + containerPort: 8888 + livenessProbe: + httpGet: + path: / + port: 8888 + initialDelaySeconds: {{ .Values.visualization.probes.liveness.initialDelaySeconds }} + periodSeconds: {{ .Values.visualization.probes.liveness.periodSeconds }} + timeoutSeconds: {{ .Values.visualization.probes.liveness.timeoutSeconds }} + readinessProbe: + httpGet: + path: / + port: 8888 + initialDelaySeconds: {{ .Values.visualization.probes.readiness.initialDelaySeconds }} + periodSeconds: {{ .Values.visualization.probes.readiness.periodSeconds }} + timeoutSeconds: {{ .Values.visualization.probes.readiness.timeoutSeconds }} + resources: + {{- toYaml .Values.visualization.resources | nindent 10 }} + securityContext: + {{- toYaml .Values.visualization.securityContext | nindent 10 }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/visualization/service.yaml b/experimental/helm/charts/pipelines/templates/visualization/service.yaml new file mode 100644 index 0000000000..437406ad7a --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/visualization/service.yaml @@ -0,0 +1,17 @@ +{{- if .Values.visualization.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: ml-pipeline-visualizationserver + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} +spec: + ports: + - name: http + port: 8888 + protocol: TCP + targetPort: 8888 + selector: + {{- include "kubeflow-pipelines.visualizationSelectorLabels" . | nindent 4 }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/visualization/serviceaccount.yaml b/experimental/helm/charts/pipelines/templates/visualization/serviceaccount.yaml new file mode 100644 index 0000000000..6442563f1d --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/visualization/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if and .Values.visualization.enabled .Values.visualization.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: ml-pipeline-visualizationserver + namespace: {{ include "kubeflow-pipelines.namespace" . }} + labels: + {{- include "kubeflow-pipelines.labels" . | nindent 4 }} + {{- with .Values.visualization.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/experimental/helm/charts/pipelines/templates/webhook/certificate.yaml b/experimental/helm/charts/pipelines/templates/webhook/certificate.yaml new file mode 100644 index 0000000000..644bb82625 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/webhook/certificate.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.certManager.enabled (eq .Values.installMode.pipelineDefinition.storage "k8s-native") }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: kfp-api-webhook-cert + namespace: {{ include "kubeflow-pipelines.namespace" . }} +spec: + commonName: kfp-api-webhook-cert + isCA: true + dnsNames: + - ml-pipeline + - ml-pipeline.{{ include "kubeflow-pipelines.namespace" . }} + - ml-pipeline.{{ include "kubeflow-pipelines.namespace" . }}.svc + - ml-pipeline.{{ include "kubeflow-pipelines.namespace" . }}.svc.cluster.local + issuerRef: + kind: Issuer + name: kfp-api-webhook-selfsigned-issuer + secretName: kfp-api-webhook-cert +{{- end }} + diff --git a/experimental/helm/charts/pipelines/templates/webhook/issuer.yaml b/experimental/helm/charts/pipelines/templates/webhook/issuer.yaml new file mode 100644 index 0000000000..60465cddd8 --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/webhook/issuer.yaml @@ -0,0 +1,10 @@ +{{- if and .Values.certManager.enabled (eq .Values.installMode.pipelineDefinition.storage "k8s-native") }} +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: kfp-api-webhook-selfsigned-issuer + namespace: {{ include "kubeflow-pipelines.namespace" . }} +spec: + selfSigned: {} +{{- end }} + diff --git a/experimental/helm/charts/pipelines/templates/webhook/mutating-webhook.yaml b/experimental/helm/charts/pipelines/templates/webhook/mutating-webhook.yaml new file mode 100644 index 0000000000..e5e63b6f9c --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/webhook/mutating-webhook.yaml @@ -0,0 +1,32 @@ +{{- if and (eq .Values.installMode.type "multi-user") (eq .Values.installMode.pipelineDefinition.storage "k8s-native") }} +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: pipelineversions.pipelines.kubeflow.org + annotations: + cert-manager.io/inject-ca-from: {{ include "kubeflow-pipelines.namespace" . }}/kfp-api-webhook-cert +webhooks: + - name: pipelineversions.pipelines.kubeflow.org + rules: + - operations: + - CREATE + - UPDATE + apiGroups: + - pipelines.kubeflow.org + apiVersions: + - v2beta1 + resources: + - pipelineversions + scope: Namespaced + admissionReviewVersions: + - v1 + sideEffects: None + failurePolicy: {{ .Values.webhooks.failurePolicy | default "Fail" }} + clientConfig: + service: + name: ml-pipeline + namespace: {{ include "kubeflow-pipelines.namespace" . }} + path: /webhooks/mutate-pipelineversion + port: 8443 +{{- end }} + diff --git a/experimental/helm/charts/pipelines/templates/webhook/validating-webhook.yaml b/experimental/helm/charts/pipelines/templates/webhook/validating-webhook.yaml new file mode 100644 index 0000000000..8f2387267a --- /dev/null +++ b/experimental/helm/charts/pipelines/templates/webhook/validating-webhook.yaml @@ -0,0 +1,32 @@ +{{- if and (eq .Values.installMode.type "multi-user") (eq .Values.installMode.pipelineDefinition.storage "k8s-native") }} +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: pipelineversions.pipelines.kubeflow.org + annotations: + cert-manager.io/inject-ca-from: {{ include "kubeflow-pipelines.namespace" . }}/kfp-api-webhook-cert +webhooks: + - name: pipelineversions.pipelines.kubeflow.org + rules: + - operations: + - CREATE + - UPDATE + apiGroups: + - pipelines.kubeflow.org + apiVersions: + - v2beta1 + resources: + - pipelineversions + scope: Namespaced + admissionReviewVersions: + - v1 + sideEffects: None + failurePolicy: {{ .Values.webhooks.failurePolicy | default "Fail" }} + clientConfig: + service: + name: ml-pipeline + namespace: {{ include "kubeflow-pipelines.namespace" . }} + path: /webhooks/validate-pipelineversion + port: 8443 +{{- end }} + diff --git a/experimental/helm/charts/pipelines/values.yaml b/experimental/helm/charts/pipelines/values.yaml new file mode 100644 index 0000000000..da4f7e6bf1 --- /dev/null +++ b/experimental/helm/charts/pipelines/values.yaml @@ -0,0 +1,744 @@ +# Default values for kubeflow-pipelines +# This configuration supports 2 flavors: +# 1. platform-agnostic-multi-user (pipelineDefinition.storage: database) +# 2. platform-agnostic-multi-user-k8s-native (pipelineDefinition.storage: k8s-native) +# Global settings +global: + # -- Namespace to install Kubeflow Pipelines + namespace: kubeflow + # -- Image registry for Kubeflow Pipelines images + imageRegistry: ghcr.io/kubeflow + # -- Global image tag for all Kubeflow Pipelines components + imageTag: 2.15.0 + # -- Global image pull policy + imagePullPolicy: IfNotPresent + # -- Global log level + logLevel: "info" + +podSecurityContext: + seccompProfile: + type: RuntimeDefault + +containerSecurityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 0 + capabilities: + drop: + - ALL + +# Installation mode configuration +installMode: + # -- Installation type: multi-user (only mode supported) + type: multi-user + + # Pipeline definition storage mode + pipelineDefinition: + storage: database + +# Custom Resource Definitions +crds: + # -- Install Pipeline CRDs + install: true + # -- Install Webhook CRDs (required for k8s-native mode) + webhook: false + +# API Server configuration +apiServer: + enabled: true + replicas: 1 + + image: + repository: kfp-api-server + tag: "" # Uses global.imageTag if not set + + resources: + requests: + cpu: 250m + memory: 500Mi + + # Probes configuration + probes: + liveness: + initialDelaySeconds: 3 + periodSeconds: 5 + timeoutSeconds: 2 + readiness: + initialDelaySeconds: 3 + periodSeconds: 5 + timeoutSeconds: 2 + startup: + initialDelaySeconds: 3 + failureThreshold: 12 + periodSeconds: 5 + timeoutSeconds: 2 + + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 0 + capabilities: + drop: + - ALL + + serviceAccount: + create: true + name: "ml-pipeline" + + service: + type: ClusterIP + port: 8888 + grpcPort: 8887 + + env: + # -- V2 driver image + v2DriverImage: "ghcr.io/kubeflow/kfp-driver:2.15.0" + # -- V2 launcher image + v2LauncherImage: "ghcr.io/kubeflow/kfp-launcher:2.15.0" + + additionalEnv: + - name: KUBEFLOW_USERID_HEADER + value: kubeflow-userid + - name: KUBEFLOW_USERID_PREFIX + value: "" + - name: PUBLISH_LOGS + value: true + - name: LOG_LEVEL + value: "info" + - name: PIPELINE_LOG_LEVEL + value: "1" + - name: AUTO_UPDATE_PIPELINE_DEFAULT_VERSION + key: autoUpdatePipelineDefaultVersion + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: OBJECTSTORECONFIG_SECURE + value: false + - name: OBJECTSTORECONFIG_BUCKETNAME + key: bucketName + - name: OBJECTSTORECONFIG_HOST + value: "minio-service.kubeflow" + - name: OBJECTSTORECONFIG_PORT + value: "9000" + - name: DBCONFIG_USER + key: username + - name: DBCONFIG_PASSWORD + key: password + - name: DBCONFIG_DBNAME + key: pipelineDb + - name: DBCONFIG_HOST + key: dbHost + - name: DBCONFIG_PORT + key: dbPort + - name: DBCONFIG_CONMAXLIFETIME + key: ConMaxLifeTime + - name: DB_DRIVER_NAME + key: dbType + - name: DBCONFIG_MYSQLCONFIG_USER + key: username + - name: DBCONFIG_MYSQLCONFIG_PASSWORD + key: password + - name: DBCONFIG_MYSQLCONFIG_DBNAME + key: pipelineDb + - name: DBCONFIG_MYSQLCONFIG_HOST + key: mysqlHost + - name: DBCONFIG_MYSQLCONFIG_PORT + key: mysqlPort + - name: OBJECTSTORECONFIG_ACCESSKEY + key: accesskey + - name: OBJECTSTORECONFIG_SECRETACCESSKEY + key: secretkey + - name: V2_DRIVER_IMAGE + value: ghcr.io/kubeflow/kfp-driver:2.15.0 + - name: V2_LAUNCHER_IMAGE + value: ghcr.io/kubeflow/kfp-launcher:2.15.0 + - name: COMPILED_PIPELINE_SPEC_PATCH + value: "{}" +# Persistence Agent configuration +persistenceAgent: + enabled: true + replicas: 1 + + image: + repository: kfp-persistence-agent + tag: "" + + resources: + requests: + cpu: 120m + memory: 500Mi + + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 0 + capabilities: + drop: + - ALL + + serviceAccount: + create: true + name: "ml-pipeline-persistenceagent" + + env: + ttlSecondsAfterWorkflowFinish: "86400" + numWorkers: "2" + + additionalEnv: [] + +# Scheduled Workflow Controller configuration +scheduledWorkflow: + enabled: true + replicas: 1 + + image: + repository: kfp-scheduled-workflow-controller + tag: "" + + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 0 + capabilities: + drop: + - ALL + + serviceAccount: + create: true + name: "ml-pipeline-scheduledworkflow" + + resources: + requests: + cpu: 120m + memory: 100Mi + +# UI configuration +ui: + enabled: true + replicas: 1 + + image: + repository: kfp-frontend + tag: "" + + resources: + requests: + cpu: 10m + memory: 70Mi + + # Probes configuration + probes: + liveness: + initialDelaySeconds: 3 + periodSeconds: 5 + timeoutSeconds: 2 + readiness: + initialDelaySeconds: 3 + periodSeconds: 5 + timeoutSeconds: 2 + + # Environment variables + env: + allowCustomVisualizations: "true" + argoArchiveLogs: "true" + disableGkeMetadata: "true" + + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 0 + capabilities: + drop: + - ALL + + serviceAccount: + create: true + name: "ml-pipeline-ui" + + service: + type: ClusterIP + port: 80 + + additionalEnv: + - 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 + valueFrom: + configMapKeyRef: + name: pipeline-install-config + key: ARTIFACTS_PROXY_ENABLED + optional: true + - name: ENABLE_AUTHZ + value: "true" + - name: KUBEFLOW_USERID_HEADER + value: "kubeflow-userid" + - name: KUBEFLOW_USERID_PREFIX + value: "" + - name: MINIO_NAMESPACE + value: "" + - name: MINIO_ACCESS_KEY + valueFrom: + secretKeyRef: + name: mlpipeline-minio-artifact + key: accesskey + - name: MINIO_SECRET_KEY + valueFrom: + secretKeyRef: + name: mlpipeline-minio-artifact + key: secretkey + - name: ALLOW_CUSTOM_VISUALIZATIONS + value: "true" + - name: FRONTEND_SERVER_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: ARGO_ARCHIVE_LOGS + value: "true" + - name: DISABLE_GKE_METADATA + value: "true" + +# Viewer CRD Controller configuration +viewerCrd: + enabled: true + replicas: 1 + + image: + repository: kfp-viewer-crd-controller + tag: "" + pullPolicy: "Always" + + resources: + requests: + cpu: 100m + memory: 100Mi + + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 0 + capabilities: + drop: + - ALL + + serviceAccount: + create: true + name: "ml-pipeline-viewer-crd-service-account" + + env: + maxNumViewers: "50" + + additionalEnv: [] + +# Visualization Server configuration +visualization: + enabled: true + replicas: 1 + + image: + repository: kfp-visualization-server + tag: "" + + resources: + requests: + cpu: 30m + memory: 500Mi + + # Probes configuration + probes: + liveness: + initialDelaySeconds: 3 + periodSeconds: 5 + timeoutSeconds: 2 + readiness: + initialDelaySeconds: 3 + periodSeconds: 5 + timeoutSeconds: 2 + + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 0 + capabilities: + drop: + - ALL + + serviceAccount: + create: true + name: "ml-pipeline-visualizationserver" + + service: + type: ClusterIP + port: 8888 + + additionalEnv: [] + +# Cache System Configuration (with cert-manager integration) +cache: + enabled: true + + serviceAccount: + create: true + name: "kubeflow-pipelines-cache" + + server: + replicas: 1 + + image: + repository: kfp-cache-server + tag: "" + + resources: + requests: + cpu: 120m + memory: 500Mi + + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 0 + capabilities: + drop: + - ALL + + service: + type: ClusterIP + port: 443 + + additionalEnv: + - name: NAMESPACE_TO_WATCH + value: "" + - name: DEFAULT_CACHE_STALENESS + key: DEFAULT_CACHE_STALENESS + - name: MAXIMUM_CACHE_STALENESS + key: MAXIMUM_CACHE_STALENESS + - name: CACHE_IMAGE + key: cacheImage + - name: CACHE_NODE_RESTRICTIONS + key: cacheNodeRestrictions + - name: DBCONFIG_DRIVER + value: mysql + - name: DBCONFIG_DB_NAME + key: cacheDb + - name: DBCONFIG_HOST_NAME + key: dbHost + - name: DBCONFIG_PORT + key: dbPort + - name: DBCONFIG_USER + valueFrom: + secretKeyRef: + name: mysql-secret + key: username + - name: DBCONFIG_PASSWORD + valueFrom: + secretKeyRef: + name: mysql-secret + key: password + +# ML Metadata Configuration +metadata: + enabled: true + + grpc: + replicas: 1 + + image: + repository: gcr.io/tfx-oss-public/ml_metadata_store_server + tag: "1.14.0" + pullPolicy: "IfNotPresent" + + resources: + requests: + cpu: 100m + memory: 300Mi + + securityContext: + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 0 + capabilities: + drop: + - ALL + + serviceAccount: + create: true + name: "metadata-grpc-server" + + service: + type: ClusterIP + port: 8080 + + additionalEnv: [] + + envoy: + replicas: 1 + + image: + repository: kfp-metadata-envoy + tag: "" + + resources: + requests: + cpu: 20m + memory: 20Mi + + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + runAsGroup: 0 + runAsNonRoot: true + runAsUser: 1000 + seccompProfile: + type: RuntimeDefault + + service: + type: ClusterIP + port: 9090 + + additionalEnv: [] + +# Metadata Writer Configuration +metadataWriter: + enabled: true + replicas: 1 + + image: + repository: kfp-metadata-writer + tag: "" + + resources: + requests: + cpu: 100m + memory: 200Mi + + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + runAsGroup: 0 + runAsNonRoot: true + runAsUser: 1000 + + serviceAccount: + create: true + name: "kubeflow-pipelines-metadata-writer" + + additionalEnv: [] + +# Third-party Dependencies +thirdParty: + # Argo Workflows + argo: + enabled: true + + # MySQL database + mysql: + enabled: true + image: "mysql" + imageTag: "8.4" + resources: + requests: + cpu: 100m + memory: 800Mi + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + runAsUser: 999 + runAsGroup: 999 + capabilities: + drop: + - ALL + podSecurityContext: + fsGroup: 999 + fsGroupChangePolicy: OnRootMismatch + seccompProfile: + type: RuntimeDefault + persistence: + size: 20Gi + + # Metacontroller (required for multi-user mode) + metacontroller: + enabled: true + +# MySQL Configuration +mysql: + enabled: true + auth: + # -- MySQL root password (leave empty to auto-generate) + rootPassword: "" + # -- MySQL database name + database: "mlpipeline" + # -- MySQL username + username: "root" + primary: + persistence: + enabled: true + size: 20Gi + +# SeaweedFS Configuration +seaweedfs: + enabled: true + # SeaweedFS image tag + imageTag: "4.00" + # Credentials for S3 access + credentials: + accesskey: "minio" + secretkey: "minio123" + # Storage configuration + persistence: + enabled: true + size: 20Gi + # -- SeaweedFS bucket name + bucket: "mlpipeline" + # -- S3 endpoint URL for profile controller + s3EndpointUrl: "http://seaweedfs.kubeflow:8333" + # -- AWS endpoint URL for profile controller + awsEndpointUrl: "http://seaweedfs.kubeflow:8111" + # -- AWS region + awsRegion: "us-east-1" + +# External MySQL database configuration (when using external database) +externalDatabase: + enabled: false + host: "" + port: 3306 + database: "mlpipeline" + username: "root" + password: "" + # -- Existing secret containing database credentials + existingSecret: "" + existingSecretPasswordKey: "password" + +# Database configuration +database: + # -- Connection max lifetime (important for external databases) + connectionMaxLifetime: "120s" + # -- Metadata database name + metadb: "metadb" + # -- Cache database name + cachedb: "cachedb" + +# Pipeline configuration +pipeline: + app: + name: "pipeline" + version: "2.15.0" + # -- Default pipeline root + defaultPipelineRoot: "" + # -- Auto-update pipeline default version + autoUpdatePipelineDefaultVersion: true + # -- Cron schedule timezone + cronScheduleTimezone: "UTC" + cache: + # -- Cache image + image: "ghcr.io/containerd/busybox" + # -- Cache node restrictions + nodeRestrictions: false + # -- Maximum cache staleness + maximumStaleness: "" + # -- Default cache staleness + defaultStaleness: "" + +# Profile Controller Configuration (Multi-User) +profileController: + enabled: true + replicas: 1 + + image: + repository: docker.io/alpine/k8s + tag: "1.32.3" + pullPolicy: IfNotPresent + + service: + type: ClusterIP + port: 80 + + # -- Disable Istio sidecar injection + disableIstioSidecar: "false" + + # -- Enable artifacts proxy in user namespaces + artifactsProxyEnabled: "false" + + # -- Artifact retention days (-1 to disable) + artifactRetentionDays: "-1" + + # -- Default pipeline root for KFP v2 + defaultPipelineRoot: "" + + additionalEnv: [] + +# Additional Service Accounts +additionalServiceAccounts: + containerBuilder: + create: true + name: "kubeflow-pipelines-container-builder" + + pipelineRunner: + create: true + name: "pipeline-runner" + + viewer: + create: true + name: "kubeflow-pipelines-viewer" + +# RBAC Configuration +rbac: + create: true + +# Networking Configuration +networking: + istio: + enabled: true + gateway: "kubeflow-gateway" + host: "*" + + virtualService: + enabled: true + prefix: "/pipeline" + + networkPolicy: + enabled: true + +# Certificate Management +certManager: + # -- Enable cert-manager integration + enabled: true + + mutating: + enabled: true + name: "cache-webhook-kubeflow" + + validating: + enabled: true + name: "cache-webhook-kubeflow" + +# Webhook Configuration (for k8s-native mode) +webhooks: + # -- Enable admission webhooks + enabled: false + # -- Webhook failure policy + failurePolicy: "Fail" + +# Pod annotations (applied to all pods) +podAnnotations: + cluster-autoscaler.kubernetes.io/safe-to-evict: "true" diff --git a/tests/helm_kustomize_compare.py b/tests/helm_kustomize_compare.py index 11fbabbbe5..b4fcead60f 100755 --- a/tests/helm_kustomize_compare.py +++ b/tests/helm_kustomize_compare.py @@ -46,6 +46,16 @@ def clean_helm_metadata(obj: Any, component: str = "katib") -> Any: # More restrictive filtering for KServe if not label_key.startswith(('helm.sh/', 'app.kubernetes.io/managed-by')): cleaned_labels[label_key] = label_value + elif component in ["pipeline", "pipelines"]: + helm_specific_labels = [ + 'app.kubernetes.io/managed-by', + 'app.kubernetes.io/version', + 'app.kubernetes.io/name', + 'app.kubernetes.io/instance', + 'app.kubernetes.io/component' + ] + if not label_key.startswith('helm.sh/') and label_key not in helm_specific_labels: + cleaned_labels[label_key] = label_value else: # Standard filtering for Katib and Model Registry helm_labels = [ @@ -64,6 +74,9 @@ def clean_helm_metadata(obj: Any, component: str = "katib") -> Any: cleaned_annotations = {} for ann_key, ann_value in meta_value.items(): if not ann_key.startswith(('helm.sh/', 'meta.helm.sh/')): + # For pipelines, ignore GCP icon annotation + if component in ["pipeline", "pipelines"] and ann_key == 'kubernetes-engine.cloud.google.com/icon': + continue cleaned_annotations[ann_key] = ann_value if cleaned_annotations: # Only add if there are remaining annotations cleaned_metadata[meta_key] = cleaned_annotations @@ -125,6 +138,8 @@ def normalize_manifest(manifest: Dict, component: str = "katib") -> Dict: # Remove leading --- if present (common in ConfigMap YAML data) if normalized_value.startswith('---'): normalized_value = normalized_value[3:].strip() + lines = normalized_value.split('\n') + normalized_value = '\n'.join(line.rstrip() for line in lines) normalized_data[key] = normalized_value else: normalized_data[key] = value @@ -144,9 +159,38 @@ def normalize_manifest(manifest: Dict, component: str = "katib") -> Dict: metadata.pop('uid', None) metadata.pop('creationTimestamp', None) metadata.pop('managedFields', None) + + # For pipelines component, remove labels from Argo CRDs + if component in ["pipeline", "pipelines"] and normalized.get('kind') == 'CustomResourceDefinition': + crd_name = normalized.get('metadata', {}).get('name', '') + if 'argoproj.io' in crd_name: + metadata.pop('labels', None) normalized.pop('status', None) + # For pipelines Argo CRDs, normalize schema differences between versions + if component in ["pipeline", "pipelines"] and normalized.get('kind') == 'CustomResourceDefinition': + crd_name = normalized.get('metadata', {}).get('name', '') + if 'argoproj.io' in crd_name and 'spec' in normalized: + def normalize_crd_schema(obj, path=""): + if isinstance(obj, dict): + cleaned = {} + for k, v in obj.items(): + if k.startswith('x-kubernetes-'): + continue + if k == 'default' and 'properties' in path: + continue + if k == 'required' and 'openAPIV3Schema.properties' in path: + continue + cleaned[k] = normalize_crd_schema(v, f"{path}.{k}" if path else k) + return cleaned + elif isinstance(obj, list): + return [normalize_crd_schema(item, path) for item in obj] + else: + return obj + + normalized['spec'] = normalize_crd_schema(normalized['spec']) + def remove_empty_values(obj): if isinstance(obj, dict): return {k: remove_empty_values(v) for k, v in obj.items() @@ -173,7 +217,7 @@ def get_resource_key(manifest: Dict, component: str = "katib") -> str: else: return f"{kind}/{name}" -def deep_diff(obj1: Any, obj2: Any, path: str = "") -> List[str]: +def deep_diff(obj1: Any, obj2: Any, path: str = "", resource_key: str = "") -> List[str]: """Compare two objects and return list of differences.""" differences = [] @@ -188,16 +232,21 @@ def deep_diff(obj1: Any, obj2: Any, path: str = "") -> List[str]: if key not in obj1: differences.append(f"{key_path}: missing in kustomize") elif key not in obj2: + if 'CustomResourceDefinition' in resource_key and 'argoproj.io' in resource_key: + if 'openAPIV3Schema.properties' in path and key == 'properties': + continue + elif '.properties.' in path: + continue differences.append(f"{key_path}: missing in helm") else: - differences.extend(deep_diff(obj1[key], obj2[key], key_path)) + differences.extend(deep_diff(obj1[key], obj2[key], key_path, resource_key)) elif isinstance(obj1, list): if len(obj1) != len(obj2): differences.append(f"{path}: list length mismatch ({len(obj1)} vs {len(obj2)})") else: for i, (item1, item2) in enumerate(zip(obj1, obj2)): - differences.extend(deep_diff(item1, item2, f"{path}[{i}]")) + differences.extend(deep_diff(item1, item2, f"{path}[{i}]", resource_key)) elif obj1 != obj2: differences.append(f"{path}: '{obj1}' != '{obj2}'") @@ -216,10 +265,72 @@ def get_expected_helm_extras(component: str, scenario: str) -> set: if scenario == "base": return {"AuthorizationPolicy/kserve-models-web-app"} return set() + elif component == "pipelines": + extras = { + # Built-in third-party Argo resources (from thirdParty.argo templates) + 'ConfigMap/workflow-controller-configmap', + 'Deployment/workflow-controller', + 'PriorityClass/workflow-controller', + 'Role/argo-role', + 'RoleBinding/argo-binding', + 'ServiceAccount/argo', + } + + # These get extra resources from the subchart dependency + argo_subchart_scenarios = [ + 'dev', + 'platform-agnostic-multi-user-emissary', + 'platform-agnostic-multi-user', + 'platform-agnostic-multi-user-legacy', + ] + + if any(sc in scenario for sc in argo_subchart_scenarios): + # Argo Workflows subchart creates these extra resources + extras.update({ + # Argo Workflows subchart RBAC resources + 'ClusterRole/pipeline-argo-workflows-admin', + 'ClusterRole/pipeline-argo-workflows-edit', + 'ClusterRole/pipeline-argo-workflows-view', + 'ClusterRole/pipeline-argo-workflows-server', + 'ClusterRole/pipeline-argo-workflows-server-cluster-template', + 'ClusterRole/pipeline-argo-workflows-workflow-controller', + 'ClusterRole/pipeline-argo-workflows-workflow-controller-cluster-template', + 'ClusterRoleBinding/pipeline-argo-workflows-server', + 'ClusterRoleBinding/pipeline-argo-workflows-server-cluster-template', + 'ClusterRoleBinding/pipeline-argo-workflows-workflow-controller', + 'ClusterRoleBinding/pipeline-argo-workflows-workflow-controller-cluster-template', + 'Role/pipeline-argo-workflows-workflow', + 'RoleBinding/pipeline-argo-workflows-workflow', + # Argo Workflows subchart deployments and services + 'Deployment/pipeline-argo-workflows-server', + 'Deployment/pipeline-argo-workflows-workflow-controller', + 'Service/pipeline-argo-workflows-server', + 'ServiceAccount/pipeline-argo-workflows-server', + 'ServiceAccount/pipeline-argo-workflows-workflow-controller', + 'ConfigMap/pipeline-argo-workflows-workflow-controller-configmap', + # Argo Workflows CRDs from subchart + 'CustomResourceDefinition/clusterworkflowtemplates.argoproj.io', + 'CustomResourceDefinition/cronworkflows.argoproj.io', + 'CustomResourceDefinition/workflowartifactgctasks.argoproj.io', + 'CustomResourceDefinition/workfloweventbindings.argoproj.io', + 'CustomResourceDefinition/workflows.argoproj.io', + 'CustomResourceDefinition/workflowtaskresults.argoproj.io', + 'CustomResourceDefinition/workflowtasksets.argoproj.io', + 'CustomResourceDefinition/workflowtemplates.argoproj.io', + }) + + if 'multi-user' in scenario: + extras.update({ + 'ConfigMap/kubeflow-pipelines-profile-controller-code', + 'ConfigMap/kubeflow-pipelines-profile-controller-env', + 'ConfigMap/pipeline-api-server-config', + }) + + return extras else: return set() -def compare_manifests(kustomize_file: str, helm_file: str, component: str, scenario: str, namespace: str = "") -> bool: +def compare_manifests(kustomize_file: str, helm_file: str, component: str, scenario: str, namespace: str = "", verbose: bool = False) -> bool: """Compare Kustomize and Helm manifests.""" kustomize_manifests = load_manifests(kustomize_file) helm_manifests = load_manifests(helm_file) @@ -252,11 +363,15 @@ def compare_manifests(kustomize_file: str, helm_file: str, component: str, scena if only_in_kustomize: print(f"Resources only in Kustomize: {len(only_in_kustomize)}") + for resource in sorted(only_in_kustomize): + print(f" - {resource}") success = False differences_found.extend(only_in_kustomize) if unexpected_helm_extras: print(f"Unexpected resources only in Helm: {len(unexpected_helm_extras)}") + for resource in sorted(unexpected_helm_extras): + print(f" - {resource}") success = False differences_found.extend(unexpected_helm_extras) @@ -265,10 +380,14 @@ def compare_manifests(kustomize_file: str, helm_file: str, component: str, scena kustomize_resource = kustomize_resources[key] helm_resource = helm_resources[key] - differences = deep_diff(kustomize_resource, helm_resource) + differences = deep_diff(kustomize_resource, helm_resource, resource_key=key) if differences: print(f"Differences in {key}: {len(differences)} fields") + print(f" Detailed differences for {key}:") + for diff in differences: + print(f" {diff}") + print() differences_found.append(key) success = False @@ -281,7 +400,7 @@ def compare_manifests(kustomize_file: str, helm_file: str, component: str, scena if __name__ == "__main__": if len(sys.argv) < 5: print("Usage: python compare.py [namespace] [--verbose]") - print("Components: katib, model-registry, kserve-models-web-app") + print("Components: katib, model-registry, kserve-models-web-app, pipeline") sys.exit(1) kustomize_file = sys.argv[1] @@ -289,11 +408,14 @@ def compare_manifests(kustomize_file: str, helm_file: str, component: str, scena component = sys.argv[3] scenario = sys.argv[4] namespace = sys.argv[5] if len(sys.argv) > 5 and not sys.argv[5].startswith('--') else "" - - if component not in ["katib", "model-registry", "kserve-models-web-app", "notebook-controller"]: + verbose = '--verbose' in sys.argv + + if component not in ["katib", "model-registry", "kserve-models-web-app", "notebook-controller", "pipelines"]: print(f"ERROR: Unknown component: {component}") - print("Supported components: katib, model-registry, kserve-models-web-app, notebook-controller") + print("Supported components: katib, model-registry, kserve-models-web-app, notebook-controller, pipelines") sys.exit(1) - - success = compare_manifests(kustomize_file, helm_file, component, scenario, namespace) + if component == "pipeline": + component = "pipelines" + + success = compare_manifests(kustomize_file, helm_file, component, scenario, namespace, verbose) sys.exit(0 if success else 1) \ No newline at end of file diff --git a/tests/helm_kustomize_compare.sh b/tests/helm_kustomize_compare.sh index 7cca489db6..d75509bdc1 100755 --- a/tests/helm_kustomize_compare.sh +++ b/tests/helm_kustomize_compare.sh @@ -11,7 +11,7 @@ ROOT_DIR="$(dirname "$SCRIPT_DIR")" if [[ -z "$COMPONENT" ]]; then echo "ERROR: Component is required" echo "Usage: $0 " - echo "Components: katib, model-registry, kserve-models-web-app, notebook-controller" + echo "Components: katib, model-registry, kserve-models-web-app, notebook-controller, pipelines" exit 1 fi @@ -132,6 +132,52 @@ case "$COMPONENT" in ) ;; + "notebook-controller") + CHART_DIR="$ROOT_DIR/experimental/helm/charts/notebook-controller" + MANIFESTS_DIR="$ROOT_DIR/applications/jupyter/notebook-controller/upstream" + + declare -A KUSTOMIZE_PATHS=( + ["base"]="$MANIFESTS_DIR/base" + ["kubeflow"]="$MANIFESTS_DIR/overlays/kubeflow" + ["standalone"]="$MANIFESTS_DIR/overlays/standalone" + ) + + declare -A HELM_VALUES=( + ["base"]="$CHART_DIR/ci/base-values.yaml" + ["kubeflow"]="$CHART_DIR/ci/kubeflow-values.yaml" + ["standalone"]="$CHART_DIR/ci/standalone-values.yaml" + ["webhook"]="$CHART_DIR/ci/webhook-values.yaml" + ["production"]="$CHART_DIR/ci/production-values.yaml" + ) + + declare -A NAMESPACES=( + ["base"]="notebook-controller-system" + ["kubeflow"]="kubeflow" + ["standalone"]="notebook-controller-system" + ["webhook"]="kubeflow" + ["production"]="kubeflow" + ) + ;; + "pipelines") + CHART_DIR="$ROOT_DIR/experimental/helm/charts/pipelines" + MANIFESTS_DIR="$ROOT_DIR/applications/pipeline/upstream" + + declare -A KUSTOMIZE_PATHS=( + ["platform-agnostic-multi-user"]="$MANIFESTS_DIR/env/cert-manager/platform-agnostic-multi-user" + ["platform-agnostic-multi-user-k8s-native"]="$MANIFESTS_DIR/env/cert-manager/platform-agnostic-multi-user-k8s-native" + ) + + declare -A HELM_VALUES=( + ["platform-agnostic-multi-user"]="$CHART_DIR/ci/values-platform-agnostic-multi-user.yaml" + ["platform-agnostic-multi-user-k8s-native"]="$CHART_DIR/ci/values-platform-agnostic-multi-user-k8s-native.yaml" + ) + + declare -A NAMESPACES=( + ["platform-agnostic-multi-user"]="kubeflow" + ["platform-agnostic-multi-user-k8s-native"]="kubeflow" + ) + ;; + "notebook-controller") CHART_DIR="$ROOT_DIR/experimental/helm/charts/notebook-controller" MANIFESTS_DIR="$ROOT_DIR/applications/jupyter/notebook-controller/upstream" @@ -161,7 +207,7 @@ case "$COMPONENT" in *) echo "ERROR: Unknown component: $COMPONENT" - echo "Supported components: katib, model-registry, kserve-models-web-app, notebook-controller" + echo "Supported components: katib, model-registry, kserve-models-web-app, notebook-controller, pipelines" exit 1 ;; esac @@ -223,6 +269,11 @@ else --namespace "$NAMESPACE" \ --include-crds \ --values "$HELM_VALUES_ARG" > "$HELM_OUTPUT" + elif [[ "$COMPONENT" == "pipelines" ]]; then + helm template pipeline . \ + --namespace "$NAMESPACE" \ + --include-crds \ + --values "$HELM_VALUES_ARG" > "$HELM_OUTPUT" else helm template model-registry . \ --namespace "$NAMESPACE" \ diff --git a/tests/helm_kustomize_compare_all.sh b/tests/helm_kustomize_compare_all.sh index 43e3da0b3b..4f0f0fd59a 100755 --- a/tests/helm_kustomize_compare_all.sh +++ b/tests/helm_kustomize_compare_all.sh @@ -13,6 +13,7 @@ declare -A COMPONENT_SCENARIOS=( ["model-registry"]="base overlay-postgres overlay-db controller-manager controller-rbac controller-default controller-prometheus controller-network-policy ui-base ui-standalone ui-integrated ui-istio istio csi" ["kserve-models-web-app"]="base kubeflow" ["notebook-controller"]="base kubeflow standalone" + ["pipelines"]="platform-agnostic-multi-user platform-agnostic-multi-user-k8s-native" ) test_component() { @@ -50,7 +51,7 @@ if [[ "$COMPONENT" == "all" ]]; then declare -a passed_components=() declare -a failed_components=() - for comp in katib model-registry kserve-models-web-app notebook-controller; do + for comp in katib model-registry kserve-models-web-app notebook-controller pipelines; do if test_component "$comp"; then passed_components+=("$comp") else @@ -79,6 +80,7 @@ elif [[ "$COMPONENT" == "help" ]] || [[ "$COMPONENT" == "--help" ]] || [[ "$COMP echo " model-registry Test Model Registry scenarios" echo " kserve-models-web-app Test KServe Models Web App scenarios" echo " notebook-controller Test Notebook Controller scenarios" + echo " pipelines Test Kubeflow Pipelines scenarios" echo "" echo "Examples:" echo " $0 # Test all components" @@ -99,7 +101,7 @@ elif [[ "${COMPONENT_SCENARIOS[$COMPONENT]:-}" ]]; then else echo "ERROR: Unknown component: $COMPONENT" - echo "Supported components: katib, model-registry, kserve-models-web-app, notebook-controller, all" + echo "Supported components: katib, model-registry, kserve-models-web-app, notebook-controller,pipelines, all" echo "Use '$0 help' for more information." exit 1 fi \ No newline at end of file