Kubernetes Service 概念整理

2018/09/17 Kubernetes

Service 简介

Service 是 Kubernetes 抽象化的一个组件,官方网站这样描述了 Service 的基本用途。

A Kubernetes Service is an abstraction which defines a logical set of Pods and a policy by which to access them

Kubernetes Service 是个抽象化的概念,主要定义了逻辑上的一群 Pod 以及如何访问它们的策略。

通过上述简介带出了几个问题:

  • 谁会使用 Service
  • 什么是逻辑上的一群 Pod
  • 什么是访问策略

KubernetesService

上述的三个问题,大体从上图来获得解释。

谁会使用 Service

集群外部的用户使用 Service 来访问集群内部 Pod 中运行的服务(1 -> 2)即使因为 Pod 故障导致重建或重启,我们也无需关心 Pod 的IP是否发生变化。 同一个集群中其它的 Pod 也有可能需要访问例如集群中运行了一组 LNMT, nginx 作为客户端访问 tomcat (路径 3 -> 2),需要注意的是两条路径的访问方式以及访问的 IP 地址有所不同。

什么是逻辑上的一群 Pod

简单的话描述就是

带着相同标签、做类似事情的一群 Pod

每个 Pod 本身会带着一个或多个不等的标签,当 Service 指定访问某个特定的标签时,Label Selector 会根据 Pod 身上自带的标签进行分组,并传回 Service 所要求的 Pod 信息。

上图右边共有三种分别为黄、绿、蓝色的 Pod,正代表集群内有三种不同的 Pod 群组,当 app=nginx 的 Pod 请求 app=tomcat 的 Pod 时,会先请求 Service 然后 Service 会将请求送至对应的 app=tomcat 的黄色群组内的其中一个 Pod 进行处理。

什么是访问策略

就是如何访问服务的规则,比如 TCP/UDP、Port 等相关规则。


Service 作为中间层,避免使用者和 Pod 直接交互,除了让服务维持一定弹性能够选择不同的 Pod 来处理请求外,某种程度上亦避免暴露 Port 而导致安全问题。

另外,也体现了一个非常重要的概念:

对于调用者而言,仅需要知道有人会处理他们的请求,而无需知道背后的处理人是谁。

如何定义 Service

Service 定义主要包括个主要元素:

  • 元数据资料(metadata)
  • 被访问应用的标签(Label)
  • 访问该服务的方式

元数据资料

metadata:
  name: service-examply

被访问应用的标签

由于每个 Pod 本身会带有一个或多个标签,如何将请求送到正确的 Pod,依赖管理者设定的标签是否得当。

比如,集群内有 Nginx 和 Apache 两种 Web 服务器在运行,运维人员希望将流量引入到 Nginx ,那么我们在定义 Pod 时设定一组 app: nginx 的标签,接着在 Service 内定义:

spec:
  selector:
    app: nginx

Service 便会根据资源定义清单内所设定的标签,通过 Label Selector 找到对应的 Pod 后,建立相对应的 iptables 规则。当使用者的请求到达 Kubernetes cluster 时,便会依照 iptables 规则将封包送到执行的 Pod 内部。

访问该服务的方式

服务要开放给外界使用时,需要定义改服务的 Port、Protocol。以常见的 Web 服务器来打比方:

  • 端口通常监听在 80、443 两个端口
  • 协议通常也为 TCP

对应到 Service 的定义方法是:

spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP
  - name: https
    port: 443
    targetPort: 443
    protocol: TCP

而完整的 spec.ports 包含以下几个元素:

  1. name:定义一个名字,运维人员应该了解该用途
  2. port:这里的端口是 Service 的端口
  3. targetPort:是实际 Pod 中应用所监听的端口
  4. protocol:该服务使用的协议目前有TCP/UDP两种,默认TCP
  5. nodePort:此设定只有在 spec.type 为 NodePort 或 LoadBalancer 时才会设定。

下面我们定义个完整的 Service:

# Service-example.yaml
apiVersion: v
kind: Service
metadata:
  name: service-example
  namespace: default
spec:
  selector:
    app: nginx
  ports:
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP
  - name: https
    port: 443
    targetPort: 443
    protocol: TCP

接着建立一个 Kubernetes Service

$ kubectl apply -f service-example.yaml
service/service-example created

查看 Service 相关资料

$ kubectl get service service-example
NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
service-example   ClusterIP   10.111.127.95   <none>        80/TCP,443/TCP   3m

# 查看详细信息
$ kubectl describe svc service-example
Name:              service-example
Namespace:         default
Labels:            <none>
Annotations:       kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"service-example","namespace":"default"},"spec":{"ports":[{"name":"http","port"...
Selector:          app=nginx
Type:              ClusterIP
IP:                10.111.127.95
Port:              http  80/TCP
TargetPort:        80/TCP
Endpoints:         <none>
Port:              https  443/TCP
TargetPort:        443/TCP
Endpoints:         <none>
Session Affinity:  None
Events:            <none>

Search

    Table of Contents