侧边栏壁纸
博主头像
再见理想博主等级

只争朝夕,不负韶华

  • 累计撰写 112 篇文章
  • 累计创建 64 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

K8S 核心概念

再见理想
2022-07-05 / 0 评论 / 0 点赞 / 429 阅读 / 8,848 字

一,简介

容器化部署的优点:

  • 快速创建/部署应用:与VM虚拟机相比,容器镜像的创建更加容易。
  • 持续开发、集成和部署:提供可靠且频繁的容器镜像构建/部署,并使用快速和简单的回滚(由于镜像不可变性)。
  • 开发和运行相分离:在build或者release阶段创建容器镜像,使得应用和基础设施解耦。
  • 开发,测试和生产环境一致性:在本地或外网(生产环境)运行的一致性。
  • 云平台或其他操作系统:可以在 Ubuntu、RHEL、 CoreOS、on-prem、Google Container Engine或其它任何环境中运行。
  • Loosely coupled,分布式,弹性,微服务化:应用程序分为更小的、独立的部件,可以动态部署和管理。
  • 资源隔离
  • 资源利用:更高效

容器化部署方式给带来很多的便利,但是也会出现一些问题,比如说:

  • 一个容器故障停机了,怎么样让另外一个容器立刻启动去替补停机的容器;
  • 当并发访问量变大的时候,怎么样做到横向扩展容器数量;

这些容器管理的问题统称为容器编排问题,为了解决这些容器编排问题,就产生了一些容器编排的软件:

  • Swarm:Docker自己的容器编排工具;
  • Mesos:Apache的一个资源统一管控的工具,需要和Marathon结合使用;
  • Kubernetes:Google开源的的容器编排工具;

二,kubernetes 是什么

Kubernetes 是容器集群管理系统,可以实现容器集群的自动化部署、自动扩缩容、维护等功能,它的目的是实现资源管理的自动化。

通过 Kubernetes,可以快速部署应用、快速扩展应用、无缝对接新的应用功能、节省资源,优化硬件资源的使用等。

Kubernetes 特点

  • 可移植:支持公有云,私有云,混合云,多重云;
  • 可扩展:模块化,插件化,可挂载,可组合;
  • 自动化:自动部署,自动重启,自动复制,自动伸缩扩展;

Kubernetes 主要功能:

  • 自我修复:一旦某一个容器崩溃,能够在1秒中左右迅速启动新的容器;
  • 弹性伸缩:可以根据需要,自动对集群中正在运行的容器数量进行调整;
  • 服务发现:服务可以通过自动发现的形式找到它所依赖的服务;
  • 负载均衡:如果一个服务起动了多个容器,能够自动实现请求的负载均衡;
  • 版本回退:如果发现新发布的程序版本有问题,可以立即回退到原来的版本;
  • 存储编排:可以根据容器自身的需求自动创建存储卷;

Kubernetes 相关概念:

Master:集群控制节点,每个集群需要至少一个master节点负责集群的管控;
Node:工作节点,由master分配容器到这些node工作节点上,然后node节点上的docker负责容器的运行;
Pod:kubernetes的最小控制单元,容器都是运行在pod中的,一个pod中可以有1个或者多个容器;
Controller:控制器,通过它来实现对pod的管理,比如启动pod、停止pod、伸缩pod的数量等等;
Service:pod对外服务的统一入口,下面可以维护者同一类的多个pod;
Label:标签,用于对pod进行分类,同一类pod会拥有相同的标签;
NameSpace:命名空间,用来隔离pod的运行环境,可实现多套环境的资源隔离或者多租户的资源隔离

三,kubernetes 组件

一个kubernetes集群主要是由控制节点(master)、工作节点(node)构成,每个节点上都会安装不同的组件。

3.1,master 组件

Master组件提供集群的管理控制中心。(管理)

  • ApiServer:资源操作的唯一入口,接收用户输入的命令,提供认证、授权、API注册和发现等机制;
  • Scheduler:负责集群资源调度,按照预定的调度策略将Pod调度到相应的node节点上;
  • ControllerManager:负责维护集群的状态,比如程序部署安排、故障检测、自动扩展、滚动更新等;
  • Etcd:是Kubernetes提供默认的存储系统,保存所有集群数据,使用时需要为etcd数据提供备份计划。

