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

Deploying VTAdmin in Vtop #272

Merged
merged 21 commits into from
Jun 28, 2022
Merged

Deploying VTAdmin in Vtop #272

merged 21 commits into from
Jun 28, 2022

Conversation

GuptaManan100
Copy link
Collaborator

@GuptaManan100 GuptaManan100 commented Jun 21, 2022

Description

This PR adds VTAdmin to the operator and associated tests.
Currently only the specific vtadmin image can be used for deploying VTAdmin, but we'll get vitess/lite image working too later.

An example config looks like the following -

spec:
  images:
    vtadmin: vitess/vtadmin:latest
  vtadmin:
    rbac:
      name: example-cluster-config
      key: rbac.yaml
    cells:
      - zone1
    apiAddresses:
      - http://localhost:14001
    replicas: 1
    readOnly: false
    apiResources:
      limits:
        memory: 128Mi
      requests:
        cpu: 100m
        memory: 128Mi
    webResources:
      limits:
        memory: 128Mi
      requests:
        cpu: 100m
        memory: 128Mi

The VTAdmin spec includes the following fields -

  • Rbac as a secret source. It is the role based access control rules to use for VTAdmin API
  • Cells as a list of strings. It is the cells where VTAdmin must be deployed. Defaults to deploying everywhere
  • APIAddresses as a list of strings. Since the VTAdmin web UI runs on the client side, it needs the API address to use to query the API. We can't use the internal kubernetes service address or the ip of the pod, since they aren't visible outside the cluster. The API Address must be provided by the user based on how they export the service of VTAdmin API. In our tests we port-forward the service to port 14001 and therefore that is the address provided here. This value is a list because the address to be used for VTAdmin web in each cell might be different. If only 1 value is provided then, that is used for all the cells. The ideal way to deploy this would be to export each individual VTAdmin service (that we create) in each cell and attach external IPs to them and provide those IPs here.
  • Replicas - Number of VTAdmin deployments required per cell. We setup a service on top of the web and API connections, so load-balancing comes out of the box
  • WebResources - Resource requests and limits for the container running the VTAdmin web server
  • APIResources - Resource requests and limits for the container running the VTAdmin API server
  • ReadOnly - Configuration to set the VTAdmin web UI to be read only.

Documentation

vitessio/website#1073

…y crds

Signed-off-by: Manan Gupta <manan@planetscale.com>
Signed-off-by: Manan Gupta <manan@planetscale.com>
Signed-off-by: Manan Gupta <manan@planetscale.com>
Signed-off-by: Manan Gupta <manan@planetscale.com>
Signed-off-by: Manan Gupta <manan@planetscale.com>
Signed-off-by: Manan Gupta <manan@planetscale.com>
Signed-off-by: Manan Gupta <manan@planetscale.com>
Signed-off-by: Manan Gupta <manan@planetscale.com>
Signed-off-by: Manan Gupta <manan@planetscale.com>
…create a keyspace

Signed-off-by: Manan Gupta <manan@planetscale.com>
Signed-off-by: Manan Gupta <manan@planetscale.com>
Signed-off-by: Manan Gupta <manan@planetscale.com>
…nds in the docker image of vtadmin

Signed-off-by: Manan Gupta <manan@planetscale.com>
…nt variables

Signed-off-by: Manan Gupta <manan@planetscale.com>
Signed-off-by: Manan Gupta <manan@planetscale.com>
Signed-off-by: Manan Gupta <manan@planetscale.com>
Signed-off-by: Manan Gupta <manan@planetscale.com>
Signed-off-by: Manan Gupta <manan@planetscale.com>
Signed-off-by: Manan Gupta <manan@planetscale.com>

- name: "VTAdmin Test"
command:
- apk add g++ make bash curl mysql mysql-client chromium
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is different from the other test setup lines. It is also installing chromium browser. We need this to run it in a headless mode to download the VTAdmin web pages. We can't use curl (which we use for the API pages) or wget because they do not support JavaScript, so a headless browser was the easiest solution.

Comment on lines +47 to +58
if len(vt.Spec.Images.Vtadmin) == 0 {
log.Error("Not deploying vtadmin since image is unspecified")
return resultBuilder.Result()
}

if len(vt.Spec.VtAdmin.APIAddresses) == 0 {
log.Errorf("Not deploying vtadmin since api addresses field is not specified. Atleast 1 value is required")
}

