第10课 Kubernetes之Service不能访问排查流程实践

2021-11-24 13:38:51 浏览数 (1)

摘要

在学习Kubernetes过程中,经常会遇到Service无法访问,这篇文章总结了可能导致的情况,希望能帮助你找到问题所在。

内容

为了完成本次演练,先运行部署一个应用:

代码语言:javascript复制
# kubectl create deployment web --image=nginx --replicas=3
deployment.apps/web created
# kubectl expose deployment web --port=8082 --type=NodePort
service/web exposed

确保Pod运行:

代码语言:javascript复制
#  kubectl get pods,svc
NAME                      READY   STATUS    RESTARTS   AGE
pod/dnsutils              1/1     Running   25         25h
pod/mysql-5ws56           1/1     Running   0          20h
pod/mysql-fwpgc           1/1     Running   0          25h
pod/mysql-smggm           1/1     Running   0          20h
pod/myweb-8dc2n           1/1     Running   0          25h
pod/myweb-mfbpd           1/1     Running   0          25h
pod/myweb-zn8z2           1/1     Running   0          25h
pod/web-96d5df5c8-8fwsb   1/1     Running   0          69s
pod/web-96d5df5c8-g6hgp   1/1     Running   0          69s
pod/web-96d5df5c8-t7xzv   1/1     Running   0          69s

NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
service/kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP          25h
service/mysql        ClusterIP   10.99.230.190    <none>        3306/TCP         25h
service/myweb        NodePort    10.105.77.88     <none>        8080:31330/TCP   25h
service/web          NodePort    10.103.246.193   <none>        8082:31303/TCP   17s

问题1:无法通过 Service 名称访问

如果你是访问的Service名称,需要确保CoreDNS服务已经部署:

代码语言:javascript复制
# kubectl get pods -n kube-system
NAME                                 READY   STATUS    RESTARTS   AGE
coredns-74ff55c5b-8q44c              1/1     Running   0          26h
coredns-74ff55c5b-f7j5g              1/1     Running   0          26h
etcd-k8s-master                      1/1     Running   2          26h
kube-apiserver-k8s-master            1/1     Running   2          26h
kube-controller-manager-k8s-master   1/1     Running   0          26h
kube-flannel-ds-f5tn6                1/1     Running   0          21h
kube-flannel-ds-ftfgf                1/1     Running   0          26h
kube-proxy-hnp7c                     1/1     Running   0          26h
kube-proxy-njw8l                     1/1     Running   0          21h
kube-scheduler-k8s-master            1/1     Running   0          26h

确认CoreDNS已部署,如果状态不是Running,请检查容器日志进一步查找问题。 采用dnsutils来测试域名解析。 dnsutils.yaml

代码语言:javascript复制
apiVersion: v1
kind: Pod
metadata:
  name: dnsutils
spec:
  containers:
  - name: dnsutils
    image: mydlqclub/dnsutils:1.3
    imagePullPolicy: IfNotPresent
    command: ["sleep","3600"]

运行并进入容器

代码语言:javascript复制
# kubectl create -f dnsutils.yaml

# kubectl exec -it dnsutils sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.

/ # nslookup web
Server:     10.96.0.10
Address:    10.96.0.10#53

Name:   web.default.svc.cluster.local
Address: 10.103.246.193

如果解析失败,可以尝试限定命名空间:

代码语言:javascript复制
/ # nslookup web.default
Server:     10.96.0.10
Address:    10.96.0.10#53

Name:   web.default.svc.cluster.local
Address: 10.103.246.193

如果解析成功,需要调整应用使用跨命名空间的名称访问Service。

如果仍然解析失败,尝试使用完全限定的名称:

代码语言:javascript复制
/ # nslookup web.default.svc.cluster.local
Server:     10.96.0.10
Address:    10.96.0.10#53

Name:   web.default.svc.cluster.local
Address: 10.103.246.193

