Add version-2.7 docs

This commit is contained in:
Billy Tat
2023-06-05 10:54:11 -07:00
parent ae741d3b8b
commit 754bfdcab5
868 changed files with 136645 additions and 0 deletions
@@ -0,0 +1,44 @@
---
title: 一般故障排除
---
本文用于帮助你解决使用 Rancher 时遇到的问题。
- [Kubernetes 组件](../pages-for-subheaders/kubernetes-components.md)
对以下核心 Kubernetes 集群组件进行故障排除:
* `etcd`
* `kube-apiserver`
* `kube-controller-manager`
* `kube-scheduler`
* `kubelet`
* `kube-proxy`
* `nginx-proxy`
- [Kubernetes resources](other-troubleshooting-tips/kubernetes-resources.md)
本节介绍了对节点、Ingress Controller 和 Rancher Agent 等 Kubernetes 资源进行故障排除的选项。
- [网络](other-troubleshooting-tips/networking.md)
介绍了解决网络问题的步骤。
- [DNS](other-troubleshooting-tips/dns.md)
解决集群的名称解析问题。
- [对安装在 Kubernetes 上的 Rancher 进行故障排除](other-troubleshooting-tips/rancher-ha.md)
解决[安装在 Kubernetes 上的 Rancher Server](../pages-for-subheaders/install-upgrade-on-a-kubernetes-cluster.md) 的问题。
- [Logging](other-troubleshooting-tips/logging.md)
了解可以配置哪些日志级别,以及如何配置日志级别。
- [审计日志中的用户 ID 跟踪](other-troubleshooting-tips/user-id-tracking-in-audit-logs.md)
了解 Rancher 管理员如何通过外部身份提供程序用户名从 Rancher 审计日志和 Kubernetes 审计日志中跟踪事件。
- [过期的 Webhook 证书](other-troubleshooting-tips/expired-webhook-certificate-rotation.md)
了解如何在每年到期后轮换 Rancher webhook 证书密钥。
@@ -0,0 +1,51 @@
---
title: Controlplane 节点故障排除
---
本文适用于具有 `controlplane` 角色的节点。
## 检查 controlplane 容器是否正在运行
具有 `controlplane` 角色的节点上启动了三个容器:
* `kube-apiserver`
* `kube-controller-manager`
* `kube-scheduler`
容器的状态应该是 **Up**。**Up** 后面显示的时间指的是容器运行的时间。
```
docker ps -a -f=name='kube-apiserver|kube-controller-manager|kube-scheduler'
```
输出示例:
```
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
26c7159abbcc rancher/hyperkube:v1.11.5-rancher1 "/opt/rke-tools/en..." 3 hours ago Up 3 hours kube-apiserver
f3d287ca4549 rancher/hyperkube:v1.11.5-rancher1 "/opt/rke-tools/en..." 3 hours ago Up 3 hours kube-scheduler
bdf3898b8063 rancher/hyperkube:v1.11.5-rancher1 "/opt/rke-tools/en..." 3 hours ago Up 3 hours kube-controller-manager
```
## controlplane 容器日志记录
:::note
如果你添加了多个具有 `controlplane` 角色的节点,`kube-controller-manager``kube-scheduler` 会通过 leader 选举来确定 leader。只有当前 leader 会记录执行的操作。有关检索当前的 leader 的更多信息,请参阅 [Kubernetes leader 选举](../other-troubleshooting-tips/kubernetes-resources.md#kubernetes-leader-选举)。
:::
容器的日志记录可能包含问题的信息。
```
docker logs kube-apiserver
docker logs kube-controller-manager
docker logs kube-scheduler
```
## RKE2 Server 日志
如果 Rancher 配置的 RKE2 集群无法与 Rancher 通信,你可以在下游集群中的 Server 节点上运行此命令,从而获取 RKE2 Server 日志:
```
journalctl -u rke2-server -f
```
@@ -0,0 +1,347 @@
---
title: etcd 节点故障排除
---
本文介绍了对具有 `etcd` 角色的节点进行故障排除的命令和提示。
## 检查 etcd 容器是否正在运行
etcd 容器的状态应该是 **Up**。**Up** 后面显示的时间指的是容器运行的时间。
```
docker ps -a -f=name=etcd$
```
输出示例:
```
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
605a124503b9 rancher/coreos-etcd:v3.2.18 "/usr/local/bin/et..." 2 hours ago Up 2 hours etcd
```
## etcd 容器日志记录
容器的日志记录可能包含问题的信息。
```
docker logs etcd
```
| 日志 | 解释 |
|-----|------------------|
| `health check for peer xxx could not connect: dial tcp IP:2380: getsockopt: connection refused` | 无法连接到端口 2380 上显示的地址。检查 etcd 容器是否在显示地址的主机上运行。 |
| `xxx is starting a new election at term x` | etcd 集群失去了集群仲裁数量,并正在尝试建立一个新的 leader。运行 etcd 的大多数节点关闭/无法访问时,可能会发生这种情况。 |
| `connection error: desc = "transport: Error while dialing dial tcp 0.0.0.0:2379: i/o timeout"; Reconnecting to {0.0.0.0:2379 0 <nil>}` | 主机防火墙正在阻止网络通信。 |
| `rafthttp: request cluster ID mismatch` | 具有 etcd 实例日志 `rafthttp: request cluster ID mismatch` 的节点正在尝试加入已经添加另一个对等节点(peer)的集群。你需要从集群中删除该节点,然后再重新添加。 |
| `rafthttp: failed to find member` | 集群状态(`/var/lib/etcd`)包含加入集群的错误信息。你需要从集群中删除该节点,清理状态目录,然后再重新添加。 |
## etcd 集群和连接检查
运行 etcd 的主机的地址配置决定了 etcd 监听的地址。如果为运行 etcd 的主机配置了内部地址,则需要显式指定 `etcdctl` 的端点。如果任何命令的响应是 `Error: context deadline exceeded`,则 etcd 实例不健康(仲裁丢失或实例未正确加入集群)。
### 检查所有节点上的 etcd 成员
输出应包含具有 `etcd` 角色的所有节点,而且所有节点上的输出应该是相同的。
命令:
```
docker exec etcd etcdctl member list
```
如果 etcd 版本低于 3.3.xKubernetes 1.13.x 及更低版本)且添加节点时指定了 `--internal-address`,则使用以下命令:
```
docker exec etcd sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT member list"
```
输出示例:
```
xxx, started, etcd-xxx, https://IP:2380, https://IP:2379,https://IP:4001
xxx, started, etcd-xxx, https://IP:2380, https://IP:2379,https://IP:4001
xxx, started, etcd-xxx, https://IP:2380, https://IP:2379,https://IP:4001
```
### 检查端点状态
`RAFT TERM` 的值应该是相等的,而且 `RAFT INDEX` 相差不能太大。
命令:
```
docker exec -e ETCDCTL_ENDPOINTS=$(docker exec etcd /bin/sh -c "etcdctl member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','") etcd etcdctl endpoint status --write-out table
```
如果 etcd 版本低于 3.3.xKubernetes 1.13.x 及更低版本)且添加节点时指定了 `--internal-address`,则使用以下命令:
```
docker exec etcd etcdctl endpoint status --endpoints=$(docker exec etcd /bin/sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','") --write-out table
```
输出示例:
```
+-----------------+------------------+---------+---------+-----------+-----------+------------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
+-----------------+------------------+---------+---------+-----------+-----------+------------+
| https://IP:2379 | 333ef673fc4add56 | 3.2.18 | 24 MB | false | 72 | 66887 |
| https://IP:2379 | 5feed52d940ce4cf | 3.2.18 | 24 MB | true | 72 | 66887 |
| https://IP:2379 | db6b3bdb559a848d | 3.2.18 | 25 MB | false | 72 | 66887 |
+-----------------+------------------+---------+---------+-----------+-----------+------------+
```
### 检查端点健康
命令:
```
docker exec -e ETCDCTL_ENDPOINTS=$(docker exec etcd /bin/sh -c "etcdctl member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','") etcd etcdctl endpoint health
```
如果 etcd 版本低于 3.3.xKubernetes 1.13.x 及更低版本)且添加节点时指定了 `--internal-address`,则使用以下命令:
```
docker exec etcd etcdctl endpoint health --endpoints=$(docker exec etcd /bin/sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','")
```
输出示例:
```
https://IP:2379 is healthy: successfully committed proposal: took = 2.113189ms
https://IP:2379 is healthy: successfully committed proposal: took = 2.649963ms
https://IP:2379 is healthy: successfully committed proposal: took = 2.451201ms
```
### 检查端口 TCP/2379 上的连接
命令:
```
for endpoint in $(docker exec etcd /bin/sh -c "etcdctl member list | cut -d, -f5"); do
echo "Validating connection to ${endpoint}/health"
docker run --net=host -v $(docker inspect kubelet --format '{{ range .Mounts }}{{ if eq .Destination "/etc/kubernetes" }}{{ .Source }}{{ end }}{{ end }}')/ssl:/etc/kubernetes/ssl:ro appropriate/curl -s -w "\n" --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) "${endpoint}/health"
done
```
如果 etcd 版本低于 3.3.xKubernetes 1.13.x 及更低版本)且添加节点时指定了 `--internal-address`,则使用以下命令:
```
for endpoint in $(docker exec etcd /bin/sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT member list | cut -d, -f5"); do
echo "Validating connection to ${endpoint}/health";
docker run --net=host -v $(docker inspect kubelet --format '{{ range .Mounts }}{{ if eq .Destination "/etc/kubernetes" }}{{ .Source }}{{ end }}{{ end }}')/ssl:/etc/kubernetes/ssl:ro appropriate/curl -s -w "\n" --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) "${endpoint}/health"
done
```
输出示例:
```
Validating connection to https://IP:2379/health
{"health": "true"}
Validating connection to https://IP:2379/health
{"health": "true"}
Validating connection to https://IP:2379/health
{"health": "true"}
```
### 检查端口 TCP/2380 上的连接
命令:
```
for endpoint in $(docker exec etcd /bin/sh -c "etcdctl member list | cut -d, -f4"); do
echo "Validating connection to ${endpoint}/version";
docker run --net=host -v $(docker inspect kubelet --format '{{ range .Mounts }}{{ if eq .Destination "/etc/kubernetes" }}{{ .Source }}{{ end }}{{ end }}')/ssl:/etc/kubernetes/ssl:ro appropriate/curl --http1.1 -s -w "\n" --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) "${endpoint}/version"
done
```
如果 etcd 版本低于 3.3.xKubernetes 1.13.x 及更低版本)且添加节点时指定了 `--internal-address`,则使用以下命令:
```
for endpoint in $(docker exec etcd /bin/sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT member list | cut -d, -f4"); do
echo "Validating connection to ${endpoint}/version";
docker run --net=host -v $(docker inspect kubelet --format '{{ range .Mounts }}{{ if eq .Destination "/etc/kubernetes" }}{{ .Source }}{{ end }}{{ end }}')/ssl:/etc/kubernetes/ssl:ro appropriate/curl --http1.1 -s -w "\n" --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) "${endpoint}/version"
done
```
输出示例:
```
Validating connection to https://IP:2380/version
{"etcdserver":"3.2.18","etcdcluster":"3.2.0"}
Validating connection to https://IP:2380/version
{"etcdserver":"3.2.18","etcdcluster":"3.2.0"}
Validating connection to https://IP:2380/version
{"etcdserver":"3.2.18","etcdcluster":"3.2.0"}
```
## etcd 告警
etcd 会触发告警(例如空间不足时)。
命令:
```
docker exec etcd etcdctl alarm list
```
如果 etcd 版本低于 3.3.xKubernetes 1.13.x 及更低版本)且添加节点时指定了 `--internal-address`,则使用以下命令:
```
docker exec etcd sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT alarm list"
```
触发 NOSPACE 告警的输出示例:
```
memberID:x alarm:NOSPACE
memberID:x alarm:NOSPACE
memberID:x alarm:NOSPACE
```
## etcd 空间错误
相关的错误消息是 `etcdserver: mvcc: database space exceeded``applying raft message exceeded backend quota`。告警 `NOSPACE` 会被触发。
解决:
- [压缩键空间](#压缩键空间)
- [对所有 etcd 成员进行碎片整理](#对所有-etcd-成员进行碎片整理)
- [检查端点状态](#检查端点状态)
- [解除告警](#解除告警)
### 压缩键空间
命令:
```
rev=$(docker exec etcd etcdctl endpoint status --write-out json | egrep -o '"revision":[0-9]*' | egrep -o '[0-9]*')
docker exec etcd etcdctl compact "$rev"
```
如果 etcd 版本低于 3.3.xKubernetes 1.13.x 及更低版本)且添加节点时指定了 `--internal-address`,则使用以下命令:
```
rev=$(docker exec etcd sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT endpoint status --write-out json | egrep -o '\"revision\":[0-9]*' | egrep -o '[0-9]*'")
docker exec etcd sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT compact \"$rev\""
```
输出示例:
```
compacted revision xxx
```
### 对所有 etcd 成员进行碎片整理
命令:
```
docker exec -e ETCDCTL_ENDPOINTS=$(docker exec etcd /bin/sh -c "etcdctl member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','") etcd etcdctl defrag
```
如果 etcd 版本低于 3.3.xKubernetes 1.13.x 及更低版本)且添加节点时指定了 `--internal-address`,则使用以下命令:
```
docker exec etcd sh -c "etcdctl defrag --endpoints=$(docker exec etcd /bin/sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','")"
```
输出示例:
```
Finished defragmenting etcd member[https://IP:2379]
Finished defragmenting etcd member[https://IP:2379]
Finished defragmenting etcd member[https://IP:2379]
```
### 检查端点状态
命令:
```
docker exec -e ETCDCTL_ENDPOINTS=$(docker exec etcd /bin/sh -c "etcdctl member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','") etcd etcdctl endpoint status --write-out table
```
如果 etcd 版本低于 3.3.xKubernetes 1.13.x 及更低版本)且添加节点时指定了 `--internal-address`,则使用以下命令:
```
docker exec etcd sh -c "etcdctl endpoint status --endpoints=$(docker exec etcd /bin/sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','") --write-out table"
```
输出示例:
```
+-----------------+------------------+---------+---------+-----------+-----------+------------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
+-----------------+------------------+---------+---------+-----------+-----------+------------+
| https://IP:2379 | e973e4419737125 | 3.2.18 | 553 kB | false | 32 | 2449410 |
| https://IP:2379 | 4a509c997b26c206 | 3.2.18 | 553 kB | false | 32 | 2449410 |
| https://IP:2379 | b217e736575e9dd3 | 3.2.18 | 553 kB | true | 32 | 2449410 |
+-----------------+------------------+---------+---------+-----------+-----------+------------+
```
### 解除告警
如果压缩和整理碎片后确定数据库大小下降了,则需要解除告警来允许 etcd 再次写入。
命令:
```
docker exec etcd etcdctl alarm list
docker exec etcd etcdctl alarm disarm
docker exec etcd etcdctl alarm list
```
如果 etcd 版本低于 3.3.xKubernetes 1.13.x 及更低版本)且添加节点时指定了 `--internal-address`,则使用以下命令:
```
docker exec etcd sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT alarm list"
docker exec etcd sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT alarm disarm"
docker exec etcd sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT alarm list"
```
输出示例:
```
docker exec etcd etcdctl alarm list
memberID:x alarm:NOSPACE
memberID:x alarm:NOSPACE
memberID:x alarm:NOSPACE
docker exec etcd etcdctl alarm disarm
docker exec etcd etcdctl alarm list
```
## 日志级别
etcd 的日志级别可以通过 API 来动态更改。你可以使用以下命令来配置调试日志。
命令:
```
docker run --net=host -v $(docker inspect kubelet --format '{{ range .Mounts }}{{ if eq .Destination "/etc/kubernetes" }}{{ .Source }}{{ end }}{{ end }}')/ssl:/etc/kubernetes/ssl:ro appropriate/curl -s -XPUT -d '{"Level":"DEBUG"}' --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) $(docker exec etcd printenv ETCDCTL_ENDPOINTS)/config/local/log
```
如果 etcd 版本低于 3.3.xKubernetes 1.13.x 及更低版本)且添加节点时指定了 `--internal-address`,则使用以下命令:
```
docker run --net=host -v $(docker inspect kubelet --format '{{ range .Mounts }}{{ if eq .Destination "/etc/kubernetes" }}{{ .Source }}{{ end }}{{ end }}')/ssl:/etc/kubernetes/ssl:ro appropriate/curl -s -XPUT -d '{"Level":"DEBUG"}' --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) $(docker exec etcd printenv ETCDCTL_ENDPOINT)/config/local/log
```
要将日志级别重置回默认值 (`INFO`),你可以使用以下命令。
命令:
```
docker run --net=host -v $(docker inspect kubelet --format '{{ range .Mounts }}{{ if eq .Destination "/etc/kubernetes" }}{{ .Source }}{{ end }}{{ end }}')/ssl:/etc/kubernetes/ssl:ro appropriate/curl -s -XPUT -d '{"Level":"INFO"}' --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) $(docker exec etcd printenv ETCDCTL_ENDPOINTS)/config/local/log
```
如果 etcd 版本低于 3.3.xKubernetes 1.13.x 及更低版本)且添加节点时指定了 `--internal-address`,则使用以下命令:
```
docker run --net=host -v $(docker inspect kubelet --format '{{ range .Mounts }}{{ if eq .Destination "/etc/kubernetes" }}{{ .Source }}{{ end }}{{ end }}')/ssl:/etc/kubernetes/ssl:ro appropriate/curl -s -XPUT -d '{"Level":"INFO"}' --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) $(docker exec etcd printenv ETCDCTL_ENDPOINT)/config/local/log
```
## etcd 内容
如果要查看 etcd 的内容,你可以查看流事件,也可以直接查询 etcd。详情请参阅以下示例。
### 查看流事件
命令:
```
docker exec etcd etcdctl watch --prefix /registry
```
如果 etcd 版本低于 3.3.xKubernetes 1.13.x 及更低版本)且添加节点时指定了 `--internal-address`,则使用以下命令:
```
docker exec etcd etcdctl --endpoints=\$ETCDCTL_ENDPOINT watch --prefix /registry
```
如果你只想查看受影响的键(而不是二进制数据),你可以将 `| grep -a ^/registry` 尾附到该命令来过滤键。
### 直接查询 etcd
命令:
```
docker exec etcd etcdctl get /registry --prefix=true --keys-only
```
如果 etcd 版本低于 3.3.xKubernetes 1.13.x 及更低版本)且添加节点时指定了 `--internal-address`,则使用以下命令:
```
docker exec etcd etcdctl --endpoints=\$ETCDCTL_ENDPOINT get /registry --prefix=true --keys-only
```
你可以使用以下命令来处理数据,从而获取每个键的计数摘要:
```
docker exec etcd etcdctl get /registry --prefix=true --keys-only | grep -v ^$ | awk -F'/' '{ if ($3 ~ /cattle.io/) {h[$3"/"$4]++} else { h[$3]++ }} END { for(k in h) print h[k], k }' | sort -nr
```
## 更换不健康的 etcd 节点
如果你 etcd 集群中的某个节点变得不健康,在将新的 etcd 节点添加到集群之前,我们建议你修复或删除故障/不健康的节点。
@@ -0,0 +1,68 @@
---
title: nginx-proxy 故障排除
---
每个没有 `controlplane` 角色的节点上都部署了 `nginx-proxy` 容器。`nginx-proxy` 基于具有 `controlplane` 角色的可用节点来动态生成 NGINX 配置,从而提供对这些 `controlplane` 角色节点的访问。
## 检查容器是否正在运行
该容器称为 `nginx-proxy`,它的状态应该是 `Up``Up` 后面显示的时间指的是容器运行的时间。
```
docker ps -a -f=name=nginx-proxy
```
输出示例:
```
docker ps -a -f=name=nginx-proxy
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c3e933687c0e rancher/rke-tools:v0.1.15 "nginx-proxy CP_HO..." 3 hours ago Up 3 hours nginx-proxy
```
## 检查生成的 NGINX 配置
生成的配置包括了具有 `controlplane` 角色的节点的 IP 地址。你可以使用以下命令来检查配置:
```
docker exec nginx-proxy cat /etc/nginx/nginx.conf
```
输出示例:
```
error_log stderr notice;
worker_processes auto;
events {
multi_accept on;
use epoll;
worker_connections 1024;
}
stream {
upstream kube_apiserver {
server ip_of_controlplane_node1:6443;
server ip_of_controlplane_node2:6443;
}
server {
listen 6443;
proxy_pass kube_apiserver;
proxy_timeout 30;
proxy_connect_timeout 2s;
}
}
```
## nginx-proxy 容器日志记录
容器的日志记录可能包含问题的信息。
```
docker logs nginx-proxy
```
@@ -0,0 +1,34 @@
---
title: Worker 节点和通用组件故障排除
---
本文包括了运行在所有角色节点上的组件,因此适用于每个节点。
## 检查容器是否正在运行
具有 `worker` 角色的节点上启动了两个容器:
* kubelet
* kube-proxy
容器的状态应该是 `Up``Up` 后面显示的时间指的是容器运行的时间。
```
docker ps -a -f=name='kubelet|kube-proxy'
```
输出示例:
```
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
158d0dcc33a5 rancher/hyperkube:v1.11.5-rancher1 "/opt/rke-tools/en..." 3 hours ago Up 3 hours kube-proxy
a30717ecfb55 rancher/hyperkube:v1.11.5-rancher1 "/opt/rke-tools/en..." 3 hours ago Up 3 hours kubelet
```
## 容器日志记录
容器的日志记录可能包含问题的信息。
```
docker logs kubelet
docker logs kube-proxy
```
@@ -0,0 +1,220 @@
---
title: DNS
---
本文列出的命令/步骤可用于检查集群中的名称解析问题。
请确保你配置了正确的 kubeconfig(例如,为 Rancher HA 配置了 `export KUBECONFIG=$PWD/kube_config_cluster.yml`)或通过 UI 使用了嵌入式 kubectl。
在运行 DNS 检查之前,请检查集群的[默认 DNS 提供商](../../reference-guides/cluster-configuration/rancher-server-configuration/rke1-cluster-configuration.md#默认-dns-提供商),并确保[覆盖网络正常运行](networking.md#检查覆盖网络是否正常运行),因为这也可能导致 DNS 解析(部分)失败。
### 检查 DNS pod 是否正在运行
```
kubectl -n kube-system get pods -l k8s-app=kube-dns
```
使用 CoreDNS 时的示例输出:
```
NAME READY STATUS RESTARTS AGE
coredns-799dffd9c4-6jhlz 1/1 Running 0 76m
```
使用 kube-dns 时的示例输出:
```
NAME READY STATUS RESTARTS AGE
kube-dns-5fd74c7488-h6f7n 3/3 Running 0 4m13s
```
### 检查 DNS 服务是否显示正确的 cluster-ip
```
kubectl -n kube-system get svc -l k8s-app=kube-dns
```
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kube-dns ClusterIP 10.43.0.10 <none> 53/UDP,53/TCP 4m13s
```
### 检查是否正在解析域名
检查是否正在解析内部集群名称(在本例中为 `kubernetes.default`),`Server:` 后面显示的 IP 应与 `kube-dns` 服务的 `CLUSTER-IP` 一致。
```
kubectl run -it --rm --restart=Never busybox --image=busybox:1.28 -- nslookup kubernetes.default
```
输出示例:
```
Server: 10.43.0.10
Address 1: 10.43.0.10 kube-dns.kube-system.svc.cluster.local
Name: kubernetes.default
Address 1: 10.43.0.1 kubernetes.default.svc.cluster.local
pod "busybox" deleted
```
检查是否正在解析外部名称(在本例中为 `www.google.com`):
```
kubectl run -it --rm --restart=Never busybox --image=busybox:1.28 -- nslookup www.google.com
```
输出示例:
```
Server: 10.43.0.10
Address 1: 10.43.0.10 kube-dns.kube-system.svc.cluster.local
Name: www.google.com
Address 1: 2a00:1450:4009:80b::2004 lhr35s04-in-x04.1e100.net
Address 2: 216.58.211.100 ams15s32-in-f4.1e100.net
pod "busybox" deleted
```
如果要检查所有主机的域名解析,请执行以下步骤:
1. 将以下文件另存为 `ds-dnstest.yml`
```
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: dnstest
spec:
selector:
matchLabels:
name: dnstest
template:
metadata:
labels:
name: dnstest
spec:
tolerations:
- operator: Exists
containers:
- image: busybox:1.28
imagePullPolicy: Always
name: alpine
command: ["sh", "-c", "tail -f /dev/null"]
terminationMessagePath: /dev/termination-log
```
2. 通过运行 `kubectl create -f ds-dnstest.yml` 启动它。
3. 等待 `kubectl rollout status ds/dnstest -w` 返回 `daemon set "dnstest" successfully rolled out`。
4. 将环境变量 `DOMAIN` 配置为主机能够解析的完全限定域名(Fully Qualified Domain NameFQDN),例如 `www.google.com`,并运行以下命令让每个主机上的各个容器解析配置的域名(它是单行命令):
```
export DOMAIN=www.google.com; echo "=> Start DNS resolve test"; kubectl get pods -l name=dnstest --no-headers -o custom-columns=NAME:.metadata.name,HOSTIP:.status.hostIP | while read pod host; do kubectl exec $pod -- /bin/sh -c "nslookup $DOMAIN > /dev/null 2>&1"; RC=$?; if [ $RC -ne 0 ]; then echo $host cannot resolve $DOMAIN; fi; done; echo "=> End DNS resolve test"
```
5. 完成此命令后,如果一切正确,则输出如下:
```
=> Start DNS resolve test
=> End DNS resolve test
```
如果你在输出中看到错误,则表示主机无法解析给定的 FQDN。
在以下错误输出示例中,IP 为 209.97.182.150 的主机阻止了 UDP 端口:
```
=> Start DNS resolve test
command terminated with exit code 1
209.97.182.150 cannot resolve www.google.com
=> End DNS resolve test
```
运行 `kubectl delete ds/dnstest` 清理 alpine DaemonSet。
### CoreDNS 相关
#### 检查 CoreDNS 日志记录
```
kubectl -n kube-system logs -l k8s-app=kube-dns
```
#### 检查配置
CoreDNS 配置存储在 `kube-system` 命名空间中 configmap 的 `coredns` 中。
```
kubectl -n kube-system get configmap coredns -o go-template={{.data.Corefile}}
```
#### 检查 resolv.conf 中的上游名称服务器
默认情况下,配置在主机(在 `/etc/resolv.conf` 里)上的名称服务器会用作 CoreDNS 的上游名称服务器。你可以在主机上检查此文件,或将 `dnsPolicy` 设置为 `Default`(将继承其主机的 `/etc/resolv.conf`)并运行以下 Pod
```
kubectl run -i --restart=Never --rm test-${RANDOM} --image=ubuntu --overrides='{"kind":"Pod", "apiVersion":"v1", "spec": {"dnsPolicy":"Default"}}' -- sh -c 'cat /etc/resolv.conf'
```
#### 启用日志查询
你可以通过在 configmap `coredns` 的 Corefile 配置中启用 [log plugin](https://coredns.io/plugins/log/) 来启用日志查询。为此,你可以使用 `kubectl -n kube-system edit configmap coredns`,或运行以下命令来替换配置:
```
kubectl get configmap -n kube-system coredns -o json | sed -e 's_loadbalance_log\\n loadbalance_g' | kubectl apply -f -
```
这样,所有查询都会记入日志,并且可以使用[检查 CoreDNS 日志记录](#检查-coredns-日志记录)中的命令进行检查。
### kube-dns 相关
#### 检查 kubedns 容器中的上游名称服务器
默认情况下,配置在主机(在 `/etc/resolv.conf` 里)上的名称服务器会用作 kube-dns 的上游名称服务器。有时,主机会运行本地缓存 DNS 名称服务器,这意味着 `/etc/resolv.conf` 中的地址将指向 Loopback 范围(`127.0.0.0/8`)内的地址,而容器将无法访问该范围。对于 Ubuntu 18.04,这是由 `systemd-resolved` 进行的。我们会检测 `systemd-resolved` 是否正在运行,并自动使用具有正确上游名称服务器的 `/etc/resolv.conf` 文件(位于 `/run /systemd/resolve/resolv.conf`)。
使用以下命令检查 kubedns 容器使用的上游名称服务器:
```
kubectl -n kube-system get pods -l k8s-app=kube-dns --no-headers -o custom-columns=NAME:.metadata.name,HOSTIP:.status.hostIP | while read pod host; do echo "Pod ${pod} on host ${host}"; kubectl -n kube-system exec $pod -c kubedns cat /etc/resolv.conf; done
```
输出示例:
```
Pod kube-dns-667c7cb9dd-z4dsf on host x.x.x.x
nameserver 1.1.1.1
nameserver 8.8.4.4
```
如果输出显示 Loopback 范围(`127.0.0.0/8`)内的地址 ,你可以通过以下两种方式解决此问题:
* 确保在集群节点上的 `/etc/resolv.conf` 列出了正确的名称服务器。如果需要了解如何进行操作,请参阅你的操作系统文档。请确保你在配置集群之前执行此操作,或在修改后重启节点。
* 通过配置 `kubelet` 来使用不同的文件进行名称解析,你可以使用如下的 `extra_args`(其中 `/run/resolvconf/resolv.conf` 是具有正确名称服务器的文件):
```
services:
kubelet:
extra_args:
resolv-conf: "/run/resolvconf/resolv.conf"
```
:::note
由于 `kubelet` 在容器内运行,因此 `/etc` 和 `/usr` 中文件的路径位于 `kubelet` 容器内的 `/host/etc` 和 `/host/usr` 中。
:::
请参阅[使用 YAML 编辑集群](../../reference-guides/cluster-configuration/rancher-server-configuration/rke1-cluster-configuration.md#使用-yaml-编辑集群)了解如何应用此修改。集群配置完成后,你必须删除 kube-dns pod 以激活 pod 中的新设置:
```
kubectl delete pods -n kube-system -l k8s-app=kube-dns
pod "kube-dns-5fd74c7488-6pwsf" deleted
```
你可以[检查是否正在解析域名](#检查是否正在解析域名)来尝试再次解析名称。
如果要检查集群中的 kube-dns 配置(例如,检查是否配置了不同的上游名称服务器),你可以运行以下命令来列出 kube-dns 配置:
```
kubectl -n kube-system get configmap kube-dns -o go-template='{{range $key, $value := .data}}{{ $key }}{{":"}}{{ $value }}{{"\n"}}{{end}}'
```
输出示例:
```
upstreamNameservers:["1.1.1.1"]
```
@@ -0,0 +1,28 @@
---
title: 过期 Webhook 证书轮换
---
如果你的 Rancher 版本安装了 `rancher-webhook`,某些版本创建的证书将在一年后过期。如果证书未续订,你需要轮换你的 webhook 证书。
在 Rancher v2.6.3 及更高版本中,rancher-webhook deployments 将在到期日期后 30 天或更短的时间内自动更新其 TLS 证书。如果你使用的是 v2.6.2 或更低版本,你可以通过下面两种方法来解决这个问题。
##### 1. 如果用户具有集群访问权限,运行以下命令:
```
kubectl delete secret -n cattle-system cattle-webhook-tls
kubectl delete mutatingwebhookconfigurations.admissionregistration.k8s.io --ignore-not-found=true rancher.cattle.io
kubectl delete pod -n cattle-system -l app=rancher-webhook
```
##### 2. 如果用户没有集群访问权限,使用 `kubectl`:
1. 删除 local 集群 `cattle-system` 命名空间中的 `cattle-webhook-tls` 密文。
2. 删除 `rancher.cattle.io` mutating webhook。
3. 删除 local 集群 `cattle-system` 命名空间中的 `rancher-webhook` pod。
:::note
webhook 证书过期问题不止示例中列出的 `cattle-webhook-tls`。你需要相应地填写你过期的证书密文。
:::
@@ -0,0 +1,255 @@
---
title: Kubernetes 资源
---
本文列出的命令/步骤可用于检查最重要的 Kubernetes 资源,并应用于 [Rancher 启动的 Kubernetes](../../pages-for-subheaders/launch-kubernetes-with-rancher.md) 集群。
请确保你配置了正确的 kubeconfig(例如,为 Rancher HA 配置了 `export KUBECONFIG=$PWD/kube_config_cluster.yml`)或通过 UI 使用了嵌入式 kubectl。
## 节点
### 获取节点
运行以下命令并检查以下内容:
- 集群中的所有节点都已列出,没有缺失的节点。
- 所有节点的状态都是 **Ready**(如果未处于 **Ready** 状态,请运行 `docker logs kubelet` 检查该节点上的 `kubelet` 容器日志)
- 检查所有节点是否报告了正确的版本。
- 检查 OS/Kernel/Docker 值是否按预期显示(此问题可能与升级 OS/Kernel/Docker 相关)。
```
kubectl get nodes -o wide
```
输出示例:
```
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
controlplane-0 Ready controlplane 31m v1.13.5 138.68.188.91 <none> Ubuntu 18.04.2 LTS 4.15.0-47-generic docker://18.9.5
etcd-0 Ready etcd 31m v1.13.5 138.68.180.33 <none> Ubuntu 18.04.2 LTS 4.15.0-47-generic docker://18.9.5
worker-0 Ready worker 30m v1.13.5 139.59.179.88 <none> Ubuntu 18.04.2 LTS 4.15.0-47-generic docker://18.9.5
```
### 获取节点状况
运行以下命令列出具有 [Node Conditions](https://kubernetes.io/docs/concepts/architecture/nodes/#condition) 的节点:
```
kubectl get nodes -o go-template='{{range .items}}{{$node := .}}{{range .status.conditions}}{{$node.metadata.name}}{{": "}}{{.type}}{{":"}}{{.status}}{{"\n"}}{{end}}{{end}}'
```
运行以下命令,列出具有 active [Node Conditions](https://kubernetes.io/docs/concepts/architecture/nodes/#condition) 的节点,这些节点可能阻止正常操作:
```
kubectl get nodes -o go-template='{{range .items}}{{$node := .}}{{range .status.conditions}}{{if ne .type "Ready"}}{{if eq .status "True"}}{{$node.metadata.name}}{{": "}}{{.type}}{{":"}}{{.status}}{{"\n"}}{{end}}{{else}}{{if ne .status "True"}}{{$node.metadata.name}}{{": "}}{{.type}}{{": "}}{{.status}}{{"\n"}}{{end}}{{end}}{{end}}{{end}}'
```
输出示例:
```
worker-0: DiskPressure:True
```
## Kubernetes leader 选举
### Kubernetes Controller 管理器 leader
Leader 由 Leader 选举确定。确定 Leader 后,Leader`holderIdentity`)会保存在 `kube-controller-manager` 端点中(在本例中为 `controlplane-0`)。
```
kubectl -n kube-system get endpoints kube-controller-manager -o jsonpath='{.metadata.annotations.control-plane\.alpha\.kubernetes\.io/leader}'
{"holderIdentity":"controlplane-0_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","leaseDurationSeconds":15,"acquireTime":"2018-12-27T08:59:45Z","renewTime":"2018-12-27T09:44:57Z","leaderTransitions":0}>
```
### Kubernetes 调度器 Leader
Leader 由 Leader 选举确定。确定 Leader 后,Leader`holderIdentity`)会保存在 `kube-scheduler` 端点中(在本例中为 `controlplane-0`)。
```
kubectl -n kube-system get endpoints kube-scheduler -o jsonpath='{.metadata.annotations.control-plane\.alpha\.kubernetes\.io/leader}'
{"holderIdentity":"controlplane-0_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","leaseDurationSeconds":15,"acquireTime":"2018-12-27T08:59:45Z","renewTime":"2018-12-27T09:44:57Z","leaderTransitions":0}>
```
## Ingress Controller
默认的 Ingress Controller 是 NGINX,作为 DaemonSet 部署在 `ingress-nginx` 命名空间中。Pod 仅会调度到具有 `worker` 角色的节点。
检查 pod 是否运行在所有节点上:
```
kubectl -n ingress-nginx get pods -o wide
```
输出示例:
```
kubectl -n ingress-nginx get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
default-http-backend-797c5bc547-kwwlq 1/1 Running 0 17m x.x.x.x worker-1
nginx-ingress-controller-4qd64 1/1 Running 0 14m x.x.x.x worker-1
nginx-ingress-controller-8wxhm 1/1 Running 0 13m x.x.x.x worker-0
```
如果 pod 无法运行(即状态不是 **Running**Ready 状态未显示 `1/1`,或者有大量 Restarts),请检查 pod 详细信息,日志和命名空间事件。
### Pod 详细信息
```
kubectl -n ingress-nginx describe pods -l app=ingress-nginx
```
### Pod 容器日志
下面的命令可以显示所有标记为 “app=ingress-nginx” 的 pod 的日志,但是由于 `kubectl logs` 命令的限制,它只会显示 10 行日志。有关详细信息,请参阅 `kubectl logs -h``--tail`
```
kubectl -n ingress-nginx logs -l app=ingress-nginx
```
如果需要查看完整的日志,请在命令中尾随 pod 名称:
```
kubectl -n ingress-nginx logs <pod name>
```
### 命名空间事件
```
kubectl -n ingress-nginx get events
```
### 调试日志
要启用调试日志:
```
kubectl -n ingress-nginx patch ds nginx-ingress-controller --type='json' -p='[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--v=5"}]'
```
### 检查配置
在每个 pod 中检索生成的配置:
```
kubectl -n ingress-nginx get pods -l app=ingress-nginx --no-headers -o custom-columns=.NAME:.metadata.name | while read pod; do kubectl -n ingress-nginx exec $pod -- cat /etc/nginx/nginx.conf; done
```
## Rancher Agents
Rancher Agent 用于实现与集群的通信(通过 `cattle-cluster-agent` 的 Kubernetes API)和与节点的通信(通过 `cattle-node-agent` 的集群配置)。
#### cattle-node-agent
检查每个节点上是否存在 cattle-node-agent pod,状态是否为 **Running**,并且重启次数不多:
```
kubectl -n cattle-system get pods -l app=cattle-agent -o wide
```
输出示例:
```
NAME READY STATUS RESTARTS AGE IP NODE
cattle-node-agent-4gc2p 1/1 Running 0 2h x.x.x.x worker-1
cattle-node-agent-8cxkk 1/1 Running 0 2h x.x.x.x etcd-1
cattle-node-agent-kzrlg 1/1 Running 0 2h x.x.x.x etcd-0
cattle-node-agent-nclz9 1/1 Running 0 2h x.x.x.x controlplane-0
cattle-node-agent-pwxp7 1/1 Running 0 2h x.x.x.x worker-0
cattle-node-agent-t5484 1/1 Running 0 2h x.x.x.x controlplane-1
cattle-node-agent-t8mtz 1/1 Running 0 2h x.x.x.x etcd-2
```
检查特定或所有 cattle-node-agent pod 的日志记录:
```
kubectl -n cattle-system logs -l app=cattle-agent
```
#### cattle-cluster-agent
检查 cattle-cluster-agent pod 是否存在于集群中,状态是否为 **Running**,并且重启次数不多:
```
kubectl -n cattle-system get pods -l app=cattle-cluster-agent -o wide
```
输出示例:
```
NAME READY STATUS RESTARTS AGE IP NODE
cattle-cluster-agent-54d7c6c54d-ht9h4 1/1 Running 0 2h x.x.x.x worker-1
```
检查 cattle-cluster-agent pod 的日志记录:
```
kubectl -n cattle-system logs -l app=cattle-cluster-agent
```
## Jobs 和 Pods
### 检查 Pod 或 Job 的状态是否为 **Running**/**Completed**
运行以下命令进行检查:
```
kubectl get pods --all-namespaces
```
如果 Pod 的状态不是 **Running**,你可以通过运行命令来找到根本原因。
### 描述 Pod
```
kubectl describe pod POD_NAME -n NAMESPACE
```
### Pod 容器日志
```
kubectl logs POD_NAME -n NAMESPACE
```
如果 Job 的状态不是 **Completed**,你可以通过运行命令来找到根本原因。
### 描述 Job
```
kubectl describe job JOB_NAME -n NAMESPACE
```
### Job Pod 容器的日志
```
kubectl logs -l job-name=JOB_NAME -n NAMESPACE
```
### 驱逐的 Pod
可以根据 [eviction 信号](https://kubernetes.io/docs/tasks/administer-cluster/out-of-resource/#eviction-policy)来驱逐 Pod。
检索被驱逐的 Pod 列表(podname 和命名空间):
```
kubectl get pods --all-namespaces -o go-template='{{range .items}}{{if eq .status.phase "Failed"}}{{if eq .status.reason "Evicted"}}{{.metadata.name}}{{" "}}{{.metadata.namespace}}{{"\n"}}{{end}}{{end}}{{end}}'
```
要删除所有被驱逐的 pod
```
kubectl get pods --all-namespaces -o go-template='{{range .items}}{{if eq .status.phase "Failed"}}{{if eq .status.reason "Evicted"}}{{.metadata.name}}{{" "}}{{.metadata.namespace}}{{"\n"}}{{end}}{{end}}{{end}}' | while read epod enamespace; do kubectl -n $enamespace delete pod $epod; done
```
检索被驱逐的 pod 列表、调度节点以及原因:
```
kubectl get pods --all-namespaces -o go-template='{{range .items}}{{if eq .status.phase "Failed"}}{{if eq .status.reason "Evicted"}}{{.metadata.name}}{{" "}}{{.metadata.namespace}}{{"\n"}}{{end}}{{end}}{{end}}' | while read epod enamespace; do kubectl -n $enamespace get pod $epod -o=custom-columns=NAME:.metadata.name,NODE:.spec.nodeName,MSG:.status.message; done
```
### Job 未完成
如果你启用了 Istio 而且你部署的 Job 未完成,你需要按照[这些步骤](../../how-to-guides/advanced-user-guides/istio-setup-guide/enable-istio-in-namespace.md)将注释添加到 Pod 中。
由于 Istio Sidecars 会一直运行,因此即使任务完成了,也不能认为 Job 已完成。这是一个临时的解决方法,它禁止了 Istio 和添加了注释的 Pod 之间的通信。如果你使用了这个方法,由于这个 Job 无法访问服务网格,因此你将不能继续使用 Job 进行集成测试。
@@ -0,0 +1,72 @@
---
title: Logging
---
## 日志级别
Rancher 使用了以下日志级别:
| 名称 | 描述 |
|---------|-------------|
| `info` | 记录信息性消息。这是默认的日志级别。 |
| `debug` | 记录可用于调试的更详细消息。 |
| `trace` | 记录内部功能的非常详细的消息。非常冗长,并且可能包含敏感信息。 |
### 如何配置日志级别
#### Kubernetes 安装
* 配置 debug 日志级别
```
$ KUBECONFIG=./kube_config_cluster.yml
$ kubectl -n cattle-system get pods -l app=rancher --no-headers -o custom-columns=name:.metadata.name | while read rancherpod; do kubectl -n cattle-system exec $rancherpod -c rancher -- loglevel --set debug; done
OK
OK
OK
$ kubectl -n cattle-system logs -l app=rancher -c rancher
```
* 配置 info 日志级别
```
$ KUBECONFIG=./kube_config_cluster.yml
$ kubectl -n cattle-system get pods -l app=rancher --no-headers -o custom-columns=name:.metadata.name | while read rancherpod; do kubectl -n cattle-system exec $rancherpod -c rancher -- loglevel --set info; done
OK
OK
OK
```
#### Docker 安装
* 配置 debug 日志级别
```
$ docker exec -ti <container_id> loglevel --set debug
OK
$ docker logs -f <container_id>
```
* 配置 info 日志级别
```
$ docker exec -ti <container_id> loglevel --set info
OK
```
## Rancher 主机调试日志
如果需要解决在基础设施提供商中创建对象的问题,你可以使用 `rancher-machine` 调试日志。
你可以在启动 Rancher 时设置环境变量来为 `rancher-machine` 启用调试日志。
`CATTLE_WHITELIST_ENVVARS` 环境变量允许用户将特定环境变量列入白名单,让它们能在配置期间传递给 `rancher-machine`
`MACHINE_DEBUG` 变量在 `rancher-machine` 中启用调试日志。
因此,通过设置 `MACHINE_DEBUG=true` 并将 `MACHINE_DEBUG` 添加到 `CATTLE_WHITELIST_ENVVARS` 中的变量默认列表(例如 `CATTLE_WHITELIST_ENVVARS=HTTP_PROXY,HTTPS_PROXY,NO_PROXY,MACHINE_DEBUG`),你可以在配置 RKE1、RKE2 和 K3s 集群时在 `rancher-machine` 中启用调试日志。
:::caution
像上面的 `trace` 日志级别一样,`rancher-machine` 调试日志可以包含敏感信息。
:::
@@ -0,0 +1,121 @@
---
title: 网络
---
本文列出的命令/步骤可用于检查集群中的网络问题。
请确保你配置了正确的 kubeconfig(例如,为 Rancher HA 配置了 `export KUBECONFIG=$PWD/kube_config_cluster.yml`)或通过 UI 使用了嵌入式 kubectl。
### 仔细检查你的(主机)防火墙中是否打开了所有必需的端口
仔细检查你的(主机)防火墙中是否打开了所有[必需的端口](../../how-to-guides/new-user-guides/kubernetes-clusters-in-rancher-setup/node-requirements-for-rancher-managed-clusters.md#网络要求)。其他所需的端口都使用 TCP,而覆盖网络使用 UDP。
### 检查覆盖网络是否正常运行
你可以将 Pod 调度到集群中的任何主机,但是 NGINX Ingress Controller 需要能够将 `NODE_1` 请求路由到 `NODE_2`。这会在覆盖网络上进行。如果覆盖网络无法正常工作,由于 NGINX Ingress Controller 无法路由到 pod,因此 TCP/HTTP 连接会间歇性失败。
要测试覆盖网络,你可以启动以下 `DaemonSet` 定义。这样,每台主机上都会运行一个 `swiss-army-knife` 容器(镜像由 Rancher 工程师开发,可在[此处](https://github.com/rancherlabs/swiss-army-knife)找到),我们使用该镜像在所有主机上的容器之间运行 `ping` 测试。
:::note
此容器[不支持 ARM 节点](https://github.com/leodotcloud/swiss-army-knife/issues/18)(例如 Raspberry Pi)。Pod 日志会显示为 `exec user process caused: exec format error`
:::
1. 将以下内容另存为 `overlaytest.yml`
```
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: overlaytest
spec:
selector:
matchLabels:
name: overlaytest
template:
metadata:
labels:
name: overlaytest
spec:
tolerations:
- operator: Exists
containers:
- image: rancherlabs/swiss-army-knife
imagePullPolicy: Always
name: overlaytest
command: ["sh", "-c", "tail -f /dev/null"]
terminationMessagePath: /dev/termination-log
```
2. 使用 `kubectl create -f overlaytest.yml` 启动它。
3. 等待 `kubectl rollout status ds/overlaytest -w` 返回 `daemon set "overlaytest" successfully rolled out`。
4. 从同一位置运行以下脚本。它会让每个主机上的所有 `overlaytest` 容器相互 ping 通:
```
#!/bin/bash
echo "=> Start network overlay test"
kubectl get pods -l name=overlaytest -o jsonpath='{range .items[*]}{@.metadata.name}{" "}{@.spec.nodeName}{"\n"}{end}' |
while read spod shost
do kubectl get pods -l name=overlaytest -o jsonpath='{range .items[*]}{@.status.podIP}{" "}{@.spec.nodeName}{"\n"}{end}' |
while read tip thost
do kubectl --request-timeout='10s' exec $spod -c overlaytest -- /bin/sh -c "ping -c2 $tip > /dev/null 2>&1"
RC=$?
if [ $RC -ne 0 ]
then echo FAIL: $spod on $shost cannot reach pod IP $tip on $thost
else echo $shost can reach $thost
fi
done
done
echo "=> End network overlay test"
```
5. 命令运行完成后,它会输出每条路由的状态:
```
=> Start network overlay test
Error from server (NotFound): pods "wk2" not found
FAIL: overlaytest-5bglp on wk2 cannot reach pod IP 10.42.7.3 on wk2
Error from server (NotFound): pods "wk2" not found
FAIL: overlaytest-5bglp on wk2 cannot reach pod IP 10.42.0.5 on cp1
Error from server (NotFound): pods "wk2" not found
FAIL: overlaytest-5bglp on wk2 cannot reach pod IP 10.42.2.12 on wk1
command terminated with exit code 1
FAIL: overlaytest-v4qkl on cp1 cannot reach pod IP 10.42.7.3 on wk2
cp1 can reach cp1
cp1 can reach wk1
command terminated with exit code 1
FAIL: overlaytest-xpxwp on wk1 cannot reach pod IP 10.42.7.3 on wk2
wk1 can reach cp1
wk1 can reach wk1
=> End network overlay test
```
如果你在输出中看到错误,则说明两台主机上的 Pod 路由存在问题。在上面的输出中,节点 `wk2` 在覆盖网络上没有连接。原因可能是没有为 `wk2` 打开覆盖网络的[必需端口](../../how-to-guides/new-user-guides/kubernetes-clusters-in-rancher-setup/node-requirements-for-rancher-managed-clusters.md#网络要求)。
6. 你现在可以通过运行 `kubectl delete ds/overlaytest` 来清理 DaemonSet。
### 检查主机和对等/隧道设备/设备上的 MTU 是否正确配置
如果 MTU 在运行 Rancher 的主机、创建/导入集群中的节点或两者之间的设备上配置不正确,Rancher 和 Agent 会记录类似以下的错误信息:
* `websocket: bad handshake`
* `Failed to connect to proxy`
* `read tcp: i/o timeout`
有关在 Rancher 和集群节点之间使用 Google Cloud VPN 时如何正确配置 MTU 的示例,请参阅 [Google Cloud VPNMTU 注意事项](https://cloud.google.com/vpn/docs/concepts/mtu-considerations#gateway_mtu_vs_system_mtu)。
### 已解决的问题
#### 由于缺少节点注释,使用 Canal/Flannel 时覆盖网络中断
| | |
|------------|------------|
| GitHub issue | [#13644](https://github.com/rancher/rancher/issues/13644) |
| 解决于 | v2.1.2 |
要检查你的集群是否受到影响,运行以下命令来列出损坏的节点(此命令要求安装 `jq`):
```
kubectl get nodes -o json | jq '.items[].metadata | select(.annotations["flannel.alpha.coreos.com/public-ip"] == null or .annotations["flannel.alpha.coreos.com/kube-subnet-manager"] == null or .annotations["flannel.alpha.coreos.com/backend-type"] == null or .annotations["flannel.alpha.coreos.com/backend-data"] == null) | .name'
```
如果没有输出,则集群没有影响。
@@ -0,0 +1,79 @@
---
title: Rancher HA
---
本文列出的命令/步骤可用于检查你的 Rancher Kubernetes 安装。
请确保你配置了正确的 kubeconfig(例如,`export KUBECONFIG=$PWD/kube_config_cluster.yml`)。
### 检查 Rancher Pod
Rancher pod 会部署为 `cattle-system` 命名空间中的一个 Deployment。
检查 pod 是否运行在所有节点上:
```
kubectl -n cattle-system get pods -l app=rancher -o wide
```
输出示例:
```
NAME READY STATUS RESTARTS AGE IP NODE
rancher-7dbd7875f7-n6t5t 1/1 Running 0 8m x.x.x.x x.x.x.x
rancher-7dbd7875f7-qbj5k 1/1 Running 0 8m x.x.x.x x.x.x.x
rancher-7dbd7875f7-qw7wb 1/1 Running 0 8m x.x.x.x x.x.x.x
```
如果 pod 无法运行(即状态不是 **Running**Ready 状态未显示 `1/1`,或者有大量 Restarts),请检查 pod 详细信息,日志和命名空间事件。
#### Pod 详细信息
```
kubectl -n cattle-system describe pods -l app=rancher
```
#### Pod 容器日志
```
kubectl -n cattle-system logs -l app=rancher
```
#### 命名空间事件
```
kubectl -n cattle-system get events
```
### 检查 Ingress
Ingress 应该具有正确的 `HOSTS`(显示配置的 FQDN)和 `ADDRESS`(将被路由到该主机地址):
```
kubectl -n cattle-system get ingress
```
输出示例:
```
NAME HOSTS ADDRESS PORTS AGE
rancher rancher.yourdomain.com x.x.x.x,x.x.x.x,x.x.x.x 80, 443 2m
```
### 检查 Ingress Controller 日志
如果访问你配置的 Rancher FQDN 时没有显示 UI,请检查 Ingress Controller 日志以查看尝试访问 Rancher 时发生了什么:
```
kubectl -n ingress-nginx logs -l app=ingress-nginx
```
### Leader 选举
Leader 由 Leader 选举确定。确定 Leader 后,Leader`holderIdentity`)会保存在 `cattle-controllers` ConfigMap 中(在本例中为 `rancher-7dbd7875f7-qbj5k`):
```
kubectl -n kube-system get configmap cattle-controllers -o jsonpath='{.metadata.annotations.control-plane\.alpha\.kubernetes\.io/leader}'
{"holderIdentity":"rancher-7dbd7875f7-qbj5k","leaseDurationSeconds":45,"acquireTime":"2019-04-04T11:53:12Z","renewTime":"2019-04-04T12:24:08Z","leaderTransitions":0}
```
@@ -0,0 +1,67 @@
---
title: 注册集群
---
本文列出的命令/步骤可用于检查你正在注册或已在 Rancher 中注册的集群。
请确保你配置了正确的 kubeconfig(例如,`export KUBECONFIG=$PWD/kubeconfig_from_imported_cluster.yml`)。
### Rancher Agents
Rancher Agent 用于实现与集群的通信(通过 cattle-cluster-agent 的 Kubernetes API)和与节点的通信。
如果 cattle-cluster-agent 无法连接到配置的 `server-url`,集群将保持在 **Pending** 状态并显示 `Waiting for full cluster configuration`
#### cattle-node-agent
:::note
cattle-node-agents 只会在使用 RKE 在 Rancher 创建的集群中显示。
:::
检查每个节点上是否存在 cattle-node-agent pod,状态是否为 **Running**,并且重启次数不多:
```
kubectl -n cattle-system get pods -l app=cattle-agent -o wide
```
输出示例:
```
NAME READY STATUS RESTARTS AGE IP NODE
cattle-node-agent-4gc2p 1/1 Running 0 2h x.x.x.x worker-1
cattle-node-agent-8cxkk 1/1 Running 0 2h x.x.x.x etcd-1
cattle-node-agent-kzrlg 1/1 Running 0 2h x.x.x.x etcd-0
cattle-node-agent-nclz9 1/1 Running 0 2h x.x.x.x controlplane-0
cattle-node-agent-pwxp7 1/1 Running 0 2h x.x.x.x worker-0
cattle-node-agent-t5484 1/1 Running 0 2h x.x.x.x controlplane-1
cattle-node-agent-t8mtz 1/1 Running 0 2h x.x.x.x etcd-2
```
检查特定或所有 cattle-node-agent pod 的日志记录:
```
kubectl -n cattle-system logs -l app=cattle-agent
```
#### cattle-cluster-agent
检查 cattle-cluster-agent pod 是否存在于集群中,状态是否为 **Running**,并且重启次数不多:
```
kubectl -n cattle-system get pods -l app=cattle-cluster-agent -o wide
```
输出示例:
```
NAME READY STATUS RESTARTS AGE IP NODE
cattle-cluster-agent-54d7c6c54d-ht9h4 1/1 Running 0 2h x.x.x.x worker-1
```
检查 cattle-cluster-agent pod 的日志记录:
```
kubectl -n cattle-system logs -l app=cattle-cluster-agent
```
@@ -0,0 +1,22 @@
---
title: 审计日志中的用户 ID 跟踪
---
Rancher 使用以下审计日志来跟踪本地和下游集群中发生的事件:
* [Kubernetes 审计日志](https://rancher.com/docs/rke/latest/en/config-options/audit-log/)
* [Rancher API 审核日志](../../how-to-guides/advanced-user-guides/enable-api-audit-log.md)
Rancher 2.6 增强了审计日志,在 Rancher 和下游 Kubernetes 审计日志中都包含了外部身份提供程序名称(即外部身份提供程序中用户的通用名称)。
在 Rancher 2.6 之前,如果管理员不知道外部身份提供程序中的用户名和 Rancher 中的 userId (`u-xXXX`) 之间的映射,则无法通过 Rancher 审计日志和 Kubernetes 审计日志来追踪事件。
要知道这个映射,集群管理员需要能够访问 Rancher API、UI 和 local 管理集群。
有了这个功能之后,下游集群管理员就能够查看 Kubernetes 审计日志,并且可以不在 Rancher 中查看任何内容就能知道哪个外部身份提供程序 (IDP) 用户执行了某项操作。
如果集群传出了审计日志,日志系统的用户就能够识别外部身份提供程序中的用户。
Rancher 管理员现在能够查看 Rancher 审计日志,并使用外部身份提供程序用户名来跟踪 Kubernetes 审计日志。
### 功能描述
- 在下游集群启用了 Kubernetes 审计日志后,会在“元数据”级别为每个请求记录外部身份提供程序的用户名。
- 在 Rancher 启用 Rancher API 审计日志后,每个到达 Rancher API Server 的请求记录(包括登录请求)对应的外部身份提供程序用户名也会记录在 `auditLog.level=1` 中。