Reconfigure a Node's Kubelet in a Live Cluster
Kubernetes v1.22 [deprecated]
allows you to change the configuration of each kubelet in a running Kubernetes cluster, by deploying a ConfigMap and configuring each Node to use it.
KubeletConfiguration
.
Before you begin
You need to have a Kubernetes cluster.
You also need kubectl
, installed and configured to communicate with your cluster.
Make sure that you are using a version of kubectl
that is
compatible with your cluster.
Your Kubernetes server must be at or later than version v1.11.
To check the version, enter kubectl version
.
Some of the examples use the command line tool
For each node that you're reconfiguring, you must set the kubelet
The basic workflow for configuring a kubelet in a live cluster is as follows: Each kubelet watches a configuration reference on its respective Node object.
When this reference changes, the kubelet downloads the new configuration,
updates a local reference to refer to the file, and exits.
For the feature to work correctly, you must be running an OS-level service
manager (such as systemd), which will restart the kubelet if it exits. When the
kubelet is restarted, it will begin using the new configuration. The new configuration completely overrides configuration provided by The status of the Node's kubelet configuration is reported via
This document describes editing Nodes using This document only describes a single Node consuming each ConfigMap. Keep in
mind that it is also valid for multiple Nodes to consume the same ConfigMap. Previously, you were required to manually create RBAC rules
to allow Nodes to access their assigned ConfigMaps. The Node Authorizer now
automatically configures these rules. The Dynamic Kubelet Configuration feature allows you to provide an override for
the entire configuration object, rather than a per-field overlay. This is a
simpler model that makes it easier to trace the source of configuration values
and debug issues. The compromise, however, is that you must start with knowledge
of the existing configuration to ensure that you only change the fields you
intend to change. The kubelet loads settings from its configuration file, but you can set command
line flags to override the configuration in the file. This means that if you
only know the contents of the configuration file, and you don't know the
command line overrides, then you do not know the running configuration either. Because you need to know the running configuration in order to override it,
you can fetch the running configuration from the kubelet. You can generate a
config file containing a Node's current configuration by accessing the kubelet's
For more information on configuring the kubelet via a configuration file, see
Set kubelet parameters via a config file). Choose a Node to reconfigure. In this example, the name of this Node is
referred to as Start the kubectl proxy in the background using the following command: Run the following command to download and unpack the configuration from the
Using a text editor, change one of the parameters in the
file generated by the previous procedure. For example, you
might edit the parameter Push the edited configuration file to the control plane with the
following command: This is an example of a valid response: You created that ConfigMap inside the The Edit the Node's reference to point to the new ConfigMap with the
following command: In your text editor, add the following YAML under You must specify all three of Retrieve the Node using the The You can use the following command (using The following is an example response: (if you do not have If an error occurs, the kubelet reports it in the Follow the workflow above to make more changes and push them again. Each time
you push a ConfigMap with new contents, the To reset the Node to use the configuration it was provisioned with, edit the
Node using After removing this subfield, You can change a Node's configSource using several different mechanisms.
This example uses When a new config is assigned to the Node, the kubelet downloads and unpacks the
config payload as a set of files on the local disk. The kubelet also records metadata
that locally tracks the assigned and last-known-good config sources, so that the
kubelet knows which config to use across restarts, even if the API server becomes
unavailable. After checkpointing a config and the relevant metadata, the kubelet
exits if it detects that the assigned config has changed. When the kubelet is
restarted by the OS-level service manager (such as The recorded metadata is fully resolved, meaning that it contains all necessary
information to choose a specific config version - typically a When you are debugging problems on a node, you can inspect the kubelet's config
metadata and checkpoints. The structure of the kubelet's checkpointing directory is: The following table describes error messages that can occur
when using Dynamic Kubelet Config. You can search for the identical text
in the Kubelet log for additional details and context about the error.--dynamic-config-dir
flag to a writable directory.Reconfiguring the kubelet on a running node in your cluster
Basic workflow overview
--config
,
and is overridden by command-line flags. Unspecified values in the new configuration
will receive default values appropriate to the configuration version
(e.g. kubelet.config.k8s.io/v1beta1
), unless overridden by flags.Node.Status.Config
. Once you have updated a Node to use the new
ConfigMap, you can observe this status to confirm that the Node is using the
intended configuration.kubectl edit
.
There are other ways to modify a Node's spec, including kubectl patch
, for
example, which facilitate scripted workflows.kubectl
's --append-hash
option,
and incrementally roll out updates to Node.Spec.ConfigSource
.
Automatic RBAC rules for Node Authorizer
Generating a file that contains the current configuration
configz
endpoint, through kubectl proxy
. The next section explains how to
do this.configz
endpoint is there to help with debugging, and is not
a stable part of kubelet behavior.
Do not rely on the behavior of this endpoint for production scenarios or for
use with automated tools.
Generate the configuration file
jq
command to streamline working with JSON.
To follow the tasks as written, you need to have jq
installed. You can
adapt the steps if you prefer to extract the kubeletconfig
subobject manually.
NODE_NAME
.kubectl proxy --port=8001 &
configz
endpoint. The command is long, so be careful when copying and
pasting. If you use zsh, note that common zsh configurations add backslashes
to escape the opening and closing curly braces around the variable name in the URL.
For example: ${NODE_NAME}
will be rewritten as $\{NODE_NAME\}
during the paste.
You must remove the backslashes before running the command, or the command will fail.NODE_NAME="the-name-of-the-node-you-are-reconfiguring"; curl -sSL "http://localhost:8001/api/v1/nodes/${NODE_NAME}/proxy/configz" | jq '.kubeletconfig|.kind="KubeletConfiguration"|.apiVersion="kubelet.config.k8s.io/v1beta1"' > kubelet_configz_${NODE_NAME}
kind
and apiVersion
to the downloaded
object, because those fields are not reported by the configz
endpoint.
Edit the configuration file
eventRecordQPS
, that controls
rate limiting for event recording.Push the configuration file to the control plane
kubectl -n kube-system create configmap my-node-config --from-file=kubelet=kubelet_configz_${NODE_NAME} --append-hash -o yaml
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2017-09-14T20:23:33Z
name: my-node-config-gkt4c2m4b2
namespace: kube-system
resourceVersion: "119980"
uid: 946d785e-998a-11e7-a8dd-42010a800006
data:
kubelet: |
{...}
kube-system
namespace because the kubelet
is a Kubernetes system component.--append-hash
option appends a short checksum of the ConfigMap contents
to the name. This is convenient for an edit-then-push workflow, because it
automatically, yet deterministically, generates new names for new resources.
The name that includes this generated hash is referred to as CONFIG_MAP_NAME
in the following examples.Set the Node to use the new configuration
kubectl edit node ${NODE_NAME}
spec
:configSource:
configMap:
name: CONFIG_MAP_NAME # replace CONFIG_MAP_NAME with the name of the ConfigMap
namespace: kube-system
kubeletConfigKey: kubelet
name
, namespace
, and kubeletConfigKey
.
The kubeletConfigKey
parameter shows the kubelet which key of the ConfigMap
contains its config.Observe that the Node begins using the new configuration
kubectl get node ${NODE_NAME} -o yaml
command and inspect
Node.Status.Config
. The config sources corresponding to the active
,
assigned
, and lastKnownGood
configurations are reported in the status.
active
configuration is the version the kubelet is currently running with.assigned
configuration is the latest version the kubelet has resolved based on
Node.Spec.ConfigSource
.lastKnownGood
configuration is the version the
kubelet will fall back to if an invalid config is assigned in Node.Spec.ConfigSource
.lastKnownGood
configuration might not be present if it is set to its default value,
the local config deployed with the node. The status will update lastKnownGood
to
match a valid assigned
config after the kubelet becomes comfortable with the config.
The details of how the kubelet determines a config should become the lastKnownGood
are
not guaranteed by the API, but is currently implemented as a 10-minute grace period.jq
) to filter down
to the config status:kubectl get no ${NODE_NAME} -o json | jq '.status.config'
{
"active": {
"configMap": {
"kubeletConfigKey": "kubelet",
"name": "my-node-config-9mbkccg2cc",
"namespace": "kube-system",
"resourceVersion": "1326",
"uid": "705ab4f5-6393-11e8-b7cc-42010a800002"
}
},
"assigned": {
"configMap": {
"kubeletConfigKey": "kubelet",
"name": "my-node-config-9mbkccg2cc",
"namespace": "kube-system",
"resourceVersion": "1326",
"uid": "705ab4f5-6393-11e8-b7cc-42010a800002"
}
},
"lastKnownGood": {
"configMap": {
"kubeletConfigKey": "kubelet",
"name": "my-node-config-9mbkccg2cc",
"namespace": "kube-system",
"resourceVersion": "1326",
"uid": "705ab4f5-6393-11e8-b7cc-42010a800002"
}
}
}
jq
, you can look at the whole response and find Node.Status.Config
by eye).Node.Status.Config.Error
structure. Possible errors are listed in
Understanding Node.Status.Config.Error messages.
You can search for the identical text in the kubelet log for additional details
and context about the error.Make more changes
--append-hash
kubectl option creates
the ConfigMap with a new name. The safest rollout strategy is to first create a
new ConfigMap, and then update the Node to use the new ConfigMap.Reset the Node to use its local default configuration
kubectl edit node ${NODE_NAME}
and remove the
Node.Spec.ConfigSource
field.Observe that the Node is using its local default configuration
Node.Status.Config
eventually becomes
empty, since all config sources have been reset to nil
, which indicates that
the local default config is assigned
, active
, and lastKnownGood
, and no
error is reported.kubectl patch
examplekubectl patch
:kubectl patch node ${NODE_NAME} -p "{\"spec\":{\"configSource\":{\"configMap\":{\"name\":\"${CONFIG_MAP_NAME}\",\"namespace\":\"kube-system\",\"kubeletConfigKey\":\"kubelet\"}}}}"
Understanding how the kubelet checkpoints config
systemd
), it reads the new
metadata and uses the new config.UID
and ResourceVersion
.
This is in contrast to Node.Spec.ConfigSource
, where the intended config is declared
via the idempotent namespace/name
that identifies the target ConfigMap; the kubelet
tries to use the latest version of this ConfigMap.- --dynamic-config-dir (root for managing dynamic config)
| - meta
| - assigned (encoded kubeletconfig/v1beta1.SerializedNodeConfigSource object, indicating the assigned config)
| - last-known-good (encoded kubeletconfig/v1beta1.SerializedNodeConfigSource object, indicating the last-known-good config)
| - checkpoints
| - uid1 (dir for versions of object identified by uid1)
| - resourceVersion1 (dir for unpacked files from resourceVersion1 of object with uid1)
| - ...
| - ...
Understanding
Node.Status.Config.Error
messages
Error Message | Possible Causes |
---|---|
failed to load config, see Kubelet log for details | The kubelet likely could not parse the downloaded config payload, or encountered a filesystem error attempting to load the payload from disk. |
failed to validate config, see Kubelet log for details | The configuration in the payload, combined with any command-line flag overrides, and the sum of feature gates from flags, the config file, and the remote payload, was determined to be invalid by the kubelet. |
invalid NodeConfigSource, exactly one subfield must be non-nil, but all were nil | Since Node.Spec.ConfigSource is validated by the API server to contain at least one non-nil subfield, this likely means that the kubelet is older than the API server and does not recognize a newer source type. |
failed to sync: failed to download config, see Kubelet log for details | The kubelet could not download the config. It is possible that Node.Spec.ConfigSource could not be resolved to a concrete API object, or that network errors disrupted the download attempt. The kubelet will retry the download when in this error state. |
failed to sync: internal failure, see Kubelet log for details | The kubelet encountered some internal problem and failed to update its config as a result. Examples include filesystem errors and reading objects from the internal informer cache. |
internal failure, see Kubelet log for details | The kubelet encountered some internal problem while manipulating config, outside of the configuration sync loop. |
What's next
- Set kubelet parameters via a config file explains the supported way to configure a kubelet.
- See the reference documentation for Node, including the
configSource
field within the Node's .spec - Learn more about kubelet configuration by checking the
KubeletConfiguration
reference.