# 云平台排错

本章主要介绍在公有云中运行 Kubernetes 时可能会碰到的问题以及解决方法。

在公有云平台上运行 Kubernetes，一般可以使用云平台提供的托管 Kubernetes 服务（比如 Google 的 GKE、微软 Azure 的 AKS 或者 AWS 的 Amazon EKS 等）。当然，为了更自由的灵活性，也可以直接在这些公有云平台的虚拟机中部署 Kubernetes。无论哪种方法，一般都需要给 Kubernetes 配置 Cloud Provider 选项，以方便直接利用云平台提供的高级网络、持久化存储以及安全控制等功能。

而在云平台中运行 Kubernetes 的常见问题有

* 认证授权问题：比如 Kubernetes Cloud Provider 中配置的认证方式无权操作虚拟机所在的网络或持久化存储。这一般从 kube-controller-manager 的日志中很容易发现。
* 网络路由配置失败：正常情况下，Cloud Provider 会为每个 Node 配置一条 PodCIDR 至 NodeIP 的路由规则，如果这些规则有问题就会导致多主机 Pod 相互访问的问题。
* 公网 IP 分配失败：比如 LoadBalancer 类型的 Service 无法分配公网 IP 或者指定的公网 IP 无法使用。这一版也是配置错误导致的。
* 安全组配置失败：比如无法为 Service 创建安全组（如超出配额等）或与已有的安全组冲突等。
* 持久化存储分配或者挂载问题：比如分配 PV 失败（如超出配额、配置错误等）或挂载到虚拟机失败（比如 PV 正被其他异常 Pod 引用而导致无法从旧的虚拟机中卸载）。
* 网络插件使用不当：比如网络插件使用了云平台不支持的网络协议等。

## Node 未注册到集群中

通常，在 Kubelet 启动时会自动将自己注册到 kubernetes API 中，然后通过 `kubectl get nodes` 就可以查询到该节点。 如果新的 Node 没有自动注册到 Kubernetes 集群中，那说明这个注册过程有错误发生，需要检查 kubelet 和 kube-controller-manager 的日志，进而再根据日志查找具体的错误原因。

### Cloud Controller Manager 启动时序问题

在使用外部云提供商（external cloud provider）时，可能会遇到 cloud-controller-manager 的启动时序问题：

#### 问题现象

1. Node 注册后长时间处于 `SchedulingDisabled` 状态
2. Node 显示 `node.cloudprovider.kubernetes.io/uninitialized` taint
3. cloud-controller-manager Pod 无法正常调度或启动

#### 排查步骤

1. **检查 Node taint 状态**

```bash
kubectl describe node <node-name> | grep -i taint
```

2. **检查 cloud-controller-manager 状态**

```bash
kubectl -n kube-system get pods -l component=cloud-controller-manager
kubectl -n kube-system describe pod -l component=cloud-controller-manager
```

3. **检查 cloud-controller-manager 日志**

```bash
kubectl -n kube-system logs -l component=cloud-controller-manager --tail=100
```

#### 解决方案

1. **确保 cloud-controller-manager 具有正确的容忍度**

```yaml
tolerations:
- key: "node.cloudprovider.kubernetes.io/uninitialized"
  operator: "Exists"
  effect: "NoSchedule"
- key: "node-role.kubernetes.io/control-plane"
  operator: "Exists"
  effect: "NoSchedule"
```

2. **使用主机网络模式避免网络依赖**

```yaml
spec:
  hostNetwork: true
```

3. **调度到控制平面节点**

```yaml
nodeSelector:
  node-role.kubernetes.io/control-plane: ""
```

### Kubelet 日志

查看 Kubelet 日志需要首先 SSH 登录到 Node 上，然后运行 `journalctl` 命令查看 kubelet 的日志：

```bash
journalctl -l -u kubelet
```

常见错误信息：

* `failed to initialize cloud provider`: 云提供商配置错误
* `node not found`: Node 在云平台中不存在或权限不足
* `waiting for node to be registered by cloud provider`: 等待 cloud-controller-manager 初始化

### kube-controller-manager 日志

kube-controller-manager 会自动在云平台中给 Node 创建路由，如果路由创建创建失败也有可能导致 Node 注册失败。

```bash
PODNAME=$(kubectl -n kube-system get pod -l component=kube-controller-manager -o jsonpath='{.items[0].metadata.name}')
kubectl -n kube-system logs $PODNAME --tail 100
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://kubernetes.feisky.xyz/troubleshooting/cloud.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