3.2,节点 Node 组件

集群的数据平面,负责为容器提供运行环境 ( 干活 )

  • Kubelet:负责维护容器的生命周期,即通过控制docker,来创建、更新、销毁容器;
  • KubeProxy:负责提供集群内部的服务发现和负载均衡;
  • Docker:负责节点上容器的各种操作;

image.png

下面,以部署一个nginx服务来说明kubernetes系统各个组件调用关系:

  1. 首先要明确,一旦kubernetes环境启动之后,master和node都会将自身的信息存储到etcd数据库中;
  2. 一个nginx服务的安装请求会首先被发送到master节点的apiServer组件;
  3. apiServer组件会调用scheduler组件来决定到底应该把这个服务安装到哪个node节点上;
    在此时,它会从etcd中读取各个node节点的信息,然后按照一定的算法进行选择,并将结果告知apiServer
  4. apiServer调用controller-manager去调度Node节点安装nginx服务;
  5. kubelet接收到指令后,会通知docker,然后由docker来启动一个nginx的pod。pod是kubernetes的最小操作单元,容器必须跑在pod中至此;
  6. 一个nginx服务就运行了,如果需要访问nginx,就需要通过kube-proxy来对pod产生访问的代理;

这样,外界用户就可以访问集群中的nginx服务了

四,资源管理

4.1,资源管理介绍

在kubernetes中,所有的内容都抽象为资源,用户需要通过操作资源来管理 kubernetes。用户可以在集群中部署各种服务,也就是在kubernetes 集群中运行一个个的容器。

kubernetes 的最小管理单元是 pod 而不是容器,所以只能将容器放在Pod中,通过Pod控制器来管理Pod的。
Pod可以提供服务之后,就要考虑如何访问Pod中服务,kubernetes提供了 Service 资源实现这个功能。当然,如果Pod中程序的数据需要持久化,kubernetes 还提供了各种存储系统。

image.png

学习kubernetes的核心,就是学习如何对集群上 Pod、Pod控制器、Service、存储等各种资源进行操作!


4.2,资源管理方式

  • 命令式对象管理:直接使用命令去操作kubernetes资源
kubectl run nginx-pod --image=nginx:1.17.1 --port=80
  • 命令式对象配置:通过命令配置和配置文件去操作kubernetes资源
kubectl create/patch -f nginx-pod.yaml
  • 声明式对象配置:通过apply命令和配置文件去操作kubernetes资源,多用于创建或更新资源。
kubectl apply -f nginx-pod.yaml

4.3,有状态和无状态

无状态
● 是指该服务运行的实例不会在本地存储需要持久化的数据,并且多个实例对于同一个请求响应的结果是完全一致的;
● 多个实例可以共享相同的持久化数据。例如:nginx实例,tomcat实例等;
● 相关的k8s资源有:ReplicaSet、ReplicationController、Deployment等,由于是无状态服务,所以这些控制器创建的 pod 序号都是随机值。并且在缩容的时候并不会明确缩容某一个pod,而是随机的,因为所有实例得到的返回值都是一样,所以缩容任何一个 pod 都可以;


有状态
需要数据存储功能的服务、或者指多线程类型的服务,队列等。(mysql、kafka、zookeeper等);
● 每个实例都需要有自己独立的持久化存储,并且在k8s中是通过申明模板来进行定义。持久卷申明模板在创建 pod 之前创建,绑定到 pod 中,模板可以定义多个;
● 相关的k8s资源为:statefulSet,由于是有状态的服务,所以每个pod都有特定的名称和网络标识。比如pod名是由statefulSet名+有序的数字组成(0、1、2…);
● 在进行缩容操作的时候,可以明确知道会缩容哪一个pod,从数字最大的开始。


五,重要概念

5.1,Namespace

image.png
Namespace 是 kubernetes 系统中的一种非常重要资源,它的主要作用是用来实现多套环境的资源隔离或者多租户的资源隔离

默认情况下,kubernetes集群中的所有的Pod都是可以相互访问的。但是在实际中,可能不想让两个Pod之间进行互相的访问,那此时就可以将两个Pod划分到不同的namespace下。kubernetes通过将集群内部的资源分配到不同的Namespace中,可以形成逻辑上的"组",以方便不同的组的资源进行隔离使用和管理。

