以独立模式运行 kubelet

本教程将向你展示如何运行一个独立的 kubelet 实例。

你可能会有不同的动机来运行一个独立的 kubelet。 本教程旨在向你介绍 Kubernetes,即使你对此并没有太多经验也没有关系。 你可以跟随本教程学习节点设置、基本(静态)Pod 以及 Kubernetes 如何管理容器。

你学习完本教程后,就可以尝试使用带一个控制平面的集群来管理 Pod、节点和其他类别的对象。例如,你好,Minikube

你还可以以独立模式运行 kubelet 来满足生产场景要求,例如为高可用、弹性部署的集群运行控制平面。 本教程不涵盖运行弹性控制平面所需的细节。

教程目标

  • 在 Linux 系统上安装 cri-okubelet,并将其作为 systemd 服务运行。
  • 启动一个运行 nginx 的 Pod,监听针对此 Pod 的 IP 地址的 TCP 80 端口的请求。
  • 学习此方案中不同组件之间如何交互。

注意:

本教程中所使用的 kubelet 配置在设计上是不安全的,得用于生产环境中。

准备开始

  • 对使用 systemdiptables(或使用 iptables 仿真的 nftables)的 Linux 系统具有管理员(root)访问权限。
  • 有权限访问互联网以下载本教程所需的组件,例如:

准备好系统

配置内存交换

默认情况下,如果在节点上检测到内存交换,kubelet 将启动失败。 这意味着内存交换应该被禁用或被 kubelet 容忍。

说明:

如果你配置 kubelet 为容忍内存交换,则 kubelet 仍会配置 Pod(以及这些 Pod 中的容器)不使用交换空间。 要了解 Pod 实际上可以如何使用可用的交换,你可以进一步阅读 Linux 节点上交换内存管理

如果你启用了交换内存,则禁用它或在 kubelet 配置文件中添加 failSwapOn: false

要检查交换内存是否被启用:

  1. sudo swapon --show

如果此命令没有输出,则交换内存已被禁用。

临时禁用交换内存:

  1. sudo swapoff -a

要使此变更持续到重启之后:

确保在 /etc/fstabsystemd.swap 中禁用交换内存,具体取决于它在你的系统上是如何配置的。

启用 IPv4 数据包转发

检查 IPv4 数据包转发是否被启用:

  1. cat /proc/sys/net/ipv4/ip_forward

如果输出为 1,则 IPv4 数据包转发已被启用。如果输出为 0,按照以下步骤操作。

要启用 IPv4 数据包转发,创建一个配置文件,将 net.ipv4.ip_forward 参数设置为 1

  1. sudo tee /etc/sysctl.d/k8s.conf <<EOF
  2. net.ipv4.ip_forward = 1
  3. EOF

将变更应用到系统:

  1. sudo sysctl --system

输出类似于:

  1. ...
  2. * Applying /etc/sysctl.d/k8s.conf ...
  3. net.ipv4.ip_forward = 1
  4. * Applying /etc/sysctl.conf ...

下载、安装和配置组件

说明: 本部分链接到提供 Kubernetes 所需功能的第三方项目。Kubernetes 项目作者不负责这些项目。此页面遵循CNCF 网站指南,按字母顺序列出项目。要将项目添加到此列表中,请在提交更改之前阅读内容指南

安装容器运行时

下载所需软件包的最新可用版本(推荐)。

本教程建议安装 CRI-O 容器运行时(外部链接)。

根据你安装的特定 Linux 发行版,有几种安装容器运行时的方式。 尽管 CRI-O 推荐使用 debrpm 包,但本教程使用 CRI-O Packaging 项目中的静态二进制包脚本, 以简化整个安装过程,并保持与 Linux 发行版无关。

此脚本安装并配置更多必需的软件,例如容器联网所用的 cni-plugins 以及运行容器所用的 crunrunc

此脚本将自动检测系统的处理器架构(amd64arm64),并选择和安装最新版本的软件包。

