k8s - Service不能访问问题排查流程_ihdgp-程序员宅基地

技术标签: kubernetes  

对于新安装的 Kubernetes,经常出现的一个问题是 Service 没有正常工作。如果您已经运行了 Deployment 并创建了一个 Service,但是当您尝试访问它时没有得到响应,希望这份文档能帮助您找出问题所在。

 

先来熟悉下Service工作逻辑:

为了完成本次演练的目的,我们先运行几个 Pod

$ kubectl run hostnames --image=k8s.gcr.io/serve_hostname \                        --labels=app=hostnames \                        --port=9376 \                        --replicas=3deployment.apps/hostnames created

确认您的 Pods 是运行状态:

$ kubectl get pods -l app=hostnamesNAME                        READY     STATUS    RESTARTS   AGEhostnames-632524106-bbpiw   1/1       Running   0          2mhostnames-632524106-ly40y   1/1       Running   0          2mhostnames-632524106-tlaok   1/1       Running   0          2m

问题1:Service 存在吗?

细心的读者会注意到我们还没有真正创建一个 Service - 其实这是我们有意的。这是一个有时会被遗忘的步骤,也是第一件要检查的事情。

那么,如果我试图访问一个不存在的 Service,会发生什么呢?假设您有另一个 Pod,想通过名称使用这个 Service,您将得到如下内容:

u@pod$ wget -O- hostnamesResolving hostnames (hostnames)... failed: Name or service not known.wget: unable to resolve host address 'hostnames'

因此,首先要检查的是 Service 是否确实存在:

$ kubectl get svc hostnamesNo resources found.Error from server (NotFound): services "hostnames" not found

我们已经有一个罪魁祸首了,让我们来创建 Service。就像前面一样,这里的内容仅仅是为了步骤的执行 - 在这里您可以使用自己的 Service 细节。​​​​​​​

$ kubectl expose deployment hostnames --port=80 --target-port=9376service/hostnames exposed

再查询一遍,确定一下:​​​​​​​

$ kubectl get svc hostnamesNAME        TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGEhostnames   ClusterIP   10.0.1.175   <none>        80/TCP    5s

与前面相同,这与您使用 YAML 启动的 Service 一样:​​​​​​​

apiVersion: v1kind: Servicemetadata:  name: hostnamesspec:  selector:    app: hostnames  ports:  - name: default    protocol: TCP    port: 80    targetPort: 9376

现在您可以确认 Service 存在。

问题2:Service 是否通过 DNS 工作?

从相同 Namespace 下的 Pod 中运行:​​​​​​​

u@pod$ nslookup hostnamesAddress 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name:      hostnamesAddress 1: 10.0.1.175 hostnames.default.svc.cluster.local

如果失败,那么您的 Pod 和 Service 可能位于不同的 Namespace 中,请尝试使用限定命名空间的名称:​​​​​​​

u@pod$ nslookup hostnames.defaultAddress 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name:      hostnames.defaultAddress 1: 10.0.1.175 hostnames.default.svc.cluster.local

如果成功,那么需要调整您的应用,使用跨命名空间的名称去访问服务,或者,在相同的 Namespace 中运行应用和 Service。如果仍然失败,请尝试一个完全限定的名称:​​​​​​​

u@pod$ nslookup hostnames.default.svc.cluster.localAddress 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name:      hostnames.default.svc.cluster.localAddress 1: 10.0.1.175 hostnames.default.svc.cluster.local

注意这里的后缀:”default.svc.cluster.local”。”default” 是我们正在操作的 Namespace。”svc” 表示这是一个 Service。”cluster.local” 是您的集群域,在您自己的集群中可能会有所不同。

您也可以在集群中的 Node 上尝试此操作:

注意: 10.0.0.10 是我的 DNS Service,您的可能不同)​​​​​​​

u@node$ nslookup hostnames.default.svc.cluster.local 10.0.0.10Server:         10.0.0.10Address:        10.0.0.10#53
Name:   hostnames.default.svc.cluster.localAddress: 10.0.1.175

如果您能够使用完全限定的名称查找,但不能使用相对名称,则需要检查 /etc/resolv.conf 文件是否正确。​​​​​​​

