diff --git a/charts/kubernetes-switchcloud/Chart.yaml b/charts/kubernetes-switchcloud/Chart.yaml index ec1951e..1968f1b 100644 --- a/charts/kubernetes-switchcloud/Chart.yaml +++ b/charts/kubernetes-switchcloud/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: kubernetes-switchcloud description: Managed Kubernetes service on Switch Cloud (OpenStack + Talos) type: application -version: 0.8.1 +version: 0.8.2 appVersion: "1.32.6" annotations: talos-csr-signer/chart-url: "oci://ghcr.io/aenix-org/talos-csr-signer" diff --git a/charts/kubernetes-switchcloud/templates/clustermesh.yaml b/charts/kubernetes-switchcloud/templates/clustermesh.yaml index 28c42d6..8ea1fb0 100644 --- a/charts/kubernetes-switchcloud/templates/clustermesh.yaml +++ b/charts/kubernetes-switchcloud/templates/clustermesh.yaml @@ -56,6 +56,9 @@ spec: - {{ . | quote }} {{- end }} {{- end }} + {{- if .persistentKeepalive }} + persistentKeepalive: {{ .persistentKeepalive }} + {{- end }} {{- end }} {{- if $hasLocalCluster }} - name: {{ $localCluster.name }} @@ -73,6 +76,9 @@ spec: - {{ . | quote }} {{- end }} {{- end }} + {{- if $localCluster.persistentKeepalive }} + persistentKeepalive: {{ $localCluster.persistentKeepalive }} + {{- end }} {{- end }} {{- end }} {{- end }} diff --git a/packages/core/platform/templates/cozyrds.yaml b/packages/core/platform/templates/cozyrds.yaml index 9b10d9b..4bdeb87 100644 --- a/packages/core/platform/templates/cozyrds.yaml +++ b/packages/core/platform/templates/cozyrds.yaml @@ -10,7 +10,7 @@ spec: singular: kubernetesswitchcloud plural: kubernetesswitchclouds openAPISchema: |- - {"title":"Chart Values","type":"object","properties":{"openstack":{"description":"OpenStack connection settings.","type":"object","default":{},"properties":{"authURL":{"description":"OpenStack identity endpoint.","type":"string","default":""},"regionName":{"description":"OpenStack region name.","type":"string","default":""},"applicationCredentialID":{"description":"Application credential ID.","type":"string","default":""},"applicationCredentialSecret":{"description":"Application credential secret.","type":"string","default":""},"cloudName":{"description":"Cloud name used as key in clouds.yaml.","type":"string","default":"openstack"},"existingSecret":{"description":"Name of existing Secret with clouds.yaml (overrides inline credentials).","type":"string","default":""},"floatingIPNetwork":{"description":"External network for Floating IPs (leave empty to disable FIPs).","type":"string","default":""},"loadBalancer":{"description":"Centralised LoadBalancer feature. When enabled, the management-cluster loadbalancer-controller provisions Octavia LBs for tenant Services of type LoadBalancer using the OpenStack credentials configured above; tenant cluster users never see those credentials directly.","type":"object","default":{},"properties":{"enabled":{"description":"Enable centralised LoadBalancer provisioning for this tenant. Off by default; turn on only after the controller has been deployed to the management cluster.","type":"boolean","default":false},"providerDriver":{"description":"Octavia provider driver. In Switch Cloud zhw only `ovn` is functional (the `amphora` driver has no flavors). Leave empty to use the project default.","type":"string","default":"ovn"},"vipNetworkID":{"description":"REQUIRED when enabled=true. Neutron network ID where the LB VIP port is allocated. Must be a tenant-owned network reachable from the worker nodes (typically the same network as spec.openstack.network.id). In Switch Cloud zhw direct-on-public VIP is not BGP-announced for IPv4, so VIP must live on a tenant network and external access is wired via floatingNetworkID below.","type":"string","default":""},"floatingNetworkID":{"description":"Optional external network ID. When set, the controller allocates a floating IP from this network after the LB becomes ACTIVE and binds it to the LB VIP port; the FIP address is reported back in Service.status.loadBalancer.ingress. Leave empty for internal-only LBs (no external reachability).","type":"string","default":""},"floatingSubnetID":{"description":"Optional Neutron subnet ID within floatingNetworkID. Pins FIP allocation to a specific subnet when the external network has multiple subnets (e.g. dual-stack). Leave empty to let Neutron pick.","type":"string","default":""},"workerSecurityGroupID":{"description":"Optional Neutron security group ID attached to the worker-node ports. When set, the controller manages per-Service ingress rules in this SG (one rule per Service port \u00d7 allowedCIDRs). Required for external traffic to reach the NodePort behind the LB: Octavia's pool members carry the worker port's SG, so without an explicit allow rule the default SG (which only permits intra-SG traffic) drops inbound packets coming from the LB VIP. Leave empty if you prefer to manage SG rules manually outside the controller; operator-managed rules are then your responsibility.","type":"string","default":""},"allowedCIDRs":{"description":"CIDR allowlist for inbound traffic to the LB NodePort. Each Service port gets ingress rules in workerSecurityGroupID for every CIDR listed here. Defaults to 0.0.0.0/0 (publicly reachable); narrow this when only specific networks should reach the Service. Ignored when workerSecurityGroupID is unset.","type":"array","default":["0.0.0.0/0"],"items":{"type":"string"}}}},"network":{"description":"OpenStack network settings. When `id` is set the chart operates in legacy mode and CAPO consumes that pre-existing network. When `id` is empty CAPO auto-manages a per-cluster network/subnet/router on apply and tears them down on cluster delete, giving full L2/L3 isolation between clusters in the same project.","type":"object","default":{},"properties":{"id":{"description":"Pre-existing OpenStack network ID for worker nodes. Legacy mode. Leave empty to enable auto-managed mode below. IMMUTABLE once set: clearing this field would switch a live cluster from legacy to auto-managed and trigger CAPO to provision a brand-new network, orphaning the old one and rerolling all workers (hard outage). Delete and recreate the cluster CR if you really need to switch modes.","type":"string","default":"","x-kubernetes-validations":[{"rule":"self == oldSelf || oldSelf == ''","message":"spec.openstack.network.id is immutable once set: clearing it would switch the cluster from legacy to auto-managed mode and trigger a network re-provision (data loss). Delete and recreate the cluster CR instead."}]},"subnetCIDR":{"description":"IPv4 CIDR for the auto-managed worker subnet. Used only when `id` is empty. Default `10.244.0.0/24` is chosen to NOT overlap the in-cluster default podCIDR `10.243.0.0/16`; pick a non-overlapping range if you mesh multiple clusters via Kilo.","type":"string","default":"10.244.0.0/24"},"externalNetworkID":{"description":"Neutron network ID used as the router's external gateway in auto-managed mode. Leave empty to let CAPO auto-discover the single project-visible external network (Switch Cloud zhw: the `public` network).","type":"string","default":""},"dnsNameservers":{"description":"DNS servers wired into the auto-managed subnet's DHCP. Used only when `id` is empty. Empty list = OpenStack default.","type":"array","default":[],"items":{"type":"string"}}}}}},"version":{"description":"Kubernetes version string (e.g. v1.32.6).","type":"string","default":"v1.32.6"},"talosVersion":{"description":"Talos OS version embedded in the node image.","type":"string","default":"v1.10.0"},"controlPlane":{"description":"Kamaji control-plane configuration.","type":"object","default":{},"properties":{"replicas":{"description":"Number of control-plane replicas.","type":"integer","default":2}}},"host":{"description":"External hostname for the Kubernetes API. Defaults to ..svc:6443 when empty.","type":"string","default":""},"ingressClassName":{"description":"IngressClass for the Kamaji-managed apiserver Ingress. When empty (default), falls back to `_namespace.ingress` (= the parent tenant namespace name) so per-tenant Ingress controllers like `tenant-root` keep working unchanged. Set to e.g. `nginx` to route the apiserver through a host-level ingress controller instead (saves provisioning a dedicated tenant-root ingress-nginx for clusters that already expose one at the platform level; the controller must have --enable-ssl-passthrough since the Kamaji apiserver terminates TLS itself).","type":"string","default":""},"nodeGroups":{"description":"Worker node group definitions.","type":"object","default":{"md0":{"minReplicas":0,"maxReplicas":10,"flavorName":"c004r008","imageName":"talos-openstack-amd64","roles":[],"resources":{"cpu":4,"memory":"8Gi"},"kubelet":{"evictionHardMemory":"7%","evictionSoftMemory":"10%"},"securityGroups":["default"]}},"additionalProperties":{"type":"object","required":["flavorName","imageName","maxReplicas","minReplicas"],"properties":{"minReplicas":{"description":"Minimum autoscaler replicas.","type":"integer","default":0},"maxReplicas":{"description":"Maximum autoscaler replicas.","type":"integer","default":10},"flavorName":{"description":"OpenStack Nova flavor name.","type":"string","default":"c004r008"},"imageName":{"description":"Glance image name for Talos nodes.","type":"string","default":"talos-openstack-amd64"},"roles":{"description":"Node roles propagated as labels.","type":"array","items":{"type":"string"}},"resources":{"description":"CPU/memory for kubelet reservations and autoscaler capacity hints.","type":"object","properties":{"cpu":{"anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"kubelet":{"description":"Kubelet eviction threshold overrides.","type":"object","properties":{"evictionHardMemory":{"type":"string","default":"7%"},"evictionSoftMemory":{"type":"string","default":"10%"}}},"securityGroups":{"description":"OpenStack security groups.","type":"array","items":{"type":"string"}}}}},"addons":{"description":"Cluster addons configuration.","type":"object","default":{},"properties":{"certManager":{"type":"object","default":{},"properties":{"enabled":{"type":"boolean","default":true},"valuesOverride":{"type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"cilium":{"type":"object","default":{},"properties":{"valuesOverride":{"type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"ingressNginx":{"type":"object","default":{},"properties":{"enabled":{"type":"boolean","default":false,"description":"Enable Ingress-NGINX controller in the tenant cluster."},"exposeMethod":{"type":"string","enum":["LoadBalancer","Proxied"],"default":"LoadBalancer","description":"How the controller is reachable from outside. Proxied is reserved for a future platform-side router and currently fails render in switchcloud."},"hosts":{"type":"array","default":[],"items":{"type":"string"},"description":"Domains served by this tenant ingress. Used for cert-manager SANs and to document the public routing target."},"valuesOverride":{"type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"metricsServer":{"type":"object","default":{},"properties":{"enabled":{"type":"boolean","default":true},"valuesOverride":{"type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"fluxcd":{"type":"object","default":{},"properties":{"enabled":{"type":"boolean","default":false},"valuesOverride":{"type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"kilo":{"type":"object","default":{},"properties":{"enabled":{"type":"boolean","default":false,"description":"Install Kilo WireGuard mesh in the tenant cluster. Required for cross-location routing or kilo-clustermesh-operator participation."},"valuesOverride":{"type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true},"clusterMesh":{"type":"object","default":{},"description":"When remoteClusters is non-empty, emits a ClusterMesh CR for kilo-clustermesh-operator. The local cluster entry is auto-derived; for each remote tenant supply its name and the Kamaji admin-kubeconfig Secret name.","properties":{"localWireguardCIDR":{"type":"string","default":"","description":"WireGuard CIDR for the local cluster; must match the kilo.transitCIDR you set under addons.kilo.valuesOverride."},"wireguardPort":{"type":"integer","default":51820,"description":"UDP port for WireGuard peers."},"remoteClusters":{"type":"array","default":[],"description":"Remote clusters to mesh with. Empty list disables ClusterMesh emission.","items":{"type":"object","required":["name","kubeconfigSecretName","podCIDRs","serviceCIDR","wireguardCIDR"],"properties":{"name":{"type":"string"},"kubeconfigSecretName":{"type":"string","description":"Name of the Secret in tenant-root holding the remote cluster admin kubeconfig (Kamaji default: -admin-kubeconfig)."},"kubeconfigSecretKey":{"type":"string","default":"super-admin.conf"},"podCIDRs":{"type":"array","items":{"type":"string"}},"additionalCIDRs":{"type":"array","default":[],"description":"Extra CIDRs folded into the AllowedIPs of the remote cluster leader peer. Use this to cover pod subnets of non-leader nodes that lack a WireGuard IP (e.g. location-granularity clusters with multiple nodes).","items":{"type":"string"}},"serviceCIDR":{"type":"string"},"wireguardCIDR":{"type":"string"},"wireguardPort":{"type":"integer","default":51820}}}}}}}}}},"network":{"type":"object","default":{},"description":"Cluster network CIDRs. Immutable after cluster creation.","properties":{"podCIDR":{"type":"string","default":"10.243.0.0/16","description":"CIDR allocated for pods. Maps onto CAPI Cluster.spec.clusterNetwork.pods.cidrBlocks."},"serviceCIDR":{"type":"string","default":"10.95.0.0/16","description":"CIDR allocated for Services. Maps onto CAPI Cluster.spec.clusterNetwork.services.cidrBlocks."},"dnsClusterIP":{"type":"string","default":"10.95.0.10","description":"ClusterIP for the CoreDNS Service. Must fall inside serviceCIDR."}}}}} + {"title":"Chart Values","type":"object","properties":{"openstack":{"description":"OpenStack connection settings.","type":"object","default":{},"properties":{"authURL":{"description":"OpenStack identity endpoint.","type":"string","default":""},"regionName":{"description":"OpenStack region name.","type":"string","default":""},"applicationCredentialID":{"description":"Application credential ID.","type":"string","default":""},"applicationCredentialSecret":{"description":"Application credential secret.","type":"string","default":""},"cloudName":{"description":"Cloud name used as key in clouds.yaml.","type":"string","default":"openstack"},"existingSecret":{"description":"Name of existing Secret with clouds.yaml (overrides inline credentials).","type":"string","default":""},"floatingIPNetwork":{"description":"External network for Floating IPs (leave empty to disable FIPs).","type":"string","default":""},"loadBalancer":{"description":"Centralised LoadBalancer feature. When enabled, the management-cluster loadbalancer-controller provisions Octavia LBs for tenant Services of type LoadBalancer using the OpenStack credentials configured above; tenant cluster users never see those credentials directly.","type":"object","default":{},"properties":{"enabled":{"description":"Enable centralised LoadBalancer provisioning for this tenant. Off by default; turn on only after the controller has been deployed to the management cluster.","type":"boolean","default":false},"providerDriver":{"description":"Octavia provider driver. In Switch Cloud zhw only `ovn` is functional (the `amphora` driver has no flavors). Leave empty to use the project default.","type":"string","default":"ovn"},"vipNetworkID":{"description":"REQUIRED when enabled=true. Neutron network ID where the LB VIP port is allocated. Must be a tenant-owned network reachable from the worker nodes (typically the same network as spec.openstack.network.id). In Switch Cloud zhw direct-on-public VIP is not BGP-announced for IPv4, so VIP must live on a tenant network and external access is wired via floatingNetworkID below.","type":"string","default":""},"floatingNetworkID":{"description":"Optional external network ID. When set, the controller allocates a floating IP from this network after the LB becomes ACTIVE and binds it to the LB VIP port; the FIP address is reported back in Service.status.loadBalancer.ingress. Leave empty for internal-only LBs (no external reachability).","type":"string","default":""},"floatingSubnetID":{"description":"Optional Neutron subnet ID within floatingNetworkID. Pins FIP allocation to a specific subnet when the external network has multiple subnets (e.g. dual-stack). Leave empty to let Neutron pick.","type":"string","default":""},"workerSecurityGroupID":{"description":"Optional Neutron security group ID attached to the worker-node ports. When set, the controller manages per-Service ingress rules in this SG (one rule per Service port \u00d7 allowedCIDRs). Required for external traffic to reach the NodePort behind the LB: Octavia's pool members carry the worker port's SG, so without an explicit allow rule the default SG (which only permits intra-SG traffic) drops inbound packets coming from the LB VIP. Leave empty if you prefer to manage SG rules manually outside the controller; operator-managed rules are then your responsibility.","type":"string","default":""},"allowedCIDRs":{"description":"CIDR allowlist for inbound traffic to the LB NodePort. Each Service port gets ingress rules in workerSecurityGroupID for every CIDR listed here. Defaults to 0.0.0.0/0 (publicly reachable); narrow this when only specific networks should reach the Service. Ignored when workerSecurityGroupID is unset.","type":"array","default":["0.0.0.0/0"],"items":{"type":"string"}}}},"network":{"description":"OpenStack network settings. When `id` is set the chart operates in legacy mode and CAPO consumes that pre-existing network. When `id` is empty CAPO auto-manages a per-cluster network/subnet/router on apply and tears them down on cluster delete, giving full L2/L3 isolation between clusters in the same project.","type":"object","default":{},"properties":{"id":{"description":"Pre-existing OpenStack network ID for worker nodes. Legacy mode. Leave empty to enable auto-managed mode below. IMMUTABLE once set: clearing this field would switch a live cluster from legacy to auto-managed and trigger CAPO to provision a brand-new network, orphaning the old one and rerolling all workers (hard outage). Delete and recreate the cluster CR if you really need to switch modes.","type":"string","default":"","x-kubernetes-validations":[{"rule":"self == oldSelf || oldSelf == ''","message":"spec.openstack.network.id is immutable once set: clearing it would switch the cluster from legacy to auto-managed mode and trigger a network re-provision (data loss). Delete and recreate the cluster CR instead."}]},"subnetCIDR":{"description":"IPv4 CIDR for the auto-managed worker subnet. Used only when `id` is empty. Default `10.244.0.0/24` is chosen to NOT overlap the in-cluster default podCIDR `10.243.0.0/16`; pick a non-overlapping range if you mesh multiple clusters via Kilo.","type":"string","default":"10.244.0.0/24"},"externalNetworkID":{"description":"Neutron network ID used as the router's external gateway in auto-managed mode. Leave empty to let CAPO auto-discover the single project-visible external network (Switch Cloud zhw: the `public` network).","type":"string","default":""},"dnsNameservers":{"description":"DNS servers wired into the auto-managed subnet's DHCP. Used only when `id` is empty. Empty list = OpenStack default.","type":"array","default":[],"items":{"type":"string"}}}}}},"version":{"description":"Kubernetes version string (e.g. v1.32.6).","type":"string","default":"v1.32.6"},"talosVersion":{"description":"Talos OS version embedded in the node image.","type":"string","default":"v1.10.0"},"controlPlane":{"description":"Kamaji control-plane configuration.","type":"object","default":{},"properties":{"replicas":{"description":"Number of control-plane replicas.","type":"integer","default":2}}},"host":{"description":"External hostname for the Kubernetes API. Defaults to ..svc:6443 when empty.","type":"string","default":""},"ingressClassName":{"description":"IngressClass for the Kamaji-managed apiserver Ingress. When empty (default), falls back to `_namespace.ingress` (= the parent tenant namespace name) so per-tenant Ingress controllers like `tenant-root` keep working unchanged. Set to e.g. `nginx` to route the apiserver through a host-level ingress controller instead (saves provisioning a dedicated tenant-root ingress-nginx for clusters that already expose one at the platform level; the controller must have --enable-ssl-passthrough since the Kamaji apiserver terminates TLS itself).","type":"string","default":""},"nodeGroups":{"description":"Worker node group definitions.","type":"object","default":{"md0":{"minReplicas":0,"maxReplicas":10,"flavorName":"c004r008","imageName":"talos-openstack-amd64","roles":[],"resources":{"cpu":4,"memory":"8Gi"},"kubelet":{"evictionHardMemory":"7%","evictionSoftMemory":"10%"},"securityGroups":["default"]}},"additionalProperties":{"type":"object","required":["flavorName","imageName","maxReplicas","minReplicas"],"properties":{"minReplicas":{"description":"Minimum autoscaler replicas.","type":"integer","default":0},"maxReplicas":{"description":"Maximum autoscaler replicas.","type":"integer","default":10},"flavorName":{"description":"OpenStack Nova flavor name.","type":"string","default":"c004r008"},"imageName":{"description":"Glance image name for Talos nodes.","type":"string","default":"talos-openstack-amd64"},"roles":{"description":"Node roles propagated as labels.","type":"array","items":{"type":"string"}},"resources":{"description":"CPU/memory for kubelet reservations and autoscaler capacity hints.","type":"object","properties":{"cpu":{"anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"kubelet":{"description":"Kubelet eviction threshold overrides.","type":"object","properties":{"evictionHardMemory":{"type":"string","default":"7%"},"evictionSoftMemory":{"type":"string","default":"10%"}}},"securityGroups":{"description":"OpenStack security groups.","type":"array","items":{"type":"string"}}}}},"addons":{"description":"Cluster addons configuration.","type":"object","default":{},"properties":{"certManager":{"type":"object","default":{},"properties":{"enabled":{"type":"boolean","default":true},"valuesOverride":{"type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"cilium":{"type":"object","default":{},"properties":{"valuesOverride":{"type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"ingressNginx":{"type":"object","default":{},"properties":{"enabled":{"type":"boolean","default":false,"description":"Enable Ingress-NGINX controller in the tenant cluster."},"exposeMethod":{"type":"string","enum":["LoadBalancer","Proxied"],"default":"LoadBalancer","description":"How the controller is reachable from outside. Proxied is reserved for a future platform-side router and currently fails render in switchcloud."},"hosts":{"type":"array","default":[],"items":{"type":"string"},"description":"Domains served by this tenant ingress. Used for cert-manager SANs and to document the public routing target."},"valuesOverride":{"type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"metricsServer":{"type":"object","default":{},"properties":{"enabled":{"type":"boolean","default":true},"valuesOverride":{"type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"fluxcd":{"type":"object","default":{},"properties":{"enabled":{"type":"boolean","default":false},"valuesOverride":{"type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"kilo":{"type":"object","default":{},"properties":{"enabled":{"type":"boolean","default":false,"description":"Install Kilo WireGuard mesh in the tenant cluster. Required for cross-location routing or kilo-clustermesh-operator participation."},"valuesOverride":{"type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true},"clusterMesh":{"type":"object","default":{},"description":"When remoteClusters is non-empty, emits a ClusterMesh CR for kilo-clustermesh-operator. The local cluster entry is auto-derived; for each remote tenant supply its name and the Kamaji admin-kubeconfig Secret name.","properties":{"localWireguardCIDR":{"type":"string","default":"","description":"WireGuard CIDR for the local cluster; must match the kilo.transitCIDR you set under addons.kilo.valuesOverride."},"wireguardPort":{"type":"integer","default":51820,"description":"UDP port for WireGuard peers."},"remoteClusters":{"type":"array","default":[],"description":"Remote clusters to mesh with. Empty list disables ClusterMesh emission.","items":{"type":"object","required":["name","kubeconfigSecretName","podCIDRs","serviceCIDR","wireguardCIDR"],"properties":{"name":{"type":"string"},"kubeconfigSecretName":{"type":"string","description":"Name of the Secret in tenant-root holding the remote cluster admin kubeconfig (Kamaji default: -admin-kubeconfig)."},"kubeconfigSecretKey":{"type":"string","default":"super-admin.conf"},"podCIDRs":{"type":"array","items":{"type":"string"}},"additionalCIDRs":{"type":"array","default":[],"description":"Extra CIDRs folded into the AllowedIPs of the remote cluster leader peer. Use this to cover pod subnets of non-leader nodes that lack a WireGuard IP (e.g. location-granularity clusters with multiple nodes).","items":{"type":"string"}},"serviceCIDR":{"type":"string"},"wireguardCIDR":{"type":"string"},"wireguardPort":{"type":"integer","default":51820},"persistentKeepalive":{"type":"integer","default":0,"description":"WireGuard PersistentKeepalive interval in seconds. Set to a non-zero value (e.g. 25) for clusters behind NAT to keep the stateful NAT mapping alive and enable bidirectional traffic.","minimum":0,"maximum":65535}}}}}}}}}},"network":{"type":"object","default":{},"description":"Cluster network CIDRs. Immutable after cluster creation.","properties":{"podCIDR":{"type":"string","default":"10.243.0.0/16","description":"CIDR allocated for pods. Maps onto CAPI Cluster.spec.clusterNetwork.pods.cidrBlocks."},"serviceCIDR":{"type":"string","default":"10.95.0.0/16","description":"CIDR allocated for Services. Maps onto CAPI Cluster.spec.clusterNetwork.services.cidrBlocks."},"dnsClusterIP":{"type":"string","default":"10.95.0.10","description":"ClusterIP for the CoreDNS Service. Must fall inside serviceCIDR."}}}}} release: prefix: kubernetes-switchcloud- labels: