当前位置: 首页 > news >正文

Kubernetes service 基于工作原理的实验

1.ClusterIP 实验                

 

元数据 当前service的名字

 命名空间 default

期望:

  工作模式 ClusterIP  默认 ClusterIP

标签选择器  : pod 的标签 做子集运算 selector 必须是pod的 子集就可以 匹配上

然后定义我们当前你的负载均衡集群端口

端口给个名字 :http

集群端口 80

后端真实服务器的端口 80

1.IPVS多种工作方式

1.NAT模式 

这种模式好处在于 后端端口跟集群端口可以不一样,缺点在于我们当前的流量,还必须要经过ipvs的调度器本身 不管是入栈还是出栈

2.DR模式 直接路由模式

它的好处在于回程流量不需要经过负载接收器,本身压力会更小 缺点在于 它可能需要对我们当前的ARP的响应和通况行为做设定  而且后端端口和集群负载均衡的端口 必须一致

3.TUN隧道模式

这个缺点在于 当前它的性能会比较低,因为需要跨多个物理公网环境,而且还需要做数据报文的二次封装

优点在于 可以跨公网网络进行集聚化的组建

4.fullnat 模式

当前kubeproxy 默认是以ipvs  的 NAT模式 进行工作的

大家可以明确的发现 当前我们kubernetes集群创建的service 它的集群端口和后端真实服务器端口可以不一致

大家会有一个疑问,NAT没有DR性能那么强吗,为什么不用DR

其实每一个机器上的ipvs的规则 只会被当前机器的客户端所访问,如果客户端要访问服务器端的话它会借助本地的ipvs规则,去导向到它到它 那如果这个节点的客户端,它不会访问到我节点的ipvs

再加上每个kubernetes 节点最大pod 数量,所以我们可以确认每个机器的ipvs集群,它的规模访问根本不会超过300个,那在这种情况下 你说我不管是nat模式好还是DR模式也好,有多少性能影响呢,

2.开始实验

kubectl create svc clusterip myapp --tcp=80:80 --dry-run -o yaml

这是以前的创建模式

测试创建导出资源清单

这样创建的方式默认是以自己service名字 为值 app 为key 作为pod 选择器 

 

1.创建deployment 

apiVersion: apps/v1
kind: Deployment
metadata:
 name: myapp-clusterip-deploy
 namespace: default
spec:
 replicas: 3
 selector:
  matchLabels:
   app: myapp
   release: stabel
   svc: clusterip
 template:
  metadata:
   labels:
    app: myapp
    release: stabel
    env: test
    svc: clusterip
  spec:
   containers:
     - name: myapp-container
       image: wangyanglinux/myapp:v1.0
       imagePullPolicy: IfNotPresent
       ports:
         - name: http
           containerPort: 80
       readinessProbe:
          httpGet:
           port: 80
           path: /index1.html
          initialDelaySeconds: 1
          periodSeconds: 3

ports 端口 设置name就是给 80起了一个别名 仅此而已 可以让service 访问 一个叫 http 的端口仅此而已

再给我们的mainC 加上就绪探测

kubectl apply -f myapp-deploy.yaml

发现未就绪

1.svc 选中pod的逻辑
  1.  pod初一就绪状态
  2. svc标签是pod标签的子集 (同一个名称空间下)

2.创建svc

apiVersion: v1
kind: Service
metadata:
 name: myapp-clusterip
 namespace: default
spec:
 type: ClusterIP
 selector:
  app: myapp
  release: stabel
  svc: clusterip
 ports:
  - name: http
    port: 80
    targetPort: 80

ports

  port 定义当前service负载均衡的端口 

  targetPort 是后端真实服务器的端口

windows部署kubectl 

参考以下链接

https://cloudmessage.top/archives/k8s-zai-windowszhong-shi-yong-kubectllian-jie-ji-qun

10.3.57.76这就是ipvs集群的 虚拟IP 也叫VIP  或叫集群IP 

3.未就绪原因

定义deployment 里面的pod 的规格的时候 去定义了就绪探测,http形式,访问的是pod的80端口里面的index1.html文件,但是在镜像中 故意 没有这个文件,所以无法就绪

