K8S Service基础详解

前言

本篇文章我们介绍Kubernetes Service的各个类型,各类端口的含义,向外部暴露内部服务的方式以及2套Kubernetes的WEB管理工具的部署。

Service 介绍

Kubernetes中一个应用服务会有一个或多个实例(Pod),每个实例(Pod)的IP地址由网络插件动态随机分配(Pod重启后IP地址会改变)。为屏蔽这些后端实例的动态变化和对多实例的负载均衡,引入了Service这个资源对象,如下所示:

apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  labels:
    app: nginx
spec:
  type: ClusterIP
  ports:
    - port: 80
       targetPort: 80
  selector:
    app: nginx

Service type

服务可以被外部的客户访问,也可以被内部的客户访问。Service通过创建时指定的标签选择器来决定用户的请求转发到后台的哪些Pods中。 根据创建Service的type类型不同,常见的,可分成3种模式 :

  • ClusterIP : 默认方式 , 通过为Kubernetes的Service分配一个集群内部可访问的固定虚拟IP(Cluster IP),实现集群内的访问。为最常见的方式。
  • NodePort:除了使用Cluster IP之外,还通过将service的port映射到集群内每个节点的相同一个端口,实现通过nodeIP:nodePort从集群外访问服务。
  • LoadBalancer:和nodePort类似,不过除了使用一个Cluster IP和nodePort之外,还会向所使用的公有云申请一个负载均衡器(负载均衡器后端映射到各节点的nodePort),实现从集群外通过LB访问服务。

Service与endpoints

  • Endpoints 是组成Service的一组IP地址和端口资源。

  • Kubernetes在创建Service时,根据Service的标签选择器(Label Selector)来查找Pod,据此创建与Service同名的EndPoints对象。当Pod的地址发生变化时,EndPoints也随之变化。Service接收到请求时,就能通过EndPoints找到请求转发的目标地址。

  • kube-proxy根据Service和Endpoint来维护本地的路由规则。当Endpoint发生变化,即Service以及关联的pod发生变化,kube-proxy都会在每个节点上更新iptables,实现一层负载均衡。

#查询Service与endpoints
kubectl get service,endpoints --all-namespaces

Service的各种Port与IP

PORT

  • port:这是service的端口,通过clusteripport即可访问到service服务,返回为pod tag,注意必须ip和端口缺一不可!
  • nodePortnodePort的范围是30000-32767,集群内不允许冲突,在service的yaml中设置 , 一旦设置了nodePort,所有的node主机都会监听这个端口,也就是说使用集群内任意一台nodeIP:nodePort都可以访问到service服务,同样,在集群内此端口就只能被设置一次。
  • containerPort :容器的实际端口,Pod内的容器与外部进行通信的端口,Pod中的所有容器共享一个网络IP,容器间可直接用localhost访问。
  • targetPort:Pod上的端口,从portnodePort上到来的数据最终经过kube-proxy流入到后端pod的targetPort上进入容器。所以需要在service的yaml中定义,来告诉service。
  • hostPorthostPort是直接将容器的端口与所调度的节点上的端口路由,这样用户就可以通过宿主机的IP加上来访问Pod了。
port汇总
  1. containerPort 和 targetPort 放在一起理解,两个不是一个概念,前者容器的port,负责容器间的交流,前者在deploy yaml中设置,后者再在svc yanl 中设置,与kube-proxy进行连接,不强制保持一致!请求先通过targetProt到到达pod,然后再通过containerPort 进入容器!
  2. port 和 nodePort 放在一起理解,前者是在集群内访问service 需要的端口,需要结合clusterip ,缺一不可!
  3. 如果想在集群外访问,则需要将service变成nodePort的类型,需要抛出nodeProt,使用集群任意node ip即可访问!
  4. hostPort 是集群外想访问pod 需要抛出的端口,使用pod 所在node 的ip,结合此端口实现!因为pod ip变换莫测,所以应用比较局限,需要自己维护这个变化,比如node打上标签!
  5. targetPort 和port 默认是相同的,可以不同!

IP

  • Pod IP:Pod的IP,每个Pod启动时,会自动创建一个镜像为gcr.io/google_containers/pause的容器,Pod内部其他容器的网络模式使用container模式,并指定为pause容器的ID,即:network_mode: “container:pause容器ID”,使得Pod内所有容器共享pause容器的网络,与外部的通信经由此容器代理,pause容器的IP也可以称为Pod IP。
  • ClusterIP:Pod IP 地址是实际存在于某个网卡(可以是虚拟设备)上的,但clusterIP就不一样了,没有网络设备承载这个地址。它是一个虚拟地址,由kube-proxy使用iptables规则重新定向到其本地端口,再均衡到后端Pod。当kube-proxy发现一个新的service后,它会在本地节点打开一个任意端口,创建相应的iptables规则,重定向服务的clusterIP和port到这个新建的端口,开始接受到达这个服务的连接。
  • 节点IP:Node-IP,service对象在Cluster IP range池中分配到的IP只能在内部访问,如果服务作为一个应用程序内部的层次,还是很合适的。如果这个service作为前端服务,准备为集群外的客户提供业务,我们就需要给这个服务提供公共IP了。指定service的spec.type=NodePort,这个类型的service,系统会给它在集群的各个代理节点上分配一个节点级别的端口,能访问到代理节点的客户端都能访问这个端口,从而访问到服务。

