静态 Pod 由特定节点上的 kubelet 守护进程直接管理,无需 API 服务器 观察它们。与由控制平面管理的 Pod(例如 Deployment)不同;相反,kubelet 会监控每个静态 Pod(并在其失败时重启它)。
静态 Pod 总是绑定到特定节点上的一个 Kubelet。
对于每个静态 Pod,kubelet 会自动在 Kubernetes API 服务器上创建一个 镜像 Pod。这意味着在节点上运行的 Pod 在 API 服务器上是可见的,但无法从那里进行控制。Pod 名称将以节点主机名作为后缀,中间由连字符分隔。
你需要有一个 Kubernetes 集群,并且必须配置 kubectl 命令行工具以与你的集群通信。建议在至少有两个节点的集群上运行本教程,且这些节点不能作为控制平面主机。如果你还没有集群,可以通过 minikube 创建一个,或者使用以下 Kubernetes 演练场之一。
要检查版本,请输入 kubectl version。
本页面假设你正在使用 CRI-O 来运行 Pod,并且你的节点运行的是 Fedora 操作系统。对于其他发行版或 Kubernetes 安装,说明可能会有所不同。
你可以使用 文件系统托管的配置文件 或 Web 托管的配置文件 来配置静态 Pod。
清单是 JSON 或 YAML 格式的标准 Pod 定义,存放在特定目录中。在 kubelet 配置文件 中使用 staticPodPath: <目录> 字段,kubelet 会定期扫描该目录,并在 YAML/JSON 文件出现或消失时创建/删除静态 Pod。请注意,kubelet 在扫描指定目录时会忽略以点开头的文件。
cp kube-apiserver.yaml kube-apiserver.yaml.backup 来创建清单的备份,kubelet 将读取 两个 文件,并尝试从每个文件中创建静态 Pod。当两个文件定义了同名 Pod 时,最终行为是未定义的,并且可能导致备份的过时规范悄悄生效,而不是当前的清单。如果你确实需要创建备份,请将其存储在静态 Pod 目录 之外(例如 /etc/kubernetes/backup/)。例如,下面是如何将简单的 Web 服务器作为静态 Pod 启动的方法:
选择一个你想要运行静态 Pod 的节点。在本例中,它是 my-node1。
ssh my-node1
选择一个目录,例如 /etc/kubernetes/manifests,并将 Web 服务器 Pod 定义放在那里,例如 /etc/kubernetes/manifests/static-web.yaml
# Run this command on the node where kubelet is running
mkdir -p /etc/kubernetes/manifests/
cat <<EOF >/etc/kubernetes/manifests/static-web.yaml
apiVersion: v1
kind: Pod
metadata:
name: static-web
labels:
role: myrole
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
protocol: TCP
EOF
在该节点上配置 kubelet,在 kubelet 配置文件 中设置 staticPodPath 的值。
有关详细信息,请参阅 通过配置文件设置 Kubelet 参数。
另一种已弃用的方法是使用命令行参数配置该节点上的 kubelet 以在本地查找静态 Pod 清单。要使用这种已弃用的方法,启动 kubelet 时带上--pod-manifest-path=/etc/kubernetes/manifests/ 参数。
重启 kubelet。在 Fedora 上,你会运行
# Run this command on the node where the kubelet is running
systemctl restart kubelet
kubelet 会定期下载由 --manifest-url=<URL> 参数指定的文件,并将其解释为包含 Pod 定义的 JSON/YAML 文件。与 文件系统托管的清单 的工作方式类似,kubelet 会按计划重新获取清单。如果静态 Pod 列表发生了变化,kubelet 会应用这些更改。
要使用这种方法:
创建一个 YAML 文件并将其存储在 Web 服务器上,以便你可以将该文件的 URL 传递给 kubelet。
apiVersion: v1
kind: Pod
metadata:
name: static-web
labels:
role: myrole
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
protocol: TCP
通过运行带 --manifest-url=<manifest-url> 参数的 kubelet,在选定的节点上配置它以使用此 Web 清单。在 Fedora 上,编辑 /etc/kubernetes/kubelet 以包含此行:
KUBELET_ARGS="--cluster-dns=10.254.0.10 --cluster-domain=kube.local --manifest-url=<manifest-url>"
重启 kubelet。在 Fedora 上,你会运行
# Run this command on the node where the kubelet is running
systemctl restart kubelet
当 kubelet 启动时,它会自动启动所有定义的静态 Pod。由于你已经定义了静态 Pod 并重启了 kubelet,新的静态 Pod 应该已经在运行了。
你可以通过运行(在节点上)来查看正在运行的容器(包括静态 Pod):
# Run this command on the node where the kubelet is running
crictl ps
输出可能如下所示:
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
129fd7d382018 docker.io/library/nginx@sha256:... 11 minutes ago Running web 0 34533c6729106
crictl 会输出镜像 URI 和 SHA-256 校验和。NAME 看起来更像:docker.io/library/nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31。你可以在 API 服务器上看到镜像 Pod:
kubectl get pods
NAME READY STATUS RESTARTS AGE
static-web-my-node1 1/1 Running 0 2m
静态 Pod 的 标签 (Labels) 会传播到镜像 Pod 中。你可以通过 选择器 (selectors) 等正常使用这些标签。
如果你尝试使用 kubectl 从 API 服务器删除镜像 Pod,kubelet 不会 删除静态 Pod:
kubectl delete pod static-web-my-node1
pod "static-web-my-node1" deleted
你可以看到 Pod 仍在运行:
kubectl get pods
NAME READY STATUS RESTARTS AGE
static-web-my-node1 1/1 Running 0 4s
回到运行 kubelet 的节点上,你可以尝试手动停止容器。你会发现,过一段时间后,kubelet 会注意到并自动重启该 Pod:
# Run these commands on the node where the kubelet is running
crictl stop 129fd7d382018 # replace with the ID of your container
sleep 20
crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
89db4553e1eeb docker.io/library/nginx@sha256:... 19 seconds ago Running web 1 34533c6729106
一旦确定了正确的容器,你可以使用 crictl 获取该容器的日志:
# Run these commands on the node where the container is running
crictl logs <container_id>
10.240.0.48 - - [16/Nov/2022:12:45:49 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"
10.240.0.48 - - [16/Nov/2022:12:45:50 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"
10.240.0.48 - - [16/Nove/2022:12:45:51 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"
要了解更多关于如何使用 crictl 进行调试的信息,请访问 使用 crictl 调试 Kubernetes 节点。
正在运行的 kubelet 会定期扫描配置的目录(在本例中为 /etc/kubernetes/manifests)以查找更改,并在该目录中出现/消失文件时添加/删除 Pod。
# This assumes you are using filesystem-hosted static Pod configuration
# Run these commands on the node where the container is running
#
mv /etc/kubernetes/manifests/static-web.yaml /tmp
sleep 20
crictl ps
# You see that no nginx container is running
mv /tmp/static-web.yaml /etc/kubernetes/manifests/
sleep 20
crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
f427638871c35 docker.io/library/nginx@sha256:... 19 seconds ago Running web 1 34533c6729106
crictl 调试 Kubernetes 节点crictl 的信息