可以通过kubernetes的授权机制,将不同的namespace交给不同租户进行管理,这样就实现了多租户的资源隔离。此时还能结合kubernetes的资源配额机制,限定不同租户能占用的资源,例如CPU使用量、内存使用量等等,来实现租户可用资源的管理。

5.2,Pod

image.png

Pod 是 Kubernetes创建或部署的最小/最简单的基本单位,一个Pod代表集群上正在运行的一个进程。

一个Pod封装一个应用容器(也可以有多个容器),存储资源、一个独立的网络IP以及管理控制容器运行方式的策略选项。Pod代表部署的一个单位:Kubernetes中单个应用的实例,它可能由单个容器或多个容器共享组成的资源。

每个 Pod 被分配一个独立的IP地址,Pod 中的每个容器共享网络命名空间,包括 IP 地址和网络端口。Pod 内的容器可以使用 localhost 相互通信。当 Pod 中的容器与 Pod 外部通信时,他们必须协调如何使用共享网络资源(如端口)。


Kubernetes中的Pod使用可分两种主要方式:

  • Pod中运行一个容器。“one-container-per-Pod”模式是Kubernetes最常见的用法; 在这种情况下,你可以将Pod视为单个封装的容器,但是Kubernetes是直接管理Pod而不是容器。
  • Pods中运行多个需要一起工作的容器。Pod可以封装紧密耦合的应用,它们需要由多个容器组成,它们之间能够共享资源,这些容器可以形成一个单一的内部service单位 - 一个容器共享文件,另一个“sidecar”容器来更新这些文件。Pod将这些容器的存储资源作为一个实体来管理。

5.2.1,pod的生命周期

我们一般将pod对象从创建至终的这段时间范围称为pod的生命周期,它主要包含下面的过程:

  1. pod创建过程;
  2. 运行初始化容器(init container)过程;
  3. 运行主容器(main container);
    1. 容器启动后钩子(post start)、容器终止前钩子(pre stop);
    2. 容器的存活性探测(liveness probe)、就绪性探测(readiness probe);
  4. pod终止过程;

5.2.1.1,pod的几种状态
  • 挂起(Pending):apiserver已经创建了pod资源对象,但它尚未被调度完成或者仍处于下载镜像的过程中;
  • 运行中(Running):pod已经被调度至某节点,并且所有容器都已经被kubelet创建完成;
  • 成功(Succeeded):pod中的所有容器都已经成功终止并且不会被重启;
  • 失败(Failed):所有容器都已经终止,但至少有一个容器终止失败,即容器返回了非0值的退出状态;
  • 未知(Unknown):apiserver无法正常获取到pod对象的状态信息,通常由网络通信失败所导致;

5.2.1.2,pod的创建过程

  1. 用户通过 kubectl 或其他 api 客户端提交需要创建的 pod 信息给 apiServer
  2. apiServer开始生成pod对象的信息,并将信息存入 etcd,然后返回确认信息至客户端;
  3. apiServer 开始反映 etcd 中的 pod 对象的变化,其它组件使用 watch 机制来跟踪检查 apiServer 上的变动;
  4. scheduler 发现有新的 pod 对象要创建,开始为 Pod 分配主机并将结果信息更新至 apiServer
  5. node 节点上的 kubelet 发现有 pod 调度过来,尝试调用 docker 启动容器,并将结果回送至apiServer;
  6. apiServer 将接收到的 pod 状态信息存入 etcd 中;

5.2.1.3,pod的终止过程
  1. 用户向 apiServer 发送删除 pod 对象的命令;
  2. apiServcer 中的 pod 对象信息会随着时间的推移而更新,在宽限期内(默认30s),pod 被视为 dead;
  3. 将 pod 标记为 terminating 状态;
  4. kubelet 在监控到 pod 对象转为 terminating 状态的同时启动 pod 关闭过程;
  5. 端点控制器监控到 pod 对象的关闭行为时将其从所有匹配到此端点的 service 资源的端点列表中移除;
  6. 如果当前 pod 对象定义了 preStop 钩子处理器,则在其标记为 terminating 后即会以同步的方式启动执行;
  7. pod 对象中的容器进程收到停止信号;
  8. 宽限期结束后,若 pod 中还存在仍在运行的进程,那么 pod 对象会收到立即终止的信号;
  9. kubelet 请求 apiServer 将此 pod 资源的宽限期设置为 0 从而完成删除操作,此时 pod 对于用户已不可见;

