Kubernetes:Service

时间:2021-02-19 13:29:13   收藏:0   阅读:0

概述

配置

一个典型的Service对象配置如下:

kind: Service
apiVersion: v1
metadata:
  name: nginx-server
spec:
  clusterIP: 192.168.1.0
  selector:
    app: nginx
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 9376
    - name: https
      protocol: TCP
      port: 443
      targetPort: 9377

无标签选择器的Service

上文提到,Service常用于对Pod的流量调度,但也可以用于访问:

此时需要定义一个没有标签选择器的Service,如:

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

因为该Service没有标签选择器,相应的Endpoint对象便无法自动创建。因此我们需要手动创建一个Endpoint对象,以便将到达该Service监听的端口的请求映射到后端程序或其他Service的IP地址和端口:

apiVersion: v1
kind: Endpoints
metadata:
  name: my-service
subsets:
  - addresses:
      - ip: 192.0.2.42
    ports:
      - port: 9376

在上述例子中,Service 将请求路由到 Endpoint:192.0.2.42:9376 (TCP)。另外,目标IP不能是本机回环地址或虚拟IP地址。

Headless Services

Headless Service不提供负载均衡的特性,也没有自己的 IP 地址,kube-proxy并不会处理这类Service。只需要指定 spec.clusterIP字段值为 "None",便可以创建一个Headless Service对象。

代理模式

技术图片

服务发现模式

Kubernetes 支持两种基本的服务发现模式 —— 环境变量和 DNS。

环境变量

kubelet会为节点上活跃的Service对象创建一组环境变量(包括Service的clusterIP、监听的端口等),并在创建Pod时这些环境它们注入其中。使用这种服务发现模式要求Service先于Pod创建,因此有一定的局限性。

DNS

集群中的DNS服务器(例如CoreDNS)使用Kubernetes的watch api不断监测Service的创建并为每一个Service创建一条DNS记录,从而使Pod可以解析该Service的域名。对于不同类型的Service,其DNS记录的分配方式有所不同:

Headless Service以外的Service

< service-name>.<namespace-name>.svc.cluster.local

? 其中,cluster.local为,该DNS记录解析到Service的ClusterIP。

? 则可根据该SRV记录发现该Service的命名端口及IP地址。

Headless Service

外部访问

集群中的节点(虚拟机)可以通过网关访问互联网,但Pod的IP地址与其所在节点的IP地址显然不同。由于网关的NAT功能只能转换节点(虚拟机)的IP地址,而无法转换Pod的IP地址。毕竟网关根本无法知晓节点上运行了什么样的Pod,因此Pod是无法访问外网的。而我们常希望将集群中的一些运行前端应用的Pod暴露给集群外部的IP地址,这时便需要改变spec.type字段定义特殊类型的Service了。

ClusterIP

默认的Service类型,通过集群中的内部IP暴露Service,这种方式的 Service只能在集群内部访问。

NodePort

通过每个节点上的 IP 和静态端口(spec.ports.nodePort)暴露服务,其配置如下:

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: NodePort
  selector:
    app: MyApp
  ports:
      # 默认情况下,为了方便起见,targetPort与port字段值相同
    - port: 80
      targetPort: 80
      # 如不指定,则会从30000-32767范围内分配一个端口号
      nodePort: 30007

该类型的Service在集群外部可以通过<NodeIP>:<spec.ports.nodePort> 访问,同时也会自动创建一个ClusterIP类型的访问方式:<spec.clusterIp>:<spec.ports.port>可供集群内部访问。

LoadBalancer

使用云提供商的负载均衡器向集群外部暴露服务,同时也会自动创建ClusterIP和NodePort类型的访问方式:

负载均衡器是异步创建的。当LoadBalancer类型的Service创建完成后,负载均衡器的信息将被回写到 Service 的 status.loadBalancer 字段中,例如:

  apiVersion: v1
  kind: Service
  metadata:
    name: example-service
  spec:
    selector:
      app: example
    clusterIP: 10.84.206.2
    externalIPs:
    - 172.29.245.25
    ports:
    - nodePort: 31688
      port: 8765
      protocol: TCP
      targetPort: 9376
    type: LoadBalancer
  status:
    loadBalancer:
      ingress:
      - ip: 172.29.245.25

Loadbalancer类型的Service处理外网入方向流量的流程如下:

ExternalName

ExternalName类型的Service将Service映射到DNS名称,而非标签选择器选取的一组Pod上,其配置如下:

apiVersion: v1
kind: Service
metadata:
  name: my-service
  namespace: prod
spec:
  type: ExternalName
  externalName: my.database.example.com

当查找域名:my-service.prod.svc.cluster.local时,集群内的DNS服务将返回一条CNAME记录, 即spec.externalName字段的值 my.database.example.com。访问该服务的方式与其他类型的Service相同,但主要区别在于重定向发生在DNS级别,而不是通过代理或转发。

External IP

如果有外部 IP 路由到 Kubernetes 集群的一个或多个节点,任意类型的Service可以通过<spec.externalIPs>:<spec.ports.port> 进行访问。

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 9376
  externalIPs:
    - 80.11.12.10

在上面的例子中,客户端即可通过80.11.12.10:80访问名为my-service的Service对象。

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!