因为不满足就绪

所以访问集群是访问不通的

我们可以看一下ipvs集群

ipvsadm -Ln

 

这里会有一个TCP的 集群 地址是10.3.57.76  和上面 svc 分配的 地址是一样的 算法 rr 轮询的方式负载均衡 

真实服务器为空 原因很简单 达到我的要求的没有

标签虽然都达到了,但是pod未就绪 所以不满足我的规则

往我们一个pod中加入index1.html文件 让其中一个就绪 

由于我们给第一个添加了index1.html  文件

所以它就绪了

这时候已经能够访问到了

看一下负载均衡结果

 4.我们又给第二个加上 index1.html文件

5.访问svc方式

1.通过cluseterip
kubectl get svc
 2.通过DNS插件

每一个service创建完成后都会去有一个DNS的域名在我们的插件中被解析 解析的结果就是当前此IP

1.安装一个工具 bind-utils
yum -y install bind-utils

bind 就是伯克利大学的 名字解析服务 utils 是他的工具包 我们可以得到一个DNS的测试工具

dig -t A myapp-clusterip.default.svc.cluster.local. @10.0.0.10

dig 后面跟-t 代表tcp进行解析  A 代表A记录  当前svc的名字.当前所在的名称空间.svc.默认域名

 默认域名是在我们集群内部去用的改不改其实说实话影响不大

这时候我们在后面 加上一个 @ 跟上我们另一个 IP  这个是 就是你要把这个域名进行A记录解析

找谁解析呢 那我们这边很显然找的是我们集群内部的DNS插件 我们可以通过

kubectl get pod -n kube-system | grep dns

大家就会发现有两个出现了   

当然我们可以加上 -o wide 看一下ip地址

kubectl get pod -n kube-system -o wide  | grep dns

 然后我们在看一下 ipvs 集群规则

ipvsadm -Ln

特别注意一下  kubernetes 已经帮我们创建了一个 ipvs 集群 已经被添加成了一个 10.0.0.10:53 的负载均衡集群了,别人帮你写好了 甚至底下还有UDP的

那对于DNS来说 默认一般tcp用于数据同步 UDP 用于我们的解析 当然如果多次采用UDP 解析不通过的话 也会允许到tcp解析 当然现在还有很多厂商呢 在基于http 协议封装的DNS解析过程 这种我们就不再赘述了

回到我们默认情况下,那也就意味着如果我们想要访问DNS服务的话 没必要去找这两个pod的IP,而是直接向10.0.0.10发起解析即可 反正有负载均衡帮我们找到最后的 两个DNS插件的 pod IP上 

当然由于你集群设置的参数可能不一样,那这个值也可能有所区别所以建议大家自己先按上面步骤查询一下

解析成功了 

解析完全一致 

当然也有人担心 那我创建的pod 能用这两个DNS服务器吗 别忘我们的物理机的DNS是我们自己指定的 但kubernetes及其内部的pod 它的默认DNS 都是只想到这两个DNS插件的IP上的,所以不需要我们配置 它就可以解析通过

2.找个pod来试一下
apiVersion: v1
kind: Pod
metadata:
  name: pod-demo
  namespace: default
  labels:
    app: myapp
spec:
  containers:
    - name: busybox-1
      image: wangyanglinux/tools:busybox
      command:
        - "/bin/sh"
        - "-c"
        - "sleep 3600"

这个镜像里是由我们对应的curl命令的

跑起来了 我们以它当客户端去访问一下当前的域名 

 kubectl exec -it pod-demo -- /bin/
wget http://myapp-clusterip.default.svc.cluster.local./hostname.html && cat hostname.html && rm -rf hostname.html

在我们pod内部本身默认就把我们的 DNS指向到了 我们的dns插件上了,所以你的域名是可以直接使用的 不需要再像dig 一样解析域名指向 我们的DNS插件 @哪个DNS服务器 

这就是我们两种访问当前service的方式

3.各有利弊

service没有创建 访问域名就可以知道它的ip地址 通过访问域名可以不需要知道IP

6.策略方式

默认为Cluster类型

 Local类型 与 Cluster类型
kubectl edit svc myapp-clusterip

 改成Local

