kubeflow / dashboard

Kubeflow Central Dashboard is the web interface for Kubeflow
Apache License 2.0
3 stars 2 forks source link

Differences between standalone and kubeflow modes of our web apps #41

Open kimwnasptd opened 3 years ago

kimwnasptd commented 3 years ago

There are many cases where users would like to install specific components of Kubeflow and not the entire solution. To accommodate this need we will have to engineer our web apps to be deploy-able as standalone components as well.

This issue aims to provide a cohesive story around how we want our web apps to behave when they are installed as part of Kubeflow or as standalone components. It's an effort to document the technical details as well as the design decisions to achieve this.

Once we have a solid understanding and ironed out most of the important details then we can convert the knowledge and discussions from this issue into a design doc.

Kubeflow mode

When we say that an app is deployed alongside Kubeflow this means the following things:

  1. There is always a logged in user.
    • This is enforced in a central place which can be IAP, Dex etc. The user first logins to this central entity and then navigates to Kubeflow. This entity places the username in a configurable header in each request that passes from it
    • The backend of each app will be checking that header to deduce the identity of the user and will creating SubjectAccessReviews to ensure the user is authorized to perform an action https://github.com/kubeflow/community/pull/334
  2. There is a CentralDashboard which
    • decides what Namespaces to show to the user and feeds to the app the selected Namespace
    • has a left hand sidebar, which can have subsections https://github.com/kubeflow/kubeflow/pull/5474. This side bar can be used for navigating the user between different pages of the underlying deployed app

Standalone mode

This means that only this app is exposed and no other Kubeflow component. This introduces the following consequences that the web apps need to handle:

  1. There is no CentralDashboard
    • the app must handle it's navigation to different pages on each own
    • it must handle Namespace selection on its own
  2. There is no guarantee that there will be an authentication system, a logged in user. This leads into two scenarios:
    • if there is such a system then it must be setting the user identity in a specific header. This header is configurable for our web apps. If a custom one is used the admin can let the app know which header to look for. In this case the app relies on SubjectAccessReviews to ensure the user is authorized.
    • if there is no such a system then we expect that every user is admin and can do anything they want in any namespace. In this case the backend must be configurable to not perform any authnz checks
kimwnasptd commented 3 years ago

cc @kubeflow/wg-notebooks-leads

And also since this affects the web app for katib https://github.com/kubeflow/katib/issues/1421 https://github.com/kubeflow/katib/issues/1090 I'll also cc @kubeflow/wg-automl-leads

nrchakradhar commented 3 years ago
  • if there is no such a system then we expect that every user is admin and can do anything they want in any namespace. In this case the backend must be configurable to not perform any authnz checks

If the service account used by the web-app deployment has RBAC set in a way that it can only access the same namespace, then the app cannot do anything in any namespace. It will be restricted by the RBAC settings of the service account. Is my understanding correct?

nrchakradhar commented 3 years ago
  1. There is no CentralDashboard

Why cant CentralDashboard also be namespace scoped and just allow navigation to other installed apps? I want to understand the limitations

nrchakradhar commented 3 years ago

I think for the standalone mode, all apps should have configurable path. They should support base_path prefix.

kimwnasptd commented 3 years ago

@nrchakradhar thank you for bringing these up!

If the service account used by the web-app deployment has RBAC set in a way that it can only access the same namespace, then the app cannot do anything in any namespace. It will be restricted by the RBAC settings of the service account. Is my understanding correct?

Yes, it's accurate. So in the standalone case, with no authn, the only limiting factor is the permissions of the web app. This will be configured from the manifests of each app, which gives us a lot of flexibility.

One edge case here is that in standalone mode the web apps themselves will have to decide on what Namespaces to show to the users, in the dropdown. One simple solution would be to just show them every namespace and if they tried to access a namespace where the web app has no permissions to list CRs then they would get 403 errors.

Another idea would be to copy and adjust the current mechanism the CentralDashboard uses, to figure out these namespaces, to the web apps. cc @yanniszark

Why cant CentralDashboard also be namespace scoped and just allow navigation to other installed apps? I want to understand the limitations

This isn't a discussion about namespace scoping the dashboard and the different Kubeflow components.

In this issue I want to expose our understanding on how the underlying apps should be deployed if they are part of a Kubeflow installation, which includes the dashboard, or as completely standalone apps without expecting any other Kubeflow component.

The question of whether the Dashboard can be namespace scoped leads to a different discussion from what this issue tries to document. It leads to the discussion of how can the Dashboard and the underlying apps be namespaced scoped.