对外暴露内部服务

  • hostNetwork: true: 在yaml文件中spec部分指定,如果在POD中使用hostNetwork:true配置网络,pod中运行的应用程序可以直接看到宿主主机的网络接口,从而使其可以使用宿主主机网络端口。宿主主机所在的局域网上所有网络接口都可以访问到该应用程序。hostNetwork模式不再需要创建一个service yaml。该配置的缺点:应用的网络与宿主机一样,需保证应用需要监听的网络端口在宿主机上没有被占用。并且无法使用容器漂移,动态伸缩特性。

  • HostPort:在yaml文件中spec.containers.ports部分指定, 通过HostPort设置,您可以请求暴露主机上的任何可用端口。 指定HostPort后,在部署pod容器的主机上,该端口会暴露给外部访问。在hostIP:HostPort上的流量将会被路由到pod容器的专用端口。HostPort模式不再需要创建一个service yaml。

    image-20191028010959415

  • Port Forward: 通过端口转发访问集群中的应用程序 ,这种类型的连接对于调试很有帮助。 配置方法:当前机器必须配置有目标集群的kubectl config:

    #测试本地机器8099端口转发到目标nginx pod的80端口:
    kubectl port-forward -n default nginx 8099:80
    
  • ClusterIPClusterIP本身是不会对集群外暴露服务的,但是却单单可以通过K8s Proxy API来访问。Proxy API是一种特殊的API,Kube-APIServer只代理这类API的HTTP请求,然后将请求转发到某个节点上的Kubelet进程监听的端口上,最后有该端口上的REST API响应请求。在集群外部访问,需要借助于kubectl,所以集群外的节点必须配置了经过认证的kubectl,可以参看kubectl的配置章节,这种方式要求访问节点必须具备受认证的kubectl,所以只能用做调试使用。

    kubectl proxy --port=8080
    #通过selfLink即可访问,注意这里的服务名需要指定https
    curl http://localhost:8080/api/v1/namespaces/kube-system/services/https:kubernetes-  dashboard:/proxy/
    
  • NodePort: NodePort是基于ClusterIP的方式来暴露服务的,不过不需要kubectl的配置,他是在每一个node上都监听同一个端口,该端口的访问都会被引导到Service的ClusterIP 。NodePort的默认范围是:30000-32767。从Kubernetes集群外部,进入NodeIP:NodePort的流量将被定向到工作负载(由kube-proxy组件完成这项工作)。NodeIP可以是Kubernetes集群中任何节点的IP地址。

    image-20191028011053757

  • LoadBalancer:只能在Service上定义,LoadBalancer是一些特定公有云提供的负载均衡器,需要特定的云服务商提供,比如:AWS、Azure、OpenStack 和 GCE (Google Container Engine)。

  • Ingress:与之前的暴露集群Service的方式都不同,Ingress其实不是一种服务。它位于多个服务之前,充当集群中的智能路由器或入口点。类似于Nginx提供的反向代理,其实官方推荐的方式就是Nginx的实现方式。Ingress是自kubernetes1.1版本后引入的资源类型。必须要部署Ingress controller才能创建Ingress资源,Ingress controller是以一种插件的形式提供。使用 Ingress 时一般会有三个组件:

    1. 反向代理负载均衡器
    • 反向代理负载均衡器很简单,类似nginx,haproxy;在集群中反向代理负载均衡器可以自由部署,可以使用 Replication Controller、Deployment、DaemonSet 等等,推荐DaemonSet 的方式部署
    1. Ingress Controller
    • Ingress Controller 实质上可以理解为是个监视器,Ingress Controller 通过不断地跟 kubernetes API 打交道,实时的感知后端 service、pod 等变化,比如新增和减少 pod,service 增加与减少等;当得到这些变化信息后,Ingress Controller 再结合下文的 Ingress 生成配置,然后更新反向代理负载均衡器,并刷新其配置,达到服务发现的作用。
    1. Ingress
    • Ingress简单理解就是个规则定义;比如说某个域名对应某个 service,即当某个域名的请求进来时转发给某个 service;这个规则将与 Ingress Controller 结合,然后 Ingress Controller 将其动态写入到负载均衡器配置中,从而实现整体的服务发现和负载均衡。
  • IngressRoute:Traefik 1.x只能够通过 [Kubernetes Ingress provider] 来支持 Kubernetes,这是严格意义上的 Kubernetes Ingress 控制器。但是,由于社区表达了需要从 Traefik 优秀特性中获益而不需要使用大量的 annotations 注解,最终Traefik 2.x实现了一个名为 IngressRoute 的自定义资源类型,可以提供更好的方式来配置对 Kubernetes 集群的访问。

    我们将会在下一篇文章中详细讲解使用Traefik 2.0.2的IngressRoute来实现各种对外暴露内部服务的功能。
    更好的方式来配置对 Kubernetes 集群的访问。

    我们将会在下一篇文章中详细讲解使用Traefik 2.0.2的IngressRoute来实现各种对外暴露内部服务的功能。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值