5.2.1.4,初始化容器

初始化容器是在pod的主容器启动之前要运行的容器,主要是做一些主容器的前置工作,它具有两大特征:

  1. 初始化容器必须运行完成直至结束,若某初始化容器运行失败,那么kubernetes需要重启它直到成功完成
  2. 初始化容器必须按照定义的顺序执行,当且仅当前一个成功之后,后面的一个才能运行

5.2.1.5,钩子函数

钩子函数能够感知自身生命周期中的事件,并在相应的时刻到来时运行用户指定的程序代码。kubernetes 在主容器的启动之后和停止之前提供了两个钩子函数:

  • postStart:容器创建之后执行,如果失败了会重启容器;
  • preStop :容器终止之前执行,执行完成之后容器将成功终止,在其完成之前会阻塞删除容器的操作;

5.2.1.6,容器探测

容器探测用于检测容器中的应用实例是否正常工作,是保障业务可用性的一种传统机制。如果探测到实例的状态不符合预期,那么kubernetes就会把该问题实例移除。kubernetes提供了两种探针来实现容器探测,分别是:

  • liveness probes:存活性探针,用于检测应用实例当前是否处于正常运行状态,如果不是,k8s会重启容器;
  • readiness probes:就绪性探针,用于检测应用实例当前是否可以接收请求,如果不能,k8s不会转发流量;

探测方式:

  • Exec 命令:在容器内执行一次命令,如果命令执行的退出码为 0,则认为程序正常,否则不正常;
  • TCPSocket:将会尝试访问一个用户容器的端口,如果能够建立这条连接,则认为程序正常,否则不正常;
  • HTTPGet:调用容器内Web应用的URL,如果返回的状态码在200和399之间,则认为程序正常,否则不正常;

5.2.1.7,重启策略

在上一节中,一旦容器探测出现了问题,kubernetes 就会对容器所在的 Pod 进行重启,其实这是由pod的重启策略决定的,pod 的重启策略有 3 种,分别如下:

  • Always:容器失效时,自动重启该容器,这也是默认值;
  • OnFailure: 容器终止运行且退出码不为 0 时重启;
  • Never: 不论状态为何,都不重启该容器;

5.2.2,pod 调度

在默认情况下,kubernetes 提供了四大类调度方式:

  • 自动调度:运行在哪个节点上完全由 Scheduler 经过一系列的算法计算得出;
  • 定向调度:NodeName、NodeSelector;
  • 亲和性调度:NodeAffinity、PodAffinity、PodAntiAffinity;
  • 污点(容忍)调度:Taints、Toleration;

5.2.2.1,定向调度

定向调度,指的是利用在pod上声明 nodeName 或者 nodeSelector,以此将 Pod 调度到期望的 node 节点上。注意,这里的调度是强制的,这就意味着即使要调度的目标Node不存在,也会向上面进行调度,只不过pod运行失败而已。

nodeName:强制约束将Pod调度到指定的Name的Node节点上;

nodeSelector:将pod调度到添加了指定标签的node节点上;


5.2.2.2,亲和性调度

定向调度中存在一些问题,如果没有满足条件的Node,那么Pod将不会被运行,即使在集群中还有可用Node列表也不行,这就限制了它的使用场景。

基于上面的问题,kubernetes还提供了一种亲和性调度(Affinity)。它在NodeSelector的基础之上的进行了扩展,可以通过配置的形式,优先选择满足条件的Node进行调度,如果没有再调度到不满足条件的节点上,使调度更加灵活。

Affinity主要分为三类:

  • nodeAffinity(node亲和性): 以node为目标,解决pod可以调度到哪些node的问题;
  • podAffinity(pod亲和性) : 以pod为目标,解决pod可以和哪些已存在的pod部署在同一个拓扑域中的问题;
  • podAntiAffinity(pod反亲和性) : 以pod为目标,解决pod不能和哪些已存在pod部署在同一个拓扑域中的问题;

关于亲和性(反亲和性)使用场景的说明:

