Skip to content

Commit fc31f52

Browse files
committed
Enable pipeline again
Signed-off-by: Patrick Schönthaler <[email protected]>
1 parent b5f07cd commit fc31f52

14 files changed

+485
-20
lines changed

.github/workflows/pipeline_swfs_test.yaml

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
name: Test pipelines with seaweedfs
22
on:
33
workflow_dispatch:
4-
# pull_request:
5-
# paths:
6-
# - tests/gh-actions/install_KinD_create_KinD_cluster_install_kustomize.sh
7-
# - .github/workflows/pipeline_swfs_test.yaml
8-
# - apps/pipeline/upstream/**
9-
# - tests/gh-actions/install_istio.sh
10-
# - tests/gh-actions/install_cert_manager.sh
11-
# - tests/gh-actions/install_oauth2-proxy.sh
12-
# - common/cert-manager/**
13-
# - common/oauth2-proxy/**
14-
# - common/istio*/**
15-
# - experimental/seaweedfs/**
4+
pull_request:
5+
paths:
6+
#- tests/gh-actions/install_KinD_create_KinD_cluster_install_kustomize.sh
7+
- .github/workflows/pipeline_swfs_test.yaml
8+
- apps/pipeline/upstream/**
9+
#- tests/gh-actions/install_istio.sh
10+
#- tests/gh-actions/install_cert_manager.sh
11+
#- tests/gh-actions/install_oauth2-proxy.sh
12+
#- common/cert-manager/**
13+
#- common/oauth2-proxy/**
14+
#- common/istio*/**
15+
- experimental/seaweedfs/**
1616

1717
jobs:
1818
build:

experimental/seaweedfs/base/kustomization.yaml

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,27 @@ kind: Kustomization
33
namespace: kubeflow
44

55
resources:
6-
- seaweedfs-deployment.yaml
7-
- seaweedfs-pvc.yaml
8-
- seaweedfs-service.yaml
9-
- seadweedfs-networkpolicy.yaml
6+
- seaweedfs/
7+
- ../../../apps/pipeline/upstream/env/cert-manager/platform-agnostic-multi-user
8+
configMapGenerator:
9+
- name: kubeflow-pipelines-profile-controller-code
10+
behavior: replace
11+
files:
12+
- pipeline-profile-controller/sync.py
13+
patches:
14+
- path: minio-service-patch.yaml
15+
- path: pipeline-profile-controller/deployment.yaml
16+
- patch: |-
17+
apiVersion: apps/v1
18+
kind: Deployment
19+
metadata:
20+
name: ml-pipeline-ui
21+
spec:
22+
template:
23+
spec:
24+
containers:
25+
- name: ml-pipeline-ui
26+
env:
27+
- name: ARTIFACTS_SERVICE_PROXY_ENABLED
28+
value: 'false'
29+
$patch: merge
File renamed without changes.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: kubeflow-pipelines-profile-controller
5+
spec:
6+
template:
7+
spec:
8+
containers:
9+
- name: profile-controller
10+
securityContext:
11+
allowPrivilegeEscalation: false
12+
seccompProfile:
13+
type: RuntimeDefault
14+
runAsNonRoot: true
15+
runAsUser: 1000
16+
runAsGroup: 0
17+
capabilities:
18+
drop:
19+
- ALL
20+
# We just need an image with the python botocore library installed
21+
image: docker.io/alpine/k8s:1.32.3
22+
command: ["python", "/hooks/sync.py"]
23+
env:
24+
- name: KFP_VERSION
25+
valueFrom:
26+
configMapKeyRef:
27+
name: pipeline-install-config
28+
key: appVersion
29+
- name: AWS_ENDPOINT_URL
30+
value: http://seaweedfs:8111
31+
- name: AWS_REGION
32+
value: us-east-1
33+
- name: AWS_ACCESS_KEY_ID
34+
valueFrom:
35+
secretKeyRef:
36+
name: mlpipeline-minio-artifact
37+
key: accesskey
38+
- name: AWS_SECRET_ACCESS_KEY
39+
valueFrom:
40+
secretKeyRef:
41+
name: mlpipeline-minio-artifact
42+
key: secretkey
Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
# Copyright 2020-2021 The Kubeflow Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from http.server import BaseHTTPRequestHandler, HTTPServer
16+
import json
17+
import os
18+
import base64
19+
20+
# From awscli installed in alpine/k8s image
21+
import botocore.session
22+
23+
S3_BUCKET_NAME = 'mlpipeline'
24+
25+
session = botocore.session.get_session()
26+
# To interact with seaweedfs user management. Region does not matter.
27+
iam = session.create_client('iam', region_name='foobar')
28+
29+
30+
def main():
31+
settings = get_settings_from_env()
32+
server = server_factory(**settings)
33+
server.serve_forever()
34+
35+
36+
def get_settings_from_env(controller_port=None,
37+
visualization_server_image=None, frontend_image=None,
38+
visualization_server_tag=None, frontend_tag=None, disable_istio_sidecar=None):
39+
"""
40+
Returns a dict of settings from environment variables relevant to the controller
41+
42+
Environment settings can be overridden by passing them here as arguments.
43+
44+
Settings are pulled from the all-caps version of the setting name. The
45+
following defaults are used if those environment variables are not set
46+
to enable backwards compatibility with previous versions of this script:
47+
visualization_server_image: ghcr.io/kubeflow/kfp-visualization-server
48+
visualization_server_tag: value of KFP_VERSION environment variable
49+
frontend_image: ghcr.io/kubeflow/kfp-frontend
50+
frontend_tag: value of KFP_VERSION environment variable
51+
disable_istio_sidecar: Required (no default)
52+
minio_access_key: Required (no default)
53+
minio_secret_key: Required (no default)
54+
"""
55+
settings = dict()
56+
settings["controller_port"] = \
57+
controller_port or \
58+
os.environ.get("CONTROLLER_PORT", "8080")
59+
60+
settings["visualization_server_image"] = \
61+
visualization_server_image or \
62+
os.environ.get("VISUALIZATION_SERVER_IMAGE", "ghcr.io/kubeflow/kfp-visualization-server")
63+
64+
settings["frontend_image"] = \
65+
frontend_image or \
66+
os.environ.get("FRONTEND_IMAGE", "ghcr.io/kubeflow/kfp-frontend")
67+
68+
# Look for specific tags for each image first, falling back to
69+
# previously used KFP_VERSION environment variable for backwards
70+
# compatibility
71+
settings["visualization_server_tag"] = \
72+
visualization_server_tag or \
73+
os.environ.get("VISUALIZATION_SERVER_TAG") or \
74+
os.environ["KFP_VERSION"]
75+
76+
settings["frontend_tag"] = \
77+
frontend_tag or \
78+
os.environ.get("FRONTEND_TAG") or \
79+
os.environ["KFP_VERSION"]
80+
81+
settings["disable_istio_sidecar"] = \
82+
disable_istio_sidecar if disable_istio_sidecar is not None \
83+
else os.environ.get("DISABLE_ISTIO_SIDECAR") == "true"
84+
85+
return settings
86+
87+
88+
def server_factory(visualization_server_image,
89+
visualization_server_tag, frontend_image, frontend_tag,
90+
disable_istio_sidecar, url="", controller_port=8080):
91+
"""
92+
Returns an HTTPServer populated with Handler with customized settings
93+
"""
94+
class Controller(BaseHTTPRequestHandler):
95+
def sync(self, parent, attachments):
96+
# parent is a namespace
97+
namespace = parent.get("metadata", {}).get("name")
98+
99+
pipeline_enabled = parent.get("metadata", {}).get(
100+
"labels", {}).get("pipelines.kubeflow.org/enabled")
101+
102+
if pipeline_enabled != "true":
103+
return {"status": {}, "attachments": []}
104+
105+
# Compute status based on observed state.
106+
desired_status = {
107+
"kubeflow-pipelines-ready":
108+
len(attachments["Secret.v1"]) == 1 and
109+
len(attachments["ConfigMap.v1"]) == 3 and
110+
len(attachments["Deployment.apps/v1"]) == 2 and
111+
len(attachments["Service.v1"]) == 2 and
112+
len(attachments["DestinationRule.networking.istio.io/v1alpha3"]) == 1 and
113+
len(attachments["AuthorizationPolicy.security.istio.io/v1beta1"]) == 1 and
114+
"True" or "False"
115+
}
116+
117+
# Generate the desired attachment object(s).
118+
desired_resources = [
119+
{
120+
"apiVersion": "v1",
121+
"kind": "ConfigMap",
122+
"metadata": {
123+
"name": "kfp-launcher",
124+
"namespace": namespace,
125+
},
126+
"data": {
127+
"defaultPipelineRoot": f"minio://{S3_BUCKET_NAME}/private-artifacts/{namespace}/v2/artifacts",
128+
},
129+
},
130+
{
131+
"apiVersion": "v1",
132+
"kind": "ConfigMap",
133+
"metadata": {
134+
"name": "metadata-grpc-configmap",
135+
"namespace": namespace,
136+
},
137+
"data": {
138+
"METADATA_GRPC_SERVICE_HOST":
139+
"metadata-grpc-service.kubeflow",
140+
"METADATA_GRPC_SERVICE_PORT": "8080",
141+
},
142+
},
143+
{
144+
"apiVersion": "v1",
145+
"kind": "ConfigMap",
146+
"metadata": {
147+
"name": "artifact-repositories",
148+
"namespace": namespace,
149+
"annotations": {
150+
"workflows.argoproj.io/default-artifact-repository": "default-namespaced"
151+
}
152+
},
153+
"data": {
154+
"default-namespaced": json.dumps({
155+
"archiveLogs": True,
156+
"s3": {
157+
"endpoint": "minio-service.kubeflow:9000",
158+
"bucket": S3_BUCKET_NAME,
159+
"keyFormat": f"private-artifacts/{namespace}/{{{{workflow.name}}}}/{{{{workflow.creationTimestamp.Y}}}}/{{{{workflow.creationTimestamp.m}}}}/{{{{workflow.creationTimestamp.d}}}}/{{{{pod.name}}}}",
160+
"insecure": True,
161+
"accessKeySecret": {
162+
"name": "mlpipeline-minio-artifact",
163+
"key": "accesskey",
164+
},
165+
"secretKeySecret": {
166+
"name": "mlpipeline-minio-artifact",
167+
"key": "secretkey",
168+
}
169+
}
170+
})
171+
}
172+
},
173+
]
174+
print('Received request:\n', json.dumps(parent, sort_keys=True))
175+
print('Desired resources except secrets:\n', json.dumps(desired_resources, sort_keys=True))
176+
177+
# Moved after the print argument because this is sensitive data.
178+
179+
# Check if secret is already there when the controller made the request. If yes, then
180+
# use it. Else create a new credentials on seaweedfs for the namespace.
181+
if s3_secret := attachments["Secret.v1"].get(f"{namespace}/mlpipeline-minio-artifact"):
182+
desired_resources.append(s3_secret)
183+
print('Using existing secret')
184+
else:
185+
print('Creating new access key.')
186+
s3_access_key = iam.create_access_key(UserName=namespace)
187+
# Use the AWS IAM API of seaweedfs to manage access policies to bucket.
188+
# This policy ensures that a user can only access artifacts from his own profile.
189+
iam.put_user_policy(
190+
UserName=namespace,
191+
PolicyName=f"KubeflowProject{namespace}",
192+
PolicyDocument=json.dumps(
193+
{
194+
"Version": "2012-10-17",
195+
"Statement": [{
196+
"Effect": "Allow",
197+
"Action": [
198+
"s3:Put*",
199+
"s3:Get*",
200+
"s3:List*"
201+
],
202+
"Resource": [
203+
f"arn:aws:s3:::{S3_BUCKET_NAME}/artifacts/*",
204+
f"arn:aws:s3:::{S3_BUCKET_NAME}/private-artifacts/{namespace}/*",
205+
f"arn:aws:s3:::{S3_BUCKET_NAME}/private/{namespace}/*",
206+
f"arn:aws:s3:::{S3_BUCKET_NAME}/shared/*",
207+
]
208+
}]
209+
})
210+
)
211+
desired_resources.insert(
212+
0,
213+
{
214+
"apiVersion": "v1",
215+
"kind": "Secret",
216+
"metadata": {
217+
"name": "mlpipeline-minio-artifact",
218+
"namespace": namespace,
219+
},
220+
"data": {
221+
"accesskey": base64.b64encode(s3_access_key["AccessKey"]["AccessKeyId"].encode('utf-8')).decode("utf-8"),
222+
"secretkey": base64.b64encode(s3_access_key["AccessKey"]["SecretAccessKey"].encode('utf-8')).decode("utf-8"),
223+
},
224+
})
225+
226+
return {"status": desired_status, "attachments": desired_resources}
227+
228+
def do_POST(self):
229+
# Serve the sync() function as a JSON webhook.
230+
observed = json.loads(
231+
self.rfile.read(int(self.headers.get("content-length"))))
232+
desired = self.sync(observed["object"], observed["attachments"])
233+
234+
self.send_response(200)
235+
self.send_header("Content-type", "application/json")
236+
self.end_headers()
237+
self.wfile.write(bytes(json.dumps(desired), 'utf-8'))
238+
239+
return HTTPServer((url, int(controller_port)), Controller)
240+
241+
242+
if __name__ == "__main__":
243+
main()
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
apiVersion: kustomize.config.k8s.io/v1beta1
2+
kind: Kustomization
3+
namespace: kubeflow
4+
5+
resources:
6+
- seaweedfs-deployment.yaml
7+
- seaweedfs-pvc.yaml
8+
- seaweedfs-networkpolicy.yaml
9+
- seaweedfs-create-admin-user-job.yaml
10+
- seaweedfs-service.yaml
11+
- seaweedfs-service-account.yaml

0 commit comments

Comments
 (0)