带你玩转kubernetes-k8s(第29篇:k8s-深入掌握Service:定义详解)

    Pod的讲解终于告一段落了,现在我们来一起学习Service。      

    Service是Kubernetes的核心概念,通过创建Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上。本章对Service的使用进行详细说明,包括Service的负载均衡机制、如何访问Service、Headless Service、DNS服务的机制和实践、Ingress 7层路由机制等。

   Service的yaml定义文件完整内容如下:

apiVersion: v1        // Required
kind: Service        // Required
metadata:            // Required
  name: string            // Required
  namespace: string         // Required
  labels:
  - name: string
  annotations:
  - name: string
spec:                             // Required
  selector: []                              // Required
  type: string                  // Required
  clusterIP: string
  sessionAffinity: string
  ports:
  - name: string
    protocol: string
    port: int
    targetPort: int
    nodePort: int
  status:
    loadBalancer:
      ingress:
        ip: string
        hostname: string 
属性名称 取值类型 是否必选 取值说明
apiVersion string v1
kind string Service
metadata object 元数据
metadata.name string Service名称
metadata.namespace string 命名空间,不指定默认为default

metadata.labels[]

metadata.annotation[]

list

list

 

自定义标签属性列表

自定义注释属性列表

spec object 详细描述
spec.selector[] list

label selector配置,将选择具有指定label标签的Pod

作为管理范围

spec.type string

Service的类型,指定Service的访问方式,默认值为ClusterIP。

1.Cluster IP:虚拟的服务IP地址,该地址用于K8s集群内部的Pod访问,在Node上kube-prox通过设置的optables规则进行转发。

2.NodePort: 使用宿主机的端口,使能够访问各Node的外部客户端通过Node的IP地址和端口号就能访问服务。

3. LoadBalancer: 使用外接负载均衡器完成到服务的负载分发,需要在spec.status.loadBalancer字段指定外部负载均衡器的IP地址,并同时定义nodePort和clusterIP,用于公有云环境。

spec.clusterIP string   虚拟服务IP地址,当type=clusterIP时,如果不指定。这系统进行自动分配,也可以手工指定:当type=loadBalancer时,这需要指定
spec.sessionAffinity string  

是否支持Session,可选值为ClusterIP,默认值为空。

clusterIP: 表示同一个客户端的访问请求都转发到同一个后端Pod

spec.ports[] list   Service需要暴露的端口列表
spec.ports[].name string   端口名称
spec.ports[].protocol string   端口协议,支持TCP和UDP。默认为TCP
spec.ports[].port init   服务监听的端口号
spec.ports[].targePort

int

  需要转发到后端Pod的端口号
spec.ports[].nodePort

int

 

当spec.type=NodePort时,指定映射到物理机的端口号

status object   当spec.type=LoadBalancer时,设置外部负载均衡的地址,用于公有云环境
status.loadBalancer object   外部负载均衡器
status.loadBalancer.ingress object   外部负载均衡器
status.loadBalancer.ingress.ip string   外部负载均衡器的IP地址
status.loadBalancer.ingress.hostname string   外部负载均衡器的主机名

Service 的基本用法

      一般来说,对外提供服务的应用程序需要通过某种机制来实现,对于容器应用最简便的方式就是通过TCP/IP机制及监听IP和端口号来实现。例如,定义一个提供Web服务的RC,由两个Tomcat容器副组成,每个容器都通过containerPort设置提供服务的端口号为8080:

webapp-rc.yaml

apiVersion: v1
kind: ReplicationController
metadata:
  name: webapp
spec:
  replicas: 2
  template:
    metadata:
      name: webapp
      labels:
        app: webapp
    spec:
      containers:
      - name: webapp
        image: tomcat
        ports:
        - containerPort: 8080

创建该RC之后获取该Pod的IP地址

kubectl get pod -l app=webapp -o yaml | grep podIP

可以直接通过这两个Pod的IP地址和端口号访问Tomcat服务:

带你玩转kubernetes-k8s(第29篇:k8s-深入掌握Service:定义详解)_第1张图片

       直接通过Pod的IP地址和端口号可以访问到容器应用内的服务,但是Pod的IP地址是不可靠的,例如当Pod所在的Node发生故障时,Pod将被Kubernetes重新调度到另一个Node,Pod的IP地址将发生变化。更重要的是,如果容器应用本身是分布式的部署方式,通过多个实例共同提供服务,就需要在这些实例的前端设置一个负载均衡器来实现请求的分发。Kubernetes中的Service就是用于解决这些问题的核心组件。

       以前面创建的webapp应用为例,为了让客户端应用访问到两个Tomcat Pod实例,需要创建一个Service来提供服务。Kubernetes提供了一种快速的方法,即通过kubectl expose命令来创建Service:

