This commit is contained in:
behrooz
2025-08-18 11:14:37 +03:30
parent dc18529168
commit e2ea0f9fe2
55 changed files with 18 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
{{/*
is deploy etcd enabled?
*/}}
{{- define "vcluster.database.embedded.enabled" -}}
{{- $backingStores := 0 -}}
{{- if .Values.controlPlane.backingStore.etcd.embedded.enabled -}}
{{- $backingStores = add1 $backingStores -}}
{{- end -}}
{{- if .Values.controlPlane.backingStore.etcd.deploy.enabled -}}
{{- $backingStores = add1 $backingStores -}}
{{- end -}}
{{- if .Values.controlPlane.backingStore.etcd.external.enabled -}}
{{- $backingStores = add1 $backingStores -}}
{{- end -}}
{{- if .Values.controlPlane.backingStore.database.embedded.enabled -}}
{{- $backingStores = add1 $backingStores -}}
{{- end -}}
{{- if .Values.controlPlane.backingStore.database.external.enabled -}}
{{- $backingStores = add1 $backingStores -}}
{{- end -}}
{{- if gt $backingStores 1 -}}
{{- fail "you can only enable one backingStore at the same time" -}}
{{- else if or (eq $backingStores 0) .Values.controlPlane.backingStore.database.embedded.enabled -}}
{{- true -}}
{{- end -}}
{{- end -}}
{{/*
migrate from deployed etcd?
*/}}
{{- define "vcluster.etcd.embedded.migrate" -}}
{{- if and .Values.controlPlane.backingStore.etcd.embedded.enabled .Values.controlPlane.backingStore.etcd.embedded.migrateFromDeployedEtcd -}}
{{- true -}}
{{- end -}}
{{- end -}}

View File

@@ -0,0 +1,27 @@
{{- define "vcluster.distro.env" -}}
{{- if and (eq (include "vcluster.distro" .) "k3s") .Values.controlPlane.distro.k3s.env -}}
{{ toYaml .Values.controlPlane.distro.k3s.env }}
{{- else if and (eq (include "vcluster.distro" .) "k8s") .Values.controlPlane.distro.k8s.env -}}
{{ toYaml .Values.controlPlane.distro.k8s.env }}
{{- end -}}
{{- end -}}
{{/*
vCluster Distro
*/}}
{{- define "vcluster.distro" -}}
{{- $distros := 0 -}}
{{- if .Values.controlPlane.distro.k3s.enabled -}}
k3s
{{- $distros = add1 $distros -}}
{{- end -}}
{{- if .Values.controlPlane.distro.k8s.enabled -}}
k8s
{{- $distros = add1 $distros -}}
{{- end -}}
{{- if eq $distros 0 -}}
k8s
{{- else if gt $distros 1 -}}
{{- fail "you can only enable one distro at the same time" -}}
{{- end -}}
{{- end -}}

View File

