K8s基础8——svc基础使用、应用暴露、iptables代理、ipvs代理

news/2024/10/30 23:13:52/

文章目录

  • 一、Service基本了解
  • 二、Service定义与创建
    • 2.1 相关命令
    • 2.2 yaml文件参数大全
    • 2.3 创建svc
      • 2.3.1 两种创建方式类比
      • 2.3.2 验证集群内A应用访问B应用
      • 2.3.3 将集群外服务定义为K8s的svc
      • 2.3.4 分配多个端口
    • 2.4 常用三种类型
      • 2.4.1 ClusterIP(集群内部访问)
      • 2.4.2 NodePort(浏览器访问)
      • 2.4.3 LoadBalancer
    • 2.5 svc支持的协议
  • 三、svc负载均衡
    • 3.1 iptables模式
    • 3.2 ipvs模式

一、Service基本了解

Service存在的意义?

  • 引入Service主要是解决Pod的动态变化,通过创建Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上。
  • 若提供服务的容器应用是分布式,所以存在多个pod副本,而Pod副本数量可能在运行过程中动态改变,比如水平扩缩容,或者服务器发生故障Pod的IP地址也有可能发生变化。当pod的地址端口发生改变后,客户端再想连接访问应用就得人工干预,很麻烦,这时就可以通过service来解决问题。

概念:

  • Service主要用于提供网络服务,通过Service的定义,能够为客户端应用提供稳定的访问地址(域名或IP地址)和负载均衡功能,以及屏蔽后端Endpoint的变化,是K8s实现微服务的核心资源。

svc特点:

  1. 服务发现,防止阴滚动升级等因素导致Pod IP发生改变而失联,找到提供同一个服务的Pod。
  2. 负载均衡,定义一组Pod的访问策略。
    在这里插入图片描述

svc与pod关系:

  • pod在创建时,与资源没有明确关联,通过service标签和pod标签相匹配来以此关联。
  • 可以通过endpoints来查看关联的pod。
    在这里插入图片描述

二、Service定义与创建

2.1 相关命令

命令说明
kubectl create service clusterip web --tcp=80:80命令创建svc
kubectl apply -f service.yaml定义yaml文件创建svc
kubectl expose deployment webapp命令创建svc,需要提前创建deploy
kubectl get service查看svc

2.2 yaml文件参数大全

参数释义是否必选
version版本号,例如v1必选
kind资源对象类型,例如pod、deployment、service必选
metadata元数据必选
metadata.name对象名称必选
metadata.namespace对象所属的命名空间,默认值为 default必选
metadata.labels自定义标签列表
metadata.annotation自定义注解列表
spec详细定义描述必选
spec.selectorLabel Selector 配置,将选择具有指定 Label 标签的 Pod 作为管擦绡啷谎理范围必选
spec.typesvc类型,指定svc访问方式,默认为ClusterIP。
1、ClusterP:虚拟服务IP地址,用于K8s集群内部的Pod访问,在 Node 上kube-proxy通过设置的iptables 规则进行转发。
2、NodePort:对外部客户端提供访问应用使用。
3、LoadBalancer:使用外接负载均衡器完成到服务的负载分发,用于公有云环境。
必选
spec.clusterlP虚拟服务的IP 地址。
当type=ClusterIP 时,若不指定,则系统进行自动分配,也可以手工指定;
当type=LoadBalancer时,需要指定。
spec.sessionAffinity是否支持 Session,可选值为 ClientP,默认值为 None。
ClientIP表示将同一个客户端(根据客户端的IP 地址决定)的访问请求都转发到同一个后端 Pod。
spec.ports定义端口设置列表。
spec.ports.name端口名称
spec.ports.protocol端口协议,支持TCP、HTTP、UDP、SCTP等等,默认值为TCP
Spec.ports.portsvc端口
spec.ports.targetPort容器端口
spec.ports.nodePort当spec.type=NodePort 时,指定映射到宿主机的端口号
Status当spec.ype=lodBalaner 时,设置外部负均衡器的地址,用于公有云环境
status.loadBalancer外部负载均衡器
status.loadBalancer.ingress外部负载均衡器
status.loadBalancer.ingress.ip外部负载均衡器IP
status.loadBalancer.ingress.hostname外部负载均衡器的主机名
spec.selector指定关联Pod的标签必选

2.3 创建svc

1.创建一个service,名称为seride-demo,指定类型为clusterip,第一个80是svc端口,第二个80是容器端口。

[root@k8s-master bck]# kubectl  create service  clusterip service-demo  --tcp=80:80

2.查看svc
在这里插入图片描述