1.进入我们测试pod的内部 再访问

会发现进入pod内部用 域名访问可以

但是出来后用 ip访问被拒绝了 

我们说一下Local的含义

只会路由你访问节点地址的Pod 由于我们是在master节点上面 调用 ip 

master上面根本没有允许pod 所以这样的流量会被丢弃掉

注意官方特别强调 Drop 

那如果学习过防火墙的 netfilter 的 你可以知道 我们不想让他访问 有两种处理方式 一种是Reject 一种是 Drop,  Reject是 直接拒绝 Drop是直接丢弃  不让进 这里采用的是Drop方式直接把流量丢弃掉

到node01 上面执行就能访问到了 而且只能访问 node01 上面的pod 

3.进阶理解

之前我们在自己学习ipvs或LVS的时候,我们应该有了解过其中的一个特性,我们叫持久化连接,

对于持久化连接它的作用是什么呢,可以将我们的用户请求 定向再一台机器上,当然我们需要加一个前缀 就在有限的时间内 将用户的请求定向到同一台机器  那当然有人可能会问  那这个跟 lvs的 SH算法有什么区别呢? 原地址散列,不也是将一个同样的客户请求 定向到同一台机器吗 但SH比较呆板 只要我们对于的hash表没有被清理 那这样的用户始终会被定向到同一台机器 根本不会去考虑它的重复的访问 包括负载是否均衡 可能会有这方面的问题

但是我们的持久化连接呢 它会在有限的时间内  我们会在定义持久化连接的时候 加一个-p 的选项

比如这条命令应该是这样的 

ipvsadm -A -t 192.168.72.100:80 -s rr -p120

-s 指定负载均衡算法

-p 指定持久化连接的时间 秒

那这样我们可以添加一个持久化连接

把客户定向到目标机器的有效时间 就是120 秒

当我们通过LVS去访问后端服务器的 比如 rs1 rs2 ,我们第一次过来访问的时候 我们持久化连接虽然开了 但在我的LVS里 没有你客户端和真实服务器的对应关系 那第一个我可能根据我的rr算法帮你定向在了rs1 的机器 定向完成后 我就会把你的客户端的标记  比如地址和端口 与真实服务器的进行绑定 进行映射 当然后面会出现一个有限时间 120秒  那这个秒会逐渐衰弱 119  118 倒计时 直到0 时 这条记录就被清除 如果衰减到60秒 客户端再一次来访问 我们是有此纪录的 所以根据记录 我会直接定向到rs1 的机器  如果衰减为 0 的话就被清楚 ,我就相当于第一次过来,又被负载均衡算法分配到某个机器上面又开始120 秒的倒计时

所以是在有限时间内将 源定向到同一台机器 这么一种的模式

相对我们的SH算法来说 会更灵活 更有效 目前主要的应用场景就是在于https的  请求里 

我们知道https如果要建立连接的话 前面需要比较多的一个沟通的过程比如确定我们SSL的版本

确定我们的加密算法 确定我们的密钥 后续才能进行加密访问  当我刚开始跟你建立了加密访问

结果我发生了一个请求以后  下一次我被定向到了一个台新的机器 我跟新的机器又需要重复的进行https的这么一个加密过程 是比较浪费资源的 所以在https的集群中 如果需要做负载均衡集群的话 那我们是完全可以 通过ipvs的持久化连接 去实现对应的功能 会更好用一些 

那这样的持久化功能 我们当时应该也学过对应的分类是吧  比如基于客户端持久化连接  基于端口连接 基于防火墙标记连接   那么这里我们就不再赘述了

如果想把lvs的持久化连接 引入到当前kubernetes集群内部的话 那这里会出现一个叫 会话亲和性 

说白了底层就是在使用ipvs的持久化连接 去实现 比较我们知道当前的service 它的4层实现 底层就是基于ipvs实现的 

4.基于ipvs实现持久化连接(实验)

1.先展示不加 这个持久化连接的结果 

先把上面改成Local的 配置改回来 

 这是他会负载到三个pod都去访问

也就是我们所谓的没有加 ipvs的持久化连接的结果

2.会话保持

如果加了 就叫会话保持

找到这个 默认 是None

 改成 ClientIP