@@ -0,0 +1,37 @@
{{- define "vcluster.exportKubeConfig.validate" }}
{{- /*
Verify that exportKubeConfig.secret and exportKubeConfig.additionalSecrets are
not set at the same time.
*/}}
{{- $secretSet := false }}
{{- if .Values.exportKubeConfig.secret }}
{{- $secretSet = or (.Values.exportKubeConfig.secret.name | trim | ne "") (.Values.exportKubeConfig.secret.namespace | trim | ne "") }}
{{- end }}
{{- $additionalSecretsSet := false }}
{{- if .Values.exportKubeConfig.additionalSecrets }}
{{- $additionalSecretsSet = gt (len .Values.exportKubeConfig.additionalSecrets) 0 }}
{{- end }}
{{- if and $secretSet $additionalSecretsSet }}
{{- fail "exportKubeConfig.secret and exportKubeConfig.additionalSecrets cannot be set at the same time" }}
{{- end }}
{{- /*
Verify that additional secrets have name or namespace set.
*/}}
{{- range $_, $additionalSecret := .Values.exportKubeConfig.additionalSecrets }}
{{- $nameSet := false }}
{{- $namespaceSet := false }}
{{- if $additionalSecret.name }}
{{- if $additionalSecret.name | trim | ne "" }}
{{- $nameSet = true }}
{{- end }}
{{- end }}
{{- if $additionalSecret.namespace }}
{{- if $additionalSecret.namespace | trim | ne "" }}
{{- $namespaceSet = true }}
{{- end }}
{{- end }}
{{- if not (or $nameSet $namespaceSet) }}
{{- fail (cat "additional secret must have name and/or namespace set, found:" (toJson $additionalSecret)) }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,17 @@
{{- define "vcluster.controlPlane.image" -}}
{{- $tag := .Chart.Version -}}
{{- if .Values.controlPlane.statefulSet.image.tag -}}
{{- $tag = .Values.controlPlane.statefulSet.image.tag -}}
{{- end -}}
{{- include "vcluster.image" (dict "defaultImageRegistry" .Values.controlPlane.advanced.defaultImageRegistry "tag" $tag "registry" .Values.controlPlane.statefulSet.image.registry "repository" .Values.controlPlane.statefulSet.image.repository) -}}
{{- end -}}
{{- define "vcluster.image" -}}
{{- if .defaultImageRegistry -}}
{{ .defaultImageRegistry }}/{{ .repository }}:{{ .tag }}
{{- else if .registry -}}
{{ .registry }}/{{ .repository }}:{{ .tag }}
{{- else -}}
{{ .repository }}:{{ .tag }}
{{- end -}}
{{- end -}}

View File

@@ -0,0 +1,181 @@
{{- define "vcluster.initContainers" -}}
{{- if eq (include "vcluster.distro" .) "k3s" -}}
{{ include "vcluster.k3s.initContainers" . }}
{{- else if eq (include "vcluster.distro" .) "k8s" -}}
{{ include "vcluster.k8s.initContainers" . }}
{{- end -}}
{{- end -}}
{{/* Bump $defaultTag value whenever k8s version is bumped */}}
{{- define "vcluster.k8s.image.tag" -}}
{{- if not (empty .Values.controlPlane.distro.k8s.version) -}}
{{- if .Values.privateNodes.enabled -}}
{{ .Values.controlPlane.distro.k8s.version }}-full
{{- else -}}
{{ .Values.controlPlane.distro.k8s.version }}
{{- end -}}
{{- else -}}
{{- if .Values.privateNodes.enabled -}}
{{ .Values.controlPlane.distro.k8s.image.tag }}-full
{{- else -}}
{{ .Values.controlPlane.distro.k8s.image.tag }}
{{- end -}}
{{- end -}}
{{- end -}}
{{- define "vcluster.k8s.initContainers" -}}
{{- include "vcluster.oldPlugins.initContainers" . }}
{{- include "vcluster.plugins.initContainers" . }}
- name: kubernetes
image: "{{ include "vcluster.image" (dict "defaultImageRegistry" .Values.controlPlane.advanced.defaultImageRegistry "registry" .Values.controlPlane.distro.k8s.image.registry "repository" .Values.controlPlane.distro.k8s.image.repository "tag" (include "vcluster.k8s.image.tag" .)) }}"
volumeMounts:
- mountPath: /binaries
name: binaries
command:
- cp
args:
- -a
- /kubernetes/.
- /binaries/
{{- if .Values.controlPlane.distro.k8s.imagePullPolicy }}
imagePullPolicy: {{ .Values.controlPlane.distro.k8s.imagePullPolicy }}
{{- end }}
securityContext:
{{ toYaml .Values.controlPlane.distro.k8s.securityContext | indent 4 }}
resources:
{{ toYaml .Values.controlPlane.distro.k8s.resources | indent 4 }}
{{- end -}}
{{- define "vcluster.k3s.initContainers" -}}
{{- include "vcluster.oldPlugins.initContainers" . }}
{{- include "vcluster.plugins.initContainers" . }}
- name: vcluster
image: "{{ include "vcluster.image" (dict "defaultImageRegistry" .Values.controlPlane.advanced.defaultImageRegistry "registry" .Values.controlPlane.distro.k3s.image.registry "repository" .Values.controlPlane.distro.k3s.image.repository "tag" .Values.controlPlane.distro.k3s.image.tag) }}"
command:
- /bin/sh
args:
- -c
- "cp /bin/k3s /binaries/k3s"
{{- if .Values.controlPlane.distro.k3s.imagePullPolicy }}
imagePullPolicy: {{ .Values.controlPlane.distro.k3s.imagePullPolicy }}
{{- end }}
securityContext:
{{ toYaml .Values.controlPlane.distro.k3s.securityContext | indent 4 }}
volumeMounts:
- name: binaries
mountPath: /binaries
resources:
{{ toYaml .Values.controlPlane.distro.k3s.resources | indent 4 }}
{{- end -}}
{{/*
Plugin init container definition
*/}}
{{- define "vcluster.plugins.initContainers" -}}
{{- range $key, $container := .Values.plugins }}
{{- if not $container.image }}
{{- continue }}
{{- end }}
- {{- if $.Values.controlPlane.advanced.defaultImageRegistry }}
image: {{ $.Values.controlPlane.advanced.defaultImageRegistry }}/{{ $container.image }}
{{- else }}
image: {{ $container.image }}
{{- end }}
{{- if $container.name }}
name: {{ $container.name | quote }}
{{- else }}
name: {{ $key | quote }}
{{- end }}
{{- if $container.imagePullPolicy }}
imagePullPolicy: {{ $container.imagePullPolicy }}
{{- end }}
{{- if or $container.command $container.args }}
{{- if $container.command }}
command:
{{- range $commandIndex, $command := $container.command }}
- {{ $command | quote }}
{{- end }}
{{- end }}
{{- if $container.args }}
args:
{{- range $argIndex, $arg := $container.args }}
- {{ $arg | quote }}
{{- end }}
{{- end }}
{{- else }}
command: ["sh"]
args: ["-c", "cp -r /plugin /plugins/{{ $key }}"]
{{- end }}
{{- if $container.securityContext }}
securityContext:
{{ toYaml $container.securityContext | indent 4 }}
{{- end }}
{{- if $container.volumeMounts }}
volumeMounts:
{{ toYaml $container.volumeMounts | indent 4 }}
{{- else }}
volumeMounts:
- mountPath: /plugins
name: plugins
{{- end }}
{{- if $container.resources }}
resources:
{{ toYaml $container.resources | indent 4 }}
{{- end }}
{{- end }}
{{- end -}}
{{/*
Old Plugin init container definition
*/}}
{{- define "vcluster.oldPlugins.initContainers" -}}
{{- range $key, $container := .Values.plugin }}
{{- if or (ne $container.version "v2") (not $container.image) -}}
{{- continue -}}
{{- end -}}
- {{- if $.Values.controlPlane.advanced.defaultImageRegistry }}
image: {{ $.Values.controlPlane.advanced.defaultImageRegistry }}/{{ $container.image }}
{{- else }}
image: {{ $container.image }}
{{- end }}
{{- if $container.name }}
name: {{ $container.name | quote }}
{{- else }}
name: {{ $key | quote }}
{{- end }}
{{- if $container.imagePullPolicy }}
imagePullPolicy: {{ $container.imagePullPolicy }}
{{- end }}
{{- if or $container.command $container.args }}
{{- if $container.command }}
command:
{{- range $commandIndex, $command := $container.command }}
- {{ $command | quote }}
{{- end }}
{{- end }}
{{- if $container.args }}
args:
{{- range $argIndex, $arg := $container.args }}
- {{ $arg | quote }}
{{- end }}
{{- end }}
{{- else }}
command: ["sh"]
args: ["-c", "cp -r /plugin /plugins/{{ $key }}"]
{{- end }}
securityContext:
{{ toYaml $container.securityContext | indent 4 }}
{{- if $container.volumeMounts }}
volumeMounts:
{{ toYaml $container.volumeMounts | indent 4 }}
{{- else }}
volumeMounts:
- mountPath: /plugins
name: plugins
{{- end }}
{{- if $container.resources }}
resources:
{{ toYaml $container.resources | indent 4 }}
{{- end }}
{{- end }}
{{- end -}}

View File

@@ -0,0 +1,41 @@
{{/*
ControlPlane Kind
*/}}
{{- define "vcluster.kind" -}}
{{ if or (include "vcluster.persistence.volumeClaim.enabled" .) .Values.controlPlane.backingStore.etcd.embedded.enabled }}StatefulSet{{ else }}Deployment{{ end }}
{{- end -}}
{{/*
StatefulSet Persistence Options
*/}}
{{- define "vcluster.persistence" -}}
{{- if .Values.controlPlane.statefulSet.persistence.volumeClaimTemplates }}
volumeClaimTemplates:
{{ toYaml .Values.controlPlane.statefulSet.persistence.volumeClaimTemplates | indent 2 }}
{{- else if include "vcluster.persistence.volumeClaim.enabled" . }}
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: {{ .Values.controlPlane.statefulSet.persistence.volumeClaim.accessModes }}
{{- if .Values.controlPlane.statefulSet.persistence.volumeClaim.storageClass }}
storageClassName: {{ .Values.controlPlane.statefulSet.persistence.volumeClaim.storageClass }}
{{- end }}
resources:
requests:
storage: {{ .Values.controlPlane.statefulSet.persistence.volumeClaim.size }}
{{- end }}
{{- end -}}
{{/*
is persistence enabled?
*/}}
{{- define "vcluster.persistence.volumeClaim.enabled" -}}
{{- if .Values.controlPlane.statefulSet.persistence.volumeClaimTemplates -}}
{{- true -}}
{{- else if eq (toString .Values.controlPlane.statefulSet.persistence.volumeClaim.enabled) "true" -}}
{{- true -}}
{{- else if and (eq (toString .Values.controlPlane.statefulSet.persistence.volumeClaim.enabled) "auto") (or (include "vcluster.database.embedded.enabled" .) .Values.controlPlane.backingStore.etcd.embedded.enabled) -}}
{{- true -}}
{{- end -}}
{{- end -}}

View File

@@ -0,0 +1,126 @@
{{/*
Plugin volume mount definition
*/}}
{{- define "vcluster.plugins.volumeMounts" -}}
{{- $pluginFound := false -}}
{{- range $key, $container := .Values.plugin }}
{{- if or (ne $container.version "v2") (not $container.image) }}
{{- continue }}
{{- end }}
{{ $pluginFound = true }}
- mountPath: /plugins
name: plugins
{{- break }}
{{- end }}
{{- if eq $pluginFound false }}
{{- range $key, $container := .Values.plugins }}
{{- if not $container.image }}
{{- continue }}
{{- end }}
- mountPath: /plugins
name: plugins
{{- break }}
{{- end }}
{{- end }}
{{- end -}}
{{/*
Plugin volume definition
*/}}
{{- define "vcluster.plugins.volumes" -}}
{{- $pluginFound := false -}}
{{- range $key, $container := .Values.plugin }}
{{- if or (ne $container.version "v2") (not $container.image) }}
{{- continue }}
{{- end }}
{{ $pluginFound = true }}
- name: plugins
emptyDir: {}
{{- break }}
{{- end }}
{{- if eq $pluginFound false }}
{{- range $key, $container := .Values.plugins }}
{{- if not $container.image }}
{{- continue }}
{{- end }}
- name: plugins
emptyDir: {}
{{- break }}
{{- end }}
{{- end }}
{{- end -}}
{{/*
Sidecar container definition for the legacy syncer parts
*/}}
{{- define "vcluster.legacyPlugins.containers" -}}
{{- $counter := -1 -}}
{{- range $key, $container := .Values.plugin }}
{{- if eq $container.version "v2" }}
{{ continue }}
{{- end }}
{{- $counter = add1 $counter }}
- {{- if $.Values.controlPlane.advanced.defaultImageRegistry }}
image: {{ $.Values.controlPlane.advanced.defaultImageRegistry }}/{{ $container.image }}
{{- else }}
image: {{ $container.image }}
{{- end }}
{{- if $container.name }}
name: {{ $container.name | quote }}
{{- else }}
name: {{ $key | quote }}
{{- end }}
{{- if $container.imagePullPolicy }}
imagePullPolicy: {{ $container.imagePullPolicy }}
{{- end }}
{{- if $container.workingDir }}
workingDir: {{ $container.workingDir }}
{{- end }}
{{- if $container.command }}
command:
{{- range $commandIndex, $command := $container.command }}
- {{ $command | quote }}
{{- end }}
{{- end }}
{{- if $container.args }}
args:
{{- range $argIndex, $arg := $container.args }}
- {{ $arg | quote }}
{{- end }}
{{- end }}
{{- if $container.terminationMessagePath }}
terminationMessagePath: {{ $container.terminationMessagePath }}
{{- end }}
{{- if $container.terminationMessagePolicy }}
terminationMessagePolicy: {{ $container.terminationMessagePolicy }}
{{- end }}
env:
- name: VCLUSTER_PLUGIN_ADDRESS
value: "localhost:{{ add 14000 $counter }}"
- name: VCLUSTER_PLUGIN_NAME
value: "{{ $key }}"
{{- if $container.env }}
{{ toYaml $container.env | indent 4 }}
{{- end }}
envFrom:
{{ toYaml $container.envFrom | indent 4 }}
securityContext:
{{ toYaml $container.securityContext | indent 4 }}
lifecycle:
{{ toYaml $container.lifecycle | indent 4 }}
livenessProbe:
{{ toYaml $container.livenessProbe | indent 4 }}
readinessProbe:
{{ toYaml $container.readinessProbe | indent 4 }}
startupProbe:
{{ toYaml $container.startupProbe | indent 4 }}
volumeDevices:
{{ toYaml $container.volumeDevices | indent 4 }}
volumeMounts:
{{ toYaml $container.volumeMounts | indent 4 }}
{{- if $container.resources }}
resources:
{{ toYaml $container.resources | indent 4 }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,268 @@
{{- define "vcluster.clusterRoleName" -}}
{{- printf "vc-%s-v-%s" .Release.Name .Release.Namespace | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- define "vcluster.clusterRoleNameMultinamespace" -}}
{{- printf "vc-mn-%s-v-%s" .Release.Name .Release.Namespace | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Whether to create a cluster role or not
*/}}
{{- define "vcluster.createClusterRole" -}}
{{- if eq (toString .Values.rbac.clusterRole.enabled) "true" -}}
{{- true -}}
{{- else if eq (toString .Values.rbac.clusterRole.enabled) "auto" -}}
{{- if or
.Values.rbac.clusterRole.overwriteRules
(not (empty (include "vcluster.rbac.clusterRoleExtraRules" . )))
(not (empty (include "vcluster.plugin.clusterRoleExtraRules" . )))
(not (empty (include "vcluster.generic.clusterRoleExtraRules" . )))
.Values.networking.replicateServices.fromHost
.Values.pro
.Values.sync.toHost.storageClasses.enabled
.Values.experimental.isolatedControlPlane.enabled
.Values.sync.toHost.persistentVolumes.enabled
.Values.sync.toHost.priorityClasses.enabled
.Values.sync.fromHost.priorityClasses.enabled
.Values.sync.toHost.volumeSnapshotContents.enabled
.Values.sync.fromHost.volumeSnapshotClasses.enabled
(and (eq (include "vcluster.distro" .) "k8s") .Values.controlPlane.distro.k8s.scheduler.enabled)
.Values.controlPlane.advanced.virtualScheduler.enabled
.Values.sync.toHost.pods.hybridScheduling.enabled
.Values.sync.fromHost.ingressClasses.enabled
.Values.sync.fromHost.runtimeClasses.enabled
(eq (toString .Values.sync.fromHost.storageClasses.enabled) "true")
(eq (toString .Values.sync.fromHost.csiNodes.enabled) "true")
(eq (toString .Values.sync.fromHost.csiDrivers.enabled) "true")
(eq (toString .Values.sync.fromHost.csiStorageCapacities.enabled) "true")
.Values.sync.fromHost.nodes.enabled
.Values.sync.toHost.customResources
.Values.sync.fromHost.customResources
.Values.integrations.kubeVirt.enabled
.Values.integrations.externalSecrets.enabled
(and .Values.integrations.certManager.enabled .Values.integrations.certManager.sync.fromHost.clusterIssuers.enabled)
(and .Values.integrations.metricsServer.enabled .Values.integrations.metricsServer.nodes)
.Values.sync.fromHost.configMaps.enabled
.Values.sync.fromHost.secrets.enabled
.Values.integrations.istio.enabled
.Values.sync.toHost.namespaces.enabled
-}}
{{- true -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Role rules defined on global level
*/}}
{{- define "vcluster.rbac.roleExtraRules" -}}
{{- if .Values.rbac.role.extraRules }}
{{- range $ruleIndex, $rule := .Values.rbac.role.extraRules }}
- {{ toJson $rule }}
{{- end }}
{{- end }}
{{- end -}}
{{/*
Role rules defined by plugins
*/}}
{{- define "vcluster.plugin.roleExtraRules" -}}
{{- range $key, $container := .Values.plugin }}
{{- if $container.rbac }}
{{- if $container.rbac.role }}
{{- if $container.rbac.role.extraRules }}
{{- range $ruleIndex, $rule := $container.rbac.role.extraRules }}
- {{ toJson $rule }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- range $key, $container := .Values.plugins }}
{{- if $container.rbac }}
{{- if $container.rbac.role }}
{{- if $container.rbac.role.extraRules }}
{{- range $ruleIndex, $rule := $container.rbac.role.extraRules }}
- {{ toJson $rule }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- end -}}
{{/*
Cluster role rules defined by plugins
*/}}
{{- define "vcluster.plugin.clusterRoleExtraRules" -}}
{{- range $key, $container := .Values.plugin }}
{{- if $container.rbac }}
{{- if $container.rbac.clusterRole }}
{{- if $container.rbac.clusterRole.extraRules }}
{{- range $ruleIndex, $rule := $container.rbac.clusterRole.extraRules }}
- {{ toJson $rule }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- range $key, $container := .Values.plugins }}
{{- if $container.rbac }}
{{- if $container.rbac.clusterRole }}
{{- if $container.rbac.clusterRole.extraRules }}
{{- range $ruleIndex, $rule := $container.rbac.clusterRole.extraRules }}
- {{ toJson $rule }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- end -}}
{{/*
Role rules defined in generic syncer
*/}}
{{- define "vcluster.generic.roleExtraRules" -}}
{{- if .Values.experimental.genericSync.role }}
{{- if .Values.experimental.genericSync.role.extraRules }}
{{- range $ruleIndex, $rule := .Values.experimental.genericSync.role.extraRules }}
- {{ toJson $rule }}
{{- end }}
{{- end }}
{{- end }}
{{- end -}}
{{/*
Role rules defined in generic syncer
*/}}
{{- define "vcluster.customResources.roleExtraRules" -}}
{{- if .Values.sync.toHost.customResources }}
{{- range $crdName, $rule := .Values.sync.toHost.customResources }}
{{- if $rule.enabled }}
{{- $crdNameWithoutVersion := (split "/" $crdName)._0 -}} # Takes part before "/"
- resources: [ "{{ (splitn "." 2 $crdNameWithoutVersion)._0 }}" ]
apiGroups: [ "{{ (splitn "." 2 $crdNameWithoutVersion)._1 }}" ]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]
{{- end }}
{{- end }}
{{- end }}
{{- end -}}
{{/*
Cluster role rules defined in generic syncer
*/}}
{{- define "vcluster.customResources.clusterRoleExtraRules" -}}
{{- if .Values.sync.fromHost.customResources }}
{{- range $crdName, $rule := .Values.sync.fromHost.customResources }}
{{- if $rule.enabled }}
{{- $crdNameWithoutVersion := (split "/" $crdName)._0 -}} # Takes part before "/"
- resources: [ "{{ (splitn "." 2 $crdNameWithoutVersion)._0 }}" ]
apiGroups: [ "{{ (splitn "." 2 $crdNameWithoutVersion)._1 }}" ]
verbs: ["get", "list", "watch"]
{{- end }}
{{- end }}
{{- end }}
{{- end -}}
{{/*
Cluster role rules defined in generic syncer
*/}}
{{- define "vcluster.generic.clusterRoleExtraRules" -}}
{{- if .Values.experimental.genericSync.clusterRole }}
{{- if .Values.experimental.genericSync.clusterRole.extraRules }}
{{- range $ruleIndex, $rule := .Values.experimental.genericSync.clusterRole.extraRules }}
- {{ toJson $rule }}
{{- end }}
{{- end }}
{{- end }}
{{- end -}}
{{/*
Cluster Role rules defined on global level
*/}}
{{- define "vcluster.rbac.clusterRoleExtraRules" -}}
{{- if .Values.rbac.clusterRole.extraRules }}
{{- range $ruleIndex, $rule := .Values.rbac.clusterRole.extraRules }}
- {{ toJson $rule }}
{{- end }}
{{- end }}
{{- end -}}
{{/*
Whether to create a role and role binding to access the platform API key secret
*/}}
{{- define "vcluster.rbac.createPlatformSecretRole" -}}
{{- $createRBAC := dig "platform" "apiKey" "createRBAC" true .Values.external -}}
{{- if and $createRBAC (ne (include "vcluster.rbac.platformSecretNamespace" .) .Release.Namespace) }}
{{- true -}}
{{- end }}
{{- end -}}
{{/*
Namespace containing the vCluster platform secret
*/}}
{{- define "vcluster.rbac.platformSecretNamespace" -}}
{{- dig "platform" "apiKey" "namespace" .Release.Namespace .Values.external | default .Release.Namespace -}}
{{- end -}}
{{/*
Name specifies the secret name containing the vCluster platform licenses and tokens
*/}}
{{- define "vcluster.rbac.platformSecretName" -}}
{{- dig "platform" "apiKey" "secretName" "vcluster-platform-api-key" .Values.external | quote -}}
{{- end -}}
{{- define "vcluster.rbac.platformRoleName" -}}
{{- printf "vc-%s-v-%s-platform-role" .Release.Name .Release.Namespace | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- define "vcluster.rbac.platformRoleBindingName" -}}
{{- printf "vc-%s-v-%s-platform-role-binding" .Release.Name .Release.Namespace | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Cluster role rules needed for fromHost sync (containing namespaces + configmaps/secret/other core resources)
*/}}
{{- define "vcluster.rbac.rulesForFromHostSyncerForGivenCoreResource" -}}
{{- $root := index . 0 -}}
{{- $mappings := index . 1 -}}
{{- $kind := index . 2 -}}
{{- $enabled := index . 3 -}}
{{- if and $enabled $mappings -}}
{{- $namespaces := list -}}
{{- $objNames := list -}}
{{- $addResourceNames := true -}}
{{- range $key, $val := $mappings -}}
{{- $sourceNs := splitList "/" $key | first -}}
{{- $sourceObjName := splitList "/" $key | last }}
{{- if eq $sourceNs "" -}}
{{- $namespaces = append $namespaces (quote $root.Release.Namespace) -}}
{{- else -}}
{{- $namespaces = append $namespaces (quote $sourceNs) -}}
{{- end -}}
{{- if eq $sourceObjName "*" -}}
{{- $addResourceNames = false -}}
{{- else -}}
{{- $objNames = append $objNames (quote $sourceObjName) -}}
{{- end -}}
{{- end -}}
{{- $objList := $objNames | uniq | sortAlpha -}}
{{- $nsList := $namespaces | uniq | sortAlpha -}}
- apiGroups: [""]
resources: [ "namespaces" ]
resourceNames: [ {{ join "," $nsList }} ]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: [ {{ $kind | quote }} ]
verbs: ["list", "watch"]
- apiGroups: [""]
resources: [ {{ $kind | quote }} ]
verbs: ["get"]
{{- if $addResourceNames }}
resourceNames: [ {{ join "," $objList }} ]
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,4 @@
{{- define "vcluster.vClusterConfigHash" -}}
{{- $vals := deepCopy .Values -}}
{{- (unset $vals.privateNodes "nodePools") | toYaml | b64enc | sha256sum | quote -}}
{{- end -}}

