通过配置文件设置 kubelet 参数

准备开始

此页面中的某些步骤使用 jq 工具。如果你没有 jq,你可以通过操作系统的软件源安装它,或者从 https://jqlang.github.io/jq/ 中获取它。

某些步骤还涉及安装 curl,它可以通过操作系统的软件源安装。

通过保存在硬盘的配置文件设置 kubelet 的部分配置参数,这可以作为命令行参数的替代。

建议通过配置文件的方式提供参数,因为这样可以简化节点部署和配置管理。

创建配置文件

KubeletConfiguration 结构体定义了可以通过文件配置的 kubelet 配置子集,

配置文件必须是这个结构体中参数的 JSON 或 YAML 表现形式。 确保 kubelet 可以读取该文件。

下面是一个 kubelet 配置文件示例:

  1. apiVersion: kubelet.config.k8s.io/v1beta1
  2. kind: KubeletConfiguration
  3. address: "192.168.0.8"
  4. port: 20250
  5. serializeImagePulls: false
  6. evictionHard:
  7. memory.available: "100Mi"
  8. nodefs.available: "10%"
  9. nodefs.inodesFree: "5%"
  10. imagefs.available: "15%"

在此示例中,kubelet 配置为以下设置:

  1. address:kubelet 将在 192.168.0.8 IP 地址上提供服务。
  2. port:kubelet 将在 20250 端口上提供服务。
  3. serializeImagePulls:并行拉取镜像。
  4. evictionHard:kubelet 将在以下情况之一驱逐 Pod:
    • 当节点的可用内存降至 100MiB 以下时。
    • 当节点主文件系统的已使用 inode 超过 95%。
    • 当镜像文件系统的可用空间小于 15% 时。
    • 当节点主文件系统的 inode 超过 95% 正在使用时。

说明:

在示例中,通过只更改 evictionHard 的一个参数的默认值, 其他参数的默认值将不会被继承,他们会被设置为零。如果要提供自定义值,你应该分别设置所有阈值。

imagefs 是一个可选的文件系统,容器运行时使用它来存储容器镜像和容器可写层。

启动通过配置文件配置的 kubelet 进程

说明:

如果你使用 kubeadm 初始化你的集群,在使用 kubeadm init 创建你的集群的时候请使用 kubelet-config。 更多细节请阅读使用 kubeadm 配置 kubelet

启动 kubelet 需要将 --config 参数设置为 kubelet 配置文件的路径。kubelet 将从此文件加载其配置。

请注意,命令行参数与配置文件有相同的值时,就会覆盖配置文件中的该值。 这有助于确保命令行 API 的向后兼容性。

请注意,kubelet 配置文件中的相对文件路径是相对于 kubelet 配置文件的位置解析的, 而命令行参数中的相对路径是相对于 kubelet 的当前工作目录解析的。

请注意,命令行参数和 kubelet 配置文件的某些默认值不同。 如果设置了 --config,并且没有通过命令行指定值,则 KubeletConfiguration 版本的默认值生效。在上面的例子中,version 是 kubelet.config.k8s.io/v1beta1

kubelet 配置文件的插件目录

特性状态: Kubernetes v1.30 [beta]

你可以为 kubelet 指定一个插件配置目录。默认情况下,kubelet 不会在任何地方查找插件配置文件 - 你必须指定路径。 例如:--config-dir=/etc/kubernetes/kubelet.conf.d

对于 Kubernetes v1.28 到 v1.29,如果你还为 kubelet 进程设置了环境变量 KUBELET_CONFIG_DROPIN_DIR_ALPHA(该变量的值无关紧要), 则只能指定 --config-dir

说明:

合法的 kubelet 插件配置文件的后缀必须.conf。例如 99-kubelet-address.conf

kubelet 通过按字母数字顺序对整个文件名进行排序来处理其配置插件目录中的文件。 例如,首先处理 00-kubelet.conf,然后用名为 01-kubelet.conf 的文件覆盖。

这些文件可能包含部分配置,但不应无效,并且必须包含类型元数据,特别是 apiVersionkind。 仅对 kubelet 内部存储的、最终生成的配置结构执行验证。 这为管理和合并来自不同来源的 kubelet 配置提供了灵活性,同时防止了不需要的配置。 但是,请务必注意,产生的行为会根据配置字段的数据类型而有所不同。

kubelet 配置结构中不同数据类型的合并方式不同。 有关详细信息,请参阅参考文档

kubelet 配置合并顺序

在启动时,kubelet 会合并来自以下几部分的配置:

  • 在命令行中指定的特性门控(优先级最低)。
  • kubelet 配置文件。
  • 排序的插件配置文件。
  • 不包括特性门控的命令行参数(优先级最高)。

说明:

kubelet 的配置插件目录机制类似,但与 kubeadm 工具允许 patch 配置的方式不同。 kubeadm 工具使用特定的补丁策略, 而 kubelet 配置插件文件的唯一补丁策略是 replace。kubelet 根据字母数字对后缀进行排序来确定合并顺序, 并替换更高优先级文件中存在的每个字段。

查看 kubelet 配置

由于现在可以使用此特性将配置分布在多个文件中,因此如果有人想要检查最终启动的配置, 他们可以按照以下步骤检查 kubelet 配置:

  1. 在终端中使用 kubectl proxy 启动代理服务器。

    1. kubectl proxy

    其输出如下:

    1. Starting to serve on 127.0.0.1:8001
  2. 打开另一个终端窗口并使用 curl 来获取 kubelet 配置。 将 <node-name> 替换为节点的实际名称:

    1. curl -X GET http://127.0.0.1:8001/api/v1/nodes/<node-name>/proxy/configz | jq .
    1. {
    2. "kubeletconfig": {
    3. "enableServer": true,
    4. "staticPodPath": "/var/run/kubernetes/static-pods",
    5. "syncFrequency": "1m0s",
    6. "fileCheckFrequency": "20s",
    7. "httpCheckFrequency": "20s",
    8. "address": "192.168.1.16",
    9. "port": 10250,
    10. "readOnlyPort": 10255,
    11. "tlsCertFile": "/var/lib/kubelet/pki/kubelet.crt",
    12. "tlsPrivateKeyFile": "/var/lib/kubelet/pki/kubelet.key",
    13. "rotateCertificates": true,
    14. "authentication": {
    15. "x509": {
    16. "clientCAFile": "/var/run/kubernetes/client-ca.crt"
    17. },
    18. "webhook": {
    19. "enabled": true,
    20. "cacheTTL": "2m0s"
    21. },
    22. "anonymous": {
    23. "enabled": true
    24. }
    25. },
    26. "authorization": {
    27. "mode": "AlwaysAllow",
    28. "webhook": {
    29. "cacheAuthorizedTTL": "5m0s",
    30. "cacheUnauthorizedTTL": "30s"
    31. }
    32. },
    33. "registryPullQPS": 5,
    34. "registryBurst": 10,
    35. "eventRecordQPS": 50,
    36. "eventBurst": 100,
    37. "enableDebuggingHandlers": true,
    38. "healthzPort": 10248,
    39. "healthzBindAddress": "127.0.0.1",
    40. "oomScoreAdj": -999,
    41. "clusterDomain": "cluster.local",
    42. "clusterDNS": [
    43. "10.0.0.10"
    44. ],
    45. "streamingConnectionIdleTimeout": "4h0m0s",
    46. "nodeStatusUpdateFrequency": "10s",
    47. "nodeStatusReportFrequency": "5m0s",
    48. "nodeLeaseDurationSeconds": 40,
    49. "imageMinimumGCAge": "2m0s",
    50. "imageMaximumGCAge": "0s",
    51. "imageGCHighThresholdPercent": 85,
    52. "imageGCLowThresholdPercent": 80,
    53. "volumeStatsAggPeriod": "1m0s",
    54. "cgroupsPerQOS": true,
    55. "cgroupDriver": "systemd",
    56. "cpuManagerPolicy": "none",
    57. "cpuManagerReconcilePeriod": "10s",
    58. "memoryManagerPolicy": "None",
    59. "topologyManagerPolicy": "none",
    60. "topologyManagerScope": "container",
    61. "runtimeRequestTimeout": "2m0s",
    62. "hairpinMode": "promiscuous-bridge",
    63. "maxPods": 110,
    64. "podPidsLimit": -1,
    65. "resolvConf": "/run/systemd/resolve/resolv.conf",
    66. "cpuCFSQuota": true,
    67. "cpuCFSQuotaPeriod": "100ms",
    68. "nodeStatusMaxImages": 50,
    69. "maxOpenFiles": 1000000,
    70. "contentType": "application/vnd.kubernetes.protobuf",
    71. "kubeAPIQPS": 50,
    72. "kubeAPIBurst": 100,
    73. "serializeImagePulls": true,
    74. "evictionHard": {
    75. "imagefs.available": "15%",
    76. "memory.available": "100Mi",
    77. "nodefs.available": "10%",
    78. "nodefs.inodesFree": "5%"
    79. },
    80. "evictionPressureTransitionPeriod": "1m0s",
    81. "enableControllerAttachDetach": true,
    82. "makeIPTablesUtilChains": true,
    83. "iptablesMasqueradeBit": 14,
    84. "iptablesDropBit": 15,
    85. "featureGates": {
    86. "AllAlpha": false
    87. },
    88. "failSwapOn": false,
    89. "memorySwap": {},
    90. "containerLogMaxSize": "10Mi",
    91. "containerLogMaxFiles": 5,
    92. "configMapAndSecretChangeDetectionStrategy": "Watch",
    93. "enforceNodeAllocatable": [
    94. "pods"
    95. ],
    96. "volumePluginDir": "/usr/libexec/kubernetes/kubelet-plugins/volume/exec/",
    97. "logging": {
    98. "format": "text",
    99. "flushFrequency": "5s",
    100. "verbosity": 3,
    101. "options": {
    102. "json": {
    103. "infoBufferSize": "0"
    104. }
    105. }
    106. },
    107. "enableSystemLogHandler": true,
    108. "enableSystemLogQuery": false,
    109. "shutdownGracePeriod": "0s",
    110. "shutdownGracePeriodCriticalPods": "0s",
    111. "enableProfilingHandler": true,
    112. "enableDebugFlagsHandler": true,
    113. "seccompDefault": false,
    114. "memoryThrottlingFactor": 0.9,
    115. "registerNode": true,
    116. "localStorageCapacityIsolation": true,
    117. "containerRuntimeEndpoint": "unix:///var/run/crio/crio.sock"
    118. }
    119. }

接下来