K8S Service 常见问题
如果 ENDPOINTS 列的值为 ,则应检查 Service 的 spec.selector 字段, 以及你实际想选择的 Pod 的 metadata.labels 的值。对于每个 Pod 末端,在那个 KUBE-SVC- 链中应该有一些规则与之对应,还应该 有一个 KUBE-SEP- 链与之对应,其中包含为数不多的几条规则。如果你的集群不使用 kube-proxy,则以下各节将不适用,你将必须
Service 问题排查
为了演示需要部署以下服务。
apiVersion: apps/v1
kind: Deployment
metadata:
name: busybox
namespace: apps
labels:
app: busybox
spec:
replicas: 1
selector:
matchLabels:
app: busybox
template:
metadata:
labels:
app: busybox
spec:
containers:
- name: busybox
image: busybox:1.28
command: ["sh","-c","sleep 113600"]
ports:
- containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: hostnames
name: hostnames
namespace: apps
spec:
selector:
matchLabels:
app: hostnames
replicas: 3
template:
metadata:
labels:
app: hostnames
spec:
containers:
- name: hostnames
image: mirrorgooglecontainers/serve_hostname
部署成功以后查看状态如下
[root@master01 yaml]# kubectl get po -n apps
NAME READY STATUS RESTARTS AGE
busybox-6c8989b4f7-pmwkd 1/1 Running 0 5m36s
hostnames-6ff7c698bc-j2d7s 1/1 Running 0 5s
hostnames-6ff7c698bc-pzk2x 1/1 Running 0 5s
hostnames-6ff7c698bc-wlxsn 1/1 Running 0 5s
确认 Pod 是否正常
kubectl get pods -n apps -l app=hostnames -o go-template='{{range .items}}{{.status.podIP}}{{"\n"}}{{end}}'
输出结果如下:
172.29.55.26
172.21.231.191
172.31.112.138
测试部署的 hostnames 是否可以正常访问
在 busybox 容器内访问或者在主机上访问都可以,端口是9376。
for i in 172.29.55.26:9376 172.21.231.191:9376 172.31.112.138:9376;do wget -qO- $i ;done
输出结果如下:
hostnames-6ff7c698bc-j2d7s
hostnames-6ff7c698bc-pzk2x
hostnames-6ff7c698bc-wlxsn
如果输出和我这个不一样 你的 Pod 肯定那块出问题了
给 hostname 服务创建 Service
kubectl expose deployment hostnames --port=80 --target-port=9376 -n apps
测试 Service 是否可通过 DNS 名字访问
通过 busybox Pod 中访问 Service 名字:
nslookup hostnames
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local # 这个是DNS服务地址
Name: hostnames
Address 1: 10.110.220.210 hostnames.apps.svc.cluster.local # 这个是咱们测试的服务地址
如果不通的话有可能不是同一个命名空间,可以添加命名空间在测试。
apps 是我测试的命名空间,需要修改成自己的。
nslookup hostnames.apps.svc.cluster.local
注意这里的后缀:“apps.svc.cluster.local”。“apps” 是我们正在操作的命名空间。 “svc” 表示这是一个 Service。“cluster.local” 是你的集群域,在你自己的集群中可能会有所不同。
如果不能通过DNS域名访问,则需要检查你 Pod 中的 /etc/resolv.conf 文件是否正确。在 Pod 中运行以下命令:(10.96.0.10 这个是DNS 服务的域名)
/ # cat /etc/resolv.conf
search apps.svc.cluster.local svc.cluster.local cluster.local openstacklocal
nameserver 10.96.0.10
options ndots:5
如果还是失败 就需要查看 kube-proxy 服务是否异常。
测试 Service 能否通过 IP访问
假设 DNS 工作正常,那么接下来要测试 Service 能否通过它的 IP 访问。 从集群中的一个 Pod,尝试访问 Service 的 IP(从上面的 kubectl get 命令获取)。
Service IP查看方法:
[root@master01 ~]# kubectl get svc -n apps -owide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
hostnames ClusterIP 10.110.220.210 <none> 80/TCP 46h app=hostnames
尝试通过 IP地址访问
for i in $(seq 1 3); do
wget -qO- 10.110.220.210:80
done
输出应该类似这样:
hostnames-632524106-bbpiw
hostnames-632524106-ly40y
hostnames-632524106-tlaok
查看 Service 的配置是否正确
kubectl get svc -n apps hostnames -oyaml
apiVersion: v1
kind: Service
metadata:
labels:
app: hostnames
name: hostnames
namespace: apps
spec:
clusterIP: 10.110.220.210
clusterIPs:
- 10.110.220.210
internalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- port: 80
protocol: TCP
targetPort: 9376
selector:
app: hostnames
sessionAffinity: None
type: ClusterIP
- 你想要访问的 Service 端口是否在 spec.ports[] 中列出?
- targetPort 对你的 Pod 的端口是否正确
- selector 标签是否写错了
- 端口类型是数字类型(9376)的还是字符串类型(“9376”)
- 如果使用名称型端口,那么你的 Pod 是否暴露了一个同名端口?
- 端口的协议 protocol 和 Pod 的是否对应?
查看Service 是否有 Endpoints
kubectl get endpoints -n apps hostnames
NAME ENDPOINTS AGE
hostnames 172.21.231.191:9376,172.29.55.26:9376,172.31.112.138:9376 46h
这证实 Endpoints 控制器已经为你的 Service 找到了正确的 Pods。 如果 ENDPOINTS 列的值为 ,则应检查 Service 的 spec.selector 字段, 以及你实际想选择的 Pod 的 metadata.labels 的值。 常见的错误是输入错误或其他错误,例如 Service 想选择 app=hostnames,但是 Deployment 指定的是 run=hostnames。在 1.18之前的版本中 kubectl run 也可以被用来创建 Deployment。
查看 kube-proxy 工作是否正常
如果到这里,则说明 Service 正在运行,拥有 Endpoints,Pod 真正在提供服务。 此时,整个 Service 代理机制是可疑的,也就是 proxy 服务又可能有问题。
Service 的默认实现(在大多数集群上应用的)是 kube-proxy。 这是一个在每个节点上运行的程序,负责配置用于提供 Service 抽象的机制之一。 如果你的集群不使用 kube-proxy,则以下各节将不适用,你将必须检查你正在使用的 Service 的实现方式。
查看kube-proxy 状态
systemctl status kube-proxy
● kube-proxy.service - Kubernetes Kube Proxy
Loaded: loaded (/usr/lib/systemd/system/kube-proxy.service; enabled; vendor preset: disabled)
Active: active (running) since Mon 2024-04-15 16:47:57 CST; 1 weeks 1 days ago
Docs: https://github.com/kubernetes/kubernetes
Main PID: 205214 (kube-proxy)
Tasks: 13
Memory: 22.4M
CGroup: /system.slice/kube-proxy.service
└─205214 /usr/local/bin/kube-proxy --config=/etc/kubernetes/kube-proxy.yaml --v=2
Apr 15 16:47:57 master01 kube-proxy[205214]: I0415 16:47:57.081959 205214 shared_informer.go:270] Waiting for caches to sync for node config
Apr 15 16:47:57 master01 kube-proxy[205214]: I0415 16:47:57.084942 205214 proxier.go:1023] "Not syncing ipvs rules until Services and Endpoints have been received from master"
Apr 15 16:47:57 master01 kube-proxy[205214]: I0415 16:47:57.084944 205214 proxier.go:1023] "Not syncing ipvs rules until Services and Endpoints have been received from master"
Apr 15 16:47:57 master01 kube-proxy[205214]: I0415 16:47:57.180586 205214 shared_informer.go:277] Caches are synced for endpoint slice config
Apr 15 16:47:57 master01 kube-proxy[205214]: I0415 16:47:57.180645 205214 proxier.go:1023] "Not syncing ipvs rules until Services and Endpoints have been received from master"
Apr 15 16:47:57 master01 kube-proxy[205214]: I0415 16:47:57.180656 205214 proxier.go:1023] "Not syncing ipvs rules until Services and Endpoints have been received from master"
Apr 15 16:47:57 master01 kube-proxy[205214]: I0415 16:47:57.182189 205214 shared_informer.go:277] Caches are synced for node config
Apr 15 16:47:57 master01 kube-proxy[205214]: I0415 16:47:57.182212 205214 shared_informer.go:277] Caches are synced for service config
Apr 15 16:47:57 master01 kube-proxy[205214]: I0415 16:47:57.182436 205214 proxier.go:1050] "Stale service" protocol="udp" servicePortName="kube-system/kube-dns:dns...10.96.0.10"
Apr 15 16:49:57 master01 kube-proxy[205214]: I0415 16:49:57.075394 205214 graceful_termination.go:102] "Removed real server from graceful delete real server list" ...2.139:3300"
Hint: Some lines were ellipsized, use -l to show in full.
或者:
[root@master01 ~]# ps -efl|grep kube-proxy
4 S root 205214 1 0 80 0 - 318565 futex_ Apr15 ? 00:15:56 /usr/local/bin/kube-proxy --config=/etc/kubernetes/kube-proxy.yaml --v=2
0 S root 206389 144305 0 80 0 - 28180 pipe_r 15:40 pts/1 00:00:00 grep --color=auto kube-proxy
查看日志有没有明显报错
# 查看 kube-proxy 服务的日志
journalctl -u kube-proxy
# 查看最近的 kube-proxy 日志(最近的 100 行)
journalctl -u kube-proxy -n 100
# 实时查看 kube-proxy 日志
journalctl -u kube-proxy -f
查看 kube-proxy 运行模式
验证Kube-Proxy模式
curl 127.0.0.1:10249/proxyMode
根据自己的那个模式查看
Iptables 模式
我的是 ipvs 模式 这个事我在别的地方粘贴的。
在 “iptables” 模式中, 你应该可以在节点上看到如下输出:
iptables-save | grep hostnames
-A KUBE-SEP-57KPRZ3JQVENLNBR -s 10.244.3.6/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-57KPRZ3JQVENLNBR -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.3.6:9376
-A KUBE-SEP-WNBA2IHDGP2BOBGZ -s 10.244.1.7/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-WNBA2IHDGP2BOBGZ -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.1.7:9376
-A KUBE-SEP-X3P2623AGDH6CDF3 -s 10.244.2.3/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-X3P2623AGDH6CDF3 -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.2.3:9376
-A KUBE-SERVICES -d 10.0.1.175/32 -p tcp -m comment --comment "default/hostnames: cluster IP" -m tcp --dport 80 -j KUBE-SVC-NWV5X2332I4OT4T3
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-WNBA2IHDGP2BOBGZ
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-X3P2623AGDH6CDF3
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -j KUBE-SEP-57KPRZ3JQVENLNBR
对于每个 Service 的每个端口,应有 1 条 KUBE-SERVICES 规则、一个 KUBE-SVC- 链。 对于每个 Pod 末端,在那个 KUBE-SVC- 链中应该有一些规则与之对应,还应该 有一个 KUBE-SEP- 链与之对应,其中包含为数不多的几条规则。 实际的规则数量可能会根据你实际的配置(包括 NodePort 和 LoadBalancer 服务)有所不同。
IPVS 模式
在 “ipvs” 模式中, 你应该在节点下看到如下输出:
## 正常情况里面会有好多条目 我只是贴出来一部分,要不我那个太多了。
ipvsadm -ln
TCP 10.110.220.210:80 rr ## 这个是svc 地址加端口,下面三个是Pod ip地址。
-> 172.21.231.191:9376 Masq 1 0 0
-> 172.29.55.26:9376 Masq 1 0 0
-> 172.31.112.138:9376 Masq 1 0 0
对于每个 Service 的每个端口,还有 NodePort,External IP 和 LoadBalancer 类型服务 的 IP,kube-proxy 将创建一个虚拟服务器。 对于每个 Pod 末端,它将创建相应的真实服务器。 在此示例中,服务主机名(10.110.220.210:80)拥有 3 个末端(172.21.231.191:9376、 172.29.55.26:9376 和 172.31.112.138:9376)。
测试 kube-proxy 是否可以代理
curl 10.110.220.210
输出如下:
hostnames-6ff7c698bc-wlxsn
如果这步操作仍然失败,请查看 kube-proxy 日志中的特定行,如:
Setting endpoints for default/hostnames:default to [172.21.231.191:9376 172.29.55.26:9376 172.31.112.138:9376]
如果没有看到这些,请尝试将 -v 标志设置为 4 并重新启动 kube-proxy,然后再查看日志。
更多推荐
所有评论(0)