Kubernetes Service

2024-6-30|2024-8-24
麦兜
麦兜
type
Post
status
Published
date
Jun 30, 2024
slug
Kubernetes
summary
tags
network
kubernetes
category
学习思考
password
icon
Kubernetes 的 Service 是一种资源概念,它的作用是为 Pod 集群提供统一入口,将请求负责均衡的转发给容器(Pod),Pod 会因为创建和销毁更变 IP ,但是 Service(Cluster IP) 一但创建整个生命周期它的 IP都不会更变。
Service 与 Pod 关联是根据 Label Selector 来实现。Service 有不同类型,并且各个实现和功能都有差别(NodePort、Cluster IP、Headless、LoadBalancer、ExternalName)
 
在每个 Node 上都运行着 一个 Kube-proxy,用于转发(TCP等协议)的流量给相相对应的 Pod,Cluster ip(None/Headless) 和 ExternalName 使用的是 DNS 实现,而不是 Kube-proxyKube-proxy 在 Linux 默认使用的代理模式是iptables
 
使用 DNS 实现服务转发有几个不好的地方是:
  • DNS 的实现不遵守记录的 TTL 约定的历史由来已久,在记录过期后可能仍有结果缓存。
  • 有些应用只做一次 DNS 查询,然后永久缓存结果 (nginx)。
  • 即使应用程序和库进行了适当的重新解析,TTL 取值较低或为零的 DNS 记录可能会给 DNS 带来很大的压力, 从而变得难以管理。

Cluster IP

对于 Cluster IP 类型的 Service,Kubernetes 集群在内部分配一个虚拟 IP 给这个Service,其实就是在 Iptables 加了一条规则,然后每个 Pod 也在 Iptables 加了一条规则,而关联这个 Service 的 Pod 的集合会加入一条 Iptables 链 ,Service 的 Iptables 规则就是转发到 Iptables 链,Iptables 还可以根据权重实现均衡负载 Cluster IP 使用的是 NAT 所以 Socket 服务无法正常获取真实 IP。
 
以下例子基于 service-name: nginx,service-port:80 Pods Endpoint:80
CMD:iptables-save 可以看到。
//Service 规则 跳到 KUBE-SVC-ZUZW5FVTOFNMWE2A 链 -A KUBE-SERVICES -d 10.99.62.169/32 -p tcp -m comment --comment "default/nginx:xsp7pg cluster IP" -m tcp --dport 80 -j KUBE-SVC-ZUZW5FVTOFNMWE2A
//pod 链 -j KUBE-SEP-GCDM52NCNNFMCVVN -j KUBE-SEP-QFZTNLHEG5UO3NYA -A KUBE-SVC-ZUZW5FVTOFNMWE2A -m comment --comment "default/nginx:xsp7pg" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-SX3FZRKWG23D4ARR -A KUBE-SVC-ZUZW5FVTOFNMWE2A -m comment --comment "default/nginx:xsp7pg" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-JPK2UOYN5LAXTCGG -A KUBE-SVC-ZUZW5FVTOFNMWE2A -m comment --comment "default/nginx:xsp7pg" -j KUBE-SEP-WAFDPEMEUUYA22C5
//pod ip:10.244.1.14 -A KUBE-SEP-SX3FZRKWG23D4ARR -s 10.244.1.14/32 -m comment --comment "default/nginx:xsp7pg" -j KUBE-MARK-MASQ -A KUBE-SEP-SX3FZRKWG23D4ARR -p tcp -m comment --comment "default/nginx:xsp7pg" -m tcp -j DNAT --to-destination 10.244.1.14:80 //pod ip:10.244.1.16 -A KUBE-SEP-JPK2UOYN5LAXTCGG -s 10.244.1.16/32 -m comment --comment "default/nginx:xsp7pg" -j KUBE-MARK-MASQ -A KUBE-SEP-JPK2UOYN5LAXTCGG -p tcp -m comment --comment "default/nginx:xsp7pg" -m tcp -j DNAT --to-destination 10.244.1.16:80 ///pod ip:10.244.2.12 -A KUBE-SEP-WAFDPEMEUUYA22C5 -s 10.244.2.12/32 -m comment --comment "default/nginx:xsp7pg" -j KUBE-MARK-MASQ -A KUBE-SEP-WAFDPEMEUUYA22C5 -p tcp -m comment --comment "default/nginx:xsp7pg" -m tcp -j DNAT --to-destination 10.244.2.12:80
[root@localhost ~]# kubectl get pods -o wide -l k8s.kuboard.cn/name=nginx NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-59ff7ffd6b-7vgh2 1/1 Running 0 39m 10.244.2.12 node2 <none> <none> nginx-59ff7ffd6b-g6pgc 1/1 Running 0 9s 10.244.1.16 node1 <none> <none> nginx-59ff7ffd6b-hcqhb 1/1 Running 0 39m 10.244.1.14 node1 <none> <none>

NodePort

NodePort 是基于 Cluster IP 模式的,创建 NodePort 的时候每个节点都会分配统一的端口监听用于转发到 Cluster IP,NodePort 模式 在 Iptables 也分配了 Cluster IP。

Headless (Cluster None)

Headless 不像 Cluster IP 一样有 IP 地址,是基于 DNS 记录实现,Kubernetes 有个内部服务 CoreDNS 用于查询 DNS记录, 在 Pod 集群内部有一个标识符用于访问和发现 pod。格式为 <pod-name>.<namespace>.svc.cluster.local 当使用 dig <pod-name>.<namespace>.svc.cluster.local 可以获取到 pod 的所有 ip,比如 nginx 的,因为是拿到所有 ip 所以需要客户端自己实现均衡负载
//dig echo ; <<>> DiG 9.18.24-1-Debian <<>> nginx.default.svc.cluster.local ;; global options: +cmd ;; Got answer: ;; WARNING: .local is reserved for Multicast DNS ;; You are currently testing what happens when an mDNS query is leaked to DNS ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10029 ;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1232 ; COOKIE: a02b22621e8b3b4d (echoed) ;; QUESTION SECTION: ;nginx.default.svc.cluster.local. IN A //这里就是返回这条 DNS 记录所关联的 pod ip ;; ANSWER SECTION: nginx.default.svc.cluster.local. 30 IN A 10.244.1.15 nginx.default.svc.cluster.local. 30 IN A 10.244.2.12 nginx.default.svc.cluster.local. 30 IN A 10.244.1.14 ;; Query time: 0 msec ;; SERVER: 10.96.0.10#53(10.96.0.10) (UDP) ;; WHEN: Sun Jul 14 08:38:53 UTC 2024 ;; MSG SIZE rcvd: 213
[root@localhost ~]# kubectl get pods -o wide -l k8s.kuboard.cn/name=nginx NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-59ff7ffd6b-7vgh2 1/1 Running 0 35m 10.244.2.12 node2 <none> <none> nginx-59ff7ffd6b-hcqhb 1/1 Running 0 35m 10.244.1.14 node1 <none> <none> nginx-59ff7ffd6b-r2f96 1/1 Running 0 35m 10.244.1.15 node1 <none> <none>
 
 
 
 
学习的方法Redis 使用 epoll 封装 Reactor 模型