ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、视频、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
"Headless Service" 翻译过来就是“无头服务”,它表示的是创建的 Service 没有设置 Cluster IP。它的创建非常简单,只需要设置`service.spec.clusterIP=None`即可。 它属于一种特殊类型的集群服务,通常应用于以下两种情况中: * 自定义负载均衡策略,即:不使用 Service 默认的负载均衡策略(默认的策略是通过服务转发连接到符合要求的任一一个 Pod 上)。 * 获取属于相同标签选择器下的所有 Pod 列表 所以通过 Headless Service 可以获取到所有符合相关要求的 Pod 列表,然后可以通过自定义负载均衡器让客户端的连接转发到一个、多个、或是所有的 Pod 上,典型的应用就是:StatefulSet。 Headless Service 的特点如下: * 在集群内部没有一个特定的 Cluster IP 地址 * kube-proxy 不会处理 Headless Service * 没有负载均衡和路由功能 * 根据服务是否有标签选择器进行 DNS 配置 是否定义标签选择器主要影响 DNS 配置: * 设置了 Selector:Endpoints Controller 在 apiService 中会创建 Endpoints 记录,并且修改 DNS 配置返回 A 记录,这样就可以获取到 Headless Service 对应的所有 Pod 的 IP 地址。 * 没有设置 Selector:不会有 Endpoints 记录。 所以 Headless Service 自定义负载均衡的实现逻辑是:通过标签选择器获取到所有符合标签的 Pod 的 IP 地址列表,然后自定义服务响应的方式。 下面通过一个具体的例子来加深印象。 在`/home/shiyanlou`目录下新建`nginx-deployment.yaml`文件,并向其中写入如下内容: ~~~yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: selector: matchLabels: app: nginx replicas: 3 # 创建 3 个 nginx Pod 副本 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 # 指定开放 80 端口 ~~~ 然后创建一个普通的、有 ClusterIP 的服务,在`/home/shiyanlou`目录下新建`normal-service.yaml`文件,并向其中写入如下内容: ~~~yaml apiVersion: v1 kind: Service metadata: name: normal-service spec: selector: app: nginx ports: - protocol: TCP port: 8080 # 将服务的 8080 端口映射到 nginx 容器的 80 端口 targetPort: 80 ~~~ 接着创建一个 headless 类型的 Service,在`/home/shiyanlou`目录下新建`headless-service.yaml`文件,并向其中写入如下内容: ~~~yaml apiVersion: v1 kind: Service metadata: name: headless-service spec: clusterIP: None # 注意:这里一定要设置为 None selector: app: nginx ports: - protocol: TCP port: 8080 targetPort: 80 ~~~ 执行创建: ~~~bash $ kubectl create -f nginx-deployment.yaml deployment.apps/nginx created $ kubectl create -f normal-service.yaml service/normal-service created $ kubectl create -f headless-service.yaml service/headless-service created ~~~ ~~~bash $ kubectl get all # 有 3 个新创建的 nginx Pod NAME READY STATUS RESTARTS AGE pod/nginx-5754944d6c-5v6wq 1/1 Running 0 2m13s pod/nginx-5754944d6c-q5mxh 1/1 Running 0 2m13s pod/nginx-5754944d6c-vzjb9 1/1 Running 0 2m13s # headless-service 的 CLUSTER-IP 为 None,而 normal-service 有一个固定的 CLUSTER-IP 为 10.107.154.5 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/headless-service ClusterIP None <none> 8080/TCP 90s service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 85d service/normal-service ClusterIP 10.107.154.5 <none> 8080/TCP 97s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/nginx 3/3 3 3 2m13s NAME DESIRED CURRENT READY AGE replicaset.apps/nginx-5754944d6c 3 3 3 2m13s ~~~ 为了便于后面的验证,先查询创建的 3 个 Pod 的 IP 地址: ~~~bash $ kubectl get pods -l app=nginx -o yaml|grep podIP podIP: 10.244.2.5 podIP: 10.244.2.4 podIP: 10.244.3.3 ~~~ 现在可以进入容器内部通过 DNS 查找 podIP,这里单独运行一个使用 utils 镜像创建的 pod 执行命令(镜像中已经安装了 dnsutils): ~~~bash $ kubectl run --generator=run-pod/v1 --rm utils -it --image registry-vpc.cn-hangzhou.aliyuncs.com/chenshi-kubernetes/utils:latest bash root@utils:/# nslookup normal-service Server: 10.96.0.10 Address: 10.96.0.10#53 Name: normal-service.default.svc.cluster.local Address: 10.107.154.5 root@utils:/# nslookup headless-service Server: 10.96.0.10 Address: 10.96.0.10#53 Name: headless-service.default.svc.cluster.local Address: 10.244.3.3 Name: headless-service.default.svc.cluster.local Address: 10.244.2.4 Name: headless-service.default.svc.cluster.local Address: 10.244.2.5 ~~~ 通过上面的输出也就证实了,访问 normal-service 获得的是服务在集群中的 ClusterIP,而访问 headless-service 获取到的是符合标签选择器的所有 Pod 的 IP 地址列表。 Headless Service 可以让我们直接连接到所有的 Pod,而不需要使用作为负载均衡的 Service 或是 kube-proxy,这类特殊的服务有其特定的用途,比如经常和 StatefulSet 搭配使用。