摘要: 我们前面课程中的集群是单主集群,对于生产环境来说风险太大,所以做一个高可用的集群是非常必要的这里的高可用性集群主要是针对控制面板的,比如kube—apiserver,etcd,kube—controller—manage...
我们前面课程中的集群是单主集群,对于生产环境来说风险太大,所以做一个高可用的集群是非常必要的这里的高可用性集群主要是针对控制面板的,比如kube—apiserver,etcd,kube—controller—manager和kube—scheduler其中,kube—scheduler组件中的kube—controller—manager是由Kubernetes集群本身高度可用的当有多个组件时,它会自动选择一个作为Leader来提供服务,所以我们不需要手动实现高可用性,但是apiserver和etcd需要手动构建高可用性集群有许多高度可用的架构,例如典型的haproxy keepalived架构,或者使用nginx的代理实现 环境准备 4个节点,均为Centos 7.6系统,内核版本:3.10.0—1062.4.1.el7.x86_64。在每个节点上添加主机信息: 。~ cat/etc/hosts 192 . 168 . 31 . 10 API . k8s . local # VIP 192 . 168 . 31 . 31 master 1192 . 168 . 31 . 32 master 2192 . 168 . 31 . 33 master 3192 . 168 . 31 . 100 node 1 192.168.31.10是vip,由域名api.k8s.local映射. 节点的主机名必须用标准的DNS来命名,千万不要使用localhost的默认主机名,这样会导致各种错误在Kubernetes项目中,机器名和存储在Etcd中的所有API对象必须由标准DNS命名您可以使用hostnamectl set—hostname node1命令来修改主机名 禁用防火墙: ~systemctlstopfirewalld 禁用SELINUX: ~setenforce0 由于需要加载br_netfilter模块来打开内核ipv4转发,因此请加载以下模块: 。~ modproblebr _ net filter 创建/etc/sysctl.d/k8s.conf文件并添加以下内容: net . bridge . bridge—nf—call—ip6 tables=1 net . bridge . bridge—nf—call—iptables=1 net . IP v4 . IP _ forward=1 执行以下命令使修改生效: 。~ sysctl—p/etc/sysctl . d/k8s . conf 安装ipv: ~ catgt/etc/sysconfig/modules/ipvs . module SLT,由上述脚本创建的/etc/sysconfig/modules/ipvs . modules文件确保了在节点重新启动后可以自动加载所需的模块 grep—e IP _ vs—e nf _ conn track _ IP v4命令查看所需的内核模块是否已正确加载 接下来,您需要确保每个节点上都安装了ipset包: 。~yuminstallipset 要查看ipvs的代理规则,最好安装管理工具ipvsadm: 。~yuminstallipvsadm 同步服务器时间。 关闭交换分区: 。~swapoff—a 修改/etc/fstab文件,注释掉swap的自动挂载,并使用free —m确认SWAP已关闭。Swappiness参数调整,修改/etc/sysctl.d/k8s.conf并添加以下行: vm.swappiness=0 执行sysctl —p /etc/sysctl.d/k8s.conf以使修改生效。 安装容器 我们已经学习了容器运行时中容器的一些基本用法,然后在每个节点上安装了容器。 因为containerd需要调用runc,所以我们也需要先安装runc但是,containerd提供了一个压缩包CRI—containerd—CNI—$版本$ OS—$ arch.tar.gz,可直接用于安装 将压缩包直接提取到系统的每个目录中: 。~ tar—C/—xzfcri—containerd—CNI—1 . 5 . 5—Linux—amd64 . tar . gz 然后将/usr/local/bin和/usr/local/sbin追加到~/的PATH环境变量中。bashrc文件: export path=$ PATH :/usr/local/bin :/usr/local/sbin 然后执行以下命令。 其立即生效: 。~source~/.bashrc containerd 的默认配置文件为 /etc/containerd/config.toml,我们可以通过如下所示的命令生成一个默认的配置: ~mkdir—p/etc/containerd 对于使用 systemd 作为 init system 的 Linux 的发行版,使用 systemd 作为容器的 cgroup driver 可以确保节点在资源紧张的情况更加稳定,所以推荐将 containerd 的 cgroup driver 配置为 systemd。 修改前面生成的配置文件 /etc/containerd/config.toml,在 plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options 配置块下面将 SystemdCgroup 设置为 true: ...SystemdCgroup=true.... 然后再为镜像仓库配置一个加速器,需要在 cri 配置块下面的 registry 配置块下面进行配置 registry.mirrors: 由于上面我们下载的 containerd 压缩包中包含一个 etc/systemd/system/containerd.service 的文件,这样我们就可以通过 systemd 来配置 containerd 作为守护进程运行了,现在我们就可以启动 containerd 了,直接执行下面的命令即可: ~systemctldaemon—reload 启动完成后就可以使用 containerd 的本地 CLI 工具 ctr 和 crictl 了,比如查看版本: ~ctrversionClient:Version:v1.5.5Revision:72cec4be58a9eb6b2910f5d10f1c01ca47d231c0Goversion:go1.16.6Server:Version:v1.5.5Revision:72cec4be58a9eb6b2910f5d10f1c01ca47d231c0UUID:cd2894ad—fd71—4ef7—a09f—5795c7eb4c3b 为 apiserver 提供负载均衡器有很多方法,比如传统的 haproxy+keepalived,或者使用 nginx 代理也可以,这里我们使用一个比较新颖的工具 kube—vip。 在以前我们在私有环境下创建 Kubernetes 集群时,我们需要准备一个硬件/软件的负载均衡器来创建多控制面集群,更多的情况下我们会选择使用 HAProxy + Keepalived 来实现这个功能一般情况下我们创建2个负载均衡器的虚拟机,然后分配一个 VIP,然后使用 VIP 为负载均衡器提供服务,通过 VIP 将流量重定向到后端的某个 Kubernetes 控制器平面节点上 haproxy+keepalived 如果我们使用 kube—vip 的话会怎样呢。 kube—vip kube—vip 可以通过静态 pod 运行在控制平面节点上,这些 pod 通过 ARP 会话来识别每个节点上的其他主机,我们可以选择 BGP 或 ARP 来设置负载平衡器,这与 Metal LB 比较类似在 ARP 模式下,会选出一个领导者,这个节点将继承虚拟 IP 并成为集群内负载均衡的 Leader,而在 BGP 模式下,所有节点都会通知 VIP 地址 集群中的 Leader 将分配 vip,并将其绑定到配置中声明的选定接口上当 Leader 改变时,它将首先撤销 vip,或者在失败的情况下,vip 将直接由下一个当选的 Leader 分配当 vip 从一个主机移动到另一个主机时,任何使用 vip 的主机将保留以前的 vipMAC 地址映射,直到 ARP 过期并检索到一个新的 vipMAC 映射,这可以通过使用无偿的 ARP 广播来优化 kube—vip 可以被配置为广播一个无偿的 arp,通常会立即通知所有本地主机 vipMAC 地址映射已经改变。 要使用 kube—vip 来实现集群的高可用,首先在 master1 节点上生成基本的 Kubernetes 静态 Pod 资源清单文件: ~mkdir—p/etc/kubernetes/manifests/#配置vip地址~exportVIP=192.168.31.10#设置网卡名称~exportINTERFACE=ens33~ctrimagepulldocker.io/plndr/kube—vip:v0.3.8#使用下面的容器输出静态Pod资源清单 这里我们将 vip 设置为 192.168.31.10,首先会将 master1 节点选举为 Leader,然后接下来我们使用该 vip 来初始化控制器平台。 初始化控制平面 上面的相关环境配置也完成了,现在我们就可以来安装 Kubeadm 了,我们这里是通过指定 yum 源的方式来进行安装的: 当然了,上面的 yum 源是需要科学上网的,如果不能科学上网的话,我们可以使用阿里云的源进行安装: 然后安装 kubeadm,kubelet,kubectl: #——disableexcludes禁掉除了kubernetes之外的别的仓库~yummakecachefast~yuminstall—ykubelet—1.22.1kubeadm—1.22.1kubectl—1.22.1——disableexcludes=kubernetes 可以看到我们这里安装的是 v1.22.1 版本,然后将 master 节点的 kubelet 设置成开机启动: 。~systemctlenable——nowkubelet 到这里为止上面所有的操作都需要在所有节点执行配置。 当我们执行 kubelet ——help 命令的时候可以看到原来大部分命令行参数都被 DEPRECATED了,这是因为官方推荐我们使用 ——config 来指定配置文件,在配置文件中指定原来这些参数的配置,可以通过官方文档 Set Kubelet parameters via a config file 了解更多相关信息,这样 Kubernetes 就可以支持动态 Kubelet 配置了,参考 Reconfigure a Nodersquo,s Kubelet in a Live Cluster。 然后我们可以通过下面的命令在 master1 节点上输出集群初始化默认使用的配置: 。~kubeadmconfigprintinit—defaults——component—configsKubeletConfigurationgt,kubeadm.yaml 然后根据我们自己的需求修改配置,比如修改 imageRepository 指定集群初始化时拉取 Kubernetes 所需镜像的地址,kube—proxy 的模式为 ipvs,另外需要注意的是我们这里是准备安装 flannel 网络插件的,需要将 networking.podSubnet 设置为10.244.0.0/16: 这里需要注意的是我们在 ClusterConfiguration 块的配置中新增了控制平面的地址以及将 api.k8s.local 这个域名加入到了证书签名中,该域名将映射到 vip: controlPlaneEndpoint:api.k8s.local:6443#设置控制平面Endpoint地址apiServer:extraArgs:authorization—mode:Node,RBACtimeoutForControlPlane:4m0scertSANs:#添加其他master节点的相关信息—api.k8s.local—master1—master2—master3—192.168.31.30—192.168.31.31—192.168.31.32 在开始初始化集群之前可以使用 kubeadm config images pull ——config kubeadm.yaml 预先在各个服务器节点上拉取所k8s需要的容器镜像。 配置文件准备好过后,可以使用如下命令先将相关镜像 pull 下面: 上面在拉取 coredns 镜像的时候出错了,没有找到这个镜像,我们可以手动 pull 该镜像,然后重新 tag 下镜像地址即可: 然后就可以使用上面的配置文件在 master1 节点上进行初始化: 这里初始化的 ——upload—certs 标志用来将在所有控制平面实例之间的共享证书上传到集群。然后根据安装提示拷贝 kubeconfig 文件: ~mkdir—p$HOME/.kube~sudocp—i/etc/kubernetes/admin.conf$HOME/.kube/config 接着我们可以根据上面的提示添加其他的控制平面节点。 添加控制平面 对于每个其他控制平面节点,执行先前在第一个节点 master1 上的 kubeadm init 输出提供的 join 命令来添加控制平面节点: 。~kubeadmjoinapi.k8s.local:6443——tokenabcdef.0123456789abcdef——discovery—token—ca—cert—hashsha256:435fbc28490d1f897337923c19ec27bcf3639e9fe84e8448177777d23cae4176——control—plane——certificate—key7892cd62c5ab60b28b462af32c7e49aa73d5fd4f723352f3af6546a74e465abcRunningpre—flightchecksReadingconfigurationfromthecluster...FYI:Youcanlookatthisconfigfilewith'kubectl—nkube—systemgetcmkubeadm—config—oyaml'Runningpre—flightchecksbeforeinitializingthenewcontrolplaneinstance......Thisnodehasjoinedtheclusterandanewcontrolplaneinstancewascreated:*Certificatesigningrequestwassenttoapiserverandapprovalwasreceived.*TheKubeletwasinformedofthenewsecureconnectiondetails.*Controlplanelabelandtaintwereappliedtothenewnode.*TheKubernetescontrolplaneinstancesscaledup.*Anewetcdmemberwasaddedtothelocal/stackedetcdcluster.Tostartadministeringyourclusterfromthisnode,youneedtorunthefollowingasaregularuser:mkdir—p$HOME/.kubesudocp—i/etc/kubernetes/admin.conf$HOME/.kube/configsudochown$:$$HOME/.kube/configRun'kubectlgetnodes'toseethisnodejointhecluster. 需要注意需要在另外两个节点 master2 和 master3 都执行上面的 join 命令,上面的命令中的 ——control—plane 就是通知 kubeadm join 创建一个新的控制平面,——certificate—key 会从集群中的 kubeadm—certs Secret 下载控制平面证书并使用给定的密钥进行解密。 当这两个节点被添加到集群后,我们接下来也需要在节点上运行 kube—vip,将当前节点作为 kube—vip 的成员,同样执行下面的命令即可: #配置vip地址~exportVIP=192.168.31.10#设置网卡名称~exportINTERFACE=ens33~ctrimagepulldocker.io/plndr/kube—vip:v0.3.8#使用下面的容器输出静态Pod资源清单 当 kube—vip 的静态 Pod 清单创建完成后,正常将能够看到 kube—vip 的 Pod 会按预期启动并运行: grepvipkube—systemkube—vip—master11/1Running17m42skube—systemkube—vip—master21/1Running04m24skube—systemkube—vip—master31/1Running014s 这个时候控制平面节点就都准备好了: 。~kubectlgetnodesNAMESTATUSROLESAGEVERSIONmaster1Readycontrol—plane,master9m18sv1.22.1master2Readycontrol—plane,master7m11sv1.22.1master3Readycontrol—plane,master5m9sv1.22.1 添加工作节点 接下来我们可以将 node1 工作节点加入到集群中,同样使用在 master1 上初始化后的提示 join 命令,记得将 master1 节点上面的 $HOME/.kube/config 文件拷贝到 node 节点对应的文件中,安装 kubeadm,kubelet,kubectl,然后执行上面初始化完成后提示的 join 命令即可: ~kubeadmjoinapi.k8s.local:6443——tokenabcdef.0123456789abcdefgt,——discovery—token—ca—cert—hashsha256:435fbc28490d1f897337923c19ec27bcf3639e9fe84e8448177777d23cae4176Runningpre—flightchecksReadingconfigurationfromthecluster...FYI:Youcanlookatthisconfigfilewith'kubectl—nkube—systemgetcmkubeadm—config—oyaml'Writingkubeletconfigurationtofile"/var/lib/kubelet/config.yaml"Writingkubeletenvironmentfilewithflagstofile"/var/lib/kubelet/kubeadm—flags.env"StartingthekubeletWaitingforthekubelettoperformtheTLSBootstrap...Thisnodehasjoinedthecluster:*Certificatesigningrequestwassenttoapiserverandaresponsewasreceived.*TheKubeletwasinformedofthenewsecureconnectiondetails.Run'kubectlgetnodes'onthecontrol—planetoseethisnodejointhecluster. 如果忘记了上面的 join 命令可以使用命令 kubeadm token create ——print—join—command 重新获取 执行成功后运行 get nodes 命令: 。~kubectlgetnodesNAMESTATUSROLESAGEVERSIONmaster1Readycontrol—plane,master9m18sv1.22.1master2Readycontrol—plane,master7m11sv1.22.1master3Readycontrol—plane,master5m9sv1.22.1node1NotReady24sv1.22.1 隔一会儿查看 Pod 运行状态: 网络插件运行成功了,node 状态也正常了: 。~kubectlgetnodesNAMESTATUSROLESAGEVERSIONmaster1Readycontrol—plane,master9m18sv1.22.1master2Readycontrol—plane,master7m11sv1.22.1master3Readycontrol—plane,master5m9sv1.22.1node1Ready24sv1.22.1 测试高可用 上面我们搭建了3个 master 节点的高可用 Kubernetes 集群,接下来我们来测试下高可用是否生效。 首先查看其中任一个 kube—vip 的 Pod 日志: 。~kubectllogs—fkube—vip—master1—nkube—systemtime="2021—09—07T08:53:24Z"level=infomsg="serverstarted"time="2021—09—07T08:53:24Z"level=infomsg="StartingKube—vipManagerwiththeARPengine"time="2021—09—07T08:53:24Z"level=infomsg="Namespace,Hybridmode"time="2021—09—07T08:53:24Z"level=infomsg="Beginningclustermembership,namespace,lockname,id"I090708:53:24.2056691leaderelection.go:243)attemptingtoacquireleaderleasekube—system/plndr—svcs—lock...time="2021—09—07T08:53:24Z"level=infomsg="Beginningclustermembership,namespace,lockname(plndr—cp—lock),id"I090708:53:24.2061621leaderelection.go:243)attemptingtoacquireleaderleasekube—system/plndr—cp—lock.........time="2021—09—07T08:55:55Z"level=infomsg="Node(master3)isassumingleadershipofthecluster"time="2021—09—07T08:55:55Z"level=infomsg="newleaderelected:master3" 可以看到 master3 现在是我们的 Leader,接下来我们将 master3 节点关掉,然后观察另外的 kube—vip 的日志变化: 。~kubectllogs—fkube—vip—master2—nkube—system......time="2021—09—07T08:55:55Z"level=infomsg="Node(master3)isassumingleadershipofthecluster"time="2021—09—07T08:55:55Z"level=infomsg="newleaderelected:master3"time="2021—09—07T10:28:58Z"level=infomsg="Nodeisassumingleadershipofthecluster"...... 可以看到 master1 节点获取了 kube—vip 的 Leader,也就是这个时候 vip 是绑定到 master1 节点的,而且这个时候集群仍然可以正常访问的。 Dashboard v1.22.1 版本的集群需要安装最新的 2.0+ 版本的 Dashboard: 直接创建: 。~kubectlapply—frecommended.yaml 新版本的 Dashboard 会被默认安装在 kubernetes—dashboard 这个命名空间下面: 。~kubectlgetpods—nkubernetes—dashboard—owideNAMEREADYSTATUSRESTARTSAGEIPNODENOMINATEDNODEREADINESSGATESdashboard—metrics—scraper—856586f554—pllvt1/1Running024m10.88.0.7masterkubernetes—dashboard—76597d7df5—829981/1Running021m10.88.0.2node2 我们仔细看可以发现上面的 Pod 分配的 IP 段是 10.88.xx.xx,包括前面自动安装的 CoreDNS 也是如此,我们前面不是配置的 podSubnet 为 10.244.0.0/16 吗。我们先去查看下 CNI 的配置文件: 。~ls—la/etc/cni/net.d/total8drwxr—xr—x21001docker67Aug3116:45.drwxr—xr—x.31001docker19Jul3001:13..—rw—r——r——11001docker604Jul3001:1310—containerd—net.conflist—rw—r——r——1rootroot292Aug3116:4510—flannel.conflist 可以看到里面包含两个配置,一个是 10—containerd—net.conflist,另外一个是我们上面创建的 Flannel 网络插件生成的配置,我们的需求肯定是想使用 Flannel 的这个配置,我们可以查看下 containerd 这个自带的 cni 插件配置: 。~cat/etc/cni/net.d/10—containerd—net.conflist"cniVersion":"0.4.0","name":"containerd—net","plugins":("type":"bridge","bridge":"cni0","isGateway":true,"ipMasq":true,"promiscMode":true,"ipam":"type":"host—local","ranges":(("subnet":"10.88.0.0/16"),("subnet":"2001:4860:4860::/64")),"routes":("dst":"0.0.0.0/0","dst":"::/0"),"type":"portmap","capabilities":"portMappings":true) 可以看到上面的 IP 段恰好就是 10.88.0.0/16,但是这个 cni 插件类型是 bridge 网络,网桥的名称为 cni0: 。~ipa...6:cni0:lt,BROADCAST,MULTICAST,PROMISC,UP,LOWER_UPgt,mtu1500qdiscnoqueuestateUPgroupdefaultqlen1000link/ether9a:e7:eb:40:e8:66brdff:ff:ff:ff:ff:ffinet10.88.0.1/16brd10.88.255.255scopeglobalcni0valid_lftforeverpreferred_lftforeverinet62001:4860:4860::1/64scopeglobalvalid_lftforeverpreferred_lftforeverinet6fe80::98e7:ebff:fe40:e866/64scopelinkvalid_lftforeverpreferred_lftforever... 但是使用 bridge 网络的容器无法跨多个宿主机进行通信,跨主机通信需要借助其他的 cni 插件,比如上面我们安装的 Flannel,或者 Calico 等等,由于我们这里有两个 cni 配置,所以我们需要将 10—containerd—net.conflist 这个配置删除,因为如果这个目录中有多个 cni 配置文件,kubelet 将会使用按文件名的字典顺序排列的第一个作为配置文件,所以前面默认选择使用的是 containerd—net 这个插件。 ~mv/etc/cni/net.d/10—containerd—net.conflist/etc/cni/net.d/10—containerd—net.conflist.bak~ifconfigcni0downamp,amp,iplinkdeletecni0~systemctldaemon—reload 然后记得重建 coredns 和 dashboard 的 Pod,重建后 Pod 的 IP 地址就正常了: ~kubectlgetpods—nkubernetes—dashboard—owideNAMEREADYSTATUSRESTARTSAGEIPNODENOMINATEDNODEREADINESSGATESdashboard—metrics—scraper—856586f554—tp8m51/1Running042s10.244.1.6node2kubernetes—dashboard—76597d7df5—9rmbx1/1Running066s10.244.1.5node2 查看 Dashboard 的 NodePort 端口: 。~kubectlgetsvc—nkubernetes—dashboardNAMETYPECLUSTER—IPEXTERNAL—IPPORT(S)AGEdashboard—metrics—scraperClusterIP10.99.37.1728000/TCP25mkubernetes—dashboardNodePort10.103.102.27443:31050/TCP25m 信任证书 信任后就可以访问到 Dashboard 的登录页面了: Dashboard 登录页面 然后创建一个具有全局所有权限的用户来登录 Dashboard: #admin.yamlkind:ClusterRoleBindingapiVersion:rbac.authorization.k8s.io/v1metadata:name:adminroleRef:kind:ClusterRolename:cluster—adminapiGroup:rbac.authorization.k8s.iosubjects:—kind:ServiceAccountname:adminnamespace:kubernetes—dashboardapiVersion:v1kind:ServiceAccountmetadata:name:adminnamespace:kubernetes—dashboard 直接创建: ~kubectlapply—fadmin.yamlgrepadmin—tokenadmin—token—lwmmxkubernetes.io/service—account—token31d 然后用上面的 base64 解码后的字符串作为 token 登录 Dashboard 即可,新版本还新增了一个暗黑模式: k8s dashboard 最终我们就完成了使用 kubeadm 搭建 v1.22.1 版本的高可用 kubernetes 集群,使用 coredns,ipvs,flannel,containerd,kube—vip 这些组件。 清理 如果你的集群安装过程中遇到了其他问题,我们可以使用下面的命令来进行重置: ~kubeadmreset~ifconfigcni0downamp,amp,iplinkdeletecni0~ifconfigflannel.1downamp,amp,iplinkdeleteflannel.1 中国商业网资讯门户;更多内容请关注中国商业网各频道、栏目资讯免责声明:凡本站注明 “来自:(非中国商业网)”的新闻稿件和图片作品,系本站转载自其它媒体,转载目的在于信息传递,并不代表本站赞同其观点和对其真实性负责 |
鲜花 |
握手 |
雷人 |
路过 |
鸡蛋 |
2021-09-02
2021-09-02
2021-09-02
2021-09-02
2021-09-02