• [技术干货] K8s证书管理及其续期方法
    Kubernetes(K8s)是一个开源的容器编排系统,用于自动化部署、扩展和管理容器化应用程序。在K8s集群中,为了保证通信的安全性和可靠性,使用了多种证书来确保组件之间的身份验证和加密通信。本文将介绍K8s中的证书管理,以及当证书过期后如何进行续期。一、K8s证书概述K8s集群中的证书主要用于以下方面:API Server证书:用于API Server与客户端之间的通信加密和身份验证。Kubelet证书:用于Kubelet与API Server之间的通信加密和身份验证。etcd证书:用于etcd集群节点之间的通信加密和身份验证。这些证书通常具有一定的有效期,一般为1年。当证书过期后,如果不进行续期,将导致K8s集群中的组件之间无法正常通信,从而影响整个集群的稳定性和可用性。二、证书续期方法1. 手动续期手动续期证书是一种比较直接的方法,但操作相对繁琐。具体步骤如下:生成新证书:使用K8s提供的工具(如kubeadm)或第三方工具生成新的证书。替换旧证书:将新生成的证书替换掉集群中对应的旧证书。这通常涉及到修改配置文件、重启服务等操作。验证证书:确保新证书已生效,并且集群中的组件能够正常通信。2. 自动续期为了简化证书管理过程,K8s提供了自动续期的功能。具体实现方式依赖于所使用的证书管理方案,以下是一些常见的自动续期方法:(1) 使用kubeadm对于使用kubeadm初始化的K8s集群,可以通过kubeadm命令进行证书续期。kubeadm会自动检测集群中的证书过期情况,并提示用户进行续期操作。(2) 使用cert-managercert-manager是一个K8s原生的证书管理工具,它可以自动管理K8s集群中的TLS证书。通过配置cert-manager,可以自动检测证书过期情况,并在证书过期前生成新的证书,实现自动续期。(3) 使用第三方工具除了kubeadm和cert-manager外,还有一些第三方工具可以帮助实现K8s证书的自动续期。这些工具通常提供了丰富的功能和灵活的配置选项,可以根据实际需求进行选择。三、注意事项在进行证书续期时,需要注意以下几点:备份旧证书:在替换旧证书之前,务必备份好旧证书和相关配置文件,以便在出现问题时能够恢复到之前的状态。谨慎操作:证书替换涉及到集群的敏感信息和安全配置,因此在进行操作时务必谨慎,避免误操作导致集群故障。监控和告警:建议设置证书过期监控和告警机制,以便在证书即将过期时及时收到通知并进行处理。四、总结K8s证书管理是确保集群安全和稳定的重要一环。通过合理的证书管理和续期策略,可以确保K8s集群中的组件能够持续、稳定地进行通信和协作。在实际应用中,可以根据集群的规模和需求选择合适的证书管理方案,并结合自动续期功能简化证书管理过程。
  • [技术干货] k8s 为什么使用 Pod 作为最小的管理单元
    Kubernetes(K8s)作为容器编排领域的领导者,以其强大的容器管理能力、自动化部署以及高度可扩展性受到了广泛关注。在K8s的众多概念中,Pod是其最核心也是最基本的管理单元。那么,为什么K8s会选择Pod作为最小的管理单元呢?本文将从多个方面深入阐述这一问题。1. 容器间的协作与依赖关系在实际应用中,一个完整的服务或应用往往由多个容器组成,这些容器之间可能存在依赖关系,需要协同工作。例如,一个Web应用可能包含一个前端容器、一个后端容器和一个数据库容器。这些容器需要相互通信、共享数据,并且作为一个整体对外提供服务。Pod的设计正是为了支持这种容器间的协作与依赖关系。通过将多个容器封装在一个Pod中,K8s可以确保这些容器在同一台主机上运行,共享相同的网络命名空间、存储卷等资源。这使得容器间的通信变得简单高效,同时也方便了资源的统一管理和调度。2. 简化资源管理在K8s中,Pod是资源调度的基本单位。通过将多个容器组合成一个Pod,K8s可以简化资源管理。K8s只需要关注Pod的资源需求,而不需要关心Pod内部每个容器的具体资源使用情况。这种简化的管理方式使得资源分配更加灵活高效,也降低了管理的复杂性。3. 生命周期管理Pod作为最小的管理单元,其生命周期管理也更为简单和统一。K8s通过控制Pod的创建、调度、运行和销毁等生命周期阶段,可以确保整个应用或服务的稳定性和可靠性。同时,K8s还提供了丰富的钩子函数和自定义操作,允许用户在Pod的不同生命周期阶段执行特定的操作,进一步增强了其灵活性和可扩展性。4. 横向扩展与容错性在K8s中,Pod的副本集(ReplicaSet)和部署(Deployment)等高级对象允许我们轻松地对Pod进行横向扩展,以应对高并发访问或提高容错性。当某个Pod出现故障或无法提供服务时,K8s可以自动创建新的Pod来替换它,确保服务的连续性和可用性。这种自动扩展和容错机制使得K8s在处理大规模分布式系统时表现出色。5. 标准化与兼容性Pod作为K8s的核心概念之一,已经得到了广泛的认可和应用。许多云服务商和开源社区都提供了对Pod的支持和扩展。这使得基于Pod构建的应用和服务可以在不同的平台和环境中无缝迁移和部署,提高了应用的标准化程度和兼容性。总结综上所述,K8s选择Pod作为最小的管理单元是出于多方面的考虑。Pod的设计既满足了容器间协作与依赖关系的需求,又简化了资源管理、生命周期管理以及横向扩展与容错性等方面的处理。同时,Pod的标准化和兼容性也使得基于K8s构建的分布式系统更加稳定可靠、易于管理和扩展。因此,Pod作为K8s的最小管理单元具有其合理性和优越性。
  • [技术干货] Kubernetes Pod及其状态详解
    在Kubernetes(K8s)集群中,Pod是最小且最简单的部署单元。它代表了在集群上运行的一个进程。Pod封装了应用的容器(例如Docker容器),存储、唯一的网络IP,以及一个或多个容器运行所需的选项。Pod也提供了一种部署和管理容器的模式。Pod的基本概念Pod是K8s管理的最小部署单元,一个Pod可以包含一个或多个容器。这些容器共享Pod的网络命名空间、存储系统以及进程ID空间。在Pod内部,容器之间可以直接通过localhost进行通信。Pod的设计初衷是为了支持多个容器协同工作,例如一个容器作为主程序,另一个容器作为辅助程序。Pod的状态Pod在K8s集群中有多种状态,这些状态描述了Pod的当前运行情况。通过kubectl get pods命令可以查看集群中所有Pod的状态。常见的Pod状态包括:Running:Pod已经绑定到了一个节点上,Pod中所有的容器都已被创建。至少有一个容器仍在运行,或者正处于启动或重启状态。Succeeded:Pod中的所有容器都已成功终止,并且不会再重启。Failed:Pod中的所有容器都已终止,并且至少有一个容器是因为失败终止。也就是说,容器以非零状态退出或者被系统终止。Unknown:因为某些原因无法取得Pod的状态,通常发生在与Pod所在节点通信失败时。Pod的生命周期Pod的生命周期从创建开始,经历调度、启动、运行、终止等阶段,最终可能被删除。在Pod的生命周期中,K8s提供了许多钩子函数,允许用户在Pod的不同阶段执行自定义的操作,如初始化容器、前置和后置操作等。例子:一个简单的Pod定义下面是一个简单的Pod定义YAML文件示例:apiVersion: v1 kind: Pod metadata: name: my-pod labels: app: myapp spec: containers: - name: myapp-container image: myapp:v1 ports: - containerPort: 8080在这个例子中,我们定义了一个名为my-pod的Pod,它有一个容器myapp-container,该容器使用myapp:v1镜像,并监听8080端口。当我们使用kubectl create -f pod.yaml命令创建这个Pod时,K8s会尝试在集群中找到一个合适的节点来运行这个Pod。一旦Pod被调度并成功启动,我们就可以通过kubectl get pods来查看Pod的状态。Pod的状态查看假设我们已经创建了上面的Pod,并且它正在运行。执行kubectl get pods命令,我们会看到类似下面的输出:NAME READY STATUS RESTARTS AGE my-pod 1/1 Running 0 1m在这个输出中:NAME:Pod的名称。READY:Pod中就绪的容器数量与Pod中容器总数的比值。STATUS:Pod的当前状态,这里是Running。RESTARTS:Pod中容器的重启次数。AGE:Pod已经运行的时间。通过这个命令,我们可以快速了解Pod的状态和运行情况。如果需要更详细的信息,可以使用kubectl describe pod my-pod命令来查看Pod的详细描述。总结Pod是Kubernetes中最基础的部署单元,它封装了应用容器及其运行环境。通过理解Pod的基本概念、状态以及生命周期,我们可以更好地在K8s集群中部署和管理应用。掌握Pod的定义和状态查看方法,是使用K8s进行容器化应用部署的关键一步。
  • [技术干货] k8s 到底是什么,架构是怎么样的? —— 转
    你是一个程序员,你用代码写了一个博客应用服务,并将它部署在了云平台上。但应用服务太过受欢迎,访问量太大,经常会挂。所以你用了一些工具自动重启挂掉的应用服务,并且将应用服务部署在了好几个服务器上,总算抗住了。后来你又上线了商城应用服务和语音应用服务,随着应用服务变多,需求也千奇百怪。有的应用服务不希望被外网访问到,有的部署的时候要求内存得大于 xxGB 才能正常跑。你每次都需要登录到各个服务器上,执行手动操作更新。不仅容易出错,还贼浪费时间。原本就没时间找女朋友的你,现在哭得更大声了。那么问题就来了,有没有一个办法,可以解决上面的问题?当然有,没有什么是加一个中间层不能解决的,如果有,那就再加一层。这次我们要加的中间层,叫 Kubernetes。Kubernetes的位置 Kubernetes 是什么?Kubernetes,它是开源的神器,因为单词太长,所以我们习惯省略中间 8 个字母,简称它为 k8s。k8s名称的由来它介于应用服务和服务器之间,能够通过策略,协调和管理多个应用服务,只需要一个 yaml文件配置,定义应用的部署顺序等信息,就能自动部署应用到各个服务器上,还能让它们挂了自动重启,自动扩缩容。听起来有些厉害,它是怎么实现这些功能的呢?Kubernetes 架构原理为了实现上面的功能,Kubernetes 会将我们的服务器划为两部分,一部分叫控制平面(control plane,以前叫master),另一部分叫工作节点,也就是 Node。简单来说它们的关系就是老板和打工人, 用现在流行的说法就是训练师和帕鲁。控制平面负责控制和管理各个 Node,而 Node 则负责实际运行各个应用服务。k8s控制平面和Node的关系我们依次看下这两者的内部架构。控制平面内部组件• 以前我们需要登录到每台服务器上,手动执行各种命令,现在我们只需要调用 k8s 的提供的 api 接口,就能操作这些服务资源,这些接口都由 API Server 组件提供。• 以前我们需要到处看下哪台服务器 cpu 和内存资源充足,然后才能部署应用,现在这部分决策逻辑由 Scheduler(调度器)来完成。• 找到服务器后,以前我们会手动创建,关闭服务,现在这部分功能由 Controller Manager(控制器管理器)来负责。• 上面的功能都会产生一些数据,这些数据需要被保存起来,方便后续做逻辑,因此 k8s 还会需要一个存储层,用来存放各种数据信息,目前是用的 etcd,这部分源码实现的很解耦,后续可能会扩展支持其他中间件。以上就是控制平面内部的组件。k8s控制平面组件我们接下来再看看 Node 里有哪些组件。Node 内部组件Node 是实际的工作节点,它既可以是裸机服务器,也可以是虚拟机。它会负责实际运行各个应用服务。多个应用服务共享一台 Node 上的内存和 CPU 等计算资源。Node可以是裸机服务器或虚拟机在文章开头,我们聊到了部署多个应用服务的场景。以前我们需要上传代码到服务器,而用了 k8s 之后,我们只需要将服务代码打包成Container Image(容器镜像),就能一行命令将它部署。如果你不了解容器镜像的含义,你可以简单理解为它其实就是将应用代码和依赖的系统环境打了个压缩包,在任意一台机器上解压这个压缩包,就能正常运行服务。为了下载和部署镜像,Node 中会有一个 Container runtime组件。将容器镜像粗略理解为压缩包每个应用服务都可以认为是一个 Container(容器), 并且大多数时候,我们还会为应用服务搭配一个日志收集器 Container 或监控收集器 Container,多个 Container 共同组成一个一个 Pod,它运行在 Node 上。一个pod内有多个容器k8s 可以将 pod 从某个 Node 调度到另一个 Node,还能以 pod 为单位去做重启和动态扩缩容的操作。所以说 Pod 是 k8s 中最小的调度单位。Node调度Pod另外,前面提到控制平面会用 Controller Manager(通过API Server)控制 Node 创建和关闭服务,那 Node 也得有个组件能接收到这个命令才能去做这些动作,这个组件叫 kubelet,它主要负责管理和监控 Pod。最后,Node 中还有个 Kube Proxy,它负责 Node 的网络通信功能,有了它,外部请求就能被转发到 Pod 内。控制平面和Node的组件 Cluster控制平面和Node共同构成了一个 Cluster,也就是集群。在公司里,我们一般会构建多个集群, 比如测试环境用一个集群,生产环境用另外一个集群。同时,为了将集群内部的服务暴露给外部用户使用,我们一般还会部署一个入口控制器,比如 Ingress 控制器(比如Nginx),它可以提供一个入口让外部用户访问集群内部服务。生产和测试环境 kubectl 是什么上面提到说我们可以使用 k8s 提供的 API 去创建服务,但问题就来了,这是需要我们自己写代码去调用这些 API 吗?答案是不需要,k8s 为我们准备了一个命令行工具 kubectl,我们只需要执行命令,它内部就会调用 k8s 的 API。kubectl调用k8s的API接下来我们以部署服务为例子,看下 k8s 是怎么工作的。怎么部署服务?首先我们需要编写 YAML 文件,在里面定义 Pod 里用到了哪些镜像,占用多少内存和 CPU 等信息。然后使用 kubectl 命令行工具执行 kubectl apply -f xx.yaml ,此时 kubectl 会读取和解析 YAML 文件,将解析后的对象通过 API 请求发送给 Kubernetes 控制平面内 的 API Server。API Server 会根据要求,驱使 Scheduler通过 etcd提供的数据寻找合适的 Node, Controller Manager会通过 API Server 控制 Node 创建服务,Node 内部的 kubelet在收到命令后会开始基于 Container runtime组件去拉取镜像创建容器,最终完成 Pod的创建。至此服务完成创建。部署应用服务整个过程下来,我们只需要写一遍 yaml 文件,和执行一次 kubectl 命令,比以前省心太多了!部署完服务后,我们来看下服务是怎么被调用的。怎么调用服务?以前外部用户小明,直接在浏览器上发送 http 请求,就能打到我们服务器上的 Nginx,然后转发到部署的服务内。用了 k8s 之后,外部请求会先到达 Kubernetes 集群的 Ingress 控制器,然后请求会被转发到 Kubernetes 内部的某个 Node 的 Kube Proxy上,再找到对应的 pod,然后才是转发到内部容器服务中,处理结果原路返回,到这就完成了一次服务调用。用户调用k8s内应用服务的流程到这里我们就大概了解了 k8s 的工作原理啦,它本质上就是应用服务和服务器之间的中间层,通过暴露一系列 API 能力让我们简化服务的部署运维流程。并且,不少中大厂基于这些 API 能力搭了自己的服务管理平台,程序员不再需要敲 kubectl 命令,直接在界面上点点几下,就能完成服务的部署和扩容等操作,是真的嘎嘎好用。总结• k8s 是 G 家开源的神器,用于管理海量容器服务。• k8s 集群内分为控制平面和 Node,控制平面是大脑,负责发指令,Node 是手脚,负责执行任务。• 控制平面内有 API Server,Scheduler,Controller Manager 以及 etcd 等组件。Node 中含有 Pod,Kubelet,Container runtime, Kube Proxy 等组件。控制平面和 Node 共同构成一个 Cluster。• 文章通过怎么部署服务和怎么调用服务两个例子将这些组件串联了起来,方便大家加深理解。最后给大家留一个问题,我们提到 k8s 的时候,一般会提一下 docker, 但为了避免大家混淆,我在写这篇文章的时候,只字不提 docker,你知道 docker 和 k8s 之间是什么关系吗?欢迎评论区聊聊。
  • [热门活动] 【云原生专题直播有奖提问】DTSE Tech Talk 技术直播 NO.57:看直播提问题赢华为云定制长袖卫衣、华为云定制POLO衫等好礼!
    中奖结果公示感谢各位小伙伴参与本次活动,欢迎关注华为云DTSE Tech Talk 技术直播更多活动~本次活动获奖名单如下:请于4月30日下班前在此问卷中反馈您的中奖邮寄信息~直播简介【直播主题】华为云云原生FinOps解决方案,为您释放云原生最大价值【直播时间】2024年4月24日 16:30-18:00【直播专家】Roc 华为云云原生DTSE技术布道师【直播简介】还在对CCE集群成本评估感到束手无策?还在担心不合理的K8s集群资源申请和过度浪费?华为云容器服务CCE全新上线云原生FinOps中心,为用户提供多维度集群成本可视化,结合智能规格推荐、混部、超卖等成本优化手段,助力客户降本增效,释放云原生最大价值。观看直播:cid:link_1活动介绍【互动方式】直播前您可以在本帖留下您疑惑的问题,专家会在直播时为您解答。直播后您可以继续在本帖留言,与专家互动交流。我们会在全部活动结束后对参与互动的用户进行评选。【活动时间】即日起—2024年4月25日【奖励说明】评奖规则:活动1:直播期间在直播间提出与直播内容相关的问题,对专家评选为优质问题的开发者进行奖励。奖品:华为云定制长袖卫衣活动2:在本帖提出与直播内容相关的问题,由专家在所有互动贴中选出最优问题贴的开发者进行奖励。奖品:华为云定制POLO衫更多直播活动直播互动有礼:官网直播间发口令“华为云 DTSE”抽华为云定制雨伞等好礼。【注意事项】1、所有参与活动的问题,如发现为复用他人内容或直播间中重复内容,则取消获奖资格。2、为保证您顺利领取活动奖品,请您在活动公示奖项后2个工作日内私信提前填写奖品收货信息,如您没有填写,视为自动放弃奖励。3、活动奖项公示时间截止2024年4月30日,如未反馈邮寄信息视为弃奖。本次活动奖品将于奖项公示后30个工作日内统一发出,请您耐心等待。4、活动期间同类子活动每个ID(同一姓名/电话/收货地址)只能获奖一次,若重复则中奖资格顺延至下一位合格开发者,仅一次顺延。5、如活动奖品出现没有库存的情况,华为云工作人员将会替换等价值的奖品,获奖者不同意此规则视为放弃奖品。6、其他事宜请参考【华为云社区常规活动规则】。
  • [技术干货] Kubernetes(K8s)入门指南
    前言随着云计算技术的不断发展和普及,容器化技术已成为现代软件开发和部署的主流方式。而在容器编排领域,Kubernetes(简称K8s)无疑是当之无愧的领军者。本文将带您走进K8s的世界,了解其基本概念、核心组件以及如何使用K8s来管理和调度容器。一、什么是Kubernetes?Kubernetes是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。它提供了丰富的功能,包括自动调度、滚动更新、回滚、水平扩展、服务发现和存储编排等。通过使用K8s,开发人员和运维人员可以更加高效地管理和维护复杂的容器化应用程序。二、K8s的核心组件Master节点Master节点是K8s集群的控制中心,负责整个集群的管理和调度工作。它包括以下几个核心组件:API Server:提供RESTful API,供其他组件和客户端调用,实现集群资源的增删改查。Scheduler:负责根据一定的调度算法,将Pod分配到合适的Node节点上运行。Controller Manager:负责管理集群中的各种资源对象,如Pod、Service等,确保它们的状态与预期一致。Node节点Node节点是K8s集群中的工作节点,负责运行容器化应用程序。Node节点上运行的主要组件包括:Kubelet:负责与Master节点通信,接收并执行Master节点的调度指令。Kube-proxy:实现Service到Pod的流量转发功能。容器运行时:如Docker、containerd等,负责运行容器。三、如何使用K8s?安装和配置K8s集群您可以通过多种方式安装和配置K8s集群,如使用kubeadm、minikube等工具进行快速搭建,或者使用云服务提供商提供的托管K8s服务。安装完成后,您需要通过kubectl命令行工具与集群进行交互。部署应用程序在K8s中,您可以通过编写YAML或JSON格式的资源配置文件来定义您的应用程序。这些文件描述了Pod、Service、Deployment等K8s资源对象的属性。通过kubectl apply命令将这些文件提交给K8s集群,K8s将自动为您创建和管理这些资源对象。管理和维护应用程序K8s提供了丰富的功能来管理和维护您的应用程序。例如,您可以使用滚动更新功能来平滑地升级您的应用程序版本;使用自动扩展功能来根据负载情况自动调整Pod的数量;使用Service发现功能来实现服务之间的自动发现和通信等。四、总结Kubernetes作为容器编排领域的领军者,为现代软件开发和部署提供了强大的支持。通过了解K8s的基本概念、核心组件以及使用方法,您可以更加高效地管理和维护您的容器化应用程序。随着K8s生态系统的不断完善和发展,相信它将为未来的云计算领域带来更多的创新和突破。
  • [技术干货] Kmesh v0.1.0 版本发布!打造极致性能的流量治理体验
    Kmesh是业内首个内核级云原生流量治理引擎,通过基础软件创新帮助用户构筑云原生场景下高性能的通信基础设施。Kmesh第一个版本v0.1.0 [1]现已正式发布,用户可以在服务网格环境中使用yaml一键部署,无缝对接Istiod,通过流量治理下沉OS,实现相比 Istio Sidecar 方案转发时延降低50%+,为应用提供极致的转发性能体验。▍Kmesh 介绍Kmesh 基于 eBPF + 可编程内核技术,将流量治理下沉 OS,数据路径上无需经过代理层,实现了一个内核级 sidecarless 网格数据面。Kmesh 关键能力:高性能:内核中原生支持 L4~L7 流量治理功能,治理过程无需经过实体代理组件,网格内服务通信路径从代理架构下的三跳变为一跳,大幅提升网格数据面的转发性能;低开销:Pod 中无需部署 Sidecar 程序,大幅降低网格基础设施的资源开销;安全隔离:基于 eBPF 的运行时安全,并支持 cgroup 级治理隔离;平滑兼容:支持与 Istiod 等支持 XDS 协议的服务网格管控面对接,同时可以与现有 Sidecar 网格协同工作;Kmesh 的主要部件包括:kmesh-controller:负责生命周期管理、XDS 协议对接、观测运维等功能;kmesh-api:接口层,主要包括XDS 转换后的编排 API、观测运维通道等;kmesh-runtime:kernel 中实现的支持 L4~L7 流量编排的运行时;其中7层编排运行时能力依赖对内核的增强;kmesh-orchestration:基于 eBPF 实现 L4~L7 流量编排,如路由、灰度、负载均衡等;kmesh-probe:观测运维探针,提供端到端观测能力;▍Kmesh v0.1.0关键特性一键部署Kmesh社区发布了 Kmesh 的部署镜像[2],并支持通过 yaml 一键部署 Kmesh[3];基于namespace使能Kmesh类似Istio,Kmesh支持按namespace使能流量接管范围,如:kubectl label namespace default label istio.io/dataplane-mode=Kmesh无缝连通Istio Sidecar支持在已有sidecar形态的网格环境启用Kmesh,启用后namespace 下新创建的 Pod 流量会自动被 Kmesh 接管,而不再经过 sidecar 代理;自动对接服务网格控制面Kmesh支持与Istiod自动对接,且理论上遵循XDS协议的网格控制面都可以与Kmesh对接,可通过修改yaml中的  MESH_CONTROLLER 环境量指定;TCP/HTTP1.1基础流量治理支持TCP流量转发,支持HTTP1.1头域匹配、路由、灰度等,支持随机、轮询负载均衡算法;兼容运行模式支持根据运行环境的OS内核能力,自适应使能Kmesh特性,在无增强补丁的内核版本上,也能够以兼容模式运行Kmesh;详情参考Release Notes[1]。▍性能测试我们使用 fortio 测试了 Istio(Envoy)、Kmesh 在同等流量治理场景下的表现,同时测试了 K8s 下基于 kubeProxy 的服务通信时延作为基线参考;不同链接数下的时延对比:相同QPS下的CPU开销对比:从测试结果可以看到:Kmesh 的转发时延基本接近K8s原生转发时延,相比 Istio sidecar 模式的转发时延有明显降低;相同 qps 下,Kmesh 的 CPU 开销基本与 k8s 原生 CPU 开销一致,相比 Istio sidecar 模式有明显降低;想要了解详细的 demo 测试细节,可以观看我们的演示视频:videovideovideovideovideo  ▍Kmesh关键技术剖析内核级流量编排运行时微服务通信一般先建立链接,再发送业务报文,如果想要无感的对业务报文做编排处理,通常需要对流量进行劫持,编排完成后再基于调整后的报文继续转发,这也是现在 Proxy 代理的实现;Kmesh 考虑随流完成治理工作,将链路建立时机推迟到业务报文发送阶段,以实现更高的编排处理性能。伪建链pre_connect 流程挂载 bpf prog,若当前访问的目标地址在 xds 的 listener 范围,则调用 bpf_setsockopt 通过 TCP_ULP 将当前 socket 的 tcp proto hook重载到 kmesh_defer 的内核模块实现;延迟建链kmesh_defer 内核模块重写了 connect/send hook(在原生 hook 上做了增强):服务第一次走到 connect hook 时,会设置 bpf_defer_connect 标记,并不真正触发握手流程;send hook 中,若 sock 上设置了 bpf_defer_connect 标记,则触发connect,此时,会基于扩展的BPF_SOCK_OPS_TCP_DEFER_CONNECT_CB 调用 bpf prog,并在 bpf prog 中完成流量治理,然后基于调整后的通信五元组、报文进行建链和发送;整个治理过程大致如下图所示:XDS规则管理xds 模型是一颗层次化的树型规则表达,且不同版本模型定义可能会有调整,Kmesh 需要将模型信息转换成 eBPF map 存储,同时保持模型规则之间的层次关系;将 xds 模型转换成 eBPF map 数据具体过程:Kmesh 订阅 Istiod 的 xds 模型,并基于 protobuf-c 将 pb 模型转换成 c 数据结构风格;对于顶层模型( listener 等),Kmesh 定义了知名 map 表与之对应,且value 的数据结构复用 protobuf-c 导出的 c struct;map 更新从顶层的知名 map 表开始,对于记录中的指针成员,xds-adapter 中会创建 inner-map 表来存储指针指向的真实数据区域,并将 inner-map的map fd添加进 map-in-map表中,最后将其在map-in-map表的key(index)作为该指针成员的 value;map-in-map 解决 xds 模型层次化对于 map 记录的 value 成员,如果是指针变量(涉及引用其他数据结构),通过 inner-map 存储指向的数据区域:如果 vaule 成员是基础数据类型(int 等),则直接访问;如果 value 成员是指针类型,则指针存储的 value 是存放真实数据的 inner-map 在 map-in-map 表中的 index(注意:index 是在 kmesh-daemon 的xds-adapter 模块中更新 bpf map 时配合写入);访问时,先基于 index 找到 inner-map的map fd,再去 inner-map 表中查找真正数据,对于多级指针成员,则重复该过程,直到指针信息全部被剥离。流量治理编排实现xds 的治理规则复杂,层层匹配,超过了单个 eBPF 程序的复杂度限制;Kmesh 基于 eBPF Tail Calls 特性,将治理过程拆分成多个独立的 eBPF progs,具备较好的扩展性;▍展望Kmesh 是一种基于eBPF+可编程内核实现的高性能流量治理引擎,与业界方案相比,具有更高的转发性能和更低的资源开销;在无增强补丁的内核版本上,可以以兼容模式运行Kmesh,如果想要使用Kmesh完整的治理能力,当前 openEuler 23.03[4]版本已经原生支持,除此之外的其他操作系统需要基于增强的 patch 构建[5]。Kmesh 正在逐步完善,成为一个更受欢迎的流量治理引擎还有很多工作要做,欢迎大家试用 Kmesh v0.1.0 版本,并持续关注 Kmesh 社区,也期待您的共同参与。参考链接[1] Kmesh v0.1.0:cid:link_2[2] Kmesh的部署镜像:cid:link_3[3] 一键部署Kmesh:cid:link_1[4] openEuler 23.03版本:https://repo.openeuler.org/openEuler-23.03/[5] 基于增强的patch构建:cid:link_0[6] Kmesh社区地址:cid:link_4更多云原生技术动向关注容器魔方添加小助手k8s2222进入技术群
  • 改善 Kubernetes 上的 JVM 预热问题
    JVM 预热是一个非常头疼而又难解决的问题。基于 JVM 的应用程序在达到最高性能之前,需要一些时间来“预热”。当应用程序启动时,通常会从较低的性能开始。这归因于像即时(JIT)编译这些事儿,它会通过收集使用配置文件信息来优化常用代码。最终这样的负面影响是,与平均水平相比,预热期间接收的 request 将具有非常高的响应时间。在容器化、高吞吐量、频繁部署和自动伸缩的环境中,这个问题可能会加剧。在这篇文章中,我们将讨论在运行在 Kubernetes 集群中的 Java 服务如何解决 JVM 预热问题的经验。起因几年前,我们逐步从整体中分离出服务,开始在 Kubernetes 上进行迁移到基于微服务的体系结构。大多数新服务都是在 Java 中开发的。当我们在印度市场上运行一个这样的服务时,我们第一次遇到了这个问题。我们通过负载测试进行了通常的容量规划过程,并确定 N 个 Pod 足以处理超过预期的峰值流量。尽管该服务在轻松处理高峰流量,但我们在部署过程中发现了问题。我们的每个 Pod 在高峰时间处理的 RPM 都超过 10k,而我们使用的是 Kubernetes 滚动更新机制。在部署过程中,服务的响应时间会激增几分钟,然后再稳定到通常的稳定状态。在我们的仪表板中,会看到类似的图表:与此同时,我们开始收到来自部署时间段内的大量投诉,几乎都关于高响应时间和超时错误。第一步:花钱解决问题我们很快意识到这个问题与 JVM 预热阶段有关,但当时有其他的重要事情,因此我们没有太多时间进行调查,直接尝试了最简单的解决方案——增加 Pod 数量,以减少每个 Pod 的吞吐量。我们将 Pod 数量增加了近三倍,以便每个 Pod 在峰值处理约 4k RPM 的吞吐量。我们还调整了部署策略,以确保一次最多滚动更新 25%(使用 maxSurge 和 maxUnavailable 参数)。这样就解决了问题,尽管我们的运行容量是稳定状态所需容量的 3 倍,但我们能够在我们的服务中或任何相关服务中没有问题地进行部署。随着后面几个月里更多的迁移服务,我们开始在其他服务中常常看到这个问题。因此我们决定花一些时间来调查这个问题并找到更好的解决方案。第二步:预热脚本在仔细阅读了各种文章后,我们决定尝试一下预热脚本。我们的想法是运行一个预热脚本,向服务发送几分钟的综合请求,来完成 JVM 预热,然后再允许实际流量通过。为了创建预热脚本,我们从生产流量中抓取了实际的 URL。然后,我们创建了一个 Python 脚本,使用这些 URL 发送并行请求。我们相应地配置了 readiness 探针的 initialDelaySeconds,以确保预热脚本在 Pod 为 ready 并开始接受流量之前完成。令人吃惊的是,尽管结果有一些改进,但并不显著。我们仍然经常观察到高响应时间和错误。此外,预热脚本还带来了新的问题。之前,Pod 可以在 40-50 秒内准备就绪,但用了脚本,它们大约需要 3 分钟,这在部署期间成为了一个问题,更别说在自动伸缩期间。我们在预热机制上做了一些调整,比如允许预热脚本和实际流量有一个短暂的重叠期,但也没有看到显著的改进。最后,我们认为预热脚本的收益太小了,决定放弃。第三步:启发式发现由于预热脚本想法失败了,我们决定尝试一些启发式技术-GC(G1、CMS 和 并行)和各种 GC 参数堆内存CPU 分配经过几轮实验,我们终于取得了突破。测试的服务配置了 Kubernetes 资源 limits:我们将 CPU request 和 limit 增加到 2000m,并部署服务以查看影响,可以看到响应时间和错误有了巨大的改进,比预热脚本好得多。第一个 Deployment(大约下午 1 点)使用 2 个 CPU 配置,第二个 Deployment (大约下午 1:25)使用原来 1 个 CPU 配置为了进一步测试,我们将配置升级到 3000m CPU,令我们惊讶的是,问题完全消失了。正如下面看到的,响应时间没有峰值。具有 3 个 CPU 配置的 Deployment很快,我们就发现问题出在 CPU 节流上。在预热阶段,JVM 需要比平均稳定状态下更多的 CPU 时间,但 Kubernetes 资源处理机制(CGroup)根据配置的 limits,从而限制了 CPU。有一个简单的方法可以验证这一点。Kubernetes 公开了一个每个 Pod 的指标,container_cpu_cfs_throttled_seconds_total 表示这个 Pod 从开始到现在限制了多少秒 CPU。如果我们用 1000m 配置观察这个指标,应该会在开始时看到很多节流,然后在几分钟后稳定下来。我们使用该配置进行了部署,这是 Prometheus 中所有 Pod 的 container_cpu_cfs_throttled_seconds_total 图:正如预期,在容器启动的前 5 到 7 分钟有很多节流,大部分在 500 秒到 1000 秒之间,然后稳定下来,这证实了我们的假设。当我们使用 3000m CPU 配置进行部署时,观察到下图:CPU 节流几乎可以忽略不计(几乎所有 Pod 都不到 4 秒)。第四步:改进尽管我们发现了这个问题的根本,但就成本而言,该解决方案并不太理想。因为有这个问题的大多数服务都已经有类似的资源配置,并且在 Pod 数量上超额配置,以避免部署失败,但是没有一个团队有将 CPU 的 request、limits 增加三倍并相应减少 Pod 数量的想法。这种解决方案实际上可能比运行更多的 Pod 更糟糕,因为 Kubernetes 会根据 request 调度 Pod,找到具有 3 个空闲 CPU 容量的节点比找到具有 1 个空闲 CPU 的节点要困难得多。它可能导致集群自动伸缩器频繁触发,从而向集群添加更多节点。我们又回到了原点 但是这次有了一些新的重要信息。现在问题是这样的:      在最初的预热阶段(持续几分钟),JVM 需要比配置的 limits(1000m)更多的 CPU(大约 3000m)。预热后,即使 CPU limits 为 1000m,JVM 也可以充分发挥其潜力。Kubernetes 会使用 request 而不是 limits 来调度 Pod。我们清楚地了解问题后,答案就出现了——Kubernetes Burstable QoS。Kubernetes 根据配置的资源 request 和 limits 将 QoS 类分配给 Pod。到目前为止,我们一直在通过指定具有相等值的 request 和 limits(最初是 1000m,然后是 3000m)来使用 Guaranteed QoS。尽管 Guaranteed QoS 有它的好处,但我们不需要在整个 Pod 生命周期中独占 3 个 CPU,我们只需要在最初的几分钟内使用它。Burstable QoS 允许我们指定小于 limits 的 request,例如:由于 Kubernetes 使用 request 中指定的值来调度 Pod,它会找到具有 1000m CPU 容量的节点来调度这个 Pod。但是由于 3000m 的 limits 要高得多,如果应用程序在任何时候都需要超过 1000m 的 CPU,并且该节点上有空闲的 CPU 容量,那么就不会在 CPU 上限制应用程序。如果可用,它最多可以使用 3000m。这非常符合我们的问题。在预热阶段,当 JVM 需要更多的 CPU 时,它可以获取需要的 CPU。JVM 被优化后,可以在 request 范围内全速运行。这允许我们使用集群中的冗余的资源(足够可用时)来解决预热问题,而不需要任何额外的成本。最后,进行假设测试。我们更改了资源配置并部署了应用程序,成功了!我们做了更多的测试以验证结果一致。此外,我们监控了 container_cpu_cfs_throttled_seconds_total 指标,以下是其中一个 Deployment 的图表:正如我们所看到的,这张图与 3000m CPU 的 Guaranteed QoS 设置非常相似。节流几乎可以忽略不计,它证实了具有 Burstable QoS 的解决方案是有效的。为了使 Burstable QoS 解决方案正常工作,节点上需要有可用的冗余资源。这可以通过两种方式验证:就 CPU 而言,节点资源未完全耗尽;工作负载未使用 request 的 100% CPU。结论尽管花了一些时间,最终找到了一个成本效益高的解决方案。Kubernetes 资源限制是一个重要的概念。我们在所有基于 Java 的服务中实现了该解决方案,部署和自动扩展都运行良好,没有任何问题。要点:在为应用程序设置资源限制时要仔细考虑。花些时间了解应用程序的工作负载并相应地设置 request 和 limits。了解设置资源限制和各种 QoS 类的含义。通过 monitoring/alertingcontainer_cpu_cfs_throttled_seconds_total 来关注 CPU 节流。如果观察到过多的节流,可以调整资源限制。使用 Burstable QoS 时,确保在 request 中指定了稳定状态所需的容量。文章来源:K8sMeetup社区译者:Bach
  • [问题求助] 镜像拉取问题
    1. 第三方的服务是部署在园区平台的K8S上还是自建K8S,如果是园区的K8S,镜像怎么推送到仓库?2. 我们自建的harbor仓库在园区的K8S上支持不支持, 自建harbor通过host别名访问,K8S上是否能配置主机hosts
  • [专题汇总] 11月技术干货一篇写尽合集20篇
    技术干货一篇写尽合集20篇,本次给大家带来了CodeArts板块技术干货合集,设计Mysql Oracle Git 容器 运维的相关知识,希望可以给大家带来帮助  1.Oracle表索引查看常见的方法总结【转】 https://bbs.huaweicloud.com/forum/thread-0297136732000017003-1-1.html  2.Oracle数据表保留一条重复数据简单方法【转】 https://bbs.huaweicloud.com/forum/thread-0205136731850117002-1-1.html  3.Oracle导入导出dmp文件具体示例【转】 https://bbs.huaweicloud.com/forum/thread-0205136731270640001-1-1.html  4.看看CodeArts snap如何解释毕昇JDK如何进行快速反序列化 https://bbs.huaweicloud.com/forum/thread-0266136724985168025-1-1.html  5.从0到1学会MySQL单表查询【转】 https://bbs.huaweicloud.com/forum/thread-02105136720816984026-1-1.html  6.MySQL日期格式以及日期函数举例详解【转】 https://bbs.huaweicloud.com/forum/thread-0266136720702857023-1-1.html  7.MySQL主从同步延迟原因与解决方案【转】 https://bbs.huaweicloud.com/forum/thread-0257136720588871021-1-1.html  8.Docker安装mysql配置大小写不敏感挂载数据卷存储操作步骤【转】 https://bbs.huaweicloud.com/forum/thread-0290136720478298028-1-1.html  9.MySQL中的空格处理方法【转】 https://bbs.huaweicloud.com/forum/thread-02127136720383727033-1-1.html  10.MySQL中的SHOW FULL PROCESSLIST命令实现【转】 https://bbs.huaweicloud.com/forum/thread-02105136720261863025-1-1.html  11.SQL多行值合并一行字符串逗号分隔【转】 https://bbs.huaweicloud.com/forum/thread-0257136720162189020-1-1.html  12.SQL server常见的数据类型转换整理大全【转】 https://bbs.huaweicloud.com/forum/thread-0248136720112853029-1-1.html  13.SQL Server数据库游标的基本操作指南【转】 https://bbs.huaweicloud.com/forum/thread-0260136720025043021-1-1.html  14.SQL Server基础教程之游标(Cursor)【转】 https://bbs.huaweicloud.com/forum/thread-0266136719975532022-1-1.html  15.SQL去除字符串空格的ltrim()和rtrim()函数的实现【转】 https://bbs.huaweicloud.com/forum/thread-02127136719876232032-1-1.html  16.高性能负载均衡-分类和算法 https://bbs.huaweicloud.com/forum/thread-0248136637937517018-1-1.html  17.45 个 Git 经典操作场景,专治不会合代码【转】 https://bbs.huaweicloud.com/forum/thread-0248136629791027014-1-1.html  18.运维必备的17个技巧【转】 https://bbs.huaweicloud.com/forum/thread-0266136629427452015-1-1.html  19.没有Kubernetes怎么玩Dapr?【转】 https://bbs.huaweicloud.com/forum/thread-0257136629178535007-1-1.html  20.容器技术的发展历程【转】 https://bbs.huaweicloud.com/forum/thread-0229136628923618017-1-1.html
  • 轻松快速地调整Kubernetes的CPU和内存
    [技术干货] 轻松快速地调整Kubernetes的CPU和内存Kubernetes发表于 2021-02-24 13:23:373289查看在Kubernetes中分配和管理CPU和内存资源可能很棘手,但也很容易。本文,我将向你展示什么是Kubernetes资源和限制以及如何管理它们。本文的目标是简单–如何帮助你快速调整项目中的Kubernetes资源信息,主要通过三种方式:1. 为容器和 Pod 分配CPU和内存资源2. Resources Quota: 限制namespace的资源消耗3. Limit Ranges:配置默认的CPU请求和限制为容器和 Pod 分配CPU和内存资源下图,解释了Kubernetes资源的度量单位,资源状态工作流以及如何使用资源限制。CPU和内存单位Kubernetes 中的一个 cpu 等于:1 AWS vCPU1 GCP Core1 Azure vCore1 Hyperthread 在带有超线程的裸机 Intel 处理器上以下,Deployment使用了内存资源和CPU资源的请求和限制将CPU和内存 请求 (request)和内存 限制 (limit)分配给一个容器更详细的信息和代码段:将内存资源分配给容器和Pod将CPU资源分配给容器和PodKubernetes最佳实践资源要求和限制应用程序开发人员在Azure Kubernetes Service(AKS)中管理资源的最佳实践Resources Quota: 限制namespace的资源消耗资源配额,通过 ResourceQuota 对象来定义,对每个namespace的资源消耗总量提供限制。它可以限制namespace中某种类型的对象的总数目上限,也可以限制命令空间中的 Pod 可以使用的计算资源的总上限。资源配额的工作方式如下:不同的团队可以在不同的namespace下工作,目前这是非约束性的,在未来的版本中可能会通过 ACL (Access Control List 访问控制列表) 来实现强制性约束。集群管理员可以为每个namespace创建一个或多个 ResourceQuota 对象。当用户在namespace下创建资源(如 Pod、Service 等)时,Kubernetes 的配额系统会 跟踪集群的资源使用情况,以确保使用的资源用量不超过 ResourceQuota 中定义的硬性资源限额。如果资源创建或者更新请求违反了配额约束,那么该请求会报错(HTTP 403 FORBIDDEN), 并在消息中给出有可能违反的约束。如果namespace下的计算资源 (如 cpu 和 memory)的配额被启用,则用户必须为 这些资源设定请求值(request)和约束值(limit),否则配额系统将拒绝 Pod 的创建。 提示: 可使用 LimitRanger 准入控制器来为没有设置计算资源需求的 Pod 设置默认值。以下,是对持久卷声明和namespace资源的配额定义。你可以使用该kubectl apply命令来设置namespace的配额限制。kubectl apply -f resource-quota.yaml — namespace backend如何使用配额的详细说明,请参考https://kubernetes.io/docs/concepts/policy/resource-quotas/Limit Ranges:配置默认的CPU请求和限制如果你的namespace有资源配额,那么默认内存限制是很有帮助的。将 LimitRange 添加到namespace,不仅会限制cpu和内存,还会为存储请求大小强制设置最小值和最大值。存储是通过 PersistentVolumeClaim 来发起请求的。执行限制范围控制的准入控制器会拒绝任何高于或低于管理员所设阈值的 PVC。更详细的信息和代码段。为namespace配置默认的 CPU 请求和限制限制名称空间的存储使用量Kubernetes中的 Limit Range工具:管理Kubernetes的CPU和内存Popeye 会扫描集群中是否存在与配置,资源和网络漏洞有关的问题,并生成有关所有问题的详细报告。Goldilocks 扫描Pod中的资源限制,并使用建议的资源创建报告。Kube-advisor 来自Azure团队的工具,可扫描容器中缺少的资源并限制请求。K9s+benchmark 提供了一个命令行界面(CLI),使你可以轻松地管理,监视甚至对 你喜欢的终端软件中的集群进行基准测试你还可以将这些工具与 Datadog, Grafana + Prometeus,Azure Monitor结合使用,以改善资源并限制监视。总结设置资源请求:获取有关特定应用程序/容器的CPU和内存使用情况的信息。设置资源限制:运行负载测试以检测高负载下容器的CPU和内存。监视容器的CPU和内存使用情况。监视持久卷使用情况。检查是否可以使用Limit Range应用资源限制使用配额(不建议在生产环境中应用配额)文章来源:K8s中文社区译者:王延飞原文链接:https://dzone.com/articles/easy-and-fast-adjustment-of-kubernetes-cpu-and-mem
  • [热门活动] 【云原生专题直播有奖提问】DTSE Tech Talk 技术直播 NO.42:看直播提问题赢华为云定制U型按摩枕、华为云定制POLO衫等好礼!
    中奖结果公示感谢各位小伙伴参与本次活动,本次活动获奖名单如下:请各位获奖的伙伴在9月10日之前点击此处填写收货地址,如逾期未填写视为弃奖。再次感谢各位小伙伴参与本次活动,欢迎关注华为云DTSE Tech Talk 技术直播更多活动~直播简介【直播主题】云原生Bursting如何助力企业降本增效?【直播时间】2023年9月6日 16:30-18:00【直播专家】刘雨青 华为云云原生DTSE技术布道师【直播简介】线下IDC自建K8s集群容量无法满足业务峰值诉求?IDC基础设施扩容流程慢,一次性投入大,管理维护成本高?本期直播将聚焦华为云Serverless容器服务CCI提供的云原生CloudBursting解决方案,为用户提供资源随启随用、业务灵活弹性分配以及基础设施免运维的极致体验,助力企业降本增效。直播链接:cid:link_1活动介绍【互动方式】直播前您可以在本帖留下您疑惑的问题,专家会在直播时为您解答。直播后您可以继续在本帖留言,与专家互动交流。我们会在全部活动结束后对参与互动的用户进行评选。【活动时间】即日起—2023年9月7日【奖励说明】评奖规则:活动1:直播期间在直播间提出与直播内容相关的问题,对专家评选为优质问题的开发者进行奖励。奖品:华为云定制U型按摩枕活动2:在本帖提出与直播内容相关的问题,由专家在所有互动贴中选出最优问题贴的开发者进行奖励。奖品:华为云定制POLO衫更多直播活动直播互动有礼:官网直播间发口令“华为云 DTSE”抽华为云定制鼠标垫、填写问卷抽华为云定制保温杯等好礼分享问卷有礼 :邀请5位朋友以上完成问卷即可获得华为云定制帆布袋。老观众专属福利:连续报名并观看DTT直播3期以上抽送华为云DTT定制T恤。【注意事项】1、所有参与活动的问题,如发现为复用他人内容,则取消获奖资格。2、为保证您顺利领取活动奖品,请您在活动公示奖项后2个工作日内私信提前填写奖品收货信息,如您没有填写,视为自动放弃奖励。3、活动奖项公示时间截止2023年9月7日,如未反馈邮寄信息视为弃奖。本次活动奖品将于奖项公示后30个工作日内统一发出,请您耐心等待。4、活动期间同类子活动每个ID(同一姓名/电话/收货地址)只能获奖一次,若重复则中奖资格顺延至下一位合格开发者,仅一次顺延。5、如活动奖品出现没有库存的情况,华为云工作人员将会替换等价值的奖品,获奖者不同意此规则视为放弃奖品。6、其他事宜请参考【华为云社区常规活动规则】。
  • [技术干货] K3s vs K8s:轻量级和全功能的对决
    Kubernetes,通常缩写为 K8s,是领先的容器编排工具。该开源项目最初由 Google 开发,帮助塑造了现代编排的定义。该系统包括了部署和运行容器化系统所需的一切。社区供应商基于 Kubernetes 创建了适用于不同用例的独立发行版。K3s[1] 是由 Rancher 创建的一种 kubernetes 流行发行版,现在作为云原生计算基金会[2](CNCF)的一部分进行维护。K3s 的目标是成为一个轻量级的 Kubernetes 版本,适合在资源受限的硬件上使用,例如 IoT 设备。它还易于设置和使用,因此非常适合用于本地开发集群。它专注于边缘部署,但并不排除对大规模云部署的支持:K3s 的 CNCF 认证意味着它提供了所有 Kubernetes 功能,并且可以用于生产环境。在本文中,你将了解 K3s 与 Kubernetes 项目提供的官方发行版之间的比较,包括它们的区别、何时使用它们以及掌握它们的容易程度。什么是 K8sKubernetes 是一个开源的容器编排引擎,用来对容器化应用进行自动化部署、 扩缩和管理。该项目托管在 CNCF。Kubernetes 提供了部署容器并在多个主机上进行扩展的所有所需工具。Kubernetes 集群中的每台主机被称为一个节点,节点由 Kubernetes 控制平面管理。它会将你的容器调度到空闲节点上,管理网络和存储并提供与之交互的 API。什么是 K3sK3s 是由 Rancher 主导开发的 Kubernetes 发行版。它在不分叉的基础上构建了上游项目。概念上,Kubernetes 发行版类似于 Linux 操作系统:K3s 是一种 Kubernetes 发行版,就像 Ubuntu 是一种 Linux 发行版一样。K3s 在保留 Kubernetes 功能的基础上,还增加了自己的功能。K3s 经过专门设计,即使在最小的硬件环境中也能良好运行。K3s 提供了一个小于 60MB 的单个二进制文件。这个轻量级可执行文件包含了启动完全功能的 Kubernetes 集群所需的一切。通过放弃非必要的 Kubernetes 功能(如云服务提供商集成和非 CSI[3] 存储提供商),实现了这个小巧的二进制文件大小。利用 Go 语言的 goroutines[4],将各个 Kubernetes 组件从单个入口点运行起来。K3s 和 K8s 易于部署通常情况下,相比 K8s,K3s 更容易部署和维护。轻量级的二进制文件让你可以用一个命令启动所有的 Kubernetes 控制平面组件。而要启动官方的 Kubernetes 集群则需要更多的时间和步骤,并且可能更难维护。部署 K3s以下命令可以启动并运行一个 K3s 集群:$ curl -sFL https://get.k3s.io | sh -官方的安装脚本会下载二进制文件并注册一个系统服务,该系统服务会在进程终止或主机重新启动时自动启动 K3s。它还配置了 Kubernetes 实用工具,包括 kubectl CLI。在新的机器上运行脚本后,你应该能够在几秒钟内与你的集群进行交互:$ kubectl run nginx --image=nginx pod/nginx created你可以通过在其他节点上运行以下命令,轻松地将节点加入到你的 K3s 集群中:$ sudo k3s agent --server https://<control-plane-ip>:6443 \ --token <node-token>你可以通过从运行 K3s 控制平面的机器上读取 /var/lib/rancher/k3s/server/node-token 文件来获取 <node-token> 的值。K3s 还可以通过 Rancher 开发的 k3d[5] 部署。k3d 将 K3s 封装在 docker 容器内并运行。K3d 允许你在单个主机上运行多个 K3s 集群,并使用熟悉的 Docker 工具进行管理。你可以使用以下命令安装 k3d:$ curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | \ TAG=v5.4.5 bash然后创建你的第一个集群:$ k3d create cluster demo-cluster现在你可以使用 kubectl 来向 k3d/K3s 集群添加对象:$ kubectl run nginx –image nginx:latest pod/nginx created部署 K8sK8s 的部署过程比较复杂。Kubernetes 项目提供了各个组件的下载,比如:API server、controller manager 和 scheduler。你需要成功部署每个组件来创建你的控制平面。然后,你还需要在每个工作节点上安装 kubelet。通过 kubeadm 工具,可以简化 Kubernetes 安装。在使用 kubeadm 之前,你需要安装一个容器运行时,比如 containerd[6]。然后,你可以运行以下命令在你的主机上初始化 Kubernetes 控制平面:$ kubeadm init初始化完成后,系统会告诉你运行下一步需要做什么:$ mkdir -p $HOME/.kube $ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config $ sudo chown $(id -u):$(id -g) $HOME/.kube/config然后,你需要手动选择并安装一个 Pod 网络插件,这样你的 Pod 才能相互通信。Flannel 是一个受欢迎的选项:$ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yaml经过所有这些步骤,你就可以向集群中添加节点了:kubeadm join --token <token> <control-plane-ip>:<control-plane-port> \ --discovery-token-ca-cert-hash sha256:<hash><token> 的值是通过在控制平面主机上运行 kubeadm token list 命令获取的。要找到正确的 discovery-token-ca-cert-hash,你需要在控制平面主机上运行以下命令:openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin \ -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'使用 kubeadm 启动本地 Kubernetes 集群比使用 K3s 要复杂得多。K3s 抽象了集群设置步骤,使得快速启动和运行变得更加简单。在本地使用 K8s 需要额外的时间和精力来学习安装过程并配置环境。K3s 和 K8s 之间的主要区别K8s 和 K3s 对用户提供了相同的功能接口。如果你有一个 Kubernetes YAML 清单,你可以在两个集群中使用任何一个进行部署,而无需进行修改。这两个发行版的区别在于它们的打包方式和包含的组件。以下是一些你应该考虑的关键特点:默认安装的组件K8s 和 K3s 打包了不同的组件来实现 Kubernetes 的架构。其中最大的变化之一就是控制平面使用的数据存储:上游 Kubernetes 使用 etcd,而 K3s 选择使用内置的 SQLite 数据库。这通常提高了性能并减小了二进制文件的大小,但可能不适用于大规模集群。如果需要,K3s 也可以连接到外部的 etcd 或使用 K3s 内置的 etcd 数据存储,以及其他基于 SQL 的数据库,如 MySQL 和 PostgreSQL。标准的 Kubernetes 发行版只包括控制平面所需的组件。K3s 还内置了常用的生态工具,比如:kubectl。K3s 集成了 Helm 支持[7],可以通过将 Helm Chart 表示为集群中的 HelmChart 对象来部署 Helm Chart。然而,上游 Kubernetes 不理解 Helm;你需要单独安装 Helm CLI 并使用其命令来安装你的 Chart。K8s 和 K3s 都使用 containerd 作为默认的容器运行时,但这可以进行定制。K3s 还包含了其他几个来自社区的组件,包括用于 Pod 网络的 flannel 以及作为入口控制器和内置负载均衡器的 Traefik。Kubernetes 让你自己选择和安装这些工具,而 K3s 则内置了我们常用的工具。当你不想花太多的时间成本去学习 K8s 各个组件作用时,K3s 是更好的选择。它可以启动一个功能完整的集群,并且可用于生产。资源要求K3s 可以在 1C 512MB 的设备上运行,K3s 二进制文件大小不到 60 MB,并且不需要外部依赖。使用 kubeadm 创建的集群具有更高的资源需求。文档建议至少有两个空闲的 CPU 核和 2 GB 的内存。控制平面组件的增加开销意味着需要更多的硬件资源才能达到相同的结果。这在云上部署集群时可能会增加成本。K3s 是资源受限环境的优先选择。这是该项目的核心关注领域。请记住,虽然 K3s 可以运行在 512 MB 内存的设备上,但并不推荐这样,因为你需要给应用程序预留运行空间。升级K3s 提供简化的集群升级体验。你只需再次运行安装脚本即可下载最新版本并自动完成升级:$ curl -sfL https://get.k3s.io | sh -在每个节点上重复执行此命令将使你的集群升级到最新的稳定版本,无需任何手动干预。对于使用 kubeadm 创建的 K8s 集群进行升级需要执行几个额外的步骤。你需要获取最新版本的 kubeadm:# Updating to v1.24.1 $ apt-get update $ apt-get install -y kubeadm=1.24.1接下来,使用 kubeadm 升级你的控制平面:$ kubeadm upgrade apply v1.24.1最后,升级每个工作节点上的 kubelet 和 kubectl:$ apt-get update $ apt-get install -y kubelet=1.24.1 kubectl=1.24.1 $ systemctl daemon-reload $ systemctl restart kubeletK3s 再次提供了更简单、无需干预的体验。Kubeadm 的升级同样也相对简单,但需要运行更多的命令。这增加了升级过程中出错的可能性。而使用 K3s,你只需调用安装脚本并等待集群更新即可。速度在等效硬件上部署的 K8s 集群和 K3s 集群应该可以以相似的性能运行你的容器,因为它们使用相同的 containerd 运行时。然而,K3s 非常轻巧,它安装和启动控制平面的速度要比 K8s 快得多。相比之下,上游的 Kubernetes 可能需要几分钟才能启动(而 K3s 通常在一分钟内可用)。这使得 K3s 更适合于临时的集群,例如本地开发和测试环境。你可以快速启动一个集群,使用后再将 K3s 关闭。安全K3s 在设计上是安全的,并提供了一个最小的攻击面。所有组件都打包在一个二进制文件中,减少的依赖关系使得安全漏洞的出现可能性较小。这并不意味着 K8s 是不安全的。Kubernetes 已成为最受欢迎的开源项目之一,被全球各大公司采用。它经过定期审查,以确保集群受到攻击的保护。无论你使用哪种解决方案,你都应该在安装后加强集群的安全保护。K3s 和 Kubernetes 都有自己的安全建议[8],用于创建安全的集群。K3s 和 K8s 的理想使用场景K3s 具有最低的硬件要求,适用于资源受限的环境,这些环境无法容纳标准的 K8s 集群。K3s 放弃了诸如 etcd 之类的组件,而选择了更小的替代方案,这意味着 K3s 可以适应 IoT 和边缘设备。同时,K3s 也是在开发测试环境中运行本地 Kubernetes 集群的理想解决方案。工程师可以在几秒钟内快速启动自己的环境,而无需安装依赖项或在云中使用托管的 Kubernetes 服务产生成本。你甚至可以在 CI 流水线脚本中运行 K3s,以简化测试流程。虽然 K3s 适用于许多不同的环境,但在某些情况下,使用更大的 Kubernetes 发行版可能更合理。例如,在 大规模部署或需要使用依赖于 K8s 特定组件的场景时。如果你在这个规模上运作,你可能需要使用 kubeadm 或其他工具部署和维护 K8s。对于希望对各个控制平面组件具有完全控制权的大型集群,K3s 的简单性可能会过于局限。总结Kubernetes 是部署和分发容器的领先编排工具。虽然它在推动容器进入生产技术方面发挥了重要作用,但纯 Kubernetes 仍然相当复杂且难以维护。K3s 通过提供一个经过 CNCF 认证的 Kubernetes 发行版,将其打包为一个不到 60MB 的单个二进制文件,解决了这些挑战。它的轻量级方案让你可以在边缘、工作站和传统云环境中运行相同版本的 Kubernetes。参考资料[1]K3s 官网: https://k3s.io/[2]CNCF: https://www.cncf.io/[3]Container Storage Interface (CSI) for Kubernetes GA: https://kubernetes.io/blog/2019/01/15/container-storage-interface-ga[4]goroutines: https://gobyexample.com/goroutines[5]K3d: https://github.com/k3d-io/k3d[6]containerd: https://containerd.io/[7]K3s Helm: https://rancher.com/docs/k3s/latest/en/helm[8]保护集群: https://rancher.com/docs/k3s/latest/en/security/hardening_guide转自边缘计算k3s社区 LFAPAC
  • [技术干货] 【K8S系列】深入解析K8S调度-转载
     1 基础介绍 1.1 什么是k8s调度 Kubernetes调度(Scheduling):是指将未调度的Pod自动分配到集群中的节点的过程。 Pod是Kubernetes中最小的可部署单元,它通常包括一个或多个容器。 在Kubernetes中,容器可以在集群中的任何节点上运行,调度器可以根据节点的资源使用情况、Pod的资源需求、亲和性和反亲和性等因素,将Pod分配到最合适的节点上运行。 每个Pod都有一个调度器(Scheduler)负责将其分配到一个可用的节点上。 调度器是Kubernetes集群中的一个核心组件,它监视未调度的Pod对象,并为其选择最佳的节点。 2 Kubernetes调度的工作原理 2.1 原理详解 Kubernetes调度的工作原理可以概括为以下几个步骤: 创建Pod:用户通过Kubernetes API创建Pod对象,并在其中指定Pod的资源需求、容器镜像等信息。 调度器监视Pod:Kubernetes调度器监视集群中的未调度Pod对象,并为其选择最佳的节点。 选择节点:调度器通过算法选择最佳的节点,并将Pod绑定到该节点上。调度器选择节点的依据包括节点的资源使用情况、Pod的资源需求、亲和性和反亲和性等。 绑定Pod到节点:调度器将Pod和节点之间的绑定信息保存在etcd数据库中,以便节点可以获取Pod的调度信息。 节点启动Pod:节点定期检查etcd数据库中的Pod调度信息,并启动相应的Pod。如果节点故障或资源不足,调度器会重新调度Pod,并将其绑定到其他节点上运行。  2.2 其他因素 调度器选择节点的过程中,有以下一些因素需要考虑: 节点资源:调度器需要考虑节点的资源使用情况,如CPU、内存、磁盘等。 Pod资源需求:调度器需要考虑Pod的资源需求,如CPU、内存、磁盘等。 亲和性和反亲和性:调度器可以根据Pod指定的亲和性和反亲和性规则来选择节点。 节点污点(Taints)和容忍度(Tolerations):节点可以设置污点,表示节点上不允许运行特定类型的Pod。Pod可以设置容忍度,以容忍节点上的污点。 节点标签:调度器可以根据节点的标签来选择最佳的节点。 3 调度算法 调度算法是指决定Pod应该调度到哪个节点上的算法。Kubernetes提供了多种调度算法,可以根据实际情况选择合适的算法。以下是Kubernetes常用的调度算法:   随机算法 最小负载算法 贪心算法 最佳适应算法 加权最小平均负载算法  3.1 随机算法  随机算法是最简单的调度算法之一。  规则:它会随机选择一个可用节点,并将Pod调度到该节点上。 效率:这种算法简单、快速,适用于不需要考虑资源利用率和负载均衡的场景。 缺点:随机算法可能会导致节点资源的不均衡分配和资源浪费。 3.2 最小负载算法  最小负载算法会选择当前负载最低的节点,并将Pod调度到该节点上。  这种算法可以避免节点资源的不均衡分配,但是可能会导致某些节点的资源利用率过高,从而影响其他Pod的运行。  3.2.1 优点  优点在于可以避免节点资源的不均衡分配和负载过高的问题,从而提高Kubernetes集群的资源利用率和稳定性。同时,最小负载算法可以与其他调度算法结合使用,例如可以与负载均衡算法结合使用,以进一步优化节点的资源利用率和负载均衡。  3.2.2 缺点  缺点在于可能会导致某些节点的资源利用率过低,从而浪费资源。此外,最小负载算法不能保证Pod被调度到最优的节点上,无法满足一些特殊的需求。  3.3 贪心算法  贪心算法是一种基于启发式的算法,它尝试在当前状态下找到最优解。  在Pod调度中,贪心算法会尝试选择最优节点,并将Pod调度到该节点上。  贪心算法的核心思想是:在每一步选择中都采取在当前状态下最优的选择,从而希望最终能够得到全局最优解。  优点  优点在于速度快,可以快速找到局部最优解,适用于大规模的Kubernetes集群。  同时,贪心算法可以与其他调度算法结合使用,例如可以与最小负载算法或最佳适应算法结合使用,以实现更好的负载均衡和资源利用率。  缺点 贪心算法的缺点在于不能保证找到全局最优解,有可能会陷入局部最优解而无法跳出。  此外,贪心算法也可能会导致某些节点的资源利用率过高,从而影响其他Pod的运行。  使用  在实际使用中,贪心算法可以与其他调度算法结合使用,例如可以与最小负载算法或最佳适应算法结合使用,以实现更好的负载均衡和资源利用率。同时,调度器还可以使用亲和性/反亲和性规则来筛选节点,以进一步优化贪心算法的效果。  3.4 最佳适应算法  最佳适应算法(Best Fit Algorithm),它会选择当前可用节点中最适合Pod的节点,并将Pod调度到该节点上。  最佳适应算法考虑节点的资源利用率情况,避免将Pod调度到资源利用率不高的节点上,从而实现负载均衡和资源利用率最大化的目的。  优点 最佳适应算法的优点在于可以避免节点资源的不均衡分配和资源浪费,从而提高Kubernetes集群的资源利用率和稳定性。同时,最佳适应算法可以与其他调度算法结合使用,例如可以与贪心算法或最小负载算法结合使用,以进一步优化节点的资源利用率和负载均衡。  缺点 最佳适应算法的缺点在于可能会导致节点资源利用率的不稳定性,从而影响Pod的运行。如果节点资源利用率变化较快,最佳适应算法可能会导致Pod频繁地迁移,从而影响Pod的稳定性和性能。  3.5 加权最小平均负载算法  加权最小平均负载算法(Weighted Least-Connection Algorithm)是一种调度算法,它会选择当前负载最低且权重最高的节点,并将Pod调度到该节点上。加权最小平均负载算法考虑节点的负载情况和权重,避免将Pod调度到负载过高或权重过低的节点上,从而实现负载均衡和资源利用率最大化的目的。  优点 加权最小平均负载算法的优点在于可以避免节点资源的不均衡分配和负载过高的问题,从而提高Kubernetes集群的资源利用率和稳定性。同时,加权最小平均负载算法可以根据节点的权重分配资源,以满足不同节点的需求。  缺点 加权最小平均负载算法的缺点在于可能会陷入局部最优解而无法跳出。如果节点资源利用率变化较快,加权最小平均负载算法可能会导致Pod频繁地迁移,从而影响Pod的稳定性和性能。  4 调度组件  Kubernetes的调度组件是Kubernetes集群中的一个核心组件,它负责将Pod调度到Kubernetes集群中的节点上,以实现负载均衡和资源利用率最大化的目的。  调度组件通常由以下两个组件组成:  调度器(Scheduler):负责对新创建的Pod进行调度,选择合适的节点,并将Pod调度到该节点上。调度器会根据节点的资源利用率、亲和性/反亲和性规则、Pod的资源需求等因素来选择节点,并确保Pod能够被成功地调度和运行。  调度器扩展器(Scheduler Extender):负责对调度器进行扩展,并提供额外的调度策略和规则。调度器扩展器可以通过插件的形式进行扩展,例如可以添加自定义的亲和性/反亲和性规则、节点选择器、调度器过滤器等,以实现更灵活和多样化的调度策略。  调度器实现 Kubernetes还提供了多种调度器实现,包括:  默认调度器(Default Scheduler):是Kubernetes中的默认调度器,负责对新创建的Pod进行调度,并将Pod调度到合适的节点上。  自定义调度器(Custom Scheduler):是一种自定义的调度器实现,可以根据实际需求来定义调度策略和规则,以实现更灵活和多样化的调度功能。  扩展调度器(Extended Scheduler):是一种支持调度器扩展器的调度器实现,可以通过调度器扩展器来添加自定义的调度规则和策略,以实现更灵活和多样化的调度功能。  总之,Kubernetes的调度组件是Kubernetes集群中的一个核心组件,可以实现负载均衡和资源利用率最大化的目的。在实际使用中,需要根据实际情况和需求来选择合适的调度器实现和调度策略,以确保Kubernetes集群的资源利用率最大化。  5 调度示例  5.1 如何实现pod的调度 当我们创建一个Pod时,Pod会被加入到调度器的无调度队列中等待被调度。调度器会定期轮询无调度队列,检查每个Pod的调度需求,然后将它们调度到最适合的节点上。调度器的调度决策是基于节点的资源利用率、Pod的资源需求和亲和性/反亲和性规则等因素。  以下是Pod的调度流程的详细步骤:  获取Pod的 调度需求 选择适合的节点 分配Pod到节点 保存调度信息 启动Pod 1 获取Pod的 调度需求 调度器首先获取Pod的调度需求,包括Pod的容器镜像、资源需求和亲和性/反亲和性规则等。  2 选择适合的节点  调度器会根据Pod的调度需求和集群的资源情况,在可用的节点中选择最适合的一个。调度器会根据节点的资源利用率、Pod的资源需求和亲和性/反亲和性规则等因素来进行选择。如果没有可用的节点满足Pod的需求,Pod就会一直处于等待调度的状态。  3 分配Pod到节点  调度器会将Pod分配到选择的节点上,并将Pod对象的spec.nodeName字段设置为节点的名称。这样,kubelet就可以知道Pod被分配到了哪个节点上。  4 保存调度信息  调度器会将Pod和节点之间的绑定信息保存在etcd数据库中。这些信息包括Pod的名称、命名空间、调度时间戳和节点名称等。kube-scheduler会周期性地检查这些绑定信息,以确保Pod已经被分配到了正确的节点上。  5 启动Pod  当Pod被分配到节点上时,kubelet会从etcd数据库中获取Pod的配置信息,并根据这些信息启动Pod中的容器。容器启动后,Pod就可以开始运行了。  总之,Pod的调度流程是由调度器来完成的。调度器会根据节点的资源利用率、Pod的资源需求和亲和性/反亲和性规则等因素来选择最适合的节点,并将Pod分配到节点上运行。一旦Pod被分配到节点上,kubelet就会从etcd数据库中获取Pod的配置信息,并启动Pod中的容器。  5.2 调度器如何选择最适合的节点? 调度器在选择最适合的节点时,会根据一定的策略和算法进行选择。以下是调度器选择节点的一些主要考虑因素:   资源利用率 Pod的资源需求 亲和性和反亲和性规则 节点的标签和注释 节点的负载均衡  资源利用率  调度器会检查集群中各个节点的资源使用情况,包括CPU、内存、磁盘和网络等方面的使用情况。调度器会选择资源利用率最低的节点,以确保Pod能够得到足够的资源。  Pod的资源需求  调度器会检查Pod的资源需求,包括CPU和内存等方面的需求。调度器会选择可以满足Pod资源需求的节点,以避免Pod因为资源不足而无法正常运行。  亲和性和反亲和性规则  调度器会检查Pod的亲和性和反亲和性规则。亲和性规则指定了Pod应该调度到哪些节点上,而反亲和性规则指定了Pod不应该调度到哪些节点上。调度器会根据这些规则来选择节点,以确保Pod被调度到最合适的节点上。  节点的标签和注释  调度器会检查节点的标签和注释。节点的标签可以用来标识节点的特性和属性,而注释可以提供节点的附加信息。调度器可以使用这些信息来选择最适合的节点。  节点的负载均衡  调度器会尝试在集群中平衡负载,避免某个节点过度负载,而其他节点资源利用率太低。调度器会选择负载均衡最优的节点,以确保集群中的资源利用率最大化。  总之,调度器在选择最适合的节点时,会考虑多个因素,包括资源利用率、Pod的资源需求、亲和性和反亲和性规则、节点的标签和注释以及负载均衡等。调度器会使用这些信息来选择最优的节点,以确保Pod被调度到最合适的节点上。  5.3 调度器如何检查Pod的资源需求? 调度器在检查Pod的资源需求时,会查看Pod的定义中  spec.containers[*].resources.requests spec.containers[*].resources.limits 字段中指定的资源需求和资源限制。  resources.requests字段指定了Pod启动时所需的最小资源量。例如,CPU和内存等资源的需求量。如果Pod的实际资源使用量超过了请求量,Kubernetes会杀死该Pod并重新启动。  resources.limits字段指定了Pod最大可以使用的资源量。例如,CPU和内存等资源的限制量。如果Pod的实际资源使用量超过了限制量,Kubernetes会限制该Pod的资源使用,并可能导致Pod无法正常运行。  调度器会根据这些资源需求和限制来选择最适合的节点来调度Pod。调度器在选择节点时会考虑节点的资源利用率和Pod的资源需求,以确保Pod可以得到足够的资源来正常运行。  5.2 如何设置Pod的亲和性和反亲和性规则 在Kubernetes中,亲和性(Affinity)和反亲和性(Anti-Affinity)是用来指定Pod和Node之间关系的规则。通过设置亲和性和反亲和性规则,可以让调度器将Pod分配到最合适的节点上。  亲和性规则用于指示Pod应该被调度到哪些节点上,而反亲和性规则用于指示Pod不应该被调度到哪些节点上。下面是如何设置Pod的亲和性和反亲和性规则:  通过标签(Labels)设置亲和性和反亲和性规则  可以通过标签来设置Pod的亲和性和反亲和性规则。首先,需要在Pod中定义标签选择器(Label Selector),然后使用Node Affinity和Pod Affinity来指定亲和性规则,使用Node Anti-Affinity和Pod Anti-Affinity来指定反亲和性规则。例如,以下是一个使用标签选择器和亲和性规则的Pod定义:  apiVersion: v1 kind: Pod metadata:   name: my-pod spec:   containers:   - name: my-container     image: my-image   affinity:     nodeAffinity:       requiredDuringSchedulingIgnoredDuringExecution:         nodeSelectorTerms:         - matchExpressions:           - key: my-label             operator: In             values:             - my-value  在上面的示例中,Pod选择器使用matchExpressions指定了一个标签选择器,该选择器选择my-label=my-value的节点。然后,使用nodeAffinity指定了一个亲和性规则,该规则要求Pod被调度到拥有该标签的节点上。  通过拓扑域(Topology)设置亲和性和 反亲和性规则 可以使用Topology来指定Pod的亲和性和反亲和性规则。Topology是指节点的拓扑结构,如拓扑域、区域、机架等。使用Topology可以确保Pod被调度到拓扑结构相似的节点上。例如,以下是一个使用Topology和亲和性规则的Pod定义:  apiVersion: v1 kind: Pod metadata:   name: my-pod spec:   containers:   - name: my-container     image: my-image   affinity:     podAffinity:       requiredDuringSchedulingIgnoredDuringExecution:       - labelSelector:           matchLabels:             app: my-app         topologyKey: rack  在上面的示例中,Pod选择器使用matchLabels指定了一个标签选择器,该选择器选择app=my-app的Pod。然后,使用topologyKey指定了一个亲和性规则,该规则要求Pod被调度到与已经调度了app=my-app的Pod在同一个rack中的节点上。  总之,通过设置亲和性和反亲和性规则,可以让调度器将Pod分配到最合适的节点上。可以使用标签或拓扑域来设置Pod的亲和性和反亲和性规则。注意,正确的设置亲和性和反亲和性规则需要了解集群的拓扑结构和资源使用情况,否则可能会导致Pod无法正确调度。  5.2 如何设置Pod的资源限制和请求 在Kubernetes中,可以通过设置Pod的资源限制和请求来控制Pod使用的资源量。资源限制(Resource Limits)指定了Pod最大可以使用的资源量,而资源请求(Resource Requests)则指定了Pod启动时所需的最小资源量。设置Pod的资源限制和请求可以确保Pod在运行时不会使用过多的资源,并且可以提高Pod在集群中的调度成功率。  以下是如何设置Pod的资源限制和请求的示例:  apiVersion: v1 kind: Pod metadata:   name: my-pod spec:   containers:   - name: my-container     image: my-image     resources:       limits:         cpu: "1"         memory: "500Mi"       requests:         cpu: "0.5"         memory: "250Mi"  在上面的示例中,Pod中的容器my-container设置了资源限制和请求。容器的资源限制是1个CPU核心和500MiB内存,而容器的资源请求是0.5个CPU核心和250MiB内存。  可以通过以下方式设置资源限制和请求:  CPU和内存  可以使用CPU和内存来设置资源限制和请求。CPU的单位是CPU核心,内存的单位是字节。可以使用以下格式指定CPU和内存:  CPU:使用分数或整数表示CPU核心数量。例如,0.5表示一半核心,1表示一个核心,2表示两个核心。 内存:使用字节、千字节、兆字节或吉字节表示内存大小。例如,1Gi表示1个吉字节,500Mi表示500兆字节。 其他资源  除了CPU和内存之外,还可以使用其他资源来设置资源限制和请求,如GPU、存储等。不同的资源可以使用不同的单位,具体取决于资源类型。可以在Kubernetes文档中查看各种资源类型的详细信息。  总之,设置Pod的资源限制和请求可以控制Pod使用的资源量。可以使用CPU和内存来设置资源限制和请求,也可以使用其他资源类型。在设置资源限制和请求时,需要考虑Pod所需的资源量以及集群的资源使用情况,以避免Pod无法正常运行或影响其他Pod的运行。  6 总结 总之,Kubernetes调度是Kubernetes的核心功能之一,它能够自动将Pod分配到最合适的节点上,并确保Pod在所选节点上正常运行。调度器通过算法选择最佳的节点,并将Pod绑定到该节点上。调度器选择节点的依据包括节点的资源使用情况、Pod的资源需求、亲和性和反亲和性等。管理员可以根据自己的需求选择不同的调度算法,并监视调度器的日志以确保集群的正常运行。  ———————————————— 版权声明:本文为CSDN博主「颜淡慕潇」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_36755535/article/details/131415996 
  • [产品讨论] 跟calico 相关联的BIRD是什么
    github: cid:link_2BIRD是什么      BIRD是布拉格查理大学数学与物理学院的一个学校项目,项目名是BIRD Internet Routing Daemon的缩写。 目前,它由CZ.NIC实验室开发和支持。     BIRD项目旨在开发一个功能齐全的动态 IP 路由守护进程,主要针对(但不限于)Linux,FreeBSD和其他类UNIX系统,并在GNU通用公共许可证下分发。详细信息参照官网 https://bird.network.cz    calico 中的 Bird是一个BGP client,它会主动读取felix在host上设置的路由信息,然后通过BGP协议广播出去.bird github上主要是提供了 bird,bird6,birdcl 3个可执行程序如果要通过编译源代码则有点不容易,我经过测试,通过下在 bird2.07 的源码比较靠谱birdcl 命令1987  birdcl -s /var/run/calico/bird.ctl  show protocols1988  birdcl -s /var/run/calico/bird.ctl  show status1989  birdcl -s /var/run/calico/bird.ctl  show interface1990  birdcl -s /var/run/calico/bird.ctl  show protocols1991  birdcl -s /var/run/calico/bird.ctl  show ospf interface1992  birdcl -s /var/run/calico/bird.ctl  show ospf status1993  birdcl -s /var/run/calico/bird.ctl  show ospf state1994  birdcl -s /var/run/calico/bird.ctl  show state1995  birdcl -s /var/run/calico/bird.ctl  show static1996  birdcl -s /var/run/calico/bird.ctl  show bfd session1997  birdcl -s /var/run/calico/bird.ctl  show route1998  birdcl -s /var/run/calico/bird.ctl  show configurate1999  birdcl -s /var/run/calico/bird.ctl  dump routes2000  birdcl -s /var/run/calico/bird.ctl show route/usr/local/etc/bird.conf cat /usr/local/etc/bird.conf# This is a basic configuration file, which contains boilerplate options and# some basic examples. It allows the BIRD daemon to start but will not cause# anything else to happen.## Please refer to the BIRD User's Guide documentation, which is also available# online at cid:link_4 in HTML format, for more information on# configuring BIRD and adding routing protocols.# Configure logginglog syslog all;# log "/var/log/bird.log" { debug, trace, info, remote, warning, error, auth, fatal, bug };# Set router ID. It is a unique identification of your router, usually one of# IPv4 addresses of the router. It is recommended to configure it explicitly.# router id 198.51.100.1;# Turn on global debugging of all protocols (all messages or just selected classes)# debug protocols all;# debug protocols { events, states };# Turn on internal watchdog# watchdog warning 5 s;# watchdog timeout 30 s;# You can define your own constants# define my_asn = 65000;# define my_addr = 198.51.100.1;# Tables master4 and master6 are defined by default# ipv4 table master4;# ipv6 table master6;# Define more tables, e.g. for policy routing or as MRIB# ipv4 table mrib4;# ipv6 table mrib6;# The Device protocol is not a real routing protocol. It does not generate any# routes and it only serves as a module for getting information about network# interfaces from the kernel. It is necessary in almost any configuration.protocol device {}# The direct protocol is not a real routing protocol. It automatically generates# direct routes to all network interfaces. Can exist in as many instances as you# wish if you want to populate multiple routing tables with direct routes.protocol direct {       disabled;               # Disable by default       ipv4;                   # Connect to default IPv4 table       ipv6;                   # ... and to default IPv6 table}# The Kernel protocol is not a real routing protocol. Instead of communicating# with other routers in the network, it performs synchronization of BIRD# routing tables with the OS kernel. One instance per table.protocol kernel {       ipv4 {                  # Connect protocol to IPv4 table by channel#             table master4;    # Default IPv4 table is master4#             import all;       # Import to table, default is import all             export all;       # Export to protocol. default is export none       };#       learn;                  # Learn alien routes from the kernel#       kernel table 10;        # Kernel table to synchronize with (default: main)}# Another instance for IPv6, skipping default optionsprotocol kernel {       ipv6 { export all; };}# Static routes (Again, there can be multiple instances, for different address# families and to disable/enable various groups of static routes on the fly).protocol static {       ipv4;                   # Again, IPv4 channel with default options#       route 0.0.0.0/0 via 198.51.100.10;#       route 192.0.2.0/24 blackhole;#       route 10.0.0.0/8 unreachable;#       route 10.2.0.0/24 via "eth0";#       # Static routes can be defined with optional attributes#       route 10.1.1.0/24 via 198.51.100.3 { rip_metric = 3; };#       route 10.1.2.0/24 via 198.51.100.3 { ospf_metric1 = 100; };#       route 10.1.3.0/24 via 198.51.100.4 { ospf_metric2 = 100; };}# Pipe protocol connects two routing tables. Beware of loops.# protocol pipe {#       table master4;          # No ipv4/ipv6 channel definition like in other protocols#       peer table mrib4;#       import all;             # Direction peer table -> table#       export all;             # Direction table -> peer table# }# RIP example, both RIP and RIPng are supported# protocol rip {#       ipv4 {#               # Export direct, static routes and ones from RIP itself#               import all;#               export where source ~ [ RTS_DEVICE, RTS_STATIC, RTS_RIP ];#       };#       interface "eth*" {#               update time 10;                 # Default period is 30#               timeout time 60;                # Default timeout is 180#               authentication cryptographic;   # No authentication by default#               password "hello" { algorithm hmac sha256; }; # Default is MD5#       };# }# OSPF example, both OSPFv2 and OSPFv3 are supported# protocol ospf v3 {#       ipv6 {#               import all;#               export where source = RTS_STATIC;#       };#       area 0 {#               interface "eth*" {#                       type broadcast;         # Detected by default#                       cost 10;                # Interface metric#                       hello 5;                # Default hello perid 10 is too long#               };#               interface "tun*" {#                       type ptp;               # PtP mode, avoids DR selection#                       cost 100;               # Interface metric#                       hello 5;                # Default hello perid 10 is too long#               };#               interface "dummy0" {#                       stub;                   # Stub interface, just propagate it#               };#       };#}# Define simple filter as an example for BGP import filter# See cid:link_1 for more examples# filter rt_import# {#       if bgp_path.first != 64496 then accept;#       if bgp_path.len > 64 then accept;#       if bgp_next_hop != from then accept;#       reject;# }# BGP example, explicit name 'uplink1' is used instead of default 'bgp1'# protocol bgp uplink1 {#       description "My BGP uplink";#       local 198.51.100.1 as 65000;#       neighbor 198.51.100.10 as 64496;#       hold time 90;           # Default is 240#       password "secret";      # Password used for MD5 authentication##       ipv4 {                  # regular IPv4 unicast (1/1)#               import filter rt_import;#               export where source ~ [ RTS_STATIC, RTS_BGP ];#       };##       ipv6 {                  # regular IPv6 unicast (2/1)#               import filter rt_import;#               export filter { # The same as 'where' expression above#                       if source ~ [ RTS_STATIC, RTS_BGP ]#                       then accept;#                       else reject;#               };#       };##       ipv4 multicast {        # IPv4 multicast topology (1/2)#               table mrib4;    # explicit IPv4 table#               import filter rt_import;#               export all;#       };##       ipv6 multicast {        # IPv6 multicast topology (2/2)#               table mrib6;    # explicit IPv6 table#               import filter rt_import;#               export all;#        import filter rt_import;#        export all;#       };#}# Template example. Using templates to define IBGP route reflector clients.# template bgp rr_clients {#       local 10.0.0.1 as 65000;#       neighbor as 65000;#       rr client;#       rr cluster id 1.0.0.1;##       ipv4 {#        import all;#        export where source = RTS_BGP;#       };##       ipv6 {#        import all;#        export where source = RTS_BGP;#       };# }## protocol bgp client1 from rr_clients {#       neighbor 10.0.1.1;# }## protocol bgp client2 from rr_clients {#       neighbor 10.0.2.1;# }## protocol bgp client3 from rr_clients {#       neighbor 10.0.3.1;# }root@node-10-120-13-236:~#                                         birdcl -s /var/run/calico/bird.ctl show route BIRD v0.3.3+birdv1.6.8 ready.0.0.0.0/0          via 10.120.13.1 on ens160 [kernel1 2020-12-31] * (10)192.168.98.0/26    via 10.120.13.237 on ens160 [Mesh_10_120_13_237 2020-12-31] * (100/0) [i]                  unreachable [Mesh_10_120_127_236 2021-01-01 from 10.120.127.236] (100/-) [i]                  unreachable [Mesh_10_120_127_235 2021-01-01 from 10.120.127.235] (100/-) [i]                  unreachable [Mesh_10_120_127_238 2021-01-01 from 10.120.127.238] (100/-) [i]                  unreachable [Mesh_10_120_127_237 2021-01-01 from 10.120.127.237] (100/-) [i]                  via 10.120.13.237 on ens160 [Mesh_10_120_13_238 2020-12-31 from 10.120.13.238] (100/0) [i]                  via 10.120.13.237 on ens160 [kernel1 2020-12-31] (10)192.168.100.0/26   blackhole [static1 2020-12-31] * (200)                  unreachable [Mesh_10_120_127_236 2021-01-01 from 10.120.127.236] (100/-) [i]                  unreachable [Mesh_10_120_127_235 2021-01-01 from 10.120.127.235] (100/-) [i]                  unreachable [Mesh_10_120_127_237 2021-01-01 from 10.120.127.237] (100/-) [i]                  unreachable [Mesh_10_120_127_238 2021-01-01 from 10.120.127.238] (100/-) [i]192.168.100.0/32   dev vxlan.calico [direct1 2020-12-31] * (240)192.168.100.5/32   dev calia2c25e78e3e [kernel1 2020-12-31] * (10)192.168.100.4/32   dev cali03f1aaccec2 [kernel1 2020-12-31] * (10)192.168.100.6/32   dev calicc710dcfd64 [kernel1 2020-12-31] * (10)192.168.69.192/26  via 10.120.13.1 on ens160 [Mesh_10_120_127_235 2021-01-01 from 10.120.127.235] * (100/?) [i]                  via 10.120.13.1 on ens160 [Mesh_10_120_127_236 2021-01-01 from 10.120.127.236] (100/?) [i]                  via 10.120.13.1 on ens160 [Mesh_10_120_127_237 2021-01-01 from 10.120.127.237] (100/?) [i]                  via 10.120.13.1 on ens160 [Mesh_10_120_127_238 2021-01-01 from 10.120.127.238] (100/?) [i]                  unreachable [Mesh_10_120_13_237 2020-12-31 from 10.120.13.237] (100/-) [i]                  unreachable [Mesh_10_120_13_238 2020-12-31 from 10.120.13.238] (100/-) [i]                  via 192.168.69.192 on vxlan.calico [kernel1 2020-12-31] (10)192.168.95.0/26    via 10.120.13.1 on ens160 [Mesh_10_120_127_235 2021-01-01 from 10.120.127.235] * (100/?) [i]                  via 10.120.13.1 on ens160 [Mesh_10_120_127_236 2021-01-01 from 10.120.127.236] (100/?) [i]                  via 10.120.13.1 on ens160 [Mesh_10_120_127_237 2021-01-01 from 10.120.127.237] (100/?) [i]                  via 10.120.13.1 on ens160 [Mesh_10_120_127_238 2021-01-01 from 10.120.127.238] (100/?) [i]                  unreachable [Mesh_10_120_13_237 2020-12-31 from 10.120.13.237] (100/-) [i]                  unreachable [Mesh_10_120_13_238 2020-12-31 from 10.120.13.238] (100/-) [i]                  via 192.168.95.0 on vxlan.calico [kernel1 2020-12-31] (10)192.168.34.192/26  via 10.120.13.238 on ens160 [Mesh_10_120_13_237 2020-12-31 from 10.120.13.237] * (100/0) [i]                  unreachable [Mesh_10_120_127_236 2021-01-01 from 10.120.127.236] (100/-) [i]                  unreachable [Mesh_10_120_127_235 2021-01-01 from 10.120.127.235] (100/-) [i]                  unreachable [Mesh_10_120_127_237 2021-01-01 from 10.120.127.237] (100/-) [i]                  unreachable [Mesh_10_120_127_238 2021-01-01 from 10.120.127.238] (100/-) [i]                  via 10.120.13.238 on ens160 [Mesh_10_120_13_238 2020-12-31] (100/0) [i]                  via 10.120.13.238 on ens160 [kernel1 2020-12-31] (10)192.168.56.128/26  via 10.120.13.1 on ens160 [Mesh_10_120_127_235 2021-01-01 from 10.120.127.235] * (100/?) [i]                  via 10.120.13.1 on ens160 [Mesh_10_120_127_236 2021-01-01 from 10.120.127.236] (100/?) [i]                  via 10.120.13.1 on ens160 [Mesh_10_120_127_237 2021-01-01 from 10.120.127.237] (100/?) [i]                  via 10.120.13.1 on ens160 [Mesh_10_120_127_238 2021-01-01 from 10.120.127.238] (100/?) [i]                  unreachable [Mesh_10_120_13_237 2020-12-31 from 10.120.13.237] (100/-) [i]                  unreachable [Mesh_10_120_13_238 2020-12-31 from 10.120.13.238] (100/-) [i]                  via 192.168.56.128 on vxlan.calico [kernel1 2020-12-31] (10)192.168.3.128/26   via 10.120.13.1 on ens160 [Mesh_10_120_127_235 2021-01-01 from 10.120.127.235] * (100/?) [i]                  via 10.120.13.1 on ens160 [Mesh_10_120_127_236 2021-01-01 from 10.120.127.236] (100/?) [i]                  via 10.120.13.1 on ens160 [Mesh_10_120_127_237 2021-01-01 from 10.120.127.237] (100/?) [i]                  via 10.120.13.1 on ens160 [Mesh_10_120_127_238 2021-01-01 from 10.120.127.238] (100/?) [i]                  unreachable [Mesh_10_120_13_237 2020-12-31 from 10.120.13.237] (100/-) [i]                  unreachable [Mesh_10_120_13_238 2020-12-31 from 10.120.13.238] (100/-) [i]                  via 192.168.3.128 on vxlan.calico [kernel1 2020-12-31] (10)10.120.13.0/24     dev ens160 [direct1 2020-12-31] * (240)172.17.0.0/16      dev docker0 [direct1 2020-12-31] * (240)bird的 github 上 有 配置的 样例cid:link_0bird的官网也有例子# Generated by confdinclude "bird_aggr.cfg";include "bird_ipam.cfg";router id 10.192.0.2;# Configure synchronization between routing tables and kernel.protocol kernel { learn;             # Learn all alien routes from the kernel persist;           # Don't remove routes on bird shutdown scan time 2;       # Scan kernel routing table every 2 seconds import all; export filter calico_kernel_programming; # Default is export none graceful restart;  # Turn on graceful restart to reduce potential flaps in                    # routes when reloading BIRD configuration.  With a full                    # automatic mesh, there is no way to prevent BGP from                    # flapping since multiple nodes update their BGP                    # configuration at the same time, GR is not guaranteed to                    # work correctly in this scenario.}# Watch interface up/down events.protocol device { debug { states }; scan time 2;    # Scan interfaces every 2 seconds}protocol direct { debug { states }; interface -"cali*", "*"; # Exclude cali* but include everything else.}# Template for all BGP clientstemplate bgp bgp_template { debug { states }; description "Connection to BGP peer"; local as 64512; multihop; gateway recursive; # This should be the default, but just in case. import all;        # Import all routes, since we don't know what the upstream                    # topology is and therefore have to trust the ToR/RR. export filter calico_export_to_bgp_peers;  # Only want to export routes for workloads. source address 10.192.0.2;  # The local address we use for the TCP connection add paths on; graceful restart;  # See comment in kernel section about graceful restart. connect delay time 2; connect retry time 5; error wait time 5,30;}# ------------- Node-to-node mesh -------------# This node is configured as a route reflector with cluster ID 10.0.0.1;# ignore node-to-node mesh setting.# ------------- Global peers -------------# No global peers configured.# ------------- Node-specific peers -------------# For peer /host/kube-master/peer_v4/172.19.4.87protocol bgp Node_172_19_4_87 from bgp_template { neighbor 172.19.4.87 as 64533;}
总条数:27 到第
上滑加载中