View File

@@ -0,0 +1,148 @@
{{- if (include "vcluster.createClusterRole" . ) -}}
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: {{ template "vcluster.clusterRoleName" . }}
labels:
app: vcluster
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
{{- if .Values.controlPlane.advanced.globalMetadata.annotations }}
annotations:
{{ toYaml .Values.controlPlane.advanced.globalMetadata.annotations | indent 4 }}
{{- end }}
rules:
{{- if .Values.rbac.clusterRole.overwriteRules }}
{{ toYaml .Values.rbac.clusterRole.overwriteRules | indent 2 }}
{{- else }}
{{- if .Values.pro }}
- apiGroups: ["cluster.loft.sh", "storage.loft.sh"]
resources: ["features", "virtualclusters"]
verbs: ["get", "list", "watch"]
- apiGroups: ["management.loft.sh"]
resources: ["virtualclusterinstances"]
verbs: ["get"]
{{- end }}
{{- if or .Values.pro .Values.sync.fromHost.nodes.enabled }}
- apiGroups: [""]
resources: ["pods", "nodes", "nodes/status", "nodes/metrics", "nodes/stats", "nodes/proxy"]
verbs: ["get", "watch", "list"]
{{- end }}
{{- if .Values.experimental.isolatedControlPlane.enabled }}
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "watch", "list"]
{{- end }}
{{- if and .Values.sync.fromHost.nodes.enabled .Values.sync.fromHost.nodes.syncBackChanges }}
- apiGroups: [""]
resources: ["nodes", "nodes/status"]
verbs: ["update", "patch"]
{{- end }}
{{- if or
(and (eq (include "vcluster.distro" .) "k8s") .Values.controlPlane.distro.k8s.scheduler.enabled)
.Values.controlPlane.advanced.virtualScheduler.enabled
.Values.sync.toHost.pods.hybridScheduling.enabled
}}
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses", "csinodes", "csidrivers", "csistoragecapacities"]
verbs: ["get", "watch", "list"]
{{- end }}
{{- if eq (toString .Values.sync.fromHost.storageClasses.enabled) "true" }}
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "watch", "list"]
{{- end }}
{{- if eq (toString .Values.sync.fromHost.csiNodes.enabled) "true" }}
- apiGroups: ["storage.k8s.io"]
resources: ["csinodes"]
verbs: ["get", "watch", "list"]
{{- end }}
{{- if eq (toString .Values.sync.fromHost.csiDrivers.enabled) "true" }}
- apiGroups: ["storage.k8s.io"]
resources: ["csidrivers"]
verbs: ["get", "watch", "list"]
{{- end }}
{{- if eq (toString .Values.sync.fromHost.csiStorageCapacities.enabled) "true" }}
- apiGroups: ["storage.k8s.io"]
resources: ["csistoragecapacities"]
verbs: ["get", "watch", "list"]
{{- end }}
{{- if .Values.sync.toHost.persistentVolumes.enabled }}
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["create", "delete", "patch", "update", "get", "watch", "list"]
{{- end }}
{{- if .Values.sync.fromHost.ingressClasses.enabled }}
- apiGroups: ["networking.k8s.io"]
resources: ["ingressclasses"]
verbs: ["get", "watch", "list"]
{{- end }}
{{- if .Values.sync.fromHost.runtimeClasses.enabled }}
- apiGroups: ["node.k8s.io"]
resources: ["runtimeclasses"]
verbs: ["get", "watch", "list"]
{{- end }}
{{- if .Values.sync.toHost.storageClasses.enabled }}
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["create", "delete", "patch", "update", "get", "watch", "list"]
{{- end }}
{{- if or .Values.sync.toHost.priorityClasses.enabled .Values.sync.fromHost.priorityClasses.enabled }}
- apiGroups: ["scheduling.k8s.io"]
resources: ["priorityclasses"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]
{{- end }}
{{- if .Values.sync.fromHost.volumeSnapshotClasses.enabled }}
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotclasses"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.sync.toHost.volumeSnapshotContents.enabled }}
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotcontents"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]
{{- end }}
{{- if .Values.networking.replicateServices.fromHost }}
- apiGroups: [""]
resources: ["services", "endpoints"]
verbs: ["get", "watch", "list"]
{{- end }}
{{- if .Values.sync.toHost.namespaces.enabled }}
- apiGroups: [""]
resources: ["namespaces", "serviceaccounts"]
verbs: ["create", "delete", "patch", "update", "get", "watch", "list"]
{{- end }}
{{- if (and .Values.integrations.metricsServer.enabled .Values.integrations.metricsServer.nodes) }}
- apiGroups: ["metrics.k8s.io"]
resources: ["nodes"]
verbs: ["get", "list"]
{{- end }}
{{- if or (and .Values.integrations.kubeVirt.enabled .Values.integrations.kubeVirt.webhook.enabled) (and .Values.integrations.externalSecrets.enabled .Values.integrations.externalSecrets.webhook.enabled ) }}
- apiGroups: ["admissionregistration.k8s.io"]
resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if or .Values.integrations.kubeVirt.enabled .Values.integrations.externalSecrets.enabled .Values.integrations.certManager.enabled .Values.sync.toHost.customResources .Values.sync.fromHost.customResources .Values.integrations.istio.enabled }}
- apiGroups: ["apiextensions.k8s.io"]
resources: ["customresourcedefinitions"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if and .Values.integrations.externalSecrets.enabled (or .Values.integrations.externalSecrets.sync.clusterStores.enabled .Values.integrations.externalSecrets.sync.fromHost.clusterStores.enabled) }}
- apiGroups: ["external-secrets.io"]
resources: ["clustersecretstores"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if and .Values.integrations.certManager.enabled .Values.integrations.certManager.sync.fromHost.clusterIssuers.enabled }}
- apiGroups: ["cert-manager.io"]
resources: ["clusterissuers"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- include "vcluster.rbac.rulesForFromHostSyncerForGivenCoreResource" (list $ .Values.sync.fromHost.configMaps.mappings.byName "configmaps" .Values.sync.fromHost.configMaps.enabled ) | nindent 2 }}
{{- include "vcluster.rbac.rulesForFromHostSyncerForGivenCoreResource" (list $ .Values.sync.fromHost.secrets.mappings.byName "secrets" .Values.sync.fromHost.secrets.enabled ) | nindent 2 }}
{{- include "vcluster.customResources.clusterRoleExtraRules" . | indent 2 }}
{{- include "vcluster.plugin.clusterRoleExtraRules" . | indent 2 }}
{{- include "vcluster.generic.clusterRoleExtraRules" . | indent 2 }}
{{- include "vcluster.rbac.clusterRoleExtraRules" . | indent 2 }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,27 @@
{{- if (include "vcluster.createClusterRole" . ) -}}
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: {{ template "vcluster.clusterRoleName" . }}
labels:
app: vcluster
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
{{- if .Values.controlPlane.advanced.globalMetadata.annotations }}
annotations:
{{ toYaml .Values.controlPlane.advanced.globalMetadata.annotations | indent 4 }}
{{- end }}
subjects:
- kind: ServiceAccount
{{- if .Values.controlPlane.advanced.serviceAccount.name }}
name: {{ .Values.controlPlane.advanced.serviceAccount.name }}
{{- else }}
name: vc-{{ .Release.Name }}
{{- end }}
namespace: {{ .Release.Namespace }}
roleRef:
kind: ClusterRole
name: {{ template "vcluster.clusterRoleName" . }}
apiGroup: rbac.authorization.k8s.io
{{- end }}

View File

@@ -0,0 +1,17 @@
apiVersion: v1
kind: Secret
metadata:
name: "vc-config-{{ .Release.Name }}"
namespace: {{ .Release.Namespace }}
labels:
app: vcluster
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
{{- if .Values.controlPlane.advanced.globalMetadata.annotations }}
annotations:
{{ toYaml .Values.controlPlane.advanced.globalMetadata.annotations | indent 4 }}
{{- end }}
type: Opaque
data:
config.yaml: {{ .Values | toYaml | b64enc | quote }}

View File

@@ -0,0 +1,34 @@
{{- if not .Values.experimental.isolatedControlPlane.headless }}
{{- if or .Values.controlPlane.backingStore.etcd.deploy.enabled (include "vcluster.etcd.embedded.migrate" .) }}
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}-etcd-headless
namespace: {{ .Release.Namespace }}
labels:
app: vcluster-etcd
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
{{- $annotations := merge dict .Values.controlPlane.advanced.globalMetadata.annotations .Values.controlPlane.backingStore.etcd.deploy.headlessService.annotations }}
{{- if $annotations }}
annotations:
{{ toYaml $annotations | indent 4 }}
{{- end }}
spec:
publishNotReadyAddresses: true
ports:
- name: etcd
port: 2379
targetPort: 2379
protocol: TCP
- name: peer
port: 2380
targetPort: 2380
protocol: TCP
clusterIP: None
selector:
app: vcluster-etcd
release: "{{ .Release.Name }}"
{{- end }}
{{- end }}

