diff --git a/charms/worker/k8s/charmcraft.yaml b/charms/worker/k8s/charmcraft.yaml index 29b9cc9a..0f685cc3 100644 --- a/charms/worker/k8s/charmcraft.yaml +++ b/charms/worker/k8s/charmcraft.yaml @@ -81,6 +81,58 @@ config: Example: e.g.: key1=value1 key2=value2 + bootstrap-datastore: + default: dqlite + type: string + description: | + The datastore to use in Canonical Kubernetes. This cannot be changed + after deployment. Allowed values are "dqlite" and "etcd". If "etcd" is + chosen, the charm should be integrated with the etcd charm. + bootstrap-node-taints: + type: string + default: "" + description: | + Space-separated list of taints to apply to this node at registration time. + + This config is only used at bootstrap time when Kubelet first registers the + node with Kubernetes. To change node taints after deploy time, use kubectl + instead. + + For more information, see the upstream Kubernetes documentation about + taints: + https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + bootstrap-pod-cidr: + type: string + default: "10.1.0.0/16" + description: | + Comma-separated CIDR blocks for IP addresses that can be assigned + to pods within the cluster. Can contain at most 2 blocks, one for IPv4 + and one for IPv6. + + After deployment it is not possible to change the size of + the IP range. + + Examples: + - "192.0.2.0/24" + - "2001:db8::/32" + - "192.0.2.0/24,2001:db8::/32" + - "2001:db8::/32,192.0.2.0/24" + bootstrap-service-cidr: + type: string + default: 10.152.183.0/24 + description: | + Comma-separated CIDR blocks for IP addresses that can be assigned + to services within the cluster. Can contain at most 2 blocks, one for IPv4 + and one for IPv6. + + After deployment it is not possible to change the size of + the IP range. + + Examples: + - "192.0.2.0/24" + - "2001:db8::/32" + - "192.0.2.0/24,2001:db8::/32" + - "2001:db8::/32,192.0.2.0/24" containerd-custom-registries: type: string default: "[]" @@ -127,59 +179,32 @@ config: "cert_file": "'"$(base64 -w 0 < ~/my.custom.cert.pem)"'", "key_file": "'"$(base64 -w 0 < ~/my.custom.key.pem)"'", }]' - - bootstrap-datastore: - default: dqlite - type: string + dns-enabled: + type: boolean + default: true description: | - The datastore to use in Canonical Kubernetes. This cannot be changed - after deployment. Allowed values are "dqlite" and "etcd". If "etcd" is - chosen, the charm should be integrated with the etcd charm. - bootstrap-node-taints: + Enable/Disable the DNS feature on the cluster. + dns-cluster-domain: type: string - default: "" + default: "cluster.local" description: | - Space-separated list of taints to apply to this node at registration time. - - This config is only used at bootstrap time when Kubelet first registers the - node with Kubernetes. To change node taints after deploy time, use kubectl - instead. - - For more information, see the upstream Kubernetes documentation about - taints: - https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ - bootstrap-pod-cidr: + Sets the local domain of the cluster + dns-service-ip: type: string - default: "10.1.0.0/16" + default: "" description: | - Comma-separated CIDR blocks for IP addresses that can be assigned - to pods within the cluster. Can contain at most 2 blocks, one for IPv4 - and one for IPv6. - - After deployment it is not possible to change the size of - the IP range. - - Examples: - - "192.0.2.0/24" - - "2001:db8::/32" - - "192.0.2.0/24,2001:db8::/32" - - "2001:db8::/32,192.0.2.0/24" - bootstrap-service-cidr: + Sets the IP address of the dns service. If omitted defaults to the IP address + of the Kubernetes service created by the feature. + + Can be used to point to an external dns server when feature is disabled. + dns-upstream-nameservers: type: string - default: 10.152.183.0/24 + default: "" description: | - Comma-separated CIDR blocks for IP addresses that can be assigned - to services within the cluster. Can contain at most 2 blocks, one for IPv4 - and one for IPv6. - - After deployment it is not possible to change the size of - the IP range. - - Examples: - - "192.0.2.0/24" - - "2001:db8::/32" - - "192.0.2.0/24,2001:db8::/32" - - "2001:db8::/32,192.0.2.0/24" + Space-separated list of upstream nameservers used to forward queries for out-of-cluster + endpoints. + + If omitted defaults to `/etc/resolv.conf` and uses the nameservers on each node. gateway-enabled: type: boolean default: false @@ -256,6 +281,11 @@ config: "Retain". If set to "Delete", the storage will be deleted when the PersistentVolumeClaim is deleted. If set to "Retain", the storage will be retained when the PersistentVolumeClaim is deleted. + metrics-server-enabled: + type: boolean + default: true + description: | + Enable/Disable the metrics-server feature on the cluster. network-enabled: type: boolean default: true diff --git a/charms/worker/k8s/src/charm.py b/charms/worker/k8s/src/charm.py index 216f5fc5..edaaa0cf 100755 --- a/charms/worker/k8s/src/charm.py +++ b/charms/worker/k8s/src/charm.py @@ -48,6 +48,7 @@ K8sdConnectionError, LoadBalancerConfig, LocalStorageConfig, + MetricsServerConfig, NetworkConfig, UnixSocketConnectionFactory, UpdateClusterConfigRequest, @@ -423,6 +424,16 @@ def _assemble_cluster_config(self) -> UserFacingClusterConfig: # https://github.com/canonical/k8s-operator/pull/169/files#r1847378214 ) + dns_config = DNSConfig( + enabled=self.config.get("dns-enabled"), + ) + if cfg := self.config.get("dns-cluster-domain"): + dns_config.cluster_domain = str(cfg) + if cfg := self.config.get("dns-service-ip"): + dns_config.service_ip = str(cfg) + if cfg := self.config.get("dns-upstream-nameservers"): + dns_config.upstream_nameservers = str(cfg).split() + gateway = GatewayConfig(enabled=self.config.get("gateway-enabled")) network = NetworkConfig( @@ -434,6 +445,8 @@ def _assemble_cluster_config(self) -> UserFacingClusterConfig: enable_proxy_protocol=self.config.get("ingress-enable-proxy-protocol"), ) + metrics_server = MetricsServerConfig(enabled=self.config.get("metrics-server-enabled")) + load_balancer = LoadBalancerConfig( enabled=self.config.get("load-balancer-enabled"), cidrs=str(self.config.get("load-balancer-cidrs")).split(), @@ -451,13 +464,15 @@ def _assemble_cluster_config(self) -> UserFacingClusterConfig: cloud_provider = "external" return UserFacingClusterConfig( - local_storage=local_storage, - gateway=gateway, - network=network, - ingress=ingress, annotations=self._get_valid_annotations(), cloud_provider=cloud_provider, + dns_config=dns_config, + gateway=gateway, + ingress=ingress, + local_storage=local_storage, load_balancer=load_balancer, + metrics_server=metrics_server, + network=network, ) def _configure_datastore(self, config: Union[BootstrapConfig, UpdateClusterConfigRequest]): @@ -584,25 +599,6 @@ def _create_cos_tokens(self): token_type=ClusterTokenType.WORKER, ) - @on_error( - WaitingStatus("Waiting to enable features"), - InvalidResponseError, - K8sdConnectionError, - ) - def _enable_functionalities(self): - """Enable necessary components for the Kubernetes cluster.""" - status.add(ops.MaintenanceStatus("Updating K8s features")) - log.info("Enabling K8s features") - dns_config = DNSConfig(enabled=True) - network_config = NetworkConfig(enabled=True) - local_storage_config = LocalStorageConfig(enabled=True) - user_cluster_config = UserFacingClusterConfig( - dns=dns_config, network=network_config, local_storage=local_storage_config - ) - update_request = UpdateClusterConfigRequest(config=user_cluster_config) - - self.api_manager.update_cluster_config(update_request) - @on_error( WaitingStatus("Ensure that the cluster configuration is up-to-date"), ReconcilerError, @@ -801,12 +797,11 @@ def _reconcile(self, event: ops.EventBase): if self.lead_control_plane: self._k8s_info(event) self._bootstrap_k8s_snap() - self._enable_functionalities() + self._ensure_cluster_config() self._create_cluster_tokens() self._create_cos_tokens() self._apply_cos_requirements() self._revoke_cluster_tokens(event) - self._ensure_cluster_config() self._announce_kubernetes_version() self._join_cluster(event) self._config_containerd_registries() diff --git a/charms/worker/k8s/tests/unit/test_base.py b/charms/worker/k8s/tests/unit/test_base.py index a69a6f45..6a3f419a 100644 --- a/charms/worker/k8s/tests/unit/test_base.py +++ b/charms/worker/k8s/tests/unit/test_base.py @@ -58,7 +58,6 @@ def mock_reconciler_handlers(harness): if harness.charm.is_control_plane: handler_names |= { "_bootstrap_k8s_snap", - "_enable_functionalities", "_create_cluster_tokens", "_create_cos_tokens", "_apply_cos_requirements",