设置 CRI-O

查阅发布版本页面(外部链接)。

下载静态二进制包脚本:

  1. curl https://raw.githubusercontent.com/cri-o/packaging/main/get > crio-install

运行安装器脚本:

  1. sudo bash crio-install

启用并启动 crio 服务:

  1. sudo systemctl daemon-reload
  2. sudo systemctl enable --now crio.service

快速测试:

  1. sudo systemctl is-active crio.service

输出类似于:

  1. active

详细的服务检查:

  1. sudo journalctl -f -u crio.service

安装网络插件

cri-o 安装器安装并配置 cni-plugins 包。你可以通过运行以下命令来验证安装包:

  1. /opt/cni/bin/bridge --version

输出类似于:

  1. CNI bridge plugin v1.5.1
  2. CNI protocol versions supported: 0.1.0, 0.2.0, 0.3.0, 0.3.1, 0.4.0, 1.0.0

检查默认配置:

  1. cat /etc/cni/net.d/11-crio-ipv4-bridge.conflist

输出类似于:

  1. {
  2. "cniVersion": "1.0.0",
  3. "name": "crio",
  4. "plugins": [
  5. {
  6. "type": "bridge",
  7. "bridge": "cni0",
  8. "isGateway": true,
  9. "ipMasq": true,
  10. "hairpinMode": true,
  11. "ipam": {
  12. "type": "host-local",
  13. "routes": [
  14. { "dst": "0.0.0.0/0" }
  15. ],
  16. "ranges": [
  17. [{ "subnet": "10.85.0.0/16" }]
  18. ]
  19. }
  20. }
  21. ]
  22. }

说明:

确保默认的 subnet 范围(10.85.0.0/16)不会与你已经在使用的任一网络地址重叠。 如果出现重叠,你可以编辑此文件并进行相应的更改。更改后重启服务。

下载并设置 kubelet

下载 kubelet 的最新稳定版本

  1. curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubelet"
  1. curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubelet"

配置:

  1. sudo mkdir -p /etc/kubernetes/manifests
  1. sudo tee /etc/kubernetes/kubelet.yaml <<EOF
  2. apiVersion: kubelet.config.k8s.io/v1beta1
  3. kind: KubeletConfiguration
  4. authentication:
  5. webhook:
  6. enabled: false # 请勿在生产集群中使用!
  7. authorization:
  8. mode: AlwaysAllow # 请勿在生产集群中使用!
  9. enableServer: false
  10. logging:
  11. format: text
  12. address: 127.0.0.1 # 限制对 localhost 的访问
  13. readOnlyPort: 10255 # 请勿在生产集群中使用!
  14. staticPodPath: /etc/kubernetes/manifests
  15. containerRuntimeEndpoint: unix:///var/run/crio/crio.sock
  16. EOF

说明:

由于你搭建的不是一个生产集群,所以你可以使用明文 HTTP(readOnlyPort: 10255)对 kubelet API 进行不做身份认证的查询。

为了顺利完成本次教学,身份认证 Webhook 被禁用,鉴权模式被设置为 AlwaysAllow。 你可以进一步了解鉴权模式Webhook 身份认证, 以正确地配置 kubelet 在你的环境中以独立模式运行。

参阅端口和协议以了解 Kubernetes 组件使用的端口。

安装:

  1. chmod +x kubelet
  2. sudo cp kubelet /usr/bin/

创建 systemd 服务单元文件:

  1. sudo tee /etc/systemd/system/kubelet.service <<EOF
  2. [Unit]
  3. Description=Kubelet
  4. [Service]
  5. ExecStart=/usr/bin/kubelet \
  6. --config=/etc/kubernetes/kubelet.yaml
  7. Restart=always
  8. [Install]
  9. WantedBy=multi-user.target
  10. EOF

服务配置文件中故意省略了命令行参数 --kubeconfig。此参数设置 kubeconfig 文件的路径,指定如何连接到 API 服务器,以启用 API 服务器模式。省略此参数将启用独立模式。

