对于新装置的 Kubernetes,经常出现的一个问题是 Service 没有失常工作。如果您曾经运行了 Deployment 并创立了一个 Service,然而当您尝试拜访它时没有失去响应,心愿这份文档能帮忙您找出问题所在。
先来相熟下 Service 工作逻辑:
为了实现本次演练的目标,咱们先运行几个 Pod。
$ kubectl run hostnames --image=k8s.gcr.io/serve_hostname \
--labels=app=hostnames \
--port=9376 \
--replicas=3
deployment.apps/hostnames created
确认您的 Pods 是运行状态:
$ kubectl get pods -l app=hostnames
NAME READY STATUS RESTARTS AGE
hostnames-632524106-bbpiw 1/1 Running 0 2m
hostnames-632524106-ly40y 1/1 Running 0 2m
hostnames-632524106-tlaok 1/1 Running 0 2m
问题 1:Service 存在吗?
仔细的读者会留神到咱们还没有真正创立一个 Service – 其实这是咱们无意的。这是一个有时会被忘记的步骤,也是第一件要查看的事件。
那么,如果我试图拜访一个不存在的 Service,会产生什么呢?假如您有另一个 Pod,想通过名称应用这个 Service,您将失去如下内容:
u@pod$ wget -O- hostnames
Resolving hostnames (hostnames)... failed: Name or service not known.
wget: unable to resolve host address 'hostnames'
因而,首先要查看的是 Service 是否的确存在:
$ kubectl get svc hostnames
No resources found.
Error from server (NotFound): services "hostnames" not found
咱们曾经有一个罪魁祸首了,让咱们来创立 Service。就像后面一样,这里的内容仅仅是为了步骤的执行 – 在这里您能够应用本人的 Service 细节。
$ kubectl expose deployment hostnames --port=80 --target-port=9376
service/hostnames exposed
再查问一遍,确定一下:
$ kubectl get svc hostnames
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hostnames ClusterIP 10.0.1.175 <none> 80/TCP 5s
与后面雷同,这与您应用 YAML 启动的 Service 一样:
apiVersion: v1
kind: Service
metadata:
name: hostnames
spec:
selector:
app: hostnames
ports:
- name: default
protocol: TCP
port: 80
targetPort: 9376
当初您能够确认 Service 存在。
问题 2:Service 是否通过 DNS 工作?
从雷同 Namespace 下的 Pod 中运行:
u@pod$ nslookup hostnames
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: hostnames
Address 1: 10.0.1.175 hostnames.default.svc.cluster.local
如果失败,那么您的 Pod 和 Service 可能位于不同的 Namespace 中,请尝试应用限定命名空间的名称:
u@pod$ nslookup hostnames.default
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: hostnames.default
Address 1: 10.0.1.175 hostnames.default.svc.cluster.local
如果胜利,那么须要调整您的利用,应用跨命名空间的名称去拜访服务,或者,在雷同的 Namespace 中运行利用和 Service。如果依然失败,请尝试一个齐全限定的名称:
u@pod$ nslookup hostnames.default.svc.cluster.local
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: hostnames.default.svc.cluster.local
Address 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.10
Server: 10.0.0.10
Address: 10.0.0.10#53
Name: hostnames.default.svc.cluster.local
Address: 10.0.1.175
如果您可能应用齐全限定的名称查找,但不能应用绝对名称,则须要查看 /etc/resolv.conf 文件是否正确。
u@pod$ cat /etc/resolv.conf
nameserver 10.0.0.10
search default.svc.cluster.local svc.cluster.local cluster.local example.com
options ndots:5
nameserver 行必须批示您的集群的 DNS Service,它通过 –cluster-dns 标记传递到 kubelet。
search 行必须蕴含一个适当的后缀,以便查找 Service 名称。在本例中,它在本地 Namespace(default.svc.cluster.local)、所有 Namespace 中的 Service(svc.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.default
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: kubernetes.default
Address 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:80
hostnames-0utonu@node$
curl 10.0.1.175:80
hostnames-yp2kp
u@node$ curl 10.0.1.175:80
hostnames-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=hostnames
NAME READY STATUS RESTARTS AGE
hostnames-0uton 1/1 Running 0 1h
hostnames-bvc05 1/1 Running 0 1h
hostnames-yp2kp 1/1 Running 0 1h
“AGE”列表明这些 Pod 曾经启动一个小时了,这意味着它们运行良好,而不是解体。
-l app=hostnames 参数是一个标签选择器 – 就像咱们的 Service 一样。在 Kubernetes 零碎中有一个管制循环,它评估每个 Service 的选择器,并将后果保留到 Endpoints 对象中。
$ kubectl get endpoints hostnames
NAME ENDPOINTS
hostnames 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。
问题 7:Pod 失常工作吗?
到了这步,咱们晓得您的 Service 存在并抉择了 Pods。让咱们检查一下 Pod 是否真的在工作 – 咱们能够绕过 Service 机制,间接进入 Pod。
留神:这些命令应用的是 Pod 端口(9376),而不是 Service 端口(80)。
u@pod$ wget -qO- 10.244.0.5:9376
hostnames-0uton
pod $ wget -qO- 10.244.0.6:9376
hostnames-bvc05
u@pod$ wget -qO- 10.244.0.7:9376
hostnames-yp2kp
咱们冀望的是 Endpoints 列表中的每个 Pod 返回本人的主机名。如果这没有产生(或者您本人的 Pod 的正确行为没有产生),您应该考察产生了什么。您会发现 kubectl logs 这个时候十分有用,或者应用 kubectl exec 间接进入到您的 Pod,并从那里查看服务。
另一件要查看的事件是,您的 Pod 没有解体或正在重新启动。频繁的重新启动可能会导致断断续续的连贯问题。
$ kubectl get pods -l app=hostnames
NAME READY STATUS RESTARTS AGE
hostnames-632524106-bbpiw 1/1 Running 0 2m
hostnames-632524106-ly40y 1/1 Running 0 2m
hostnames-632524106-tlaok 1/1 Running 0 2m
如果重新启动计数很高,请查阅无关如何调试 pods 获取更多信息。
问题 8:kube-proxy 失常工作吗?
如果您到了这里,那么 Service 正在运行,也有 Endpoints,而您的 Pod 实际上也正在服务。在这一点上,整个 Service 代理机制是否失常就是可疑的了。咱们来确认一下,一部分一部分来。
确认 kube-proxy 正在您的 Nodes 上运行。您应该失去如下内容:
u@node$ ps auxw | grep kube-proxy
root 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 master
I1027 22:14:54.040048 5063 proxier.go:294] Adding new service "default/kubernetes:https" at 10.0.0.1:443/TCP
I1027 22:14:54.040154 5063 proxier.go:294] Adding new service "kube-system/kube-dns:dns" at 10.0.0.10:53/UDP
I1027 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),而后重试。
问题 9: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 -ln
Prot 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:9376, 10.244.0.6:9376, 10.244.0.7:9376),你会失去相似下面的后果。
如果走到这一步还没解决!那只有烧香拜佛了!
注:全文来自官网文档翻译而成