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,然后再查看日志。

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