跳转至

K8s 相关问题集锦(五)

7 运维与故障排查类

7.1 查看集群的健康状态

使用 kubectl get nodes 查看节点状态,使用 kubectl describe node 了解节点详细信息。

在 Kubernetes 集群中,查看集群的健康状态非常重要,通常我们会通过 kubectl 命令来了解节点、Pod 以及其他组件的状态。以下是详细操作和命令,帮助你全面了解 Kubernetes 集群的健康状况:

1. 查看节点的健康状态

1.1 使用 kubectl get nodes

这个命令可以帮助你快速查看集群中各个节点的状态,包括它们的 Ready 状态以及版本信息。

sh kubectl get nodes

输出示例:

sh NAME STATUS ROLES AGE VERSION node1 Ready master 10d v1.25.0 node2 Ready <none> 10d v1.25.0 node3 NotReady <none> 10d v1.25.0

  • STATUS:显示节点的状态。常见的状态有 Ready、NotReady、Unknown 等。
  • Ready:节点正常。
  • NotReady:节点未准备好,可能有网络问题或其他故障。

1.2 使用 kubectl describe node

要查看节点的详细信息,使用 kubectl describe node 命令。这会显示该节点的详细配置和状态信息,例如容量、使用情况、运行的 Pod、状态事件等。

sh kubectl describe node <node-name>

例如:

sh kubectl describe node node1

输出示例(部分):

yaml Name: node1 Roles: master Labels: kubernetes.io/hostname=node1 node-role.kubernetes.io/master= CreationTimestamp: Mon, 10 Oct 2024 12:00:00 +0800 Taints: <none> Capacity: cpu: 4 memory: 8Gi Allocatable: cpu: 4 memory: 7.5Gi Conditions: Type Status LastHeartbeatTime Reason Message ---- ------ ----------------- ------ ------- Ready True Mon, 10 Oct 2024 12:01:00 +0800 KubeletReady kubelet is posting ready status ...

Conditions 中 Ready 的状态表明节点是否可用;其他字段如 MemoryPressure、DiskPressure 也显示节点的资源使用情况。

2. 查看节点中的 Pod 状态

2.1 使用 kubectl get pods -o wide 查看 Pod 状态

可以查看整个集群的 Pod 状态,并包括更多详细信息,例如它们在哪个节点上运行。

sh kubectl get pods -o wide --all-namespaces

输出示例:

sh NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE kube-system kube-dns-598d7fb7d4-5kfz2 3/3 Running 2 7d 10.244.1.2 node1 default nginx-deployment-6d8ff7cc8b-qsdjf 1/1 Running 0 2d 10.244.2.4 node2

  • READY:显示容器的就绪情况,如 1/1 表示 1 个容器已经就绪。
  • STATUS:Pod 的状态,包括 Running、Pending、Failed、CrashLoopBackOff 等。
  • NODE:显示 Pod 正在哪个节点上运行。

2.2 使用 kubectl describe pod 查看 Pod 详情

如果某个 Pod 出现了问题,可以使用 kubectl describe pod 查看该 Pod 的详细状态、事件和日志。

sh kubectl describe pod <pod-name> -n <namespace>

例如:

sh kubectl describe pod nginx-deployment-6d8ff7cc8b-qsdjf -n default

输出示例(部分):

yaml Name: nginx-deployment-6d8ff7cc8b-qsdjf Namespace: default Node: node2/192.168.1.11 Containers: nginx: Container ID: docker://abc123 Image: nginx:1.19.3 State: Running Ready: True Restart Count: 0 Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 2d default-scheduler Successfully assigned default/nginx-deployment-6d8ff7cc8b-qsdjf to node2 Normal Started 2d kubelet Started container nginx

这里的 Events 部分可以帮助诊断 Pod 问题,如调度失败、容器启动失败等。

3. 查看集群组件的健康状态

3.1 使用 kubectl get componentstatuses

可以查看 Kubernetes 集群关键组件(如 scheduler、controller-manager)的健康状态。

sh kubectl get componentstatuses

输出示例:

sh NAME STATUS MESSAGE ERROR scheduler Healthy ok controller-manager Healthy ok etcd-0 Healthy {"health":"true"}

  • STATUS:显示组件的健康状态,如果为 Healthy,表示组件正常工作。
  • MESSAGE:包含附加信息。

4. 查看集群的详细健康报告

4.1 使用 kubectl get events

可以查看整个集群中的事件,包括节点、Pod、服务等的事件信息,这些事件可以用来了解集群中是否发生了一些异常情况。

sh kubectl get events --all-namespaces

输出示例:

sh LAST SEEN TYPE REASON OBJECT MESSAGE 10s Warning BackOff pod/nginx-5bb69b79f9-ht4vh Back-off restarting failed container 20s Normal ScalingReplicaSet deployment/nginx-deployment Scaled up replica set nginx-5bb69b79f9 to 3

这里可以看到集群中各个组件的事件,例如 Pod 的重启、节点的变化等。

5. 其他有用的检查命令

  • 查看 kube-system 命名空间中的 Pod 状态,检查关键组件是否正常运行:

sh kubectl get pods -n kube-system - 检查 kubelet 服务日志: 如果节点出现问题,可以在节点上检查 kubelet 服务的日志:

sh journalctl -u kubelet

总结

  1. 查看节点的状态:使用 kubectl get nodes,并通过 kubectl describe node 查看详细信息。
  2. 查看 Pod 状态:使用 kubectl get pods -o wide --all-namespaces 和 kubectl describe pod。
  3. 查看关键组件健康状态:使用 kubectl get componentstatuses。
  4. 查看集群事件:使用 kubectl get events --all-namespaces。
  5. 检查 kubelet 服务日志:在节点上查看 kubelet 日志,排查节点问题。

通过这些命令,可以全面了解 Kubernetes 集群的健康状态,及时发现并处理潜在问题。

7.2 调试无法访问的 Service

可能需要检查 Service、Endpoint、Pod 状态,验证网络策略,使用 kubectl exec 进入容器进行网络测试。

在 Kubernetes 中,Service 负责将请求分发到后端 Pod,从而实现应用的负载均衡。然而,有时你可能会遇到 Service 无法访问的情况。在这种情况下,调试步骤主要包括检查 Service、Endpoint、Pod 的状态,验证网络策略,并进入容器进行网络测试。以下是详细的调试步骤和操作命令:

1. 检查 Service 的状态

首先检查 Service 是否存在,类型是否正确,是否暴露了期望的端口。

1.1 使用 kubectl get services

sh kubectl get svc -n <namespace>

例如:

sh kubectl get svc -n default

输出示例:

sh NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE my-service ClusterIP 10.0.0.1 <none> 80/TCP 3d

  • CLUSTER-IP:检查是否有有效的 Cluster IP 地址。
  • PORT(S):确保服务的端口设置正确。

1.2 使用 kubectl describe service

sh kubectl describe svc <service-name> -n <namespace>

例如:

sh kubectl describe svc my-service -n default

检查以下内容:

  • Selectors:确保 Service 的 selector 与 Pod 的标签匹配。
  • Endpoints:确保 Service 已正确关联到 Pod。如果 Endpoints 为空,说明没有 Pod 被绑定到该 Service。

2. 检查 Endpoint 的状态

Service 是通过 Endpoint 关联 Pod 的,确保 Service 具备有效的 Endpoint。

2.1 使用 kubectl get endpoints

sh kubectl get endpoints <service-name> -n <namespace>

例如:

sh kubectl get endpoints my-service -n default

输出示例:

sh NAME ENDPOINTS AGE my-service 10.244.1.2:80 3d

  • 如果 ENDPOINTS 为空,说明没有 Pod 被关联到 Service。你需要检查 Pod 的标签是否与 Service 的 selector 匹配。

3. 检查 Pod 的状态

确认 Pod 是否在运行,且无异常。

3.1 使用 kubectl get pods

sh kubectl get pods -n <namespace> -o wide

例如:

sh kubectl get pods -n default -o wide

  • 确保 Pod 的状态为 Running,并注意 Pod 所在节点。
  • RESTARTS 计数:如果 Pod 多次重启,可能存在配置问题或崩溃。

3.2 使用 kubectl describe pod

如果 Pod 无法运行或状态异常,使用 kubectl describe 查看详细信息和事件。

sh kubectl describe pod <pod-name> -n <namespace>

  • 检查 Events 部分,寻找启动失败、探针失败等错误信息。

4. 验证网络策略

Kubernetes 中可以通过 NetworkPolicy 控制网络流量,如果存在错误的策略配置,可能会导致无法访问 Service。

4.1 使用 kubectl get networkpolicies

sh kubectl get networkpolicies -n <namespace>

查看是否存在网络策略来阻止对 Service 或 Pod 的访问。

4.2 使用 kubectl describe networkpolicy

sh kubectl describe networkpolicy <networkpolicy-name> -n <namespace>

检查策略配置,确保允许所需的入站和出站流量。

5. 使用 kubectl exec 进行网络测试

进入 Pod,检查是否能够访问目标 Pod 的 IP 和端口,或者测试访问 Service 的 Cluster IP。

5.1 使用 kubectl exec 进入 Pod

sh kubectl exec -it <pod-name> -n <namespace> -- /bin/sh

例如:

sh kubectl exec -it nginx-deployment-5bb69b79f9-ht4vh -n default -- /bin/sh

5.2 使用 curl 或 wget 测试网络连接

在 Pod 内部,使用 curl 或 wget 命令测试与 Service 或 Pod 的连接:

  • 测试通过 Service Cluster IP 访问: sh curl http://<service-cluster-ip>:<port>
  • 测试通过 Pod 的 IP 访问: sh curl http://<pod-ip>:<port>

如果能够通过 Pod 的 IP 访问,但无法通过 Service 的 Cluster IP 访问,则可能是 Service 或 Endpoint 配置有问题。

6. 检查 DNS 服务

如果 Service 是通过域名访问的,需要确保 Kubernetes DNS 服务正常工作。

6.1 检查 DNS Pod

使用以下命令查看 kube-dns 或 coredns 的状态:

sh kubectl get pods -n kube-system -l k8s-app=kube-dns

确保 DNS Pod 处于 Running 状态。

6.2 测试 DNS 解析

进入 Pod 中测试域名解析:

sh kubectl exec -it <pod-name> -n <namespace> -- nslookup <service-name>

如果 DNS 无法解析,则可能是 kube-dns 或 coredns 的问题,需要进一步检查 DNS Pod 的日志。

7. 检查 Kube Proxy 和 IP 路由

Service 的流量通过 kube-proxy 实现负载均衡,如果 kube-proxy 出现问题,也会导致服务不可用。

7.1 查看 kube-proxy Pod 状态

sh kubectl get pods -n kube-system -l k8s-app=kube-proxy

确保 kube-proxy Pod 正常运行。

7.2 检查节点 IP 路由

在节点上使用以下命令查看 iptables 规则,以确保 kube-proxy 正常配置:

sh iptables -t nat -L -n | grep <service-name>

确保流量转发规则正确。

总结

  1. 检查 Service 的状态:使用 kubectl get svc 和 kubectl describe svc 确认 Service 的配置是否正确。
  2. 检查 Endpoint:使用 kubectl get endpoints 确认 Pod 是否正确关联到 Service。
  3. 检查 Pod 的状态:使用 kubectl get pods 和 kubectl describe pod 确保 Pod 正常运行。
  4. 验证网络策略:使用 kubectl get networkpolicies 和 kubectl describe networkpolicy 确认网络策略不会阻止流量。
  5. 使用 kubectl exec 进行网络测试:进入 Pod 内部,使用 curl 或 wget 测试连接。
  6. 检查 DNS 服务:确认 DNS 服务正常工作并可以解析 Service 域名。
  7. 检查 kube-proxy:确保 kube-proxy 正常运行,查看 iptables 规则是否正确。

通过这些步骤,可以有效地调试无法访问的 Kubernetes Service 问题,并逐步排查服务无法访问的原因。

7.3 备份和恢复 etcd 数据

使用 etcdctl 工具进行备份和恢复,确保数据安全。

Kubernetes 集群使用 etcd 作为其分布式键值存储,存储着整个集群的配置和状态数据。因此,备份和恢复 etcd 数据是确保集群安全和灾难恢复的重要步骤。通常使用 etcdctl 工具来备份和恢复 etcd 数据。

以下是详细操作步骤,包括备份和恢复 etcd 数据的方法:

1. etcd 备份

为了确保 Kubernetes 集群的高可用性,建议定期对 etcd 数据进行备份。

1.1 前提条件

  • etcdctl 工具已经安装。
  • 确保与 etcd 服务通信的正确访问权限和证书。

可以通过以下命令查看 etcdctl 版本:

sh etcdctl version

注意:备份和恢复操作需要以 root 用户或具有相应权限的用户执行。

1.2 设置环境变量

设置以下环境变量以便 etcdctl 访问 etcd 集群:

sh export ETCDCTL_API=3 export ETCDCTL_CACERT=/etc/kubernetes/pki/etcd/ca.crt export ETCDCTL_CERT=/etc/kubernetes/pki/etcd/server.crt export ETCDCTL_KEY=/etc/kubernetes/pki/etcd/server.key

以上路径是 etcd 的默认证书路径,具体路径可能因集群配置不同而有所差异。

1.3 使用 etcdctl 备份 etcd 数据

使用 etcdctl snapshot save 命令进行备份,将 etcd 数据保存为快照文件。

sh etcdctl --endpoints=https://127.0.0.1:2379 snapshot save /path/to/backup/etcd-backup.db

  • --endpoints:etcd 的访问地址,一般为本地地址 https://127.0.0.1:2379。
  • /path/to/backup/etcd-backup.db:保存备份的路径,建议存储在安全的地方。

成功备份后,会显示类似以下输出:

sh Snapshot saved at /path/to/backup/etcd-backup.db

2. etcd 恢复

恢复 etcd 数据需要从之前保存的快照文件中重建 etcd 集群,通常用于集群中 etcd 数据损坏或丢失的情况。

2.1 停止 kube-apiserver

在恢复 etcd 之前,建议先停止 Kubernetes API Server 以防止集群与损坏的 etcd 数据进行交互。

sh systemctl stop kube-apiserver

在大多数集群中,kube-apiserver 是通过 systemd 进行管理的,因此可以使用 systemctl 命令。

2.2 使用 etcdctl 恢复快照

使用 etcdctl snapshot restore 命令从备份文件中恢复 etcd 数据。

sh etcdctl snapshot restore /path/to/backup/etcd-backup.db --name <etcd-node-name> --data-dir /var/lib/etcd-restored

  • /path/to/backup/etcd-backup.db:之前创建的备份文件的路径。
  • --name:etcd 节点的名称,通常可以通过查看原 etcd 配置文件获得。
  • --data-dir:恢复数据的路径,可以是 /var/lib/etcd,但推荐使用不同的目录,如 /var/lib/etcd-restored,以避免覆盖现有数据。

成功恢复后,会显示类似以下输出:

sh Snapshot restored and written to /var/lib/etcd-restored

2.3 更新 etcd 数据目录

恢复完成后,需要将 etcd 服务的 --data-dir 参数指向恢复后的数据目录。例如: 编辑 etcd 的 systemd 服务文件 /etc/systemd/system/etcd.service,找到 --data-dir 相关配置并更新为恢复后的目录 /var/lib/etcd-restored。

sh --data-dir=/var/lib/etcd-restored

2.4 启动 etcd 和 kube-apiserver

完成 etcd 恢复后,重新启动 etcd 服务和 kube-apiserver 服务。

```sh

启动 etcd 服务

systemctl daemon-reload systemctl start etcd

启动 kube-apiserver 服务

systemctl start kube-apiserver ```

3. 验证 etcd 恢复结果

3.1 验证 etcd 集群健康状态

使用 etcdctl 查看 etcd 集群的健康状态,确保恢复后的 etcd 节点处于正常状态。

sh etcdctl --endpoints=https://127.0.0.1:2379 endpoint health

输出示例:

sh https://127.0.0.1:2379 is healthy: successfully committed proposal

3.2 验证 Kubernetes 集群状态

在恢复和启动所有服务后,可以使用 kubectl 验证 Kubernetes 集群的健康状态,例如查看节点和 Pod 的状态:

sh kubectl get nodes kubectl get pods --all-namespaces

确保所有组件正常运行。

