s19.基于 Kubernetes v1.25.0(kubeadm) 和 Docker 部署高可用

家电维修 2023-07-16 19:17www.caominkang.com家电维修技术

基于 Kuberes v1.25.0 和 Docker 部署高可用集群 主要内容
  • Kuberes 集群架构组成
  • 容器运行时 CRI
  • Kuberes v1.25 新特性
  • Kuberes v1.24 之后不再支持 Docker 的解决方案
  • Kuberes v1.25 高可用集群架构
  • 基于 Kuberes v1.25.0 和 Docker 部署高可用集群实战案例
1.Kuberes v1.25 新特性 1.1 Kuberes 组件

Docker 的运行机制

执行docker命令,这个docker命令实际上它是一个客户端,通过连接docker engine就是docker引擎,docker引擎和docker client有连接接口,然后docker引擎去调用containerd,然后再去连接containerd-shim这实际上就是一个所谓的中间的垫片,然后再去连接到runc,然后再去运行docker对应的容器,这就是docker的运行机制;这里边涉及到两个组件一个就是containerd,containerd属于docker的一部分,还有一个是runc,这两个合起来构成了docker运行的一个环境有一个专业的称呼叫运行时。

Kuberes的设计初衷是支持可插拔架构,从而利于扩展kuberes的功能。

k8s和docker的作用是不一样的,docker管理的是单个主机上的容器,而k8s它的目标是管理多个主机跨系统、跨平台的一个分布式的管理系统,可以说它是一个云原生的操作系统;

k8s里有很多丰富的组件,在k8s里边上图左侧是它的核心部分,右侧是它的一个配套的一个组件,可以分成两部分一个叫k8s的master节点,这个master节点可以认为就是主控节点,一个叫k8s的node节点叫ork节点,master就相当于公司的总部,node就相当于它下辖的一些公司或者分公司,具体完成任务的都是由node对应的工作节点来完成具体任务的,而master相对于一个控制中心它是一个总的管理者,你可以认为master就是领导node就是员工这样的一个关系,将来在k8s部署的时候至少需要有两台主机,一个充当master一个充当node这样才有意义,生产中的master和node为了高可用为了性能通常可能会有很多组机器,从角色来讲可以分层两类一个是master一个是node,可能将来会部署多个master以及多个node节点,这是从节点角色来做的介绍,那也就是我们需要部署两类主机一类充当master节点的服务器,一类充当node节点或者ork节点的服务器;

其中master节点上面它提供主控功能也就是控制功能,这个控制功能里边细分成若干个组件这些是k8s的核心组件,其中有一个叫做Kube-APIServer它相当于对外的总的联络中心,你可以认为它就相当于一个公司的总经办或者是秘书处,它对外提供一个总的接口,所有去访问k8s资源的都需要通过Kube-APIServer作为一个总的接口,你可以认为就是一个公司的前台一个总机,从外部进来都需要通过Kube-APIServer才能进入到公司内部,它是一个总的对外的连接的接口,大家都知道很多公司里边都有总经理办公室它下发指令给各个下属部门,这就是一个总出口也就是一个总的接口,所有相关的资源都要从Kube-APIServer进行接入,这是唯一的一个接口;

还有就是etcd它主要用来存储k8s的一些资源的,你可以认为它就是一个数据库,它本身实际上就是个数据库,这个数据库存放了k8s的各种信息、各种资源,你可以认为它就是类似于mysql一样的这样的数据库,它的数据库类型并不是用的关系型数据库,这里etcd数据库类似于公司里的档案、仓库,专门存储信息的这样一个组件;

第三个组件叫Kube-Scheduler称为计划调度器,在学习linux的时候学过所谓的调度就是crontab类似于的这种调度器就是周期性的任务,Kube-Scheduler也是有点相似的,有点像公交系统的调度系统,把整个k8s中接触的各种要求、工作给它下发到具体要完成的工作的某一个node节点,将来在企业里边node节点它是真正完成任务的节点,这个节点会很多,当我们收到一个具体的任务的时候,比方说要去运行一个java服务就需要通过Kube-Scheduler把任务转发到具体来完成这个任务的某一个工作节点,这个工作就交给Kube-Scheduler来进行调度、进行转发,这是个调度器;

因为k8s里边资源众多可能有几十个,资源不同管理方法也是不同的需要有一个Kube-Controller-Manager也叫控制器,控制器有很多,比如Route控制器、卷的控制器、node控制器等等,这个有点像比方说一个公司的总部里边有各个不同的科室,比如有财务室、人力资源、后勤等等,有各个部分这些部分分别来管控各种资源就是这样的一个大概的关系;

k8s的核心组件来说有几个组件,第一个叫Kube-APIServer相当于总经理办公室,是一个总的对外的一个接口,由它和别人进行接洽,就是etcd这就是数据库来存放相关的k8s的资源的,还有一个是Kube-Schduler调度把任务下发到node节点进行完成这些任务由调度来完成,再一个就是Kube-Controller-Manager它包含各种的控制器来管理各种资源,提供了各种控制功能,这就是整个k8s在master上的核心组件。

Kuberes提供了三个特定功能的接口,kuberes通过调用这几个接口,来完成相应的功能。

  • 容器运行时接口CRI: Container Runtime Interface

    kuberes 对于容器的解决方案,只是预留了容器接口,只要符合CRI标准的解决方案都可以使用

  • 容器网络接口CNI: Container Netork Interface

    kuberes 对于网络的解决方案,只是预留了网络接口,只要符合CNI标准的解决方案都可以使用

  • 容器存储接口CSI: Container Storage Interface

    kuberes 对于存储的解决方案,只是预留了存储接口,只要符合CSI标准的解决方案都可以使用此接口非必须

master它只是完成了领导性的任务,你可以理解为它就是一个管理中心,后续它要完成这些k8s里的工作,比如要跑一些服务还是要靠真正的node节点或者叫ork节点来完成的,这些ork节点和k8s之间怎么连接呢,就需要依赖于提供的三个接口,k8s为了支持更多的平台,k8s准确来说它实际上就是一个有点像淘宝一样的平台,它可以向外提供很多的第三方接入,你可以寄居在k8s的生态圈里边开发自己和k8s结合的各种组件,只要遵守它的相关接口规范即可,它的接口有3个接口,第一个叫容器运行时接口,这个容器运行时接口也就是说k8s管理的是容器,但这个容器到底用的是什么技术呢我们不关心,只要你遵守这个规范就可以了,有一个CRI的接口叫容器运行时接口,这个接口就是一种规范就是一种标准,你只要遵守这种规范不论你是用哪种容器技术都可以支持,目标来讲提供CRI最主流的技术仍然是docker,换句话说CRI以docker为主,目前已经并不唯一,也有一些其它的CRI也提供了,只要遵守这个CRI标准k8s就可以进行连接进行容器的管理;第二个叫CNI叫网络接口,这个网络接口简单的说就是通过k8s跨网络和node节点的的容器进行通讯,这个也需要有网络的解决方案,网络的解决方案也是要遵守这种k8s提供的网络接口规范的,这个接口规范目前来讲主流的有flannel和calico等等若干个解决方案这是用的比较多的,待会去部署k8s集群也必须要部署对应的CNI的某一种,如果不部署就相当于网络是没方法连通的,它是依赖于网络插件的,这些都是以插件方式提供的,因为k8s它只是提供了接口具体怎么实现我并不关心,你只要符合这个规范都是可以支持的;第三种叫CSI也就是存储,将来在k8s节点中运行的这些应用有可能需要有一些存储的需求,比如要存放数据、存放日志等这些需要有存储,存储也提供了一个所谓的叫CSI的接口,这个CSI接口来让我们这些工作节点将来把一些数据存放在某个地方,这个也是有一个规范的,不过应用有些没有存放数据的需求,所以CSI并不是一个必备的要求,你可以不需要。

容器运行时接口(CRI)

CRI是kuberes定义的一组gRPC服务。Kubelet作为客户端,基于gRPC协议通过Socket和容器运行时通信。

CRI 是一个插件接口,它使 kubelet 能够使用各种容器运行时,无需重新编译集群组件。

Kuberes 集群中需要在每个节点上都有一个可以正常工作的容器运行时, 这样 kubelet 能启动 Pod 及其容器。

容器运行时接口(CRI)是 kubelet 和容器运行时之间通信的主要协议。

CRI 括两类服务镜像服务(Image Service)和运行时服务(Runtime Service)。

镜像服务提供下载、检查和删除镜像的远程程序调用。

运行时服务包含用于管理容器生命周期,以及与容器交互的调用的远程程序调用。

OCI(Open Container Initiative,开放容器计划)定义了创建容器的格式和运行时的开源行业标准,包括镜像规范(Image Specification)和运行时规范(Runtime Specification)。

CRI叫容器运行时接口,这个容器运行时接口它实际上就是让k8s能够通过CRI能够和k8s的ork节点进行连接,并且去使用上面的容器技术,这个容器它是依赖于容器的运行时环境的,这个运行时环境目前来讲有很多,早期的时候只有k8s和docker是一个密切的结合,也就是说只有唯一的选择就是docker,现在经过多年的发展容器运行时也可以选择除了docker以外的其它的容器解决方案,CRI就是一个接口规范,容器的接口规范k8s已经定义了关于它的两种具体的服务,一种叫镜像服务一种叫运行时服务,镜像服务简单来说就是我定义了一个镜像的标准规范,比方说我们做这个容器的docker的时候这个镜像应该遵守哪种格式,它应该怎么去进行网络通讯等等,怎么去进行镜像的管理,就是容器运行的一个服务,这两个都是属于CRI的标准规范,k8s已经定义了这个标准规范,容器如果想使用k8s来进行通讯、进行相互的管理的话就要遵守这种规范。

对于容器运行时主要有两个级别Lo Level(使用接近内核层) 和 High Level(使用接近用户层)目前,市面上常用的容器引擎有很多,主要有下图的那几种。


