首页 > 其他分享 >K8S Service基础详解

K8S Service基础详解

时间:2022-10-17 22:33:21浏览次数:53  
标签:Service service 端口 访问 详解 集群 Pod K8S


一起学kubernetes系列(2)‌

本篇文章我们介绍Kubernetes Service的各个类型,各类端口的含义,向外部暴露内部服务的方式。

Service 介绍

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

  1. ​apiVersion: v1​
  2. ​kind: Service​
  3. ​metadata:​
  4. ​ name: nginx-svc​
  5. ​ labels:​
  6. ​ app: nginx​
  7. ​spec:​
  8. ​ type: ClusterIP​
  9. ​ ports:​
  10. ​ - port: 80​
  11. ​ targetPort: 80​
  12. ​ selector:​
  13. ​ 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,实现一层负载均衡。
  1. ​#查询Service与endpoints​
  2. ​kubectl get service,endpoints --all-namespaces​

Service的各种Port与IP

PORT

  • ​port​​​:这是service的端口,通过 ​​clusterip​​和 ​​port​​即可访问到service服务,返回为pod tag,注意必须ip和端口缺一不可!
  • ​nodePort​​​: ​​nodePort​​的范围是30000-32767,集群内不允许冲突,在service的yaml中设置 , 一旦设置了 ​​nodePort​​,所有的node主机都会监听这个端口,也就是说使用集群内任意一台 ​​nodeIP:nodePort​​都可以访问到service服务,同样,在集群内此端口就只能被设置一次。
  • ​containerPort​​:容器的实际端口,Pod内的容器与外部进行通信的端口,Pod中的所有容器共享一个网络IP,容器间可直接用localhost访问。
  • ​targetPort​​​:Pod上的端口,从 ​​port​​和 ​​nodePort​​上到来的数据最终经过kube-proxy流入到后端pod的 ​​targetPort​​上进入容器。所以需要在service的yaml中定义,来告诉service。
  • ​hostPort​​​: ​​hostPort​​是直接将容器的端口与所调度的节点上的端口路由,这样用户就可以通过宿主机的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

  • ​PodIP​​:Pod的IP,每个Pod启动时,会自动创建一个镜像为gcr.io/googlecontainers/pause的容器,Pod内部其他容器的网络模式使用container模式,并指定为pause容器的ID,即:networkmode: "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。
  • K8S Service基础详解_nginx
  • ​PortForward​​:通过端口转发访问集群中的应用程序 ,这种类型的连接对于调试很有帮助。配置方法:当前机器必须配置有目标集群的kubectl config:
  1. ​ #测试本地机器8099端口转发到目标nginx pod的80端口:​
  2. ​ kubectl port-forward -n default nginx 8099:80​
  • ​ClusterIP​​​: ​​ClusterIP​​本身是不会对集群外暴露服务的,但是却单单可以通过K8s Proxy API来访问。Proxy API是一种特殊的API,Kube-APIServer只代理这类API的HTTP请求,然后将请求转发到某个节点上的Kubelet进程监听的端口上,最后有该端口上的REST API响应请求。在集群外部访问,需要借助于kubectl,所以集群外的节点必须配置了经过认证的kubectl,可以参看kubectl的配置章节,这种方式要求访问节点必须具备受认证的kubectl,所以只能用做调试使用。
  1. ​ kubectl proxy --port=8080​
  2. ​ #通过selfLink即可访问,注意这里的服务名需要指定https​
  3. ​ 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地址。
  • K8S Service基础详解_反向代理_02
  • ​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 的方式部署
  • Ingress Controller
  • Ingress Controller 实质上可以理解为是个监视器,Ingress Controller 通过不断地跟 kubernetes API 打交道,实时的感知后端 service、pod 等变化,比如新增和减少 pod,service 增加与减少等;当得到这些变化信息后,Ingress Controller 再结合下文的 Ingress 生成配置,然后更新反向代理负载均衡器,并刷新其配置,达到服务发现的作用。
  • 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​​来实现各种对外暴露TCP,HTTPS内部服务及自动生成证书等功能。
    K8S Service基础详解_负载均衡_03



标签:Service,service,端口,访问,详解,集群,Pod,K8S
From: https://blog.51cto.com/starsliao/5764547

相关文章

  • 一起学kubernetes系列(3)‌K8S的WebUI:Dashboard&Kuboard
    ​本篇介绍2套kubernetes的WEBUI管理控制台Kubernetes官方Dashboard部署KubernetesDashboard是Kubernetes的官方WebUI。使用KubernetesDashboard,您可以:向Kubern......
  • 【Azure 应用服务】登录App Service 高级工具 Kudu站点的 Basic Auth 方式
    问题描述从AzureAppService的页面中,直接跳转到高级管理工具Kudu站点(https://<yourappservicename>.scm.chinacloudsites.cn/)时,可以自动使用AAD用户(即登录Azure门......
  • Selenium4Web自动化3-等待机制详解
    一、sleepsleep(timeout)是设定一个固定的等待时长,代码运行到此处,会强行进行等待指定的时间,使用方便的同时,效率最低,不建议使用。缺点:不能准确把握需要等待的时间(有时操......
  • 【蓝桥杯】模拟赛详解,冲刺国赛
    ......
  • Python __new__()方法详解
    __new__()是一种负责创建类实例的静态方法,它无需使用staticmethod装饰器修饰,且该方法会优先__init__()初始化方法被调用。一般情况下,覆写__new__()的实现将会使用合......
  • Python函数(函数定义、函数调用)用法详解
    Python 中函数的应用非常广泛,前面章节中我们已经接触过多个函数,比如input()、print()、range()、len()函数等等,这些都是Python的内置函数,可以直接使用。除了可以直接......
  • Python while循环语句详解
    Python 中,while循环和if条件分支语句类似,即在条件(表达式)为真的情况下,会执行相应的代码块。不同之处在于,只要条件为真,while就会一直重复执行那段代码块。while语句的......
  • Python for循环及用法详解
    Python 中的循环语句有2种,分别是while循环和for循环,前面章节已经对while做了详细的讲解,本节给大家介绍for循环,它常用于遍历字符串、列表、元组、字典、集合等序......
  • Python len()函数详解:获取字符串长度或字节数
    Python 中,要想知道一个字符串有多少个字符(获得字符串长度),或者一个字符串占用多少个字节,可以使用len函数。len函数的基本语法格式为:len(string)其中string用于指定要......
  • Python split()方法详解:分割字符串
    Python 中,除了可以使用一些内建函数获取字符串的相关信息外(例如len()函数获取字符串长度),字符串类型本身也拥有一些方法供我们使用。注意,这里所说的方法,指的是字符串类......