Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[vtadmin] Unify vtadmin-web + vtadmin-api into a single vtadmin component, by default #10118

Open
doeg opened this issue Apr 20, 2022 · 1 comment
Assignees
Projects

Comments

@doeg
Copy link
Contributor

doeg commented Apr 20, 2022

Motivation

"VTAdmin" comprises two distinct components:

  • vtadmin-api, the HTTP/gRPC API server
  • vtadmin-web, the front-end codebase

Currently, Vitess operators must deploy these as separate components: separate kube pods, for example, with separate hostnames.

This has a few benefits:

  • ✅ The front-end and back-end have completely separate routing schemes: there is no chance of conflict between vtadmin-web's client-side routing and vtadmin-api's server-side routing.

  • ✅ One service going down doesn't affect the other. This is a bit of a reach though, since vtadmin-web wouldn't be very useful without vtadmin-api. :)

  • ✅ Flexibility. The big reason we initially architected vtadmin-web and vtadmin-api as separate components was very much to enable this kind of unification down the road if we wanted to (and it turns out we do). It's easier to combine services than to split them apart.

There are, however, some very significant drawbacks to vtadmin-web and vtadmin-api being separate Things:

  • ❌ At a high level, two separate Things means you have two Things to worry about instead of one Thing. Two deploy pipelines, two services, etc. etc. You could, for example, stuff them both into the same Docker container to alleviate some of this, but would not obviate the other ❌s in this list.

  • ❌ Separate hostnames necessitate Cross-Origin Resource Sharing (CORS), a terrible curse indeed. In order for https://vtadmin-web.example.com to issue requests to https://vtadmin-api.example.com (or even https://vtadmin.example.com:80 against https://vtadmin.example.com:1234, since hostname equivalency means protocol, host and port must all be the same per the Same Origin Policy), vtadmin-api's --http-origin flag must be set to the hostname(s) of vtadmin-web. In most cases, this isn't so bad, but when CORS doesn't work, it's miserable to debug.

  • ❌ When running as separate components, vtadmin-web needs to know vtadmin-api's hostname(s). And because vtadmin-web produces a static HTML/CSS/JS bundle, any configuration variables need to be embedded during build time; see the create-react-app docs for more on this. This means that anyone wanting to run vtadmin-web will need to do a vtadmin-web build to bake in the REACT_APP_VTADMIN_API_ADDRESS env variable specific to their environment. This is annoying for several reasons:

    • We can't distribute (commit to the repo, etc.) a vtadmin-web build
    • Building vtadmin-web requires node, unlike other Vitess components
    • npm install + npm build can be relatively slow (on the order of minutes)
  • ❌ Even though vtadmin-web is ultimately deployed as a relatively straightforward folder of static HTML/CSS/JS files, those files still need to be served somehow. While flexible and pretty straightforward, "how should I serve this" is still an additional step in deploying VTAdmin.

A Proposed Solution

A single "vtadmin" component that serves both the user interface (vtadmin-web) and HTTP/gRPC API (vtadmin-api) is much simpler and more approachable for, I think, the vast majority of Vitess operators.

At a high level, vtadmin-api will serve both its existing /api routes, and then (in the simplest implentation) all other routes will "fall through" to the client-side app, which defines its own client-side routing. This is described a little bit in the create-react-app Deployment docs.

