一句话总结Kubernetes的Headless服务

云计算 云原生
Kubernetes的概念很多,有的着实让人费解,比如说Headless服务,听名字就很拗口。那Headless服务是什么,使用场景是什么。一句话总结:Headless服务就是一组Pod组成的只供集群内访问(没有ClusterIP)的Service,一般结合StatefulSet用于部署有状态应用的场景。

Kubernetes的概念很多,有的着实让人费解,比如说Headless服务,听名字就很拗口。那Headless服务是什么,使用场景是什么。一句话总结:Headless服务就是一组Pod组成的只供集群内访问(没有ClusterIP)的Service,一般结合StatefulSet用于部署有状态应用的场景。

1、Service与服务发现

提到Headless Service就得先说说Service和服务发现。

1.1、Service简述

Service主要用于实现对一组Pod的访问,Service 通过标签选择器来关联 Pod 资源。Service对外暴露服务的方式有nodePort和loadbalancer。Service 根据访问的端口将对应的请求转发至后端Pod的端口上。

Service对象的IP地址(ClusterIP)是虚拟IP地址,仅在 Kubernetes集群内可访问,外部无法访问。一般有以下几种方式将Service暴露给外部访问:

  • 通过hostPort方式在单一节点上做端口映射
  • 通过Pod的hostNetwork配置让Pod资源使用工作节点上的网络
  • 使用NodePort或LoadBalancer类型的Service
  • 使用Ingress 资源

本质上来讲,一个Service 对象对应于工作节点内核之中的一组路由规则,这些规则能够将到达Service对象的ClusterIP的流量转发至相应Pod对象的IP地址和端口。

每个工作节点的kube-proxy组件通过API Server持续监听各个Service及其关联的Pod对象,并将Service对象的创建或变动,实时写入到当前工作节点的路由规则上。客户端、Service及Pod对象的关系如下图所示:

1.2、Service类型

Service 一般分为3种类型:ClusterIP、NodePort、LoadBalancer。

ClusterIP

通过集群内部IP 地址暴露服务,CusterIP地址仅在集群内部可以访问,无法被集群外部的客户端访问。

NodePort

NodePort类型,将Service的端口号映射到每个Node的一个端口号上,然后分发给后端的Pod处理。这种类型的Service 既可以被集群内部客户端通过 CIusterIP 直接访问,也可以在集群外部客户端通过nodeIP:nodePort进行访问。

LoadBalancer

LoadBalancer类型建立在 NodePort基础上,将Service映射到一个负载均衡器的IP 地址上,通常在公有云环境中使用。

客户端通过负载均衡器的IP和Service的端号就可以访问到具体的服务,无须再通过 kube-proxy提供的负载均衡机制进行流量转发,可以直接将流量转发到后端 Pod上。

如果是本地搭建LoadBalancer,一般采用metallb方案,官网地址:https://metallb.universe.tf/,有兴趣的朋友自行搭建。

2、Headless Service的概念

在某些场景中,无需对外提供访问能力,只需要在内部找到自己想找到的Pod资源时,可以通过Headless Service来实现。

这种不具有ClusterIP的Service资源就是Headless Service,该 Service 的请求流量不需要 kube-proxy 处理,也不会有负载均衡和路由规则,而是由ClusterDNS的域名解析机制直接去访问固定的Pod资源。

一般Headless会搭配着StatefulSet一起使用,下面继续介绍。

3、StatefulSet结合Headless使用

3.1、StatefulSet概述

StatefulSet是编排有状态应用的控制器。所谓有状态的应用就是一组具有唯一持久数据和固定访问名称的 Pod。StatefulSet主要用来部署有状态应用,比如部署ZK、Kafka、MySQL、Redis等。

有状态的资源通常由两个组件构成:Headless Service和StatefulSet。Headless Service用于为各个Pod资源分配唯一固定的标识,然后生成DNS 解析记录。StatefulSet用于编排Pod 对象,并借助volumeClaimTemplate自动为Pod资源创建专有的存储。

数据的高可用是StatefulSet会极力保障的一个特性,不管是缩容还是扩容的场景。StatefulSet控制器不支持并行扩缩容机制,它一次只启动或者终止一个Pod 资源,避免数据错误。

StatefulSet、volumeClaimTemplate、PVC、PV的关系见下图:

