Service介绍

Service资源对象可以为一组具有相同功能的Pod提供一个单一不变的接入点。

引入Service的原因:

  • Pod的IP地址是随机变化的,并且无法直接由外部访问或访问外部;

  • Service的IP地址和端口是固定的;

下图是典型的前后端之间互相访问的架构图,前端Pod不会与后端Pod直接通信,而是通过Service访问后端Pod,前端暴露给外部客户端的同样也是一个Service:

内部和外部客户端通常通过Service连接到Pod

Service对象是通过标签选择器来匹配Pods,在匹配到一个Pod后,会创建一个Endpoint资源,并将该Pod的IP地址和端口记录下来,因此Service与Pod之间其实还有一层Endpoint。

创建Service

Service同样是使用标签选择器spec.selector来匹配Pod作为其转发流量的后端Pod。

创建Service同样有两种方法:

  1. 使用kubectl expose命令来创建Service,详情可见常用命令汇总一节

  2. 使用配置文件创建Service,如下:

apiVersion: v1
kind: Service
metadata:
  name: httpd-svc
  labels:    # Service的标签
    run: httpd
spec:
  type: NodePort    # Service的类型,NodePort在ClusterIP的基础上增加了非k8s集群可访问的特性(推荐使用LoadBalancer,它会指定一个唯一可公开访问的ip地址,然后将所有连接重定向至Service,这样可以防止某一个Node挂了)
  externalTrafficPolicy: Local    # (当spec.type为NodePort或LoadBalance时)这个可以不做;写成这样是为了让外部通信连接的Node,将该连接转发至本Node的Pod上,防止转发给其他Node上的Pod时造成额外的网络跳数(但是有这个的话,本Node不会对外部流量做SNAT)
  selector:        # 通过selector中指定的值,与Pod的labels对应,用来选择Pod,当type为ExternalName时,这里不用写(如果不写的话,就不会自动创建Endpoint资源了)
    run: httpd
  ports:        # 该Service暴露的端口(可以同时暴露多个端口)
  - protocol: TCP
    nodePort: 30000        # 指定集群节点上监听的端口(若不指定,会自动生成)
    port: 8080            # ClusterIP监听的端口
    targetPort: 80        # Pod监听的端口(这里可以写成对应的Pod的spec.containers.ports.name来根据端口名匹配)
    name: xxx        # 端口的名字为xxx
  sessionAffinity: ClientIP    # 会话亲和性,默认是None,会使Service将来自同一个客户端IP地址的所有请求都转发至同一个Pod上

Tips:

  1. spec.type共有五种:

    • None:用于创建headless Service;

    • ExternalName:用于与集群外部服务映射,并且不用指定spec.selector,因此不会自动创建Endpoint;

    • ClusterIP:默认类型,用于集群内部资源访问;

    • NodePort、LoadBalancer:用于暴露集群内部资源给外部访问;

  2. Service共有两种IP地址:

    • CLUSTER-IP:该IP地址和其端口都是虚拟的,无法Ping通,均由iptables实现。即集群内部的资源可以访问的IP地址,除了Service的spec.typeExternalName时没有外,其余类型都有;

    • EXTERNAL-IP:该IP地址是集群外部的资源可以访问的IP地址,其端口是真实存在的,会被一个进程监听,仅当Service的spec.typeNodePortLoadBalancerExternalName时才有;

Last updated

Was this helpful?