部署前提使用kubeadm部署Kubernetes集群的前提条件支持Kubernetes运行的Linux主机,例如Debian、RedHat及其变体等每主机2GB以上的内存,以及2颗以上的CPU各主机间能够通过网络无障碍通信独占的hostname、MAC地址以及productuuid,主机名能够正常解析放行由Kubernetes使用到的各端口,或直接禁用iptables禁用各主机的上的Swap设备各主机时间同步部署环境OS:Ubuntu20。04。2LTSDocker:20。10。10,CGroupDriver:systemdKubernetes:v1。26。3,CRI:containerd,CNI:Flannel主机 主机IP 主机名称 角色 192。168。32。200 k8smaster01。org master 192。168。32。203 k8snode01。org node01 192。168。32。204 k8snode02。org node02 192。168。32。205 k8snode03。org node03修改主机名称修改192。168。32。200的主机名称为k8smaster01。org修改192。168。32。203的主机名称为k8snode01。org修改192。168。32。204的主机名称为k8snode02。org修改192。168。32。205的主机名称为k8snode03。org主机时间同步 在所有主机上安装chrony所有主机上执行rootk8smaster01:aptinstallychrony 建议用户配置使用本地的的时间服务器,在节点数量众多时尤其如此。存在可用的本地时间服务器时,修改节点的etcchronychrony。conf配置文件,并将时间服务器指向相应的主机即可,配置格式如下:serverCHRONYSERVERNAMEORIPiburst主机名称解析 出于简化配置步骤的目的,本测试环境使用hosts文件进行各节点名称解析,文件内容如下所示。其中,我们使用kubeapi主机名作为APIServer在高可用环境中的专用接入名称,也为控制平面的高可用配置留下便于配置的余地。编辑etchosts文件加入如下内容rootk8smaster01:vimetchosts192。168。32。200k8smaster01。org192。168。32。203k8snode01。org192。168。32。204k8snode02。org192。168。32。205k8snode03。org禁用Swap设备 部署集群时,kubeadm默认会预先检查当前主机是否禁用了Swap设备,并在未禁用时强制终止部署过程。因此,在主机内存资源充裕的条件下,需要禁用所有的Swap设备,否则,就需要在后文的kubeadminit及kubeadmjoin命令执行时额外使用相关的选项忽略检查错误。 关闭Swap设备,需要分两步完成。首先是关闭当前已启用的所有Swap设备:临时关闭,所有机器执行rootk8smaster01:swapoffa 而后编辑etcfstab配置文件,注释用于挂载Swap设备的所有行所有机器执行rootk8smaster01:vimetcfstab注释如下一行swap。imgnoneswapsw00禁用默认的防火墙服务 Ubuntu和Debian等Linux发行版默认使用ufw(UncomplicatedFireWall)作为前端来简化iptables的使用,处于启用状态时,它默认会生成一些规则以加强系统安全。出于降低配置复杂度之目的,本文选择直接将其禁用。rootk8smaster01:ufwdisableFirewallstoppedanddisabledonsystemstartuprootk8smaster01:ufwstatusStatus:inactiverootk8smaster01:安装程序包 提示:以下操作需要在本示例中的所有四台主机上分别进行。安装并启动docker 首先,生成dockerce相关程序包的仓库,这里以阿里云的镜像服务器为例进行说明: dockerce镜像dockerce下载地址dockerce安装教程阿里巴巴开源镜像站(aliyun。com)step1:安装必要的一些系统工具sudoaptgetupdatesudoaptgetyinstallapttransporthttpscacertificatescurlsoftwarepropertiescommonstep2:安装GPG证书curlfsSLhttps:mirrors。aliyun。comdockercelinuxubuntugpgsudoaptkeyaddStep3:写入软件源信息sudoaddaptrepositorydeb〔archamd64〕https:mirrors。aliyun。comdockercelinuxubuntu(lsbreleasecs)stableStep4:更新并安装DockerCEsudoaptgetyupdatesudoaptgetyinstalldockerce安装指定版本的DockerCE:Step1:查找DockerCE的版本:aptcachemadisondockercedockerce17。03。1ce0ubuntuxenialhttps:mirrors。aliyun。comdockercelinuxubuntuxenialstableamd64Packagesdockerce17。03。0ce0ubuntuxenialhttps:mirrors。aliyun。comdockercelinuxubuntuxenialstableamd64PackagesStep2:安装指定版本的DockerCE:(VERSION例如上面的17。03。1ce0ubuntuxenial)sudoaptgetyinstalldockerce〔VERSION〕 本文以为20。10。10版本为例rootk8snode3:aptinstalldockerce5:20。10。1030ubuntufocaldockercecli5:20。10。1030ubuntufocal kubelet需要让docker容器引擎使用systemd作为CGroup的驱动,其默认值为cgroupfs,因而,我们还需要编辑docker的配置文件etcdockerdaemon。json,添加如下内容,其中的registrymirrors用于指明使用的镜像加速服务。vimetcdockerdaemon。json{registrymirrors:〔https:ung2thfc。mirror。aliyuncs。com,https:mirror。ccs。tencentyun。com,https:registry。dockercn。com,http:hubmirror。c。163。com,https:docker。mirrors。ustc。edu。cn〕,execopts:〔native。cgroupdriversystemd〕}systemctldaemonreloadsystemctlrestartdocker安装cridockerd Kubernetes自v1。24移除了对dockershim的支持,而DockerEngine默认又不支持CRI规范,因而二者将无法直接完成整合。为此,Mirantis和Docker联合创建了cridockerd项目,用于为DockerEngine提供一个能够支持到CRI规范的垫片,从而能够让Kubernetes基于CRI控制Docker。 项目地址:https:github。comMirantiscridockerd cridockerd项目提供了预制的二进制格式的程序包,用户按需下载相应的系统和对应平台的版本即可完成安装,这里以Ubuntu200464bits系统环境,以及cridockerd目前最新的程序版本v0。3。0为例。wgethttps:github。comMirantiscridockerdreleasesdownloadv0。3。0cridockerd0。3。0。30。ubuntufocalamd64。debdpkgicridockerd0。3。0。30。ubuntufocalamd64。deb 完成安装后,相应的服务cridockerd。service便会自动启动。我们也可以使用如下命令进行验证,若服务处于Running状态即可进行后续步骤。rootk8smaster01:systemctlstatuscridocker。servicecridocker。serviceCRIInterfaceforDockerApplicationContainerEngineLoaded:loaded(libsystemdsystemcridocker。service;enabled;vendorpreset:enabled)Active:active(running)sinceTue2023032110:59:57CST;1min20sagoTriggeredBy:cridocker。socketDocs:https:docs。mirantis。comMainPID:17591(cridockerd)Tasks:7Memory:11。9MCGroup:system。slicecridocker。service17591usrbincridockerdcontainerruntimeendpointfd:Mar2110:59:57k8smaster01。orgcridockerd〔17591〕:time20230321T10:59:5708:00levelinfomsgStartdockerclientwithrequesttimeout0sMar2110:59:57k8smaster01。orgcridockerd〔17591〕:time20230321T10:59:5708:00levelinfomsgHairpinmodeissettononeMar2110:59:57k8smaster01。orgcridockerd〔17591〕:time20230321T10:59:5708:00levelinfomsgLoadednetworkplugincniMar2110:59:57k8smaster01。orgcridockerd〔17591〕:time20230321T10:59:5708:00levelinfomsgDockercrinetworkingmanagedbynetworkplugincniMar2110:59:57k8smaster01。orgsystemd〔1〕:StartedCRIInterfaceforDockerApplicationContainerEngine。Mar2110:59:58k8smaster01。orgcridockerd〔17591〕:time20230321T10:59:5708:00levelinfomsgDockerInfo:{ID:WQBA:P7R2:H6ZI:KWU3:FVFW:MHLC:QTT7:CJCXMar2110:59:58k8smaster01。orgcridockerd〔17591〕:time20230321T10:59:5708:00levelinfomsgSettingcgroupDrivercgroupfsMar2110:59:58k8smaster01。orgcridockerd〔17591〕:time20230321T10:59:5708:00levelinfomsgDockercrireceivedruntimeconfigRuntimeConfig{NetworkMar2110:59:58k8smaster01。orgcridockerd〔17591〕:time20230321T10:59:5708:00levelinfomsgStartingtheGRPCbackendfortheDockerCRIinterface。Mar2110:59:58k8smaster01。orgcridockerd〔17591〕:time20230321T10:59:5708:00levelinfomsgStartcridockerdgrpcbackendlines12121(END)安装kubelet、kubeadm和kubectl 首先,在各主机上生成kubelet和kubeadm等相关程序包的仓库,这里以阿里云的镜像服务为例:aptgetupdateaptgetinstallyapttransporthttpscurlhttps:mirrors。aliyun。comkubernetesaptdocaptkey。gpgaptkeyaddcatEOFetcaptsources。list。dkubernetes。listdebhttps:mirrors。aliyun。comkubernetesaptkubernetesxenialmainEOFaptgetupdateaptgetinstallykubeletkubeadmkubectl 安装完成后,要确保kubeadm等程序文件的版本,这将也是后面初始化Kubernetes集群时需要明确指定的版本号。整合kubelet和cridockerd 仅支持CRI规范的kubelet需要经由遵循该规范的cridockerd完成与dockerce的整合。配置cridockerd 配置cridockerd,确保其能够正确加载到CNI插件。编辑usrlibsystemdsystemcridocker。service文件,确保其〔Service〕配置段中的ExecStart的值类似如下内容。ExecStartusrbincridockerdcontainerruntimeendpointfd:networkplugincnipodinfracontainerimageregistry。aliyuncs。comgooglecontainerspause:3。7cnibindiroptcnibincnicachedirvarlibcnicachecniconfdiretccninet。d 需要添加的各配置参数(各参数的值要与系统部署的CNI插件的实际路径相对应):networkplugin:指定网络插件规范的类型,这里要使用CNI;cnibindir:指定CNI插件二进制程序文件的搜索目录;cnicachedir:CNI插件使用的缓存目录;cniconfdir:CNI插件加载配置文件的目录; 配置完成后,重载并重启cridocker。service服务。rootk8smaster01:systemctldaemonreload;systemctlrestartcridocker配置kubelet 配置kubelet,为其指定cridockerd在本地打开的UnixSock文件的路径,该路径一般默认为runcridockerd。sock。编辑文件etcsysconfigkubelet,为其添加如下指定参数。 提示:若etcsysconfig目录不存在,则需要先创建该目录。KUBELETKUBEADMARGScontainerruntimeremotecontainerruntimeendpointruncridockerd。sock 需要说明的是,该配置也可不进行,而是直接在后面的各kubeadm命令上使用crisocketunix:runcridockerd。sock选项。初始化第一个主节点 该步骤开始尝试构建Kubernetes集群的master节点,配置完成后,各worker节点直接加入到集群中的即可。需要特别说明的是,由kubeadm部署的Kubernetes集群上,集群核心组件kubeapiserver、kubecontrollermanager、kubescheduler和etcd等均会以静态Pod的形式运行,它们所依赖的镜像文件默认来自于registry。k8s。io这一Registry服务之上。但我们无法直接访问该服务,常用的解决办法有如下两种使用能够到达该服务的代理服务;使用国内的镜像服务器上的服务,例如registry。aliyuncs。comgooglecontainers等。初始化master节点(在k8smaster01上完成如下操作) 运行如下命令完成k8smaster01节点的初始化:kubeadminitimagerepositoryregistry。aliyuncs。comgooglecontainerskubernetesversionv1。26。3podnetworkcidr10。244。0。016servicecidr10。96。0。012tokenttl0crisocketunix:runcridockerd。sock 命令中的各选项简单说明如下:imagerepository:指定要使用的镜像仓库,默认为registry。k8s。io;kubernetesversion:kubernetes程序组件的版本号,它必须要与安装的kubelet程序包的版本号相同;controlplaneendpoint:控制平面的固定访问端点,可以是IP地址或DNS名称,会被用于集群管理员及集群组件的kubeconfig配置文件的APIServer的访问地址;单控制平面部署时可以不使用该选项;podnetworkcidr:Pod网络的地址范围,其值为CIDR格式的网络地址,通常,Flannel网络插件的默认为10。244。0。016,ProjectCalico插件的默认值为192。168。0。016;servicecidr:Service的网络地址范围,其值为CIDR格式的网络地址,默认为10。96。0。012;通常,仅Flannel一类的网络插件需要手动指定该地址;apiserveradvertiseaddress:apiserver通告给其他组件的IP地址,一般应该为Master节点的用于集群内部通信的IP地址,0。0。0。0表示节点上所有可用地址;tokenttl:共享令牌(token)的过期时长,默认为24小时,0表示永不过期;为防止不安全存储等原因导致的令牌泄露危及集群安全,建议为其设定过期时长。未设定该选项时,在token过期后,若期望再向集群中加入其它节点,可以使用如下命令重新创建token,并生成节点加入命令。初始化完成后的操作步骤 对于Kubernetes系统的新用户来说,无论使用上述哪种方法,命令运行结束后,请记录最后的kubeadmjoin命令输出的最后提示的操作步骤。下面的内容是需要用户记录的一个命令输出示例,它提示了后续需要的操作步骤。下面是成功完成第一个控制平面节点初始化的提示信息及后续需要完成的步骤YourKubernetescontrolplanehasinitializedsuccessfully!为了完成初始化操作,管理员需要额外手动完成几个必要的步骤Tostartusingyourcluster,youneedtorunthefollowingasaregularuser:第1个步骤提示,Kubernetes集群管理员认证到Kubernetes集群时使用的kubeconfig配置文件mkdirpHOME。kubesudocpietckubernetesadmin。confHOME。kubeconfigsudochown(idu):(idg)HOME。kubeconfig我们也可以不做上述设定,而使用环境变量KUBECONFIG为kubectl等指定默认使用的kubeconfig;Alternatively,ifyouaretherootuser,youcanrun:exportKUBECONFIGetckubernetesadmin。conf第2个步骤提示,为Kubernetes集群部署一个网络插件,具体选用的插件则取决于管理员;Youshouldnowdeployapodnetworktothecluster。Runkubectlapplyf〔podnetwork〕。yamlwithoneoftheoptionslistedat:https:kubernetes。iodocsconceptsclusteradministrationaddons第3个步骤提示,向集群添加额外的控制平面节点,但本文会略过该步骤,并将在其它文章介绍其实现方式。Youcannowjoinanynumberofthecontrolplanenoderunningthefollowingcommandoneachasroot:第4个步骤提示,向集群添加工作节点Thenyoucanjoinanynumberofworkernodesbyrunningthefollowingoneachasroot:在部署好kubeadm等程序包的各工作节点上以root用户运行类似如下命令;提示:与cridockerd结合使用dockerce作为containerruntime时,通常需要为下面的命令额外附加crisocketunix:runcridockerd。sock选项;kubeadmjoin192。168。32。200:6443tokenivu3t7。pogk70dd5pualoz2discoverytokencacerthashsha256:3edb3c8e3e6c944afe65b2616d46b49305c1420e6967c1fab966ddf8f149502d设定kubectl kubectl是kubeapiserver的命令行客户端程序,实现了除系统部署之外的几乎全部的管理操作,是kubernetes管理员使用最多的命令之一。kubectl需经由APIserver认证及授权后方能执行相应的管理操作,kubeadm部署的集群为其生成了一个具有管理员权限的认证配置文件etckubernetesadmin。conf,它可由kubectl通过默认的HOME。kubeconfig的路径进行加载。当然,用户也可在kubectl命令上使用kubeconfig选项指定一个别的位置。 下面复制认证为Kubernetes系统管理员的配置文件至目标用户(例如当前用户root)的家目录下: mkdir。kube cpetckubernetesadmin。conf。kubeconfig部署网络插件 Kubernetes系统上Pod网络的实现依赖于第三方插件进行,这类插件有近数十种之多,较为著名的有flannel、calico、canal和kuberouter等,简单易用的实现是为CoreOS提供的flannel项目。下面的命令用于在线部署flannel至Kubernetes系统之上: 首先,下载适配系统及硬件平台环境的flanneld至每个节点,并放置于optbin目录下。我们这里选用flanneldamd64,目前最新的版本为v0。21。3,因而,我们需要在集群的每个节点上执行如下命令:mkdiroptcnibincurlLhttps:github。comflannelioflannelreleasesdownloadv0。20。2flanneldamd64ooptcnibinflanneldchmodxoptcnibinflanneld提示:下载flanneld的地址为https:github。comflannelioflannelreleases 随后,在初始化的第一个master节点k8smaster01上运行如下命令,向Kubernetes部署kubeflannel。kubectlapplyfhttps:raw。githubusercontent。comflannelioflannelv0。21。3Documentationkubeflannel。yml 而后使用如下命令确认其输出结果中Pod的状态为Running,类似如下命令及其输入的结果所示:rootk8smaster01:kubectlgetpodsnkubeflannelNAMEREADYSTATUSRESTARTSAGEkubeflanneldsjgkxd11Running02m59srootk8smaster01:验证master节点已经就绪 kubectlgetnodes 上述命令应该会得到类似如下输出,这表示k8smaster01节点已经就绪rootk8smaster01:kubectlgetnodesNAMESTATUSROLESAGEVERSIONk8smaster01。orgReadycontrolplane62mv1。26。3rootk8smaster01:添加节点到集群中 下面的两个步骤,需要分别在k8snode01、k8snode02和k8snode03上各自完成。 1、若未禁用Swap设备,编辑kubelet的配置文件etcdefaultkubelet,设置其忽略Swap启用的状态错误,内容如下:KUBELETEXTRAARGSfailswaponfalse 2、将节点加入第二步中创建的master的集群中,要使用主节点初始化过程中记录的kubeadmjoin命令;rootk8snode01:optcnibinkubeadmjoin192。168。32。200:6443tokenivu3t7。pogk70dd5pualoz2discoverytokencacerthashsha256:3edb3c8e3e6c944afe65b2616d46b49305c1420e6967c1fab966ddf8f149502dcrisocketunix:runcridockerd。sock验证节点添加结果 在每个节点添加完成后,即可通过kubectl验证添加结果。下面的命令及其输出是在所有的三个节点均添加完成后运行的,其输出结果表明三个WorkerNode已经准备就绪。 kubectlgetnodesrootk8smaster01:kubectlgetnodesNAMESTATUSROLESAGEVERSIONk8smaster01。orgReadycontrolplane80mv1。26。3k8snode01。orgReadynone15mv1。26。3k8snode2。orgReadynone114sv1。26。3k8snode3。orgReadynone11mv1。26。3rootk8smaster01:测试应用编排及服务访问 到此为止,一个master,并附带有三个worker的kubernetes集群基础设施已经部署完成,用户随后即可测试其核心功能。rootk8smaster01:kubectlcreatedeploymenttestnginximagenginx:latestreplicas3deployment。appstestnginxcreatedrootk8smaster01:rootk8smaster01:kubectlcreateservicenodeporttestnginxtcp80:80servicetestnginxcreatedrootk8smaster01: 而后,使用如下命令了解Service对象testnginx使用的NodePort,以便于在集群外部进行访问:rootk8smaster01:kubectlgetsvclapptestnginxNAMETYPECLUSTERIPEXTERNALIPPORT(S)AGEtestnginxNodePort10。100。229。239none80:31888TCP50srootk8smaster01: 因此,用户可以于集群外部通过http:NodeIP:31888这个URL访问web应用,例如于集群外通过浏览器访问http:192。168。32。203:31888。 小结 本文给出了部署Kubernetes分布式集群的具体步骤,并在最后测试了将应用部署并运行于Kubernetes系统上的结果。在读者朋友们自行测试时,cridockerd、dockerce、flannel、kubeadm、kubectl和kubelet的版本均可能存在版本上的不同,也因此可能会存在一定程度上的配置差异,具体调整方式请大家自行参考相关的文档进行。