如果我们要设置它的 持久化连接时间 

这个对象 下的这个字段 默认是3 小时 值必须要大于0  &&<=86400 一天

 

改完以后再次访问,他就持久化定向到了同一个机器上

不像刚才我们是不是在第一个和第二个反复横跳 因为当前的默认的算法是 rr

 当然我们也可以从底层的原理去看一下
ipvsadm -Ln

其他没有被持久化的 ip 是不是没有加 persistent 10800

代表我们当前的 这个 svc开启持久化连接了 

你可以将持久化时间调节低一点 但是有些不同内核版本的 ipvs  对于秒数比较低的支持不是那么理想

那么第一种工作模式就讲完了

2.NodePort 类型 实验

主要就是把集群内部的服务暴露给集群以外 

 如果是集群内部的互相沟通 我们更建议大家通过clusterip 去使用 原因很简单 nodeport 是一种升级版的cluseterip 不仅可以做到 clusterip 拥有的功能 还支持在当前的物理网卡上 去绑定一个物理端口 以此去实现外部访问 但是功能越多 相当于它消耗的代价就会越高 但如果你不需要集群外部的访问 又消耗了更多的一些额外资源 它肯定是不理想的 

1.实验前的准备

1.创建service NodePort 类型

nodeport 对于物理网卡上面的端口 一般要大于30000 但是可以在apiserver启动的时候 配置 来调节最小的端口

apiVersion: v1
kind: Service
metadata:
 name: myapp-nodeport
 namespace: default
spec:
 type: NodePort
 selector:
  app: myapp
  release: stabel
  svc: nodeport
 ports:
   - name: http
     port: 80
     targetPort: 80
     nodePort: 30010

如果ports 设置多个 

那么每个port 的name值 端口值 后端端口值 nodeport值必须一样 否则会引起冲突

port 代表是通过集群内部访问这个负载调度器 这个负载调度器的端口是多少 

targetPort 后端的真实服务器的端口号

nodePort 那这个代表的是我们当前的物理网卡上绑定的物理的端口号  当然默认情况下我们说过很多次了 最好是大于 30000以上 而且官方强烈不建议你去通过nodeport 手动去指定这个端口号 

你若不写官方会帮你自动去分配 这种是更理想的一种状态 防止我们端口号冲突 好那这就是一个nodeport的资源清单的一个解释

2.创建deployment

apiVersion: apps/v1
kind: Deployment
metadata:
 name: myapp-nodeport-deploy
 namespace: default
spec:
 replicas: 3
 selector:
  matchLabels:
   app: myapp
   release: stabel
   svc: nodeport
 template:
  metadata:
   labels:
    app: myapp
    release: stabel
    env: test
    svc: nodeport
  spec:
   containers:
    - name: myapp-container
      image: wangyanglinux/myapp:v1.0
      imagePullPolicy: IfNotPresent
      ports:
       - name: http
         containerPort: 80

2.访问测试  

下面是对内部的 上面是对外部 

在内部访问没有问题 

pod内部用DNS访问 也没有问题 

wget myapp-nodeport.default.svc.cluster.local./hostname.html && cat hostname.html && rm -rf hostname.html

 它相当于是支持我们当前 svc clusterip 类型的 所有功能 那额外的功能在哪里呢  就来自于物理网卡的此端口的集群 以外的访问

它是怎么去实现的呢 其实原理很简单 

我们看一下ipvs 集群 

ipvsadm -Ln

他把我当前的物理网卡 192.168.72.11的30010  做了一个负载均衡集群 负载到的依然是当前的每个节点真实的服务器

把172.17.0.1也做了  docker0的网卡

这都是我们当前可以的网卡信息

如果你机器有多块网卡的话它会把当前机器的每一块可用网卡的地址 都帮你写一个ipvs集群

ipvsadm -Ln 看到是本机的 ipvs集群

通过外界访问 依然能够访问到

 

好像默认开启了持久化 对外界浏览器,但在内部还不是持久化

每一个节点的物理网络的这个端口 都可以对此进行访问在真正的生产环境中 我们可能需要在外部再加一个调度器去负载到当前的每一个节点

