节点管理

添加节点

删除节点

Worker 节点状态说明

# kubectl get nodes k8s-node-1 -o yaml 
apiVersion: v1
kind: Node
metadata:
  annotations:
    flannel.alpha.coreos.com/backend-data: '{"VNI":1,"VtepMAC":"42:c9:0e:55:b6:75"}'
    flannel.alpha.coreos.com/backend-type: vxlan
    flannel.alpha.coreos.com/kube-subnet-manager: "true"
    flannel.alpha.coreos.com/public-ip: 10.0.0.101
    kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
    node.alpha.kubernetes.io/ttl: "0"
    volumes.kubernetes.io/controller-managed-attach-detach: "true"
  creationTimestamp: "2022-09-12T16:47:05Z"
  labels:
    beta.kubernetes.io/arch: amd64
    beta.kubernetes.io/os: linux
    kubernetes.io/arch: amd64
    kubernetes.io/hostname: k8s-node-1
    kubernetes.io/os: linux
  name: k8s-node-1
  resourceVersion: "1765092"
  uid: 954f530e-fdbe-4928-810f-b7e9621c7db7
spec:
  podCIDR: 10.244.1.0/24
  podCIDRs:
  - 10.244.1.0/24
status:
  addresses: # 已分配的地址信息
  - address: 10.0.0.101
    type: InternalIP
  - address: k8s-node-1
    type: Hostname
  allocatable: # 可分配的资源信息
    cpu: "2"
    ephemeral-storage: "22900525019"
    hugepages-1Gi: "0"
    hugepages-2Mi: "0"
    memory: 2890828Ki
    pods: "110" # 该节点最多创建110个Pod
  capacity: # 最多使用的资源
    cpu: "2"
    ephemeral-storage: 24848660Ki
    hugepages-1Gi: "0"
    hugepages-2Mi: "0"
    memory: 2993228Ki
    pods: "110"
  conditions: # 状况
  - lastHeartbeatTime: "2022-12-23T03:49:02Z"
    lastTransitionTime: "2022-12-23T03:49:02Z"
    message: Flannel is running on this node
    reason: FlannelIsUp
    status: "False" # False表示目前没有发现网络不可用
    type: NetworkUnavailable # 网络是否不可用
  - lastHeartbeatTime: "2022-12-23T07:56:36Z"
    lastTransitionTime: "2022-11-16T04:24:58Z"
    message: kubelet has sufficient memory available
    reason: KubeletHasSufficientMemory
    status: "False" # False表示目前没有发现内存不足
    type: MemoryPressure # 内存是否不足
  - lastHeartbeatTime: "2022-12-23T07:56:36Z"
    lastTransitionTime: "2022-11-16T04:24:58Z"
    message: kubelet has no disk pressure
    reason: KubeletHasNoDiskPressure
    status: "False"
    type: DiskPressure
  - lastHeartbeatTime: "2022-12-23T07:56:36Z"
    lastTransitionTime: "2022-11-16T04:24:58Z"
    message: kubelet has sufficient PID available
    reason: KubeletHasSufficientPID
    status: "False"
    type: PIDPressure
  - lastHeartbeatTime: "2022-12-23T07:56:36Z"
    lastTransitionTime: "2022-11-16T04:24:58Z"
    message: kubelet is posting ready status. AppArmor enabled
    reason: KubeletReady # 节点是否就绪
    status: "True" # True表示已经就绪
    type: Ready
  daemonEndpoints:
    kubeletEndpoint:
      Port: 10250
  images: # 当前节点所存储的镜像信息
  - names:
    - docker.elastic.co/kibana/kibana@sha256:9dd46102f9eadf43f62216a3113ed8b9ad675fe36706ff9daea8652f05d1a61e
    - docker.elastic.co/kibana/kibana:7.17.3
    sizeBytes: 796844751
  - names:
    - docker.elastic.co/elasticsearch/elasticsearch@sha256:8734ac48c10ff836a6d0c3d600297b453cb389e85fd26bb4ccb3d5a5bde7e554
    - docker.elastic.co/elasticsearch/elasticsearch:7.17.3
    sizeBytes: 613347051
...
  nodeInfo:
    architecture: amd64
    bootID: ebf781a4-9049-4785-a1cb-96aa81086fc1
    containerRuntimeVersion: docker://19.3.15
    kernelVersion: 5.4.0-135-generic
    kubeProxyVersion: v1.23.10
    kubeletVersion: v1.23.10
    machineID: c7796bd76a994c9593ed6a4c71aedfb2
    operatingSystem: linux
    osImage: Ubuntu 20.04.4 LTS
    systemUUID: 04b94d56-72d5-2120-1b24-5168950d63cd