2.3.1 两种创建方式类比

1.先通过kubectl expose方式创建,先创建一个deployment,此时的pod名称为demo1,标签为app=demo1。
在这里插入图片描述
2.创建一个svc,名为demo1,看是否能和demo1的pod关联上。

[root@k8s-master bck]# kubectl  create svc clusterip demo1 --tcp=80:80

3.此时查看demo1的svc和demo1的pod关联上了,是因为创建的svc标签是和deployment创建的pod标签一样。
在这里插入图片描述

2.3.2 验证集群内A应用访问B应用

  • 我们创建一个svc后,会随机分配和cluster-ip,配合svc端口,可以在任何一个节点上访问其他应用。

在这里插入图片描述

1.创建一个pod,配合上面创建的svc demo1来模拟前端访问后端。这里的bs为前端,demo1为后端。进入bs容器,通过clusterip:svc端口来访问demo1前端网页。
在这里插入图片描述

2.3.3 将集群外服务定义为K8s的svc

  • 将一个Kubernetes集群外部的已知服务定义为Kubernetes内的一个Service,供集群内的其他应用访问。

应用场景:

  • 已部署的一个集群外服务,例如数据库服务、缓存服务等。
  • 其他Kubernetes集群的某个服务。
  • 迁移过程中对某个服务进行Kubernetes内的服务名访问机制的验证。

1.准备一个集群外的服务,我这里在192.168.130.147上部署一个nginx服务。

[root@k8s-node2 ~]# docker run -d --name nginx1 -p 80:80 nginx

在这里插入图片描述
2.此时我想将这个nginx服务定义成K8s集群内部的svc,供集群内的其他应用访问。

[root@k8s-master ~]# cat svc.yaml 
---
apiVersion: v1
kind: Service
metadata:name: qingjun1
spec:ports:- protocol: TCPport: 80targetPort: 80---
apiVersion: v1
kind: Endpoints
metadata:name: qingjun1   ##与svc名称一致。
subsets:- addresses:- ip: 192.168.130.147    ##外部服务地址ports:- port: 80     ##外部服务访问端口[root@k8s-master ~]# kubectl  apply -f svc.yaml 

3.查看,此时就会会创建一个svc并分配clusterip,同时endpoint将其与外部服务关联。
在这里插入图片描述
4.此时进入测试容器验证,可以访问到外部服务。

[root@k8s-master ~]# kubectl  run bs --image=busybox -- sleep 24h

在这里插入图片描述

2.3.4 分配多个端口

  • 多端口Service定义:对于某些服务,需要公开多个端口,Service也需要配置多个端口定义,通过端口名称区分。

1.先创建1个pod内有两个容器,一个是Nginx,一个是tomcat。现在需要通过访问80端口到达nginx,访问svc的8080端口到达tomcat。
在这里插入图片描述
2.创建svc,编辑yaml文件,添加多个端口。

[root@k8s-master bck]# cat svc.yaml 
apiVersion: v1
kind: Service
metadata:name: web-multi
spec:ports:# nginx- name: 80-80port: 80       ##代理nginx80端口。protocol: TCPtargetPort: 80# tomcat- name: 88-8080port: 88        ##代理tomcat8080端口。protocol: TCPtargetPort: 8080selector:app: web-multitype: ClusterIP

在这里插入图片描述
3.通过另外一个pod验证,进入bs容器,访问web-multi里的容器端口。访问88端口,则返回tomcat;访问80端口,则返回nginx。

在这里插入图片描述
在这里插入图片描述

  • ep相当于svc的小弟,就相当于rs是deployment的小弟,帮忙连接多个pod。

在这里插入图片描述

2.4 常用三种类型

类型描述
ClusterIP集群内部使用(Pod)
NodePort对外暴露应用(浏览器)
LoadBalancer对外暴露应用,将Service映射到一个已存在的负载均衡器的IP地址上,适用公有云
ExternalName将Service映射为一个外部域名地址,通过externalName字段进行设置。

2.4.1 ClusterIP(集群内部访问)

  • 作用:默认分配一个稳定的虚拟IP,即VIP,仅可被集群内部的客户端应用访问。
  • 原理图:
    在这里插入图片描述

2.4.2 NodePort(浏览器访问)

作用:在每个节点上启用一个端口来暴露服务,可以在集群外部访问。也会分配一个稳定内部集群IP地址。
基本常识

  • 访问地址:<任意NodeIP>:
  • 端口范围:30000-32767
  • 默认情况下,Node的kube-proxy会在全部网卡(0.0.0.0)上绑定NodePort端口号。也可以通过配置启动参数“–nodeport-addresses”指定需要绑定的网卡IP地址,多个地址之间使用逗号分隔。