说明:其中“default”表示正在操作的命名空间,“svc”表示是一个Service,“cluster.local”是集群域。

再集群中的Node尝试指定DNS IP(你的可能不同,可以通过kubectl get svc -n kube-system查看)解析下:

代码语言:javascript复制
#  nslookup web.default.svc.cluster.local
Server:     103.224.222.222
Address:    103.224.222.222#53

** server can't find web.default.svc.cluster.local: REFUSED

发现查找不到。检查 /etc/resolv.conf 文件是否正确,增加coreDNS的IP和查找路径。 增加:

代码语言:javascript复制
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

改为: vim /etc/resolv.conf

代码语言:javascript复制
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 103.224.222.222
nameserver 103.224.222.223
nameserver 8.8.8.8
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

说明:

nameserver:行必须指定CoreDNS Service,它通过在kubelet设置 --cluster-dns 参加自动配置。

search :行必须包含一个适当的后缀,以便查找 Service 名称。在本例中,它在本地 Namespace(default.svc.cluster.local)、所有 Namespace 中的 Service(svc.cluster.local)以及集群(cluster.local)中查找服务。

options :行必须设置足够高的 ndots,以便 DNS 客户端库优先搜索路径。在默认情况下,Kubernetes 将这个值设置为 5。

问题2:无法通过 Service IP访问

假设可以通过Service名称访问(CoreDNS正常工作),那么接下来要测试的 Service 是否工作正常。从集群中的一个节点,访问 Service 的 IP:

代码语言:javascript复制
# curl -I 10.103.246.193
HTTP/1.1 200 OK
Server: Tengine
Date: Sun, 22 Aug 2021 13:04:15 GMT
Content-Type: text/html
Content-Length: 1326
Last-Modified: Wed, 26 Apr 2017 08:03:47 GMT
Connection: keep-alive
Vary: Accept-Encoding
ETag: "59005463-52e"
Accept-Ranges: bytes

本集群异常,连接超时:

代码语言:javascript复制
# curl -I 10.103.246.193
curl: (7) Failed to connect to 10.103.246.193 port 8082: Connection timed out

思路1:Service 端口配置是否正确?

检查 Service 配置和使用的端口是否正确:

代码语言:javascript复制
# kubectl get svc web -o yaml
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: "2021-08-22T04:04:11Z"
  labels:
    app: web
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:labels:
          .: {}
          f:app: {}
      f:spec:
        f:externalTrafficPolicy: {}
        f:ports:
          .: {}
          k:{"port":8082,"protocol":"TCP"}:
            .: {}
            f:port: {}
            f:protocol: {}
            f:targetPort: {}
        f:selector:
          .: {}
          f:app: {}
        f:sessionAffinity: {}
        f:type: {}
    manager: kubectl-expose
    operation: Update
    time: "2021-08-22T04:04:11Z"
  name: web
  namespace: default
  resourceVersion: "118039"
  uid: fa5bbc6b-7a79-45a4-b6ba-e015340d2bab
spec:
  clusterIP: 10.103.246.193
  clusterIPs:
  - 10.103.246.193
  externalTrafficPolicy: Cluster
  ports:
  - nodePort: 31303
    port: 8082
    protocol: TCP
    targetPort: 8082
  selector:
    app: web
  sessionAffinity: None
  type: NodePort
status:
  loadBalancer: {}

说明:

  • spec.ports[]:访问ClusterIP带的端口,8082
  • targetPort :目标端口,是容器中服务提供的端口,8082
  • spec.nodePort :集群外部访问端口,http://NodeIP:31303

思路2:Service 是否正确关联到Pod?

检查 Service 关联的 Pod 是否正确:

代码语言:javascript复制
# kubectl get pods  -o wide -l app=web
NAME                  READY   STATUS    RESTARTS   AGE    IP           NODE        NOMINATED NODE   READINESS GATES
web-96d5df5c8-8fwsb   1/1     Running   0          4h9m   10.244.1.5   k8s-node2   <none>           <none>
web-96d5df5c8-g6hgp   1/1     Running   0          4h9m   10.244.1.6   k8s-node2   <none>           <none>
web-96d5df5c8-t7xzv   1/1     Running   0          4h9m   10.244.1.4   k8s-node2   <none>           <none>

-l app=hostnames 参数是一个标签选择器。

在 Kubernetes 系统中有一个控制循环,它评估每个 Service 的选择器,并将结果保存到 Endpoints 对象中。

在k8s-node2上却是可以通的。

代码语言:javascript复制
root@k8s-node2:/data/k8s# curl -I 10.244.1.4
HTTP/1.1 200 OK
Server: nginx/1.21.1
Date: Sun, 22 Aug 2021 08:16:16 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 06 Jul 2021 14:59:17 GMT
Connection: keep-alive
ETag: "60e46fc5-264"
Accept-Ranges: bytes

这3个POD都部署在k8s-node2上,不是查询的k8s-master节点。 说明本集群的2个节点不同,大概率是flannel出问题了。

在 Kubernetes 系统中有一个控制循环,它评估每个 Service 的选择器,并将结果保存到 Endpoints 对象中。

代码语言:javascript复制
root@k8s-master:/data/k8s# kubectl get endpoints web
NAME   ENDPOINTS                                         AGE
web    10.244.1.4:8082,10.244.1.5:8082,10.244.1.6:8082   4h14m

结果所示, endpoints 控制器已经为 Service 找到了 Pods。但并不说明关联的Pod就是正确的,还需要进一步确认Service 的 spec.selector 字段是否与Deployment中的 metadata.labels 字段值一致。

代码语言:javascript复制
root@k8s-master:/data/k8s# kubectl get svc web -o yaml
...
  selector:
    app: web
...

获取deployment的信息;

代码语言:javascript复制
root@k8s-master:/data/k8s# kubectl get deployment web -o yaml

...
  selector:
    matchLabels:
      app: web
...

思路3:Pod 是否正常工作?

检查Pod是否正常工作,绕过Service,直接访问Pod IP:

代码语言:javascript复制
root@k8s-master:/data/k8s# kubectl get pods -o wide
NAME                  READY   STATUS    RESTARTS   AGE     IP           NODE         NOMINATED NODE   READINESS GATES
dnsutils              1/1     Running   29         29h     10.244.0.4   k8s-master   <none>           <none>
mysql-5ws56           1/1     Running   0          24h     10.244.1.3   k8s-node2    <none>           <none>
mysql-fwpgc           1/1     Running   0          29h     10.244.0.5   k8s-master   <none>           <none>
mysql-smggm           1/1     Running   0          24h     10.244.1.2   k8s-node2    <none>           <none>
myweb-8dc2n           1/1     Running   0          29h     10.244.0.7   k8s-master   <none>           <none>
myweb-mfbpd           1/1     Running   0          29h     10.244.0.6   k8s-master   <none>           <none>
myweb-zn8z2           1/1     Running   0          29h     10.244.0.8   k8s-master   <none>           <none>
web-96d5df5c8-8fwsb   1/1     Running   0          4h21m   10.244.1.5   k8s-node2    <none>           <none>
web-96d5df5c8-g6hgp   1/1     Running   0          4h21m   10.244.1.6   k8s-node2    <none>           <none>
web-96d5df5c8-t7xzv   1/1     Running   0          4h21m   10.244.1.4   k8s-node2    <none>           <none>

部署在另一个节点的pods不可以通信。

代码语言:javascript复制
root@k8s-master:/data/k8s# curl -I 10.244.1.3:3306
curl: (7) Failed to connect to 10.244.1.4 port 3306: Connection timed out

部署在本节点的pods可以通信。

代码语言:javascript复制
root@k8s-master:/data/k8s# curl -I 10.244.0.5:3306
5.7.35=H9A_)cÿÿ


	

0 人点赞