亲和性:如果两个应用频繁交互,那就有必要利用亲和性让两个应用的尽可能的靠近,这样可以减少因网络通信而带来的性能损耗。

反亲和性:当应用的采用多副本部署时,有必要采用反亲和性让各个应用实例打散分布在各个node上,这样可以提高服务的高可用性。

5.2.2.3,污点调度

前面的调度方式都是站在Pod的角度上,通过在Pod上添加属性,来确定Pod是否要调度到指定的Node上,其实我们也可以站在Node的角度上,通过在Node上添加污点属性,来决定是否允许Pod调度过来。

Node被设置上污点之后就和Pod之间存在了一种相斥的关系,进而拒绝Pod调度进来,甚至可以将已经存在的Pod驱逐出去。

污点的格式为:key=value:effect, key和value是污点的标签,effect描述污点的作用,支持如下三个选项:

  • PreferNoSchedule:kubernetes 将尽量避免把Pod调度到具有该污点的Node上,除非没有其他节点可调度0;
  • NoSchedule:kubernetes 将不会把Pod调度到具有该污点的Node上,但不会影响当前Node上已存在的Pod;
  • NoExecute:kubernetes 将不会把Pod调度到具有该污点的Node上,同时也会将Node上已存在的Pod驱离;

5.2.2.4,容忍调度

上面介绍了污点的作用,我们可以在node上添加污点用于拒绝pod调度上来,但是如果想将一个pod调度到一个有污点的node上去,这就要使用到容忍

污点就是拒绝,容忍就是忽略,Node通过污点拒绝pod调度上去,Pod通过容忍忽略拒绝。


5.2.3,Pod 控制器

在 kubernetes 中,Pod 是最小的控制单元,但是 kubernetes 很少直接控制Pod,一般都是通过 Pod 控制器来完成的。pod 控制器用于 pod 的管理,确保 pod 资源符合预期的状态,当 pod 的资源出现故障时,它会基于指定策略重新编排Pod。

Deployment 是 kubernetes的其中一类Pod控制器。


在kubernetes中,有很多类型的pod控制器,每种都有自己的适合的场景,常见的有下面这些:

  • ReplicaSet:保证副本数量一直维持在期望值,并支持pod数量扩缩容,镜像版本升级;
  • Deployment:通过控制ReplicaSet来控制Pod,并支持滚动升级、回退版本;
  • Horizontal Pod Autoscaler:可以根据集群负载自动水平调整Pod的数量,实现削峰填谷;
  • DaemonSet:在集群中的指定Node上运行且仅运行一个副本,一般用于守护进程类的任务;
  • Job:它创建出来的pod只要完成任务就立即退出,不需要重启或重建,用于执行一次性任务;
  • Cronjob:它创建的Pod负责周期性任务控制,不需要持续后台运行;
  • StatefulSet:管理有状态应用;

5.2.3.1,ReplicaSet(RS)

ReplicaSet 的主要作用是保证一定数量的pod正常运行,它会持续监听这些Pod的运行状态,一旦Pod发生故障,就会重启或重建。同时支持对pod数量的扩缩容镜像版本的升降级


5.2.3.2,Deployment

为了更好的解决服务编排的问题,kubernetes在V1.2版本开始,引入了Deployment控制器。**这种控制器并不直接管理pod,而是通过管理 ReplicaSet 来间接管理Pod,**即:Deployment管理 ReplicaSet,ReplicaSet 管理Pod。

Deployment主要功能有下面几个:

  • 支持ReplicaSet的所有功能;
  • 支持发布的停止、继续;
  • 支持滚动升级和回滚版本;

扩缩容

# 命令
# kubectl scale deploy pod 控制器名称 --replicas=副本数  -n 命名空间
# 或 通过修改控制器实现
# kubectl edit deploy pod 控制器名称 -n 命名空间

镜像更新

deployment支持两种更新策略:重建更新和滚动更新,可以通过strategy指定策略类型,支持两个属性:

strategy:指定新的Pod替换旧的Pod的策略, 支持两个属性:
  type:指定策略类型,支持两种策略
    Recreate:在创建出新的Pod之前会先杀掉所有已存在的Pod
    RollingUpdate:滚动更新,就是杀死一部分,就启动一部分,在更新过程中,存在两个版本Pod;
  rollingUpdate:当type为RollingUpdate时生效,用于为RollingUpdate设置参数,支持两个属性:
    maxUnavailable:用来指定在升级过程中不可用Pod的最大数量,默认为25%。
    违规词汇: 用来指定在升级过程中可以超过期望的Pod的最大数量,默认为25%。