总结

  1. 备份 etcd 数据:

  2. 使用 etcdctl snapshot save 命令创建快照备份。

  3. 定期备份并将备份文件存储在安全位置。
  4. 恢复 etcd 数据:

  5. 停止 kube-apiserver,防止不必要的操作影响恢复。

  6. 使用 etcdctl snapshot restore 命令从快照恢复数据。
  7. 更新 etcd 的 --data-dir,并重启 etcd 和 kube-apiserver 服务。
  8. 验证:

  9. 使用 etcdctl 验证 etcd 集群健康状态。

  10. 使用 kubectl 查看 Kubernetes 集群中节点和 Pod 的状态,确保所有组件正常运行。

通过以上步骤,能够有效地备份和恢复 etcd 数据,保障 Kubernetes 集群的高可用性和数据安全性。

7.4 集群中的节点资源紧张时应该怎么做?

考虑节点扩展、Pod 资源配额管理(如 requests 和 limits 的设置),或者使用 Node Affinity 和 Taints/Tolerations 调整调度策略。

在 Kubernetes 集群中,当节点资源紧张时,需要合理管理和调优资源,以确保集群的稳定性和服务的正常运行。以下是应对集群节点资源紧张的一些解决方案:

1. 节点扩展(水平扩展集群)

最直接的解决方法是通过添加更多的节点来扩展集群的容量,以缓解资源紧张的情况。这可以手动增加节点,也可以通过自动扩展来实现。

1.1 手动增加节点

  • 手动增加虚拟机或物理机,并将其加入 Kubernetes 集群。
  • 使用以下命令将新节点加入集群: sh kubeadm join <master-ip>:<master-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>

以上命令需要在新节点上执行,并通过适当的认证加入到现有集群中。

1.2 自动扩展(Cluster Autoscaler)

  • Cluster Autoscaler 是 Kubernetes 提供的自动扩展组件,用于根据 Pod 资源需求自动增加或减少集群中的节点数量。
  • 配置 Cluster Autoscaler 后,它会自动检测节点资源不足的情况,并向集群中添加节点,确保新创建的 Pod 能够成功调度。

安装 Cluster Autoscaler 的步骤:

  • 可以使用 Helm 或 kubectl apply 安装 Cluster Autoscaler,并根据云服务提供商的设置进行配置。

2. Pod 资源配额管理

管理 Pod 的资源使用是缓解资源紧张的重要手段。可以通过设置 requests 和 limits 来控制容器的 CPU 和内存资源使用。

2.1 配置 requests 和 limits

  • requests:表示容器运行时需要的最低资源,调度器会根据 requests 确定 Pod 是否能被分配到某个节点上。
  • limits:表示容器最多可以使用的资源上限,用于防止单个容器过度消耗资源,影响其他容器的运行。

示例 YAML 文件:

yaml apiVersion: v1 kind: Pod metadata: name: resource-demo namespace: default spec: containers: - name: resource-container image: nginx resources: requests: cpu: "500m" # 500 毫核 memory: "256Mi" # 256 MiB 内存 limits: cpu: "1" # 1 核 CPU memory: "512Mi" # 512 MiB 内存

通过合理设置 requests 和 limits,可以避免 Pod 过度占用节点资源,确保集群资源能够合理分配。

3. 使用 Node Affinity 和 Taints/Tolerations 调整调度策略

调整调度策略是优化资源利用率、减少节点压力的有效手段。

3.1 Node Affinity

Node Affinity 是 Kubernetes 调度策略的一种,它允许用户将 Pod 调度到特定属性的节点上。例如,将计算密集型任务调度到高性能的节点。

Node Affinity 示例:

yaml apiVersion: v1 kind: Pod metadata: name: affinity-demo spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: node-type operator: In values: - high-performance containers: - name: nginx image: nginx

通过使用 Node Affinity,可以确保特定的 Pod 被调度到适合其需求的节点上,避免对资源紧张节点的进一步压力。

3.2 Taints 和 Tolerations

Taints 和 Tolerations 用于控制哪些 Pod 可以调度到哪些节点上。当节点上打了 taint,只有带有相应 toleration 的 Pod 才能调度到该节点。

Taints 示例:

sh kubectl taint nodes node1 key=value:NoSchedule

该命令会在 node1 节点上打上 taint,只有包含对应 toleration 的 Pod 才能调度到该节点上。

Tolerations 配置:

yaml apiVersion: v1 kind: Pod metadata: name: toleration-demo spec: tolerations: - key: "key" operator: "Equal" value: "value" effect: "NoSchedule" containers: - name: nginx image: nginx

通过使用 Taints 和 Tolerations,可以把某些节点的资源保护起来,用于特定工作负载,避免所有 Pod 被调度到同一节点造成资源紧张。

4. 使用 Vertical Pod Autoscaler 或 Horizontal Pod Autoscaler

4.1 Horizontal Pod Autoscaler(HPA)

HPA 可以根据 CPU 使用率或自定义指标自动调整 Deployment、ReplicaSet 等资源的副本数量,平衡节点间的负载,减少单个节点的资源紧张。

示例 HPA 配置:

sh kubectl autoscale deployment my-deployment --cpu-percent=50 --min=1 --max=10

  • --cpu-percent:当 CPU 使用率超过 50% 时,HPA 将自动增加副本数量。

4.2 Vertical Pod Autoscaler(VPA)

VPA 可以根据实际的资源使用情况动态调整 Pod 的 CPU 和内存 requests/limits,确保资源利用率最大化,并减少资源浪费。

安装 VPA 可以通过 Helm 或直接应用 VPA 的 YAML 文件,具体配置参考 Kubernetes 官方文档。

5. 资源配额(Resource Quota)和限制范围(LimitRange)

为确保不同命名空间之间的资源公平分配,可以使用 Resource Quota 和 LimitRange。

5.1 Resource Quota

Resource Quota 用于限制命名空间级别的资源使用,防止某一命名空间独占集群资源。

示例 Resource Quota:

yaml apiVersion: v1 kind: ResourceQuota metadata: name: ns-quota namespace: default spec: hard: pods: "10" # 限制最多可以创建 10 个 Pod requests.cpu: "4" # CPU 请求总量不能超过 4 核 requests.memory: "8Gi" # 内存请求总量不能超过 8 GiB limits.cpu: "8" limits.memory: "16Gi"

5.2 LimitRange

LimitRange 用于在命名空间中设置 Pod 或容器的默认 requests 和 limits,确保所有 Pod 遵循合理的资源使用范围。

示例 LimitRange:

yaml apiVersion: v1 kind: LimitRange metadata: name: limits namespace: default spec: limits: - default: cpu: "1" memory: "512Mi" defaultRequest: cpu: "500m" memory: "256Mi" type: Container

总结

  1. 节点扩展:可以通过手动增加节点或使用 Cluster Autoscaler 自动扩展节点数量。
  2. Pod 资源配额管理:通过合理设置 requests 和 limits,确保资源的合理分配和使用。
  3. 调整调度策略:使用 Node Affinity、Taints/Tolerations 控制 Pod 的调度,避免节点资源不均衡。
  4. 使用 HPA/VPA 自动扩展:根据资源使用情况,自动增加 Pod 副本或调整资源请求。
  5. Resource Quota 和 LimitRange:控制不同命名空间的资源使用,防止资源独占或浪费。

通过以上方法,可以有效应对 Kubernetes 集群中节点资源紧张的情况,确保集群稳定、高效地运行。

7.4.1 手动增加节点

假设已经建立了一个 3个master的节点的k8s 集群,那么我现在所面临的有可能是增加一个master节点,或是增加多个 slave 节点,在新的物理机器上要部署什么什么,做什么操作,什么配置,什么命令

在 Kubernetes 集群中扩展节点时,可以根据集群的需求添加新的 Master 节点(控制平面节点)或 Worker 节点(也称为 Slave 节点)。以下是详细的操作步骤,包括在新物理机器上需要部署的组件、配置操作,以及加入集群的命令。

一、增加一个 Master 节点

增加一个 Master 节点的目的是提高控制平面的高可用性。增加新的 Master 节点需要确保它可以与其他 Master 节点进行通信并参与 etcd 集群。

1.1.1 在新机器上安装 Kubernetes 组件

在新的物理机器上,首先需要安装 Kubernetes 相关组件,包括 kubeadm、kubelet 和 kubectl,这些组件可以通过以下步骤安装:

  1. 更新系统并安装依赖包:

sh sudo apt-get update sudo apt-get install -y apt-transport-https ca-certificates curl 2. 添加 Kubernetes 仓库的 GPG 密钥和仓库地址:

sh curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list deb https://apt.kubernetes.io/ kubernetes-xenial main EOF 3. 安装 kubeadm、kubelet 和 kubectl:

sh sudo apt-get update sudo apt-get install -y kubelet kubeadm kubectl sudo apt-mark hold kubelet kubeadm kubectl

1.1.2 配置主机

  1. 禁用交换分区(Kubernetes 不支持交换分区):

sh sudo swapoff -a

还需要注释 /etc/fstab 中的交换分区条目,确保重启后交换分区依旧关闭。 2. 修改网络配置: 确保节点之间可以互相通信,并设置合适的主机名和 /etc/hosts 文件,确保其他 Master 节点的 IP 和主机名可被解析。

1.1.3 加入集群

  1. 获取集群加入的 token 和 discovery-token-ca-cert-hash: 在现有的任意一个 Master 节点上执行以下命令获取 token 和 hash:

sh kubeadm token create --print-join-command

该命令会输出类似以下的 kubeadm join 命令,其中包含 --token 和 --discovery-token-ca-cert-hash,例如:

sh kubeadm join 10.0.0.1:6443 --token abc123.0123456789abcdef --discovery-token-ca-cert-hash sha256:1234567890abcdef... 2. 在新 Master 节点上执行加入命令: 使用上一步生成的 kubeadm join 命令,将新 Master 节点加入集群,并指定该节点为控制平面节点:

sh kubeadm join <master-ip>:<master-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash> --control-plane

示例:

sh kubeadm join 10.0.0.1:6443 --token abc123.0123456789abcdef --discovery-token-ca-cert-hash sha256:1234567890abcdef... --control-plane

1.1.4 确保 etcd 和 kubeadm 证书共享

在多 Master 节点配置中,所有 Master 节点需要共享 etcd 证书和 kubeadm 的 CA 证书。可以将现有 Master 节点的 /etc/kubernetes/pki 目录(包含证书和密钥)复制到新 Master 节点,确保所有证书一致。

二、增加 Worker(Slave)节点

增加 Worker 节点可以扩展集群的计算和存储容量,使得更多的工作负载能够在集群中运行。

1.2.1 在新机器上安装 Kubernetes 组件

与增加 Master 节点类似,增加 Worker 节点同样需要安装 Kubernetes 相关组件。

  1. 更新系统并安装依赖包:

sh sudo apt-get update sudo apt-get install -y apt-transport-https ca-certificates curl 2. 添加 Kubernetes 仓库的 GPG 密钥和仓库地址:

sh curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list deb https://apt.kubernetes.io/ kubernetes-xenial main EOF 3. 安装 kubeadm、kubelet 和 kubectl:

sh sudo apt-get update sudo apt-get install -y kubelet kubeadm kubectl sudo apt-mark hold kubelet kubeadm kubectl

1.2.2 配置主机

  1. 禁用交换分区:

sh sudo swapoff -a

注释 /etc/fstab 中的交换分区条目,确保重启后交换分区依旧关闭。 2. 修改网络配置: 确保节点之间可以互相通信,并设置合适的主机名和 /etc/hosts 文件,确保其他 Master 和 Worker 节点的 IP 和主机名可被解析。

1.2.3 加入集群

  1. 获取集群加入的 token 和 discovery-token-ca-cert-hash: 在现有 Master 节点上执行以下命令获取加入命令:

sh kubeadm token create --print-join-command

输出类似以下命令:

sh kubeadm join 10.0.0.1:6443 --token abc123.0123456789abcdef --discovery-token-ca-cert-hash sha256:1234567890abcdef... 2. 在新 Worker 节点上执行加入命令: 在新 Worker 节点上运行上一步的 kubeadm join 命令:

sh kubeadm join 10.0.0.1:6443 --token abc123.0123456789abcdef --discovery-token-ca-cert-hash sha256:1234567890abcdef...

这样,新 Worker 节点就会加入集群,并能够被 Master 节点调度 Pod 工作负载。

三、检查节点是否成功加入

  1. 在任意一个 Master 节点上,可以使用以下命令查看节点的状态:

sh kubectl get nodes

输出示例: sh NAME STATUS ROLES AGE VERSION master1 Ready control-plane 10d v1.25.0 master2 Ready control-plane 10d v1.25.0 master3 Ready control-plane 10d v1.25.0 new-master Ready control-plane 1h v1.25.0 worker1 Ready <none> 10d v1.25.0 new-worker Ready <none> 20m v1.25.0

  • STATUS:应为 Ready,表示节点已经成功加入并正常运行。
  • ROLES:control-plane 表示 Master 节点,<none> 表示 Worker 节点。

总结

  • 安装 Kubernetes 组件:在新 Master 或 Worker 节点上,需要安装 kubeadm、kubelet 和 kubectl。
  • 禁用交换分区:确保关闭交换分区并在 /etc/fstab 中注释相关条目。
  • 加入集群:
  • Master 节点:使用 kubeadm join 命令并加上 --control-plane 参数。
  • Worker 节点:使用 kubeadm join 命令加入到集群中。
  • 共享证书:在增加 Master 节点时,需要确保所有控制平面节点之间的证书一致。

通过以上步骤,可以成功扩展 Kubernetes 集群,无论是增加 Master 节点还是 Worker 节点,均可以帮助缓解集群中的资源紧张问题,提高集群的高可用性和扩展能力。

7.4.2 自动增加节点

Cluster Autoscaler 是 Kubernetes 集群的一个组件,它可以自动检测集群中的资源利用情况,并根据工作负载的需求动态调整节点的数量。这对于在高峰时自动扩展集群,或在资源使用率较低时减少节点数量以节省成本特别有用。

Cluster Autoscaler 的自动扩展配置主要依赖于云服务提供商提供的 API,因为它需要管理节点(虚拟机实例),因此在云环境中(如 AWS、GCP、Azure)效果最佳。以下是详细的设置步骤和配置选项。

1. 安装 Cluster Autoscaler

可以通过 kubectl apply 或 Helm 来安装 Cluster Autoscaler。安装之前需要确保 Kubernetes 集群能够管理节点,并且你有合适的云提供商集成。例如,如果你的集群部署在 AWS 上,则需要将 IAM 角色和权限正确配置,以允许自动扩展。

1.1 使用 kubectl 安装 Cluster Autoscaler

Step 1: 下载 Cluster Autoscaler 的配置文件。

  • Kubernetes 官方提供了适用于不同云服务提供商的 YAML 配置文件。例如,假设你在 AWS 上运行集群,可以下载以下文件并进行修改: sh curl -O https://raw.githubusercontent.com/kubernetes/autoscaler/cluster-autoscaler-release-1.25/cluster-autoscaler/cloudprovider/aws/examples/cluster-autoscaler-autodiscover.yaml

Step 2: 编辑文件并根据集群配置进行调整。

  • 需要设置适合你的云提供商的参数,通常包括 cluster-name、node-group 名称等。

例如,文件中可能包含类似于以下的配置部分,你需要根据集群环境进行修改:

yaml command: - ./cluster-autoscaler - --v=4 - --stderrthreshold=info - --cloud-provider=aws - --skip-nodes-with-local-storage=false - --expander=least-waste - --nodes=1:10:<node-group-name> # 需要根据你的集群配置修改 node group 名称

  • --cloud-provider=aws:根据你的云提供商配置,可能是 aws、gce、azure、alibaba 等。
  • --nodes=1:10:<node-group-name>:表示在特定的节点组(Node Group)中,最少有 1 个节点,最多有 10 个节点。<node-group-name> 应替换为你的节点组名称。

Step 3: 应用 Cluster Autoscaler 的 YAML 文件。

sh kubectl apply -f cluster-autoscaler-autodiscover.yaml

1.2 使用 Helm 安装 Cluster Autoscaler

也可以使用 Helm Charts 进行安装,这种方法比较方便,特别是需要安装特定版本时。

Step 1: 添加 Helm 仓库。

sh helm repo add autoscaler https://kubernetes.github.io/autoscaler helm repo update

Step 2: 使用 Helm 安装 Cluster Autoscaler。