With this, vtadmin-api and vtadmin-web will "both" be running on the same host name. ("Both" scare quotes since, at this point, they're no longer separate components per se, but the nomenclature is still handy.) This means... no CORS! 🎉

Even more exciting is that it means that REACT_APP_VTADMIN_API_ADDRESS is no longer required; if the (unified) vtadmin is running on https://vtadmin.example.com, a UI page like https://vtadmin.example.com/tablets can make its API requests to https://vtadmin.example.com/api/tablets. (We can also get a little fancy and use Proxying to make this transparent to the front-end.)

Doing away with REACT_APP_VTADMIN_API_ADDRESS means that we can distribute a static vtadmin-web build that will work for 95% of use cases (more on this below). And that removes the requirement for Vitess operators to do their own build, which in turn removes to requirement for Vitess operators to install node at all.

I say that this will work for 95% of use cases; the other 5% are Vitess operators that do want to set vtadmin-web env variables
. As mentioned above and in the create-react-app docs, changing env variables will require running npm install and npm build to generate the static files. Even a custom build like this, though, still works with a unified "vtadmin" component as long as you build the files into the place vtadmin is configured to look for them (or configure vtadmin to look elsewhere). (This may also require a vtadmin-api build if we use something like embed.)

For development, vtadmin-api and vtadmin-web will remain separate (as they are today). One big benefit of create-react-app is its dev server, which has hot reloading and other nice features; running vtadmin-web in dev mode doesn't produce a static build, though, so vtadmin-api won't have anything to host (nor would we want it to, since it would probably be way slower).

To summarize the above benefits of a unified vtadmin component, and note a couple more:

  • ✅ Only one service to deploy
  • ✅ We can distribute a static HTML/CSS/JS build that will work for most use cases
  • ✅ No need to install node or build the front-end (unless you require custom configuration)
  • ✅ No CORS
  • ✅ It will still be possible to deploy vtadmin-web and vtadmin-api separately for those that want to; we can add a flag to vtadmin-api to omit the front-end integrations for this use case. Indeed, they'll be separate in "dev mode".)
  • ✅ It's closer in spirit to how the vtctld2 web UI works, which will make migration more straightforward.
  • ✅ We can remove the serve package from vtadmin-web, added in [vtadmin] Improve vtadmin-{up,down}.sh scripts for the local example #10081 for the "Get Started" example.

There are also a couple of drawbacks worth mentioning:

  • ❌ The routes for vtadmin-api and vtadmin-web can now conflict with each other (since same hostname), which is complicated by the route definitions living in two separate places. vtadmin-web could never, for example, define a route that starts with /api. And configuring vtadmin-api so that all non-/api routes fall through to the client is annoying, since even a simple 404 page will require loading the whole client-side app.

  • ❌ Optimizations like server-side rendering (SSR) become more complicated, since that typically requires the Thing serving the front-end to have some knowledge of the routing/rendering. (Most SSR libraries are written in node for this reason, as I understand it.) This is very much a premature optimization concern though, since there's lots of other optimizations we could make. (Inserting JSON into index.html for common data, making the front-end bundle smaller, code splitting, etc.)

  • ❌ If vtadmin-api goes down, it'll take the UI down with it.

@doeg doeg added Type: Feature Request Needs Triage This issue needs to be correctly labelled and triaged and removed Needs Triage This issue needs to be correctly labelled and triaged labels Apr 20, 2022
@doeg doeg added this to Inbox (unplanned/untriaged) in VTAdmin via automation Apr 20, 2022
@doeg doeg added the Component: VTAdmin VTadmin interface label Apr 21, 2022
@doeg doeg self-assigned this Apr 21, 2022
@notfelineit notfelineit moved this from Inbox (unplanned/untriaged) to To do soon-ish (planned but not started) in VTAdmin Apr 5, 2023
@notfelineit notfelineit moved this from To do soon-ish (planned but not started) to In progress in VTAdmin Apr 5, 2023
@notfelineit notfelineit self-assigned this Apr 5, 2023
@notfelineit
Copy link
Contributor

It's been a while since we've looked at this issue, but since then we've moved to Vite! We might explore this https://github.com/torenware/vite-go as an option for serving the web page since it is recommended by Vite.

@notfelineit notfelineit moved this from In progress to To do soon-ish (planned but not started) in VTAdmin Mar 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
VTAdmin
To do soon-ish (planned but not started)
Development

Successfully merging a pull request may close this issue.

2 participants