启用并启动 kubelet 服务:

  1. sudo systemctl daemon-reload
  2. sudo systemctl enable --now kubelet.service

快速测试:

  1. sudo systemctl is-active kubelet.service

输出类似于:

  1. active

详细的服务检查:

  1. sudo journalctl -u kubelet.service

检查 kubelet 的 API /healthz 端点:

  1. curl http://localhost:10255/healthz?verbose

输出类似于:

  1. [+]ping ok
  2. [+]log ok
  3. [+]syncloop ok
  4. healthz check passed

查询 kubelet 的 API /pods 端点:

  1. curl http://localhost:10255/pods | jq '.'

输出类似于:

  1. {
  2. "kind": "PodList",
  3. "apiVersion": "v1",
  4. "metadata": {},
  5. "items": null
  6. }

在 kubelet 中运行 Pod

在独立模式下,你可以使用 Pod 清单运行 Pod。这些清单可以放在本地文件系统上,或通过 HTTP 从配置源获取。

为 Pod 创建一个清单:

  1. cat <<EOF > static-web.yaml
  2. apiVersion: v1
  3. kind: Pod
  4. metadata:
  5. name: static-web
  6. spec:
  7. containers:
  8. - name: web
  9. image: nginx
  10. ports:
  11. - name: web
  12. containerPort: 80
  13. protocol: TCP
  14. EOF

static-web.yaml 清单文件复制到 /etc/kubernetes/manifests 目录。

  1. sudo cp static-web.yaml /etc/kubernetes/manifests/

查找 kubelet 和 Pod 的信息

Pod 网络插件为每个 Pod 创建一个网络桥(cni0)和一对 veth 接口 (这对接口的其中一个接口在新创建的 Pod 内,另一个接口在主机层面)。

查询 kubelet 的 API 端点 http://localhost:10255/pods

  1. curl http://localhost:10255/pods | jq '.'

要获取 static-web Pod 的 IP 地址:

  1. curl http://localhost:10255/pods | jq '.items[].status.podIP'

输出类似于:

  1. "10.85.0.4"

连接到 nginx 服务器 Pod,地址为 http://<IP>:<Port>(端口 80 是默认端口),在本例中为:

  1. curl http://10.85.0.4

输出类似于:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Welcome to nginx!</title>
  5. ...

了解更多细节

如果你需要排查在学习本教程时遇到的问题,你可以在以下目录中查找监控和故障排查资料:

  1. /var/lib/cni
  2. /var/lib/containers
  3. /var/lib/kubelet
  4. /var/log/containers
  5. /var/log/pods

清理

kubelet

  1. sudo systemctl disable --now kubelet.service
  2. sudo systemctl daemon-reload
  3. sudo rm /etc/systemd/system/kubelet.service
  4. sudo rm /usr/bin/kubelet
  5. sudo rm -rf /etc/kubernetes
  6. sudo rm -rf /var/lib/kubelet
  7. sudo rm -rf /var/log/containers
  8. sudo rm -rf /var/log/pods

容器运行时

  1. sudo systemctl disable --now crio.service
  2. sudo systemctl daemon-reload
  3. sudo rm -rf /usr/local/bin
  4. sudo rm -rf /usr/local/lib
  5. sudo rm -rf /usr/local/share
  6. sudo rm -rf /usr/libexec/crio
  7. sudo rm -rf /etc/crio
  8. sudo rm -rf /etc/containers

网络插件

  1. sudo rm -rf /opt/cni
  2. sudo rm -rf /etc/cni
  3. sudo rm -rf /var/lib/cni

结论

本页涵盖了以独立模式部署 kubelet 的各个基本方面。你现在可以部署 Pod 并测试更多功能。

请注意,在独立模式下,kubelet 支持从控制平面获取 Pod 配置(因为没有控制平面连接)。

你还不能使用 ConfigMapSecret 来配置静态 Pod 中的容器。

接下来