sh helm install cluster-autoscaler autoscaler/cluster-autoscaler \ --namespace kube-system \ --set cloudProvider=aws \ --set awsRegion=<your-region> \ --set rbac.create=true

  • cloudProvider:根据你的集群所在的云服务提供商设置为 aws、gce、azure 等。
  • awsRegion:设置为你的集群所在的 AWS 区域(例如 us-west-2)。

2. 配置 Cloud Provider 权限

Cluster Autoscaler 需要管理集群中的节点,因此需要足够的权限在云服务提供商的环境中创建、删除节点。

以 AWS 为例:

2.1 配置 IAM 角色

  • 在 AWS 上运行的节点必须有合适的 IAM 角色,使得 Cluster Autoscaler 可以管理这些节点。
  • IAM 角色中需要添加以下权限:

json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "autoscaling:DescribeAutoScalingGroups", "autoscaling:DescribeAutoScalingInstances", "autoscaling:DescribeTags", "autoscaling:SetDesiredCapacity", "autoscaling:TerminateInstanceInAutoScalingGroup", "ec2:DescribeLaunchTemplateVersions" ], "Resource": "*" } ] }

  • 这将允许 Cluster Autoscaler 在节点组(Node Group)中增加或删除节点。

2.2 配置节点组(Node Group)

  • 在 AWS 中,你的 Kubernetes 集群的节点通常由 Auto Scaling Group (ASG) 管理。Cluster Autoscaler 使用这些 ASG 来添加或删除节点。
  • 在节点组的配置中,设置最小和最大节点数量,例如最少 1 个节点,最多 10 个节点。
  • Cluster Autoscaler 会自动调整节点数量,以确保满足 Pod 的资源请求。

3. 配置 Cluster Autoscaler 参数

为了更好地管理节点扩展行为,你可以配置 Cluster Autoscaler 的一些常用参数:

  • --balance-similar-node-groups:确保扩展时,在不同的节点组间保持平衡。
  • --skip-nodes-with-system-pods=false:允许包含系统 Pod 的节点被删除。
  • --expander:指定扩展策略。
  • random:随机选择一个节点组进行扩展。
  • least-waste:最小化资源浪费,选择最合适的节点组进行扩展。
  • most-pods:选择拥有最多 Pod 数量的节点组进行扩展。
  • --scale-down-enabled:是否允许自动缩减节点数量。
  • --scale-down-delay-after-add=10m:在新增节点后的 10 分钟后,才允许进行缩减操作。

4. 验证 Cluster Autoscaler 是否工作

Step 1: 确认 Cluster Autoscaler Pod 正在运行。

sh kubectl get pods -n kube-system | grep cluster-autoscaler

输出示例:

sh cluster-autoscaler-xxxxxxxxxx-yyyyy 1/1 Running 0 1m

Step 2: 查看 Cluster Autoscaler 的日志,确保它正常工作并根据需要调整节点数量。

sh kubectl logs -f deployment/cluster-autoscaler -n kube-system

在日志中可以看到 Cluster Autoscaler 在检查集群状态,决定是否增加或删除节点。

5. 测试自动扩展

为了测试 Cluster Autoscaler 是否正常工作,你可以创建一个需要大量资源的 Deployment。例如:

Step 1: 创建一个 Deployment 需要大量 CPU 和内存。

yaml apiVersion: apps/v1 kind: Deployment metadata: name: stress-deployment namespace: default spec: replicas: 10 selector: matchLabels: app: stress template: metadata: labels: app: stress spec: containers: - name: stress image: busybox command: ["sh", "-c", "while true; do echo 'Stress test'; sleep 10; done"] resources: requests: cpu: "500m" memory: "512Mi"

应用该文件后,集群可能会因资源不足而导致部分 Pod 处于 Pending 状态,Cluster Autoscaler 应该会检测到这一点并自动扩展节点以容纳新 Pod。

Step 2: 观察扩展情况。 使用以下命令查看节点状态,观察是否有新的节点加入集群:

sh kubectl get nodes

总结

  1. 安装 Cluster Autoscaler:

  2. 可以通过 kubectl apply 或 Helm 安装。

  3. 需要根据云提供商(如 AWS、GCP、Azure 等)进行特定配置。
  4. 配置 Cloud Provider 权限:

  5. 在 AWS 上需要配置 IAM 角色,并确保节点组支持扩展。

  6. 设置节点组(Node Group)的最小和最大节点数量。
  7. 配置 Cluster Autoscaler 参数:

  8. 可以通过 --expander、--scale-down-enabled 等参数调整 Cluster Autoscaler 的行为。

  9. 验证和测试 Cluster Autoscaler:

  10. 查看 Cluster Autoscaler Pod 状态和日志,确保其正常工作。

  11. 通过创建需要大量资源的 Deployment 测试自动扩展功能。

通过正确配置 Cluster Autoscaler,可以有效应对 Kubernetes 集群中的资源不足问题,实现节点的自动扩展和缩减,提高集群的灵活性和稳定性。

7.4.3 Pod 资源配额管理

在 Kubernetes 中,通过为 Pod 配置 requests 和 limits,可以有效地管理集群中的资源,确保容器之间的公平资源分配,避免个别容器占用过多资源而导致其他容器受影响。这种管理方式对于集群资源紧张情况下的资源优化分配尤其重要。以下是对 requests 和 limits 的详细说明,以及为什么合理设置它们可以有效缓解节点资源紧张。