CRI的运行时有两种,一种是低级运行时,还有一种是高级运行时,低级运行时可以认为就是更接近内核级,一个软件在运行的时候有的时候它属于易用性,有的时候它要和内核进行通讯,所以运行时是分成两类的,一个是低级的,比如说以runc为代表,runc主要是和内核进行通讯比较密切,而还有高级运行时,高级运行时主要是贴近用户的,也就是说用户去访问的时候是和高级运行时进行结合的,需要注意运行时这个概念是非常专业性的,对于很多人来讲不是很容易理解,什么叫运行时呢,简单说运行时就是一个程序运行的环境的集合,任何一个程序要运行都需要一套环境,例如java程序要运行它需要有java虚拟机,java虚拟机实际上就提供了java程序运行的运行时环境,简单说就是运行一个程序所需要的环境这就叫运行时,对应的还有一种叫编译时,比如一个程序刚刚开发出来它只是个源码,我要把它编译成一个二进制这时候就需要有编译时把它编译成一个可以执行的程序,这时候它就需要有一个叫编译这样的环境,它和运行时是两个不同阶段,一个程序先从源代码通过编译的这种环境把它编译成一个可以执行的二进制这就是编译时,然后最终要把它从二进制真正跑起来运行起来就需要用到运行时,所以这是不同的阶段需要依赖的环境,运行时表现主要是有两种,一种是这个程序运行所依赖的进程它有可能是相关的一些进程,也可以是它依赖的一些库,比如说java运行它有一些函数库它是要依赖的,简单的来说运行时它就是一套运行环境的依赖。

dockershim, containerd 和cri-o都是遵循CRI的容器运行时,我们称他们为高层级运行时(High-level Runtime)

其他的容器运营厂商最底层的runc仍然是Docker在维护的。

Google,CoreOS,RedHat都推出自已的运行时:lmctfy,rkt,cri-o,但到目前Docker仍然是最主流的容器引擎技术。


上图描述的就是k8s定义的两个规范,一个是CRI规范,k8s有个管理工具叫kubelet,它要去管理这些容器的话只要遵守CRI的规范那么这些容器都可以进行运行,这些运行目前来讲支持的容器遵守CRI的有很多,有docker为代表的、还有containerd、还有cri-o,这些都是遵守CRI的,也就是说目前来讲docker并不是唯一的选择,容器真正运行的时候它也有一个叫OCI的规范,OCI叫开放容器计划,它定义了创建容器的格式以及运行容器的标准规范,目前来讲这些都是行业标准,不论是用哪种的容器解决方案都是要左侧遵守CRI右侧要遵守OCI,容器的运行是遵守两套规范的,只有遵守两套规范才能上和k8s结合,下去调用这些所谓的标准的可以被别人所兼容的这种容器技术。

1.2 Kuberes v1.24 之后不再支持 Docker ?


2014年 Docker & Kuberes 蜜月期

2015~2016年 Kuberes & RKT vs Docker, 最终Docker 胜出

2016年 Kuberes逐渐赢得任务编排的胜利

2017年 rkt 和 containerd 捐献给 CNCF

2020年 kuberes宣布废弃dockershim,但 Mirantis 和 Docker 宣布维护 dockershim

2022年5月3日,Kuberes v1.24正式发布,此版本提供了很多重要功能。该版本涉及46项增强功能其中14项已升级为稳定版,15项进入beta阶段,13项则刚刚进入alpha阶段。,另有2项功能被弃用、2项功能被删除。v1.24 之前的 Kuberes 版本包括与 Docker Engine 的直接集成,使用名为 dockershim 的组件。 值得注意的是v1.24 的 Kuberes 正式移除对Dockershim的支持,即默认不再支持 docker

2022年8月24日,Kuberes v1.25 正式发布

在2013年docker开源之后,2014年k8s也开源,刚开始的时候在容器行业里边没有别的选择docker是唯一的选择,既然这样k8s当年和docker关系非常融洽,因为k8s属于弱者是后来者,它要想使用容器技术市面上没有别的选择只能和docker进行密切结合,当初在14年的时候它们是没有什么矛盾的,以谷歌为代表的k8s它不可能去屈从docker这样的小公司由你来主导,所以在后续就逐渐推出来一些相关的竞品来和docker竞争,k8s推出了相关的竞争产品RKT和docker进行竞争结果失败了没有成功docker胜出了,后续docker也电脑维修网希望能够进入到容器的编排领域它也开发了docker sarm产品,后期和k8s竞争失败了,也就是双方在各自擅长的领域都没有竞争过对方,双手只能在自己擅长的领域实现自己的目标,侵入到对方的地盘好像是非常困难的,后期k8s它把自己的一些相关技术就捐献到了CNCF,CNCF就是云原生的一个组织,在k8s逐渐占领企业级编排市场之后逐渐的它有了一定的主动权,在2020年它宣布要废除dockershim,这就是k8s 1.24以后不在支持docker的一个重要原因,宣布废止它没有立即废止,到了2年之后也就是2022年的5月3号它的1.24版发布之后正式剔除了dockershim这个组件,docker原来可以直接和k8s进行集成,现在不行了,需要额外的安装组件才可以,这就是它的一个重大变化,在3个月之后2022年的8月24号1.25正式发布。

官方说明

https://kuberes.io/zh-/docs/setup/production-environment/container-runtimes/


移除 Dockershim 的说明

https://kuberes.io/zh-/blog/2022/02/17/dockershim-faq/

Dockershim的历史背景

https://mp.eixin.qq./s/elkfBVzN8-zC30111zFpM

Kuberes CNCF 2022-05-03 10:40 发表于香港
作者Kat Cosgrove

从 Kuberes v1.24 开始,Dockershim 会给移除,这对于项目来说是个积极的举措。,无论是在社会上,还是在软件开发中,上下文对于完全理解某些东西都是很重要的,这值得更深入的研究。在 Kuberes v1.24 中移除 dockershim 的,我们在社区中看到了一些困惑(有时达到恐慌的程
度),和对这一决定的不满,很大程度上是由于缺乏关于这移除的上下文。弃用并最终将 dockershim 从 Kuberes 移除的决定,并不是迅速或轻率做出的。尽管如此,它已经操作了很长时间,以至于今天的许多用户都比这个决定更新,也比导致 dockershim 成为必要的选择更新。

那么,dockershim 是什么,为什么它会消失?

在 Kuberes 的早期,我们只支持一个容器运行时。那个运行时是 Docker Engine。当时,没有太多其他选择,Docker 是处理容器的主要工具,所以这不是个有争议的选择。最终,我们开始添加更多的容器运行时,比如 rkt 和 hyperes,很明显 Kuberes 用户电脑维修网希望选择最适合他们的运行时。 Kuberes 需要种方法,来允许集群操作者灵活地使用他们选择的任何运行时。

发布CRI[1](Container Runtime Interface,容器运行时接口)就是为了提供这种灵活性。CRI 的引入对项目和用户来说都很棒,但它也引入了一个问题Docker Engine 作为容器运行时的使用早于 CRI, Docker Engine 与 CRI 不兼容。为了解决这个问题,引入了一个小软件垫片("shim",dockershim)作为 kubelet 组件的一部分,专门用于填补 Docker Engine 和 CRI 之间的空白,允许集群运营商继续使用 Docker Engine 作为他们的容器运行时,基本上不会给中断。

,这个小小的软件垫片从来就不是永久的解决方案。多年来,它的存在给 kubelet 本身带来了许多不必要的复杂性。由于这个垫片,Docker 的一些集成实现不一致,导致维护人员的负担增加,并且维护特定于供应商的代码不符合我们的开源理念。为了减少这种维护负担,并向一个支持开放标准的更具协作性的社区发展,KEP-2221 获引入[2],它建议去掉 dockershim。随着 Kuberes v1.20 的发布,这一弃用成为正式。

我们没有很好地传达这一点,不幸的是,弃用声明导致了社区内的一些恐慌。对于 Docker 作为一家公司来说这意味着什么,由 Docker 构建的容器镜像能否运行,以及 Docker Engine 实际是什么导致了社交媒体上的一场大火。这是我们的过失;我们应该更清楚地沟通当时发生了什么以及原因。为了解决这个问题,我们发布了一个博客[3]和相关的常见问题[4],以减轻社区的恐惧,并纠正一些关于 Docker 是什么,以及容器如何在 Kuberes 中工作的误解。由于社区的关注,Docker 和 Mirantis 共同同意以cri-docker[5]的形式继续支持 dockershim 代码,允许你在需要时继续使用 Docker Engine 作为你的容器运行时。为了让那些想尝试其他运行时(如 containerd 或 cri-o)的用户感兴趣,编写了迁移文档[6]。

我们后来对社区进行了调查[7],发现仍然有许多用户有问题和顾虑[8]。作为回应,Kuberes 维护者和 CNCF 致力于通过扩展文档和其他程序来解决这些问题。事实上,这篇博文就是这个计划的一部分。随着如此多的最终用户成功地迁移到其他运行时,以及文档的改进,我们相信现在每个人都有了迁移的道路。

无论是作为工具还是作为公司,Docker 都不会消失。它是云原生社区和 Kuberes 项目历史的重要组成部分。没有他们我们不会有今天。也就是说,从 kubelet 中移除 dockershim 最终对社区、生态系统、项目和整个开源都有好处。这是我们所有人一起支持开放标准的机会,我们很高兴在 Docker 和社区的帮助下这样做。

Kuberes 调用 runtime 的变化


k8s和docker之间的关系,上面4张图详细的描述了k8s和docker之间的从蜜月期到后期的分道扬镳中间的分分合合的历史,刚开始k8s刚刚诞生的时候docker已经在市面上有很强的市场号召力,而且它基本上已经是容器的唯一选择,在市面上没有容器的其它技术所竞争,所以k8s为了使用容器被逼无奈降低身段和docker密切结合,它当时去使用docker的话采用的机制很简单就是在k8s里面内置了一个docker的客户端,docker命令实际上它就是个客户端,在系统中运行docker它会开启一个守护进程,docker命令实际上就是充当客户端的,k8s为了使用docker它就开发在k8s里边内置了一个客户端直接连接docker从而就可以使用docker的容器了,这是最早时候的状态;