原理图
在这里插入图片描述
注意事项:

  • NodePort会在每台Node上监听端口接收用户流量,在实际情况下,对用户暴露的只会有一个IP和端口,那这么多台Node该使用哪台让用户访问呢?
  • 这时就需要前面加一个公网负载均衡器为项目提供统一访问入口了。比如在公网机器上部署nginx做负载均衡,配置配置文件upstream ——> 网站A端口30001,upstream2——> 应用服务B端口30002。
    在这里插入图片描述
  • yaml文件配置模板
spec:type: NodePort  ##修改此处ports:- port: 80 protocol: TCP targetPort: 80 nodePort: 30009    ##添加此行,指定端口,也可以不指定,使用随机端口。selector: app: web

1.配置svc的yaml文件,指定NodePort类型,使用随机端口。

##这里没有指定端口,后面是随机生成一个端口。
[root@k8s-master bck]# vim svc.yaml 
apiVersion: v1
kind: Service
metadata:name: web-demo1
spec:ports:# nginx- name: 80-80port: 80protocol: TCPtargetPort: 80selector:app: demo1type: NodePort    ##指定类型。

2.导入yaml文件,查看svc随机端口为32580。
在这里插入图片描述
3.浏览器访问验证。
在这里插入图片描述
4.使用指定端口。

[root@k8s-master bck]# cat svc.yaml 
apiVersion: v1
kind: Service
metadata:name: web-demo1
spec:ports:# nginx- name: 80-80port: 80protocol: TCPtargetPort: 80nodePort: 30003   ##指定端口。selector:app: demo1type: NodePort  ##指定类型。

在这里插入图片描述

2.4.3 LoadBalancer

  • 作用:与NodePort类似,在每个节点上启用一个端口来暴露服务。除此之外,Kubernetes会请求底层云平台(例如阿里云、腾讯云、AWS等)上的负载均衡器,将每个Node([NodeIP]:[NodePort])作为后端添加进去。

  • 原理图
    在这里插入图片描述

2.5 svc支持的协议

协议是否支持
TCP默认网络协议,支持所有类型的svc。
UDP可用于大多数类型的svc,LoadBalancer类型取决于云服务商对UDP的支持。
HTTP取决于云服务商是否支持HTTP和实现机制。
PROXY取决于云服务商是否支持HTTP和实现机制。
SCTP现已默认启用,如需关闭该特性,则需要设置kube-apiserver的启动参数–feature-gates=SCTPSupport=false进行关闭。
  • 定义AppProtocol字段,用于标识后端服务在某个端口号上提供的应用层协议类型,例如HTTP、HTTPS、SSL、DNS等。
  • 需要设置kube-apiserver的启动参数–feature-gates=ServiceAppProtocol=true进行开启,然后在Service或Endpoint的定义中设置AppProtocol字段指定应用层协议的类型。

三、svc负载均衡

实现原理:

  • 当一个Service对象在K8s集群中被定义出来时,集群内的客户端应用就可以通过服务IP访问到具体的Pod容器提供的服务了。从服务IP到后端Pod的负载均衡机制,则是由每个Node上的kube-proxy负责实现的。

实现负载均衡的2种方式:

  1. kube-proxy的代理模式,通过启动参数–proxy-mode设置。
  2. 会话保持机制。设置sessionAffinity实现基于客户端IP的会话保持机制,即首次将某个客户端来源IP发起的请求转发到后端的某个Pod上,之后从相同的客户端IP发起的请求都将被转发到相同的后端Pod上。

kube-proxy的代理模式分类:

  1. userspace模式:用户空间模式,由kube-proxy完成代理的实现,效率最低,不推荐。
  2. iptables模式:kube-proxy通过设置Linux Kernel的iptables规则,实现从Service到后端Endpoint列表的负载分发规则,效率较高。用此模式时需要给pod设置健康检查,这样可以避免某个后端Endpoint不可用导致客户端请求失败。
  3. ipvs模式:1.11版本推出,kube-proxy通过设置Linux Kernel的netlink接口设置IPVS规则,转发效率和支持的吞吐率达到最高。ipvs模式要求Linux Kernel启用IPVS模块,如果操作系统未启用IPVS内核模块,kube-proxy则会自动切换至iptables模式。支持负载均衡策略如下:
    • rr:round-robin,轮询。
    • lc:least connection,最小连接数。
    • dh:destination hashing,目的地址哈希。
    • sh:source hashing,源地址哈希。
    • sed:shortest expected delay,最短期望延时。
    • nq:never queue,永不排队。
  4. kernelspace模式:Windows Server上的代理模式。