以此保证当前任何一个节点死亡不会造成我们用户的访问中断 那万一你把用户直接定向过来了

节点死了,那不是造成不可用了嘛

3.注意

nodeport 有个和 clusterip 很像的 配置 就是 externalTrafficPolicy 默认是 Cluster 可以负载均衡到任意node,改成  Local 就会变成 只能访问当前node 下的pod

在ClusterIP 类型 中 internalTrafficPolicy 叫这个 是指 在 node 内部 访问 service,只能访问 当前node下的 pod

如果比如你要访问 master 但我master根本没有pod 那我就会把你的请求进行 Drop 掉 丢弃掉

好 我们的 NodePort 就讲完了

3.LoadBalancer 结构 类型 实验

我们说过 对于纯粹的 nodeport 它没有办法给我们解决高可用的问题

一般我们会在前面架一个调度器 可以是4层 可以是 7层

 可以用 F5 可以用 IPVS 可以用 nginx

有没有更加方便的方案呢 有但是 有个前提 必须工作在云的环境中 比如 阿里云 比如 百度云 

 这种方式只能以云的方式去使用

这是阿里云的 

 仅适用于公网的 云中

4.ExternalName结构

 

前面三种类型都需要依赖于底层的 ipvs 参与 但是这个 特别 ,不需要ipvs的参与,仅仅只是靠我们的DNS的插件

CNAME的别名机制去实现DNS的转换 我们只需要去找DNS插件去进行一个固定域名解析 ,他就可以帮我们解析到外部的这个服务的对应的具体的ip或域名上,当然如果外部的Mysql 的IP 或域名修改了 那我们只需要修改这个externalname 的 CNAME 的记录就可以了 后续所有的Tomcat 的pod 都不需要你去更改  相当于解耦了 

   

kind: Service
apiVersion: v1
metadata:
  name: my-service-1
  namespace: default
spec:
  type: ExternalName
  externalName: www.baidu.com

当pod内部请求 这个service 的域名 也就是 my-service-1.default.svc.cluster.local. 的时候 会解析成www.baidu.com

 那百度的解析结果给我

 

当然很显然一定是集群内部的pod 或者是集群上的工具去访问的  ,一定不能在集群以外使用 

集群以外的客户端并不会把他的DNS 指向到你集群内部的这么一个DNS插件上

 查看ipvs 的持久化记录

ipvsadm -lnc

相关文章:

  • IDEA 接入 Skywalking Agent ClassNotFoundException
  • 基于多二阶广义积分器的正负序谐波提取方法
  • 人体的三个 Bug
  • 全局引用,utils 目录下的文件打包并安装到系统Python环境中
  • 漏洞挖掘---迅饶科技X2Modbus网关-GetUser信息泄露漏洞
  • 基于javaweb的SSM公寓房屋出租系统设计与实现(源码+文档+部署讲解)
  • 五.ubuntu20.04 - ffmpeg推拉流以及Nginx、SRS本地部署
  • Maven 构建生命周期
  • React(六)React过渡动画-CSS编写方式
  • Altium Designer 24 PCB编辑器[设计]栏找不到[规则]选项而只有[Constraints Manager]选项
  • 【操作系统】内存泄漏 vs 内存碎片
  • 游戏开发中的贝塞尔曲线:感受丝滑的数学之美
  • UE学习记录part11
  • DHT11数字温湿度传感器驱动开发全解析(中) | 零基础入门STM32第八十七步
  • 回调后门基础
  • Day18 -实例:app信息收集工具(Appinfoscanner、Mobsf)的配置和使用
  • 从PDF到精准答案:Coze助力RAGFlow框架提升数据召回率
  • Java基本类型深度解析:从内存模型到高效编程实践
  • 【MinerU】可本地部署的PDF解析器
  • HCIP-6 DHCP
  • 建设班级网站/最佳磁力搜索天堂
  • 做外贸哪个英文网站好/杭州搜索引擎优化公司
  • 诸城做网站建设的/百度推广页面投放
  • 黑彩网站怎么做/市场调研报告范文2000
  • 软件外包公司绩效考核/关键词优化外包
  • 做劫持和攻击网站的手机不能视频吗/软文云