静态Pod

在 Kubernetes 集群中除了我们经常使用到的普通的 Pod 外,还有一种特殊的 Pod,叫做Static Pod,也就是我们说的静态 Pod,静态 Pod 有什么特殊的地方呢?

静态 Pod 直接由节点上的 kubelet 进程来管理,不通过 master 节点上的 apiserver。无法与我们常用的控制器 Deployment 或者 DaemonSet 进行关联,它由 kubelet 进程自己来监控,当 pod 崩溃时会重启该 pod,kubelet 也无法对他们进行健康检查。静态 pod 始终绑定在某一个 kubelet 上,并且始终运行在同一个节点上。kubelet 会自动为每一个静态 pod 在 Kubernetes 的 apiserver 上创建一个镜像 Pod,因此我们可以在 apiserver 中查询到该 pod,但是不能通过 apiserver 进行控制(例如不能删除)。

创建静态 Pod 有两种方式:配置文件和HTTP两种方式,这里我们只记录常用的配置文件形式

配置文件

配置文件就是放在特定目录下的标准的 JSON 或 YAML 格式的 pod 定义文件。用kubelet --pod-manifest-path=来启动 kubelet 进程,kubelet 定期的去扫描这个目录,根据这个目录下出现或消失的 YAML/JSON 文件来创建或删除静态 pod。

比如我们在 node01 这个节点上用静态 pod 的方式来启动一个 nginx 的服务。我们登录到node01节点上面,可以通过下面命令找到 kubelet 对应的启动配置文件

systemctl status kubelet

查看命令执行结果:

[root@node1 kubelet.service.d]# systemctl status kubelet 
● kubelet.service - kubelet: The Kubernetes Node Agent
   Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled)
  Drop-In: /usr/lib/systemd/system/kubelet.service.d
           └─10-kubeadm.conf
   Active: active (running) since 三 2023-06-14 15:55:38 CST; 2 days ago
     Docs: https://kubernetes.io/docs/
 Main PID: 103826 (kubelet)
    Tasks: 17
   Memory: 65.1M
   CGroup: /system.slice/kubelet.service
           └─103826 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib...

616 17:19:37 node1 kubelet[103826]: I0616 17:19:37.050464  103826 log.go:181] http: superfluous response.WriteHeader call from k8s.io/kubernetes...og.go:217)
Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.
Hint: Some lines were ellipsized, use -l to show in full.

那么我们就去vim一下/usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf这个文件

# Note: This dropin only works with kubeadm and kubelet v1.11+
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
# This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use
# the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file.
EnvironmentFile=-/etc/sysconfig/kubelet
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS

其中显示kubelet的config的配置文件路径:/var/lib/kubelet/config.yaml

那么我们就去编辑它看一下:

apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
  anonymous:
    enabled: false
  webhook:
    cacheTTL: 0s
    enabled: true
  x509:
    clientCAFile: /etc/kubernetes/pki/ca.crt
authorization:
  mode: Webhook
  webhook:
    cacheAuthorizedTTL: 0s
    cacheUnauthorizedTTL: 0s
cgroupDriver: cgroupfs
clusterDNS:
- 10.96.0.10
clusterDomain: cluster.local
cpuManagerReconcilePeriod: 0s
evictionPressureTransitionPeriod: 0s
fileCheckFrequency: 0s
healthzBindAddress: 127.0.0.1
healthzPort: 10248
httpCheckFrequency: 0s
imageMinimumGCAge: 0s
kind: KubeletConfiguration
logging: {}
nodeStatusReportFrequency: 0s
nodeStatusUpdateFrequency: 0s
rotateCertificates: true
runtimeRequestTimeout: 0s
staticPodPath: /etc/kubernetes/manifests
streamingConnectionIdleTimeout: 0s
syncFrequency: 0s
volumeStatsAggPeriod: 0s

你会发现静态pod的配置路径就是:/etc/kubernetes/manifests
那么我们进去看一下你会发现是空的,我们只需将静态pod的yaml资源清单放到这里即可,kubelet会自动进行扫描并执行!

比如我们创建一个静态pod的yaml资源清单上传到上述目录下(你想在哪台node节点部署静态pod那么就上传到哪台node节点服务器的对应的目录当中去):

# 作用:是为了验证静态pod 就是一个普通的nginx服务的yaml配置清单
# 找到你的node节点上的静态pod文件存放的地方
# systemctl status kubelet;然后会有 /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf路径去编辑它 然后会找到/var/lib/kubelet/config.yaml文件
# 里面就有你当前这台node节点存放静态pod资源文件的路径 比如:staticPodPath: /etc/kubernetes/manifests
# 那么就把这个静态pod的yaml资源文件放到路径/etc/kubernetes/manifests下即可 kubelet会自动取管理它 不受kube-apiserver的控制 如果要删除静态pod直接把文件从该目录下删除即可
apiVersion: v1
kind: Pod
metadata:
  name: static-web
  labels:
    app: static
spec:
  containers:
    - name: web
      image: nginx
      ports:
        - name: web
          containerPort: 80

# 为什么要使用静态pod?

# Kubernetes官方文档,在介绍Static pod时,特别做了如下的标注说明:

# Note: If you are running clustered Kubernetes and are using static Pods to run a Pod on every node, you should probably be using a DaemonSet instead.

# 也就是说,如果你在使用Static pod来实现kubernetes集群中每个Node的上启动Pod,那么你更应该使用DaemonSet,而不是Static pod。