1. requests 和 limits 详细解释

  • requests:

  • 资源请求(Resource Requests)是容器运行时所需的最小资源量。

  • Kubernetes 调度器会根据 Pod 的 requests 值来确定该 Pod 能够被分配到哪个节点上。
  • 例如,如果某个容器请求了 500m CPU(500 毫核),调度器会查找具有至少 500m 可用 CPU 的节点,以将 Pod 调度到该节点上。
  • limits:

  • 资源上限(Resource Limits)是容器在运行时可以使用的最大资源量。

  • 容器可以在 requests 和 limits 之间自由消耗资源,但是无法超出 limits 设定的值。
  • 例如,CPU 限制设置为 1 核,表示该容器最多只能使用 1 核 CPU,即便集群中有更多空闲资源。

通过合理设置 requests 和 limits,可以实现以下效果:

  • 提高集群资源的利用效率。
  • 防止资源争用,即某些容器占用过多的资源而影响其他容器的正常运行。
  • 支持资源调度的公平性,使调度器根据请求的资源量合理分配 Pod 到合适的节点上。

2. 示例 YAML 文件解释

以下是一个示例 YAML 文件,通过定义 requests 和 limits 来管理资源。

yaml apiVersion: v1 kind: Pod metadata: name: resource-demo namespace: default spec: containers: - name: resource-container image: nginx resources: requests: cpu: "500m" # 500 毫核 CPU memory: "256Mi" # 256 MiB 内存 limits: cpu: "1" # 1 核 CPU memory: "512Mi" # 512 MiB 内存

2.1 配置项说明

  • requests:

  • cpu: "500m" 表示容器需要 500 毫核 CPU(即 0.5 核)。

  • memory: "256Mi" 表示容器需要 256 MiB 内存。
  • 当 Pod 创建时,Kubernetes 调度器会确保容器调度到一个拥有足够资源的节点上。如果某个节点可用资源不足以满足 requests,那么该 Pod 将不会被调度到该节点上。
  • limits:

  • cpu: "1" 表示容器最多可以使用 1 核 CPU。

  • memory: "512Mi" 表示容器最多可以使用 512 MiB 内存。
  • 当容器尝试使用超过 limits 的资源时,Kubernetes 会采取措施限制使用。
    • CPU 超过 limits:容器会被限制使用更多 CPU,但是不会被强行杀死。Kubernetes 使用 CFS 带宽(CFS quota)来对 CPU 进行节流。
    • 内存超过 limits:容器会被系统终止(OOM,即内存溢出)以保护节点的其他容器。

3. requests 和 limits 的作用及其影响

  1. 资源调度:

  2. requests 对应的是 Kubernetes 调度器的决策。调度器根据请求值决定哪个节点适合容纳新的 Pod。

  3. 如果设置 requests 过高,可能会导致 Pod 难以被调度,因为需要有足够资源的节点才能接受该 Pod。如果设置过低,Pod 会被调度到资源不足的节点,从而导致潜在的资源争用问题。
  4. 资源限制:

  5. limits 定义了容器使用资源的上限,用于确保某个 Pod 不会占用超过其配额的资源。

  6. 设置合理的 limits 可以防止“资源抢占”——某个容器占用大量资源而影响到其他容器的情况。如果不设定 limits,某些工作负载可能会无限制地消耗资源,导致其他关键任务无法运行。
  7. 防止资源争用:

  8. 通过对每个 Pod 的 CPU 和内存进行限制,Kubernetes 可以确保所有工作负载按照设定的资源约束运行,防止某些工作负载因编程错误或其他原因消耗过多资源而导致整个节点性能下降。

  9. 提高资源利用率:

  10. 通过精确的 requests 和 limits 配置,可以更高效地利用节点上的资源。

  11. 例如,假设节点上有 4 核 CPU,如果多个 Pod 的 requests 加起来不超过 4 核,调度器会合理地分配它们到这个节点中,充分利用资源。

4. 示例分析:为何合理配置非常重要?

以下是一些常见的配置方案以及它们的效果:

4.1 没有设置 requests 和 limits

  • 如果没有设置 requests,调度器将认为该 Pod 的资源需求为 0,这意味着 Pod 可以被调度到任何节点,即使该节点几乎没有可用资源。
  • 没有 limits 意味着容器可以无限制地消耗节点资源,可能导致系统 OOM(Out of Memory)并强制终止其他容器。

4.2 设置了 requests 但没有设置 limits

  • Pod 会被调度到有足够可用资源的节点上,但由于没有 limits,容器仍然可以占用更多资源,可能导致影响其他容器。

4.3 设置了合理的 requests 和 limits

  • 调度器会根据 requests 确定是否有足够资源可供分配,而 limits 会限制容器最大资源使用,确保资源不会被单个容器抢占,从而保护其他容器的运行。

5. 小结和最佳实践

  • 为所有 Pod 设置 requests 和 limits:

  • 为 Pod 设置合理的 requests 和 limits,可以避免资源争用并提高调度的准确性。

  • 合理设置值:

  • requests 应该设置为容器的正常运行所需的资源,以确保 Pod 能被调度到合适的节点。

  • limits 则可以设置为稍高于 requests,以确保在高负载时容器有能力使用更多资源,但仍受限于上限值。
  • 监控和调整:

  • 使用监控工具(如 Prometheus 和 Grafana)来观察 Pod 的资源使用情况,定期调整 requests 和 limits 的配置,以适应应用程序的资源需求变化。

  • 平衡资源利用率与调度灵活性:

  • 如果 requests 设置过大,可能导致 Pod 难以被调度;如果设置过小,则可能导致节点资源紧张,因此需要根据实际资源使用情况进行调整。

通过合理的资源配置,Kubernetes 可以确保集群中的每个工作负载都能获得所需的资源,避免过度分配和资源争用问题,从而提高整个集群的稳定性和资源利用率。