Skip to content

Commit dcb1f11

Browse files
Simon Emmsroboquat
Simon Emms
authored andcommitted
[kots]: configure Gitpod as a KOTS-installable app
1 parent 9f0d5da commit dcb1f11

17 files changed

+618
-1
lines changed

install/kots/README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,47 @@
22

33
[Kubernetes Off-The-Shelf(KOTS)](https://kots.io/) is how we deliver
44
Gitpod to enterprise customers.
5+
6+
# Getting started
7+
8+
You will need:
9+
- a Kubernetes cluster
10+
- a [Replicated](https://vendor.replicated.com) license file
11+
12+
Go to [our Replicated channels page](https://vendor.replicated.com/apps/gitpod/channels) and
13+
follow the installation instructions on screen.
14+
15+
# Terminology
16+
17+
KOTS is the technology which is used to deliver a Replicated installation. Generally,
18+
KOTS should refer to the underlying open source technology and Replicated is the
19+
commercially supported project.
20+
21+
# Development
22+
23+
## Authentication
24+
25+
Two environment variables are required to be able to publish to our Replicated account:
26+
27+
- `REPLICATED_APP`: the unique application slug
28+
- `REPLICATED_API_TOKEN`: a [User API Token](https://vendor.replicated.com/account-settings) with `Read/Write` permissions
29+
30+
## Naming conventions
31+
32+
- Starts with `kots` - part of the KOTS configuration. Typically, this will follow the KOTS documentation/conventions
33+
- Starts with `gitpod` - part of the Gitpod application. Typically, this will be something we define/own
34+
- Starts with `helm` - a Helm chart
35+
- Starts with `crd` - a Custom Resource Definition
36+
37+
## Helm charts
38+
39+
KOTS [requires](https://kots.io/reference/v1beta1/helmchart) Helm charts to be uploaded as a `.tgz`
40+
file. The `make helm` command iterates through everything inside `charts`, installs the dependencies
41+
and packages them up as a `.tgz` file.
42+
43+
The `.tgz` files should not be committed to the repository.
44+
45+
## Create an unstable release
46+
47+
An unstable release can be created by running `make create_unstable_release`. This builds and publishes
48+
a new unstable release to the account. This can be then applied to your development cluster.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
apiVersion: v1
2+
kind: Secret
3+
metadata:
4+
name: https-certificates
5+
annotations:
6+
kots.io/when: '{{repl ConfigOptionEquals "cert_manager_enabled" "0" }}'
7+
type: kubernetes.io/tls
8+
data:
9+
tls.crt: '{{repl ConfigOption "tls_crt" }}'
10+
tls.key: '{{repl ConfigOption "tls_key" }}'
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
apiVersion: cert-manager.io/v1
2+
kind: Certificate
3+
metadata:
4+
name: https-certificates
5+
annotations:
6+
kots.io/when: '{{repl ConfigOptionEquals "cert_manager_enabled" "1" }}'
7+
spec:
8+
secretName: https-certificates
9+
issuerRef:
10+
name: '{{repl if (ConfigOptionEquals "cert_manager_provider" "incluster" ) }}ca-issuer{{repl else }}gitpod-issuer{{repl end }}'
11+
kind: '{{repl if (ConfigOptionEquals "cert_manager_provider" "azure") }}ClusterIssuer{{repl else }}Issuer{{repl end }}'
12+
dnsNames:
13+
- '{{repl ConfigOption "domain" }}'
14+
- '*.{{repl ConfigOption "domain" }}'
15+
- '*.ws.{{repl ConfigOption "domain" }}'
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
apiVersion: v1
2+
kind: Secret
3+
metadata:
4+
name: cloudsql
5+
annotations:
6+
kots.io/when: '{{repl and (ConfigOptionEquals "db_incluster" "0") (ConfigOptionEquals "db_cloudsql_enabled" "1") }}'
7+
data:
8+
credentials.json: '{{repl ConfigOption "db_gcp_credentials" }}'
9+
encryptionKeys: '{{repl ConfigOption "db_encryption_keys" | Base64Encode }}'
10+
password: '{{repl ConfigOption "db_password" | Base64Encode }}'
11+
username: '{{repl ConfigOption "db_username" | Base64Encode }}'
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
apiVersion: v1
2+
kind: Secret
3+
metadata:
4+
name: database
5+
annotations:
6+
kots.io/when: '{{repl and (ConfigOptionEquals "db_incluster" "0") (ConfigOptionEquals "db_cloudsql_enabled" "0") }}'
7+
data:
8+
encryptionKeys: '{{repl ConfigOption "db_encryption_keys" | Base64Encode }}'
9+
host: '{{repl ConfigOption "db_host" | Base64Encode }}'
10+
password: '{{repl ConfigOption "db_password" | Base64Encode }}'
11+
port: '{{repl ConfigOption "db_port" | Base64Encode }}'
12+
username: '{{repl ConfigOption "db_username" | Base64Encode }}'
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
apiVersion: v1
2+
kind: Secret
3+
metadata:
4+
name: cert-manager-gcp-dns-solver
5+
annotations:
6+
kots.io/when: '{{repl and (ConfigOptionEquals "cert_manager_enabled" "1") (ConfigOptionEquals "cert_manager_provider" "gcp") }}'
7+
data:
8+
key.json: '{{repl ConfigOption "cert_manager_gcp_credentials" }}'
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# This exists as debug information for the support bundle
2+
apiVersion: v1
3+
kind: ConfigMap
4+
metadata:
5+
name: gitpod-installation
6+
data:
7+
channelName: '{{repl ChannelName }}'
8+
cursor: '{{repl Cursor }}'
9+
isAirgap: '{{repl IsAirgap }}'
10+
releaseNotes: '{{repl ReleaseNotes }}'
11+
sequence: '{{repl Sequence }}'
12+
version: '{{repl VersionLabel }}'

install/kots/manifests/gitpod-installer-job.yaml

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# The installer job is where the magic happens. It generates
2-
# the config and installs Gitpod
2+
# the config, installs Gitpod and then deletes itself when
3+
# it's finished
34
apiVersion: batch/v1
45
kind: Job
56
metadata:
@@ -27,22 +28,35 @@ spec:
2728
args:
2829
- |
2930
set -e
31+
3032
echo "Gitpod: Install jq"
3133
apk add --no-cache jq
34+
3235
echo "Gitpod: Perform the check"
3336
while [ "$(helm status -n {{repl Namespace }} cert-manager -o json | jq '.info.status == "deployed"')" = "false" ];
3437
do
3538
echo "Gitpod: Release not found - will retry in 10s"
3639
sleep 10
3740
done
41+
3842
echo "Gitpod: Release found - goodbye"
3943
containers:
4044
- name: installer
4145
# This will normally be the release tag - using this tag as need the license evaluator
4246
image: 'eu.gcr.io/gitpod-core-dev/build/installer:main.2569'
47+
volumeMounts:
48+
- mountPath: /mnt/node0
49+
name: node-fs0
50+
readOnly: true
4351
env:
4452
- name: CONFIG_FILE
4553
value: /tmp/gitpod-config.yaml
54+
- name: CONTAINERD_DIR_K3S
55+
value: /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io
56+
- name: CONTAINERD_SOCKET_K3S
57+
value: /run/k3s/containerd/containerd.sock
58+
- name: GITPOD_OBJECTS
59+
value: /tmp/gitpod
4660
command:
4761
- /bin/sh
4862
- -c
@@ -53,10 +67,102 @@ spec:
5367
echo "Gitpod: Generate the base Installer config"
5468
/app/installer init > "${CONFIG_FILE}"
5569
70+
echo "Gitpod: auto-detecting containerd location on host machine"
71+
if [ -d "/mnt/node0${CONTAINERD_DIR_K3S}" ]; then
72+
echo "Gitpod: containerd dir detected as k3s"
73+
74+
yq e -i ".workspace.runtime.containerdRuntimeDir = \"${CONTAINERD_DIR_K3S}\"" "${CONFIG_FILE}"
75+
fi
76+
77+
if [ -S "/mnt/node0${CONTAINERD_SOCKET_K3S}" ]; then
78+
echo "Gitpod: containerd socket detected as k3s"
79+
80+
yq e -i ".workspace.runtime.containerdSocket = \"${CONTAINERD_SOCKET_K3S}\"" "${CONFIG_FILE}"
81+
fi
82+
5683
echo "Gitpod: Inject the Replicated variables into the config"
5784
yq e -i '.domain = "{{repl ConfigOption "domain" }}"' "${CONFIG_FILE}"
85+
yq e -i '.license.kind = "secret"' "${CONFIG_FILE}"
86+
yq e -i '.license.name = "gitpod-license"' "${CONFIG_FILE}"
87+
88+
if [ '{{repl and (ConfigOptionEquals "db_incluster" "0") (ConfigOptionEquals "db_cloudsql_enabled" "1") }}' = "true" ];
89+
then
90+
echo "Gitpod: configuring CloudSQLProxy"
91+
92+
yq e -i ".database.inCluster = false" "${CONFIG_FILE}"
93+
yq e -i ".database.cloudSQL.instance = \"{{repl ConfigOption "db_cloudsql_instance" }}\"" "${CONFIG_FILE}"
94+
yq e -i ".database.cloudSQL.serviceAccount.kind = \"secret\"" "${CONFIG_FILE}"
95+
yq e -i ".database.cloudSQL.serviceAccount.name = \"cloudsql\"" "${CONFIG_FILE}"
96+
fi
97+
98+
if [ '{{repl and (ConfigOptionEquals "db_incluster" "0") (ConfigOptionEquals "db_cloudsql_enabled" "0") }}' = "true" ];
99+
then
100+
echo "Gitpod: configuring external database"
101+
102+
yq e -i ".database.inCluster = false" "${CONFIG_FILE}"
103+
yq e -i ".database.external.certificate.kind = \"secret\"" "${CONFIG_FILE}"
104+
yq e -i ".database.external.certificate.name = \"database\"" "${CONFIG_FILE}"
105+
fi
106+
107+
if [ '{{repl ConfigOptionEquals "reg_incluster" "0" }}' = "true" ];
108+
then
109+
echo "Gitpod: configuring external container registry"
110+
111+
yq e -i ".containerRegistry.inCluster = false" "${CONFIG_FILE}"
112+
yq e -i ".containerRegistry.external.url = \"{{repl ConfigOption "reg_url" }}\"" "${CONFIG_FILE}"
113+
yq e -i ".containerRegistry.external.certificate.kind = \"secret\"" "${CONFIG_FILE}"
114+
yq e -i ".containerRegistry.external.certificate.name = \"container-registry\"" "${CONFIG_FILE}"
115+
116+
if [ '{{repl ConfigOptionEquals "reg_s3storage" "1" }}' = "true" ];
117+
then
118+
echo "Gitpod: configuring container registry S3 backend"
119+
120+
yq e -i ".containerRegistry.s3storage.bucket = \"{{repl ConfigOption "reg_bucketname" }}\"" "${CONFIG_FILE}"
121+
yq e -i ".containerRegistry.s3storage.certificate.kind = \"secret\"" "${CONFIG_FILE}"
122+
yq e -i ".containerRegistry.s3storage.certificate.name = \"container-registry-s3-backend\"" "${CONFIG_FILE}"
123+
fi
124+
fi
125+
126+
if [ '{{repl ConfigOptionNotEquals "store_provider" "incluster" }}' = "true" ];
127+
then
128+
echo "Gitpod: configuring the storage"
129+
130+
yq e -i ".metadata.region = \"{{repl ConfigOption "store_region" }}\"" "${CONFIG_FILE}"
131+
yq e -i ".objectStorage.inCluster = false" "${CONFIG_FILE}"
132+
133+
if [ '{{repl ConfigOptionEquals "store_provider" "azure" }}' = "true" ];
134+
then
135+
echo "Gitpod: configuring storage for Azure"
136+
137+
yq e -i ".objectStorage.azure.credentials.kind = \"secret\"" "${CONFIG_FILE}"
138+
yq e -i ".objectStorage.azure.credentials.name = \"storage-azure\"" "${CONFIG_FILE}"
139+
fi
140+
141+
if [ '{{repl ConfigOptionEquals "store_provider" "gcp" }}' = "true" ];
142+
then
143+
echo "Gitpod: configuring storage for GCP"
144+
145+
yq e -i ".objectStorage.cloudStorage.project = \"{{repl ConfigOption "store_gcp_project" }}\"" "${CONFIG_FILE}"
146+
yq e -i ".objectStorage.cloudStorage.serviceAccount.kind = \"secret\"" "${CONFIG_FILE}"
147+
yq e -i ".objectStorage.cloudStorage.serviceAccount.name = \"storage-gcp\"" "${CONFIG_FILE}"
148+
fi
149+
150+
if [ '{{repl ConfigOptionEquals "store_provider" "s3" }}' = "true" ];
151+
then
152+
echo "Gitpod: configuring storage for S3"
153+
154+
yq e -i ".objectStorage.s3.endpoint = \"{{repl ConfigOption "store_s3_endpoint" }}\"" "${CONFIG_FILE}"
155+
yq e -i ".objectStorage.s3.credentials.secret = \"secret\"" "${CONFIG_FILE}"
156+
yq e -i ".objectStorage.s3.credentials.name = \"storage-s3\"" "${CONFIG_FILE}"
157+
fi
158+
fi
58159
59160
echo "Gitpod: Generate the Kubernetes objects and apply"
60161
/app/installer render -c "${CONFIG_FILE}" --namespace {{repl Namespace }} | kubectl apply -f -
61162
62163
echo "Gitpod: Installer job finished - goodbye"
164+
volumes:
165+
- name: node-fs0
166+
hostPath:
167+
path: /
168+
type: Directory
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Azure doesn't seem to like using an Issuer
2+
# @link https://github.com/cert-manager/cert-manager/issues/4867c
3+
apiVersion: cert-manager.io/v1
4+
kind: ClusterIssuer
5+
metadata:
6+
name: gitpod-issuer
7+
annotations:
8+
kots.io/when: '{{repl and (ConfigOptionEquals "cert_manager_enabled" "1") (ConfigOptionEquals "cert_manager_provider" "azure") }}'
9+
spec:
10+
acme:
11+
email: '{{repl ConfigOption "cert_manager_email" }}'
12+
server: '{{repl ConfigOption "cert_manager_acme_url" }}'
13+
privateKeySecretRef:
14+
name: issuer-account-key
15+
solvers:
16+
- dns01:
17+
azureDNS:
18+
subscriptionID: '{{repl ConfigOption "cert_manager_azure_subscription_id" }}'
19+
resourceGroupName: '{{repl ConfigOption "cert_manager_azure_resource_group" }}'
20+
hostedZoneName: '{{repl ConfigOption "domain" }}'
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
apiVersion: cert-manager.io/v1
2+
kind: Issuer
3+
metadata:
4+
name: gitpod-issuer
5+
annotations:
6+
kots.io/when: '{{repl and (ConfigOptionEquals "cert_manager_enabled" "1") (ConfigOptionEquals "cert_manager_provider" "gcp") }}'
7+
spec:
8+
acme:
9+
email: '{{repl ConfigOption "cert_manager_email" }}'
10+
server: '{{repl ConfigOption "cert_manager_acme_url" }}'
11+
privateKeySecretRef:
12+
name: issuer-account-key
13+
solvers:
14+
- dns01:
15+
cloudDNS:
16+
project: '{{repl ConfigOption "cert_manager_gcp_project" }}'
17+
serviceAccountSecretRef:
18+
name: cert-manager-gcp-dns-solver
19+
key: key.json
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
apiVersion: v1
2+
kind: Secret
3+
metadata:
4+
name: gitpod-license
5+
data:
6+
license: '{{repl LicenseFieldValue "signature" | Base64Encode }}'
7+
type: '{{repl printf "replicated" | Base64Encode }}'
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
apiVersion: v1
2+
kind: Secret
3+
metadata:
4+
name: container-registry-s3-backend
5+
annotations:
6+
kots.io/when: '{{repl and (ConfigOptionEquals "reg_incluster" "0") (ConfigOptionEquals "reg_s3storage" "1") }}'
7+
data:
8+
s3AccessKey: '{{repl ConfigOption "reg_accesskey" | Base64Encode }}'
9+
s3SecretKey: '{{repl ConfigOption "reg_secretkey" | Base64Encode }}'
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
apiVersion: v1
2+
kind: Secret
3+
metadata:
4+
name: container-registry
5+
annotations:
6+
kots.io/when: '{{repl ConfigOptionEquals "reg_incluster" "0" }}'
7+
type: kubernetes.io/dockerconfigjson
8+
data:
9+
.dockerconfigjson: '{{repl printf "{\"auths\": {\"%s\": {\"username\": \"%s\", \"password\": %s, \"auth\": \"%s\"}}}" (ConfigOption "reg_server" | default (ConfigOption "reg_url")) (ConfigOption "reg_username") (ConfigOption "reg_password" | toJson) (printf "%s:%s" (ConfigOption "reg_username") (ConfigOption "reg_password") | Base64Encode) | Base64Encode }}'
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
apiVersion: v1
2+
kind: Secret
3+
metadata:
4+
name: storage-azure
5+
annotations:
6+
kots.io/when: '{{repl ConfigOptionEquals "store_provider" "azure" }}'
7+
data:
8+
accountName: '{{repl ConfigOption "store_azure_account_name" | Base64Encode }}'
9+
accountKey: '{{repl ConfigOption "store_azure_access_key" | Base64Encode }}'
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
apiVersion: v1
2+
kind: Secret
3+
metadata:
4+
name: storage-gcp
5+
annotations:
6+
kots.io/when: '{{repl ConfigOptionEquals "store_provider" "gcp" }}'
7+
data:
8+
service-account.json: '{{repl ConfigOption "store_gcp_credentials" }}'
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
apiVersion: v1
2+
kind: Secret
3+
metadata:
4+
name: storage-azure
5+
annotations:
6+
kots.io/when: '{{repl ConfigOptionEquals "store_provider" "s3" }}'
7+
data:
8+
accessKeyId: '{{repl ConfigOption "store_s3_access_key_id" | Base64Encode }}'
9+
secretAccessKey: '{{repl ConfigOption "store_s3_secret_access_key" | Base64Encode }}'

0 commit comments

Comments
 (0)