update dynamic kubelet config docs for v1.11 (#8766)
* update dynamic kubelet config docs for v1.11 * Substantial copyedit * Address feedback
This commit is contained in:
committed by
Misty Linville
parent
0c1970eaaf
commit
bf668921f4
@@ -7,31 +7,28 @@ content_template: templates/task
|
|||||||
---
|
---
|
||||||
|
|
||||||
{{% capture overview %}}
|
{{% capture overview %}}
|
||||||
{{< feature-state state="alpha" >}}
|
{{< feature-state for_k8s_version="v1.11" state="beta" >}}
|
||||||
As of Kubernetes 1.8, the new
|
|
||||||
[Dynamic Kubelet Configuration](https://github.com/kubernetes/features/issues/281)
|
[Dynamic Kubelet Configuration](https://github.com/kubernetes/features/issues/281)
|
||||||
feature is available in alpha. This allows you to change the configuration of
|
allows you to change the configuration of each Kubelet in a live Kubernetes
|
||||||
Kubelets in a live Kubernetes cluster via first-class Kubernetes concepts.
|
cluster by deploying a ConfigMap and configuring each Node to use it.
|
||||||
Specifically, this feature allows you to configure individual Nodes' Kubelets
|
|
||||||
via ConfigMaps.
|
|
||||||
|
|
||||||
{{< warning >}}
|
{{< warning >}}
|
||||||
**Warning:** All Kubelet configuration parameters may be changed dynamically,
|
**Warning:** All Kubelet configuration parameters can be changed dynamically,
|
||||||
but not all parameters are safe to change dynamically. This feature is intended
|
but this is unsafe for some parameters. Before deciding to change a parameter
|
||||||
for system experts who have a strong understanding of how configuration changes
|
dynamically, you need a strong understanding of how that change will affect your
|
||||||
will affect behavior. No documentation currently exists which plainly lists
|
cluster's behavior. Always carefully test configuration changes on a small set
|
||||||
"safe to change" fields, but we plan to add it before this feature graduates
|
of nodes before rolling them out cluster-wide. Advice on configuring specific
|
||||||
from alpha.
|
fields is available in the inline `KubeletConfiguration`
|
||||||
|
[type documentation](https://github.com/kubernetes/kubernetes/blob/release-1.11/pkg/kubelet/apis/kubeletconfig/v1beta1/types.go).
|
||||||
{{< /warning >}}
|
{{< /warning >}}
|
||||||
{{% /capture %}}
|
{{% /capture %}}
|
||||||
|
|
||||||
{{% capture prerequisites %}}
|
{{% capture prerequisites %}}
|
||||||
- A live Kubernetes cluster with both Master and Node at v1.8 or higher must be
|
- Kubernetes v1.11 or higher on both the Master and the Nodes
|
||||||
running, with the `DynamicKubeletConfig` feature gate enabled and the Kubelet's
|
- kubectl v1.11 or higher, configured to communicate with the cluster
|
||||||
`--dynamic-config-dir` flag set to a writable directory on the Node.
|
- The Kubelet's `--dynamic-config-dir` flag must be set to a writable
|
||||||
This flag must be set to enable Dynamic Kubelet Configuration.
|
directory on the Node.
|
||||||
- The kubectl command-line tool must be also v1.8 or higher, and must be
|
|
||||||
configured to communicate with the cluster.
|
|
||||||
{{% /capture %}}
|
{{% /capture %}}
|
||||||
|
|
||||||
{{% capture steps %}}
|
{{% capture steps %}}
|
||||||
@@ -50,20 +47,19 @@ Kubelet's configuration.
|
|||||||
Each Kubelet watches a configuration reference on its respective Node object.
|
Each Kubelet watches a configuration reference on its respective Node object.
|
||||||
When this reference changes, the Kubelet downloads the new configuration,
|
When this reference changes, the Kubelet downloads the new configuration,
|
||||||
updates a local reference to refer to the file, and exits.
|
updates a local reference to refer to the file, and exits.
|
||||||
For the feature to work correctly, you must be running a process manager
|
For the feature to work correctly, you must be running an OS-level service
|
||||||
(like systemd) which will restart the Kubelet when it exits. When the Kubelet is
|
manager (such as systemd), which will restart the Kubelet if it exits. When the
|
||||||
restarted, it will begin using the new configuration.
|
Kubelet is restarted, it will begin using the new configuration.
|
||||||
|
|
||||||
The new configuration completely overrides configuration provided by `--config`,
|
The new configuration completely overrides configuration provided by `--config`,
|
||||||
and is overridden by command-line flags. Unspecified values in the new configuration
|
and is overridden by command-line flags. Unspecified values in the new configuration
|
||||||
will receive default values appropriate to the configuration version
|
will receive default values appropriate to the configuration version
|
||||||
(e.g. `kubelet.config.k8s.io/v1beta1`), unless overridden by flags.
|
(e.g. `kubelet.config.k8s.io/v1beta1`), unless overridden by flags.
|
||||||
|
|
||||||
The status of the Node's Kubelet configuration is reported via the `KubeletConfigOK`
|
The status of the Node's Kubelet configuration is reported via
|
||||||
condition in the Node status. Once you have updated a Node to use the new
|
`Node.Spec.Status.Config`. Once you have updated a Node to use the new
|
||||||
ConfigMap, you can observe this condition to confirm that the Node is using the
|
ConfigMap, you can observe this status to confirm that the Node is using the
|
||||||
intended configuration. A table describing the possible conditions can be found
|
intended configuration.
|
||||||
at the end of this article.
|
|
||||||
|
|
||||||
This document describes editing Nodes using `kubectl edit`.
|
This document describes editing Nodes using `kubectl edit`.
|
||||||
There are other ways to modify a Node's spec, including `kubectl patch`, for
|
There are other ways to modify a Node's spec, including `kubectl patch`, for
|
||||||
@@ -72,16 +68,19 @@ example, which facilitate scripted workflows.
|
|||||||
This document only describes a single Node consuming each ConfigMap. Keep in
|
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.
|
mind that it is also valid for multiple Nodes to consume the same ConfigMap.
|
||||||
|
|
||||||
### Node Authorizer Workarounds
|
{{< warning >}}
|
||||||
|
**Warning:** While it is *possible* to change the configuration by
|
||||||
|
updating the ConfigMap in-place, this causes all Kubelets configured with
|
||||||
|
that ConfigMap to update simultaneously. It is much safer to treat ConfigMaps
|
||||||
|
as immutable by convention, aided by `kubectl`'s `--append-hash` option,
|
||||||
|
and incrementally roll out updates to `Node.Spec.ConfigSource`.
|
||||||
|
{{< /warning >}}
|
||||||
|
|
||||||
The Node Authorizer does not yet pay attention to which ConfigMaps are assigned
|
### Automatic RBAC rules for Node Authorizer
|
||||||
to which Nodes. If you currently use the Node authorizer, your Kubelets will not
|
|
||||||
be automatically granted permission to download their respective ConfigMaps.
|
|
||||||
|
|
||||||
The temporary workaround used in this document is to manually create the RBAC
|
Previously, you were required to manually create RBAC rules
|
||||||
Roles and RoleBindings for each ConfigMap. The Node Authorizer will be extended
|
to allow Nodes to access their assigned ConfigMaps. The Node Authorizer now
|
||||||
before the Dynamic Kubelet Configuration feature graduates from alpha, so doing
|
automatically configures these rules.
|
||||||
this in production should never be necessary.
|
|
||||||
|
|
||||||
### Generating a file that contains the current configuration
|
### Generating a file that contains the current configuration
|
||||||
|
|
||||||
@@ -92,54 +91,62 @@ 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
|
of the existing configuration to ensure that you only change the fields you
|
||||||
intend to change.
|
intend to change.
|
||||||
|
|
||||||
In the future, the Kubelet will be bootstrapped from a file on disk
|
Ideally, the Kubelet would be bootstrapped from a file on disk
|
||||||
|
and you could edit this file (which could also be version-controlled),
|
||||||
|
to create the first Kubelet ConfigMap
|
||||||
(see [Set Kubelet parameters via a config file](/docs/tasks/administer-cluster/kubelet-config-file)),
|
(see [Set Kubelet parameters via a config file](/docs/tasks/administer-cluster/kubelet-config-file)),
|
||||||
and you will simply edit a copy of this file (which, as a best practice, should
|
Currently, the Kubelet is bootstrapped with **a combination of this file and command-line flags**
|
||||||
live in version control) while creating the first Kubelet ConfigMap. Today,
|
that can override the configuration in the file.
|
||||||
however, the Kubelet is still bootstrapped with command-line flags. Fortunately,
|
As a workaround, you can generate a config file containing a Node's current
|
||||||
there is a dirty trick you can use to generate a config file containing a Node's
|
configuration by accessing the Kubelet server's `configz` endpoint via the
|
||||||
current configuration. The trick involves accessing the Kubelet server's `configz`
|
kubectl proxy. This endpoint, in its current implementation, is intended to be
|
||||||
endpoint via the kubectl proxy. This endpoint, in its current implementation, is
|
used only as a debugging aid. Do not rely on the behavior of this endpoint for
|
||||||
intended to be used only as a debugging aid, which is part of why this is a
|
production scenarios. The examples below use the `jq` command to streamline
|
||||||
dirty trick. The endpoint may be improved in the future, but until then
|
working with JSON. To follow the tasks as written, you need to have `jq`
|
||||||
it should not be relied on for production scenarios.
|
installed, but you can adapt the tasks if you prefer to extract the
|
||||||
This trick also requires the `jq` command to be installed on your machine,
|
`kubeletconfig` subobject manually.
|
||||||
for unpacking and editing the JSON response from the endpoint.
|
|
||||||
|
|
||||||
Do the following to generate the file:
|
#### Generate the configuration file
|
||||||
|
|
||||||
1. Pick a Node to reconfigure. We will refer to this Node's name as NODE_NAME.
|
1. Choose a Node to reconfigure. In this example, the name of this Node is
|
||||||
2. Start the kubectl proxy in the background with `kubectl proxy --port=8001 &`
|
referred to as `NODE_NAME`.
|
||||||
3. Run the following command to download and unpack the configuration from the
|
2. Start the kubectl proxy in the background using the following command:
|
||||||
configz endpoint:
|
```bash
|
||||||
|
kubectl proxy --port=8001 &
|
||||||
|
```
|
||||||
|
3. Run the following command to download and unpack the configuration from the
|
||||||
|
`configz` endpoint. The command is long, so be careful when copying and
|
||||||
|
pasting. **If you use zsh**, replace the `${NODE_NAME}` in the URL with the
|
||||||
|
actual name of the node, because zsh automatically escapes opening curly
|
||||||
|
braces, which causes the command to fail.
|
||||||
|
|
||||||
```
|
```bash
|
||||||
$ export NODE_NAME=the-name-of-the-node-you-are-reconfiguring
|
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}
|
||||||
$ 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}
|
```
|
||||||
```
|
|
||||||
|
|
||||||
Note that we have to manually add the `kind` and `apiVersion` to the downloaded
|
{{< note >}}
|
||||||
object, as these are not reported by the configz endpoint. This is one of the
|
You need to manually add the `kind` and `apiVersion` to the downloaded
|
||||||
limitations of the endpoint.
|
object, because they are not reported by the `configz` endpoint.
|
||||||
|
{{< /note >}}
|
||||||
|
|
||||||
### Edit the configuration file
|
#### Edit the configuration file
|
||||||
|
|
||||||
Using your editor of choice, change one of the parameters in the
|
Using a text editor, change one of the parameters in the
|
||||||
`kubelet_configz_${NODE_NAME}` file from the previous step. A QPS parameter,
|
file generated by the previous procedure. For example, you
|
||||||
`eventRecordQPS` for example, is a good candidate.
|
might edit the QPS parameter `eventRecordQPS`.
|
||||||
|
|
||||||
### Push the configuration file to the control plane
|
#### Push the configuration file to the control plane
|
||||||
|
|
||||||
Push the edited configuration file to the control plane with the
|
Push the edited configuration file to the control plane with the
|
||||||
following command:
|
following command:
|
||||||
|
|
||||||
```
|
```bash
|
||||||
$ kubectl -n kube-system create configmap my-node-config --from-file=kubelet=kubelet_configz_${NODE_NAME} --append-hash -o yaml
|
kubectl -n kube-system create configmap my-node-config --from-file=kubelet=kubelet_configz_${NODE_NAME} --append-hash -o yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
You should see a response similar to:
|
This is an example of a valid response:
|
||||||
|
|
||||||
```
|
```none
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
data:
|
data:
|
||||||
kubelet: |
|
kubelet: |
|
||||||
@@ -154,304 +161,204 @@ metadata:
|
|||||||
uid: 946d785e-998a-11e7-a8dd-42010a800006
|
uid: 946d785e-998a-11e7-a8dd-42010a800006
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that the configuration data must appear under the ConfigMap's
|
The ConfigMap is created in the `kube-system` namespace because this
|
||||||
`kubelet` key.
|
ConfigMap configures a Kubelet, which is Kubernetes system component.
|
||||||
|
|
||||||
We create the ConfigMap in the `kube-system` namespace, which is appropriate
|
|
||||||
because this ConfigMap configures a Kubernetes system component - the Kubelet.
|
|
||||||
|
|
||||||
The `--append-hash` option appends a short checksum of the ConfigMap contents
|
The `--append-hash` option appends a short checksum of the ConfigMap contents
|
||||||
to the name. This is convenient for an edit->push workflow, as it will
|
to the name. This is convenient for an edit-then-push workflow, because it
|
||||||
automatically, yet deterministically, generate new names for new ConfigMaps.
|
automatically, yet deterministically, generates new names for new ConfigMaps.
|
||||||
|
The name that includes this generated hash is referred to as `CONFIG_MAP_NAME`
|
||||||
|
in the following examples.
|
||||||
|
|
||||||
We use the `-o yaml` output format so that the name, namespace, and uid are all
|
#### Set the Node to use the new configuration
|
||||||
reported following creation. We will need these in the next step. We will refer
|
|
||||||
to the name as CONFIG_MAP_NAME and the uid as CONFIG_MAP_UID.
|
|
||||||
|
|
||||||
### Authorize your Node to read the new ConfigMap
|
|
||||||
|
|
||||||
Now that you've created a new ConfigMap, you need to authorize your node to
|
|
||||||
read it. First, create a Role for your new ConfigMap with the
|
|
||||||
following commands:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ export CONFIG_MAP_NAME=name-from-previous-output
|
|
||||||
$ kubectl -n kube-system create role ${CONFIG_MAP_NAME}-reader --verb=get --resource=configmap --resource-name=${CONFIG_MAP_NAME}
|
|
||||||
```
|
|
||||||
|
|
||||||
Next, create a RoleBinding to associate your Node with the new Role:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ kubectl -n kube-system create rolebinding ${CONFIG_MAP_NAME}-reader --role=${CONFIG_MAP_NAME}-reader --user=system:node:${NODE_NAME}
|
|
||||||
```
|
|
||||||
|
|
||||||
Once the Node Authorizer is updated to do this automatically, you will
|
|
||||||
be able to skip this step.
|
|
||||||
|
|
||||||
### Set the Node to use the new configuration
|
|
||||||
|
|
||||||
Edit the Node's reference to point to the new ConfigMap with the
|
Edit the Node's reference to point to the new ConfigMap with the
|
||||||
following command:
|
following command:
|
||||||
|
|
||||||
```
|
```bash
|
||||||
kubectl edit node ${NODE_NAME}
|
kubectl edit node ${NODE_NAME}
|
||||||
```
|
```
|
||||||
|
|
||||||
Once in your editor, add the following YAML under `spec`:
|
In your text editor, add the following YAML under `spec`:
|
||||||
|
|
||||||
```
|
```yaml
|
||||||
configSource:
|
configSource:
|
||||||
configMapRef:
|
configMap:
|
||||||
name: CONFIG_MAP_NAME
|
name: CONFIG_MAP_NAME
|
||||||
namespace: kube-system
|
namespace: kube-system
|
||||||
uid: CONFIG_MAP_UID
|
kubeletConfigKey: kubelet
|
||||||
```
|
```
|
||||||
|
|
||||||
Be sure to specify all three of `name`, `namespace`, and `uid`.
|
You must specify all three of `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
|
#### Observe that the Node begins using the new configuration
|
||||||
|
|
||||||
Retrieve the Node with `kubectl get node ${NODE_NAME} -o yaml`, and look for the
|
Retrieve the Node using the `kubectl get node ${NODE_NAME} -o yaml` command and inspect
|
||||||
`KubeletConfigOK` condition in `status.conditions`. You should see the message
|
`Node.Status.Config`. The config sources corresponding to the `active`,
|
||||||
`Using current (UID: CONFIG_MAP_UID)` when the Kubelet starts using the new
|
`assigned`, and `lastKnownGood` configurations are reported in the status.
|
||||||
configuration.
|
|
||||||
|
|
||||||
For convenience, you can use the following command (using `jq`) to filter down
|
- The `active` configuration is the version the Kubelet is currently running with.
|
||||||
to the `KubeletConfigOK` condition:
|
- The `assigned` configuration is the latest version the Kubelet has resolved based on
|
||||||
|
`Node.Spec.ConfigSource`.
|
||||||
|
- The `lastKnownGood` configuration is the version the
|
||||||
|
Kubelet will fall back to if an invalid config is assigned in `Node.Spec.ConfigSource`.
|
||||||
|
|
||||||
|
The`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.
|
||||||
|
|
||||||
|
You can use the following command (using `jq`) to filter down
|
||||||
|
to the config status:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get no ${NODE_NAME} -o json | jq '.status.config'
|
||||||
```
|
```
|
||||||
$ kubectl get no ${NODE_NAME} -o json | jq '.status.conditions|map(select(.type=="KubeletConfigOK"))'
|
|
||||||
[
|
The following is an example response:
|
||||||
{
|
|
||||||
"lastHeartbeatTime": "2017-09-20T18:08:29Z",
|
```json
|
||||||
"lastTransitionTime": "2017-09-20T18:08:17Z",
|
{
|
||||||
"message": "using current: /api/v1/namespaces/kube-system/configmaps/my-node-config-gkt4c2m4b2",
|
"active": {
|
||||||
"reason": "passing all checks",
|
"configMap": {
|
||||||
"status": "True",
|
"kubeletConfigKey": "kubelet",
|
||||||
"type": "KubeletConfigOK"
|
"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"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
```
|
|
||||||
|
|
||||||
If something goes wrong, you may see one of several different error conditions,
|
|
||||||
detailed in the table of KubeletConfigOK conditions, below. When this happens, you
|
|
||||||
should check the Kubelet's log for more details.
|
|
||||||
|
|
||||||
### Edit the configuration file again
|
|
||||||
|
|
||||||
To change the configuration again, we simply repeat the above workflow.
|
|
||||||
Try editing the `kubelet` file, changing the previously changed parameter to a
|
|
||||||
new value.
|
|
||||||
|
|
||||||
### Push the newly edited configuration to the control plane
|
|
||||||
|
|
||||||
Push the new configuration to the control plane in a new ConfigMap with the
|
|
||||||
following command:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ kubectl create configmap my-node-config --namespace=kube-system --from-file=kubelet=kubelet_configz_${NODE_NAME} --append-hash -o yaml
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This new ConfigMap will get a new name, as we have changed the contents.
|
If an error occurs, the Kubelet reports it in the `Node.Status.Config.Error`
|
||||||
We will refer to the new name as NEW_CONFIG_MAP_NAME and the new uid
|
structure. Possible errors are listed in
|
||||||
as NEW_CONFIG_MAP_UID.
|
[Understanding Node.Status.Config.Error messages](#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.
|
||||||
|
|
||||||
### Authorize your Node to read the new ConfigMap
|
#### Make more changes
|
||||||
|
|
||||||
Now that you've created a new ConfigMap, you need to authorize your node to
|
Follow the workflow above to make more changes and push them again. Each time
|
||||||
read it. First, create a Role for your new ConfigMap with the
|
you push a ConfigMap with new contents, the --append-hash kubectl option creates
|
||||||
following commands:
|
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
|
||||||
$ export NEW_CONFIG_MAP_NAME=name-from-previous-output
|
|
||||||
$ kubectl -n kube-system create role ${NEW_CONFIG_MAP_NAME}-reader --verb=get --resource=configmap --resource-name=${NEW_CONFIG_MAP_NAME}
|
|
||||||
```
|
|
||||||
|
|
||||||
Next, create a RoleBinding to associate your Node with the new Role:
|
To reset the Node to use the configuration it was provisioned with, edit the
|
||||||
|
Node using `kubectl edit node ${NODE_NAME}` and remove the
|
||||||
|
`Node.Spec.ConfigSource` field.
|
||||||
|
|
||||||
```
|
#### Observe that the Node is using its local default configuration
|
||||||
$ kubectl -n kube-system create rolebinding ${NEW_CONFIG_MAP_NAME}-reader --role=${NEW_CONFIG_MAP_NAME}-reader --user=system:node:${NODE_NAME}
|
|
||||||
```
|
|
||||||
|
|
||||||
Once the Node Authorizer is updated to do this automatically, you will
|
After removing this subfield, `Node.Status.Config` eventually becomes
|
||||||
be able to skip this step.
|
empty, since all config sources have been reset to `nil`, which indicates that
|
||||||
|
the local default config is `assigned`, `active`, and `lastKnownGood`, and no
|
||||||
### Configure the Node to use the new configuration
|
error is reported.
|
||||||
|
|
||||||
Once more, edit the Node's `spec.configSource` with
|
|
||||||
`kubectl edit node ${NODE_NAME}`. Your new `spec.configSource` should look like
|
|
||||||
the following, with `name` and `uid` substituted as necessary:
|
|
||||||
|
|
||||||
```
|
|
||||||
configSource:
|
|
||||||
configMapRef:
|
|
||||||
name: ${NEW_CONFIG_MAP_NAME}
|
|
||||||
namespace: kube-system
|
|
||||||
uid: ${NEW_CONFIG_MAP_UID}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Observe that the Kubelet is using the new configuration
|
|
||||||
|
|
||||||
Once more, retrieve the Node with `kubectl get node ${NODE_NAME} -o yaml`, and
|
|
||||||
look for the `KubeletConfigOK` condition in `status.conditions`. You should see the message
|
|
||||||
`using current: /api/v1/namespaces/kube-system/configmaps/${NEW_CONFIG_MAP_NAME}` when the Kubelet starts using the
|
|
||||||
new configuration.
|
|
||||||
|
|
||||||
### Deauthorize your Node from reading the old ConfigMap
|
|
||||||
|
|
||||||
Once you know your Node is using the new configuration and are confident that
|
|
||||||
the new configuration has not caused any problems, it is a good idea to
|
|
||||||
deauthorize the node from reading the old ConfigMap. Run the following
|
|
||||||
commands to remove the RoleBinding and Role:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ kubectl -n kube-system delete rolebinding ${CONFIG_MAP_NAME}-reader
|
|
||||||
$ kubectl -n kube-system delete role ${CONFIG_MAP_NAME}-reader
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that this does not necessarily prevent the Node from reverting to the old
|
|
||||||
configuration, as it may locally cache the old ConfigMap for an indefinite
|
|
||||||
period of time.
|
|
||||||
|
|
||||||
You may optionally also choose to remove the old ConfigMap:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ kubectl -n kube-system delete configmap ${CONFIG_MAP_NAME}
|
|
||||||
```
|
|
||||||
|
|
||||||
Once the Node Authorizer is updated to do this automatically, you will
|
|
||||||
be able to skip this step.
|
|
||||||
|
|
||||||
### Reset the Node to use its local default configuration
|
|
||||||
|
|
||||||
Finally, if you wish to reset the Node to use the configuration it was
|
|
||||||
provisioned with, simply edit the Node with `kubectl edit node ${NODE_NAME}` and
|
|
||||||
remove the `spec.configSource` subfield.
|
|
||||||
|
|
||||||
### Observe that the Node is using its local default configuration
|
|
||||||
|
|
||||||
After removing this subfield, you should eventually observe that the KubeletConfigOK
|
|
||||||
condition's message reverts to `using current: local`.
|
|
||||||
|
|
||||||
### Deauthorize your Node from reading the old ConfigMap
|
|
||||||
|
|
||||||
Once you know your Node is using the default configuration again, it is a good
|
|
||||||
idea to deauthorize the node from reading the old ConfigMap. Run the following
|
|
||||||
commands to remove the RoleBinding and Role:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ kubectl -n kube-system delete rolebinding ${NEW_CONFIG_MAP_NAME}-reader
|
|
||||||
$ kubectl -n kube-system delete role ${NEW_CONFIG_MAP_NAME}-reader
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that this does not necessarily prevent the Node from reverting to the old
|
|
||||||
ConfigMap, as it may locally cache the old ConfigMap for an indefinite
|
|
||||||
period of time.
|
|
||||||
|
|
||||||
You may optionally also choose to remove the old ConfigMap:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ kubectl -n kube-system delete configmap ${NEW_CONFIG_MAP_NAME}
|
|
||||||
```
|
|
||||||
|
|
||||||
Once the Node Authorizer is updated to do this automatically, you will
|
|
||||||
be able to skip this step.
|
|
||||||
|
|
||||||
{{% /capture %}}
|
{{% /capture %}}
|
||||||
|
|
||||||
{{% capture discussion %}}
|
{{% capture discussion %}}
|
||||||
## Kubectl Patch Example
|
## Kubectl Patch Example
|
||||||
As mentioned above, there are many ways to change a Node's configSource.
|
|
||||||
Here is an example command that uses `kubectl patch`:
|
|
||||||
|
|
||||||
```
|
You can change a Node's configSource using several different mechanisms.
|
||||||
kubectl patch node ${NODE_NAME} -p "{\"spec\":{\"configSource\":{\"configMapRef\":{\"name\":\"${CONFIG_MAP_NAME}\",\"namespace\":\"kube-system\",\"uid\":\"${CONFIG_MAP_UID}\"}}}}"
|
This example uses `kubectl patch`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl patch node ${NODE_NAME} -p "{\"spec\":{\"configSource\":{\"configMap\":{\"name\":\"${CONFIG_MAP_NAME}\",\"namespace\":\"kube-system\",\"kubeletConfigKey\":\"kubelet\"}}}}"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Understanding KubeletConfigOK Conditions
|
## Understanding how the Kubelet checkpoints config
|
||||||
|
|
||||||
The following table describes several of the `KubeletConfigOK` Node conditions you
|
When a new config is assigned to the Node, the Kubelet downloads and unpacks the
|
||||||
might encounter in a cluster that has Dynamic Kubelet Config enabled. If you
|
config payload as a set of files on the local disk. The Kubelet also records metadata
|
||||||
observe a condition with `status=False`, you should check the Kubelet log for
|
that locally tracks the assigned and last-known-good config sources, so that the
|
||||||
more error details by searching for the message or reason text.
|
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 `systemd`), it reads the new
|
||||||
|
metadata and uses the new config.
|
||||||
|
|
||||||
|
The recorded metadata is fully resolved, meaning that it contains all necessary
|
||||||
|
information to choose a specific config version - typically a `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.
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
```none
|
||||||
|
- --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
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
|
|
||||||
|
|
||||||
<table align="left">
|
<table align="left">
|
||||||
<tr>
|
<tr>
|
||||||
<th>Possible Messages</th>
|
<th>Error Message</th>
|
||||||
<th>Possible Reasons</th>
|
<th>Possible Causes</th>
|
||||||
<th>Status</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><p>using current: local</p></td>
|
<td><p>failed to load config, see Kubelet log for details</p></td>
|
||||||
<td><p>when the config source is nil, the Kubelet uses its local config</p></td>
|
<td><p>The Kubelet likely could not parse the downloaded config payload, or encountered a filesystem error attempting to load the payload from disk.</p></td>
|
||||||
<td><p>True</p></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><p>using current: /api/v1/namespaces/${CURRENT_CONFIG_MAP_NAMESPACE}/configmaps/${CURRENT_CONFIG_MAP_NAME}</p></td>
|
<td><p>failed to validate config, see Kubelet log for details</p></td>
|
||||||
<td><p>passing all checks</p></td>
|
<td><p>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.</p></td>
|
||||||
<td><p>True</p></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><p>using last-known-good: local</p></td>
|
<td><p>invalid NodeConfigSource, exactly one subfield must be non-nil, but all were nil</p></td>
|
||||||
<td>
|
<td><p>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.</p></td>
|
||||||
<ul>
|
|
||||||
<li>failed to load current: /api/v1/namespaces/${CURRENT_CONFIG_MAP_NAMESPACE}/configmaps/${CURRENT_CONFIG_MAP_NAME}</li>
|
|
||||||
<li>failed to parse current: /api/v1/namespaces/${CURRENT_CONFIG_MAP_NAMESPACE}/configmaps/${CURRENT_CONFIG_MAP_NAME}</li>
|
|
||||||
<li>failed to validate current: /api/v1/namespaces/${CURRENT_CONFIG_MAP_NAMESPACE}/configmaps/${CURRENT_CONFIG_MAP_NAME}</li>
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
<td><p>False</p></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><p>using last-known-good: /api/v1/namespaces/${LAST_KNOWN_GOOD_CONFIG_MAP_NAMESPACE}/configmaps/${LAST_KNOWN_GOOD_CONFIG_MAP_NAME}</p></td>
|
<td><p>failed to sync: failed to download config, see Kubelet log for details</p></td>
|
||||||
<td>
|
<td><p>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.</p></td>
|
||||||
<ul>
|
|
||||||
<li>failed to load current: /api/v1/namespaces/${CURRENT_CONFIG_MAP_NAMESPACE}/configmaps/${CURRENT_CONFIG_MAP_NAME}</li>
|
|
||||||
<li>failed to parse current: /api/v1/namespaces/${CURRENT_CONFIG_MAP_NAMESPACE}/configmaps/${CURRENT_CONFIG_MAP_NAME}</li>
|
|
||||||
<li>failed to validate current: /api/v1/namespaces/${CURRENT_CONFIG_MAP_NAMESPACE}/configmaps/${CURRENT_CONFIG_MAP_NAME}</li>
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
<td><p>False</p></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td><p>failed to sync: internal failure, see Kubelet log for details</p></td>
|
||||||
<p>
|
<td><p>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.</p></td>
|
||||||
The reasons in the next column could potentially appear for any of
|
</tr>
|
||||||
the above messages.
|
<tr>
|
||||||
</p>
|
<td><p>internal failure, see Kubelet log for details</p></td>
|
||||||
<p>
|
<td><p>The Kubelet encountered some internal problem while manipulating config, outside of the configuration sync loop.</p></td>
|
||||||
This condition indicates that the Kubelet is having trouble
|
|
||||||
reconciling `spec.configSource`, and thus no change to the in-use
|
|
||||||
configuration has occurred.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
The "failed to sync" reasons are specific to the failure that
|
|
||||||
occurred, and the next column does not necessarily contain all
|
|
||||||
possible failure reasons.
|
|
||||||
</p>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<p>failed to sync, reason:</p>
|
|
||||||
<ul>
|
|
||||||
<li>failed to read Node from informer object cache</li>
|
|
||||||
<li>failed to reset to local config</li>
|
|
||||||
<li>invalid NodeConfigSource, exactly one subfield must be non-nil, but all were nil</li>
|
|
||||||
<li>invalid ObjectReference, all of UID, Name, and Namespace must be specified</li>
|
|
||||||
<li>invalid ConfigSource.ConfigMapRef.UID: ${UID} does not match ${API_PATH}.UID: ${UID_OF_CONFIG_MAP_AT_API_PATH}</li>
|
|
||||||
<li>failed to determine whether object ${API_PATH} with UID ${UID} was already checkpointed</li>
|
|
||||||
<li>failed to download ConfigMap with name ${NAME} from namespace ${NAMESPACE}</li>
|
|
||||||
<li>failed to save config checkpoint for object ${API_PATH} with UID ${UID}</li>
|
|
||||||
<li>failed to set current config checkpoint to local config</li>
|
|
||||||
<li>failed to set current config checkpoint to object ${API_PATH} with UID ${UID}</li>
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
<td><p>False</p></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
{{% /capture %}}
|
{{% /capture %}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user