删除 Worker 节点

  • kubectl delete node <节点名称>

扩容 Worker 节点

kubesphere

通过 kubesphere 部署的集群,可通过以下方法扩容:

https://www.kubesphere.io/zh/docs/v3.3/installing-on-linux/cluster-operation/add-new-nodes/

Worker 节点缩容

https://blog.csdn.net/weixin_45713326/article/details/125109432

需要注意的是,下述流程中的一些步骤可能需要一些时间来完成,特别是在有大量 Pod 需要重新调度的情况下。

在 Kubernetes 中进行节点缩容是一项关键的操作,需要注意以下几个事项:

  1. 节点负载:在进行节点缩容之前,确保要缩容的节点上没有正在运行的重要应用程序或服务。如果有,首先需要迁移这些应用程序到其他节点上,确保集群中的负载得以平衡。
  2. 调度策略:节点缩容会影响到调度器的决策。在进行节点缩容之前,确保集群的调度策略能够正确地将新的 Pod 调度到其他节点上,以确保集群的稳定性和可用性。
  3. 状态监控:在进行节点缩容之前,监控集群的状态和健康状况。确保集群中的其他节点具备足够的资源来接收要迁移的 Pod,并且集群的整体性能不会受到过大的影响。
  4. 优雅终止:在缩容节点之前,使用 Kubernetes 的优雅终止机制来停止节点上的应用程序和服务。这样可以确保正在运行的应用程序能够正常地完成请求,并进行必要的清理工作。
  5. 数据持久性:如果要缩容的节点上有存储卷(如持久卷或本地存储),请确保提前备份数据或迁移数据到其他节点。节点缩容可能会导致数据丢失或不可用性,因此要提前处理好存储卷的数据迁移问题。
  6. 监控和日志:在进行节点缩容期间,密切监控集群的日志和监控指标。这样可以及时发现和解决任何潜在的问题,并确保节点缩容过程的顺利进行。
  7. 验证缩容:在完成节点缩容后,验证集群的状态和应用程序的正常运行。确保缩容操作没有引入任何故障,并且集群的负载得到适当的平衡。

需要注意的是,节点缩容是一项敏感的操作,错误的处理可能会导致集群的不可用性或数据丢失。因此,在进行节点缩容之前,请确保已经充分了解和熟悉 Kubernetes 的相关文档,并且在测试环境中进行充分的实践和验证。

Kubernetes 中的节点缩容涉及多个步骤和组件的协同工作。下面是一个详细的节点缩容流程:

  1. 从节点上驱逐 Pod:首先,Kubernetes 调度器会评估节点上运行的 Pod,并将它们标记为待驱逐状态。调度器将尝试将这些 Pod 迁移到其他可用节点上,以确保集群的负载平衡。调度器会考虑 Pod 的调度约束、资源需求和节点亲和性等因素来选择新的节点。
  2. Pod 迁移:一旦 Pod 被标记为待驱逐状态,Kubernetes 会触发迁移过程。这包括在新节点上创建 Pod 并确保其正常运行。Pod 的迁移可以通过多种方式实现,例如使用 ReplicaSet、Deployment 或 DaemonSet 控制器。
  3. 监控迁移状态:在进行节点缩容期间,Kubernetes 会监控 Pod 迁移的状态。它会检查新节点上的 Pod 是否成功运行,并且原节点上的 Pod 是否已经成功驱逐。集群管理员可以使用 Kubernetes 的监控工具来跟踪迁移进度和检测任何错误或故障。
  4. 置换节点:一旦所有的 Pod 成功迁移到其他节点上,并且原节点上不再运行任何关键应用程序或服务,就可以开始节点的实际缩容。在这一步中,Kubernetes 会将节点从集群中移除,并更新集群的拓扑信息。
  5. 清理节点:节点缩容完成后,需要进行一些清理工作。这可能包括回收节点上的资源,例如持久卷、网络配置等。此外,还需要确保节点上的任何配置、日志和监控数据都得到适当的处理和存档。
  6. 验证缩容:完成节点缩容后,需要验证集群的状态和功能是否正常。确保缩容操作没有引入任何故障,并且集群的负载得到适当的平衡。可以使用自动化测试、监控工具和日志分析来验证缩容的效果。

