K8S二进制部署高可用集群-1.22[六]
本节前言:
本节关键字:KUBELET、KUBE-PROXY;
关于"KUBELET"组件,其主要作用为:运行于"NODE"之上的守护进程,"NODE"的核心代理程序;从"KUBE-APISERVER"接收关于"POD"对象的配置信息并确保它们处于期望的状态;另外"KUBELET"会在"KUBE-APISERVER"上注册当前工作节点,定期向"MASTER"汇报节点资源使用情况;
关于"KUBE-PROXY"组件,其主要作用为:负责为"Service"资源提供集群内部的服务发现和负载均衡;它能够按需为"Service"资源对象生成"IPTABLES"或"IPVS"规则,使访问"Service"资源的流量正确转发至后端的"POD"对象;
本节开始……
一、KUBELET组件
注意:在执行本步骤前,你应该已经将[ kubelet、kube-proxy ]这些文件保存至"/usr/local/bin"[192.168.100.41 - 43、192.168.100.46 -47];另外,本处的示例操作,博主暂时并不打算使用[192.168.100.16 - 47]节点,而是复用MASTER的节点,也就是说,[192.168.100.41 - 43]既是MASTER节点,同时又是NODE工作节点;为什么这样配置?这其实是考虑到真实生产环境中,有可能有这种需求"在MASTER上运行某此特定的POD",比如说监控;当然,作为MASTER节点,实际上我们并不希望上面运行着非特殊需求的POD,那么我们可以设置节点的特性解决这种问题,例如K8S的"污点"概念,真实情况下,将真实节点配置为"不可调度状态"是常用的做法;
以下操作均在[192.168.100.41]进行,然后按需要推送至[192.168.100.42 - 43];开始:生成"KUBELET"组件的"kubelet-bootstrap.kubeconfig"配置文件;还记得前面"KUBE-APISERVER"组件部署章节中,博主提示了关注"kube-apiserver.token.csv"这份文件中的"kubelet-bootstrap"这个用户名吗?这个用户名不是K8S集群的默认内置用户,那么这个用户名是怎么在K8S集群中生效的?本处的"kubectl create clusterrolebinding"告诉了你答案;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
$ cd /opt/cluster/ssl $ kubectl config set-cluster kubernetes --certificate-authority=/opt/cluster/ssl/rootca/rootca.pem \ --embed-certs=true --server=https://192.168.100.40:6443 \ --kubeconfig=kubernetes/kubelet-bootstrap.kubeconfig $ kubectl config set-credentials kubelet-bootstrap --token=$(awk -F "," '{print $1}' /opt/cluster/ssl/kubernetes/kube-apiserver.token.csv) \ --kubeconfig=kubernetes/kubelet-bootstrap.kubeconfig $ kubectl config set-context default --cluster=kubernetes --user=kubelet-bootstrap \ --kubeconfig=kubernetes/kubelet-bootstrap.kubeconfig $ kubectl config use-context default --kubeconfig=kubernetes/kubelet-bootstrap.kubeconfig # 这条命令实际上与上面的命令没有什么关系,正确来说应该分开来写的,但是博主已经这么写了,算了 # # # 关于本命令中的"kubelet-bootstrap" # 第一个"kubelet-bootstrap":会在K8S集群中创建一个名为"kubelet-bootstrap"的"ClusterRoleBinding"资源 # "kubectl get clusterrolebinding" # # 第二个"--user=kubelet-bootstrap":表示将对应"ClusterRoleBinding"资源中的"subjects.kind"="User"、"subjects.name"="kubelet-bootstrap" # "kubectl get clusterrolebinding kubelet-bootstrap -o yaml" # # 在经过本命令的配置后,KUBE-APISERVER的"kube-apiserver.token.csv"配置文件中的用户名"kubelet-bootstrap" # 便真正的在K8S集群中有了意义 $ kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap |
生成"KUBELET"组件的"kubelet.conf"配置文件[实际是指K8S的"KubeletConfiguration"资源][这实际是一份YAML文件];本处可能有人有疑问,为什么"KUBELET"组件需要"kubelet.conf"这份配置文件?既然是配置,为什么不直接写在"kubelet.service"这份文件中?博主简单解释一下:1、这是官方的默认做法,目的主要是适配"KUBEADM"部署K8S集群;2、使用"kubelet -h",你会发现,很多的配置项标记为"DEPRECATED"状态,为了避免后续的K8S集群升级引发额外的问题,所以使用了官方的默认方法;3、关于"KUBELET"组件的配置项,官方将配置项分为两种状态,每个节点均应该相同的配置项及每个节点可以自定义的配置项,关于"每个节点可自定义的配置项",官方将其实优先放入"kubelet.con"中[第三种是网络上的某种说法,博主对这个说法保留意见;实际上博主觉得,K8S官方更多的是希望为"KUBELET"组件设计一份专属格式的配置文件,就像其它软件一样,有其专属的配置文件,只不过这份"kubelet.conf"配置文件要达到稳定状态,还需要一点一点的去积累];注意,以上强行解释仅是一种猜测:
这份"kubelet.conf"配置文件实际上是每个工作节点[NODE]通用的,但你应该要先明白这份配置要达到通用状态的前提条件是什么~而其中比较关键的一条是配置文件中的"address: 0.0.0.0"配置项,是的,配置文件中并未特别为每一个节点配置特定的IP地址!!!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# 可以使用以下命令获取一份"KubeletConfiguration"资源的基础配置[需要删除有关KUBEADM的部分] # "kubeadm config print init-defaults --component-configs KubeletConfiguration > kubelet.conf" # 相关配置说明文档[https://kubernetes.io/docs/reference/config-api/] $ cd /opt/cluster/ssl cat > kubernetes/kubelet.conf << "EOF" kind: KubeletConfiguration apiVersion: kubelet.config.k8s.io/v1beta1 address: 0.0.0.0 # [增加]KUBELET的监听地址[官方默认"0.0.0.0"] port: 10250 # [增加]KUBELET的监听地址[官方默认"10250"] readOnlyPort: 0 # [增加]KUBELET仅访问权限的监听地址[建议配置为"0"禁用] authentication: anonymous: enabled: false webhook: cacheTTL: 2m0s enabled: true x509: clientCAFile: /opt/cluster/ssl/rootca/rootca.pem # 指向的根CA公钥 authorization: mode: Webhook webhook: cacheAuthorizedTTL: 5m0s cacheUnauthorizedTTL: 30s cgroupDriver: systemd # 需要与DOCKER的"native.cgroupdriver=systemd"配置值相同[cgroupfs/systemd] clusterDNS: - 10.96.0.10 # 设置集群中DNS服务器所使用的地址[此值与后面部署CoreDNS的配置有关],此值与 clusterDomain: cluster.local # "kube-controller-manager"的"--service-cluster-ip-range="配置有关 healthzBindAddress: 127.0.0.1 healthzPort: 10248 rotateCertificates: true evictionHard: # [增加]一些不错的优化配置 imagefs.available: 15% memory.available: 100Mi nodefs.available: 10% nodefs.inodesFree: 5% maxOpenFiles: 1000000 maxPods: 110 EOF |
将证书与配置文件分发至其它服务器[分发至:192.168.100.42 - 43];
1 2 |
scp -r /opt/cluster/ssl 192.168.100.42:/opt/cluster/ scp -r /opt/cluster/ssl 192.168.100.43:/opt/cluster/ |
为"KUBELET"生成"kubelet.service"启动文件;此文件通用!见上面的通用前提[192.168.100.41 - 43]:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
cat > /usr/lib/systemd/system/kubelet.service << "EOF" [Unit] Description=Kubernetes:Kubelet After=network.target network-online.target docker.service Requires=docker.service [Service] Restart=on-failure RestartSec=5 ExecStart=/usr/local/bin/kubelet \ --bootstrap-kubeconfig=/opt/cluster/ssl/kubernetes/kubelet-bootstrap.kubeconfig \ # BOOTSTRAP[KUBELET向APISERVER申请证书就是由此文件实现的] --config=/opt/cluster/ssl/kubernetes/kubelet.conf \ # KUBELET的配置文件[监听地址与监听端口在此处配置了] --kubeconfig=/opt/cluster/kubelet/kubelet.kubeconfig \ # 此文件是不存在的,证书申请成功会自动生成此文件 --cert-dir=/opt/cluster/kubelet/ssl \ # 向APISERVER申请到的证书将保存至此目录 --network-plugin=cni \ # 启用CNI网络插件[例如:FLANNEL、CALICO] --pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2 \ # 所使用的PAUSE镜像 --logtostderr=false \ # 日志配置 --v=2 \ --log-dir=/opt/cluster/log/kubelet [Install] WantedBy=multi-user.target EOF # 关于镜像 # 默认情况下是使用"k8s.gcr.io/pause:3.2",这是GOOGLE的官方源; # 本处使用了阿里云的镜像源解决DOCKER镜像下载的问题;对于K8S默认使用到的DOCKER镜像,除了本镜像外 # 其它镜像均可以直接在国内下载到; |
启动"KUBELET"组件[192.168.100.41 - 43];你应该可以看到"KUBELET"组件的正常启动[注意:此时NODE并未真正的加入K8S集群]:
1 |
systemctl daemon-reload && systemctl enable --now kubelet.service && systemctl status kubelet.service |
使用"kubectl"命令测试:
1 2 3 4 5 6 7 8 |
# 1、查询当前K8S集群中接收到的证书签发请求[处于"Pending"状态的为未签发状态] kubectl get csr # 2、对某个处于"Pending"状态的"CSR"资源进行签发,并发送对应的证书至"KUBELET" kubectl certificate approve CSR_NAME # *、你可以通过以下命令,直接通过所有处于"Pending"的"CSR"资源[证书签发请求] kubectl get csr | grep 'Pending' | awk 'NR>0{print $1}' | xargs kubectl certificate approve |
使用"kubelet"命令进行测试~
1 2 |
*、你可以使用以下命令进行测试,你应该能获取到相关节点的信息[NoReady] kubectl get node |
补充:前面说了,MASTER节点正常情况下,我们应该将基标记为"不可调度状态",那么,你可以使用以下命令实现;但目前,你不应该这么做,原因:后续的CALICO部署,如果你设定了"kubectl cordon",那么你会发现某此POD不能正常启动,原因也很简单,那些能正常启动的POD,它们是通过"DaemonSet"的方式部署的,而不能正常启动的POD,是使用"Deployment"资源启动的~
1 2 |
*、如果KUBELET运行在APISERVER的节点上,可使用以下命令将其标记为"不可调度"状态 kubectl cordon k8s-master01 |
关于"KUBE-APISERVER"组件部署至此结束~~
二、KUBE-PROXY组件
以下操作均在[192.168.100.41]进行,然后按需要推送至[192.168.100.42 - 43];开始:生成"KUBE-PROXY"相关证书:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# 生成证书请求"kube-proxy-csr.json" $ cd /opt/cluster/ssl $ cat > kubernetes/kube-proxy-csr.json << "EOF" { "CN": "system:kube-proxy", # 这里的"CN"值非常重要,CONTROLLER-MANAGER是否能正常与APISERVER通讯与此值有关 "key": { "algo": "ecdsa", "size": 256 }, "names": [ { "C": "CN", "ST": "GuangDong", "L": "GuangZhou", "O": "KUBERNETES", # 这里的定义的"O"值相对KUBE-PROXY来说没什么特殊意义 "OU": "LEMONSYS" } ] } EOF # 生成服务器密钥对 -- "kube-proxy-key.pem" 和"kube-proxy.pem" $ cd /opt/cluster/ssl $ cfssl gencert -ca=rootca/rootca.pem -ca-key=rootca/rootca-key.pem --config=cfssl-conf.json -profile=common kubernetes/kube-proxy-csr.json | cfssljson -bare kubernetes/kube-proxy |
生成"KUBE-PROXY"组件的"kube-proxy.kubeconfig"配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$ cd /opt/cluster/ssl $ kubectl config set-cluster kubernetes --certificate-authority=/opt/cluster/ssl/rootca/rootca.pem \ --embed-certs=true --server=https://192.168.100.40:6443 \ --kubeconfig=kubernetes/kube-proxy.kubeconfig $ kubectl config set-credentials kube-proxy --client-certificate=/opt/cluster/ssl/kubernetes/kube-proxy.pem \ --client-key=/opt/cluster/ssl/kubernetes/kube-proxy-key.pem --embed-certs=true \ --kubeconfig=kubernetes/kube-proxy.kubeconfig $ kubectl config set-context default --cluster=kubernetes --user=kube-proxy \ --kubeconfig=kubernetes/kube-proxy.kubeconfig $ kubectl config use-context default --kubeconfig=kubernetes/kube-proxy.kubeconfig |
生成"kube-proxy.conf"配置文件[实际是指K8S的"KubeletConfiguration"资源][这实际是一份YAML文件];关于这份配置文件的解释及其通用性,见前面"kubelet.conf"的相关解释;注:此文件K8S集群中通用;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# 可以使用以下命令获取一份"KubeletConfiguration"资源的基础配置[需要删除有关KUBEADM的部分] # "kubeadm config print init-defaults --component-configs KubeProxyConfiguration > kube-proxy.conf" # 相关配置说明文档[https://kubernetes.io/docs/reference/config-api/] cat > kubernetes/kube-proxy.conf << "EOF" kind: KubeProxyConfiguration apiVersion: kubeproxy.config.k8s.io/v1alpha1 clientConnection: kubeconfig: /opt/cluster/ssl/kubernetes/kube-proxy.kubeconfig bindAddress: 0.0.0.0 # KUBE-PROXY的监听地址[官方默认"0.0.0.0"] clusterCIDR: "10.97.0.0/16" # CNI网络插件所使用的CIDR范围[官方:PodIP的CIDR范围]; # 与"kube-controller-manager"的"--cluster-cidr="配置有关 healthzBindAddress: "0.0.0.0:10256" # KUBE-PROXY健康检查的地址[官方默认"0.0.0.0:10256"] metricsBindAddress: "0.0.0.0:10249" # KUBE-PROXY获取METRICS指标的地址[官方默认"127.0.0.1:10249"] mode: ipvs # 所使用流量转发模式 ipvs: # IPVS的配置 scheduler: "rr" # IPVS所使用的算法 EOF |
将证书与配置文件分发至其它服务器[分发至:192.168.100.42 - 43];
1 2 |
scp -r /opt/cluster/ssl 192.168.100.42:/opt/cluster/ scp -r /opt/cluster/ssl 192.168.100.43:/opt/cluster/ |
为"KUBE-PROXY"生成"kube-proxy.service"启动文件;此文件通用![192.168.100.41 - 43]:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
cat > /usr/lib/systemd/system/kube-proxy.service << "EOF" [Unit] Description=Kubernetes:Kube-Proxy After=network.target network-online.target Wants=network-online.target [Service] Restart=on-failure RestartSec=5 ExecStart=/usr/local/bin/kube-proxy \ --config=/opt/cluster/ssl/kubernetes/kube-proxy.conf \ # KUBE-PROXY的配置文件[监听地址在此处配置了] --logtostderr=false \ # 日志配置 --v=2 \ --log-dir=/opt/cluster/log/kube-proxy \ --hostname-override=k8s-master01 # 定义节点名称[不建议,默认会使用"hostname"所得值作为节点名称] [Install] WantedBy=multi-user.target EOF |
启动"KUBE-PROXY"组件[192.168.100.41 - 43];你应该可以看到"KUBE-PROXY"组件的正常启动:
1 |
systemctl daemon-reload && systemctl enable --now kube-proxy.service && systemctl status kube-proxy.service |
关于"KUBE-PROXY"组件部署至此结束~~
结、
在完成"KUBELET"组件与"KUBE-PROXY"组件的部署,即代表一个工作节点[NODE]就已经部署完成了,但此时这些节点是处于"NoReady"状态的,这是由我们还没有安装"CNI"插件[网络运行时]。下一节的内容是"CALICO"插件["CNI"]与"COREDNS"组件["DNS"]的部署。本篇完,读者可点击以下链接进入下一章或返回上一章;
下一章:K8S二进制部署高可用集群-1.22 [七] CALICO插件与CoreDNS插件
上一章:K8S二进制部署高可用集群-1.22 [五] KUBE-CONTROLLER-MANAGER组件与KUBE-SCHEDULER组件
K8S二进制部署高可用集群-1.22[六]:等您坐沙发呢!