竹笋

首页 » 问答 » 常识 » 容器编排系统k8s之Service资源
TUhjnbcbe - 2023/11/6 21:14:00
白癜风诚信医院 http://m.39.net/disease/a_6359070.html

Service资源在k8s上主要用来解决pod访问问题;我们知道在k8s上pod由于各种原因重建,对于重建后的podip地址和名称都是变化的,这样一来使得我们访问pod就变得有些不便;为了解决pod访问能有一个固定的端点,在k8s上就是用service来解决的;简单来讲,service对象就是工作在节点上的一组iptables或ipvs规则,用于将到达service对象ip地址的流量调度转发至相应endpoint对象指向的ip地址和端口之上;

工作于每个节点的kube-proxy组件通过apiserver持续监控着各service及其关联的pod对象,并将其创建或变动实时反映至当前工作节点上相应的iptables或ipvs规则;其实service和pod或其他资源的关联,本质上不是直接关联,它依靠一个中间组件endpoint;endpoint主要作用就是引用后端pod或其他资源(比如k8s外部的服务也可以被endpoint引用);所谓endpoint就是ip地址+端口;

提示:在k8s上kube-proxy它会监视着apiserver上的service资源变动,及时将变动转化为本机的iptables或ipvs规则;对应客户端pod访问对应serverpod,报文首先会从本机的iptables或ipvs规则所匹配,然后再由对应规则逻辑把请求调度到对应的pod上;

service代理模式模式

在k8s上service代理模式有三种,早期的k8s版本(1.1之前包含1.1的版本)默认的代理模式为userspace,后面的版本(1.11起)默认代理模式为ipvs,如果对应ipvs的模块没有加载,它会自动降级为iptables;

userspace代理模式

提示:userspace是指Linux操作系统上的用户空间;在这种代理模型下iptables只是做转发并不调度,对应调度由kube-proxy完成;userspace这种调度模型用户请求从内核空间到用户空间再到内核空间,性能效率比较低下;

iptables代理模式

提示:iptables这种代理模式,对于每个service对象,kube-proxy会创建iptables规则直接捕获到达Clusterip和port的流量,并将其重定向至当前service对象的后端pod资源;对于每个endpoint对象,service资源会为其创建iptables规则并关联至挑选的后端pod资源对象;相对于userspace代理模式来说,该模式用户请求无须在用户空间和内核空间来回切换,因此效率高效;此种模式下kube-proxy就只负责生成iptalbes规则,调度有iptables规则完成;

ipvs代理模式

提示:ipvs代理模式,kube-proxy会跟踪apiserver上service和endpoint对象的变动,据此来调用netlink接口创建ipvs规则,并确保与apiserver中的变动保持同步;这种模式与iptables的模式不同之处仅在于其请求调度由ipvs完成,余下其他功能仍由iptables完成;比如流量捕获,nat等等功能都会由iptables完成;ipvs代理模型类似iptables模型,ipvs构建于netfilter的钩子函数之上,但它使用hash表作为底层数据结构并工作于内核空间,因此具有流量转发速度快,规则同步性能好的特点,除此之外,ipvs还支持众多调度算法,比如rr,lc,sh,dh等等;

service类型

在k8s上service的类型有4种,第一种是clusterIP,我们在创建service资源时,如果不指定其type类型,默认就是clusterip;第二种是NodePort类型,第三种是LoadBalancer,第四种是ExternalName;不同类型的service,其功能和作用也有所不同;

ClusterIP

提示:如上所示,ClusterIP类型的service就是在k8s节点上创建一个满足serviceip地址的iptables或ipvs规则;这种类型的service的ip地址一定是我们在初始化集群时,指定的service网络(10.96.0.0/12)中的地址;这也意味着这种类型service不能被集群外部客户端所访问,仅能在集群节点上访问;

NodePort

提示:NodePort类型的service,是建构在ClusterIP的基础上做的扩展,主要解决了集群外部客户端访问问题;如上图所示,NodePort类型service在创建时,它会每个节点上创建一条DNAT规则,外部客户端访问集群任意节点的指定端口,都会被DNAT到对应的service上,从而实现访问集群内部Pod;对于集群内部客户端的访问它还是通过ClusterIP进行的;NodePort类型service与ClusterIP类型service唯一不同的是,NodePort类型service能够被外部客户端所访问,在集群每个节点上都有对应的DNAT规则;

LoadBalancer

提示:LoadBalancer这种类型的service是在NodePort的基础上做的扩展,这种类型service只能在底层是云环境的K8s上创建,如果底层是非云环境,这种类型无法实现,只能手动搭建反向代理进行对NodePort类型的service进行反代;它主要解决NodePort类型service被集群外部访问时的端口映射以及负载;

ExternalName

