ClusterIP、NodePort、LoadBalancer 和 ExternalName

Service 定义

在 Kubernetes 中,由于Pod 是有生命周期的,如果 Pod 重启它的 IP 可能会发生变化以及升级的时候会重建 Pod,我们需要 Service 服务去动态的关联这些 Pod 的 IP 和端口,从而使我们前端用户访问不受后端变更的干扰。

Service 原理

Kubernetes 在创建 Service 时,会根据标签选择器 Label Selector 来寻找 Pod,找到 Pod 后,会建立 Endpoint 映射表,存放 Pod 的端口和 IP 。当 Pod 发生变化时,Endpoint 也会更新它的映射关系,这样 Service 接收前端 Client 请求的时候,就会通过 Endpoint,找到最终需要转发到哪个 Pod 进行访问。Endpoint 和 Service 是同名的,这里的具体实现是靠kube-proxy完成的。

同时,由于 Kubernetes 内部有一个 DNS Server,我们可以在 Pod 容器内以【服务名.命名空间.域名后缀】的方式访问服务名称,这样也不需要固定的 Service IP 了,默认域名后缀是 svc.cluster.local

Kubernetes 的 Service 共有四种类型:ClusterIP、NodePort、LoadBalancer 和 ExternalName。

ClusterIP: 此为默认的 Service 类型,自动分配一个仅 Cluster 内部可以访问的虚拟 IP。

NodePort: 这种类型建立在 ClusterIP 类型之上,其在每个节点的 IP 地址的某静态端口(NodePort)暴露服务,因此,它依然会为 Service 分配集群 IP 地址,并将此作为 NodePort 的路由目标。这种类型的 Servcie 既可如 ClusterIP 一样受到集群内部客户端 Pod 的访问,也会受到集群外部客户端通过套接字 <NodeIP>:<NodePort> 进行的请求。

NodePort 即节点 Port,通常在安装部署 Kubernetes 集群系统时会预留一个 端口范围用于 NodePort,默认为 30000~32767 之间的端口。

LoadBalancer:这种类型建立在 NodePort 类型之上,其通过 cloud provider 提供的负载均衡器将服务暴露到集群外部,因此 LoadBalancer 一样具有 NodePort 和 ClusterIP。简单的说,就是一个 LoadBalancer 类型的 Service 会指向关联至 Kubernetes 集群外部的、切实存在的某个负载均衡设备,该设备通过工作节点之上的 NodePort 向集群内部发送请求流量。

EXternalName:其通过将 Service 映射至由 externalName 字段的内容指定的主机名来暴露服务,此主机名需要被 DNS 服务解析至 CNAME 类型的记录。此种类型并非定义由 Kubernetes 集群提供的服务,而是把集群外部的某服务以 DNS CNAME 记录的方式映射到集群内,从而让集群内的 Pod 资源能够访问外部的 Service 的一种实现方式。因此,这种类型的 Service 没有 CluserIP 和 NodePort,也没有标签选择器用于选择 Pod 资源,因此也不会有 Endpoints 存在。

port

  • port是k8s集群内部访问service的端口(service暴露在Cluster IP上的端口),即通过clusterIP: port可以访问到某个service
nodePort
  • nodePort是外部访问k8s集群中service的端口,通过nodeIP: nodePort可以从外部访问到某个service。

比如外部用户要访问k8s集群中的一个Web应用,那么我们可以配置对应service的type=NodePort,nodePort=30001。其他用户就可以通过浏览器http://node:30001访问到该web服务。而数据库等服务可能不需要被外界访问,只需被内部服务访问即可,那么我们就不必设置service的NodePort

TargetPort
  • targetPort 是pod的端口,从port和nodePort来的流量经过kube-proxy流入到后端pod的targetPort上,最后进入容器。
containerPort
  • containerPort是pod内部容器的端口,targetPort映射到containerPort。
hostPort

这是一种直接定义Pod网络的方式。hostPort是直接将容器的端口与所调度的节点上的端口路由,这样用户就可以通过宿主机的IP加上来访问Pod了,如

这样做有个缺点,因为Pod重新调度的时候该Pod被调度到的宿主机可能会变动,这样就变化了,用户必须自己维护一个Pod与所在宿主机的对应关系。 使用了 hostPort 的容器只能调度到端口不冲突的 Node 上,除非有必要(比如运行一些系统级的 daemon 服务),不建议使用端口映射功能。如果需要对外暴露服务,建议使用 NodePort Service。

总的来说,port和nodePort都是service的端口,前者暴露给集群内客户访问服务,后者暴露给集群外客户访问服务。从这两个端口到来的数据都需要经过反向代理kube-proxy流入后端 pod的targetPod,从而到达pod上的容器内。

Endpoint

创建Service的同时,会自动创建跟Service同名的Endpoints。

Endpoint 是k8s集群中一个资源对象,存储在etcd里面,用来记录一个service对应的所有pod的访问地址。service通过selector和pod建立关联。

Endpoint = Pod IP + Container Port

service配置selector endpoint controller 才会自动创建对应的endpoint 对象,否则是不会生产endpoint 对象

一个service由一组后端的pod组成,这些后端的pod通过service endpoint暴露出来,如果有一个新的pod创建创建出来,且pod的标签名称(label:pod)跟service里面的标签(label selector 的label)一致会自动加入到service的endpoints 里面,如果pod对象终止后,pod 会自动从edponts 中移除。在集群中任意节点 可以使用curl请求service <CLUSTER-IP>:<PORT>

相关推荐
Nazi69 小时前
sealos部署k8s
运维·kubernetes·k8s
伟大的大威2 天前
K8s基于节点软亲和的高 CPU Pod 扩容与优先调度方案
k8s·cpu
听说唐僧不吃肉4 天前
DevOps篇之通过GitLab CI 流水线实现k8s集群中helm应用发布
k8s·devops
java资料站7 天前
k8s集群1.20.9
k8s·kubelet
退役小学生呀11 天前
十九、云原生分布式存储 CubeFS
分布式·docker·云原生·容器·kubernetes·k8s
久绊A11 天前
Minikube win安装步骤
k8s
照物华14 天前
深入理解Kubernetes核心:标签与标签选择器实战解析
云原生·容器·kubernetes·k8s
裸奔的大金毛14 天前
K8S - NetworkPolicy的使用
容器·kubernetes·k8s
ezreal_pan16 天前
Kubernetes 负载均衡现象解析:为何同一批次请求集中于单个 Pod
运维·云原生·k8s·traefik
tb_first17 天前
k8sday11服务发现(2/2)
docker·云原生·容器·kubernetes·k8s