这种状态并没有持续太久,因为谷歌还是很有野心的,不可能一辈子依赖docker,如果是这样子的话永远跟着docker的脚步走这是很痛苦的,docker万一发生了一些接口的变化k8s就得改,k8s肯定是不甘心的,后期它就发布了一个所谓的概念叫CRI容器运行时接口,这个容器运行时接口简单的说就是k8s发布了一个接口,这个接口是一个公开的接口,这个接口尽可能保持稳定,有点像电源插座一样标准规范发布出来基本就不动了,通过这个接口再接入到k8s里边去,docker肯定不可能说主动的去上贴你的k8s,我去遵守你的CRI,docker当时的地位也是如日中天在容器领域一手遮天,所以它不可能去放下身段说我开发一个接口和你的CRI兼容,所以k8s当时为了让docker兼容它的CRI它就自己开发了一个软件叫dockershim,dockershim是k8s为了兼容docker开发的一个中间的组件,shim其实就是垫片的意思中间的一个小接口,这个小接口就是为了让k8s通过CRI接口连接到dockershim,dockershim是遵守CRI的,因为dockershim是k8s开发出来的,然后dockershim再去连接docker,从而让docker能够和k8s结合在一起,这就是后期的第二个阶段;

第三个阶段终于采取了进一步的手段,如果老是附着着docker k8s永无独立之日,它后期就变了,它把dockershim这个组件独立出来了,不再和k8s集成在一起,也就是说k8s发布的时候是没有dockershim的,这个dockershim是个独立的软件,你需要单独安装,早期的时候实际上它安装k8s的时候它会自动的把dockershim组件给你装上,这个组件已经不是内置在k8s的组件里了,它是个独立的软件了,只不过这个软件k8s安装会顺便给你装上,这个软件已经独立了,和刚才的状态已经不一样了,刚才dockershim是和k8s是在一起的,相当于一个软件内部就有了dockershim,现在它已经独立出来了,虽然是独立了这个软件仍然是由k8s开发出来的,因为docker并不遵守CRI;

接下来重头戏到了也就是1.24发布之后彻底的颠覆了我们之前的状态,因为1.24的时候k8s已经在江湖上赫赫有名,已经不在依附于docker,当时的容器技术也不仅仅只有docker可选,还有其它的容器可选,它就终于独立了,它决定把dockershim这个组件不在开发把它移除,这时候就变成了什么样子了,dockershim就彻底的没有了,1.24把dockershim抛弃了docker就没方法通过CRI和k8s进行通讯,自然k8s也就没有方法来使用docker的容器技术,docker也没有方法通过k8s来进行结合使用,这个对于k8s来讲已经不是问题,因为k8s除了docker以外它还有其它的容器技术可选,而docker对应的企业级的编排的领域只有k8s可选,因为k8s已经是垄断地位它没有第三方可选,在这种情况下docker放低身段只好自己开发一个软件贴在CRI基础之上这就是cri-dockerd,cri-dockerd是docker公司开发出来的,人家不兼容了抛弃你了,人家不理你了我就上杆子自己做个软件叫cri-dockerd来遵守CRI从而才能和k8s组合在一起。


1.3 Kuberes v1.25 新变化


2022年8月24日,Kuberes v1.25 正式发布

Kuberes 1.25主题是Combiner,即组合器。

Kuberes 1.25中包含多达40项增强功能

https://mp.eixin.qq./s/PKoNkhPU6OhjuuPzELP-Rg

PodSecurityPolicy被移除;Pod Security Admission毕业为稳定版

PodSecurityPolicy是在1.21版本中被决定弃用的,到1.25版本则将被正式删除。之所以删除此项功能,是因为想要进一步提升其可用性,就必须引入重大变更。为了保持项目整体稳定,只得加以弃用。取而代之的正是在1.25版本中毕业至稳定版的Pod Security Admission。如果你当前仍依赖PodSecurityPolicy,请按照Pod Security Admission迁移说明[1]进行操作。

临时容器迎来稳定版

临时容器是指在Pod中仅存在有限时长的容器。当我们需要检查另一容器,但又不能使用kubectl exec时(例如在执行故障排查时),往往可以用临时容器替代已经崩溃、或者镜像缺少调试工具的容器。临时容器在Kuberes 1.23版本中已经升级至Beta版,这一次则进一步升级为稳定版。

对cgroups v2的稳定支持

自Linux内核cgroups v2 API公布稳定版至今,已经过去两年多时间。如今,已经有不少发行版默认使用此API,Kuberes自然需要支持该内核才能顺利对接这些发行版。Cgroups v2对cgroups v1做出了多项改进,更多细节请参见cgroups v2说明文档[2]。虽然cgroups v1将继续受到支持,但我们后续将逐步弃用v1并全面替换为v2。

更好的Windos系统支持

  • 性能仪表板添加了对Windos系统的支持
  • 单元测试增加了对Windos系统的支持
  • 一致性测试增加了对Windos系统的支持
  • 为Windos Operational Readiness创建了新的GitHub

将容器注册服务从k8s.gcr.io移动至registry.k8s.io

1.25版本已经合并将容器注册服务从k8s.gcr.io移动至registry.k8s.io的变更。关于更多细节信息,请参阅相应iki页面[3],我们也通过Kuberes开发邮件清单发出了全面通报。

SecpDefault升级为Beta版

网络策略中的endPort已升级为稳定版

网络策略中的endPort已经迎来GA通用版。支持endPort字段的网络策略提供程序,现可使用该字段来指定端口范围以应用网络策略。在之前的版本中,每个网络策略只能指向单一端口。

请注意,endPort的起效前提是必须得到网络策略提供程序的支持。如果提供程序不支持endPort,而您又在网络策略中指定了此字段,则会创建出仅覆盖端口字段(单端口)的网络策略。

本地临时存储容量隔离迎来稳定版

本地临时存储容量隔离功能已经迎来GA通用版。这项功能最早于1.8版本中公布了alpha版,在1.10中升级至beta,如今终于成为稳定功能。它通解为各Pod之间的本地临时存储提供容量隔离支持,例如EmptyDir。如果Pod对本地临时存储容量的消耗超过了该上限,则会驱逐该Pod以限制其对共享资源的占用。

核心CSI迁移迎来稳定版

CSI迁移是SIG Storage在之前多个版本中做出的持续努力,目标是将树内存储卷插件移动到树外CSI驱动程序,并最终移除树内存储卷插件。此次核心CSI迁移已迎来GA通用版,GCE PD和AWS EBS的CSI迁移功能也同步达到GA阶段。vSphere的CSI迁移仍处于beta阶段(但也已经默认启用),Portorx的CSI迁移功能同样处于beta阶段(默认关闭)。

CSI临时存储卷提升至稳定版

CSI临时存储卷功能,允许用户在临时用例的pod规范中直接指定CSI存储卷。如此一来,即可使用已安装的存储卷直接在pod内注入任意状态,例如配置、机密、身份、变量或其他类似信息。这项功能最初于1.15版本中推出alpha版,现已升级为GA通用版。某些CSI驱动程序会使用此功能,例如负责存储秘密信息的CSI驱动程序。

CRD验证表达式语言升级至Beta版

CRD验证表达式语言现已升级为beta版,声明能够使用通用表达式语言(CEL)验证自定义资源。

服务器端未知字段验证升级为Beta版

ServerSideFieldValidation功能门现已升级为Beta版(默认启用),允许用户在检测到未知字段时,有选择地触发API服务器上的模式验证机制。如此一来,即可从kubectl中删除客户端验证,继续保持对包含未知/无效字段的请求报错。

引入KMS v2 API

引入KMS v2 alpha1 API以提升性能,实现轮替与可观察性改进。此API使用AES-GCM替代了AES-CBC,通过DEK实现静态数据(即Kuberes Secrets)加密。过程中无需额外用户操作,而且仍然支持通过AES-GCM和AES-CBC进行读取

1.4 Kuberes v1.25 集群创建方案


上图描述了k8s和docker的关系,用户通过k8s的REST API接口去连接kube-apiserver,然后通过kube-apiserver连接kubelet,kubelet通过CRI接口去连接下面的容器,目前来讲去使用容器的话有常见的3中选择,可以选择用cri-docker连接到docker再去通过containerd去runC再去container,可以使用右侧一条线来使用容器这是早期已经使用的调用方法,因为1.24已经抛弃dockershim换成cri-docker,而k8s电脑维修网希望能够尽可能摆脱docker的限制,它就默认CRI接口用的是containerd,containerd和CRI之间需要有一个垫片这个垫片通过CRI-Containerd连接到containerd再去运行容器,containerd不论是docker而好还是CRI-Containerd都用的这个组件,这个组件实际上也是docker开源出来的捐献给CNCF了,containerd究其根本还是docker公司的,只不过要想使用docker命令你就必须使用docker Engine,必须要安装cri-docker组件,如果用containerd可以不安装docker,直接用默认的就可以,只装containerd就行,containerd要操作容器的话就不方便,它用的工具并不是我们熟悉的工具,而目前大家更熟悉的是docker命令,目前来讲安装的话还是要用docker需要安装cri-docker包括docker Engine,底层它实际上还是走的是containerd,它缺少用户空间的工具,如果不去安装docker的话哪些工具就没方法使用了,除此之外还有一个CRI-O它是红帽公司研发出来的容器技术,不过这个在生产中是很少使用的技术,containerd是高级运行时,runC是低级运行时,这两个技术都是docker开源出来的,也就是说实际上还是离不开docker的影响,只不过表面上脱离了docker的管理了。

  • 方式1: Containerd

    默认情况下,Kuberes在创建集群的时候,使用的就是Containerd 方式。

  • 方式2: Docker

    Docker使用的普及率较高,虽然Kuberes-v1.24 默认情况下废弃了kubelet对于Docker的支持,我们还可以借助于Mirantis维护的cri-dockerd插件方式来实现Kuberes集群的创建。

    Docker Engine 没有实现 CRI, 而这是容器运行时在 Kuberes 中工作所需要的。 为此,必须安装一个额外的服务 cri-dockerd。 cri-dockerd 是一个基于传统的内置 Docker 引擎支持的项目, 它在 1.24 版本从 kubelet 中移除

    项目站点: https://github./Mirantis/cri-dockerd

  • 方式3: CRI-O

    CRI-O的方式是Kuberes创建容器最直接的一种方式,在创建集群的时候,需要借助于cri-o插件的方式来实现Kuberes集群的创建。

2.Kuberes 高可用集群部署架构

本示例中的Kuberes集群部署将基于以下环境进行。


表1-1 高可用Kuberes集群规划