Iptables模式和IPVS模式对比:

  • iptables:灵活、功能强大;规则遍历匹配和更新,呈线性时延
  • IPVS:工作在内核态,有更好的性能;调度算法丰富:rr,wrr,lc,wlc,ip hash…

概念图:在这里插入图片描述
数据包传输流程:

  • 客户端 ->NodePort/ClusterIP(iptables/Ipvs负载均衡规则) -> 分布在各节点Pod

查看负载均衡规则:

  • iptables模式:iptables-save |grep < SERVICE-NAME >
  • ipvs模式:ipvsadm -L -n

项目流程:

  • 项目a:用户——> LB(基于域名分流 a.com) ——> service nodeport 30001 ——> 一组pod(多副本)(相当于项目本身)
  • 项目b:用户——> LB(基于域名分流 b.com)——> service nodeport 30002 ——> 一组pod(多副本)(相当于项目本身)
  • 项目c:用户——> LB(基于域名分流 c.com)——> service nodeport 30003 ——> 一组pod(多副本)(相当于项目本身)

提问:

  • 而这里我们就要看看,我们浏览器访问svc(http://192.168.130.146:30003)是怎么转发到容器内的?
    在这里插入图片描述

3.1 iptables模式

1.根据svc名称,在工作节点上查看iptables规则。

在这里插入图片描述
在这里插入图片描述
2.将两条规则复制出来分析。(第一步:流量入口)

第一步:浏览器访问30003端口,转发到服务器上的网络协议栈,再转发到该服务器的iptables来处理,根据iptables规则一条条处理。

  • -A KUBE-NODEPORTS -p tcp -m comment --comment “default/web-demo1:80-80” -m tcp --dport 30003 -j KUBE-EXT-72T25B5TU2KEWYA6

第二步:处理完第一条规则,再处理第二条,这里就是访问cluster IP,访问pod。

  • -A KUBE-SERVICES -d 10.104.171.31/32 -p tcp -m comment --comment “default/web-demo1:80-80 cluster IP” -m tcp --dport 80 -j KUBE-SVC-72T25B5TU2KEWYA6

3.这里给demo1pod扩容增加2个副本,好看出效果。

[root@k8s-master bck]# kubectl  scale deployment demo1 --replicas=3

4.根据iptables规则链过滤查看负载均衡结果。(第二步:负载均衡)
在这里插入图片描述

1.第一个请求第一个规则的权重概率为33%。
-A KUBE-SVC-72T25B5TU2KEWYA6 -m comment --comment "default/web-demo1:80-80 -> 10.244.169.143:80" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-WNIKZVEWSTDE4VLZ2.第二个请求第二个规则权重为50%,因为第一个规则已经请求了,就剩第二、第三个请求了。
-A KUBE-SVC-72T25B5TU2KEWYA6 -m comment --comment "default/web-demo1:80-80 -> 10.244.36.87:80" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-ZM2JCM2TG2VXDQG33.从第三个请求第三个规则权重为100%,因为此时就剩下最后一条规则,所以请求概率为100%。
-A KUBE-SVC-72T25B5TU2KEWYA6 -m comment --comment "default/web-demo1:80-80 -> 10.244.36.89:80" -j KUBE-SEP-CSYMMWI2AY6NBPWB

5.查看其中一个规则链,最后转发到对应容器里。(第三步:转发到容器里)
在这里插入图片描述

3.2 ipvs模式

  • 使用此种模式需要手动去修改,因为默认是iptables模式。不同的k8s集群搭建方式,其修改方式不同。
  1. kubeadm方式修改ipvs模式:
    第一步:修改配置文kube-proxy件参数。
    kubectl edit configmap kube-proxy -n kube-system...
    mode: “ipvs“
    ...
    第二步:删除该组Pod,重建所有节点。
    kubectl delete pod kube-proxy-btz4p -n kube-system
    
    • 注意事项:
    1. kube-proxy配置文件以configmap方式挂载存储。
    2. 如果让所有节点生效,需要重建所有节点kube-proxy pod
  2. 二进制方式修改ipvs模式:
    第一步:编辑修改配置文件。
    vi kube-proxy-config.yml 
    mode: ipvs
    ipvs:scheduler: "rr“
    第二步:重启kube-proxy。
    systemctl restart kube-proxy
    

1.查看配置文件位置。

[root@k8s-master bck]# kubectl  get configmap -n kube-system

在这里插入图片描述
2.在线编辑kube-proxy文件,修改参数为ipvs模式。

[root@k8s-master bck]# kubectl edit configmaps kube-proxy -n kube-system

在这里插入图片描述
3.此时需要删除这组pod重建,相当于重启。我这里只删除了一个节点,是为了验证对比效果,正常情况下是要重启所有节点的。

[root@k8s-master bck]# kubectl  delete pod kube-proxy-vkfkh -n kube-system

在这里插入图片描述
4.在删除的kube-proxy容器所在节点上验证,我这里删除的是node2节点上的kube-proxy,重启后ipvs模式生效;node1节点没有删除,也就没有重启,依然还是iptables模式。使用ipvs模式验证需要安装ipvsadm。

yum -y install ipvsadm
  • 查看node1节点没有显示,是因为还是采用的iptables模式。

在这里插入图片描述

  • 查看node2节点,此时为ipvs模式就显示出路由数据。当访问node2节点IP:30003时,最后路由到列出来的对应容器里。

在这里插入图片描述

  • 访问cluster ip时,就转发到对应的容器里。

在这里插入图片描述


http://www.ppmy.cn/news/62072.html

相关文章

持续测试:DevOps时代质量保证的关键

在 DevOps 时代&#xff0c;持续测试已成为质量保证的一个重要方面。近年来&#xff0c;软件开发方法论发生了快速转变。随着 DevOps 的出现&#xff0c;已经发生了向自动化和持续集成与交付 (CI/CD) 的重大转变。传统的质量保证方法已不足以满足现代软件开发实践的需求。持续测…

基于微信小程序的酒店预定管理系统设计与实现

第1章 绪论 1 1.1开发背景与意义 1 1.2开发方法 1 1.3论文结构 1 2系统开发技术与环境 3 2.1 系统开发语言 3 2.2 系统开发工具 3 2.3 系统页面技术 3 2.4 系统数据库的选择 4 2.5 系统的运行环境 4 2.5.1 硬件环境 4 2.5.2 软件环境 4 3系统分析 5 3.1可行性分析 5 3.1.1 经济…

JUC并发编程与源码分析笔记13-AbstractQueuedSynchronizer之AQS

前置知识 公平锁和非公平锁可重入锁自旋思想LockSupport数据结构之双向链表设计模式之模板设计模式 AQS入门级别理论知识 是什么 AbstractQueuedSynchronizer&#xff1a;抽象的队列同步器。 用来实现锁或其他同步器组件的公共基础部分的抽象实现&#xff0c;是重量级基础框…

IDP中的黄金路径究竟是什么?

在云原生时代&#xff0c;开发人员面临着越来越多的工具、技术、思维方式的选择&#xff0c;给他们带来了极大的认知负担和工作量。为了提高开发人员的开发效率与开发体验&#xff0c;一些头部科技公司开始建立自己的内部开发者平台&#xff08;IDP&#xff09;。在之前的文章我…

阿里云CentOS服务器安装Redis教程(一步步操作)

使用阿里云服务器ECS安装Redis数据库流程&#xff0c;操作系统为CentOS 7.6镜像&#xff0c;在CentOS上安装Redis 4.0.14&#xff0c;云服务器选择的是持久内存型re6p实例&#xff0c;新手站长分享阿里云CentOS服务器安装Redis流程方法&#xff1a; 目录 在CentOS系统中部署R…

C++容器适配器stack和queue(含deque,priority_queue)

目录 1.容器适配器 1.1 什么是适配器 1.2 STL标准库中stack和queue底层结构 1.3 deque 1.3.1 deque原理介绍&#xff08;了解&#xff09; 1.3.2 deque优点和缺点 1.3.3 为什么选择deque作为stack和queue的底层默认容器 2. stack介绍和使用 2.1 stack介绍 2.2 stack使用 2.3 …

删除lpt1.css.asp或com8.index.asp这类文件的方法_asp木马无法删除解决办法

aux|prn|con|nul|com1|com2|com3|com4|com5|com6|com7|com8|com9|lpt1|lpt2|lpt3|lpt4|lpt5|lpt6|lpt7|lpt8|lpt9 但是可以通过cmd的copy命令实现&#xff1a; D:\wwwroot>copy rootkit.asp \\.\D:\wwwroot\lpt6.80sec.asp 前面必须有 \\.\ 已复制 1 个文件。 D…

K8S之自定义Controller

简介 在此之前我们先来了解下kubernetes的两个概念"声明式API"和"控制器模式"。"声明式API"核心原理就是当用户向kubernetes提交了一个API对象的描述后&#xff0c;Kubernetes会负责为你保证整个集群里各项资源的状态&#xff0c;都与你的API对象…