I think for the standalone mode, all apps should have configurable path. They should support base_path prefix.

Indeed, and this is already the case for most of the underlying web apps like the crud ones and Katib.

nrchakradhar commented 3 years ago

@kimwnasptd Thanks for the sharing detailed views in my questions.

jbottum commented 3 years ago

/priority p1 /area Jupyter

kimwnasptd commented 3 years ago

Detecting the mode

The next part we need to document is how the web apps can figure out in which mode they are being deployed in. This can be broken down into the following questions/design decisions:

Proposed solution

Reminder: once the dashboard_lib.bundle.js file is executed then it will create a window.centraldashboard object.

For our crud-web-apps, and any app that is built with Angular, the frontend:

  1. will always try to load the dashboard_lib.bundle.js using the defer attribute
  2. the frontend will dynamically deduce the mode by checking if the window.centraldashboard object is present.

This will completely decouple the frontend from the backend and simplify our architecture.

The above proposed solution is also race-free, for frontends build with Angular, because:

  1. The dashboard_lib.bundle.js script is loaded with defer
  2. The app's scripts are placed after the dashboard_lib.bundle.js in the html tree
  3. The app's scripts are loaded using defer [ this is the case for Angular apps ]

If the above hold, which is the case for the crud-web-apps, then the browser will always run the dashboard_lib.bundle.js script before the scripts of the application, due to the fact that all scripts have defer. Thus once the app loads we are sure that the dashboard either exists or not.

Note that for UIs where 2 and 3 do not hold the frontend can still try to detect the dashboard after the DOMContentLoaded is fired, if the dashboard_lib.bundle.js is loaded with the defer attribute.

Demo

I've also prepared a short video to showcase this, where the server will wait for 5 seconds before raising an error [ when serving the `dashboard_lib.bundle.js` ] https://user-images.githubusercontent.com/11134742/107962182-5ae74d00-6faf-11eb-9a30-fd96fa274340.mp4

kimwnasptd commented 3 years ago

Ofc if the frontend would rely on the backend to get this information, via and HTTP GET for example in an endpoint that exposes common setting is also fine.

The above description aims to explain why in crud-web-apps we can take for granted that the dashboard will either be there or not when the app loads.

kimwnasptd commented 3 years ago

Sidebars for navigation

In 1.3 release the CentralDashboard's left-hand side panel will be a sticky component https://github.com/kubeflow/kubeflow/pull/5474, in order to make the whole platform feel more cohesive. But, in many cases an underlying UI might need to have a left side-bar of its own that will be used for navigating to the app's different pages.

We want to avoid the scenario where, in Kubeflow mode, there will be two visible side-bars, one for the dashboard and one for the app.

We can avoid the mentioned problem, by taking into consideration that in 1.3 the CentralDashboard's left sidebar will also support sections and subsections https://github.com/kubeflow/kubeflow/pull/5474, by:

  1. Extending the dashboard with subsections with the different entries/pages of an app's side panel
  2. If the CentralDashboard is present then the apps should not show their sidebar. We've discussed ways of doing this in the previous comment
  3. If the CentralDashboard is not present then the apps should show their sidebar
Example

Here's an example screenshot of the Katib UI. Following the above steps the Katib UI should not have an inner sidebar. The names in the dashboard for Katib are only meant as an example. ![Screenshot from 2021-02-19 13-42-11](https://user-images.githubusercontent.com/11134742/108502650-c7b65c00-72bb-11eb-8bef-38b4aae396ee.png)

kimwnasptd commented 3 years ago

Selected Namespace in Standalone

If the UI is deployed in standalone mode then the frontend will have a dropdown selection list with all the available namespaces. The next question we need to tackle is which Namespace should be selected once the user navigates to the app?

Use the first item in the list (first iteration)

The easiest solution we could have as a first iteration would be for the apps to simply select the first namespace. While this works it's not ideal, since the users will need to reselect their namespace if it's not the first

Remember the previously selected Namespace (second iteration)

As an improvement we could have the frontend always remember the last selected Namespace and show this once the app loads again. We could use localStorage to persist this information.

kimwnasptd commented 3 years ago

/reopen

google-oss-robot commented 3 years ago

@kimwnasptd: Reopened this issue.

In response to [this](https://github.com/kubeflow/dashboard/issues/41): >/reopen Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md). If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

kimwnasptd commented 3 years ago

/lifecycle frozen

andreyvelich commented 1 week ago

/transfer dashboard