kubectl expose rc webapp

    查看新创建的Service,可以看到系统为它分配了一个虚拟的IP地址(ClusterIP),Service所需的端口号则从Pod中的containerPort复制而来:

接下来就可以通过Service的IP地址和Service的端口号访问该Service了:

带你玩转kubernetes-k8s(第29篇:k8s-深入掌握Service:定义详解)_第2张图片

这里,对Service地址10.111.79.254:8080的访问被自动负载分发到了后端两个Pod之一。

      除了使用kubectl expose命令创建Service,我们也可以通过配置文件定义Service,再通过kubectl create命令进行创建。例如对于前面的webapp应用,我们可以设置一个Service,代码如下:

apiVersion: v1
kind: Service
metadata:
  name: webapp1
spec:
  ports:
  - port: 8081
    targetPort: 8080
  selector:
    app: webapp

带你玩转kubernetes-k8s(第29篇:k8s-深入掌握Service:定义详解)_第3张图片

带你玩转kubernetes-k8s(第29篇:k8s-深入掌握Service:定义详解)_第4张图片

      Service定义中的关键字段是ports和selector。本例中ports定义部分指定了Service所需的虚拟端口号为8081,由于与Pod容器端口号8080不一样,所以需要再通过targetPort来指定后端Pod的端口号。selector定义部分设置的是后端Pod所拥有的label:app=webapp。

目前Kubernetes提供了两种负载分发策略:RoundRobin和SessionAffinity,具体说明如下:

◎ RoundRobin:轮询模式,即轮询将请求转发到后端的各个Pod上。
◎ SessionAffinity:基于客户端IP地址进行会话保持的模式,即第1次将某个客户端发起的请求转发到后端的某个Pod上,之后从相同的客户端发起的请求都将被转发到后端相同的Pod上。

       在默认情况下,Kubernetes采用RoundRobin模式对客户端请求进行负载分发,但我们也可以通过设置service.spec.sessionAffinity=ClientIP来启用SessionAffinity策略。这样,同一个客户端IP发来的请求就会被转发到后端固定的某个Pod上了。

       通过Service的定义,Kubernetes实现了一种分布式应用统一入口的定义和负载均衡机制。Service还可以进行其他类型的设置,例如设置多个端口号、直接设置为集群外部服务,或实现为Headless Service(无头服务)模式。

多端口Service

      有时一个容器应用也可能提供多个端口的服务,那么在Service的定义中也可以相应地设置为将多个端口对应到多个应用服务。在下面的例子中,Service设置了两个端口号,并且为每个端口号都进行了命名:

apiVersion: v1
kind: Service
metadata:
  name: webapp2
spec:
  ports:
  - port: 8080
    targetPort: 8080
    name: web
  - port: 8005
    targetPort: 8005
    name: management
  selector:
    app: webapp

带你玩转kubernetes-k8s(第29篇:k8s-深入掌握Service:定义详解)_第5张图片

另一个例子是两个端口号使用了不同的4层协议—TCP和UDP:

apiVersion: v1
kind: Service
metadata:
  name: webapp3
spec:
  ports:
  - port: 8080
    protocol: UDP
    name: tdp
  - port: 8080
    protocol: TCP
    name: tcp
  selector:
    app: webapp

带你玩转kubernetes-k8s(第29篇:k8s-深入掌握Service:定义详解)_第6张图片

外部服务Service

     在某些环境中,应用系统需要将一个外部数据库作为后端服务进行连接,或将另一个集群或Namespace中的服务作为服务的后端,这时可以通过创建一个无Label Selector的Service来实现:

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

     

通过该定义创建的是一个不带标签选择器的Service,即无法选择后端的Pod,系统不会自动创建Endpoint,因此需要手动创建一个和该Service同名的Endpoint,用于指向实际的后端访问地址。创建Endpoint的配置文件内容如下:

kind: Endpoints
apiVersion: v1
metadata:
  name: my-service
subsets:
- addresses:
  - ip: 1.2.3.4
  ports:
  - port: 8080

带你玩转kubernetes-k8s(第29篇:k8s-深入掌握Service:定义详解)_第7张图片

 

  访问没有标签选择器的Service和带有标签选择器的Service一样,请求将会被路由到由用户手动定义的后端Endpoint上。

带你玩转kubernetes-k8s(第29篇:k8s-深入掌握Service:定义详解)_第8张图片

 

    小结:

            本节内容到此结束,是不是觉得很简单呢?

            觉得简单,说明我们已经入k8s的门了,继续加油!

            多多点关注哦~

            

你可能感兴趣的:(kubernetes)