角色机器名机器配置ip地址安装软件K8s 集群主节点 1,Master和etcdk8s-master01.example.local2C4G172.31.3.101chrony-client、docker、kubeadm 、kubelet、kubectlK8s 集群主节点 2,Master和etcdk8s-master02.example.local2C4G172.31.3.102chrony-client、docker、kubeadm 、kubelet、kubectlK8s 集群主节点 3,Master和etcdk8s-master03.example.local2C4G172.31.3.103chrony-client、docker、kubeadm 、kubelet、kubectlK8s 主节点访问入口 1,提供高可用及负载均衡k8s-ha01.example.local2C2G172.31.3.104chrony-server、haproxy、keepalivedK8s 主节点访问入口 2,提供高可用及负载均衡k8s-ha02.example.local2C2G172.31.3.105chrony-server、haproxy、keepalived容器镜像仓库1k8s-harbor01.example.local2C2G172.31.3.106chrony-client、docker、docker-pose、harbor容器镜像仓库2k8s-harbor02.example.local2C2G172.31.3.107chrony-client、docker、docker-pose、harborK8s 集群工作节点 1k8s-node01.example.local2C4G172.31.3.108chrony-client、docker、kubeadm 、kubeletK8s 集群工作节点 2k8s-node02.example.local2C4G172.31.3.109chrony-client、docker、kubeadm 、kubeletK8s 集群工作节点 3k8s-node03.example.local2C4G172.31.3.110chrony-client、docker、kubeadm 、kubeletVIP,在ha01和ha02主机实现k8s.example.local172.31.3.188

软件版本信息和Pod、Service网段规划

配置信息备注支持的操作系统版本CentOS 7.9/stream 8、Rocky 8、Ubuntu 18.04/20.04Container Runtime:Docker CE 20.10.17CRIcri-dockerd v0.2.5kubeadm版本1.25.0宿主机网段172.31.0.0/21Pod网段192.168.0.0/12Service网段10.96.0.0/12 3.基于Kubeadm 实现 Kuberes v1.25.0集群部署流程说明

官方说明

https://kuberes.io/docs/setup/production-environment/tools/kubeadm/

https://kuberes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/

https://kuberes.io/zh-/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/

使用 kubeadm,能创建一个符合最佳实践的最小化 Kuberes 集群。 事实上,你可以使用 kubeadm配置一个通过 Kuberes 一致性测试的集群。 kubeadm 还支持其他集群生命周期功能, 例如启动引导令牌和集群升级。

  • 每个节点主机的初始环境准备
  • Kuberes集群API访问入口的高可用
  • 在所有Master和Node节点都安装容器运行时,实际Kuberes只使用其中的Containerd在所有Master和Node节点安装kubeadm 、kubelet、kubectl
  • 在所有节点安装和配置 cri-dockerd
  • 在第一个 master 节点运行 kubeadm init 初始化命令 ,并验证 master 节点状态
  • 在第一个 master 节点安装配置网络插件
  • 在其它master节点运行kubeadm join 命令加入到控制平面集群中
  • 在所有 node 节点使用 kubeadm join 命令加入集群
  • 创建 pod 并启动容器测试访问 ,并测试网络通信
4.基于Kubeadm 部署 Kuberes v1.25.0高可用集群案例 4.1 所有主机初始化 4.1.1 设置ip地址
#CentOS
[root@k8s-master01 ~]# cat /etc/sysconfig/ork-scripts/ifcfg-eth0 
DEVICE=eth0
NAME=eth0
BOOTPROTO=none
ONBOOT=yes
IPADDR=172.31.3.101
PREFIX=21
GATEWAY=172.31.0.2
DNS1=223.5.5.5
DNS2=180.76.76.76

#Ubuntu
root@k8s-master01:~# cat /etc/plan/01-cfg.yaml 
ork:
  version: 2
  renderer: orkd
  ethers:
 eth0:
   addresses: [172.31.3.101/21] 
   gateay4: 172.31.0.2
   nameservers:
  addresses: [223.5.5.5, 180.76.76.76]
4.1.2 设置主机名
hostnamectl set-hostname k8s-master01.example.local
hostnamectl set-hostname k8s-master02.example.local
hostnamectl set-hostname k8s-master03.example.local
hostnamectl set-hostname k8s-ha01.example.local
hostnamectl set-hostname k8s-ha02.example.local
hostnamectl set-hostname k8s-harbor01.example.local
hostnamectl set-hostname k8s-harbor02.example.local
hostnamectl set-hostname k8s-node01.example.local
hostnamectl set-hostname k8s-node02.example.local
hostnamectl set-hostname k8s-node03.example.local
4.1.3 配置镜像源

CentOS 7所有节点配置 yum源如下

rm -f /etc/yum.repos.d#&/' /etc/fstab
sapoff -a

#Ubuntu 20.04,执行下面命令
sed -ri 's/.sap./#&/' /etc/fstab
SD_NAME=`lsblk|ak -F"[ └─]" '/SWAP/{printf $3}'`
systemctl mask dev-${SD_NAME}.sap
sapoff -a
4.1.10 时间同步

ha01和ha02上安装chrony-server:

[root@k8s-ha01 ~]# cat install_chrony_server.sh 
#!/bin/bash
#
#
#Author:  Raymond
#QQ:   88563128
#Date:    2021-11-22
#FileName:   install_chrony_server.sh
#URL:     raymond.blog.csdn.
#Description:   install_chrony_server for CentOS 7/8 & Ubuntu 18.04/20.04 & Rocky 8
#Copyright (C): 2021 All rights reserved
#
COLOR="echo -e \033[01;31m"
END='33[0m'

os(){
 OS_ID=`sed -rn '/^NAME=/s@.="([[:alpha:]]+)."$p' /etc/os-release`
}

install_chrony(){
 if [ ${OS_ID} == "CentOS" -o ${OS_ID} == "Rocky" ] &> /dev/null;then
  yum -y install chrony &> /dev/null
  sed -i -e '/^pool./d' -e '/^server./d' -e '/^# Please consider ./aserver ntp.aliyun. iburstnserver time1.cloud.tencent. iburstnserver ntp.tuna.tsinghua.edu. iburst' -e 's@^#allo.@allo 0.0.0.0/0@' -e 's@^#local.@local stratum 10@' /etc/chrony.conf
  systemctl enable --no chronyd &> /dev/null
  systemctl is-active chronyd &> /dev/null ||  { ${COLOR}"chrony 启动失败,退出!"${END} ; exit; }
  ${COLOR}"chrony安装完成"${END}
 else
  apt -y install chrony &> /dev/null
  sed -i -e '/^pool./d' -e '/^# See http:./aserver ntp.aliyun. iburstnserver time1.cloud.tencent. iburstnserver ntp.tuna.tsinghua.edu. iburst' /etc/chrony/chrony.conf
  echo "allo 0.0.0.0/0" >> /etc/chrony/chrony.conf
  echo "local stratum 10" >> /etc/chrony/chrony.conf
  systemctl enable --no chronyd &> /dev/null
  systemctl is-active chronyd &> /dev/null ||  { ${COLOR}"chrony 启动失败,退出!"${END} ; exit; }
  ${COLOR}"chrony安装完成"${END}
 fi
}

main(){
 os
 install_chrony
}

main

[root@k8s-ha01 ~]# bash install_chrony_server.sh 
chrony安装完成

[root@k8s-ha02 ~]# bash install_chrony_server.sh 
chrony安装完成

[root@k8s-ha01 ~]# chronyc sources -nv
210 Number of sources = 3
MS Name/IP address   Stratum Poll Reach LastRx Last sample      
===============================================================================
^ 203.107.6.88      2   6 17 39  -1507us[-8009us] +/-   37ms
^- 139.199.215.251      2   6 17 39 +10ms[  +10ms] +/-   48ms
^? 101.6.6.172       0   7  0  -  +0ns[   +0ns] +/- 0ns

[root@k8s-ha02 ~]# chronyc sources -nv
210 Number of sources = 3
MS Name/IP address   Stratum Poll Reach LastRx Last sample      
===============================================================================
^ 203.107.6.88      2   6 17 40 +90us[-1017ms] +/-   32ms
^+ 139.199.215.251      2   6 33 37 +13ms[  +13ms] +/-   25ms
^? 101.6.6.172       0   7  0  -  +0ns[   +0ns] +/- 0ns

master、node、harbor上安装chrony-client:

[root@k8s-master01 ~]# cat install_chrony_client.sh 
#!/bin/bash
#
#
#Author:  Raymond
#QQ:   88563128
#Date:    2021-11-22
#FileName:   install_chrony_client.sh
#URL:     raymond.blog.csdn.
#Description:   install_chrony_client for CentOS 7/8 & Ubuntu 18.04/20.04 & Rocky 8
#Copyright (C): 2021 All rights reserved
#
COLOR="echo -e \033[01;31m"
END='33[0m'
SERVER1=172.31.3.104
SERVER2=172.31.3.105

os(){
 OS_ID=`sed -rn '/^NAME=/s@.="([[:alpha:]]+)."$p' /etc/os-release`
}

install_chrony(){
 if [ ${OS_ID} == "CentOS" -o ${OS_ID} == "Rocky" ] &> /dev/null;then
  yum -y install chrony &> /dev/null
  sed -i -e '/^pool./d' -e '/^server./d' -e '/^# Please consider ./aserver '${SERVER1}' iburstnserver '${SERVER2}' iburst' /etc/chrony.conf
  systemctl enable --no chronyd &> /dev/null
  systemctl is-active chronyd &> /dev/null ||  { ${COLOR}"chrony 启动失败,退出!"${END} ; exit; }
  ${COLOR}"chrony安装完成"${END}
 else
  apt -y install chrony &> /dev/null
  sed -i -e '/^pool./d' -e '/^# See http:./aserver '${SERVER1}' iburstnserver '${SERVER2}' iburst' /etc/chrony/chrony.conf
  systemctl enable --no chronyd &> /dev/null
  systemctl is-active chronyd &> /dev/null ||  { ${COLOR}"chrony 启动失败,退出!"${END} ; exit; }
  systemctl restart chronyd
  ${COLOR}"chrony安装完成"${END}
 fi
}

main(){
 os
 install_chrony
}

main

[root@k8s-master01 ~]# for i in k8s-master02 k8s-master03 k8s-harbor01 k8s-harbor02 k8s-node01 k8s-node02 k8s-node03;do scp install_chrony_client.sh $i:/root/ ; done

[root@k8s-master01 ~]# bash install_chrony_client.sh 
chrony安装完成

