Kubernetes 服务发布基础
一:service的定义
service 是 kubernetes 中的一种抽象,用于定义一组 pod 以及访问这一组 pod 的策略、service的作用是将一组 pod 封装为一个虚拟的服务,并提供一个统一的入口,供客户端访问。service 支持负载均衡、服务发现、服务暴露等功能。
Service 用于为一组提供服务的 Pod 抽象一个稳定的网络访问地址,是 k8s 实现微服务的核心概念通过 Service 的定义设置的访问地址是 DNS 域名格式的服务名称,对于客户端应用来说,网络访问方式并没有改变。Service 还提供了负载均衡器的功能,将客户端请求负载分发到后端提供具体服务的各个Pod 上。
Service 主要用于提供网络服务,通过 Service 的定义,能够为客户端应用提供稳定的访问地址(域名或 IP 地址)和负载均衡功能,以及屏蔽后端 EndPoint 的变化,是 Kubernetes 实现微服务的核心资源。
总之,service 是 kubernetes 中一个非常重要的概念,service 用于将外部请求代理到内部 pod上,提供4层负载均衡和服务发现的功能,使得我们可以构建高可用和可扩展的应用程序。
二:service工作原理
1:service 基本原理介绍
在 kubernetes中,pod的 IP地址是动态变化的,因此无法直接通过 pod的IP地址进行访问。service的出现正式为了解决找个问题的。service 会为一组 pod 创建一个虚拟的 IP 地址,通过这个 IP 地址可以访问这组 pod 中的任意一个 pod。当客户端请求这个虚拟 IP 地址时,请求会被负载均衡到一组 pod 中的某一个 pod 上,从而完成对 pod 的访问。
service 的实现依赖于 kube-proxy 组件。kube-proxy 会在每个节点上监听 service 的变化,一旦有 service 发生变化,kube-proxy 会更新本地的 iptables 规则,从而实现流量的转发和负载均衡。
另外,service 还与 CoreDNS 有关。CoreDNS 是 kubernetes 集群中的 DNS 解析服务。在 kubernetes中 service 的虚拟 IP 地址还会注册到 CoreDNS 中,从而使得客户端还可以通过 service 名称访问service 的虚拟 IP 地址。在 service 的定义中,可以通过 spec.selector 字段指定哪些 pod 属于这个service,这样,就可以将请求负载均衡到这些 pod 中。
总之,service 是 kubernetes 中一种非常重要的资源对象,它可以让 pod 对外提供服务,并提供负载均衡、服务发现等功能。service的实现依赖于kube-proxy和CoreDNS组件,他们共同协作,将service与 pod 连接起来,实现对 pod 的代理访问。
2:service的负载均衡机制
当一个 Service 对象在 Kubernetes 集群中被定义出来时,集群内的客户端应用就可以通过服务 IP访问到具体的 Pod 容器提供的服务了。从服务 IP 到后端 Pod 的负载均衡机制,则是由每个 node 上的kube-proxy 代理来负责实现的。
kubeproxy 的代理模式有:userspace、iptables、ipvs 和 kernelspace。
(1)userspace
起初,kube-proxy进程是一个真实的TCP/UDP代理,当某个pod以clusterIP方式访问某个service的时候,这个流量会被 pod 所在的本机的 iptables 转发到本机的 kube-proxy 进程,然后将请求转发到后端某个 pod 上。具体过程为:
- kube-proxy 为每个 service 在 node 上打开一个随机端口作为代理端口
- 建立 iptables 规则,将 clusterip 的请求重定向到代理端口(用户空间)
- 到达代理端口的请求再由 kubeproxy 转发到后端
(2)iptabels
kubernets从1.2版本开始将iptabels模式作为默认模式,这种模式下kube-proxy不再起到proxy
的作用。其核心功能:通过 API Server 的 watch 接口实时跟踪 Service 和 Endpoint 的变更信息,并更新对应的 iptables 规则,Client 的请求流量通过 iptables 的 NAT 机制“直接路由”到目标 Pod。
不同于 userspace,在 iptables 的模式中,kube-proxy不再负责转发数据包,kube-proxy 主要完成对 iptables 策略的动态管理。数据包的走向完全由 iptables 规则决定,这样的过程不存在内核态到用户态的切换,效率明显会高很多。但是随着 service 的增加,iptables 规则会不断增加,导致内核十分繁忙(等于在读一张很大的没建索引的表)。
(3)ipvs
从 kubernetes 1.8版本开始引入第三代的 IPVS 模式,它也是基于 netfilter 实现的,但定位不同:iptables 是为防火墙设计的,IPVS 则专门用于高性能负载均衡,并使用高效的数据结构 Hash 表,允许几乎无限的规模扩张。
ipvs 为负载均衡提供了更多的算法:
- rr:轮训
- lc:最小连接数
- df:目标哈希
- sh:源哈希
- sed:预计延迟最短
- nq:从不排队
3:service的4种类型
kubernetes 支持4中 service 类型。
(1)ClusterIP
这是最常用的 service 类型,它为 Pod 提供了一个虚拟的 IP 地址。当其他 Pod 需要访问该 Service时,它们只需要使用该虚拟 IP 地址即可。Kubernetes 会自动将请求路由到相应的 Pod 上
(2)NodePort
这种 Service 类型将 Pod 公开为集群中所有节点上的某个端口。当外部请求到达任何一个节点上的该端口时,Kubernetes 会将请求路由到相应的 Pod上。
(3)LoadBalancer
LoadBalancer Service:这种 Service 类型使用云提供商的负载均衡器将请求路由到后端 PodKubernetes 会自动创建和配置负载均衡器,并将其绑定到 Service 上。
(4)externalName
ExternalName Service: 这种 Service 类型允许你将 Service 映射到集群外部的某个名称。当 Pod需要访问该 Service 时,它们将使用该名称来解析出相应的 IP 地址。
三:生成用于测试service的Deployment
编写 Deployment,用于各种 service 的验证。
在应用 Service 概念之前,先创建一个提供 web 服务的 Pod 集合,有两个 Tomcat 容器副本组成,每个容器提供的服务端口都为 8080.
1:编辑 deployment
selector(选择器)主要用于资源的匹配,只有符合条件的资源才会被调用或使用,可以使用该方式对集群中的各类资源进行分配。Kubernetes 和核心资源 Deployment、statefulset 管理的 Pod 是通过选择器字段决定的,通过 Service 访问这些后端 Pod 也是通过选择器字段决定的。1abe1(标签)可以对 Kubernetes 的其他资源进行配置,当Kubernetes 对系统的任何 API 对象如Pod 进行分组时,会对其添加标签,用以精准的选择对应的 API对象。
2:创建该 Deployment
3:查看 pod 创建情况
[root@k8s-master ~]# kubectl get pod
4:查看各个 pod 的 IP 地址
[root@k8s-master ~]# kubectl get pods -l app=webapp -o wide
5:访问这两个地址
四:service 的创建
1:创建一个 clusterIp 类型 service
描述:ClusterIP 是默认的 Service 类型。它将创建一个虚拟的 ClusterIp 地址,用于在集群内部访问 Service.
使用场景:适用于集群内部的服务通信,例如将前端服务和后端服务连接起来,供内部其他服务使用。
通过 expose 命令创建clusterrp 类型的 Service
为了让客户端应用能够访问到前面创建的两个 Tomcat Pod 实例,需要创建一个 Service 来提供服务k8s 提供了一种快速地方法,即通过 kubectl expose 命令来创建 Service。
(1)执行 expose 命令暴露端口
(2)查看创建的 service
这里可以看到,系统为他分配了一个虚拟 IP 地址,Service 的端口号,从 pod 中复制而来。我们就可以通过这个虚拟 IP 地址,和端口号来访问这个 Service 了。
(3)访问测试
[root@k8s-master ~]# curl 10.104.162.209:8080
(4)删除此service
2:创建 NodePort 类型的 service
NodePort 将在每个节点上公开一个端口,并将流量转发到 Service。它会创建一个 clusterIP,并将指定的端口映射到每个节点上的相同端口。
这种 service 适用于需要从外部访问集群中的服务时,可以通过节点的 IP 地址和映射的端口进行访问。这对于开发和测试环境非常有用。
(1)创建Service 文件
设置 Service 类型为 NodePort,并设置具体的 nodePort 端口号为 30008
(2)创建此service
继续使用刚才的 webapp 的 Deployment,为此 Deployment 创建一个 NodePort 类型的 service。
(3)查看创建的Service
(4)在windows 宿主机上用浏览器测试访问
192.168.10.101:30008
(5)删除该Service
3:创建LoadBalancer类型的service
通常在公有云的环境中会使用 LoadBalancer 的类型,可以将 Service 映射到公有云提供的某个负载均衡器的 IP 地址上,客户端通过负载均衡器的 IP 和 Service 的端口号就可以访问到具体的服务。
描述:LoadBalancer 为 Service 创建一个外部负载均衡器,并分配一个外部 IP 地址。它通常由云提供商的负载均衡服务实现。
使用场景:适用于需要将流量从外部负载均衡器分发到集群内部的服务,例如在生产环境中暴露 web应用程序。
(1)编写LoadBalancer 类型的 Service 文件
(2)创建此 service
(3)查看创建结果
(4)在windows 宿主机上访问
(5)删除此service
4:创建ExternalName类型的service4
ExternalName 允许 Service 通过返回 CNAME 记录来引用集群外部的服务。它没有 clusterIP,NodePort 或LoadBalancer。
适用于需要将 K8s内部的服务与集群外的现有服务进行关联,例如连接到外部的数据库或其他资源。
ExternalName 类型是 Service 的特例,用于将集群外的服务定义为 Kubernetes 的集群 Service,并通过 ExternalName 字段指定外部服务的地址,可以使用域名或 IP 格式。集群内客户端应用通过访问这个 Service 就能访问外部服务了。他没有选择器,没有定义任何端口和 EndPoint,他通过返回该外部服务的别名来提供服务。
也可以用于两个不同的 namespace 之间的不同 pod 可以通过 name 的形式访问。
两个不同的命名空间中的 pod,可以直接使用他们的 IP 地址进行通信,但是 pod 的 IP 地址是随机分配的,重建 pod 后其 IP 地址就改变了,因此我们要用 pod 对应的 service 名称进行通信。但是跨命名空间是不能解析其他命名空间中创建的 service 名称的。这个时候就可以使用 ExternalName 实现两个不同命名空间中的各个 pod 间的通信。接下来,我们一两个命名空间内 Pod 之间的访问为例,讲解ExternalName 的使用方法。
(1)创建案例所需的两个命名空间
(2)第一个 Pod
1)创建命名空间为 test01 的 Pod
2)创建一个无头(headless)service
3)创建extername
(3)创建第二个 Pod
1)创建命名空间为 test02 的 Pod
2)创建一个无头(headless)service
3)创建extername
(4)验证 Pod 间的通信
test01
[root@k8s-master ~]# kubectl get pods -n test01
[root@k8s-master ~]# kubectl exec -it
myapp01-696c886d6b-tq7vv -n test01
--/bin/sh
/ # nslookup myapp-svcname02
/ # ping myapp-svcname02
/ # nslookup myapp-svc02.test2.svc.cluster.local
/ # ping myapp-svc02.test02.svc.cluster.local
[root@k8s-master ~]# kubectl get pods -n test02 -o wide
[root@k8s-master ~]# kubectl get pods -n test01 -o wide
test02
[root@k8s-master ~]# kubectl get svc -n test02 -o wide
[root@k8s-master ~]# kubectl get svc -n test1 -o wide
五:service的其他应用
1:service的多端口设置
一个容器应用可以提供多个端口的服务,在 Service 的定义中也可以相应的设置多个端口号。
(1)创建service文件
(2)创建service
(3)查看 EndPoint 列表
(4)查看创建的 Service
(5)删除这个service