View File

@@ -0,0 +1,35 @@
{{- if not .Values.experimental.isolatedControlPlane.headless }}
{{- if or .Values.controlPlane.backingStore.etcd.deploy.enabled (include "vcluster.etcd.embedded.migrate" .) }}
{{- if .Values.controlPlane.backingStore.etcd.deploy.service.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}-etcd
namespace: {{ .Release.Namespace }}
labels:
app: vcluster-etcd
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
{{- $annotations := merge dict .Values.controlPlane.advanced.globalMetadata.annotations .Values.controlPlane.backingStore.etcd.deploy.service.annotations }}
{{- if $annotations }}
annotations:
{{ toYaml $annotations | indent 4 }}
{{- end }}
spec:
type: ClusterIP
ports:
- name: etcd
port: 2379
targetPort: 2379
protocol: TCP
- name: peer
port: 2380
targetPort: 2380
protocol: TCP
selector:
app: vcluster-etcd
release: {{ .Release.Name }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,213 @@
{{- if not .Values.experimental.isolatedControlPlane.headless }}
{{- if or .Values.controlPlane.backingStore.etcd.deploy.enabled (include "vcluster.etcd.embedded.migrate" .) }}
{{- if .Values.controlPlane.backingStore.etcd.deploy.statefulSet.enabled }}
{{- $externalEtcd := .Values.controlPlane.backingStore.etcd.deploy.statefulSet }}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ .Release.Name }}-etcd
namespace: {{ .Release.Namespace }}
labels:
app: vcluster-etcd
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
{{- if $externalEtcd.labels }}
{{ toYaml $externalEtcd.labels | indent 4 }}
{{- end }}
{{- $annotations := merge dict .Values.controlPlane.advanced.globalMetadata.annotations $externalEtcd.annotations }}
{{- if $annotations }}
annotations:
{{ toYaml $annotations | indent 4 }}
{{- end }}
spec:
replicas: {{ $externalEtcd.highAvailability.replicas }}
podManagementPolicy: {{ $externalEtcd.scheduling.podManagementPolicy }}
serviceName: {{ .Release.Name }}-etcd-headless
{{- if eq $externalEtcd.persistence.volumeClaim.retentionPolicy "Delete" }}
{{- if ge (int .Capabilities.KubeVersion.Minor) 27 }}
persistentVolumeClaimRetentionPolicy:
whenDeleted: {{ $externalEtcd.persistence.volumeClaim.retentionPolicy }}
{{- end }}
{{- end }}
selector:
matchLabels:
app: vcluster-etcd
release: {{ .Release.Name }}
{{- if $externalEtcd.persistence.volumeClaimTemplates }}
volumeClaimTemplates:
{{ toYaml $externalEtcd.persistence.volumeClaimTemplates | indent 4 }}
{{- else if $externalEtcd.persistence.volumeClaim.enabled }}
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: {{ $externalEtcd.persistence.volumeClaim.accessModes }}
{{- if $externalEtcd.persistence.volumeClaim.storageClass }}
storageClassName: {{ $externalEtcd.persistence.volumeClaim.storageClass }}
{{- end }}
resources:
requests:
storage: {{ $externalEtcd.persistence.volumeClaim.size }}
{{- end }}
template:
metadata:
{{- if $externalEtcd.pods.annotations }}
annotations:
{{ toYaml $externalEtcd.pods.annotations | indent 8 }}
{{- end }}
labels:
app: vcluster-etcd
release: {{ .Release.Name }}
{{- range $k, $v := $externalEtcd.pods.labels }}
{{ $k }}: {{ $v | quote }}
{{- end }}
spec:
terminationGracePeriodSeconds: 10
{{- if $externalEtcd.scheduling.affinity }}
affinity:
{{ toYaml $externalEtcd.scheduling.affinity | indent 8 }}
{{- else }}
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
# if possible avoid scheduling more than one pod on one node
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- vcluster-etcd
- key: release
operator: In
values:
- {{ .Release.Name }}
topologyKey: "kubernetes.io/hostname"
# if possible avoid scheduling pod onto node that is in the same zone as one or more vcluster pods are running
- weight: 50
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- vcluster-etcd
- key: release
operator: In
values:
- {{ .Release.Name }}
topologyKey: topology.kubernetes.io/zone
{{- end }}
{{- if $externalEtcd.scheduling.topologySpreadConstraints }}
topologySpreadConstraints:
{{ toYaml $externalEtcd.scheduling.topologySpreadConstraints | indent 8 }}
{{- end }}
nodeSelector:
{{ toYaml $externalEtcd.scheduling.nodeSelector | indent 8 }}
tolerations:
{{ toYaml $externalEtcd.scheduling.tolerations | indent 8 }}
automountServiceAccountToken: false
{{- if .Values.controlPlane.advanced.serviceAccount.name }}
serviceAccountName: {{ .Values.controlPlane.advanced.serviceAccount.name }}
{{- else }}
serviceAccountName: vc-{{ .Release.Name }}
{{- end }}
volumes:
- name: certs
secret:
secretName: {{ .Release.Name }}-certs
{{- if $externalEtcd.persistence.addVolumes }}
{{ toYaml $externalEtcd.persistence.addVolumes | indent 8 }}
{{- end }}
{{- if not $externalEtcd.persistence.volumeClaim.enabled }}
- name: data
emptyDir: {}
{{- end }}
{{- if $externalEtcd.scheduling.priorityClassName }}
priorityClassName: {{ $externalEtcd.scheduling.priorityClassName }}
{{- end }}
{{- if $externalEtcd.security.podSecurityContext }}
securityContext:
{{ toYaml $externalEtcd.security.podSecurityContext | indent 8 }}
{{- end }}
enableServiceLinks: {{ .Values.controlPlane.backingStore.etcd.deploy.statefulSet.enableServiceLinks }}
containers:
- name: etcd
image: '{{ include "vcluster.image" (dict "defaultImageRegistry" .Values.controlPlane.advanced.defaultImageRegistry "registry" $externalEtcd.image.registry "repository" $externalEtcd.image.repository "tag" $externalEtcd.image.tag) }}'
command:
- etcd
- '--cert-file=/run/config/pki/etcd-server.crt'
- '--client-cert-auth=true'
- '--data-dir=/var/lib/etcd'
- '--advertise-client-urls=https://$(NAME).{{ .Release.Name }}-etcd-headless.{{ .Release.Namespace }}:2379'
- '--initial-advertise-peer-urls=https://$(NAME).{{ .Release.Name }}-etcd-headless.{{ .Release.Namespace }}:2380'
{{- $releaseName := .Release.Name -}}
{{- $releaseNamespace := .Release.Namespace }}
- '--initial-cluster={{ range $index := untilStep 0 (int $externalEtcd.highAvailability.replicas) 1 }}{{ if (ne (int $index) 0) }},{{ end }}{{ $releaseName }}-etcd-{{ $index }}=https://{{ $releaseName }}-etcd-{{ $index }}.{{ $releaseName }}-etcd-headless.{{ $releaseNamespace }}:2380{{ end }}'
- '--initial-cluster-token={{ .Release.Name }}'
- '--initial-cluster-state=new'
- '--listen-client-urls=https://0.0.0.0:2379'
- '--listen-metrics-urls=http://0.0.0.0:2381'
- '--listen-peer-urls=https://0.0.0.0:2380'
- '--key-file=/run/config/pki/etcd-server.key'
- '--name=$(NAME)'
- '--peer-cert-file=/run/config/pki/etcd-peer.crt'
- '--peer-client-cert-auth=true'
- '--peer-key-file=/run/config/pki/etcd-peer.key'
- '--peer-trusted-ca-file=/run/config/pki/etcd-ca.crt'
- '--snapshot-count=10000'
- '--trusted-ca-file=/run/config/pki/etcd-ca.crt'
{{- range $f := $externalEtcd.extraArgs }}
- {{ $f | quote }}
{{- end }}
{{- if $externalEtcd.security.containerSecurityContext }}
securityContext:
{{ toYaml $externalEtcd.security.containerSecurityContext | indent 10 }}
{{- end }}
env:
- name: NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
{{- if $externalEtcd.env }}
{{ toYaml $externalEtcd.env | indent 10 }}
{{- end }}
volumeMounts:
- name: data
mountPath: /var/lib/etcd
- mountPath: /run/config/pki
name: certs
readOnly: true
{{- if $externalEtcd.persistence.addVolumeMounts }}
{{ toYaml $externalEtcd.persistence.addVolumeMounts | indent 10 }}
{{- end }}
resources:
{{ toYaml $externalEtcd.resources | indent 10 }}
livenessProbe:
httpGet:
path: /health
port: 2381
scheme: HTTP
initialDelaySeconds: 10
timeoutSeconds: 15
periodSeconds: 10
successThreshold: 1
failureThreshold: 8
startupProbe:
httpGet:
path: /health
port: 2381
scheme: HTTP
initialDelaySeconds: 10
timeoutSeconds: 15
periodSeconds: 10
successThreshold: 1
failureThreshold: 24
{{- if $externalEtcd.imagePullPolicy }}
imagePullPolicy: {{ $externalEtcd.imagePullPolicy }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,43 @@
{{- if not .Values.experimental.isolatedControlPlane.headless }}
{{- if eq (include "vcluster.kind" .) "StatefulSet" }}
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}-headless
namespace: {{ .Release.Namespace }}
labels:
app: vcluster
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
{{- if .Values.controlPlane.advanced.headlessService.labels }}
{{ toYaml .Values.controlPlane.advanced.headlessService.labels | indent 4 }}
{{- end }}
{{- $annotations := merge dict .Values.controlPlane.advanced.headlessService.annotations .Values.controlPlane.advanced.globalMetadata.annotations }}
{{- if $annotations }}
annotations:
{{ toYaml $annotations | indent 4 }}
{{- end }}
spec:
publishNotReadyAddresses: true
ports:
- name: https
port: 443
targetPort: 8443
protocol: TCP
{{- if .Values.controlPlane.backingStore.etcd.embedded.enabled }}
- name: etcd
port: 2379
targetPort: 2379
protocol: TCP
- name: peer
port: 2380
targetPort: 2380
protocol: TCP
{{- end }}
clusterIP: None
selector:
app: vcluster
release: "{{ .Release.Name }}"
{{- end }}
{{- end }}