[root@k8s-master01 ~]# chronyc sources -nv
210 Number of sources = 2
MS Name/IP address   Stratum Poll Reach LastRx Last sample      
===============================================================================
^+ k8s-ha01       3   6 17  8 +84us[  +74us] +/-   55ms
^ k8s-ha02       3   6 17  8 -82us[  -91us] +/-   45ms
4.1.11 设置时区
#CentOS
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
echo 'Asia/Shanghai' >/etc/timezone

#Ubuntu
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
echo 'Asia/Shanghai' >/etc/timezone

cat >> /etc/default/locale <<-EOF
LC_TIME=en_DK.UTF-8
EOF
4.1.12 优化资源限制参数
ulimit -SHn 65535

cat >>/etc/security/limits.conf < 
4.1.13 内核配置 

CentOS7 需要升级内核至4.18+,本地升级的版本为4.19

在master01节点下载内核

[root@k8s-master01 ~]# get http://193.49.22.109/elrepo/kernel/el7/x86_64/RPMS/kernel-ml-devel-4.19.12-1.el7.elrepo.x86_64.rpm

[root@k8s-master01 ~]# get http://193.49.22.109/elrepo/kernel/el7/x86_64/RPMS/kernel-ml-4.19.12-1.el7.elrepo.x86_64.rpm

从master01节点传到其他节点

[root@k8s-master01 ~]# for i in k8s-master02 k8s-master03 k8s-node01 k8s-node02 k8s-node03;do scp kernel-ml-4.19.12-1.el7.elrepo.x86_64.rpm kernel-ml-devel-4.19.12-1.el7.elrepo.x86_64.rpm $i:/root/ ; done

所有节点安装内核

cd /root && yum localinstall -y kernel-ml

所有节点更改内核启动顺序

grub2-set-default 0 && grub2-mkconfig -o /etc/grub2.cfg

grubby --args="user_namespace.enable=1" --update-kernel="$(grubby --default-kernel)"

检查默认内核是不是4.19

grubby --default-kernel

[root@k8s-master01 ~]# grubby --default-kernel
/boot/vmlinuz-4.19.12-1.el7.elrepo.x86_64

所有节点重启,然后检查内核是不是4.19

reboot

uname -a

[root@k8s-master01 ~]# uname -a
Linux k8s-master01 4.19.12-1.el7.elrepo.x86_64 #1 SMP Fri Dec 21 11:06:36 EST 2018 x86_64 x86_64 x86_64 GNU/Linux

master和node安装ipvsadm

#CentOS
yum -y install ipvsadm ipset sysstat conntrack libsecp

#Ubuntu
apt -y install ipvsadm ipset sysstat conntrack libsecp-dev

所有节点配置ipvs模块,在内核4.19+版本nf_conntrack_ipv4已经改为nf_conntrack, 4.18以下使用nf_conntrack_ipv4即可

modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_rr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack #内核小于4.18,把这行改成nf_conntrack_ipv4

cat >> /etc/modules-load.d/ipvs.conf < 

开启一些k8s集群中必须的内核参数,所有节点配置k8s内核

cat > /etc/sysctl.d/k8s.conf < 

Kuberes内核优化常用参数详解

.ipv4.ip_forard = 1 #其值为0,说明禁止进行IP转发;如果是1,则说明IP转发功能已经打开。
.bridge.bridge-nf-call-iptables = 1 #二层的网桥在转发包时也会被iptables的FORWARD规则所过滤,这样有时会出现L3层的iptables rules去过滤L2的帧的问题
.bridge.bridge-nf-call-ip6tables = 1 #是否在ip6tables链中过滤IPv6包 
fs.may_detach_mounts = 1 #当系统有容器运行时,需要设置为1

vm.overmit_memory=1  
#0, 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
#1, 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
#2, 表示内核允许分配超过所有物理内存和交换空间总和的内存

vm.panic_on_oom=0 
#OOM就是out of memory的缩写,遇到内存耗尽、无法分配的状况。kernel面对OOM的时候,咱们也不能慌乱,要根据OOM参数来进行相应的处理。
#值为0内存不足时,启动 OOM killer。
#值为1内存不足时,有可能会触发 kernel panic(系统重启),也有可能启动 OOM killer。
#值为2内存不足时,表示强制触发 kernel panic,内核崩溃GG(系统重启)。

fs.inotify.max_user_atches=89100 #表示同一用户可以添加的atch数目(atch一般是针对目录,决定了同一用户可以监控的目录数量)

fs.file-max=52706963 #所有进程最大的文件数
fs.nr_open=52706963 #单个进程可分配的最大文件数
.filter.nf_conntrack_max=2310720 #连接跟踪表的大小,建议根据内存计算该值CONNTRACK_MAX = RAMSIZE (in bytes) / 16384 / (x / 32),并满足nf_conntrack_max=4nf_conntrack_buckets,默认262144

.ipv4.tcp_keepalive_time = 600  #KeepAlive的空闲时长,或者说每次正常发送心跳的周期,默认值为7200s(2小时)
.ipv4.tcp_keepalive_probes = 3 #在tcp_keepalive_time之后,没有接收到对方确认,继续发送保活探测包次数,默认值为9(次)
.ipv4.tcp_keepalive_intvl =15 #KeepAlive探测包的发送间隔,默认值为75s
.ipv4.tcp_max_t_buckets = 36000 #Nginx 之类的中间代理一定要关注这个值,因为它对你的系统起到一个保护的作用,一旦端口全部被占用,服务就异常了。 tcp_max_t_buckets 能帮你降低这种情况的发生概率,争取补救时间。
.ipv4.tcp_t_reuse = 1 #只对客户端起作用,开启后客户端在1s内回收
.ipv4.tcp_max_orphans = 327680 #这个值表示系统所能处理不属于任何进程的socket数量,当我们需要快速建立大量连接时,就需要关注下这个值了。

.ipv4.tcp_orphan_retries = 3
#出现大量fin-ait-1
#,fin发送之后,有可能会丢弃,那么发送多少次这样的fin包呢?fin包的重传,也会采用退避方式,在2.6.358内核中采用的是指数退避,2s,4s,的重试次数是由tcp_orphan_retries来限制的。

.ipv4.tcp_syncookies = 1 #tcp_syncookies是一个开关,是否打开SYN Cookie功能,该功能可以防止部分SYN攻击。tcp_synack_retries和tcp_syn_retries定义SYN的重试次数。
.ipv4.tcp_max_syn_backlog = 16384 #进入SYN包的最大请求队列.默认1024.对重负载服务器,增加该值显然有好处.
.ipv4.ip_conntrack_max = 65536 #表明系统将对最大跟踪的TCP连接数限制默认为65536
.ipv4.tcp_max_syn_backlog = 16384 #指定所能接受SYN同步包的最大客户端数量,即半连接上限;
.ipv4.tcp_timestamps = 0 #在使用 iptables 做 nat 时,发现内网机器 ping 某个域名 ping 的通,而使用 curl 测试不通, 原来是 .ipv4.tcp_timestamps 设置了为 1 ,即启用时间戳
.core.somaxconn = 16384	#Linux中的一个kernel参数,表示socket监听(listen)的backlog上限。什么是backlog呢?backlog就是socket的监听队列,当一个请求(request)尚未被处理或建立时,他会进入backlog。而socket server可以一次性处理backlog中的所有请求,处理后的请求不再位于监听队列中。当server处理请求较慢,以至于监听队列被填满后,新来的请求会被拒绝。

所有节点配置完内核后,重启服务器,保证重启后内核依旧加载

reboot
lsmod | grep --color=auto -e ip_vs -e nf_conntrack

[root@k8s-master01 ~]# lsmod | grep --color=auto -e ip_vs -e nf_conntrack
ip_vs_ftp     16384  0 
nf_nat     32768  1 ip_vs_ftp
ip_vs_sed     16384  0 
ip_vs_nq      16384  0 
ip_vs_fo      16384  0 
ip_vs_sh      16384  0 
ip_vs_dh      16384  0 
ip_vs_lblcr   16384  0 
ip_vs_lblc    16384  0 
ip_vs_rr     16384  0 
ip_vs_rr      16384  0 
ip_vs_lc     16384  0 
ip_vs_lc      16384  0 
ip_vs     151552  24 ip_vs_lc,ip_vs_rr,ip_vs_dh,ip_vs_lblcr,ip_vs_sh,ip_vs_fo,ip_vs_nq,ip_vs_lblc,ip_vs_rr,ip_vs_lc,ip_vs_sed,ip_vs_ftp
nf_conntrack    143360  2 nf_nat,ip_vs
nf_defrag_ipv6   20480  1 nf_conntrack
nf_defrag_ipv4   16384  1 nf_conntrack
libcrc32c     16384  4 nf_conntrack,nf_nat,xfs,ip_vs
4.2 部署 Kuberes 集群 API 访问入口的高可用

(注意如果不是高可用集群,haproxy和keepalived无需安装)

公有云要用公有云自带的负载均衡,比如阿里云的SLB,腾讯云的ELB,用来替代haproxy和keepalived,因为公有云大部分都是不支持keepalived的,如果用阿里云的话,kubectl控制端不能放在master节点,推荐使用腾讯云,因为阿里云的slb有回环的问题,也就是slb代理的服务器不能反向访问SLB,腾讯云修复了这个问题。

在172.31.3.104和172.31.3.105上实现如下操作

4.2.1 安装 HAProxy

利用 HAProxy 实现 Kubeapi 服务的负载均衡

[root@k8s-ha01 ~]# cat install_haproxy.sh 
#!/bin/bash
#
#
#Author:  Raymond
#QQ:   88563128
#Date:    2021-12-29
#FileName:   install_haproxy.sh
#URL:     raymond.blog.csdn.
#Description:   install_haproxy for CentOS 7/8 & Ubuntu 18.04/20.04 & Rocky 8
#Copyright (C): 2021 All rights reserved
#
SRC_DIR=/usr/local/src
COLOR="echo -e \033[01;31m"
END='33[0m'
CPUS=`lscpu |ak '/^CPU(s)/{print $2}'`

#lua下载地址http://.lua./ftp/lua-5.4.4.tar.gz
LUA_FILE=lua-5.4.4.tar.gz

#haproxy下载地址https://.haproxy./donload/2.6/src/haproxy-2.6.4.tar.gz
HAPROXY_FILE=haproxy-2.6.4.tar.gz
HAPROXY_INSTALL_DIR=/apps/haproxy

STATS_AUTH_USER=admin
STATS_AUTH_PASSWORD=123456

VIP=172.31.3.188
MASTER01=172.31.3.101
MASTER02=172.31.3.102
MASTER03=172.31.3.103
HARBOR01=172.31.3.106
HARBOR02=172.31.3.107

os(){
 OS_ID=`sed -rn '/^NAME=/s@.="([[:alpha:]]+)."$p' /etc/os-release`
}

check_file (){
 cd ${SRC_DIR}
 ${COLOR}'检查Haproxy相关源码包'${END}
 if [ ! -e ${LUA_FILE} ];then
  ${COLOR}"缺少${LUA_FILE}文件,请把文件放到${SRC_DIR}目录下"${END}
  exit
 elif [ ! -e ${HAPROXY_FILE} ];then
  ${COLOR}"缺少${HAPROXY_FILE}文件,请把文件放到${SRC_DIR}目录下"${END}
  exit
 else
  ${COLOR}"相关文件已准备好"${END}
 fi
}

install_haproxy(){
 [ -d ${HAPROXY_INSTALL_DIR} ] && { ${COLOR}"Haproxy已存在,安装失败"${END};exit; }
 ${COLOR}"开始安装Haproxy"${END}
 ${COLOR}"开始安装Haproxy依赖包"${END}
 if [ ${OS_ID} == "CentOS" -o ${OS_ID} == "Rocky" ] &> /dev/null;then
  yum -y install g make g-c++ glibc glibc-devel pcre pcre-devel openssl openssl-devel systemd-devel libtermcap-devel ncurses-devel libevent-devel readline-devel &> /dev/null
 else
  apt update &> /dev/null;apt -y install g make openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev libreadline-dev libsystemd-dev &> /dev/null
 fi
 tar xf ${LUA_FILE}
 LUA_DIR=`echo ${LUA_FILE} | sed -nr 's/^(.[0-9]).([[:loer:]])./1/p'`
 cd ${LUA_DIR}
 make all test
 cd ${SRC_DIR}
 tar xf ${HAPROXY_FILE}
 HAPROXY_DIR=`echo ${HAPROXY_FILE} | sed -nr 's/^(.[0-9]).([[:loer:]])./1/p'`
 cd ${HAPROXY_DIR}
 make -j ${CPUS} ARCH=x86_64 TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_CPU_AFFINITY=1 USE_LUA=1 LUA_INC=${SRC_DIR}/${LUA_DIR}/src/ LUA_LIB=${SRC_DIR}/${LUA_DIR}/src/ PREFIX=${HAPROXY_INSTALL_DIR}
 make install PREFIX=${HAPROXY_INSTALL_DIR}
 [ $? -eq 0 ] && $COLOR"Haproxy编译安装成功"$END ||  { $COLOR"Haproxy编译安装失败,退出!"$END;exit; }
 cat > /lib/systemd/system/haproxy.service <<-EOF
[Unit]
Description=HAProxy Load Balancer
After=syslog.target ork.target

[Service]
ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q
ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /var/lib/haproxy/haproxy.pid
ExecReload=/bin/kill -USR2 $MAINPID

[Install]
WantedBy=multi-user.target
EOF
 [ -L /usr/sbin/haproxy ] || ln -s ../..${HAPROXY_INSTALL_DIR}/sbin/haproxy /usr/sbin/ &> /dev/null
 [ -d /etc/haproxy ] || mkdir /etc/haproxy &> /dev/null  
 [ -d /var/lib/haproxy/ ] || mkdir -p /var/lib/haproxy/ &> /dev/null
 cat > /etc/haproxy/haproxy.cfg <<-EOF
global
maxconn 100000
chroot ${HAPROXY_INSTALL_DIR}
stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
uid 99
gid 99
daemon
pidfile /var/lib/haproxy/haproxy.pid
log 127.0.0.1 local3 info

defaults
option http-keep-alive
option forardfor
maxconn 100000
mode http
timeout connect 300000ms
timeout client 300000ms
timeout server 300000ms

listen stats
 mode http
 bind 0.0.0.0:9999
 stats enable
 log global
 stats uri /haproxy-status
 stats auth ${STATS_AUTH_USER}:${STATS_AUTH_PASSWORD}

listen kuberes-6443
 bind ${VIP}:6443
 mode tcp
 log global
 server ${MASTER01} ${MASTER01}:6443 check inter 3s fall 2 rise 5
 server ${MASTER02} ${MASTER02}:6443 check inter 3s fall 2 rise 5
 server ${MASTER03} ${MASTER03}:6443 check inter 3s fall 2 rise 5

listen harbor-80
 bind ${VIP}:80
 mode http
 log global
 balance source
 server ${HARBOR01} ${HARBOR01}:80 check inter 3s fall 2 rise 5
 server ${HARBOR02} ${HARBOR02}:80 check inter 3s fall 2 rise 5
EOF
 cat >> /etc/sysctl.conf <<-EOF
.ipv4.ip_nonlocal_bind = 1
EOF
 sysctl -p &> /dev/null
 echo "PATH=${HAPROXY_INSTALL_DIR}/sbin:${PATH}" > /etc/profile.d/haproxy.sh
 systemctl daemon-reload
 systemctl enable --no haproxy &> /dev/null
 systemctl is-active haproxy &> /dev/null && ${COLOR}"Haproxy 服务启动成功!"${END} ||  { ${COLOR}"Haproxy 启动失败,退出!"${END} ; exit; }
 ${COLOR}"Haproxy安装完成"${END}
}

main(){
 os
 check_file
 install_haproxy
}

main

[root@k8s-ha01 ~]# bash install_haproxy.sh

[root@k8s-ha02 ~]# bash install_haproxy.sh
4.2.2 安装 Keepalived

安装 keepalived 实现 HAProxy的高可用

所有ha节点配置KeepAlived健康检查文件

[root@k8s-ha02 ~]# cat check_haproxy.sh 
#!/bin/bash
err=0
for k in $(seq 1 3);do
 check_code=$(pgrep haproxy)
 if [[ $check_code == "" ]]; then
  err=$(expr $err + 1)
  sleep 1
  continue
 else
  err=0
  break
 fi
done

if [[ $err != "0" ]]; then
 echo "systemctl s keepalived"
 /usr/bin/systemctl s keepalived
 exit 1
else
 exit 0
fi

在ha01和ha02节点安装KeepAlived,配置不一样,注意区分 [root@k8s-master01 pki]# vim /etc/keepalived/keepalived.conf ,注意每个节点的网卡(interface参数)

在ha01节点上安装keepalived-master

[root@k8s-ha01 ~]# cat install_keepalived_master.sh 
#!/bin/bash
#
#
#Author:  Raymond
#QQ:   88563128
#Date:    2021-12-29
#FileName:   install_keepalived_master.sh
#URL:     raymond.blog.csdn.
#Description:   install_keepalived for CentOS 7/8 & Ubuntu 18.04/20.04 & Rocky 8
#Copyright (C): 2021 All rights reserved
#
SRC_DIR=/usr/local/src
COLOR="echo -e \033[01;31m"
END='33[0m'
KEEPALIVED_URL=https://keepalived./softare/
KEEPALIVED_FILE=keepalived-2.2.7.tar.gz
KEEPALIVED_INSTALL_DIR=/apps/keepalived
CPUS=`lscpu |ak '/^CPU(s)/{print $2}'`
NET_NAME=`ip addr |ak -F"[: ]" '/^2: e./{print $3}'`
STATE=MASTER
PRIORITY=100
VIP=172.31.3.188


os(){
 OS_ID=`sed -rn '/^NAME=/s@.="([[:alpha:]]+)."$p' /etc/os-release`
 OS_RELEASE_VERSION=`sed -rn '/^VERSION_ID=/s@.="?([0-9]+).?."?p' /etc/os-release`
}

check_file (){
 cd  ${SRC_DIR}
 if [ ${OS_ID} == "CentOS" -o ${OS_ID} == "Rocky" ] &> /dev/null;then
  rpm -q get &> /dev/null || yum -y install get &> /dev/null
 fi
 if [ ! -e ${KEEPALIVED_FILE} ];then
  ${COLOR}"缺少${KEEPALIVED_FILE}文件,如果是离线包,请放到${SRC_DIR}目录下"${END}
  ${COLOR}'开始下载Keepalived源码包'${END}
  get ${KEEPALIVED_URL}${KEEPALIVED_FILE} || { ${COLOR}"Keepalived源码包下载失败"${END}; exit; }
 elif [ ! -e check_haproxy.sh ];then
  ${COLOR}"缺少check_haproxy.sh文件,请把文件放到${SRC_DIR}目录下"${END}
  exit
 else
  ${COLOR}"相关文件已准备好"${END}
 fi
}

install_keepalived(){
 [ -d ${KEEPALIVED_INSTALL_DIR} ] && { ${COLOR}"Keepalived已存在,安装失败"${END};exit; }
 ${COLOR}"开始安装Keepalived"${END}
 ${COLOR}"开始安装Keepalived依赖包"${END}
 if [ ${OS_ID} == "Rocky" -a ${OS_RELEASE_VERSION} == 8 ];then
  URL=mirrors.sjtug.sjtu.edu.
		if [ ! `grep -R "[PoerTools]" /etc/yum.repos.d/` ];then
   cat > /etc/yum.repos.d/PoerTools.repo <<-EOF
[PoerTools]
name=PoerTools
baseurl=https://${URL}/rocky/$releasever/PoerTools/$basearch/os/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rockyofficial
EOF
  fi
 fi
 if [ ${OS_ID} == "CentOS" -a ${OS_RELEASE_VERSION} == 8 ];then
  URL=mirrors.cloud.tencent.
  if [ ! `grep -R "[PoerTools]" /etc/yum.repos.d/` ];then
   cat > /etc/yum.repos.d/PoerTools.repo <<-EOF
[PoerTools]
name=PoerTools
baseurl=https://${URL}/centos/$releasever/PoerTools/$basearch/os/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
EOF
  fi
 fi
 if [[ ${OS_RELEASE_VERSION} == 8 ]] &> /dev/null;then
  yum -y install make g ipvsadm autoconf automake openssl-devel libnl3-devel iptables-devel ipset-devel file-devel -snmp-devel glib2-devel pcre2-devel libnftnl-devel libmnl-devel systemd-devel &> /dev/null
 elif [[ ${OS_RELEASE_VERSION} == 7 ]] &> /dev/null;then
  yum -y install make g libnflink-devel libnflink ipvsadm libnl libnl-devel libnl3 libnl3-devel lm_sensors-libs -snmp-agent-libs -snmp-libs openssh-server openssh-clients openssl openssl-devel automake iproute &> /dev/null
 elif [[ ${OS_RELEASE_VERSION} == 20 ]] &> /dev/null;then
  apt update &> /dev/null;apt -y install make g ipvsadm build-essential pkg-config automake autoconf libipset-dev libnl-3-dev libnl-genl-3-dev libssl-dev libxtables-dev libip4tc-dev libip6tc-dev libipset-dev libmagic-dev libsnmp-dev libglib2.0-dev libpcre2-dev libnftnl-dev libmnl-dev libsystemd-dev
 else
  apt update &> /dev/null;apt -y install make g ipvsadm build-essential pkg-config automake autoconf iptables-dev libipset-dev libnl-3-dev libnl-genl-3-dev libssl-dev libxtables-dev libip4tc-dev libip6tc-dev libipset-dev libmagic-dev libsnmp-dev libglib2.0-dev libpcre2-dev libnftnl-dev libmnl-dev libsystemd-dev &> /dev/null
 fi
 tar xf ${KEEPALIVED_FILE}
 KEEPALIVED_DIR=`echo ${KEEPALIVED_FILE} | sed -nr 's/^(.[0-9]).([[:loer:]])./1/p'`
 cd ${KEEPALIVED_DIR}
 ./configure --prefix=${KEEPALIVED_INSTALL_DIR} --disable-fmark
 make -j $CPUS && make install
 [ $? -eq 0 ] && ${COLOR}"Keepalived编译安装成功"${END} ||  { ${COLOR}"Keepalived编译安装失败,退出!"${END};exit; }
 [ -d /etc/keepalived ] || mkdir -p /etc/keepalived &> /dev/null
 cat > /etc/keepalived/keepalived.conf <PATH}" > /etc/profile.d/keepalived.sh
 systemctl daemon-reload
 systemctl enable --no keepalived &> /dev/null 
 systemctl is-active keepalived &> /dev/null && ${COLOR}"Keepalived 服务启动成功!"${END} ||  { ${COLOR}"Keepalived 启动失败,退出!"${END} ; exit; }
 ${COLOR}"Keepalived安装完成"${END}
}

main(){
 os
 check_file
 install_keepalived
}

main

[root@k8s-ha01 ~]# bash install_keepalived_master.sh

[root@k8s-ha01 ~]# ip a
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
 i 127.0.0.1/8 scope host lo
    valid_lft forever preferred_lft forever
 i6 ::1/128 scope host 
    valid_lft forever preferred_lft forever
2: eth0:  mtu 1500 qdisc mq state UP group default qlen 1000
 link/ether 00:0c:29:04:fa:9d brd ff:ff:ff:ff:ff:ff
 i 172.31.3.104/21 brd 172.31.7.255 scope global noprefixroute eth0
    valid_lft forever preferred_lft forever
 i 172.31.3.188/32 scope global eth0:1
    valid_lft forever preferred_lft forever
 i6 fe80::20c:29ff:fe04:fa9d/64 scope link 
    valid_lft forever preferred_lft forever

在ha02节点上安装keepalived-backup

[root@k8s-ha02 ~]# cat install_keepalived_backup.sh 
#!/bin/bash
#
#
#Author:  Raymond
#QQ:   88563128
#Date:    2021-12-29
#FileName:   install_keepalived_backup.sh
#URL:     raymond.blog.csdn.
#Description:   install_keepalived for CentOS 7/8 & Ubuntu 18.04/20.04 & Rocky 8
#Copyright (C): 2021 All rights reserved
#
SRC_DIR=/usr/local/src
COLOR="echo -e \033[01;31m"
END='33[0m'
KEEPALIVED_URL=https://keepalived./softare/
KEEPALIVED_FILE=keepalived-2.2.7.tar.gz
KEEPALIVED_INSTALL_DIR=/apps/keepalived
CPUS=`lscpu |ak '/^CPU(s)/{print $2}'`
NET_NAME=`ip addr |ak -F"[: ]" '/^2: e./{print $3}'`
STATE=BACKUP
PRIORITY=90
VIP=172.31.3.188


os(){
 OS_ID=`sed -rn '/^NAME=/s@.="([[:alpha:]]+)."$p' /etc/os-release`
 OS_RELEASE_VERSION=`sed -rn '/^VERSION_ID=/s@.="?([0-9]+).?."?p' /etc/os-release`
}

check_file (){
 cd  ${SRC_DIR}
 if [ ${OS_ID} == "CentOS" -o ${OS_ID} == "Rocky" ] &> /dev/null;then
  rpm -q get &> /dev/null || yum -y install get &> /dev/null
 fi
 if [ ! -e ${KEEPALIVED_FILE} ];then
  ${COLOR}"缺少${KEEPALIVED_FILE}文件,如果是离线包,请放到${SRC_DIR}目录下"${END}
  ${COLOR}'开始下载Keepalived源码包'${END}
  get ${KEEPALIVED_URL}${KEEPALIVED_FILE} || { ${COLOR}"Keepalived源码包下载失败"${END}; exit; }
 elif [ ! -e check_haproxy.sh ];then
  ${COLOR}"缺少check_haproxy.sh文件,请把文件放到${SRC_DIR}目录下"${END}
  exit
 else
  ${COLOR}"相关文件已准备好"${END}
 fi
}

install_keepalived(){
 [ -d ${KEEPALIVED_INSTALL_DIR} ] && { ${COLOR}"Keepalived已存在,安装失败"${END};exit; }
 ${COLOR}"开始安装Keepalived"${END}
 ${COLOR}"开始安装Keepalived依赖包"${END}
 if [ ${OS_ID} == "Rocky" -a ${OS_RELEASE_VERSION} == 8 ];then
  URL=mirrors.sjtug.sjtu.edu.
		if [ ! `grep -R "[PoerTools]" /etc/yum.repos.d/` ];then
   cat > /etc/yum.repos.d/PoerTools.repo <<-EOF
[PoerTools]
name=PoerTools
baseurl=https://${URL}/rocky/$releasever/PoerTools/$basearch/os/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rockyofficial
EOF
  fi
 fi
 if [ ${OS_ID} == "CentOS" -a ${OS_RELEASE_VERSION} == 8 ];then
  URL=mirrors.cloud.tencent.
  if [ ! `grep -R "[PoerTools]" /etc/yum.repos.d/` ];then
   cat > /etc/yum.repos.d/PoerTools.repo <<-EOF
[PoerTools]
name=PoerTools
baseurl=https://${URL}/centos/$releasever/PoerTools/$basearch/os/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
EOF
  fi
 fi
 if [[ ${OS_RELEASE_VERSION} == 8 ]] &> /dev/null;then
  yum -y install make g ipvsadm autoconf automake openssl-devel libnl3-devel iptables-devel ipset-devel file-devel -snmp-devel glib2-devel pcre2-devel libnftnl-devel libmnl-devel systemd-devel &> /dev/null
 elif [[ ${OS_RELEASE_VERSION} == 7 ]] &> /dev/null;then
  yum -y install make g libnflink-devel libnflink ipvsadm libnl libnl-devel libnl3 libnl3-devel lm_sensors-libs -snmp-agent-libs -snmp-libs openssh-server openssh-clients openssl openssl-devel automake iproute &> /dev/null
 elif [[ ${OS_RELEASE_VERSION} == 20 ]] &> /dev/null;then
  apt update &> /dev/null;apt -y install make g ipvsadm build-essential pkg-config automake autoconf libipset-dev libnl-3-dev libnl-genl-3-dev libssl-dev libxtables-dev libip4tc-dev libip6tc-dev libipset-dev libmagic-dev libsnmp-dev libglib2.0-dev libpcre2-dev libnftnl-dev libmnl-dev libsystemd-dev
 else
  apt update &> /dev/null;apt -y install make g ipvsadm build-essential pkg-config automake autoconf iptables-dev libipset-dev libnl-3-dev libnl-genl-3-dev libssl-dev libxtables-dev libip4tc-dev libip6tc-dev libipset-dev libmagic-dev libsnmp-dev libglib2.0-dev libpcre2-dev libnftnl-dev libmnl-dev libsystemd-dev &> /dev/null
 fi
 tar xf ${KEEPALIVED_FILE}
 KEEPALIVED_DIR=`echo ${KEEPALIVED_FILE} | sed -nr 's/^(.[0-9]).([[:loer:]])./1/p'`
 cd ${KEEPALIVED_DIR}
 ./configure --prefix=${KEEPALIVED_INSTALL_DIR} --disable-fmark
 make -j $CPUS && make install
 [ $? -eq 0 ] && ${COLOR}"Keepalived编译安装成功"${END} ||  { ${COLOR}"Keepalived编译安装失败,退出!"${END};exit; }
 [ -d /etc/keepalived ] || mkdir -p /etc/keepalived &> /dev/null
 cat > /etc/keepalived/keepalived.conf <PATH}" > /etc/profile.d/keepalived.sh
 systemctl daemon-reload
 systemctl enable --no keepalived &> /dev/null 
 systemctl is-active keepalived &> /dev/null && ${COLOR}"Keepalived 服务启动成功!"${END} ||  { ${COLOR}"Keepalived 启动失败,退出!"${END} ; exit; }
 ${COLOR}"Keepalived安装完成"${END}
}

main(){
 os
 check_file
 install_keepalived
}

main 

[root@k8s-ha02 ~]# bash install_keepalived_backup.sh
4.2.3 测试访问
172.31.3.188 kubeapi.raymonds.

浏览器访问验证,用户名密码: admin:123456

http://kubeapi.raymonds.:9999/haproxy-status


4.3 安装harbor 4.3.1 安装harbor

在harbor01和harbor02上安装harbor:

[root@k8s-harbor01 ~]# cat install_docker_pose_harbor.sh 
#!/bin/bash
#
#
#Author:  Raymond
#QQ:   88563128
#Date:    2021-12-16
#FileName:   install_docke_pose_harbor.sh
#URL:     raymond.blog.csdn.
#Description:   install_docker_pose_harbor for CentOS 7/8 & Ubuntu 18.04/20.04 & Rocky 8
#Copyright (C): 2021 All rights reserved
#
SRC_DIR=/usr/local/src
COLOR="echo -e \033[01;31m"
END='33[0m'

DOCKER_VERSION=20.10.17
URL='mirrors.cloud.tencent.'

#docker-pose下载地址:https://github./docker/pose/releases/donload/v2.10.2/docker-pose-linux-x86_64
DOCKER_COMPOSE_FILE=docker-pose-linux-x86_64

#harbor下载地址:https://github./goharbor/harbor/releases/donload/v2.6.0/harbor-offline-installer-v2.6.0.tgz
HARBOR_FILE=harbor-offline-installer-v
HARBOR_VERSION=2.6.0
TAR=.tgz
HARBOR_INSTALL_DIR=/apps
HARBOR_DOMAIN=harbor.raymonds.
NET_NAME=`ip addr |ak -F"[: ]" '/^2: e./{print $3}'`
IP=`ip addr sho ${NET_NAME}| ak -F" +|/" '/global/{print $3}'`
HARBOR_ADMIN_PASSWORD=123456

os(){
 OS_ID=`sed -rn '/^NAME=/s@.="([[:alpha:]]+)."$p' /etc/os-release`
 OS_RELEASE_VERSION=`sed -rn '/^VERSION_ID=/s@.="?([0-9]+).?."?p' /etc/os-release`
}

check_file (){
 cd ${SRC_DIR}
 if [ ! -e ${DOCKER_COMPOSE_FILE} ];then
  ${COLOR}"缺少${DOCKER_COMPOSE_FILE}文件,请把文件放到${SRC_DIR}目录下"${END}
  exit
 elif [ ! -e ${HARBOR_FILE}${HARBOR_VERSION}${TAR} ];then
  ${COLOR}"缺少${HARBOR_FILE}${HARBOR_VERSION}${TAR}文件,请把文件放到${SRC_DIR}目录下"${END}
  exit
 else
  ${COLOR}"相关文件已准备好"${END}
 fi
}

ubuntu_install_docker(){
 ${COLOR}"开始安装DOCKER依赖包"${END}
 apt update &> /dev/null
 apt -y install apt-transport-https ca-certificates curl softare-properties-mon &> /dev/null
 curl -fsSL https://${URL}/docker-ce/linux/ubuntu/gpg | sudo apt-key add - &> /dev/null
 add-apt-repository  "deb [arch=amd64] https://${URL}/docker-ce/linux/ubuntu  $(lsb_release -cs) stable" &> /dev/null 
 apt update &> /dev/null

 ${COLOR}"Docker有以下版本"${END}
 apt-cache madison docker-ce
 ${COLOR}"10秒后即将安装:Docker-"${DOCKER_VERSION}"版本......"${END}
 ${COLOR}"如果想安装其它Docker版本,请按Ctrl+c键退出,修改版本再执行"${END}
 sleep 10

 ${COLOR}"开始安装DOCKER"${END}
 apt -y install docker-ce=5:${DOCKER_VERSION}~3-0~ubuntu-$(lsb_release -cs) docker-ce-cli=5:${DOCKER_VERSION}~3-0~ubuntu-$(lsb_release -cs) &> /dev/null || { ${COLOR}"apt源失败,请检查apt配置"${END};exit; }
}

centos_install_docker(){
	${COLOR}"开始安装DOCKER依赖包"${END}
 yum -y install yum-utils &> /dev/null
 yum-config-manager --add-repo https://${URL}/docker-ce/linux/centos/docker-ce.repo &> /dev/null
 yum clean all &> /dev/null
	yum makecache &> /dev/null

 ${COLOR}"Docker有以下版本"${END}
 yum list docker-ce.x86_64 --shoduplicates
 ${COLOR}"10秒后即将安装:Docker-"${DOCKER_VERSION}"版本......"${END}
 ${COLOR}"如果想安装其它Docker版本,请按Ctrl+c键退出,修改版本再执行"${END}
 sleep 10

 ${COLOR}"开始安装DOCKER"${END}
 yum -y install docker-ce-${DOCKER_VERSION} docker-ce-cli-${DOCKER_VERSION} &> /dev/null || { ${COLOR}"yum源失败,请检查yum配置"${END};exit; }
}

mirror_aelerator(){
 mkdir -p /etc/docker
 cat > /etc/docker/daemon.json <<-EOF
{
 "registry-mirrors": [
  "https://registry.docker-.",
  "http://hub-mirror.c.163.",
  "https://docker.mirrors.ustc.edu."
 ],
 "insecure-registries": ["${HARBOR_DOMAIN}"],
 "exec-opts": ["native.cgroupdriver=systemd"],
 "max-concurrent-donloads": 10,
 "max-concurrent-uploads": 5,
 "log-opts": {
  "max-size": "300m",
  "max-file": "2"  
 },
 "live-restore": true
}
EOF
 systemctl daemon-reload
 systemctl enable --no docker
 systemctl is-active docker &> /dev/null && ${COLOR}"Docker 服务启动成功"${END} || { ${COLOR}"Docker 启动失败"${END};exit; }
 docker version &&  ${COLOR}"Docker 安装成功"${END} || ${COLOR}"Docker 安装失败"${END}
}

set_alias(){
 echo 'alias rmi="docker images -qa|xargs docker rmi -f"' >> ~/.bashrc
 echo 'alias rmc="docker ps -qa|xargs docker rm -f"' >> ~/.bashrc
}

install_docker_pose(){
 ${COLOR}"开始安装 Docker pose....."${END}
 sleep 1
 mv ${SRC_DIR}/${DOCKER_COMPOSE_FILE} /usr/bin/docker-pose
 chmod +x /usr/bin/docker-pose
 docker-pose --version &&  ${COLOR}"Docker Compose 安装完成"${END} || ${COLOR}"Docker pose 安装失败"${END}
}

install_harbor(){
 ${COLOR}"开始安装 Harbor....."${END}
 sleep 1
 [ -d ${HARBOR_INSTALL_DIR} ] || mkdir ${HARBOR_INSTALL_DIR}
 tar xf ${SRC_DIR}/${HARBOR_FILE}${HARBOR_VERSION}${TAR} -C ${HARBOR_INSTALL_DIR}/
 mv ${HARBOR_INSTALL_DIR}/harbor/harbor.yml.tmpl ${HARBOR_INSTALL_DIR}/harbor/harbor.yml
 sed -ri.bak -e 's/^(hostname:) ./1 '${IP}'/' -e 's/^(harbor_admin_passord:) ./1 '${HARBOR_ADMIN_PASSWORD}'/' -e 's/^(https:)/#1/' -e 's/  (port: 443)/#  1/' -e 's@  (certificate: .)@#  1@' -e 's@  (private_key: .)@#  1@' ${HARBOR_INSTALL_DIR}/harbor/harbor.yml
 if [ ${OS_ID} == "CentOS" -o ${OS_ID} == "Rocky" ] &> /dev/null;then
  if [ ${OS_RELEASE_VERSION} == "8" ];then
   yum -y install python3 &> /dev/null || { ${COLOR}"安装软件包失败,请检查网络配置"${END}; exit; }
  else
   yum -y install python &> /dev/null || { ${COLOR}"安装软件包失败,请检查网络配置"${END}; exit; }
  fi
 else
  apt -y install python3 &> /dev/null || { ${COLOR}"安装软件包失败,请检查网络配置"${END}; exit; }
 fi
 ${HARBOR_INSTALL_DIR}/harbor/install.sh && ${COLOR}"Harbor 安装完成"${END} ||  ${COLOR}"Harbor 安装失败"${END}
 cat > /lib/systemd/system/harbor.service <<-EOF
[Unit]
Description=Harbor
After=docker.service systemd-orkd.service systemd-resolved.service
Requires=docker.service
Documentation=http://github./vmare/harbor

[Service]
Type=simple
Restart=on-failure
RestartSec=5
ExecStart=/usr/bin/docker-pose -f /apps/harbor/docker-pose.yml up
ExecS=/usr/bin/docker-pose -f /apps/harbor/docker-pose.yml don

[Install]
WantedBy=multi-user.target
EOF

 systemctl daemon-reload 
 systemctl enable harbor &>/dev/null && ${COLOR}"Harbor已配置为开机自动启动"${END}
}

set_sap_limit(){
 if [ ${OS_ID} == "Ubuntu" ];then
  ${COLOR}'设置Docker的"WARNING: No sap limit support"警告'${END}
  sed -ri '/^GRUB_CMDLINE_LINUX=/s@"$@ sapaount=1"@' /etc/default/grub
  update-grub &> /dev/null
  ${COLOR}"10秒后,机器会自动重启"${END}
  sleep 10
  reboot
 fi
}

main(){
 os
 check_file
 if [ ${OS_ID} == "CentOS" -o ${OS_ID} == "Rocky" ] &> /dev/null;then
  rpm -q docker-ce &> /dev/null && ${COLOR}"Docker已安装"${END} || centos_install_docker
 else
  dpkg -s docker-ce &>/dev/null && ${COLOR}"Docker已安装"${END} || ubuntu_install_docker
 fi
 [ -f /etc/docker/daemon.json ] &>/dev/null && ${COLOR}"Docker镜像加速器已设置"${END} || mirror_aelerator
 grep -Eqoi "(.rmi=|.rmc=)" ~/.bashrc && ${COLOR}"Docker别名已设置"${END} || set_alias
 docker-pose --version &> /dev/null && ${COLOR}"Docker Compose已安装"${END} || install_docker_pose
 systemctl is-active harbor &> /dev/null && ${COLOR}"Harbor已安装"${END} || install_harbor
 grep -q "sapaount=1" /etc/default/grub && ${COLOR}'"WARNING: No sap limit support"警告,已设置'${END} || set_sap_limit
}

main

[root@k8s-harbor01 ~]# bash install_docker_pose_harbor.sh

[root@k8s-harbor02 ~]# bash install_docker_pose_harbor.sh
4.3.2 创建harbor仓库

在harbor01新建项目google_containers

http://172.31.3.106/

用户名admin 密码:123456



在harbor02新建项目google_containers

http://172.31.3.107/


在harbor02上新建目标

在harbor02上新建规则

在harbor01上新建目标

在harbor01上新建规则

Copyright © 2016-2025 www.jianfeikang.com 建飞家电维修 版权所有 Power by