3.2、StatefulSet特性

有序性

StatefulSet借助 Headless Service 为每个 Pod资源分配唯一固定的标识,一般是在Pod名称后面添加-0、-1、-2、...等等,。假设设置副本数replicas=2,启动时,先启动pod-0再启动pod-1,停止时则以相反的顺序进行,先停止pod-1再停止pod-0。

有状态

无状态应用没有固定标识,他们不受其他Pod影响,同样模板创建的任意Pod就可以替换之前的Pod。

有状态应用有固定的名称和存储,会受到同一组内的其他Pod的影响。Pod对象如果被替换,新的Pod仍然具有相同的标识和相同的存储。

StatefulSet使用存储卷模板为每个 Pod 对象创建专用的 PVC存储卷,通过volumeClaimTemplate自动创建绑定的存储PVC不变。

删除 Pod 对象并不会删除相关的 PV 资源,如果Pod 对象由于节点故障等原因被重新调度到其他节点时,之前同名Pod实例专用的 PV数据可以继续复用。

稳定服务发现

因为是有状态的,所以想找到自己想找到的Pod,可以直接通过pod名称.svc名称.命名空间.svc.cluster.local访问。

4、Yaml示例

示例部署一个Headless Service + StatefulSet,比如部署一个带有存储的nginx服务。文中使用到了volumeClaimTemplates,前提要创建一个storageClassName。后面会单独写一篇讲解PV、PVC、StorageClass、Provisioner。

apiVersion: v1
kind: Service
metadata:
  name: nginx-statefulset-svc
  namespace: dev
spec:
  # ClusterIP | NodePort | LoadBalancer
  type: ClusterIP
  # headless service 这里的clusterIP使用None
  clusterIP: None
  selector:
    app: nginx-statefulset-tpl
  ports:
    - name: http
      port: 80
      targetPort: 80
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx-statefulset
  namespace: dev
  labels:
    app: nginx-statefulset
spec:
  replicas: 2
  serviceName: nginx-statefulset-svc
  selector:
    matchLabels:
      app: nginx-statefulset-tpl
  template:
    metadata:
      labels:
        app: nginx-statefulset-tpl
    spec:
      containers:
        - name: nginx
          image: nginx
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: www
              mountPath: /usr/share/nginx/html
  # volumeClaimTemplates是StatefulSet独有的配置,前提要先创建一个storageClassName
  volumeClaimTemplates:
    - metadata:
        name: www
      spec:
        resources:
          requests:
            storage: 200Mi
        accessModes:
          - ReadWriteOnce
        storageClassName: nfs-client

5、总结

一句话总结:Headless服务就是一组Pod组成的只供集群内访问(没有ClusterIP)的Service,一般结合StatefulSet用于部署有状态应用的场景。

既然是Headless Service,那首先它是Service,一般的Service能被内部和外部访问。之所以叫Headless Service是因为只对内提供访问。既然只对内访问,那肯定就需要提供稳定的访问能力了,否则就没什么作用了。比如说拥有固定的Pod名称和存储,所以一般会结合StatefulSet一起使用,用来部署有状态的应用。

责任编辑:华轩 来源: 不焦躁的程序员
相关推荐

2020-11-27 09:57:11

Python代码PyPy

2015-08-03 10:21:04

设计模式表达

2023-09-06 15:23:30

Docker容器K8S

2010-03-29 11:55:12

无线上网报错

2023-05-08 15:44:23

3D数字人

2014-05-07 10:47:51

移动金融互联网金融GMIC

2018-01-15 10:45:43

社交网络互联网巨头百度

2020-12-16 10:43:44

PythonPyPy代码

2019-08-15 11:42:56

程序员电脑软件

2011-06-03 16:42:47

SEO

2023-12-13 21:50:59

腾讯AI模型

2014-12-16 08:58:17

甲骨文Oracle数据库选件

2013-05-10 10:56:09

2024-02-08 09:33:37

苹果AI

2011-11-01 07:23:59

乔布斯悼文

2022-12-12 13:45:46

模型修图

2019-03-27 09:31:36

互联网面试技术

2024-04-01 13:03:00

AI模型

2023-08-25 17:10:14

LLM人工智能

2021-12-30 10:00:07

3DAI 人工智能
点赞
收藏

51CTO技术栈公众号