View File

@@ -0,0 +1,37 @@
{{- if .Values.controlPlane.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
{{- $annotations := merge dict .Values.controlPlane.ingress.annotations .Values.controlPlane.advanced.globalMetadata.annotations }}
{{- if $annotations }}
annotations:
{{- toYaml $annotations | nindent 4 }}
{{- end }}
name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
labels:
app: vcluster
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
{{- if .Values.controlPlane.ingress.labels }}
{{ toYaml .Values.controlPlane.ingress.labels | indent 4 }}
{{- end }}
spec:
{{- with .Values.controlPlane.ingress.spec }}
{{- tpl (toYaml .) $ | nindent 2 }}
{{- end }}
{{- if not .Values.controlPlane.ingress.spec.rules }}
rules:
- host: {{ .Values.controlPlane.ingress.host | quote }}
http:
paths:
- backend:
service:
name: {{ .Release.Name }}
port:
name: https
path: /
pathType: {{ .Values.controlPlane.ingress.pathType }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,49 @@
{{- if or (eq (toString .Values.policies.limitRange.enabled) "true") (eq (toString .Values.policies.resourceQuota.enabled) "true") }}
{{- if not (eq (toString .Values.policies.limitRange.enabled) "false") }}
apiVersion: v1
kind: LimitRange
metadata:
name: vc-{{ .Release.Name }}
{{- if .Values.experimental.syncSettings.targetNamespace }}
namespace: {{ .Values.experimental.syncSettings.targetNamespace }}
{{- else }}
namespace: {{ .Release.Namespace }}
{{- end }}
labels:
app: vcluster
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
{{- if .Values.policies.limitRange.labels }}
{{ toYaml .Values.policies.limitRange.labels | indent 4 }}
{{- end }}
{{- $annotations := merge dict .Values.controlPlane.advanced.globalMetadata.annotations .Values.policies.limitRange.annotations }}
{{- if $annotations }}
annotations:
{{ toYaml $annotations | indent 4 }}
{{- end }}
spec:
limits:
- default:
{{- range $key, $val := .Values.policies.limitRange.default }}
{{ $key }}: {{ $val | quote }}
{{- end }}
defaultRequest:
{{- range $key, $val := .Values.policies.limitRange.defaultRequest }}
{{ $key }}: {{ $val | quote }}
{{- end }}
{{- if .Values.policies.limitRange.min }}
min:
{{- range $key, $val := .Values.policies.limitRange.min }}
{{ $key }}: {{ $val | quote }}
{{- end }}
{{- end }}
{{- if .Values.policies.limitRange.max }}
max:
{{- range $key, $val := .Values.policies.limitRange.max }}
{{ $key }}: {{ $val | quote }}
{{- end }}
{{- end }}
type: Container
{{- end }}
{{- end }}

View File

@@ -0,0 +1,7 @@
{{- if .Values.experimental.deploy.host.manifests }}
{{ .Values.experimental.deploy.host.manifests }}
{{- end }}
{{- if .Values.experimental.deploy.host.manifestsTemplate }}
---
{{ tpl .Values.experimental.deploy.host.manifestsTemplate . }}
{{- end }}

View File

@@ -0,0 +1,112 @@
{{- if .Values.policies.networkPolicy.enabled }}
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: vc-work-{{ .Release.Name }}
{{- if .Values.experimental.syncSettings.targetNamespace }}
namespace: {{ .Values.experimental.syncSettings.targetNamespace }}
{{- else }}
namespace: {{ .Release.Namespace }}
{{- end }}
labels:
app: vcluster
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
{{- if .Values.policies.networkPolicy.labels }}
{{ toYaml .Values.policies.networkPolicy.labels | indent 4 }}
{{- end }}
{{- $annotations := merge dict .Values.controlPlane.advanced.globalMetadata.annotations .Values.policies.networkPolicy.annotations }}
{{- if $annotations }}
annotations:
{{ toYaml $annotations | indent 4 }}
{{- end }}
spec:
podSelector:
matchLabels:
vcluster.loft.sh/managed-by: {{ .Release.Name }}
egress:
# Allows outgoing connections to the vcluster control plane
- ports:
- port: 443
- port: 8443
to:
- podSelector:
matchLabels:
release: {{ .Release.Name }}
# Allows outgoing connections to DNS server
- ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP
# Allows outgoing connections to the internet or
# other vcluster workloads
- to:
- podSelector:
matchLabels:
vcluster.loft.sh/managed-by: {{ .Release.Name }}
- ipBlock:
cidr: {{ .Values.policies.networkPolicy.outgoingConnections.ipBlock.cidr }}
except:
{{- range .Values.policies.networkPolicy.outgoingConnections.ipBlock.except }}
- {{ . }}
{{- end }}
{{- if .Values.policies.networkPolicy.extraWorkloadRules }}
{{ toYaml .Values.policies.networkPolicy.extraWorkloadRules | indent 4 }}
{{- end }}
policyTypes:
- Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: vc-cp-{{ .Release.Name }}
namespace: {{ .Release.Namespace }}
labels:
app: vcluster
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
{{- if .Values.policies.networkPolicy.labels }}
{{ toYaml .Values.policies.networkPolicy.labels | indent 4 }}
{{- end }}
{{- $annotations := merge dict .Values.controlPlane.advanced.globalMetadata.annotations .Values.policies.networkPolicy.annotations }}
{{- if $annotations }}
annotations:
{{ toYaml $annotations | indent 4 }}
{{- end }}
spec:
podSelector:
matchLabels:
release: {{ .Release.Name }}
egress:
# Allows outgoing connections to all pods with
# port 443, 8443 or 6443. This is needed for host Kubernetes
# access
- ports:
- port: 443
- port: 8443
- port: 6443
# Allows outgoing connections to all vcluster workloads
# or kube system dns server
- to:
- podSelector: {}
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: 'kube-system'
podSelector:
matchLabels:
k8s-app: kube-dns
{{- if .Values.policies.networkPolicy.outgoingConnections.platform }}
- podSelector:
matchLabels:
app: loft
namespaceSelector: {}
{{- end }}
{{- if .Values.policies.networkPolicy.extraControlPlaneRules }}
{{ toYaml .Values.policies.networkPolicy.extraControlPlaneRules | indent 4 }}
{{- end }}
policyTypes:
- Egress
{{- end }}

View File

@@ -0,0 +1,31 @@
{{- if include "vcluster.rbac.createPlatformSecretRole" . }}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "vcluster.rbac.platformRoleName" . }}
namespace: {{ include "vcluster.rbac.platformSecretNamespace" .}}
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
resourceNames:
- {{ include "vcluster.rbac.platformSecretName" . }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "vcluster.rbac.platformRoleBindingName" . }}
namespace: {{ include "vcluster.rbac.platformSecretNamespace" .}}
subjects:
- kind: ServiceAccount
{{- if .Values.controlPlane.advanced.serviceAccount.name }}
name: {{ .Values.controlPlane.advanced.serviceAccount.name }}
{{- else }}
name: vc-{{ .Release.Name }}
{{- end }}
namespace: {{ .Release.Namespace }}
roleRef:
kind: Role
name: {{ include "vcluster.rbac.platformRoleName" . }}
apiGroup: rbac.authorization.k8s.io
{{- end }}