版本回退

deployment支持版本升级过程中的暂停、继续功能以及版本回退等诸多功能,通过kubectl rollout命令实现。

kubectl rollout: 版本升级相关功能,支持下面的选项:

  • status 显示当前升级状态
  • history 显示 升级历史记录
  • pause 暂停版本升级过程
  • resume 继续已经暂停的版本升级过程
  • restart 重启版本升级过程
  • undo 回滚到上一级版本(可以使用–to-revision回滚到指定版本)

5.2.3.3,Horizontal Pod Autoscaler

在前面的课程中,我们已经可以实现通过手工执行kubectl scale命令实现 Pod 扩容或缩容,但是这显然不符合Kubernetes 自动化、智能化的定位目标。

Kubernetes期望可以实现通过监测Pod的使用情况,实现pod数量的自动调整,于是就产生了Horizontal Pod Autoscaler(HPA)这种控制器。


HPA 的实现原理

HPA 可以获取每个 Pod 利用率,可以是内存或CPU,然后和HPA中定义的指标进行对比,同时计算出需要伸缩的具体值,最后实现Pod的数量的调整。

其实HPA与之前的Deployment一样,也属于一种Kubernetes资源对象,它通过追踪分析RC控制的所有目标Pod的负载变化情况,来确定是否需要针对性地调整目标Pod的副本数。


5.2.4,DaemonSet(DS)

DaemonSet类型的控制器可以保证在集群中的每一台(或指定)节点上都运行一个副本。一般适用于日志收集、节点监控等场景。DaemonSet控制器的特点:

  • 每当向集群中添加一个节点时,指定的 Pod 副本也将添加到该节点上
  • 当节点从集群中移除时,Pod 也就被垃圾回收了

5.2.5,Job

Job,主要用于负责批量处理短暂的一次性任务。Job特点如下:

  • 当Job创建的pod执行成功结束时,Job将记录成功结束的pod数量;
  • 当成功结束的pod达到指定的数量时,Job将完成执行;

5.2.6,CronJob

CronJob 可以在特定的时间点去运行job任务。


5.4,Label

Label 是 kubernetes 系统中的一个重要概念,它的作用是在资源上添加标识,用来对它们进行区分和选择。
Label的特点:

  • 一个Label会以key/value键值对的形式附加到各种对象上,如Node、Pod、Service等等
  • 一个资源对象可以定义任意数量的Label ,同一个Label也可以被添加到任意数量的资源对象上去
  • Label通常在资源对象定义时确定,当然也可以在对象创建后动态添加或者删除

可以通过Label实现资源的多维度分组,以便灵活、方便地进行资源分配、调度、配置、部署等管理工作。

  • 版本标签:“version”:“release”, “version”:“stable”…
  • 环境标签:“environment”:“dev”,“environment”:“test”,“environment”:“pro”
  • 架构标签:“tier”:“frontend”,“tier”:“backend”

标签定义完毕之后,还要考虑到标签的选择,这就要使用到 Label Selector,用于查询和筛选拥有某些标签的资源对象。


5.5,Service

在kubernetes中,pod是应用程序的载体,我们可以通过pod的ip来访问应用程序,但是pod
的ip地址不是固定的,这也就意味着不方便直接采用pod的ip对服务进行访问。

为了解决这个问题,kubernetes提供了Service资源,Service会对提供同一个服务的多个pod 进行聚合,并且提供一个统一的入口地址,通过访问Service的入口地址就能访问到后面的 pod服务。

Service在很多情况下只是一个概念,真正起作用的其实是kube-proxy服务进程,每个Node节点上都运行着一个kube-proxy服务进程。当创建Service的时候会通过api-server向etcd写入创建的service的信息,而kube-proxy会基于监听的机制发现这种Service的变动,然后它会将最新的Service信息转换成对应的访问规则


5.5.1,service 几种模式

5.5.1.1,userspace 模式

