Kubeadm是一个K8s部署工具,提供kubeadminit和kubeadmjoin,用于快速部署Kubernetes集群。
二进制包
从github下载发行版的二进制包,手动部署每个组件,组成Kubernetes集群。
小结:Kubeadm降低部署门槛,但屏蔽了很多细节,遇到问题很难排查。如果想更容易可控,推荐使用二进制包部署Kubernetes集群,虽然手动部署麻烦点,期间可以学习很多工作原理,也利于后期维护。
服务器要求:
Master01
LoadBalancer(Master)
172.21.161.110
172.21.161.120(vip)
kube-apiserver
kube-controller-manager
kube-scheduler
kubelet
kube-proxy
NginxL4
Master02
LoadBalancer(Backup)
docker
flannel
这里为了使搭建过程更清晰,尽量将各角色分配到不同的机器上。每个机器都部署属于自己的角色。比如生成证书就在public跳板机上去生成,然后推送到对应服务器。
单Master架构图
单Master服务器规划:
Etcd是一个分布式键值存储系统,Kubernetes使用Etcd进行数据存储,所以先准备一个Etcd数据库,为解决Etcd单点故障,应采用集群方式部署,这里使用3台组建集群,可容忍1台机器故障,当然,你也可以使用5台组建集群,可容忍2台机器故障。
cfssl是一个开源的证书管理工具,使用json文件生成证书,相比openssl更方便使用。
找一台服务器操作,这里用public节点。证书的生成以及分配都在public上操作
按照需求分类来说,这里所有的服务组件controller-manager、scheduler、kubelet、kube-proxy、kubeclt等需要访问apiserver,这里需要一套。Apiserver访问etcd集群又是一套单独的。所以这里2套证书是2个不同自签CA颁发的。
签发证书都在public机器上。
创建工作目录:
#public节点操作mkdir-p/k8s-deploy/cfssl/TLS/{etcd,k8s}cd/k8s-deploy/cfssl/TLS/etcd自签CA:
#public节点操作cat>ca-config.json< cfsslgencert-initcaca-csr.json|cfssljson-bareca-会生成ca.pem和ca-key.pem文件 创建证书申请文件: #public节点操作cat>server-csr.json< 生成证书: cfsslgencert-ca=ca.pem-ca-key=ca-key.pem-config=ca-config.json-profile=wwwserver-csr.json|cfssljson-bareserver会生成server.pem和server-key.pem文件。 以下在etcd节点1上操作,为简化操作,待会将节点1生成的所有文件拷贝到节点2和节点3. [root@publicetcd]#scp-r/k8s-deploy/cfssl/TLS/etcd/ca*pem/k8s-deploy/cfssl/TLS/etcd/server*pemroot@etcd01:/opt/etcd/ssl5.启动并设置开机启动#etcd01节点操作systemctldaemon-reload#启动的时候会hold住,因为其它两个节点没有配置,一直在寻找其它节点systemctlstartetcdsystemctlenableetcd6.将上面节点1所有生成的文件拷贝到节点2和节点3#etcd01节点操作scp-r/opt/etcd/root@etcd02:/opt/scp/usr/lib/systemd/system/etcd.serviceroot@etcd02:/usr/lib/systemd/system/scp-r/opt/etcd/root@etcd03:/opt/scp/usr/lib/systemd/system/etcd.serviceroot@etcd03:/usr/lib/systemd/system/然后在节点2和节点3分别修改etcd.conf配置文件中的节点名称和当前服务器IP:(总共5处) 这里使用Docker作为容器引擎,也可以换成别的,例如containerd 以下在所有节点操作。这里采用二进制安装,用yum安装也一样。本节其实已经用yum安装一遍了,这里只是做一个源码的演示。 tarzxvfdocker-20.10.7.tgzmvdocker/*/usr/bin systemctldaemon-reloadsystemctlstartdockersystemctlenabledocker 证书操作在public机器上,这是另一套独立etcd的自签ca证书 #切换工作目录(public)cd/k8s-deploy/cfssl/TLS/k8s/cat>ca-config.json< cfsslgencert-initcaca-csr.json|cfssljson-bareca-会生成ca.pem和ca-key.pem文件。 #public节点操作cat>server-csr.json< cfsslgencert-ca=ca.pem-ca-key=ca-key.pem-config=ca-config.json-profile=kubernetesserver-csr.json|cfssljson-bareserver会生成server.pem和server-key.pem文件。 注:打开链接你会发现里面有很多包,下载一个server包就够了,包含了Master和WorkerNode二进制文件。 #master01节点操作mkdir-p/opt/kubernetes/{bin,cfg,ssl,logs}tarzxvfkubernetes-server-linux-amd64.tar.gzcdkubernetes/server/bincpkube-apiserverkube-schedulerkube-controller-manager/opt/kubernetes/bincpkubectl/usr/bin/ 把刚才生成的证书拷贝到配置文件中的路径: [root@publick8s]#scp-r/k8s-deploy/cfssl/TLS/k8s/ca*pem/k8s-deploy/cfssl/TLS/k8s/server*pemroot@master01:/opt/kubernetes/ssl注意,因为etcd和master不在一台机器部署,这里etcd的证书也要拷贝 #首先master01要创建目录mkdir/opt/etcd/ssl-p[root@master01bin]#mkdir/opt/etcd/ssl-p[root@publick8s]#scp-r/k8s-deploy/cfssl/TLS/etcd/ca*pem/k8s-deploy/cfssl/TLS/etcd/server*pemroot@master01:/opt/etcd/ssl3.启用TLSBootstrapping机制TLSBootstraping:Masterapiserver启用TLS认证后,Node节点kubelet和kube-proxy要与kube-apiserver进行通信,必须使用CA签发的有效证书才可以,当Node节点很多时,这种客户端证书颁发需要大量工作,同样也会增加集群扩展复杂度。为了简化流程,Kubernetes引入了TLSbootstraping机制来自动颁发客户端证书,kubelet会以一个低权限用户自动向apiserver申请证书,kubelet的证书由apiserver动态签署。所以强烈建议在Node上使用这种方式,目前主要用于kubelet,kube-proxy还是由我们统一颁发一个证书。 TLSbootstraping工作流程: 创建上述配置文件中token文件: #master01节点操作cat>/opt/kubernetes/cfg/token.csv< token也可自行生成替换: #master01节点操作cat>/opt/kubernetes/cfg/kube-controller-manager.conf< #切换工作目录(public,证书一般要切换回public机器操作)cd/k8s-deploy/cfssl/TLS/k8s/#创建证书请求文件cat>kube-controller-manager-csr.json< 这里生成的证书文件因为在public,所以要拷贝到master01的相应目录 #master01节点操作cat>/opt/kubernetes/cfg/kube-scheduler.conf< #切换工作目录(public,证书一般要切换回public机器操作)cd/k8s-deploy/cfssl/TLS/k8s/#创建证书请求文件cat>kube-scheduler-csr.json< 生成kubectl连接集群的证书: #想访问k8s集群的机器操作,这里使用publiccat>admin-csr.json< kubectlgetcsNAMESTATUSMESSAGEERRORschedulerHealthyokcontroller-managerHealthyoketcd-2Healthy{"health":"true"}etcd-1Healthy{"health":"true"}etcd-0Healthy{"health":"true"}如上输出说明Master节点组件运行正常。 也可以顺便同时让master可以访问,在public将config文件拷贝至master01节点即可 [root@master01ssl]#mkdir/root/.kube[root@public~]#scp-r/root/.kube/root@master01:/root #创建node必备,不然node的kubelet无法启动,就是创建一个可以申请证书的用户kubectlcreateclusterrolebindingkubelet-bootstrap\--clusterrole=system:node-bootstrapper\--user=kubelet-bootstrap 在所有workernode创建工作目录: mkdir-p/opt/kubernetes/{bin,cfg,ssl,logs}从master至node节点: cd/tools/kubernetes/server/bin/scp-rkubeletkube-proxyroot@node01:/opt/kubernetes/bin/scp/opt/kubernetes/ssl/ca.pemroot@node01:/opt/kubernetes/ssl/scp/usr/bin/kubectlnode01:/usr/bin #node01节点操作cat>/opt/kubernetes/cfg/kubelet.conf< #查看kubelet证书请求[root@publick8s]#kubectlgetcsrNAMEAGESIGNERNAMEREQUESTORCONDITIONnode-csr-84G21oPC3hDbyMwZN62ExQDI4D2Xa8IO74zHtlWRhD860skubernetes.io/kube-apiserver-client-kubeletkubelet-bootstrapPending#批准申请[root@publick8s]#kubectlcertificateapprovenode-csr-84G21oPC3hDbyMwZN62ExQDI4D2Xa8IO74zHtlWRhD8certificatesigningrequest.certificates.k8s.io/node-csr-84G21oPC3hDbyMwZN62ExQDI4D2Xa8IO74zHtlWRhD8approved[root@publick8s]#kubectlgetnodeNAMESTATUSROLESAGEVERSIONnode01NotReady [root@publick8s]#kubectlcertificateapprovenode-csr-84G21oPC3hDbyMwZN62ExQDI4D2Xa8IO74zHtlWRhD8Noresourcesfounderror:nokind"CertificateSigningRequest"isregisteredforversion"certificates.k8s.io/v1"inscheme"k8s.io/kubernetes/pkg/kubectl/scheme/scheme.go:28"#因为客户端版本不对[root@publick8s]#kubectlversion--shortClientVersion:v1.12.7ServerVersion:v1.20.7注:由于网络插件还没有部署,节点会没有准备就绪NotReady Calico是一个纯三层的数据中心网络方案,是目前Kubernetes主流的网络方案。 部署Calico: kubectlgetnodeNAMESTATUSROLESAGEVERSIONnode01Ready 准备环境的时候,各node节点的/etc/hosts里面的默认记录,也就是localhost记录,一定不要删除或者误删,否则会出现以下报错,pod是运行的,但是健康检查一直无法通过。 应用场景:例如kubectllogs cat>apiserver-to-kubelet-rbac.yaml< [root@node01cfg]#scp-r/opt/kubernetes/root@node02:/opt#包括,程序,证书,都在里面,主要需要ca.pem[root@node01cfg]#scp-r/usr/lib/systemd/system/{kubelet,kube-proxy}.serviceroot@node02:/usr/lib/systemd/system2.删除kubelet证书和kubeconfig文件#node02节点操作rm-f/opt/kubernetes/cfg/kubelet.kubeconfig#审批通过后会自动生成rm-f/opt/kubernetes/ssl/kubelet-client*注:这几个文件是证书申请审批后自动生成的,每个Node不同,必须删除 创建serviceaccount并绑定默认cluster-admin管理员集群角色: CoreDNS用于集群内部Service名称解析。 #哪里有yaml文件可以访问集群,就在哪里操作kubectlapply-fcoredns.yamlkubectlgetpods-nkube-systemNAMEREADYSTATUSRESTARTSAGEcoredns-5ffbfd976d-j6shb1/1Running032sDNS解析测试: #创建之前要开启api访问kubelet权限,不然无法进入容器kubectlrun-it--rmdns-test--image=busybox:1.28.4shIfyoudon'tseeacommandprompt,trypressingenter./#nslookupkubernetesServer:10.0.0.2Address1:10.0.0.2kube-dns.kube-system.svc.cluster.localName:kubernetesAddress1:10.0.0.1kubernetes.default.svc.cluster.local解析没问题。 至此一个单Master集群就搭建完成了!这个环境就足以满足学习实验了,下面继续扩容多Master集群! Kubernetes作为容器集群系统,通过健康检查+重启策略实现了Pod故障自我修复能力,通过调度算法实现将Pod分布式部署,并保持预期副本数,根据Node失效状态自动在其他Node拉起Pod,实现了应用层的高可用性。 针对Kubernetes集群,高可用性还应包含以下两个层面的考虑:Etcd数据库的高可用性和KubernetesMaster组件的高可用性。而Etcd我们已经采用3个节点组建集群实现高可用,本节将对Master节点高可用进行说明和实施。 Master节点扮演着总控中心的角色,通过不断与工作节点上的Kubelet和kube-proxy进行通信来维护整个集群的健康工作状态。如果Master节点故障,将无法使用kubectl工具或者API做任何集群管理。 Master节点主要有三个服务kube-apiserver、kube-controller-manager和kube-scheduler,其中kube-controller-manager和kube-scheduler组件自身通过选择机制已经实现了高可用,所以Master高可用主要针对kube-apiserver组件,而该组件是以HTTPAPI提供服务,因此对他高可用与Web服务器类似,增加负载均衡器对其负载均衡即可,并且可水平扩容。 多Master架构图: 现在需要再增加一台新服务器,作为Master2Node,IP是172.21.161.111。 为了节省资源你也可以将之前部署好的WorkerNode1复用为Master2Node角色(即部署Master组件,这里不这么做) Master02与已部署的Master01所有操作一致。所以我们只需将Master01所有K8s文件拷贝过来,再修改下服务器IP和主机名启动即可 安装docker及更改主机名以及主机名加入到所有机器的映射 在Master02创建etcd证书目录: #master02节点操作mkdir-p/opt/etcd/ssl3.拷贝文件(Master01操作)拷贝Master1上所有K8s文件和etcd证书到Master2: scp-r/opt/kubernetesroot@master02:/optscp-r/opt/etcd/sslroot@master02:/opt/etcdscp/usr/lib/systemd/system/kube*root@master02:/usr/lib/systemd/systemscp/usr/bin/kubectlroot@master02:/usr/binscp-r/root/.kuberoot@master02:/root4.删除证书文件删除kubelet证书和kubeconfig文件: #master02节点操作#如果master没有部署node节点组件,可忽略这一步rm-f/opt/kubernetes/cfg/kubelet.kubeconfigrm-f/opt/kubernetes/ssl/kubelet*5.修改配置文件IP和主机名修改apiserver、kubelet和kube-proxy配置文件为本地IP:(7处修改) kube-apiserver高可用架构图: 注1:为了节省机器,这里与K8sMaster节点机器复用。也可以独立于k8s集群之外部署,只要nginx与apiserver能通信就行。 注2:如果你是在公有云上,一般都不支持keepalived,那么你可以直接用它们的负载均衡器产品,直接负载均衡多台Masterkube-apiserver,架构与上面一样。 在两台Master节点操作。 cat>/etc/keepalived/check_nginx.sh<<"EOF"#!/bin/bashcount=$(ss-antp|grep16443|egrep-cv"grep|$$")if["$count"-eq0];thenexit1elseexit0fiEOFchmod+x/etc/keepalived/check_nginx.sh注:keepalived根据脚本返回状态码(0为工作正常,非0不正常)判断是否故障转移。 cat>/etc/keepalived/keepalived.conf< 在NginxMaster执行pkillnginx; 在NginxBackup,ipaddr命令查看已成功绑定VIP 找K8s集群中任意一个节点,使用curl查看K8s版本测试,使用VIP访问: 通过查看Nginx日志也可以看到转发apiserverIP: [root@master01.kube]#tail-f/var/log/nginx/k8s-access.log172.21.161.110172.21.161.110:6443-[13/Jun/2021:11:56:31+0800]2002138172.21.161.110172.21.161.111:6443-[13/Jun/2021:12:01:37+0800]2001711172.21.161.115172.21.161.110:6443-[13/Jun/2021:19:04:08+0800]2001172172.21.161.115172.21.161.111:6443-[13/Jun/2021:19:05:39+0800]2003596172.21.161.116172.21.161.110:6443-[13/Jun/2021:19:06:22+0800]2001173172.21.161.116172.21.161.110:6443-[13/Jun/2021:19:06:28+0800]2001174172.21.161.116172.21.161.111:6443-[13/Jun/2021:19:07:59+0800]2003020到此还没结束,还有下面最关键的一步。 试想下,虽然我们增加了Master2Node和负载均衡器,但是我们是从单Master架构扩容的,也就是说目前所有的WorkerNode组件连接都还是Master01,如果不改为连接VIP走负载均衡器,那么Master还是单点故障。 因此接下来就是要改所有WorkerNode(kubectlgetnode命令查看到的节点)组件配置文件,由原来172.21.161.110修改为172.21.161.120(VIP)。 在所有WorkerNode执行: sed-i's#172.21.161.110:6443#172.21.161.120:16443#'/opt/kubernetes/cfg/*准确来说,上述命令只适合在纯node节点上使用,如果master01部署了node,那么也会有上述IP,所以为了更精确,下面指出具体哪几个配置文件需要更改。 最后将服务重启 systemctlrestartkubeletkube-proxy 当然,在一般情况下,master上也有kubelet等一些进行,用来部署一些系统级别pod,但是前面为了让部署的步骤拆分的更为细致,所以,每台机器部署不同的角色,这里将Master上增加worker组件。和新增一台workernode区别不大。 在node节点将WorkerNode涉及文件拷贝到master01 #node01节点操作scp-r/opt/kubernetes/root@master01:/optscp-r/usr/lib/systemd/system/{kubelet,kube-proxy}.serviceroot@master01:/usr/lib/systemd/system2.删除kubelet证书和kubeconfig文件rm-rf/opt/kubernetes/cfg/kubelet.kubeconfigrm-rf/opt/kubernetes/ssl/kubelet-client-*注:这几个文件是证书申请审批后自动生成的,每个Node不同,必须删除