u@pod$ cat /etc/resolv.confnameserver 10.0.0.10search default.svc.cluster.local svc.cluster.local cluster.local example.comoptions ndots:5

nameserver 行必须指示您的集群的 DNS Service,它通过 --cluster-dns 标志传递到 kubelet

search 行必须包含一个适当的后缀,以便查找 Service 名称。在本例中,它在本地 Namespacedefault.svc.cluster.local)、所有 Namespace 中的 Servicesvc.cluster.local)以及集群(cluster.local)中查找服务。根据您自己的安装情况,可能会有额外的记录(最多 6 条)。集群后缀通过 --cluster-domain 标志传递给 kubelet。本文档中,我们假定它是 “cluster.local”,但是您的可能不同,这种情况下,您应该在上面的所有命令中更改它。

options 行必须设置足够高的 ndots,以便 DNS 客户端库考虑搜索路径。在默认情况下,Kubernetes 将这个值设置为 5,这个值足够高,足以覆盖它生成的所有 DNS 名称。

问题3:DNS 是否可以解析默认服务?

如果上面仍然失败 - DNS 查找不到您需要的 Service - 我们可以后退一步,看看还有什么不起作用。Kubernetes 主 Service 应该一直是工作的:​​​​​​​

u@pod$ nslookup kubernetes.defaultServer:    10.0.0.10Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name:      kubernetes.defaultAddress 1: 10.0.0.1 kubernetes.default.svc.cluster.local

如果失败,您可能需要转到这个文档的 kube-proxy 部分,或者甚至回到文档的顶部重新开始,但不是调试您自己的 Service,而是调试 DNS。

问题4:Service 能够通过 IP 访问么?

假设我们可以确认 DNS 工作正常,那么接下来要测试的是您的 Service 是否工作正常。从集群中的一个节点,访问 Service 的 IP(从上面的 kubectl get 命令获取)。​​​​​​​

u@node$ curl 10.0.1.175:80hostnames-0uton
u@node$ curl 10.0.1.175:80hostnames-yp2kp
u@node$ curl 10.0.1.175:80hostnames-bvc05

如果 Service 是正常的,您应该得到正确的响应。如果没有,有很多可能出错的地方,请继续。

问题5:Service 是对的吗?

这听起来可能很愚蠢,但您应该加倍甚至三倍检查 Service 是否正确,并且与您的 Pod 匹配。查看 Service 并验证它:

​​​​​​​

$ kubectl get service hostnames -o json{
       "kind": "Service",    "apiVersion": "v1",    "metadata": {
           "name": "hostnames",        "namespace": "default",        "selfLink": "/api/v1/namespaces/default/services/hostnames",        "uid": "428c8b6c-24bc-11e5-936d-42010af0a9bc",        "resourceVersion": "347189",        "creationTimestamp": "2015-07-07T15:24:29Z",        "labels": {
               "app": "hostnames"        }    },    "spec": {
           "ports": [            {
                   "name": "default",                "protocol": "TCP",                "port": 80,                "targetPort": 9376,                "nodePort": 0            }        ],        "selector": {
               "app": "hostnames"        },        "clusterIP": "10.0.1.175",        "type": "ClusterIP",        "sessionAffinity": "None"    },    "status": {
           "loadBalancer": {}    }}

spec.ports[] 中描述的是您想要尝试访问的端口吗?targetPort 对您的 Pod 来说正确吗(许多 Pod 选择使用与 Service 不同的端口)?如果您想把它变成一个数字端口,那么它是一个数字(9376)还是字符串 “9376”?如果您想把它当作一个指定的端口,那么您的 Pod 是否公开了一个同名端口?端口的 protocol 和 Pod 的一样吗?

问题6:Service 有端点吗?

如果您已经走到了这一步,我们假设您已经确认 Service 存在,并能通过 DNS 解析。现在,让我们检查一下,您运行的 Pod 确实是由 Service 选择的。

早些时候,我们已经看到 Pod 是运行状态。我们可以再检查一下:​​​​​​​