View File

@@ -0,0 +1,44 @@
{{- if or (eq (toString .Values.policies.resourceQuota.enabled) "true") (eq (toString .Values.policies.limitRange.enabled) "true") }}
{{- if not (eq (toString .Values.policies.resourceQuota.enabled) "false") }}
apiVersion: v1
kind: ResourceQuota
metadata:
name: vc-{{ .Release.Name }}
{{- if .Values.experimental.syncSettings.targetNamespace }}
namespace: {{ .Values.experimental.syncSettings.targetNamespace }}
{{- else }}
namespace: {{ .Release.Namespace }}
{{- end }}
labels:
app: vcluster
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
{{- if .Values.policies.resourceQuota.labels }}
{{ toYaml .Values.policies.resourceQuota.labels | indent 4 }}
{{- end }}
{{- $annotations := merge dict .Values.controlPlane.advanced.globalMetadata.annotations .Values.policies.resourceQuota.annotations }}
{{- if $annotations }}
annotations:
{{ toYaml $annotations | indent 4 }}
{{- end }}
spec:
{{- if .Values.policies.resourceQuota.quota }}
hard:
{{- range $key, $val := .Values.policies.resourceQuota.quota }}
{{ $key }}: {{ $val | quote }}
{{- end }}
{{- end }}
{{- if .Values.policies.resourceQuota.scopeSelector.matchExpressions }}
scopeSelector:
matchExpressions:
{{- toYaml .Values.policies.resourceQuota.scopeSelector.matchExpressions | nindent 6 }}
{{- end }}
{{- if .Values.policies.resourceQuota.scopes }}
scopes:
{{- toYaml .Values.policies.resourceQuota.scopes | nindent 4 }}
{{- end}}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,141 @@
{{- if .Values.rbac.role.enabled }}
{{- if .Values.sync.toHost.namespaces.enabled }}
kind: ClusterRole
{{- else -}}
kind: Role
{{- end }}
apiVersion: rbac.authorization.k8s.io/v1
metadata:
{{- if .Values.sync.toHost.namespaces.enabled }}
name: {{ template "vcluster.clusterRoleNameMultinamespace" . }}
{{- else }}
name: vc-{{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
labels:
app: vcluster
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
{{- if .Values.controlPlane.advanced.globalMetadata.annotations }}
annotations:
{{ toYaml .Values.controlPlane.advanced.globalMetadata.annotations | indent 4 }}
{{- end }}
rules:
{{- if .Values.rbac.role.overwriteRules }}
{{ toYaml .Values.rbac.role.overwriteRules | indent 2 }}
{{- else }}
{{- if .Values.privateNodes.enabled}}
- apiGroups: [""]
resources: ["secrets", "configmaps"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]
- apiGroups: [""]
resources: ["services", "pods", "persistentvolumeclaims"]
verbs: ["get", "list", "watch"]
{{- else }}
- apiGroups: [""]
resources: ["configmaps", "secrets", "services", "pods", "pods/attach", "pods/portforward", "pods/exec", "persistentvolumeclaims"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]
- apiGroups: [""]
resources: ["pods/status", "pods/ephemeralcontainers"]
verbs: ["patch", "update"]
{{- end }}
- apiGroups: ["apps"]
resources: ["statefulsets", "replicasets", "deployments"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["endpoints", "events", "pods/log"]
verbs: ["get", "list", "watch"]
{{- if or .Values.sync.toHost.endpoints.enabled .Values.experimental.isolatedControlPlane.headless }}
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["create", "delete", "patch", "update"]
{{- end }}
{{- if or .Values.privateNodes.enabled (gt (int .Values.controlPlane.statefulSet.highAvailability.replicas) 1) }}
- apiGroups: ["coordination.k8s.io"]
resources: ["leases"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]
{{- end }}
{{- if (and .Values.integrations.metricsServer.enabled .Values.integrations.metricsServer.pods) }}
- apiGroups: ["metrics.k8s.io"]
resources: ["pods"]
verbs: ["get", "list"]
{{- end }}
{{- if .Values.sync.toHost.ingresses.enabled}}
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]
{{- end }}
{{- if .Values.sync.toHost.networkPolicies.enabled }}
- apiGroups: ["networking.k8s.io"]
resources: ["networkpolicies"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]
{{- end }}
{{- if .Values.sync.toHost.volumeSnapshots.enabled }}
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshots"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]
{{- end }}
{{- if .Values.sync.toHost.serviceAccounts.enabled }}
- apiGroups: [""]
resources: ["serviceaccounts"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]
{{- end }}
{{- if .Values.sync.toHost.podDisruptionBudgets.enabled }}
- apiGroups: ["policy"]
resources: ["poddisruptionbudgets"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]
{{- end }}
{{- if .Values.integrations.kubeVirt.enabled }}
- apiGroups: ["subresources.kubevirt.io"]
resources: ["*"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]
- apiGroups: ["pool.kubevirt.io"]
resources: ["virtualmachinepools", "virtualmachinepools/status"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]
- apiGroups: ["clone.kubevirt.io"]
resources: ["virtualmachineclones", "virtualmachineclones/status"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]
- apiGroups: ["cdi.kubevirt.io"]
resources: ["datavolumes", "datavolumes/status"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]
- apiGroups: ["kubevirt.io"]
resources: ["virtualmachines", "virtualmachines/status", "virtualmachineinstances", "virtualmachineinstances/status", "virtualmachineinstancemigrations", "virtualmachineinstancemigrations/status"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]
{{- end }}
{{- if .Values.integrations.externalSecrets.enabled }}
- apiGroups: ["external-secrets.io"]
resources: ["externalsecrets"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]
{{- if or .Values.integrations.externalSecrets.sync.stores.enabled .Values.integrations.externalSecrets.sync.toHost.stores.enabled }}
- apiGroups: ["external-secrets.io"]
resources: ["secretstores"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]
{{- end }}
{{- end }}
{{- if .Values.integrations.certManager.enabled }}
{{- if .Values.integrations.certManager.sync.toHost.certificates.enabled }}
- apiGroups: ["cert-manager.io"]
resources: ["certificates"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]
{{- end }}
{{- if .Values.integrations.certManager.sync.toHost.issuers.enabled }}
- apiGroups: ["cert-manager.io"]
resources: ["issuers"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]
{{- end }}
{{- end }}
{{- if .Values.integrations.istio.enabled }}
- apiGroups: [ "networking.istio.io" ]
resources: [ "destinationrules", "gateways", "serviceentries", "virtualservices" ]
verbs: [ "create", "delete", "patch", "update", "get", "list", "watch" ]
- apiGroups: [ "gateway.networking.k8s.io" ]
resources: [ "referencegrants" ]
verbs: [ "create", "delete", "patch", "update", "get", "list", "watch" ]
{{- end }}
{{- include "vcluster.customResources.roleExtraRules" . | indent 2 }}
{{- include "vcluster.plugin.roleExtraRules" . | indent 2 }}
{{- include "vcluster.generic.roleExtraRules" . | indent 2 }}
{{- include "vcluster.rbac.roleExtraRules" . | indent 2 }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,41 @@
{{- if .Values.rbac.role.enabled }}
{{- if .Values.sync.toHost.namespaces.enabled}}
kind: ClusterRoleBinding
{{- else -}}
kind: RoleBinding
{{- end }}
apiVersion: rbac.authorization.k8s.io/v1
metadata:
{{- if .Values.sync.toHost.namespaces.enabled }}
name: {{ template "vcluster.clusterRoleNameMultinamespace" . }}
{{- else }}
name: vc-{{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
labels:
app: vcluster
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
{{- if .Values.controlPlane.advanced.globalMetadata.annotations }}
annotations:
{{ toYaml .Values.controlPlane.advanced.globalMetadata.annotations | indent 4 }}
{{- end }}
subjects:
- kind: ServiceAccount
{{- if .Values.controlPlane.advanced.serviceAccount.name }}
name: {{ .Values.controlPlane.advanced.serviceAccount.name }}
{{- else }}
name: vc-{{ .Release.Name }}
{{- end }}
namespace: {{ .Release.Namespace }}
roleRef:
{{- if .Values.sync.toHost.namespaces.enabled }}
kind: ClusterRole
name: {{ template "vcluster.clusterRoleNameMultinamespace" . }}
{{- else }}
kind: Role
name: vc-{{ .Release.Name }}
{{- end }}
apiGroup: rbac.authorization.k8s.io
{{- end }}

View File

@@ -0,0 +1,95 @@
{{- if .Values.controlPlane.serviceMonitor.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: vc-{{ .Release.Name }}
namespace: {{ .Release.Namespace }}
labels:
app: vcluster
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
{{- if or (not .Values.controlPlane.serviceMonitor.labels) (not (hasKey .Values.controlPlane.serviceMonitor.labels "release")) }}
release: "{{ .Release.Name }}"
{{- end}}
heritage: "{{ .Release.Service }}"
{{- if .Values.controlPlane.serviceMonitor.labels }}
{{ toYaml .Values.controlPlane.serviceMonitor.labels | indent 4 }}
{{- end }}
{{- $annotations := merge dict .Values.controlPlane.serviceMonitor.annotations .Values.controlPlane.advanced.globalMetadata.annotations }}
{{- if $annotations }}
annotations:
{{ toYaml $annotations | indent 4 }}
{{- end }}
spec:
selector:
matchLabels:
app: vcluster
release: "{{ .Release.Name }}"
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
heritage: "{{ .Release.Service }}"
vcluster.loft.sh/service: "true"
endpoints:
- interval: 30s
port: https
path: /metrics
scheme: https
relabelings:
- targetLabel: endpoint
replacement: "apiserver"
tlsConfig:
ca:
secret:
name: vc-{{ .Release.Name }}
key: certificate-authority
cert:
secret:
name: vc-{{ .Release.Name }}
key: client-certificate
keySecret:
name: vc-{{ .Release.Name }}
key: client-key
{{- if eq (include "vcluster.distro" .) "k8s" }}
- interval: 30s
port: https
path: /controller-manager/metrics
scheme: https
relabelings:
- targetLabel: endpoint
replacement: "controller-manager"
tlsConfig:
ca:
secret:
name: vc-{{ .Release.Name }}
key: certificate-authority
cert:
secret:
name: vc-{{ .Release.Name }}
key: client-certificate
keySecret:
name: vc-{{ .Release.Name }}
key: client-key
{{- if or
(and (eq (include "vcluster.distro" .) "k8s") .Values.controlPlane.distro.k8s.scheduler.enabled)
.Values.controlPlane.advanced.virtualScheduler.enabled
}}
- interval: 30s
port: https
path: /scheduler/metrics
scheme: https
relabelings:
- targetLabel: endpoint
replacement: "scheduler"
tlsConfig:
ca:
secret:
name: vc-{{ .Release.Name }}
key: certificate-authority
cert:
secret:
name: vc-{{ .Release.Name }}
key: client-certificate
keySecret:
name: vc-{{ .Release.Name }}
key: client-key
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,63 @@
{{- $platform_svc_exists := lookup "v1" "Service" .Release.Namespace "loft" }}
{{- if $platform_svc_exists }}
{{- fail (printf "a vCluster platform installation exists in the namespace '%s'. Aborting install" .Release.Namespace) }}
{{- else if .Values.controlPlane.service.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
labels:
app: vcluster
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
vcluster.loft.sh/service: "true"
{{- if .Values.controlPlane.service.labels }}
{{ toYaml .Values.controlPlane.service.labels | indent 4 }}
{{- end }}
{{- $annotations := merge dict .Values.controlPlane.advanced.globalMetadata.annotations .Values.controlPlane.service.annotations }}
{{- if $annotations }}
annotations:
{{ toYaml $annotations | indent 4 }}
{{- end }}
spec:
{{ toYaml .Values.controlPlane.service.spec | indent 2 }}
{{- if not .Values.controlPlane.service.spec.ports }}
ports:
- name: https
port: 443
{{- if not .Values.experimental.isolatedControlPlane.headless }}
targetPort: 8443
{{- end }}
nodePort: {{ .Values.controlPlane.service.httpsNodePort }}
protocol: TCP
{{- if .Values.privateNodes.enabled }}
{{- if .Values.controlPlane.advanced.konnectivity.server.enabled }}
- name: konnectivity
port: 8132
protocol: TCP
{{- end }}
{{- end }}
{{- if .Values.integrations.istio.enabled }}
- name: wake-http
port: 9090
nodePort: {{ .Values.controlPlane.service.httpsNodePort }}
protocol: TCP
{{- end }}
{{- if and .Values.networking.advanced.proxyKubelets.byHostname (not (eq .Values.controlPlane.service.spec.type "LoadBalancer")) }}
- name: kubelet
port: 10250
{{- if not .Values.experimental.isolatedControlPlane.headless }}
targetPort: 8443
{{- end }}
nodePort: {{ .Values.controlPlane.service.kubeletNodePort }}
protocol: TCP
{{- end }}
{{- end }}
{{- if and (not .Values.controlPlane.service.spec.selector) (not .Values.experimental.isolatedControlPlane.headless) }}
selector:
app: vcluster
release: {{ .Release.Name }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,28 @@
{{- if .Values.controlPlane.advanced.serviceAccount.enabled }}
apiVersion: v1
kind: ServiceAccount
metadata:
{{- if .Values.controlPlane.advanced.serviceAccount.name }}
name: {{ .Values.controlPlane.advanced.serviceAccount.name | quote }}
{{- else }}
name: vc-{{ .Release.Name }}
{{- end }}
namespace: {{ .Release.Namespace }}
labels:
app: vcluster
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
{{- if .Values.controlPlane.advanced.serviceAccount.labels }}
{{ toYaml .Values.controlPlane.advanced.serviceAccount.labels | indent 4 }}
{{- end }}
{{- $annotations := merge dict .Values.controlPlane.advanced.serviceAccount.annotations .Values.controlPlane.advanced.globalMetadata.annotations }}
{{- if $annotations }}
annotations:
{{- toYaml $annotations | nindent 4 }}
{{- end }}
{{- if .Values.controlPlane.advanced.serviceAccount.imagePullSecrets }}
imagePullSecrets:
{{ toYaml .Values.controlPlane.advanced.serviceAccount.imagePullSecrets | indent 2 }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,230 @@
{{- include "vcluster.exportKubeConfig.validate" . }}
{{- if not .Values.experimental.isolatedControlPlane.headless }}
apiVersion: apps/v1
kind: {{ include "vcluster.kind" . }}
metadata:
name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
labels:
app: vcluster
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: {{ .Release.Name }}
heritage: "{{ .Release.Service }}"
{{- if .Values.controlPlane.statefulSet.labels }}
{{ toYaml .Values.controlPlane.statefulSet.labels | indent 4 }}
{{- end }}
{{- $annotations := merge dict .Values.controlPlane.statefulSet.annotations .Values.controlPlane.advanced.globalMetadata.annotations }}
{{- if $annotations }}
annotations:
{{ toYaml $annotations | indent 4 }}
{{- end }}
spec:
selector:
matchLabels:
app: vcluster
release: {{ .Release.Name | quote }}
{{- if eq (include "vcluster.kind" .) "StatefulSet" }}
{{- if ge (int .Capabilities.KubeVersion.Minor) 27 }}
persistentVolumeClaimRetentionPolicy:
whenDeleted: {{ .Values.controlPlane.statefulSet.persistence.volumeClaim.retentionPolicy }}
{{- end }}
serviceName: {{ .Release.Name }}-headless
podManagementPolicy: {{ .Values.controlPlane.statefulSet.scheduling.podManagementPolicy }}
{{ include "vcluster.persistence" . | indent 2 }}
{{- else }}
strategy:
rollingUpdate:
maxSurge: 1
{{- if (eq (int .Values.controlPlane.statefulSet.highAvailability.replicas) 1) }}
maxUnavailable: 0
{{- else }}
maxUnavailable: 1
{{- end }}
type: RollingUpdate
{{- end }}
replicas: {{ .Values.controlPlane.statefulSet.highAvailability.replicas }}
template:
metadata:
annotations:
vClusterConfigHash: {{ include "vcluster.vClusterConfigHash" . }}
{{- if .Values.controlPlane.statefulSet.pods.annotations }}
{{ toYaml .Values.controlPlane.statefulSet.pods.annotations | indent 8 }}
{{- end }}
labels:
app: vcluster
release: {{ .Release.Name }}
{{- if .Values.controlPlane.statefulSet.pods.labels }}
{{ toYaml .Values.controlPlane.statefulSet.pods.labels | indent 8 }}
{{- end }}
spec:
terminationGracePeriodSeconds: 10
{{- if .Values.controlPlane.statefulSet.scheduling.priorityClassName }}
priorityClassName: {{ .Values.controlPlane.statefulSet.scheduling.priorityClassName }}
{{- end }}
{{- if .Values.controlPlane.statefulSet.security.podSecurityContext }}
securityContext:
{{ toYaml .Values.controlPlane.statefulSet.security.podSecurityContext | indent 8 }}
{{- end }}
{{- if .Values.controlPlane.statefulSet.scheduling.nodeSelector }}
nodeSelector:
{{ toYaml .Values.controlPlane.statefulSet.scheduling.nodeSelector | indent 8 }}
{{- end }}
{{- if .Values.controlPlane.statefulSet.scheduling.affinity }}
affinity:
{{ toYaml .Values.controlPlane.statefulSet.scheduling.affinity | indent 8 }}
{{- end }}
{{- if .Values.controlPlane.statefulSet.scheduling.topologySpreadConstraints }}
topologySpreadConstraints:
{{ toYaml .Values.controlPlane.statefulSet.scheduling.topologySpreadConstraints | indent 8 }}
{{- end }}
{{- if .Values.controlPlane.statefulSet.scheduling.tolerations }}
tolerations:
{{ toYaml .Values.controlPlane.statefulSet.scheduling.tolerations | indent 8 }}
{{- end }}
{{- if .Values.controlPlane.statefulSet.scheduling.priorityClassName }}
priorityClassName: {{ .Values.controlPlane.statefulSet.scheduling.priorityClassName }}
{{- end }}
{{- if .Values.controlPlane.statefulSet.dnsPolicy }}
dnsPolicy: {{ .Values.controlPlane.statefulSet.dnsPolicy }}
{{- end }}
{{- if .Values.controlPlane.statefulSet.dnsConfig }}
dnsConfig:
{{ toYaml .Values.controlPlane.statefulSet.dnsConfig | indent 8 }}
{{- end }}
{{- if .Values.controlPlane.advanced.serviceAccount.name }}
serviceAccountName: {{ .Values.controlPlane.advanced.serviceAccount.name }}
{{- else }}
serviceAccountName: vc-{{ .Release.Name }}
{{- end }}
volumes:
{{- include "vcluster.plugins.volumes" . | indent 8 }}
- name: helm-cache
emptyDir: {}
{{ toYaml .Values.controlPlane.statefulSet.persistence.binariesVolume | indent 8 }}
- name: tmp
emptyDir: {}
- name: certs
emptyDir: {}
{{- if eq (include "vcluster.distro" .) "k3s" }}
- name: k3s-config
emptyDir: {}
{{- end }}
- name: vcluster-config
secret:
secretName: vc-config-{{ .Release.Name }}
{{- if .Values.controlPlane.statefulSet.persistence.dataVolume }}
{{ toYaml .Values.controlPlane.statefulSet.persistence.dataVolume | indent 8 }}
{{- else if not (include "vcluster.persistence.volumeClaim.enabled" .) }}
- name: data
emptyDir: {}
{{- end }}
{{- if .Values.controlPlane.statefulSet.persistence.addVolumes }}
{{ tpl (toYaml .Values.controlPlane.statefulSet.persistence.addVolumes) $ | indent 8 }}
{{- end }}
{{- if (not .Values.experimental.syncSettings.disableSync) }}
initContainers:
{{ include "vcluster.initContainers" . | indent 8 }}
{{- end }}
enableServiceLinks: {{ .Values.controlPlane.statefulSet.enableServiceLinks }}
containers:
- name: syncer
image: {{ include "vcluster.controlPlane.image" . | quote }}
imagePullPolicy: {{ .Values.controlPlane.statefulSet.imagePullPolicy }}
{{- if .Values.controlPlane.statefulSet.workingDir }}
workingDir: {{ .Values.controlPlane.statefulSet.workingDir }}
{{- end }}
{{- if .Values.controlPlane.statefulSet.command }}
command:
{{ toYaml .Values.controlPlane.statefulSet.command | indent 12 }}
{{- end }}
{{- if .Values.controlPlane.statefulSet.args }}
args:
{{ toYaml .Values.controlPlane.statefulSet.args | indent 12 }}
{{- end }}
{{- if .Values.controlPlane.statefulSet.probes.livenessProbe.enabled }}
livenessProbe:
httpGet:
path: /healthz
port: 8443
scheme: HTTPS
initialDelaySeconds: {{ .Values.controlPlane.statefulSet.probes.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.controlPlane.statefulSet.probes.livenessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.controlPlane.statefulSet.probes.livenessProbe.timeoutSeconds }}
failureThreshold: {{ .Values.controlPlane.statefulSet.probes.livenessProbe.failureThreshold }}
{{- end }}
{{- if .Values.controlPlane.statefulSet.probes.readinessProbe.enabled }}
readinessProbe:
httpGet:
path: /readyz
port: 8443
scheme: HTTPS
periodSeconds: {{ .Values.controlPlane.statefulSet.probes.readinessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.controlPlane.statefulSet.probes.readinessProbe.timeoutSeconds }}
failureThreshold: {{ .Values.controlPlane.statefulSet.probes.readinessProbe.failureThreshold }}
{{- end }}
{{- if .Values.controlPlane.statefulSet.probes.startupProbe.enabled }}
startupProbe:
httpGet:
path: /readyz
port: 8443
scheme: HTTPS
periodSeconds: {{ .Values.controlPlane.statefulSet.probes.startupProbe.periodSeconds }}
timeoutSeconds: {{ .Values.controlPlane.statefulSet.probes.startupProbe.timeoutSeconds }}
failureThreshold: {{ .Values.controlPlane.statefulSet.probes.startupProbe.failureThreshold }}
{{- end }}
{{- if .Values.controlPlane.statefulSet.security.containerSecurityContext }}
securityContext:
{{ toYaml .Values.controlPlane.statefulSet.security.containerSecurityContext | indent 12 }}
{{- end }}
resources:
{{ toYaml .Values.controlPlane.statefulSet.resources | indent 12 }}
env:
- name: VCLUSTER_NAME
value: "{{ .Release.Name }}"
{{- if .Values.logging }}
- name: LOFT_LOG_ENCODING
value: {{ default "console" .Values.logging.encoding }}
{{- end }}
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: NODE_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
{{- if .Values.controlPlane.statefulSet.env }}
{{ toYaml .Values.controlPlane.statefulSet.env | indent 12 }}
{{- end }}
{{ include "vcluster.distro.env" . | indent 12 }}
volumeMounts:
{{- include "vcluster.plugins.volumeMounts" . | indent 12 }}
- name: data
mountPath: /data
- name: binaries
mountPath: /binaries
- name: certs
mountPath: /pki
- name: helm-cache
mountPath: /.cache/helm
{{- if eq (include "vcluster.distro" .) "k3s" }}
- name: k3s-config
mountPath: /etc/rancher
{{- end }}
- name: vcluster-config
mountPath: /var/lib/vcluster
- name: tmp
mountPath: /tmp
{{- if .Values.controlPlane.statefulSet.persistence.addVolumeMounts }}
{{ toYaml .Values.controlPlane.statefulSet.persistence.addVolumeMounts | indent 12 }}
{{- end }}
{{- include "vcluster.legacyPlugins.containers" . | indent 8 }}
{{- end }}

View File

@@ -0,0 +1,29 @@
{{- if .Values.controlPlane.advanced.workloadServiceAccount.enabled }}
apiVersion: v1
kind: ServiceAccount
metadata:
{{- if .Values.controlPlane.advanced.workloadServiceAccount.name }}
name: {{ .Values.controlPlane.advanced.workloadServiceAccount.name | quote }}
{{- else }}
name: vc-workload-{{ .Release.Name }}
{{- end }}
namespace: {{ .Release.Namespace }}
labels:
app: vcluster
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
{{- if .Values.controlPlane.advanced.workloadServiceAccount.labels }}
{{ toYaml .Values.controlPlane.advanced.workloadServiceAccount.labels | indent 4 }}
{{- end }}
{{- $annotations := merge dict .Values.controlPlane.advanced.workloadServiceAccount.annotations .Values.controlPlane.advanced.globalMetadata.annotations }}
{{- if $annotations }}
annotations:
{{- toYaml $annotations | nindent 4 }}
{{- end }}
{{- $pullSecrets := concat .Values.controlPlane.advanced.serviceAccount.imagePullSecrets .Values.controlPlane.advanced.workloadServiceAccount.imagePullSecrets }}
{{- if $pullSecrets }}
imagePullSecrets:
{{ toYaml $pullSecrets | indent 2 }}
{{- end }}
{{- end }}