From 928c95d6ed62cc1f9531a8e47d18ad5b84d932fe Mon Sep 17 00:00:00 2001 From: Kimonas Sotirchos Date: Fri, 25 Jan 2019 20:04:27 +0200 Subject: [PATCH] Add jupyter-web-app component in jupyter pkg Add the jsonnet files in /kubeflow/jupyter. Currently the webapp is used alongside JupyterHub. The webapp is under the prefix /jupyter. The image param of the jupyter-web-app must be configured before deploying. Signed-off-by: Kimonas Sotirchos --- components/jupyter-web-app/Dockerfile | 9 +- kubeflow/jupyter/config.yaml | 116 +++++++++++ kubeflow/jupyter/jupyter-web-app.libsonnet | 181 ++++++++++++++++++ .../prototypes/jupyter-web-app.jsonnet | 14 ++ 4 files changed, 315 insertions(+), 5 deletions(-) create mode 100644 kubeflow/jupyter/config.yaml create mode 100644 kubeflow/jupyter/jupyter-web-app.libsonnet create mode 100644 kubeflow/jupyter/prototypes/jupyter-web-app.jsonnet diff --git a/components/jupyter-web-app/Dockerfile b/components/jupyter-web-app/Dockerfile index bd655921bb1..fd2a26d71e9 100644 --- a/components/jupyter-web-app/Dockerfile +++ b/components/jupyter-web-app/Dockerfile @@ -8,13 +8,12 @@ RUN apt-get update -y && \ # We copy just the requirements.txt first to leverage Docker cache COPY ./requirements.txt /app/requirements.txt -WORKDIR /app +RUN pip3 install -r /app/requirements.txt -RUN pip3 install -r requirements.txt +COPY default /app/default +COPY rok /app/rok -COPY run.py /app -COPY kubeflow /app/kubeflow +WORKDIR /app/default ENTRYPOINT ["python3"] - CMD ["run.py"] diff --git a/kubeflow/jupyter/config.yaml b/kubeflow/jupyter/config.yaml new file mode 100644 index 00000000000..849220c2063 --- /dev/null +++ b/kubeflow/jupyter/config.yaml @@ -0,0 +1,116 @@ +# Configuration file for the default JupyterHub Spawner UI +# Each key corresponds to a JupyterHub Spawner UI option +# If a key is missing, the respective Spawner UI option will be left untouched +# +# Each Spawner UI option is configured by two keys: `value` and `readOnly` +# - The `value` key contains the default value +# - The `readOnly` key determines if the option will be available to users +# +# If the 'readOnly' key is present and set to 'true', the respective option +# will be disabled for users and only set by the admin +# If the 'readOnly' key is missing (defaults to 'false'), the respective option +# will be available for users +# +# Please note that some values (e.g. {username}) may be templated +# and expanded according to KubeSpawner's rules +# +# For more information regarding JupyterHub KubeSpawner and its configuration: +# https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html + +spawnerFormDefaults: + image: + # The container Image for the user's Jupyter Notebook + # If readonly, this value must be a member of the list below + value: gcr.io/kubeflow-images-public/tensorflow-1.10.1-notebook-cpu:v0.4.0 + # The list of available standard container Images + options: + - gcr.io/kubeflow-images-public/tensorflow-1.4.1-notebook-cpu:v0.4.0 + - gcr.io/kubeflow-images-public/tensorflow-1.4.1-notebook-gpu:v0.4.0 + - gcr.io/kubeflow-images-public/tensorflow-1.5.1-notebook-cpu:v0.4.0 + - gcr.io/kubeflow-images-public/tensorflow-1.5.1-notebook-gpu:v0.4.0 + - gcr.io/kubeflow-images-public/tensorflow-1.6.0-notebook-cpu:v0.4.0 + - gcr.io/kubeflow-images-public/tensorflow-1.6.0-notebook-gpu:v0.4.0 + - gcr.io/kubeflow-images-public/tensorflow-1.7.0-notebook-cpu:v0.4.0 + - gcr.io/kubeflow-images-public/tensorflow-1.7.0-notebook-gpu:v0.4.0 + - gcr.io/kubeflow-images-public/tensorflow-1.8.0-notebook-cpu:v0.4.0 + - gcr.io/kubeflow-images-public/tensorflow-1.8.0-notebook-gpu:v0.4.0 + - gcr.io/kubeflow-images-public/tensorflow-1.9.0-notebook-cpu:v0.4.0 + - gcr.io/kubeflow-images-public/tensorflow-1.9.0-notebook-gpu:v0.4.0 + - gcr.io/kubeflow-images-public/tensorflow-1.10.1-notebook-cpu:v0.4.0 + - gcr.io/kubeflow-images-public/tensorflow-1.10.1-notebook-gpu:v0.4.0 + - gcr.io/kubeflow-images-public/tensorflow-1.11.0-notebook-cpu:v0.4.0 + - gcr.io/kubeflow-images-public/tensorflow-1.11.0-notebook-gpu:v0.4.0 + - gcr.io/kubeflow-images-public/tensorflow-1.12.0-notebook-cpu:v0.4.0 + - gcr.io/kubeflow-images-public/tensorflow-1.12.0-notebook-gpu:v0.4.0 + # By default, custom container Images are allowed + # Uncomment the following line to only enable standard container Images + readOnly: false + cpu: + # CPU for user's Notebook + value: '0.5' + # readOnly: true + memory: + # Memory for user's Notebook + value: 1.0Gi + workspaceVolume: + # Workspace Volume to be attached to user's Notebook + # Each Workspace Volume is declared with the following attributes: + # Type, Name, Size, MountPath and Access Mode + value: + type: + # The Type of the Workspace Volume + # Supported values: 'New', 'Existing' + value: New + name: + # The Name of the Workspace Volume + # Note that this is a templated value + # value: {username}-workspace + value: {username}-workspace + size: + # The Size of the Workspace Volume (in Gi) + value: '10' + mountPath: + # The Path that the Workspace Volume will be mounted + readOnly: true + value: /home/jovyan + accessModes: + # The Access Mode of the Workspace Volume + # Supported values: 'ReadWriteOnce', 'ReadWriteMany', 'ReadOnlyMany' + value: ReadWriteOnce + dataVolumes: + # List of additional Data Volumes to be attached to the user's Notebook + value: [] + # Each Data Volume is declared with the following attributes: + # Type, Name, Size, MountPath and Access Mode + # + # For example, a list with 2 Data Volumes: + #value: + # - value: + # type: + # value: New + # name: + # value: {username}-vol-1 + # size: + # value: '10' + # mountPath: + # value: /home/jovyan/{username}-vol-1 + # accessModes: + # value: ReadWriteOnce + # - value: + # type: + # value: New + # name: + # value: {username}-vol-2 + # size: + # value: '5' + # mountPath: + # value: /home/jovyan/{username}-vol-2 + # accessModes: + # value: ReadWriteOnce + # + # Uncomment the following line to make the Data Volumes list readonly + #readOnly: true + extraResources: + # Extra Resource Limits for user's Notebook + # Note that braces are escaped + value: "{{}}" diff --git a/kubeflow/jupyter/jupyter-web-app.libsonnet b/kubeflow/jupyter/jupyter-web-app.libsonnet new file mode 100644 index 00000000000..bcfffea8ef2 --- /dev/null +++ b/kubeflow/jupyter/jupyter-web-app.libsonnet @@ -0,0 +1,181 @@ +{ + local k = import "k.libsonnet", + local util = import "kubeflow/common/util.libsonnet", + + new(_env, _params):: { + local params = _env + _params, + + local defaultSpawnerData = { + // Default JH Spawner UI files + "spawner_ui_config.yaml": importstr "./config.yaml", + }, + + local jupyterConfig = { + apiVersion: "v1", + kind: "ConfigMap", + metadata: { + name: params.name + "-config", + namespace: params.namespace, + }, + data: defaultSpawnerData, + }, + jupyterConfig:: jupyterConfig, + + serviceAccount:: { + apiVersion: "v1", + kind: "ServiceAccount", + metadata: { + labels: { + app: params.name, + }, + name: params.name, + namespace: params.namespace, + }, + }, + + clusterRole:: { + apiVersion: "rbac.authorization.k8s.io/v1", + kind: "ClusterRole", + metadata: { + name: params.name + "-cluster-role", + }, + rules: [ + { + apiGroups: [""], + resources: ["namespaces"], + verbs: ["get", "list", "create", "delete"] + }, + { + apiGroups: ["kubeflow.org"], + resources: ["notebooks"], + verbs: ["get", "list", "create", "delete"], + }, + { + apiGroups: [""], + resources: ["persistentvolumeclaims"], + verbs: ["create", "delete", "get", "list"], + }, + ] + }, + + clusterRoleBinding:: { + kind: "ClusterRoleBinding", + apiVersion: "rbac.authorization.k8s.io/v1", + metadata: { + name: params.name + "-binding" + }, + subjects: [ + { + kind: "ServiceAccount", + name: params.name, + namespace: params.namespace + }, + ], + roleRef: { + kind: "ClusterRole", + name: params.name + "-cluster-role", + apiGroup: "rbac.authorization.k8s.io", + }, + }, + + svc:: { + apiVersion: "v1", + kind: "Service", + metadata: { + name: params.name, + labels: { + run: params.name + }, + annotations:{ + "getambassador.io/config": + std.join("\n", [ + "---", + "apiVersion: ambassador/v0", + "kind: Mapping", + "name: webapp_mapping", + "prefix: /" + params.prefix + "/", + "service: " + params.name + "." + params.namespace, + "add_request_headers: ", + " x-forwarded-prefix: /" + params.prefix + ]), + }, + }, + spec: { + type: "ClusterIP", + ports: [{ + port: 80, + targetPort: 5000, + protocol: "TCP", + name: "http", + }], + selector: { + app: params.name + }, + }, + }, + + depl :: { + apiVersion: "apps/v1", + kind: "Deployment", + metadata: { + name: params.name, + labels: { + app: params.name, + }, + }, + spec: { + replicas: 1, + selector: { + matchLabels: { + app: params.name, + }, + }, + template: { + metadata:{ + labels: { + app: params.name, + }, + }, + spec: { + serviceAccountName: params.name, + containers: [{ + name: params.name, + image: params.image, + workingDir: "/app/" + params.ui, + volumeMounts: [ + { + mountPath: "/etc/config", + name: "config-volume", + }, + ], + ports: [{ + containerPort: 5000, + }], + imagePullPolicy: params.policy, + }], + volumes: [ + { + configMap: { + name: params.name + "-config", + }, + name: "config-volume", + }, + ], + }, + }, + }, + }, + + parts:: self, + all:: [ + self.svc, + self.depl, + self.jupyterConfig, + self.serviceAccount, + self.clusterRoleBinding, + self.clusterRole, + ], + + list(obj=self.all):: util.list(obj), + }, +} \ No newline at end of file diff --git a/kubeflow/jupyter/prototypes/jupyter-web-app.jsonnet b/kubeflow/jupyter/prototypes/jupyter-web-app.jsonnet new file mode 100644 index 00000000000..d7740d2c301 --- /dev/null +++ b/kubeflow/jupyter/prototypes/jupyter-web-app.jsonnet @@ -0,0 +1,14 @@ +// @apiVersion 0.1 +// @name io.ksonnet.pkg.jupyter-web-app +// @shortDescription A WebApp that controlls Jupyter Notebooks +// @param name string Name to give to the Jupyter UI +// @optionalParam image string jupyter-web-app/image Docker Image used for the Jupyter UI +// @optionalParam ui string default Choose the UI to use. Supported: default | rok +// @optionalParam port string 80 Port to expose the UI's Service +// @optionalParam policy string IfNotPresent imagePullPolicy for the UI's image +// @optionalParam prefix string jupyter The prefix under which the app is accessed + +local jupyter_ui = import "kubeflow/jupyter/jupyter-web-app.libsonnet"; + +local instance = jupyter_ui.new(env, params); +instance.list(instance.all)