ClusterManager: Implements support of remote clusters.
After this change users will be able to:
* Create cluster and add/remove servers to it
* Install apps on remote cluster
* Move already installed apps between clusters
* Apps running on server being removed will auto-migrate
to another server from that same cluster
This is achieved by:
* Installing and running minimal version of dodo on remote cluster
* Ingress-nginx is installed automatically on new clusters
* Next to nginx we run VPN client in the same pod, so that
default cluster can establish secure communication with it
* Multiple reverse proxies are configured to get to the
remote cluster service from ingress installed on default cluster.
Next steps:
* Support remote clusters in dodo apps (prototype ready)
* Clean up old cluster when moving app to the new one. Currently
old cluster keeps running app pods even though no ingress can
reach it anymore.
Change-Id: Iffc908c93416d4126a8e1c2832eae7b659cb8044
diff --git a/core/installer/values-tmpl/cluster-network.cue b/core/installer/values-tmpl/cluster-network.cue
new file mode 100644
index 0000000..d470ff1
--- /dev/null
+++ b/core/installer/values-tmpl/cluster-network.cue
@@ -0,0 +1,138 @@
+import (
+ // "encoding/base64"
+)
+
+input: {
+ cluster: #Cluster
+ vpnUser: string
+ vpnProxyHostname: string
+ vpnAuthKey: string @role(VPNAuthKey) @usernameField(vpnUser)
+ // TODO(gio): support port allocator
+}
+
+name: "Cluster Network"
+namespace: "cluster-network"
+
+out: {
+ images: {
+ "ingress-nginx": {
+ registry: "registry.k8s.io"
+ repository: "ingress-nginx"
+ name: "controller"
+ tag: "v1.8.0"
+ pullPolicy: "IfNotPresent"
+ }
+ "tailscale-proxy": {
+ repository: "tailscale"
+ name: "tailscale"
+ tag: "v1.42.0"
+ pullPolicy: "IfNotPresent"
+ }
+ // portAllocator: {
+ // repository: "giolekva"
+ // name: "port-allocator"
+ // tag: "latest"
+ // pullPolicy: "Always"
+ // }
+ }
+
+ charts: {
+ "access-secrets": {
+ kind: "GitRepository"
+ address: "https://code.v1.dodo.cloud/helm-charts"
+ branch: "main"
+ path: "charts/access-secrets"
+ }
+ "ingress-nginx": {
+ kind: "GitRepository"
+ address: "https://code.v1.dodo.cloud/helm-charts"
+ branch: "main"
+ path: "charts/ingress-nginx"
+ }
+ "tailscale-proxy": {
+ kind: "GitRepository"
+ address: "https://code.v1.dodo.cloud/helm-charts"
+ branch: "main"
+ path: "charts/tailscale-proxy"
+ }
+ // portAllocator: {
+ // kind: "GitRepository"
+ // address: "https://code.v1.dodo.cloud/helm-charts"
+ // branch: "main"
+ // path: "charts/port-allocator"
+ // }
+ }
+
+ helm: {
+ _fullnameOverride: "\(global.id)-nginx-cluster-\(input.cluster.name)"
+ "access-secrets": {
+ chart: charts["access-secrets"]
+ values: {
+ serviceAccountName: _fullnameOverride
+ }
+ }
+ "ingress-nginx": {
+ chart: charts["ingress-nginx"]
+ dependsOn: [{
+ name: "access-secrets"
+ namespace: release.namespace
+ }]
+ values: {
+ fullnameOverride: _fullnameOverride
+ controller: {
+ service: enabled: false
+ ingressClassByName: true
+ ingressClassResource: {
+ name: input.cluster.ingressClassName
+ enabled: true
+ default: false
+ controllerValue: "k8s.io/\(input.cluster.name)"
+ }
+ config: {
+ "proxy-body-size": "200M" // TODO(giolekva): configurable
+ "force-ssl-redirect": "true"
+ "server-snippet": """
+ more_clear_headers "X-Frame-Options";
+ """
+ }
+ admissionWebhooks: {
+ enabled: false
+ }
+ image: {
+ registry: images["ingress-nginx"].registry
+ image: images["ingress-nginx"].imageName
+ tag: images["ingress-nginx"].tag
+ pullPolicy: images["ingress-nginx"].pullPolicy
+ }
+ extraContainers: [{
+ name: "proxy"
+ image: images["tailscale-proxy"].fullNameWithTag
+ env: [{
+ name: "TS_AUTHKEY"
+ value: input.vpnAuthKey
+ }, {
+ name: "TS_HOSTNAME"
+ value: input.vpnProxyHostname
+ }, {
+ name: "TS_EXTRA_ARGS"
+ value: "--login-server=https://headscale.\(global.domain)"
+ }]
+ }]
+ }
+ }
+ }
+ // "port-allocator": {
+ // chart: charts.portAllocator
+ // values: {
+ // repoAddr: release.repoAddr
+ // sshPrivateKey: base64.Encode(null, input.sshPrivateKey)
+ // ingressNginxPath: "\(release.appDir)/resources/ingress-nginx.yaml"
+ // image: {
+ // repository: images.portAllocator.fullName
+ // tag: images.portAllocator.tag
+ // pullPolicy: images.portAllocator.pullPolicy
+ // }
+ // }
+ // }
+ }
+}