userspace 模式下,kube-proxy 会为每一个 Service 创建一个监听端口,发向 Cluster IP 的请求被 Iptables 规则重定向到 kube-proxy 监听的端口上,kube-proxy 根据 LB 算法选择一个提供服务的 Pod 并和其建立链接,以将请求转发到 Pod 上。

该模式下,kube-proxy 充当了一个四层负责均衡器的角色。由于 kube-proxy 运行在userspace 中,在进行转发处理时会增加内核和用户空间之间的数据拷贝,虽然比较稳定,但是效率比较低。


5.5.1.2,iptables 模式

iptables 模式下,kube-proxy为service 后端的每个 Pod 创建对应的 iptables 规则,直接将发向 Cluster IP 的请求重定向到一个 Pod IP。

该模式下 kube-proxy 不承担四层负责均衡器的角色,只负责创建 iptables 规则。该模式的优点是较 userspace 模式效率更高,但不能提供灵活的LB策略,当后端 Pod 不可用时也无法进行重试。


5.5.1.3,ipvs 模式

ipvs 模式和 iptables 类似,kube-proxy 监控 Pod 的变化并创建相应的 ipvs 规则,且 ipvs 相对 iptables 转发效率更高。除此以外,ipvs支持更多的LB算法。


5.5.2,Service 类型

Service 有以下几种类型:

  • ClusterIP默认值,它是Kubernetes系统自动分配的虚拟IP,只能在集群内部访问;
  • NodePort:将Service通过指定的Node上的端口暴露给外部,通过此方法,就可以在集群外部访问服务;它的工作原理其实就是将 service 的端口映射到 Node 的一个端口上,然后就可以通过 NodeIp:NodePort 来访问 service 了。
  • LoadBalancer:LoadBalancer 和 NodePort 很相似,目的都是向外部暴露一个端口,区别在于 LoadBalancer 会在集群的外部再来做一个负载均衡设备,而这个设备需要外部环境支持的,外部服务发送到这个设备上的请求,会被设备负载之后转发到集群中。
  • ExternalName: ExternalName类型的Service用于引入集群外部的服务,它通过externalName属性指定外部一个服务的地址,然后在集群内部访问此service就可以访问到外部的服务了。

EndPoint 是什么?

EndPoint 是 kubernetes 中的一个资源对象,存储在 etcd 中,用来暴露 service 对应的所有 pod 的访问地址,它是根据 service 配置文件中 selector 描述产生的。


负载均衡策略

对 Service 的访问讲被分发到了 Pod 上去,目前 kubernetes 提供了两种负载分发策略:

  • 如果不定义,默认使用 kube-proxy 的策略,比如随机、轮询;

  • 基于客户端地址的会话保持模式,即来自同一个客户端发起的所有请求都会转发到固定的一个 Pod 上;此模式可以使在spec中添加sessionAffinity:ClientIP选项;


5.5.3,Ingress

官网:Ingress描述

在前面课程中已经提到,Service对集群之外暴露服务的主要方式有两种:NotePort和LoadBalancer,但是这两种方式,都有一定的缺点:

  • NodePort方式的缺点是会占用很多集群机器的端口,那么当集群服务变多的时候,这个缺点就愈发明显
  • LB方式的缺点是每个service需要一个LB,浪费、麻烦,并且需要kubernetes之外设备的支持

基于这种现状,kubernetes提供了Ingress资源对象,Ingress只需要一个NodePort或者一个LB就可以满足暴露多个Service的需求。工作机制大致如下图表示:


Ingress 是什么
Ingress 是对集群中服务的外部访问进行管理的 API 对象。Ingress 可为 Service 提供外部可访问的 URL、负载均衡流量、终止 SSL/TLS,以及基于名称的虚拟托管。

Ingress 核心概念

  • ingress:kubernetes中的一个对象,作用是定义请求如何转发到service的规则
  • ingress controller:具体实现反向代理及负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发,实现方式有很多,比如Nginx, Contour, Haproxy等等

Ingress 工作原理

Ingress 相当于一个 7 层的负载均衡器,它的工作原理类似于 Nginx,可以理解成在Ingress 里建立很多映射规则,Ingress Controller 通过监听这些配置规则并转化成Nginx 的反向代理配置 , 然后对外部提供服务



六,部署实战

通过K8S部署Halo博客

0

评论区