共计 3063 个字符,预计需要花费 8 分钟才能阅读完成。
这篇文章将为大家详细讲解有关 Kubernetes 里的 Service 究竟是如何工作的,文章内容质量较高,因此丸趣 TV 小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
Service 是 Kubernetes 接入层的一种抽象资源,它为我们提供了一种固定的、统一的访问接口地址和负载均衡能力,这时可能会想到,当时使用 docker-compose 的时候,不存在 Service 概念,不也运行起来了吗?是的,在 Kubernetes 集群内部 Pod ip 也是互通的,但是 Pod 的 ip 会经常因为扩容、重建而导致客户端访问错误,pod 访问无法提供负载均衡的能力,而 Service 通过选择一组 Pod 的 label 就直接可以访问到 Pod,而且可以使用万年不变的域名,所以就选择 Service 了。
1、Service 是怎么产生的,在集群内部是如何存在的呢?
在 kubernetes 当中所谓的 Service 是 kube-proxy 生成 iptables 或 ipvs 规则,它会产生一组虚拟地址,在集群环境下有效。Service 不能直接到达 Pod 内部,中间会间隔 EndPoints,这是一组 ip 和 port 的组合。默认类型是 ClusterIP 它仅能接收集群中 pod 客户端程序的访问请求。这也是最常用的一种类型,另外还有 NodePort、LoadBalancer、ExternalName。
2、iptables 或 ipvs,到底是 iptables 还是 ipvs 呢?
一个 Service 对象就是工作节点上的一些 iptables 或 ipvs 规则,用于将到达 Service 对象 IP 地址的流量调度转发至相应的 Endpoints 对象指向的 IP 地址和端口之上。
这句话我们经常看到,如何理解呢?
Kubernetes1.1 之前是基于 userspace 实现,这种模型之下,每次请求流量要先到达内核空间,经有套接字转发到 kube-proxy,然后再由它送回到内核空间,之后调度到后端 pod 之上,可以看出请求在用户空间和内核空间来回转发,效率必然不高。但是当 pod 无响应时,能够自动重定向到其它 pod。
在 Kubernetes1.1 版本开始引入 iptables 规则,Kubernetes1.2 开始成为默认类型。即在创建 Service 资源时,集群上每个节点的 kube-proxy 都会收到通知,并且创建 iptables 规则,用于转发到此 Service ClusterIP 的流量。工作 TCP/IP 的传输层,高效稳定。
但是这种方式有如下缺点:1、iptables 代理模型挑中的 pod 无响应时,不能自动重定向到集群内部其它 pod 资源对象之上。
2、kube-proxy 通过 iptables 处理 Service 和 pod 的交互,每产生一个计算节点或者产生大量的 pod 就需要产生相应大量的 iptables 规则,不难想象,这些 iptables 规则每次需要刷新匹配保证正确性,就需要占用大量的 CPU 资源,所以基于 iptables 的 Service 实现就成了制约 Kubernetes 承载更多 pod 的瓶颈。
在 Kubernetes1.11 开始默认使用 ipvs 模型,在这种模型下 kube-proxy 会跟踪 APIServer 上 Service 和 endpoints 对象变化,调用 netlink 创建 ipvs 规则,请求调度流量功能由 ipvs 实现,运行于 netfilter 之上的钩子函数,具有流量转发速度快,规则性能同步好的特点,支持众多调度算法,剩下仍然由 iptables 完成。说到这里我们就大概明白了 iptables 和 ipvs 的作用和关系了。
3、Kubernetes 的服务发现是通过 dns 实现,那么为什么会出现四种类型的服务暴露方式呢?
说到 Service 不得不介绍 kubernetes 网络模型和通信方式
一个完整的 Kubernetes 集群应该包含三层网络,首先第一层是 mater 和 node 节点之间的网络,这个网络需要在部署 kubernetes 集群之前配置完成;第二层网络是 pod 的网络通过 kubelet 或者 cni 插件实现,用于 pod 之间或者内部的通信,集群中的所有 pod 均处在同一个网络平面空间内,可以直接通信;第三层网络是 Service 资源的网络,是一个虚拟网络,用于为 Kubernetes 集群配置 IP 地址,但此地址并不配置于任何主机或者容器的网络接口之上,而是通过 kubeproxy 配置为 iptables 规则,将发往该地址的所有流量调度至后端的 pod 之上。
通信方式分为以下四种:
同一个 pod 的内部通信;
各个 pod 彼此通信;
pod 和 service 的通信;
集群外部流向 service 的通信。
所以 Service 为了满足这些通信方式就出现了如下类型:ClusterIP:为集群内部 ip 地址暴露服务,仅在集群内可达,外部 ip 无法访问,默认 Service 类型;
NodePort:这种类型建立在 clusterIp 之上,为节点的 IP 地址暴 NodePort 服务,外部节点可以通过 NodeIP:NodePort 直接访问;
LoadBalancer:这种类型构建在 NodePort 之上,它可以关联到集群外部的某个负载均衡设备。Kubernetes 没有为私有化集群提供 LoadBalancer 的支持。如果在私有化集群使用需要自建负载均衡器;
ExternalName:其通过将 Service 映射至由 externalName 字段的内容指定的主机名来暴露服务,此主机名需要被 DNS 服务解析至 CNAME 类型的记录。这句话怎么理解呢?
举个例子,你所有的服务都在集群内部,但是你有个数据库是 mongodb,没有实现容器化,更没有部署在 Kubernetes 内部,当然你可以通过在 ConfigMap 中添加配置访问这个外部服务,但是当你的环境发生变化,比如从开发环境和生产环境的数据地址不同,这个时候你需要修改和重建 ConfigMap。这个时候可以使用 Kubernetes ExternalName 内置服务发现机制运用于集群外部运行的服务,像使用集群内的服务一样使用外部服务!通过这种方式,您可以在开发环境和生产环境中实现相同的功能,如果您最终将服务移入集群内,则不需要更改任何代码和配置。
kind: ServiceapiVersion: v1metadata: name: mongospec: type: ExternalName externalName: mango123456.com
你只需要访问:mongodb:// dbuser : dbpassword @mongo: port 就可以自动访问外部服务。
4、Service 本身有端口、Pod 也有端口、容器也有端口,之间有什么关系呢?
containerPort:一个信息性数据,为集群提供一个可以快速了解相关 pod 可以访问端口的途径,而且显式指定容器端口,无论你是否指定都不影响其他节点上的客户端 pod 对其进行访问;
port:服务提供端口,用于 kubernetes 集群内部服务访问;
targetPort:pod 目标端口,如果不设置使用默认 port 端口,port 和 nodePort 的数据通过这个端口进入到 Pod 内部,Pod 里面的 containers 的端口映射到这个端口,提供服务;
nodePort:Kubernetes 集群外部用户访问端口;
关于 Kubernetes 里的 Service 究竟是如何工作的就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。