Kubernetes Headless服务
1、概述
Headless Services是一种特殊的service,其spec:clusterIP表示为None,这样在实际运行时就不会被分配ClusterIP,也被称为无头服务,通过DNS解析提供服务发现。与普通服务不同的是Headless Services不提供负载均衡功能,每个Pod都有唯一的DNS记录,直接映射到其IP地址,适用于有状态应用的场景,如与StatefulSet一起部署数据库。这种服务使得直接访问单个Pod成为可能,而不经过负载均衡器。
因为 Headless Service 属于 Service ClusterIp 类型,所以在讲解Headless Service前,先简单说下 Service 和服务发现。
2、Service与服务发现
2.1 Service概述
Service主要用于实现对一组Pod的访问,Service 通过标签选择器来关联 Pod 资源,Service 根据访问的端口将对应的请求转发至后端Pod的端口上。Service对象的IP地址(ClusterIP)是虚拟IP地址,仅在 Kubernetes集群内可访问,外部无法访问,可以通过配置 NodePort 或 LoadBalancer 类型的 Service 将集群内的服务暴露给 Kuberenetes 集群外的客户端访问。
备注:Kubernetes部署的服务实例(Pod)不仅可以通过 Service nodePort 和 loadbalancer 的方式暴露给集群外客户端,一般还有以下几种方式暴露给外部访问:
- 通过hostPort方式在单一节点上做端口映射;
- 通过Pod的hostNetwork配置让Pod资源使用工作节点上的网络;
- 使用Ingress 资源。
2.2 Service服务访问原理
本质上来讲,一个Service 对象对应于工作节点内核之中的一组路由规则,这些规则能够将到达Service对象的ClusterIP的流量转发至相应Pod对象的IP地址和端口。
每个工作节点的kube-proxy组件通过API Server持续监听各个Service及其关联的Pod对象,并将Service对象的创建或变动,实时写入到当前工作节点的路由规则上。客户端、Service及Pod对象的关系如下图所示:
2.3 Service类型
Service 一般分为3种类型:ClusterIP、NodePort、LoadBalancer。
(1)ClusterIP
通过集群内部IP 地址暴露服务,CusterIP地址仅在集群内部可以访问,无法被集群外部的客户端访问。
(2)NodePort
NodePort类型,将Service的端口号映射到每个Node的一个端口号上,然后分发给后端的Pod处理。这种类型的Service 既可以被集群内部客户端通过 CIusterIP 直接访问,也可以在集群外部客户端通过nodeIP:nodePort进行访问。
(3)LoadBalancer
LoadBalancer类型建立在 NodePort基础上,将Service映射到一个负载均衡器的IP 地址上,通常在公有云环境中使用。
客户端通过负载均衡器的IP和Service的端号就可以访问到具体的服务,无须再通过 kube-proxy提供的负载均衡机制进行流量转发,可以直接将流量转发到后端 Pod上。
如果是本地搭建LoadBalancer,一般采用metallb方案,官网地址:https://metallb.universe.tf/,有兴趣的朋友自行搭建。
3、Headless Service
简单讲完 Service 和服务发现后,现在回归本文主题,接下来详细讲解下 Headless Service。
3.1 观察Headless Service
由于现有 Kubernetes 集群里面有现成的 headless 服务,所以本文不再创建新的 headless 服务,下面观察下集群已创建的一个名为 openldap 的 headless 服务,以下是 openldap 服务规格定义文件。
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/instance: cb-openldap
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: openldap-ha
name: openldap
spec:
clusterIP: None #这使得服务成为headless
ports:
- name: ldap
port: 389
protocol: TCP
targetPort: 389
selector:
app.kubernetes.io/instance: cb-openldap
app.kubernetes.io/name: openldap-ha
sessionAffinity: None
type: ClusterIP
通过 kubectl get 和 kubectl describe 来查看服务,可以发现他没有集群 IP。
[root@cloud ~]# kubectl get svc openldap
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
openldap ClusterIP None <none> 389/TCP 185d
并且它的后端包含与pod选择器匹配的(部分)pod。“部分”是因为pod包含就绪探针,所以只有准备就绪的pod会被列出作为服务转发的上游服务,通过 kubectl describe 命令可以看出openldap 服务有两个就绪Pod(10.233.0.214:389,10.233.9.73:389)。
[root@cloud ~]# kubectl describe svc openldap
Name: openldap
Namespace: default
Labels: app.kubernetes.io/instance=cb-openldap
app.kubernetes.io/managed-by=Helm
app.kubernetes.io/name=openldap-ha
Annotations: meta.helm.sh/release-name: cb-openldap
meta.helm.sh/release-namespace: default
Selector: app.kubernetes.io/instance=cb-openldap,app.kubernetes.io/name=openldap-ha
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: None
IPs: None
Port: ldap 389/TCP
TargetPort: 389/TCP
Endpoints: 10.233.0.214:389,10.233.9.73:389
Session Affinity: None
Events: <none>
3.2 通过DNS发现Pod
Kubernetes允许客户通过DNS查找发现 Pod IP。对于普通 Kubernetes Service,当执行服务的DNS查找时,DNS服务器会返回单个IP——ClusterIP;但是对于 Headless Service,进行DNS 查找时,DNS服务器将返回的则是 Pod IP 而不是单个服务IP。
DNS服务器不会返回单个DNS A记录,而是会为该服务返回多个A记录,每个记录指向当时支持该服务的单个pod的IP。客户端因此可以做一个简单的DNS A 记录查找并获取属于该服务一部分或者所有pod的IP。客户端可以使用该信息连接到其中的一个、多个或全部。
3.2.1 DNS发现Pod示例
准备一个具有nslooup命令的 Pod(此步骤本文不再赘余,最简单的话可以运行一个 busybox pod),运行此 Pod 后,通过进入 Pod 内部通过执行DNS查找以查看是否获得了实际的pod IP。
(1)对于普通 Kubernetes Service
[root@108 ~]# kubectl get svc -n=istio-system |grep jaeger-query
jaeger-query ClusterIP 10.233.49.189 <none> 16686/TCP,16685/TCP 661d
进入具有nslooup命令Pod内部。
[root@108 ~]# kubectl exec -it busybox-848d7987f9-wbqq8 /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # cat /etc/resolv.conf
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 169.254.25.10
options ndots:5
执行服务DNS查找。
注意:经测试使用nslooup命令解析域名时候,不走search域,所以需要拼全服务名。
(2)对于普通 Headless Service
[root@108 ~]# kubectl get svc -n=xxx-middleware |grep kafka-zookeeper-headless
kafka-zookeeper-headless ClusterIP None <none> 2181/TCP,3888/TCP,2888/TCP 646d
[root@108 ~]# kubectl describe svc -n=xxx-middleware kafka-zookeeper-headless
Name: kafka-zookeeper-headless
Namespace: xxx-middleware
Labels: app=zookeeper
app.kubernetes.io/managed-by=Helm
chart=zookeeper-2.1.0
heritage=Helm
release=kafka
Annotations: meta.helm.sh/release-name: kafka
meta.helm.sh/release-namespace: xxx-middleware
Selector: app=zookeeper,release=kafka
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: None
IPs: None
Port: client 2181/TCP
TargetPort: client/TCP
Endpoints: 10.233.66.179:2181,10.233.66.181:2181,10.233.69.223:2181
Port: election 3888/TCP
TargetPort: election/TCP
Endpoints: 10.233.66.179:3888,10.233.66.181:3888,10.233.69.223:3888
Port: server 2888/TCP
TargetPort: server/TCP
Endpoints: 10.233.66.179:2888,10.233.66.181:2888,10.233.69.223:2888
Session Affinity: None
Events: <none>
进入具有nslooup命令Pod内部。
[root@108 ~]# kubectl exec -it busybox-848d7987f9-wbqq8 /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # cat /etc/resolv.conf
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 169.254.25.10
options ndots:5
执行服务DNS查找,解析地址正是服务标签关联Pod Ip(Endpoints: 10.233.66.179,10.233.66.181,10.233.69.223)。
Headless Services还有一个用处,即Headless Service的对应的每一个Endpoints,都会有对应的DNS域名;这样Pod之间就可以互相访问。我们还是看上面的这个例子,通过statefulSet管理,共三个 Pod 实例。
[root@108 ~]# kubectl get pods -n=xxx-middleware |grep zoo
kafka-zookeeper-0 1/1 Running 0 85d
kafka-zookeeper-1 1/1 Running 1 96d
kafka-zookeeper-2 1/1 Running 1 96d
现在直接解析指定 Pod 的DNS域名,对应的pod的域名为kafka-zookeeper-0、kafka-zookeeper-1、kafka-zookeeper-2,它们之间可以互相访问,这样对于一些集群类型的应用就可以解决互相之间身份识别的问题了。
注意:尽管headless服务看起来可能与常规服务不同,但在客户端的视角上它们并无不同。即使使用headless服务,集群内客户端也可以通过连接到服务的DNS名称来连接到pod上,就像使用常规服务一样。但是对于headless服务,由于DNS返回了pod的IP, 客户端直接连接到该pod,而不是通过服务代理。headless服务仍然提供跨pod的负载平衡,但是是通过DNS轮询机制,不是通过kube-proxy在工作节点提供的iptables/ipvs路由规则。
3.3 发现所有的Pod--包括未就绪的Pod
只有准备就绪的pod能够作为服务的后端。但有时希望即使pod没有准备就绪,服务发现机制也能够发现所有匹配服务标签选择器的pod。
幸运的是,不必通过查询KubernetesAPI服务器,可以使用DNS查找机制来查找那些未准备好的pod。要告诉Kubernetes无论pod的准备状态如何,希望将所有pod添加到服务中。必须将以下注解添加到服务中:
kind: Service
metadata:
annotations:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
示例:
[root@cloud ~]# kubectl describe svc -n=xxx-system redis-ha-announce-0
Name: redis-ha-announce-0
Namespace: xxx-system
Labels: app=redis-ha
app.kubernetes.io/managed-by=Helm
chart=redis-ha-3.9.0
heritage=Helm
release=cb-redis
Annotations: meta.helm.sh/release-name: cb-redis
meta.helm.sh/release-namespace: xxx-system
service.alpha.kubernetes.io/tolerate-unready-endpoints: true
Selector: app=redis-ha,release=cb-redis,statefulset.kubernetes.io/pod-name=redis-ha-server-0
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.234.235.210
IPs: 10.234.235.210
Port: server 6379/TCP
TargetPort: redis/TCP
Endpoints: 10.233.0.213:6379
Port: sentinel 26379/TCP
TargetPort: sentinel/TCP
Endpoints: 10.233.0.213:26379
Session Affinity: None
Events: <none>
3.4 其他
Headless服务就是一组Pod组成的只供集群内访问(没有ClusterIP)的Service,一般结合StatefulSet用于部署有状态应用的场景,如果想让部署的有状态应用暴露给集群外部客户端访问的话,可以新建个普通(有ClusterIP)的服务,通过标签选择关联有状态服务实例。
示例:
4、总结
在某些场景中,无需对外提供访问能力,只需要在内部找到自己想找到的Pod资源时,可以通过Headless Service来实现。这种不具有ClusterIP的Service资源就是Headless Service,该 Service 的请求流量不需要 kube-proxy 处理,也不会有负载均衡和路由规则,而是由ClusterDNS的域名解析机制直接去访问固定的Pod资源。
既然是Headless Service,那首先它是Service,一般的Service能被内部和外部访问。之所以叫Headless Service,是因为只对内提供访问,既然只对内访问,那肯定就需要提供稳定的访问能力了,否则就没什么作用了。比如说拥有固定的Pod名称和存储,所以一般会结合StatefulSet一起使用,用来部署有状态的应用。
如果想让部署的有状态应用暴露给集群外部客户端访问的话,可以新建个普通(有ClusterIP)的服务,通过标签选择关联有状态服务实例。
参考:https://www.cnblogs.com/lizexiong/p/14778359.html
参考:http://www.mangod.top/articles/2023/09/04/1693799594643.html
参考:https://www.jianshu.com/p/a6d8b28c88a2
Kubernetes Headless服务的更多相关文章
- Kubernetes master服务定制编译docker镜像
前言 之前部署了Kubernetes 1.13.0,发现master服务的启动方式与1.10.4版本有所区别,kube-apiserver.kube-controller-manager和kube-s ...
- Istio技术与实践02:源码解析之Istio on Kubernetes 统一服务发现
前言 文章Istio技术与实践01: 源码解析之Pilot多云平台服务发现机制结合Pilot的代码实现介绍了Istio的抽象服务模型和基于该模型的数据结构定义,了解到Istio上只是定义的服务发现的接 ...
- 如何发现 Kubernetes 中服务和工作负载的异常
大家好,我是来自阿里云的李煌东,今天由我为大家分享 Kubernetes 监控公开课的第二节内容:如何发现 Kubernetes 中服务和工作负载的异常. 本次分享由三个部分组成: 一.Kuberne ...
- 从零入门 Serverless | 一文讲透 Serverless Kubernetes 容器服务
作者 | 张维(贤维) 阿里云函数计算开发工程师 导读:Serverless Kubernetes 是以容器和 kubernetes 为基础的 Serverless 服务,它提供了一种简单易用.极致弹 ...
- Kubernetes之服务发现及负载Services
Service 概述 kubernetes 中的pod是有生生灭灭的,时刻都有可能被新的pod所代替,而不可复活(pod的生命周期).一旦一个pod生命终止,通过ReplicaSets动态创建和销毁p ...
- kubernetes 微服务西游记(持续更新中...)
随着微服务架构的流行,迈向云原生的趋势,容器化微服务就成为了持续集成最好的手段,镜像成为了持续交付最好的产物,容器成为了镜像运行最好的环境,kubernetes成了部署容器最好的生态系统和规范.实践出 ...
- Centos7部署kubernetes API服务(四)
1.准备软件包 [root@linux-node1 bin]# pwd /usr/local/src/kubernetes/server/bin [root@linux-node1 bin]# cp ...
- Kubernetes DNS服务配置案例
首先创建DNS服务的RC配置文件skydns-rc.yaml apiVersion: v1 kind: ReplicationController metadata: name: kube-dns-v ...
- Kubernetes Headless Service
1. Headless Service headless service 需要将 spec.clusterIP 设置成 None. 因为没有ClusterIP,kube-proxy 并不处理此类服务, ...
- 4.kubernetes的服务发现插件-CoreDNS
1.1.部署K8S内网资源清单http服务 1.2.部署coredns 部署K8S内网资源清单http服务 在运维主机HDSS7-200.host.com上,配置一个nginx虚拟主机,用以提高k8s ...
随机推荐
- ERROR: nginx-1.22.1 installation failed.
libraries. You can either do not enable the module or install the libraries.make: *** No rule to mak ...
- RK3588平台产测之ArmSoM产品高温环境测试
1. 简介专栏总目录 ArmSoM团队在产品量产之前都会对产品做几次专业化的功能测试以及性能压力测试,以此来保证产品的质量以及稳定性 优秀的产品都要进行严苛的多次全方位的功能测试以及性能压力测试才能够 ...
- Go函数介绍与一等公民
Go函数介绍与一等公民 函数对应的英文单词是 Function,Function 这个单词原本是功能.职责的意思.编程语言使用 Function 这个单词,表示将一个大问题分解后而形成的.若干具有特定 ...
- [ABC207E] Mod i 题解
Mod i 题目大意 给定一个序列 \(a\),问将其划分成若干段,满足第 \(i\) 段的和是 \(i\) 的倍数的划分方案的个数. 思路分析 考虑 DP,设 \(f_{i,j}\) 表示将序列中前 ...
- Android Kotlin 协程初探
1 它是什么(协程 和 Kotlin协程) 1.1 协程是什么 维基百科:协程,英文Coroutine [kəru'tin] (可入厅),是计算机程序的一类组件,推广了协作式多任务的子程序,允许执行被 ...
- 使用 Docker Compose 部署 RabbitMQ 的一些经验与踩坑记录
前言 RabbitMQ 是一个功能强大的开源消息队列系统,它实现了高效的消息通信和异步处理. 本文主要介绍其基于 Docker-Compose 的部署安装和一些使用的经验. 特点 成熟,稳定 消息持久 ...
- Windows下SVN服务端(Subversion)及客户端(TortoiseSVN)详细安装教程
1. Subversion和TortoiseSVN 是什么? http://www.uml.org.cn/pzgl/200811146.asp Subversion 是什么,我想如果不知道的话就没有必 ...
- zookeeper源码(04)leader选举流程
在"zookeeper源码(03)集群启动流程"中介绍了leader选举的入口,本文将详细分析leader选举组件和流程. leader选举流程(重要) quorumPeer的st ...
- 神经网络入门篇:激活函数(Activation functions)
激活函数 使用一个神经网络时,需要决定使用哪种激活函数用隐藏层上,哪种用在输出节点上.到目前为止,之前的博客只用过sigmoid激活函数,但是,有时其他的激活函数效果会更好. 在神经网路的前向传播中, ...
- 震惊,微信小程序可以设置网络字体!真香
准备工作,获取字体链接 还原设计稿的时候需要用到如下特殊字体(google 的 Montserrat): https://fonts.google.com/specimen/Montserrat 选择 ...