$ kubectl get pods -l app=hostnamesNAME              READY     STATUS    RESTARTS   AGEhostnames-0uton   1/1       Running   0          1hhostnames-bvc05   1/1       Running   0          1hhostnames-yp2kp   1/1       Running   0          1h

“AGE” 列表明这些 Pod 已经启动一个小时了,这意味着它们运行良好,而不是崩溃。

-l app=hostnames 参数是一个标签选择器 - 就像我们的 Service 一样。在 Kubernetes 系统中有一个控制循环,它评估每个 Service 的选择器,并将结果保存到 Endpoints 对象中。​​​​​​​

$ kubectl get endpoints hostnamesNAME        ENDPOINTShostnames   10.244.0.5:9376,10.244.0.6:9376,10.244.0.7:9376

这证实 endpoints 控制器已经为您的 Service 找到了正确的 Pods。如果 hostnames 行为空,则应检查 Service 的 spec.selector 字段,以及您实际想选择的 Pods 的 metadata.labels 的值。常见的错误是输入错误或其他错误,例如 Service 想选择 run=hostnames,但是 Deployment 指定的是 app=hostnames

问题8:Pod 正常工作吗?

到了这步,我们知道您的 Service 存在并选择了 Pods。让我们检查一下 Pod 是否真的在工作 - 我们可以绕过 Service 机制,直接进入 Pod

注意: 这些命令使用的是 Pod 端口(9376),而不是 Service 端口(80)。​​​​​​​

u@pod$ wget -qO- 10.244.0.5:9376hostnames-0uton
pod $ wget -qO- 10.244.0.6:9376hostnames-bvc05
u@pod$ wget -qO- 10.244.0.7:9376hostnames-yp2kp

我们期望的是 Endpoints 列表中的每个 Pod 返回自己的主机名。如果这没有发生(或者您自己的 Pod 的正确行为没有发生),您应该调查发生了什么。您会发现 kubectl logs 这个时候非常有用,或者使用 kubectl exec 直接进入到您的 Pod,并从那里检查服务。

另一件要检查的事情是,您的 Pod 没有崩溃或正在重新启动。频繁的重新启动可能会导致断断续续的连接问题。​​​​​​​

$ kubectl get pods -l app=hostnamesNAME                        READY     STATUS    RESTARTS   AGEhostnames-632524106-bbpiw   1/1       Running   0          2mhostnames-632524106-ly40y   1/1       Running   0          2mhostnames-632524106-tlaok   1/1       Running   0          2m

如果重新启动计数很高,请查阅有关如何调试 pods 获取更多信息。

问题9:kube-proxy 正常工作吗?

如果您到了这里,那么 Service 正在运行,也有 Endpoints,而您的 Pod 实际上也正在服务。在这一点上,整个 Service 代理机制是否正常就是可疑的了。我们来确认一下,一部分一部分来。

确认 kube-proxy 正在您的 Nodes 上运行。您应该得到如下内容:​​​​​​​

u@node$ ps auxw | grep kube-proxyroot  4194  0.4  0.1 101864 17696 ?    Sl Jul04  25:43 /usr/local/bin/kube-proxy --master=https://kubernetes-master --kubeconfig=/var/lib/kube-proxy/kubeconfig --v=2

下一步,确认它并没有出现明显的失败,比如连接主节点失败。要做到这一点,您必须查看日志。访问日志取决于您的 Node 操作系统。在某些操作系统是一个文件,如 /var/log/messages kube-proxy.log,而其他操作系统使用 journalctl 访问日志。您应该看到类似的东西:​​​​​​​

I1027 22:14:53.995134    5063 server.go:200] Running in resource-only container "/kube-proxy"I1027 22:14:53.998163    5063 server.go:247] Using iptables Proxier.I1027 22:14:53.999055    5063 server.go:255] Tearing down userspace rules. Errors here are acceptable.I1027 22:14:54.038140    5063 proxier.go:352] Setting endpoints for "kube-system/kube-dns:dns-tcp" to [10.244.1.3:53]I1027 22:14:54.038164    5063 proxier.go:352] Setting endpoints for "kube-system/kube-dns:dns" to [10.244.1.3:53]I1027 22:14:54.038209    5063 proxier.go:352] Setting endpoints for "default/kubernetes:https" to [10.240.0.2:443]I1027 22:14:54.038238    5063 proxier.go:429] Not syncing iptables until Services and Endpoints have been received from masterI1027 22:14:54.040048    5063 proxier.go:294] Adding new service "default/kubernetes:https" at 10.0.0.1:443/TCPI1027 22:14:54.040154    5063 proxier.go:294] Adding new service "kube-system/kube-dns:dns" at 10.0.0.10:53/UDPI1027 22:14:54.040223    5063 proxier.go:294] Adding new service "kube-system/kube-dns:dns-tcp" at 10.0.0.10:53/TCP

如果您看到有关无法连接主节点的错误消息,则应再次检查节点配置和安装步骤。

kube-proxy 无法正确运行的可能原因之一是找不到所需的 conntrack 二进制文件。在一些 Linux 系统上,这也是可能发生的,这取决于您如何安装集群,例如,您正在从头开始安装 Kubernetes。如果是这样的话,您需要手动安装 conntrack 包(例如,在 Ubuntu 上使用 sudo apt install conntrack),然后重试。

问题10:kube-proxy 是否在写 iptables 规则?

kube-proxy 的主要职责之一是写实现 Services 的 iptables 规则。让我们检查一下这些规则是否已经被写好了。

kube-proxy 可以在 “userspace” 模式、 “iptables” 模式或者 “ipvs” 模式下运行。如果您正在使用 “iptables” 模式或者 “ipvs” 模式。您应该看到以下情况之一。

Iptables​​​​​​

u@node$ 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

KUBE-SERVICES 中应该有 1 条规则,KUBE-SVC-(hash) 中每个端点有 1 或 2 条规则(取决于 SessionAffinity),每个端点中应有 1 条 KUBE-SEP-(hash) 链。准确的规则将根据您的确切配置(包括节点、端口组合以及负载均衡器设置)而有所不同。

IPVS​​​​​​​

u@node$ ipvsadm -lnProt LocalAddress:Port Scheduler Flags  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn...TCP  10.0.1.175:80 rr  -> 10.244.0.5:9376               Masq    1      0          0  -> 10.244.0.6:9376               Masq    1      0          0  -> 10.244.0.7:9376               Masq    1      0          0...

IPVS 代理将为每个服务器地址(例如集群 IP、外部 IP、节点端口 IP、负载均衡 IP等)创建虚拟服务器,并为服务的端点创建一些相应的真实服务器(如果有)。在这个例子中,服务器主机(10.0.1.175:80)有 3 个端点(10.244.0.5:937610.244.0.6:937610.244.0.7:9376),你会得到类似上面的结果。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_45423952/article/details/108006445

智能推荐

oracle 12c 集群安装后的检查_12c查看crs状态-程序员宅基地

文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态

解决jupyter notebook无法找到虚拟环境的问题_jupyter没有pytorch环境-程序员宅基地

文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境

国内安装scoop的保姆教程_scoop-cn-程序员宅基地

文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn

Element ui colorpicker在Vue中的使用_vue el-color-picker-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker

迅为iTOP-4412精英版之烧写内核移植后的镜像_exynos 4412 刷机-程序员宅基地

文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机

Linux系统配置jdk_linux配置jdk-程序员宅基地

文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk

随便推点

matlab(4):特殊符号的输入_matlab微米怎么输入-程序员宅基地

文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入

C语言程序设计-文件(打开与关闭、顺序、二进制读写)-程序员宅基地

文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。‍ Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。

Touchdesigner自学笔记之三_touchdesigner怎么让一个模型跟着鼠标移动-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动

【附源码】基于java的校园停车场管理系统的设计与实现61m0e9计算机毕设SSM_基于java技术的停车场管理系统实现与设计-程序员宅基地

文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计

Android系统播放器MediaPlayer源码分析_android多媒体播放源码分析 时序图-程序员宅基地

文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;amp;gt;Jni-&amp;amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图

java 数据结构与算法 ——快速排序法-程序员宅基地

文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法