if len(vt.Spec.VtAdmin.APIAddresses) != 1 && len(vt.Spec.VtAdmin.APIAddresses) != len(vt.Spec.VtAdmin.Cells) {
log.Errorf("Not deploying vtadmin since api addresses field doesn't align with cells field")
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are user input validations. There exist 3 -

  • The VTAdmin image should be specifically provided. We do not add a default for vitess:lite since that won't work
  • There should be at least 1 APIAddress provided
  • If more than 1 APIAddresses are provided, then the length of this list should match the length of the cells list.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense to me

Comment on lines +188 to +192
// We have already checked that atleast 1 value should be available in APIAddresses
apiAddress := vt.Spec.VtAdmin.APIAddresses[0]
if len(vt.Spec.VtAdmin.APIAddresses) > 1 {
apiAddress = vt.Spec.VtAdmin.APIAddresses[idx]
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is safe because of the user input validation above

Comment on lines +285 to +302
discoveryVal := fmt.Sprintf(`{
"vtctlds": [
{
"host": {
"fqdn": "%s:%d",
"hostname": "%s:%d"
}
}
],
"vtgates": [
{
"host": {
"hostname": "%s:%d"
}
}
]
}`, vtctldServiceIP, vtctldServiceWebPort, vtctldServiceIP, vtctldServiceGrpcPort, vtgateServiceIP, vtgateServiceGrpcPort)
secretName := vtadmin.DiscoverySecretName(vt.Name, cell.Name)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The discovery configuration file is autogenerated using the global service of vtctld and per cell service of vtgates.

Comment on lines +319 to +328
configKey := vtadmin.WebConfigFileName
configVal := fmt.Sprintf(`window.env = {
'REACT_APP_VTADMIN_API_ADDRESS': "%s",
'REACT_APP_FETCH_CREDENTIALS': "omit",
'REACT_APP_ENABLE_EXPERIMENTAL_TABLET_DEBUG_VARS': false,
'REACT_APP_BUGSNAG_API_KEY': "",
'REACT_APP_DOCUMENT_TITLE': "",
'REACT_APP_READONLY_MODE': %s,
};`, apiAddress, convertReadOnlyFieldToString(vt.Spec.VtAdmin.ReadOnly))
secretName := vtadmin.WebConfigSecretName(vt.Name, cell.Name)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some parameters of the config are not user controllable like REACT_APP_ENABLE_EXPERIMENTAL_TABLET_DEBUG_VARS is always set to false. Since we do not have a good way of discovering vttablets yet, this doesn't work. http-tablet-url-tmpl is not flexible to allow this right now. To enable this, we would have to setup services for all the vttablets and then encode them in the flag. Other complexities like new vttablets requiring change in config, etc will also have to be dealt with.
Similarly, REACT_APP_FETCH_CREDENTIALS is always set to omit because we aren't enabling CORS. If we did want to do that, then we would also need to ask the user to provide the hosts that are allowed to access the API server

Comment on lines +44 to +46
// AbsolutePath stores the absolute path to use instead of the generated path
// with /vt/secret as the prefix
AbsolutePath string
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This had to be added to allow mounting files to a specific path instead of the /vt/secrets where they usually are. For the Vtadmin web config, the path has to be /vt/web/vtadmin/build/config

Comment on lines +213 to +214
updateRbac(spec, apiFlags, vtadminAPIContainer, &obj.Spec.Template.Spec)
updateDiscovery(spec, apiFlags, vtadminAPIContainer, &obj.Spec.Template.Spec)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adds the file mounts for Rbac and discovery config

VolumeMounts: spec.ExtraVolumeMounts,
Env: spec.ExtraEnv,
}
updateWebConfig(spec, vtadminWebContainer, &obj.Spec.Template.Spec)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adds the file mount for the web config

@GuptaManan100
Copy link
Collaborator Author

GuptaManan100 commented Jun 27, 2022

Also, the vtadmin test needs to restarted after the image vitess/vtadmin:latest is pushed to docker hub. The associated PR that introduces this docker image is vitessio/vitess#10543

@GuptaManan100 GuptaManan100 marked this pull request as ready for review June 27, 2022 14:46
@GuptaManan100 GuptaManan100 changed the title Vtadmin in vtop Deploying VTAdmin in Vtop Jun 27, 2022
…with root

Signed-off-by: Manan Gupta <manan@planetscale.com>
Signed-off-by: Manan Gupta <manan@planetscale.com>
@frouioui frouioui mentioned this pull request Jun 27, 2022
43 tasks
Comment on lines +47 to +58
if len(vt.Spec.Images.Vtadmin) == 0 {
log.Error("Not deploying vtadmin since image is unspecified")
return resultBuilder.Result()
}

if len(vt.Spec.VtAdmin.APIAddresses) == 0 {
log.Errorf("Not deploying vtadmin since api addresses field is not specified. Atleast 1 value is required")
}

if len(vt.Spec.VtAdmin.APIAddresses) != 1 && len(vt.Spec.VtAdmin.APIAddresses) != len(vt.Spec.VtAdmin.Cells) {
log.Errorf("Not deploying vtadmin since api addresses field doesn't align with cells field")
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense to me

log.Errorf("Not deploying vtadmin since api addresses field doesn't align with cells field")
}

key := client.ObjectKey{Namespace: vt.Namespace, Name: vtadmin.ServiceName(vt.Name)}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can vtadmin have no service name? if it's not deployed under a k8s service for example

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a function which deterministically gives the service name to use. We are creating the service just down below. We always create services for vtctld and vtgates in cells, so that if there are multiple deployments then users can just assign a public IP address to the service and it will load balance across all the available pods

Comment on lines +231 to +233
// Symlinks are required because the web config file is mounted as a
// secret which happens to be mounted as symlink instead of an actual file
"--symlinks",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏻

@GuptaManan100 GuptaManan100 merged commit 6c27c87 into main Jun 28, 2022
@GuptaManan100 GuptaManan100 deleted the vtadmin-in-vtop branch June 28, 2022 10:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants