From fe2b26612e27fead5b268262d2761d904c99a922 Mon Sep 17 00:00:00 2001 From: Simon Emms Date: Mon, 15 Nov 2021 10:54:02 +0000 Subject: [PATCH] [installer]: create readme --- installer/README.md | 441 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 441 insertions(+) create mode 100644 installer/README.md diff --git a/installer/README.md b/installer/README.md new file mode 100644 index 00000000000000..eb5be8c83fa41e --- /dev/null +++ b/installer/README.md @@ -0,0 +1,441 @@ +

+ + +

Gitpod

+ +

Always ready-to-code.

+

+ +# Installer + +The best way to get started with Gitpod + +[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-908a85?logo=gitpod)](https://gitpod.io/from-referrer/) + +# Requirements + +- A machine running Linux/MacOS and Docker + - Windows is not currently supported, but will be in future +- [Kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) installed +- A [Kubernetes cluster configured](https://www.gitpod.io/docs/self-hosted/latest/installation) +- A [TLS certificate](#tls-certificates) + +Or, [open a Gitpod workspace](https://gitpod.io/from-referer/) + +The process to install Gitpod is: +1. generate a base config +2. amend the config for your own use-case +3. validate +4. render the Kubernetes YAML +5. `kubectl apply` + +# Quickstart + +## Build your binary + +> There is work to be done on improving the distribution of the binary +> [#6766](https://github.com/gitpod-io/gitpod/issues/6766) + +From [werft](https://werft.gitpod-dev.com), search for the tag you want, such as +`main.1919` + +```shell +# Get the versions +docker run -it --rm eu.gcr.io/gitpod-core-dev/build/versions:main.1919 cat /versions.yaml > versions.yaml +# Build your binary +go build +# Add the versions in +objcopy --add-section versionManifest=./versions.yaml ./installer +``` + +You can also `--debug-version-file` if you want to use `go run` + +## Generate the base config + +```shell +./installer init > gitpod.config.yaml +``` + +## Customise your config + +There are many things you can change in your config, which can be found in +the [Config Guide](#config). + +For the purposes of a quickstart, just change the `domain` to one of your +own. + +## Validate + +```shell +# Checks the validity of the configuration YAML +./installer validate config --config gitpod.config.yaml +``` + +Any errors here must be fixed before deploying. See [Config](#config) for +more details. + +```shell +# Checks that your cluster is ready to install Gitpod +./installer validate cluster --kubeconfig ~/.kube/config --config gitpod.config.yaml +``` + +Any errors here must be fixed before deploying. See [Cluster Dependencies](#cluster-dependencies) +for more details. + +## Render the YAML + +```shell +./installer render --config gitpod.config.yaml > gitpod.yaml +``` + +## Deploy + +```shell +kubectl apply -f gitpod.yaml +``` + +After a few minutes, your Gitpod installation will be available on the +specified `domain`. + +## Uninstallation + +The Installer generates a ConfigMap with the metadata of every Kubernetes +object generated by the Installer. This can be retrieved to remove Gitpod +from your cluster. + +```shell +kubectl get configmaps gitpod-app -o jsonpath='{.data.app\.yaml}' \ + | kubectl delete -f - # Piping to this will delete automatically +``` + +**Important**. This may leave certain objects still in your Kubernetes +cluster. This will include `Secrets` generated from internal `Certificates` +and `PersistentVolumeClaims`. These will need to be manually deleted. + +--- + +# What is installed + +- All Gitpod components +- Container registry* +- MySQL database* +- Jaeger operator* +- RabbitMQ +- Minio object storage* + +\* By default, these dependencies are installed if the `inCluster` setting +is `true`. External dependencies can be used in their place + +# Config + +> Not every parameter is discussed in this table, just ones that are likely +> to need changing. The full config structure is available in [config.go](/installer/pkg/config/v1/config.go). + +| Property | Required | Description | Notes | +| --- | --- | --- | --- | +| `domain` | Y | The domain to deploy to | This will need to be changed on every deployment | +| `kind` | Y | Installation type to run - for most users, this will be `Full` | Can be `Full`, `Meta` or `Workspace` | +| `metadata.region` | Y | Location for your `objectStorage` provider | If using Minio, set to `local` | +| `workspace.runtime.containerdRuntimeDir` | Y | The location of containerd on host machine | Common values are: | +| `workspace.runtime.containerdSocket` | Y | The location of containerd socket on the host machine | +| `workspace.runtime.fsShiftMethod` | Y | File system | Can be either `fuse` (fuse-overlayfs) or `shiftfs`. This depending upon your host OS/distribution. If unsure, use `fuse`. | + +## Auth Providers + +> This may move to a secret in future [#6867](https://github.com/gitpod-io/gitpod/issues/6867) + +Gitpod must be connected to a Git provider. This can be done via the +dashboard on first load, or by providing `authProviders` configuration. + +```yaml +authProviders: + - id: Public-GitHub + host: github.com + type: GitHub + oauth: + clientId: xxx + clientSecret: xxx + callBackUrl: https://$DOMAIN/auth/github.com/callback + settingsUrl: xxx +``` + +## In-cluster vs External Dependencies + +Gitpod requires certain services for it to function correctly. The Installer +provides all of these in-cluster, but they can be configured to use services +external to the cluster. + +To use the in-cluster dependency, set `inCluster` to be `true`. + +## Container Registry + +```yaml +containerRegistry: + inCluster: false + external: + url: + certificate: + kind: secret + name: container-registry-token +``` + +The `container-registry-token` secret must contain a `.dockerconfigjson` +key - this can be created by using the `kubectl create secret docker-registry` +[command](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/#create-a-secret-by-providing-credentials-on-the-command-line). + +## Database + +Gitpod requires an instance of MySQL 5.7 for data storage. + +The default encryption keys are `[{"name":"general","version":1,"primary":true,"material":"4uGh1q8y2DYryJwrVMHs0kWXJlqvHWWt/KJuNi04edI="}]` + +### Google Cloud SQL Proxy + +If using a GCP SQL instance, a [Cloud SQL Proxy](https://cloud.google.com/sql/docs/mysql/sql-proxy) +connection can be used. + +```yaml +database: + inCluster: false + cloudSQL: + instance: :: + serviceAccount: + kind: secret + name: cloudsql-token +``` + +The `cloudsql-token` secret must contain the following key/value pairs: + - `credentials.json` - GCP Service Account key with `roles/cloudsql.client` role + - `encryptionKeys` - database encryption key. Use default value as above if unsure + - `password` - database password + - `username` - database username + +### External Database + +For all other connections, use an external database configuration. + +```yaml +database: + inCluster: false + external: + certificate: + kind: secret + name: database-token +``` + +The `database-token` secret must contain the following key/value pairs: +- `encryptionKeys` - database encryption key. Use default value as above if unsure +- `host` - IP or URL of the database +- `password` - database password +- `port` - database port, usually `3306` +- `username` - database username + +## Object Storage + +Gitpod supports the following object storage providers: + +### GCP + +```yaml +metadata: + region: +objectStorage: + inCluster: false + cloudStorage: + project: + serviceAccount: + kind: secret + name: gcp-storage-token +``` + +The `gcp-storage-token` secret must contain the following key/value pairs: +- `service-account.json` - GCP Service Account key with `roles/storage.admin` and `roles/storage.objectAdmin` roles + +### Azure + +> Azure Blob Storage is not S3 compatible. This uses Minio Gateway to +> provide an S3 interface + +```yaml +metadata: + region: +objectStorage: + inCluster: false + azure: + certificate: + kind: secret + name: az-storage-token +``` + +The `az-storage-token` secret must contain the following key/value pairs: +- `accountName` - the globally-unique storage account name +- `accountKey` - access key for the storage account + +### S3 + +> This is currently only tested with AWS. Other S3-compatible providers should +> work but there may compatability issues - please raise a ticket if you have +> issues with other providers + +```yaml +metadata: + region: +objectStorage: + inCluster: false + s3: + endpoint: s3.amazonaws.com + credentials: + kind: secret + name: s3-storage-token +``` + +The `s3-storage-token` secret must contain the following key/value pairs: +- `accessKeyId` - username that has access to S3 account +- `secretAccessKey` - password that has access to S3 account + +> In AWS, the accessKeyId/secretAccessKey are an IAM user's credentials with +> `AmazonS3FullAccess` policy + +# Cluster Dependencies + +In order for the deployment to work successfully, there are certain +dependencies that need to be installed. + +## Kernel and Runtime + +Your Kubernetes nodes must have the Linux kernel v5.4.0 or above and +have a containerd runtime. + +## Affinity Labels + +Your Kubernetes nodes must have the following labels applied to them: +- `gitpod.io/workload_meta` +- `gitpod.io/workload_ide` +- `gitpod.io/workload_workspace_services` +- `gitpod.io/workload_workspace_regular` +- `gitpod.io/workload_workspace_headless` + +It is recommended to have a minimum of two node pools, grouping the `meta` +and `ide` nodes together and the `workspace` nodes together. + +## TLS certificates + +It is a requirement that a certificate secret exists, named as per +`certificate.name` in your config YAML with `tls.crt` and `tls.key` +in the secret data. How this certificate is generated is entirely your +choice - we suggest [cert-manager](https://cert-manager.io/) for +simplicity, however any certificate authority can be used by creating a +Kubernetes secret. + +The certificate must be associated with the following domains (where +`$DOMAIN` is the value in config `domain`): + - `$DOMAIN` + - `*.$DOMAIN` + - `*.ws.$DOMAIN` + +See [FAQs](#how-do-i-use-cert-manager-to-create-a-tls-certificate) for help +with creating a TLS certificate using cert-manager. + +### cert-manager + +cert-manager **MUST** be installed to your cluster. In order to secure +communication between the various components, the application creates +internally which are created using the cert-manager `Certificate` and +`Issuer` Custom Resource Definitions. + +```shell +helm repo add jetstack https://charts.jetstack.io +helm repo update +helm upgrade \ + --atomic \ + --cleanup-on-fail \ + --create-namespace \ + --install \ + --namespace='cert-manager' \ + --reset-values \ + --set installCRDs=true \ + --set 'extraArgs={--dns01-recursive-nameservers-only=true,--dns01-recursive-nameservers=8.8.8.8:53\,1.1.1.1:53}' \ + --wait \ + cert-manager \ + jetstack/cert-manager +``` + +# FAQs + +## Why are you writing your own Installer instead of using Helm/Kustomize/etc? + +The Installer is a complete replacement for our Helm charts. Over time, +this had grown to be too complex to effectively support and was a barrier +to entry for new users - the base config was many hundreds of lines long +and did not have effective validation on it. By contrast, the Installer's +config is < 50 lines long and can be fully validated before running. + +Also, by baking-in the container image versions to each release of the +Installer, we reduce the potential for variance making it easier to support +the community. + +## How do I use Cert Manager to create a TLS certificate? + +> Please see [cert-manager.io](https://cert-manager.io) for full documentation. +> This should be considered a quickstart guide. + +There are two steps to creating a public TLS certificate using cert-manager. + +### 1. Create the Issuer/ClusterIssuer + +As the certificate is a wildcard certificate, you must use the DNS01 Challenge +Provider. Please consult their [documentation](https://cert-manager.io/docs/configuration/acme/dns01) +for instructions. This can be either an +[`Issuer` or `ClusterIssuer`](https://cert-manager.io/docs/concepts/issuer). + +### 2. Create the certificate + +Replace `$DOMAIN` with your domain. This example assumes you have created a +`ClusterIssuer` called `gitpod-issuer` - please change this if necessary. + +This certificate is called `https-certificates` - please use that in your +Gitpod installer [config](#config). + +```yaml +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: https-certificates +spec: + secretName: https-certificates + issuerRef: + name: gitpod-issuer + kind: ClusterIssuer + dnsNames: + - $DOMAIN + - "*.$DOMAIN" + - "*.ws.$DOMAIN" +``` + +## How do I use my own TLS certificate? + +If you don't wish to use cert-manager to create a TLS certificate with a public +certificate authority, you can bring your own. + +To do this, generate your certificate as you would normally and then create a +secret with the CRT set to `tls.crt` and the Key set to `tls.key`. + +The DNS names must be `$DOMAIN`, `*.$DOMAIN` and `*.ws.$DOMAIN`, where `$DOMAIN` +is your domain. + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: https-certificates +data: + tls.crt: xxx + tls.key: xxx +``` + +# Todo + +PRs/comments welcome + +- [ ] [Improve distribution of gitpod-installer binaries](https://github.com/gitpod-io/gitpod/issues/6766) +- [ ] [Create a Gitpod workspace that can be used for installing a Gitpod instance](https://github.com/gitpod-io/gitpod/issues/6801)