提示:ExternalName这种类型service主要用来解决对应service引用集群外部的服务;我们知道对于service来说,它就是一条iptables或ipvs规则,对于后端引用的资源是什么,取决于对应endpoint关联的是什么资源的ip地址和端口;如果我们需要在集群中使用集群外部的服务,我们就可以创建ExternalName类型的service,指定后端关联外部某个服务端ip地址或域名即可;它的工作流程如上图所示,在集群内部客户端访问对应service时,首先要去core-DNS上查询对应域名的ip地址,然后再根据dns返回的ip地址去连接对应的服务;使用这种类型service的前提是对应的coredns能够连接到外部网络解析对应的域名;

service资源的创建

示例:创建ClusterIP类型的service

提示:在创建service资源时,主要要需要在spec字段中指定port和targetPort,port是service的端口,targetPort是后端资源的端口;其次就是需要定义标签选择器,这里的标签选择器用selector字段指定,它的值是一个字典,即kv键值对;默认不指定type类型就是使用的ClusterIP类型,默认不指定ClusterIP就表示自动生成对应的ClusterIP;

应用资源清单

验证:访问对应的ClusterIP看看是否能够访问到对应的资源?

提示:可以看到访问对应serviceip地址能够访问到对应的pod;

查看service详细信息

提示:可以看到对应service的type类型为ClusterIP,port为80,targetPort为80,endpoins对应了3个podip地址+targetPort;其实在创建service时,系统默认会创建一个同service相同名称的endpoints;

查看endpoints

提示:可以看到ngx-dep-svc这个endpoint关联了3个podip地址;

示例:创建NodePort类型service

提示:创建nodeport类型service需要在spec字段中使用type字段来指定其类型为NodePort;只有type的值为NodePort,对应ports字段中指定的nodePort才有意义,默认不指定它会随机生成一个端口,指定nodePort就相当于固定了端口;通常不建议指定nodePort;

应用资源配置清单

提示:可以看到nodeport类型的service,对应port就有两个值,后面的就是外部客户端访问集群内部资源的端口;

验证:使用浏览器访问k8s任意节点的端口,看看是否能够访问到对应的pod?

提示:可以看到集群外部客户端可以通过访问集群节点上的一个端口实现访问对应集群内部资源;

示例:创建ExternalName类型service

提示:以上配置清单表示创建一个名为

的Service,对应Service的类型为ExternalName;引用外部服务为

应用资源配置清单

提示:可以看到应用配置清单以后,service详细信息中,没有标签,没有选择器,没有ip地址;只有externalName和对应targetPort;

测试:把dns服务器地址指向coredns,然后访问对应服务名称,看看对应服务是否会有响应?

提示:可以看到访问对应服务名称,响应码是,说明我们的请求被代理出去了;

进入任意pod内部,使用nslookup查询coredns上对应服务名称是否能够解析?

提示:可以看到对应服务名称也能正常被解析;

示例:创建无头service

提示:所谓无头service是指没有clusterIP的service,我们知道clusterip是service作为访问后端pod的入口,那么没有clusterip,它怎么访问后端pod呢?没有ip地址我们只能使用名称来访问;在k8s上无头service默认会被coredns把对应名称的service解析为后端关联的多个pod地址;

应用资源配置清单

提示:可以看到对应service没有clusterIP;

验证:进入任意pod,使用名称访问service,看看对应名称是否能够访问到pod?

提示:在pod内部使用名称service名称可以访问到对应的pod;

验证:查看coredns是否将对应service名称解析为对应拥有service指定的标签选择器的podip呢?

提示:可以看到coredns把对应名称解析成了3个地址;这三个地址都是对应pod上拥有service指定的标签选择器上的标签的podip地址;

配置k8s使用ipvs代理模式

编写加载ipvs相关模块脚本

提示:以上脚本主要做了一件事,就是把ipvs_mods_dir所指定的目录下的所有模块加载到内核;

给脚本添加执行权限

复制该脚本到其他节点

提示:把脚本放在/etc/sysconfig/modules目录下以点modules结尾的脚本,在系统重启以后,它会自动执行对应目录下的脚本;

执行脚本,加载模块

验证:查看对应模块是否加载?

提示:能够看到以上信息表示ipvs相关模块已经加载;

编辑kube-proxy的配置

修改mode字段的值为“ipvs”,然后保存退出

删除现有k8skube-proxypod

提示:kube-proxy是一个ds控制器所管理的pod,它能容忍主节点上的污点在集群每个节点上创建对应pod;我们手动删除它,对应控制器会重新新建对应数量的pod,从而实现应用新配置的目的;生产环境不提倡这样修改,应该在集群初始化前就规划好使用哪种代理模式;

验证:在集群任意节点安装ipvs客户端工具,看看是否有对应的ipvs规则生成?

安装ipvsadm

使用ipvsadm查看是否生成的有ipvs规则?

提示:能够看到有ipvs规则生成,说明此时k8s就是使用的ipvs代理模式;

1
查看完整版本: 容器编排系统k8s之Service资源