请注意,节点缩容是一项复杂的操作,涉及到多个组件和机制的协同工作。在进行节点缩容之前,请确保已经充分了解 Kubernetes 的相关文档,并在测试环境中进行充分的实践和验证。此外,建议在生产环境中谨慎操作,并备份重要数据以防止潜在的风险。

kubernetes 节点缩容时,需要对calico网络插件做什么操作吗

在 Kubernetes 中使用 Calico 网络插件时,节点缩容通常不需要特殊的操作。Calico 是一个基于BGP的网络插件,负责管理和路由容器之间的网络流量。当节点缩容时,Calico 会自动适应节点的变化,并相应地更新网络路由和拓扑。

在节点缩容期间,Calico 会感知到节点的离线状态,并将其从网络拓扑中移除。Calico 路由器会相应地更新路由表,以确保容器的流量可以正确地路由到其他可用的节点。

因此,对于节点缩容操作而言,一般不需要对 Calico 网络插件做额外的操作。Calico 会自动处理节点的变化,并保持网络的连通性。然而,需要确保 Calico 的版本与 Kubernetes 版本兼容,并且遵循正确的安装和配置步骤。

如果遇到网络问题或者在特定情况下需要手动干预,可以考虑执行 Calico 的网络拓扑清理操作,以确保网络状态的一致性。具体操作可以参考 Calico 官方文档中关于网络拓扑清理的说明。

总而言之,在节点缩容时,对于 Calico 网络插件而言,一般情况下不需要特别的操作,它会自动适应节点的变化并保持网络的连通性。

检查节点上的 Pod

检查要缩容的节点上是否有运行中的 Pod。如果有未终止的 Pod,需要采取一些措施,如驱逐 Pod 或等待它们正常终止。

kubectl

使用 kubectl 命令行工具:

  • kubectl get pods -A --field-selector spec.nodeName=<节点名称>
# kubectl get pods -A --field-selector spec.nodeName=k8s-worker10
NAMESPACE                      NAME                   READY   STATUS    RESTARTS         AGE
kube-system                    calico-node-zv9th      1/1     Running   4 (3d14h ago)    3d16h
kube-system                    haproxy-k8s-worker10   1/1     Running   4 (3d16h ago)    99d
kube-system                    kube-proxy-cc9hl       1/1     Running   5 (3d16h ago)    99d
kube-system                    nodelocaldns-gl576     1/1     Running   4 (3d16h ago)    99d
kubesphere-monitoring-system   node-exporter-zskds    2/2     Running   12 (3d16h ago)   99d

Kubernetes API

使用 Kubernetes API:

Kubernetes API 允许通过编程方式与集群进行交互。可以使用适合编程语言的 Kubernetes 客户端库(如 Kubernetes Python 客户端)来编写代码,并使用 API 调用来获取节点上的 Pod 列表。

以下是使用 Python 客户端库示例的伪代码:

from kubernetes import client, config

# 加载 Kubernetes 配置文件
config.load_kube_config()

# 创建 Kubernetes API 客户端实例
api_instance = client.CoreV1Api()

# 获取节点上的 Pod 列表
pod_list = api_instance.list_pod_for_all_namespaces(field_selector=f"spec.nodeName=<节点名称>")

# 处理 Pod 列表
for pod in pod_list.items:
    print(pod.metadata.name)

这将打印出指定节点上的所有 Pod 的名称。

无论使用 kubectl 命令行工具还是 Kubernetes API,都需要具有适当的权限来访问集群和节点上的信息。

驱逐节点上运行的 Pod

对于每个运行在要缩容的节点上的 Pod,Kubernetes 控制平面会触发 Pod 的驱逐过程。驱逐过程会向 Pod 发送终止信号(SIGTERM),以便它们可以进行清理和终止操作。默认情况下,Kubernetes 会给予 Pod 30 秒的时间来进行清理。如果在此时间内 Pod 仍未终止,则会发送强制终止信号(SIGKILL)。

kubectl

  • kubectl drain <节点名称> --ignore-daemonsets
  • 在节点缩容时,受 DaemonSet 管理的 Pod 是不能被驱逐的,因为它们被设计为在每个节点上运行。为了解决此问题,您可以使用 --ignore-daemonsets 参数来忽略 DaemonSet 管理的 Pod,从而顺利进行节点缩容操作。
# kubectl drain k8s-worker10 --ignore-daemonsets
...

Kubernetes API

from kubernetes import client, config

# 加载 Kubernetes 配置文件
config.load_kube_config()

