服务请求走向:Client-→node ip:30380->service ip:80-→pod ip:container port
Client -->192.168.2.30:30380-->10.97.113.39:80-->pod ip:80
应用场景:跨名称空间访问
需求:default 名称空间下的 client 服务想要访问 nginx-ns 名称空间下的 nginx-svc 服务
vim client.yaml
vim nginx_svc.yaml
上面两个请求的结果一样
Client Pod 要访问 Server Pod 时,它先将请求发给内核空间中的 service iptables 规则,由它再将请求转给监听在指定套接字上的 kube-proxy 的端口,kube-proxy 处理完请求,并分发请求到指定Server Pod 后,再将请求转发给内核空间中的 service ip,由 service iptables 将请求转给各个节点中的 Server Pod。
这个模式有很大的问题,客户端请求先进入内核空间的,又进去用户空间访问 kube-proxy,由kube-proxy 封装完成后再进去内核空间的 iptables,再根据 iptables 的规则分发给各节点的用户空间的 pod。由于其需要来回在用户空间和内核空间交互通信,因此效率很差。在 Kubernetes 1.1 版本之前,userspace 是默认的代理模型。
客户端 IP 请求时,直接请求本地内核 service ip,根据 iptables 的规则直接将请求转发到到各pod 上,因为使用 iptable NAT 来完成转发,也存在不可忽视的性能损耗。另外,如果集群中存上万的Service/Endpoint,那么 Node 上的 iptables rules 将会非常庞大,性能还会再打折iptables 代理模式由 Kubernetes 1.1 版本引入,自 1.2 版本开始成为默认类型。
Kubernetes 自 1.9-alpha 版本引入了 ipvs 代理模式,自 1.11 版本开始成为默认设置。客户端请求时到达内核空间时,根据 ipvs 的规则直接分发到各 pod 上。kube-proxy 会监视KubernetesService 对象和 Endpoints,调用 netlink 接口以相应地创建 ipvs 规则并定期与KubernetesService 对象和 Endpoints 对象同步 ipvs 规则,以确保 ipvs 状态与期望一致。访问服务时,流量将被重定向到其中一个后端 Pod。与 iptables 类似,ipvs 基于 netfilter 的 hook 功能,但使用哈希表作为底层数据结构并在内核空间中工作。这意味着 ipvs 可以更快地重定向流量,并且在同步代理规则时具有更好的性能。此外,ipvs 为负载均衡算法提供了更多选项,例如:
rr:轮询调度
lc:最小连接数
dh:目标哈希
sh:源哈希
sed:最短期望延迟
nq:不排队调度
如果某个服务后端 pod 发生变化,标签选择器适应的 pod 又多一个,适应的信息会立即反映到apiserver 上,而 kube-proxy 一定可以 watch 到 etc 中的信息变化,而将它立即转为 ipvs 或者iptables 中的规则,这一切都是动态和实时的,删除一个 pod 也是同样的原理。如图:
注:
以上不论哪种,kube-proxy 都通过 watch 的方式监控着 apiserver 写入 etcd 中关于 Pod 的最新状态信息,它一旦检查到一个 Pod 资源被删除了或新建了,它将立即将这些变化,反应再 iptables 或ipvs 规则中,以便 iptables 和 ipvs 在调度 Clinet Pod 请求到 Server Pod 时,不会出现 Server Pod不存在的情况。自 k8s1.11 以后,service 默认使用 ipvs 规则,若 ipvs 没有被激活,则降级使用iptables 规则. 但在 1.1 以前,service 使用的模式默认为 userspace。Service 是由 kube-proxy 组件,加上 iptables 来共同实现的。kube-proxy 通过 iptables 处理 Service 的过程,需要在宿主机上设置相当多的 iptables 规则,如果宿主机有大量的 Pod,不断刷新 iptables 规则,会消耗大量的CPU 资源。
DNS 是什么?
DNS 全称是 Domain Name System:域名系统,是整个互联网的电话簿,它能够将可被人理解的域名翻译成可被机器理解 IP 地址,使得互联网的使用者不再需要直接接触很难阅读和理解的 IP 地址。域名系统在现在的互联网中非常重要,因为服务器的 IP 地址可能会经常变动,如果没有了 DNS,那么可能 IP 地址一旦发生了更改,当前服务器的客户端就没有办法连接到目标的服务器了,如果我们为 IP 地址提供一个『别名』并在其发生变动时修改别名和 IP 地址的关系,那么我们就可以保证集群对外提供的服务能够相对稳定地被其他客户端访。DNS 其实就是一个分布式的树状命名系统,它就像一个去中心化的分布式数据库,存储着从域名到 IP 地址的映射。
CoreDNS?
CoreDNS 其实就是一个 DNS 服务,而 DNS 作为一种常见的服务发现手段,所以很多开源项目以及工程师都会使用 CoreDNS 为集群提供服务发现的功能,Kubernetes 就在集群中使用 CoreDNS 解决服务发现的问题。 作为一个加入 CNCF(Cloud Native Computing Foundation)的服务,CoreDNS 的实现非常简单。
验证 coredns
vim dig.yaml
kubernetes.default.svc.cluster.local
服务名.名称空间.默认后缀
在 k8s 中创建 service 之后,service 默认的 FQDN 是<service name>.<namespace>.svc.cluster.local,那么 k8s 集群内部的服务就可以通过 FQDN 访问
k8s DNS 解析步骤
普通Pod的dnsPolicy属性是默认值ClusterFirst,也就是会指向集群内部的DNS服务器,kube-dns负责解析集群内部的域名
kube-dns Pod的dnsPolicy值是Default,意思是从所在Node继承DNS服务器,对于无法解析的外部域名,kube-dns会继续向集群外部的dns进行查询
kube-dns只能解析集群内部地址,而集群外部地址应该发给外部DNS服务器进行解析
网站声明:如果转载,请联系本站管理员。否则一切后果自行承担。
加入交流群
请使用微信扫一扫!