Kubernetes Service 详解

深入了解Kubernetes Service

 Service是Kubernetes最核心的概念,通过创建Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求进行负载分发到后端的各个容器应用上。

Service的四种类型

  1. Clusterip: 默认类型,自动分配一个仅cluster内部可以访问的虚拟ip
  2. NodePort: 在clusterip基础上为service在每台机器上绑定一个端口,这样就可以通过Nodeip:port方式来访问该服务
  3. Loadbalance: 在NodePort基础上,接触cloud provider创建一个外部负载均衡器,并将请求转发到nodeip:port
  4. externalName: 把集群外部的服务引入到集群内部,在集群内中直接使用,没有任何类型的代理被创建

yaml格式的pod配置文件内容及属性说明

apiVersion: v1          // 必选,版本: v1
kind: Service           // 必选,Service
metadata:           // 必选,元数据
  name: string          // 必选,Service名称
  namespace: string     // 命令空间,不指定时系统系统默认的空间"default"
  labels:           // 自定义属性标签列表
    - name: string      // 自定义注释属性列表
spec:               // 详细描述
  selector: []          // label Selector配置,选择具有指定label标签的Pod作为管理范围
  type: string          // Service的类型,默认为ClusterIP,可选NodePort和LoadbalancerclusterIP: string     // 虚拟服务IP地址,类型为ClusterIP时,如不指定,则系统自动分配
  sessionaffinity: string   // 是否支持session,默认为空,可选ClusterIP,表示同一个客户端的访问请求转发到同一个口段Pod
  ports:            // Service需要暴露的端口列表
  - name: string        // 端口名称
    protocol: string        // 端口协议,支持tcp和udp,默认tcp
    port: int           // 服务监听的端口号
    targetPort: int     // 需要转发到后端Pod的顿口号
    nodePort: int       // 当type为NodePort时,指定映射到物理机的端口号介于[30000-32767]status:           // 当type为loadbalancer时,设置尾部负载均衡的地址,用于公有云环境
    loadBalancer:       // 外部负载均衡器
      ingress:          // 外部负载均衡器
        ip: string      // 外部负载均衡器的Ip
        hostname: string    // 外部负载均衡器的主机名

Service的基本用法

 一般来说,对外提供服务的应用程序需要通过某种机制来实现,对于容器应用最方便的方式就是通过TCP/IP及监听IP和端口号的方式来实现。直接通过Pod的IP地址和端口号访问应用,但是Pod的IP地址是不可靠的,当Pod所在的Node发生故障,Kubernetes会了重新调度到另一台Node上,这样Pod的IP将发生变化。重要的是,容器本身是分布式的部署方式,通过多个实例共同提供服务,需要在这些实例的前端设置一个负载均衡器来实现请求的分发,Kubernetes中的Service就师用来解决该问题的核心组件。
 Kubernetes提供一种快速的方法,即通过kubectl expose命令来创建Service
如:

#kubectl expose rc webapp

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

#kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
webapp  169.169.235.79 <none>   8080/TCP    3s

我们可以通过该Service的IP地址和端口号来访问

#curl 169.169.235.79:8080

对Service地址169.169.235.79:8080的访问会自动负载到后端的两个Pod中的一个。 除了使用命令创建Service,也可以通过配置文件定义Service,在通过kubectl create -f命令来进行创建。

apiVersion: v1
kind: service
metadata:
 name: webapp
spec:
 ports:
 - port: 8081              // Service所需的虚拟端口号
   targetPort: 8080            // 后端Pod的端口号
 selector: 
   app: webapp             // 后端拥有label: app=webapp的Pod

 目前,Kubernetes提供两种负载分发策略:RoundRobin和SessionAffinity。默认情况下采用RoundRobin模式进行路由选择。

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

 默认情况下,Kubernetes采用RoundRbin模式进行路由选择,某些应用场景下开发人员系统自己控制负载均衡策略,Kubernetes通过Headless Service的概念来实现这种功能,即不给Service设置ClusterIP,仅通过Label Selector将后端的Pod列表返回给调用的客户端.
如:

apiVsersion: v1
kind: Service
metadata:
  name: nginx
  label:
    name: nginx
spec:
  ports:
  - ports: 80
  clusterIP: None
  selector:
    app: nginx

 该Service没有虚拟的clusterip地址,对其进行访问将获得具有label "app=nginx"的全部Pod别表,然后客户端程序需要实现自己的负载均衡分发策略。

集群外部访问Pod或Service

由于Pod和Service都是Kubernetes集群范围内的虚拟概念,所以集群外的客户端无法通过Pod的IP或者service的虚拟ip和端口号访问。为了让外部用户可以访问这些服务,可以将Pod和Service的端口映射到宿主机,使客户端通过物理机访问容器应用.

方式将容器应用的端口号映射到物理机

  1. 通过设置容器级别的hostport,将容器应用的端口号映射到物理机
apiVersion: v1
kind: Pod
metadata:
  name: webapp
  labels:
    name: webapp
spec:
  containers:
  - name: tomcat
    image: tomcat
    ports:
    - containerPort: 8080
      hostPort:8081

通过kubectl create创建该pod后即可通过物理机的IP和8081端口访问Pod内的容器服务

#curl 10.0.0.23:8081
  1. 通过设置Pod级别的hostNetwork=true,该Pod中所有容器的端口号都将被直接映射到物理机,需要注意的是,在容器的ports定义部分如不指定hostport,则默认hostport等于containerport。

使用nodePort类型将Service的端口号映射到物理机

  1. 过设置nodePort映射到物理机,同时这是Service的类型为nodePort
apiVersion: v1
kind: Service
metadata:
  name: tomcat-svc
spec:
  type: NodePort
  ports:
  - port: 8080
    nodePort: 30033
  selector:
    name: webapp

通过物理机的IP地址和nodePort30033端口访问服务

#curl 10.0.0.22:30033

同样对该Service的访问也将被负载分发到后端的多个Pod上

  1. 通过设置LoadBalancer映射到云服务商提供的LoadBalancer地址。该用法仅用于在公有云服务商的平台上设置Service的场景
posted @ 2020-08-31 19:33  純黑色  阅读(2590)  评论(0编辑  收藏  举报