# 创建 Kubernetes API 客户端实例
api_instance = client.CoreV1Api()

# 驱逐 Pod
api_instance.delete_namespaced_pod(name="<pod名称>", namespace="<命名空间>")

重新调度 Pod

一旦 Pod 被驱逐,Kubernetes 控制平面会开始重新调度这些 Pod 到其他可用的工作节点上。调度器会根据资源需求、调度约束等因素选择合适的节点,并将 Pod 调度到这些节点上。

此阶段需等待 Pod 调度完成

等待 Pod 就绪

在 Pod 被调度到新节点之后,Kubernetes 控制平面会等待 Pod 进入就绪状态。这意味着 Pod 的容器已经成功启动,并且应用程序已经可用。Pod 的就绪状态由 Pod 中的健康检查探针来确定。

此阶段需等待 Pod 就绪

标记节点不可调度

一旦所有要缩容的节点上的 Pod 都已重新调度并就绪,要将缩容的节点标记为不可调度。这样,后续的 Pod 将不会被调度到该节点上。

kubectl

kubectl cordon <节点名称>

  • 标记前
# kubectl get nodes
NAME           STATUS   ROLES                  AGE    VERSION
k8s-master1    Ready    control-plane,master   107d   v1.22.12
k8s-master2    Ready    control-plane,master   107d   v1.22.12
k8s-master3    Ready    control-plane,master   107d   v1.22.12
k8s-worker1    Ready    worker                 107d   v1.22.12
k8s-worker10   Ready    worker                 99d    v1.22.12
...
  • 标记
# kubectl cordon k8s-worker10
node/k8s-worker10 cordoned
  • 标记后
# kubectl get nodes
NAME           STATUS                     ROLES                  AGE    VERSION
k8s-master1    Ready                      control-plane,master   107d   v1.22.12
k8s-master2    Ready                      control-plane,master   107d   v1.22.12
k8s-master3    Ready                      control-plane,master   107d   v1.22.12
k8s-worker1    Ready                      worker                 107d   v1.22.12
k8s-worker10   Ready,SchedulingDisabled   worker                 99d    v1.22.12
k8s-worker2    Ready                      worker                 107d   v1.22.12
k8s-worker3    Ready                      worker                 107d   v1.22.12
k8s-worker4    Ready                      worker                 99d    v1.22.12
k8s-worker5    Ready                      worker                 99d    v1.22.12
k8s-worker6    Ready                      worker                 99d    v1.22.12
k8s-worker7    Ready                      worker                 99d    v1.22.12
k8s-worker8    Ready                      worker                 99d    v1.22.12
k8s-worker9    Ready                      worker                 99d    v1.22.12
  • 取消标记
# kubectl uncordon k8s-worker10
node/k8s-worker10 uncordoned

Kubernetes API

以下是使用 Python 客户端库示例的伪代码:

from kubernetes import client, config

# 加载 Kubernetes 配置文件
config.load_kube_config()

# 创建 Kubernetes API 客户端实例
api_instance = client.CoreV1Api()

# 标记节点为不可调度
api_instance.patch_node(name="<节点名称>", body={"spec": {"unschedulable": True}})

<节点名称> 替换为要标记为不可调度的节点的名称。这将通过 API 调用将节点的 spec.unschedulable 属性设置为 True,表示该节点不可调度新的 Pod。

请注意,标记节点为不可调度后,现有的 Pod 仍将继续在节点上运行,但新的 Pod 将不会被调度到该节点上。如果要将节点重新标记为可调度状态,可以使用 kubectl uncordon 命令或通过 API 将 spec.unschedulable 属性设置为 False

需要注意的是,上述操作可能会对集群产生影响,请在执行之前确保您的操作是安全和符合预期的。

删除工作节点

最后,当所有 Pod 都已经从要缩容的节点上移除并重新调度到其他节点上后,可以安全地将要缩容的工作节点从集群中删除。删除节点的具体方法取决于 Kubernetes 部署的类型和环境。

借助第三方工具缩容

Worker 节点扩容

准备新的 Worker 节点

在物理或虚拟机上创建一个新的机器,确保它满足 Kubernetes 的最低要求,并且具有网络连接到 Kubernetes 集群的控制平面节点,还要安装 worker 节点必要的依赖包和组件。

安装容器运行时

  • docker 或 containerd …

通过第三方工具扩容

https://www.kubesphere.io/zh/docs/v3.3/installing-on-linux/cluster-operation/add-new-nodes/

ssh免密登陆

ssh-copy-id 172.16.0.133