# 既然官方文档都推荐使用DaemonSet了,为什么还存在static pod这种机制?

# 早期的Kubernetes,为了在集群各个节点上启动例如日志采集(fluentd)、网络组件(kube-proxy)等服务,使用了Static pod的机制。后来提出了DaemonSet的概念,
# 于是这些需要在每个节点上都启动的服务,都逐渐被DaemonSet所替代,官方文档也建议优先选用DaemonSet。

# Static pod机制一直保留下来,一方面是为了兼容广大开发者采用了Static pod的使用场景;另一方面则是Static pod具有DaemonSet无法替代的特性:不需要Kubernetes集群来直接启动、
# 管理PodStatic pod最大的特点是无需调用Kube-apiserver即可快速启动Pod,也就是说,不需要一个完整的kubernetes集群,只要安装了kubelet、容器运行时,
# 即可快速地让kubelet来接管你的yaml文件定义的Pod。前面章节也简单介绍了如何快速使用这一特性。Static pod优点是不需要集群,缺点也是相对应的,没有集群层面的管理、调度功能。
# 而Static pod最经典的使用场景,就是用来Bootstrap一个Kubernetes集群

比如我们放到了node1节点的/etc/kubernetes/manifests目录下,node1节点上的kubelet就会自动去扫描并执行这个静态pod:

在这里插入图片描述
静态 Pod 的动态增加和删除

运行中的 kubelet 周期扫描配置的目录(我们这个例子中就是 /etc/kubernetes/manifests)下文件的变化,当这个目录中有文件出现或消失时创建或删除 pods:

$ mv /etc/kubernetes/manifests/static-web.yaml /tmp
$ sleep 20
$ docker ps
// no nginx container is running
$ mv /tmp/static-web.yaml  /etc/kubernetes/manifests
$ sleep 20
$ docker ps
CONTAINER ID        IMAGE         COMMAND                CREATED           ...
e7a62e3427f1        nginx:latest  "nginx -g 'daemon of   27 seconds ago

可以按照上边的命令执行一下你会发现当/etc/kubernetes/manifests目录下对应的yaml资源清单消失的时候kubelet也会自动删除对应的静态的pod,当重新放进去的时候kubelet又会重新创建一个新的静态pod

其实我们用 kubeadm 安装的集群,master 节点上面的几个重要组件都是用静态 Pod 的方式运行的,我们登录到 master 节点上查看/etc/kubernetes/manifests目录:

$ ls /etc/kubernetes/manifests/
etcd.yaml  kube-apiserver.yaml  kube-controller-manager.yaml  kube-scheduler.yaml

现在明白了吧,这种方式也为我们将集群的一些组件容器化提供了可能,因为这些 Pod 都不会受到 apiserver 的控制,不然我们这里kube-apiserver怎么自己去控制自己呢?万一不小心把这个 Pod 删掉了呢?所以只能有kubelet自己来进行控制,这就是我们所说的静态 Pod。

static-web.yaml

# 作用:是为了验证静态pod 就是一个普通的nginx服务的yaml配置清单
# 找到你的node节点上的静态pod文件存放的地方
# systemctl status kubelet;然后会有 /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf路径去编辑它 然后会找到/var/lib/kubelet/config.yaml文件
# 里面就有你当前这台node节点存放静态pod资源文件的路径 比如:staticPodPath: /etc/kubernetes/manifests
# 那么就把这个静态pod的yaml资源文件放到路径/etc/kubernetes/manifests下即可 kubelet会自动取管理它 不受kube-apiserver的控制 如果要删除静态pod直接把文件从该目录下删除即可
apiVersion: v1
kind: Pod
metadata:
  name: static-web
  labels:
    app: static
spec:
  containers:
    - name: web
      image: nginx
      ports:
        - name: web
          containerPort: 80

# 为什么要使用静态pod?

# Kubernetes官方文档,在介绍Static pod时,特别做了如下的标注说明:

# Note: If you are running clustered Kubernetes and are using static Pods to run a Pod on every node, you should probably be using a DaemonSet instead.

# 也就是说,如果你在使用Static pod来实现kubernetes集群中每个Node的上启动Pod,那么你更应该使用DaemonSet,而不是Static pod。

# 既然官方文档都推荐使用DaemonSet了,为什么还存在static pod这种机制?

# 早期的Kubernetes,为了在集群各个节点上启动例如日志采集(fluentd)、网络组件(kube-proxy)等服务,使用了Static pod的机制。后来提出了DaemonSet的概念,
# 于是这些需要在每个节点上都启动的服务,都逐渐被DaemonSet所替代,官方文档也建议优先选用DaemonSet。

# Static pod机制一直保留下来,一方面是为了兼容广大开发者采用了Static pod的使用场景;另一方面则是Static pod具有DaemonSet无法替代的特性:不需要Kubernetes集群来直接启动、
# 管理PodStatic pod最大的特点是无需调用Kube-apiserver即可快速启动Pod,也就是说,不需要一个完整的kubernetes集群,只要安装了kubelet、容器运行时,
# 即可快速地让kubelet来接管你的yaml文件定义的Pod。前面章节也简单介绍了如何快速使用这一特性。Static pod优点是不需要集群,缺点也是相对应的,没有集群层面的管理、调度功能。
# 而Static pod最经典的使用场景,就是用来Bootstrap一个Kubernetes集群
Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