Kubernetes二进制搭建

news2024/11/23 11:46:47

目录

一、K8S的架构

二、K8S创建Pod资源的工作流程

三、K8S资源对象和资源配置信息

K8S资源对象

K8S资源配置信息

四、K8S的的三种网络和三种接口

三种网络:

三种节点:

五、etcd 集群

etcd 的特点:

六、flannel

flannel方案

K8S 中 Pod 网络通信:

flannel的模式及工作原理

flannel的UDP模式工作原理

flannel的VXLAN模式工作原理

七、calico

calico方案

Calico 主要由三个部分组成

Calico 工作原理

IPIP模式和BGP模式工作原理

calico的IPIP模式工作原理

calico的BGP模式工作原理

八、flannel 和 calico 的区别

九、二进制搭建过程

九、k8s二进制部署

单master 

操作系统初始化配置

部署 etcd 集群 

准备签发证书环境:

部署 docker引擎

部署 Master 组件

部署 Worker Node 组件

部署 CNI 网络组件

部署 Calico

部署 CoreDNS

多master高可用

负载均衡部署

附件

1.k8s-cert.sh脚本

2.apiserver.sh

3.scheduler.sh

4.controller-manager.sh

5.admin.sh

总结:

etcd数据库:

etcd安装步骤:

master组件安装步骤:

1.先安装apiserver

2.再启动controller-manager 和scheduler

3.检查集群组件状态

多master部署步骤:


一、K8S的架构

K8S有 master 和 worker node 两类节点
master节点(负责K8S集群的调度和管理等运维工作)有 apiserver、controller-manager、scheduler、etcd

  • apiserver:是所有服务请求的统一访问入口
  • controller-manager:控制器管理器,负责管理K8S各种资源对象的控制器;通过apiserver监控整个K8S集群资源的状态,并确保资源始终处于预期的工作状态
  • scheduler:资源调度器,负责Pod资源的调度,通过调度算法(预选策略、优选策略)为要部署的Pod选择最适合的node节点
  • etcd:K8S集群的数据库,是一种键值对存储结构的分布式数据库,负责存储K8S集群所有的重要信息,只有apiserver有访问和读写权限

worker node节点(负责运行工作负载,即容器应用)有 kubelet、kuber-proxy、容器引擎/容器运行时(docker、containerd等)

  • kubelet:接收apiserver发来的请求,创建和管理Pod和容器,跟容器引擎交互实现对容器的生命周期的管理;收集node节点的资源信息和Pod的运行状态发送给apiserver
  • kuber-proxy:作为service资源的载体,实现对Pod的网络代理,负责维护Pod集群网络规则和四层负载均衡工作
  • 容器引擎/容器运行时:运行容器
     

二、K8S创建Pod资源的工作流程

1)用户通过客户端发送创建Pod的请求给apiserver
2)apiserver接收到请求后,会先把请求信息写入到etcd中保存,再找controller-manager根据请求信息中的资源预设模板创建Pod资源
3)controller-manager会通过apiserver找到scheduler来调度新创建的Pod资源
4)scheduler通过调度算法的预选策略和优选策略筛选出最适合的node节点进行调度
5)再通过apiserver找到对应的node节点上的kubelet去创建和管理Pod
6)kubelet会跟容器引擎交互来管理Pod及容器的生命周期
7)用户还可以通过apiserver在kube-proxy上写入iptables/ipvs网络规则,创建service资源,实现对Pod集群的网络代理

三、K8S资源对象和资源配置信息

K8S资源对象

Pod:是K8S能够创建和管理的最小单位。一个Pod里可以包含一个或者多个应用容器,Pod里的容器之间共享网络、存储等资源
Pod控制器:

  • deployment:部署无状态应用(没有实时的数据需要存储);同时也负责管理replicaset(维持Pod副本数量符合预期数量)和Pod(容器化的应用进程)
  • statefulset:部署有状态应用(有实时的数据需要存储)
  • daemonset:在所有的node节点上部署同一类型的Pod
  • job:一次性的部署短期任务的Pod(执行完任务后会自动退出的Pod)
  • cronjob:周期性的部署短期任务的Pod(执行完任务后会自动退出的Pod)

service:在K8S集群内部,为通过标签选择器相关联的一组Pod提供一个统一的访问入口(clusterIP),只支持四层代理转发
ingress:作为K8S集群外部接入层,可自定义ingress规则根据用户请求的域名或URL请求路径转发给指定的service,支持七层代理转发

K8S资源配置信息

apiversion:资源对象在K8S中使用的api接口版本
kind:资源对象的类型
metadata:资源对象的元数据信息,比如 name资源名称、annotation注释、namespace命名空间、label标签
spec:资源对象的资源配置清单(配置属性),比如 副本数、镜像、数据卷、标签选择器
status:资源对象的当前运行状态信息

label:标签,将一个键值对关联到某个资源对象,用于资源对象的分组查询和筛选
label selector:标签选择器,用于查询和筛选拥有某个标签的资源对象
annotation:注释,用于作资源对象的注释信息或在一些特殊的资源对象里用于作额外的功能特性配置
name:资源名称
namespace:命名空间,在同一个命名空间中,同类型的资源对象的名称是唯一的

四、K8S的的三种网络和三种接口

三种网络:

节点网络:nodeIP

Pod网络:podIP

Service网络: clusterIP

三种节点:

CRI容器运行时接口dockercontainerd podman cir-0
CNI容器网终接口flannel calico cilium
CSI容器存储接口ceph nfs gfs  oss  s3

五、etcd 集群

etcd是CoreOS团队于2013年6月发起的开源项目,它的目标是构建一个高可用的分布式键值(key-value)数据库。etcd内部采用raft协议作为一致性算法,etcd是go语言编写的。

etcd 的特点:

  • 简单:安装配置简单,而且提供了HTTP API进行交互,使用也很简单
  • 安全:支持SSL证书验证
  • 快速:单实例支持每秒2k+读操作
  • 可靠:采用raft算法,实现分布式系统数据的可用性和一致性

etcd 目前默认使用2379端口提供HTTP API服务, 2380端口和peer通信(这两个端口已经被IANA(互联网数字分配机构)官方预留给etcd)。 即etcd默认使用2379端口对外为客户端提供通讯,使用端口2380来进行服务器间内部通讯。
etcd 在生产环境中一般推荐集群方式部署。由于etcd 的leader选举机制,要求至少为3台或以上的奇数台。
 

六、flannel

flannel方案

需要在每个节点上把发向容器的数据包进行封装后,再用隧道将封装后的数据包发送到运行着目标Pod的node节点上。目标node节点再负责去掉封装,将去除封装的数据包发送到目标Pod上。数据通信性能则大受影响。

K8S 中 Pod 网络通信:

  • Flannel 的功能是让集群中的不同节点主机创建的 Docker 容器都具有全集群唯一的虚拟 IP 地址。
  • Flannel 是 Overlay 网络的一种,也是将 TCP 源数据包封装在另一种网络包里面进行路由转发和通信,目前支持 udp、vxlan、 host-GW 3种数据转发方式。
     

Pod 内容器与容器之间的通信
在同一个 Pod 内的容器(Pod 内的容器是不会跨宿主机的)共享同一个网络命令空间,相当于它们在同一台机器上一样,可以用 localhost 地址访问彼此的端口。

同一个 Node 内 Pod 之间的通信
每个 Pod 都有一个真实的全局 IP 地址,同一个 Node 内的不同 Pod 之间可以直接采用对方 Pod 的 IP 地址进行通信,Pod1 与 Pod2 都是通过 Veth 连接到同一个 docker0 网桥,网段相同,所以它们之间可以直接通信。

不同 Node 上 Pod 之间的通信
Pod 地址与 docker0 在同一网段,docker0 网段与宿主机网卡是两个不同的网段,且不同 Node 之间的通信只能通过宿主机的物理网卡进行。
要想实现不同 Node 上 Pod 之间的通信,就必须想办法通过主机的物理网卡 IP 地址进行寻址和通信。因此要满足两个条件:Pod 的 IP 不能冲突;将 Pod 的 IP 和所在的 Node 的 IP 关联起来,通过这个关联让不同 Node 上 Pod 之间直接通过内网 IP 地址通信。
 

flannel的模式及工作原理

UDP:出现最早的模式,但是性能较差,基干flanneld应用程序实现数据包的封装/解封装

VXLAN:默认模式,是推荐使用的模式,性能比UDP模式更好,基于内核实现数据帧的封装/解封装,配置简单使用

HOST-GW:性能最好的模式,但是配置复杂,且不能跨网段

flannel的UDP模式工作原理

1)原始数据包从源主机的Pod容器发出到cni0网桥接口,再由cni0转发到flannel0虚拟接口
2)flanneld服务进程会监听flannel0接口收到的数据,flanneld进程会将原始数据包封装到UDP报文里
3)flanneld进程会根据在etcd中维护的路由表查到目标Pod所在的nodeIP,并在UDP报文外再封装nodeIP报文、MAC报文,再通过物理网卡发送到目标node节点
4)UDP报文通过8285号端口送到目标node节点的flanneld进程进行解封装,再通过flannel0接口转发到cni0网桥,再由cni0转发到目标Pod容器

flannel的VXLAN模式工作原理

1)原始数据帧从源主机的Pod容器发出到cni0网桥接口,再由cni0转发到flannel.1虚拟接口
2)flannel.1接口收到数据帧后添加VXLAN头部,并在内核将原始数据帧封装到UDP报文里
3)flanneld进程根据在etcd维护的路由表将UDP报文通过物理网卡发送到目标node节点
4)UDP报文通过8472号端口送到目标node节点的flannel.1接口在内核进行解封装,再通过flannel.1接口转发到cni0网桥,再由cni0转发到目标Pod容器

七、calico

calico方案

Calico不使用隧道或NAT来实现转发,而是把Host当作Internet中的路由器,使用BGP同步路由,并使用iptables来做安全访问策略,完成跨Host转发来。

Calico 主要由三个部分组成

  • Calico CNI插件:主要负责与kubernetes对接,供kubelet调用使用。
  • Felix:负责维护宿主机上的路由规则、FIB转发信息库等。
  • BIRD:负责分发路由规则,类似路由器。
  • Confd:配置管理组件。

Calico 工作原理

  • Calico 是通过路由表来维护每个 pod 的通信。Calico 的 CNI 插件会为每个容器设置一个 veth pair 设备, 然后把另一端接入到宿主机网络空间,由于没有网桥,CNI 插件还需要在宿主机上为每个容器的 veth pair 设备配置一条路由规则,用于接收传入的IP包。
  • 有了这样的 veth pair 设备以后,容器发出的IP包就会通过 veth pair 设备到达宿主机,然后宿主机根据路由规则的下一跳地址, 发送给正确的网关,然后到达目标宿主机,再到达目标容器。
  • 这些路由规则都是 Felix 维护配置的,而路由信息则是 Calico BIRD 组件基于 BGP 分发而来。calico 实际上是将集群里所有的节点都当做边界路由器来处理,他们一起组成了一个全互联的网络,彼此之间通过 BGP 交换路由,这些节点我们叫做 BGP Peer。

IPIP模式和BGP模式工作原理

calico的IPIP模式工作原理

1)原始数据包从源主机的Pod容器发出到tunl0接口,并被内核的IPIP驱动封装到节点网络的IP报文里
2)再根据tunl0接口的路由经过物理网卡发送到目标node节点
3)IP数据包到达目标node节点后再通过内核的IPIP驱动解包得到原始IP数据包
4)然后根据本地的路由规则经过 veth pair 设备送达到目标Pod容器

        

calico的BGP模式工作原理

(本质就是通过路由规则来维护Pod之间的通信,Felix负责维护路由规则和网络接口管理,BIRD负责分发路由信息给其它节点)

1)源主机的Pod容器发出的原始IP数据包会通过 veth pair 设备送达到节点网络空间
2)然后会根据原始IP数据包的目标IP和节点的路由规则找到目标node节点的IP,再经过物理网卡发送到目标node节点
3)IP数据包到达目标node节点后会根据本地的路由规则经过 veth pair 设备送达到目标Pod容器

八、flannel 和 calico 的区别

flannel: UDP  VXLAN  HOST-GW
默认网段:10.244.0.0/16
通常采用VXLAN模式,用的是叠加网络、IP隧道方式传输数据,对性能有一定的影响
功能简单配置方便利于管理。但是不具备复杂的网络策略规则配置能力

calico:  IPIP  BGP  混合模式(CrossSubnet)
默认网段:192.168.0.0/16
使用IPIP模式可以实现跨子网传输,但是传输过程中需要额外的封包和解包过程,对性能有一定的影响
使用BGP模式会把每个node节点看做成路由器,通过Felix、BIRD组件来维护和分发路由规则,可实现直接通过BGP协议路由转发,传输过程中不需要额外的封包和解包,因此性能较好,但是只能同一个网段里使用,无法跨子网传输
它不使用cni0网桥,而是通过路由规则把数据包直接发送到目标网卡,所以性能高;而且还具有更丰富的网络策略配置管理能力,功能更全面,但是维护起来较为复杂

所以对于较小规模且网络要求简单的K8S集群,可以采用flannel做cni网络插件。对于集群规模较大且要求更多的网络策略配置时,可以采用性能更好功能更全的calico

九、二进制搭建过程

1)部署etcd
使用cfssl工具签发证书和私钥
解压etcd软件包,获取二进制文件 etcd etcdctl
准备etcd集群配置文件
启动etcd服务进程,加入到etcd集群

#查看etcd集群健康状态
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --endpoints="https://etcd01IP:2379,https://etcd02IP:2379,https://etcd03IP:2379" --cacert=CA证书 --cert=客户端证书 --key=客户端私钥  endpoint health -wtable
#查看etcd集群状态信息
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --endpoints="https://etcd01IP:2379,https://etcd02IP:2379,https://etcd03IP:2379" --cacert=CA证书 --cert=客户端证书 --key=客户端私钥  endpoint status -wtable
#查看etcd集群成员列表
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --endpoints="https://etcd01IP:2379" --cacert=CA证书 --cert=客户端证书 --key=客户端私钥  member list -wtable  
#备份etcd数据库
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --endpoints="https://etcd01IP:2379" --cacert=CA证书 --cert=客户端证书 --key=客户端私钥 snapshot save 备份文件路径
#恢复etcd数据库
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --endpoints="https://etcd01IP:2379" --cacert=CA证书 --cert=客户端证书 --key=客户端私钥 snapshot restore 文件路径
#查看备份文件的状态信息
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --endpoints="https://etcd01IP:2379" --cacert=CA证书 --cert=客户端证书 --key=客户端私钥 snapshot status 文件路径

2)部署master组件
使用cfssl工具签发证书和私钥
解压K8S服务端软件包,获取二进制文件 kube-apiserver  kube-controller-manager  kube-scheduler  kubectl
准备 kube-apiserver 启动时要调用的 bootstrap-token 认证文件(token.csv)
准备 kube-apiserver  kube-controller-manager  kube-scheduler 的服务进程启动参数配置文件
准备 kube-controller-manager  kube-scheduler  kubectl 的 kubeconfig 集群引导配置文件(加入K8S集群的引导文件)
依次启动 kube-apiserver  kube-controller-manager  kube-scheduler 的服务进程
执行 kubectl get cs 命令查看master组件的健康状态

3)部署node组件
获取二进制文件 kubelet  kube-proxy
准备 kubelet  kube-proxy 的 kubeconfig 集群引导配置文件 kube-proxy.kubeconfig  bootstrap.kubeconfig(kubelet首次访问apiserver加入K8S集群使用引导文件)
准备 kubelet  kube-proxy 的服务进程启动参数配置文件
启动 kubelet 服务进程,向 apiserver 发起 CSR 请求颁发证书,master 通过 CSR 请求后 kubelet 方可获取到证书
加载 ipvs 模块,启动 kube-proxy 服务进程
安装 cni 网络插件(flannel/calico)和 CoreDNS
执行 kubectl get nodes 命令查看node的状态
 

九、k8s二进制部署

k8s集群master01:192.168.30.100,kube-apiserver、kube-controller-manager、kube-scheduler、etcd
k8s集群master02:192.168.30.105
k8s集群master03: 192.168.30.203

etcd集群节点1:192.168.30.100	etcd
etcd集群节点2:192.168.30.200
etcd集群节点3:192.168.30.104
 ​
k8s集群node01:192.168.30.200   kubelet、kube-proxy、docker 
k8s集群node02:192.168.30.104
 ​ ​
负载均衡nginx+keepalive01(master):192.168.30.14
负载均衡nginx+keepalive02(backup):192.168.30.15

单master 

操作系统初始化配置

关闭防火墙  关闭selinux  关闭swap (所有节点)

#关闭防火墙 全部
systemctl stop firewalld
systemctl disable firewalld
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X

#关闭selinux 全部 
setenforce 0
vim /etc/selinux/config  disable
或sed -i 's/enforcing/disabled/' /etc/selinux/config

#关闭swap 全部
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab 

master01(192.168.30.100)

node01(192.168.30.200)

node02(192.168.30.104)

所有节点添加hosts

cat >> /etc/hosts << EOF
192.168.80.10 master01
192.168.80.11 node01
192.168.80.12 node02
EOF

调整内核参数(所有节点)

cat > /etc/sysctl.d/k8s.conf << EOF
#开启网桥模式,可将网桥的流量传递给iptables链
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
#关闭ipv6协议
net.ipv6.conf.all.disable_ipv6=1
net.ipv4.ip_forward=1
EOF

sysctl --system

时间同步(所有节点)

yum install ntpdate -y
ntpdate time.windows.com或ntpdate ntp.aliyun.com

部署 etcd 集群 

准备签发证书环境:

CFSSL是CloudFlare公司开源的一款PKI/TLS 工具。CFSSL包含一个命令行工具和一个用于签名、验证和捆绑TLS证书的HTTP API服务。使用Go语言编写。

CFSSL使用配置文件生成证书,因此自签之前,需要生成它识别的json 格式的配置文件,CFSSL 提供了方便的命令行生成配置文件。

CFSSL用来为etcd提供TLS证书,它支持签三种类型的证书:

  1. client证书,服务端连接客户端时携带的证书,用于客户端验证服务端身份,如kubeapiserver 访问etcd;
  2. server证书,客户端连接服务端时携带的证书,用于服务端验证客户端身份,如etcd对外提供服务;
  3. peer证书,相互之间连接时使用的证书,如etcd节点之间进行验证和通信。

这里全部都使用同一套证书认证。

在 master01 节点上操作

生成Etcd证书

#准备cfssl证书生成工具

上传 cfssl 、cfssljson、cfssl-certinfo到/usr/local/bin/cfssl 或

wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -O /usr/local/bin/cfssl
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -O /usr/local/bin/cfssljson
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -O /usr/local/bin/cfssl-certinfo

mkdir /opt/k8s
cd /opt/k8s/

#上传 etcd-cert.sh 、etcd-v3.4.9-linux-amd64.tar.gz和 etcd.sh 到 /opt/k8s/ 目录中
chmod +x etcd-cert.sh etcd.sh

创建用于生成CA证书、etcd 服务器证书以及私钥的目录
mkdir /opt/k8s/etcd-cert
mv etcd-cert.sh etcd-cert/
cd /opt/k8s/etcd-cert/

vim etcd-cert.sh
./etcd-cert.sh            #生成CA证书、etcd 服务器证书以及私钥

ls
ca-config.json  ca-csr.json  ca.pem        server.csr       server-key.pem
ca.csr          ca-key.pem   etcd-cert.sh  server-csr.json  server.pem

cd /opt/k8s/
tar zxvf etcd-v3.4.9-linux-amd64.tar.gz
ls etcd-v3.4.9-linux-amd64
Documentation  etcd  etcdctl  README-etcdctl.md  README.md  READMEv2-etcdctl.md

创建用于存放 etcd 配置文件,命令文件,证书的目录(master01)

mkdir -p /opt/etcd/{cfg,bin,ssl}

cd /opt/k8s/etcd-v3.4.9-linux-amd64/
mv etcd etcdctl /opt/etcd/bin/
cp /opt/k8s/etcd-cert/*.pem /opt/etcd/ssl/

cd /opt/k8s/
./etcd.sh etcd01 192.168.30.100 etcd02=https://192.168.30.200:2380,etc03=https

://192.168.30.104:2380
#进入卡住状态等待其他节点加入,这里需要三台etcd服务同时启动,如果只启动其中一台后,服务会卡在那里,直到集群中所有etcd节点都已启动,可忽略这个情况
#可另外打开一个窗口查看etcd进程是否正常
ps -ef | grep etcd

把etcd相关证书文件、命令文件和服务管理文件全部拷贝到另外两个etcd集群节点(master01)

scp -r /opt/etcd/ root@192.168.30.200:/opt/
scp -r /opt/etcd/ root@192.168.30.104:/opt/
scp /usr/lib/systemd/system/etcd.service root@192.168.30.200:/usr/lib/systemd/syste

m
scp /usr/lib/systemd/system/etcd.service root@192.168.30.104:/usr/lib/systemd/syste

m

在 node01 和node02节点上操作

在 node01 节点上操作

vim /opt/etcd/cfg/etcd
#[Member]
ETCD_NAME="etcd02"                                            #修改
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.30.200:2380"            #修改
ETCD_LISTEN_CLIENT_URLS="https://192.168.30.200:2379"        #修改

#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.30.200:2380"        #修改
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.30.200:2379"                #修改
ETCD_INITIAL_CLUSTER="etcd01=https://192.168.30.100:2380,etcd02=https://192.168.30.200:2380,etcd03=https://192.168.30.104:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"

#启动etcd服务
systemctl start etcd
systemctl enable etcd
systemctl status etcd

在 node02 节点上操作
vim /opt/etcd/cfg/etcd
#[Member]
ETCD_NAME="etcd03"                                            #修改
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.80.104:2380"            #修改
ETCD_LISTEN_CLIENT_URLS="https://192.168.80.104:2379"        #修改

#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.80.12:2380"        #修改
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.30.104:2379"                #修改
ETCD_INITIAL_CLUSTER="etcd01=https://192.168.30.100:2380,etcd02=https://192.168.30.200:2380,etcd03=https://192.168.30.104:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"

#启动etcd服务
systemctl start etcd
systemctl enable etcd
systemctl status etcd

#检查etcd群集状态
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.30.100:2379,https://192.168.30.200:2379,https://192.168.30.104:2379" endpoint health --write-out=table

------------------------------------------------------------------------------------------

#查看etcd集群成员列表
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.30.100:2379,https://192.168.30.200:2379,https://192.168.30.104:2379" --write-out=table member list
 

node01

node02

master01

部署 docker引擎

所有 node 节点部署docker引擎

yum install -y yum-utils device-mapper-persistent-data lvm2 
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 
yum install -y docker-ce docker-ce-cli containerd.io

node01和node02

vim /etc/docker/daemon.json

{

  "registry-mirrors": ["https://6na95ym4.mirror.aliyuncs.com"],

  "exec-opts": ["native.cgroupdriver=systemd"],

  "log-driver": "json-file",

  "log-opts": {

    "max-size": "500m", "max-file": "3"

  }

}

systemctl start docker.service
systemctl enable docker.service 

部署 Master 组件

master01 节点上操作

#上传 master.zip 和 k8s-cert.sh 到 /opt/k8s 目录中,解压 master.zip 压缩包
cd /opt/k8s/
unzip master.zip
chmod +x *.sh

#创建kubernetes工作目录
mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}

#创建用于生成CA证书、相关组件的证书和私钥的目录
mkdir /opt/k8s/k8s-cert
mv /opt/k8s/k8s-cert.sh /opt/k8s/k8s-cert
cd /opt/k8s/k8s-cert/

vim k8s-cert.sh
./k8s-cert.sh                #生成CA证书、相关组件的证书和私钥

ls *pem
admin-key.pem  apiserver-key.pem  ca-key.pem  kube-proxy-key.pem  
admin.pem      apiserver.pem      ca.pem      kube-proxy.pem

 

注:节点一开始做错了后转到master01上

master01

复制CA证书、apiserver相关证书和私钥到 kubernetes工作目录的 ssl 子目录中
cp *.pem /opt/kubernetes/ssl/

#上传 kubernetes-server-linux-amd64.tar.gz 到 /opt/k8s/ 目录中,解压 kubernetes 压缩包
cd /opt/k8s/
tar zxvf kubernetes-server-linux-amd64.tar.gz

#复制master组件的关键命令文件到 kubernetes工作目录的 bin 子目录中
cd /opt/k8s/kubernetes/server/bin
cp kube-apiserver kubectl kube-controller-manager kube-scheduler /opt/kubernetes/bin/
ln -s /opt/kubernetes/bin/* /usr/local/bin/

#创建 bootstrap token 认证文件,apiserver 启动时会调用,然后就相当于在集群内创建了一个这个用户,接下来就可以用 RBAC 给他授权
cd /opt/k8s/
vim token.sh
#!/bin/bash
#获取随机数前16个字节内容,以十六进制格式输出,并删除其中空格
BOOTSTRAP_TOKEN=$(head -c 16 /dev/urandom | od -An -t x | tr -d ' ')
#生成 token.csv 文件,按照 Token序列号,用户名,UID,用户组 的格式生成
cat > /opt/kubernetes/cfg/token.csv <<EOF
${BOOTSTRAP_TOKEN},kubelet-bootstrap,10001,"system:kubelet-bootstrap"
EOF

chmod +x token.sh
./token.sh

cat /opt/kubernetes/cfg/token.csv

#二进制文件、token、证书都准备好后,开启 apiserver 服务
cd /opt/k8s/
./apiserver.sh 192.168.30.10 https://192.168.30.100:2379,https://192.168.30.200:2379,https://192.168.30.104:2379

#检查进程是否启动成功
ps aux | grep kube-apiserver

netstat -natp | grep 6443   #安全端口6443用于接收HTTPS请求,用于基于Token文件或客户端证书等认证
 

#二进制文件、token、证书都准备好后,开启 apiserver 服务
cd /opt/k8s/
./apiserver.sh 192.168.30.100 https://192.168.30.100:2379,https://192.168.30.200:2379,https://192.168.30.104:2379

#检查进程是否启动成功
ps aux | grep kube-apiserver

netstat -natp | grep 6443   #安全端口6443用于接收HTTPS请求,用于基于Token文件或客户端证书等认证


#启动 scheduler 服务
cd /opt/k8s/
./scheduler.sh
ps aux | grep kube-scheduler

#启动 controller-manager 服务
./controller-manager.sh
ps aux | grep kube-controller-manager

#生成kubectl连接集群的kubeconfig文件
./admin.sh

#绑定默认cluster-admin管理员集群角色,授权kubectl访问集群
kubectl create clusterrolebinding cluster-system-anonymous --clusterrole=cluster-admin --user=system:anonymous

#通过kubectl工具查看当前集群组件状态
kubectl get cs
NAME                 STATUS    MESSAGE             ERROR
controller-manager   Healthy   ok                  
scheduler            Healthy   ok                  
etcd-2               Healthy   {"health":"true"}   
etcd-1               Healthy   {"health":"true"}   
etcd-0               Healthy   {"health":"true"}  

#查看版本信息
kubectl version

部署 Worker Node 组件

在所有 node 节点上操作

#创建kubernetes工作目录
mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}

#上传 node.zip 到 /opt 目录中,解压 node.zip 压缩包,获得kubelet.sh、proxy.sh
cd /opt/
unzip node.zip
chmod +x kubelet.sh proxy.sh

master01 节点上操作

#把 kubelet、kube-proxy 拷贝到 node 节点
cd /opt/k8s/kubernetes/server/bin
scp kubelet kube-proxy root@192.168.80.11:/opt/kubernetes/bin/
scp kubelet kube-proxy root@192.168.80.12:/opt/kubernetes/bin/

#上传kubeconfig.sh文件到/opt/k8s/kubeconfig目录中,生成kubelet初次加入集群引导kubeconfig文件和kube-proxy.kubeconfig文件
#kubeconfig 文件包含集群参数(CA 证书、API Server 地址),客户端参数(上面生成的证书和私钥),集群 context 上下文参数(集群名称、用户名)。Kubenetes 组件(如 kubelet、kube-proxy)通过启动时指定不同的 kubeconfig 文件可以切换到不同的集群,连接到 apiserver。
mkdir /opt/k8s/kubeconfig

cd /opt/k8s/kubeconfig
chmod +x kubeconfig.sh
./kubeconfig.sh 192.168.80.10 /opt/k8s/k8s-cert/

#把配置文件 bootstrap.kubeconfig、kube-proxy.kubeconfig 拷贝到 node 节点
scp bootstrap.kubeconfig kube-proxy.kubeconfig root@192.168.80.11:/opt/kubernetes/cfg/

scp bootstrap.kubeconfig kube-proxy.kubeconfig root@192.168.80.12:/opt/kubernetes/cfg/

#RBAC授权,使用户 kubelet-bootstrap 能够有权限发起 CSR 请求证书
kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap
 

在 所有node 节点上操作

#启动 kubelet 服务
cd /opt/
./kubelet.sh 192.168.80.11
ps aux | grep kubelet

在 master01 节点上操作

#检查到 node01 节点的 kubelet 发起的 CSR 请求,Pending 表示等待集群给该节点签发证书
kubectl get csr

通过 CSR 请求

kubectl certificate approve node-csr-name名

#查看节点,由于网络插件还没有部署,节点会没有准备就绪 NotReady
kubectl get node

node01节点和node02节点操作

#加载 ip_vs 模块
for i in $(ls /usr/lib/modules/$(uname -r)/kernel/net/netfilter/ipvs|grep -o "^[^.]*");do echo $i; /sbin/modinfo -F filename $i >/dev/null 2>&1 && /sbin/modprobe $i;done

#启动proxy服务
cd /opt/
./proxy.sh 192.168.30.200
ps aux | grep kube-proxy

 

部署 CNI 网络组件

node01和node02节点上操作

#上传 cni-plugins-linux-amd64-v0.8.6.tgz 和 flannel.tar 到 /opt 目录中
cd /opt/
docker load -i flannel.tar

mkdir /opt/cni/bin
tar zxvf cni-plugins-linux-amd64-v0.8.6.tgz -C /opt/cni/bin

将node01节点的 kube-flannel.yml 文件传给master01

node02

node01

 master01 节点上操作

cd /opt

kubectl get nodes   (若只有一个节点需执行以下步骤到对应节点)

cat > /etc/docker/daemon.json <<EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"]
}
EOF

systemctl restart  docker kubelet

#上传 kube-flannel.yml 文件到 /opt/k8s 目录中,部署 CNI 网络
cd /opt/k8s
kubectl apply -f kube-flannel.yml 

kubectl get pods -n kube-system或kubectl get pods -A

kubectl get nodes

master01节点

 node02节点  

更换dokcer资源限制

master01节点

部署 Calico

//在 master01 节点上操作
#上传 calico.yaml 文件到 /opt/k8s 目录中,部署 CNI 网络
cd /opt/k8s
vim calico.yaml
#修改里面定义Pod网络(CALICO_IPV4POOL_CIDR),与前面kube-controller-manager配置文件指定的cluster-cidr网段一样
    - name: CALICO_IPV4POOL_CIDR
      value: "192.168.0.0/16"
  
kubectl apply -f calico.yaml

kubectl get pods -n kube-system
NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-659bd7879c-4h8vk   1/1     Running   0          58s
calico-node-nsm6b                          1/1     Running   0          58s
calico-node-tdt8v                          1/1     Running   0          58s

#等 Calico Pod 都 Running,节点也会准备就绪
kubectl get nodes

部署 CoreDNS

在所有 node 节点上操作

//在所有 node 节点上操作
#上传 coredns.tar 到 /opt 目录中
cd /opt
docker load -i coredns.tar

docker pull busybox:1.28.4

/在 master01 节点上操作

#上传 coredns.yaml 文件到 /opt/k8s 目录中,部署 CoreDNS 
cd /opt/k8s
kubectl apply -f coredns.yaml

kubectl get pods -n kube-system 
NAME                          READY   STATUS    RESTARTS   AGE
coredns-5ffbfd976d-j6shb      1/1     Running   0          32s

#DNS 解析测试

kubectl run -it --rm dns-test --image=busybox:1.28.4 sh
If you don't see a command prompt, try pressing enter.
/ # nslookup kubernetes

多master高可用

操作系统初始化配置 master02和master03设置

#关闭防火墙 全部
systemctl stop firewalld
systemctl disable firewalld
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X

#关闭selinux 全部 
setenforce 0
vim /etc/selinux/config  disable
或sed -i 's/enforcing/disabled/' /etc/selinux/config

#关闭swap 全部
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab 

cat > /etc/sysctl.d/k8s.conf << EOF
#开启网桥模式,可将网桥的流量传递给iptables链
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
#关闭ipv6协议
net.ipv6.conf.all.disable_ipv6=1
net.ipv4.ip_forward=1
EOF

sysctl --system

yum install ntpdate -y
ntpdate time.windows.com或ntpdate ntp.aliyun.com

master02

master03

所有节点添加更改hosts

master01 节点上拷贝证书文件、各master组件的配置文件和服务管理文件到 master02 节点
scp -r /opt/etcd/ root@192.168.80.20:/opt/
scp -r /opt/kubernetes/ root@192.168.80.20:/opt
scp /usr/lib/systemd/system/{kube-apiserver,kube-controller-manager,kube-scheduler}.service root@192.168.80.20:/usr/lib/systemd/system/

 

修改配置文件kube-apiserver中的IP(master02 master03)

master02设置

vim /opt/kubernetes/cfg/kube-apiserver
KUBE_APISERVER_OPTS="--logtostderr=true \
--v=4 \
--etcd-servers=https://192.168.30.100:2379,https://192.168.30.200:2379,https://192.168.30.104:2379 \
--bind-address=192.168.30.105 \                #修改
--secure-port=6443 \
--advertise-address=192.168.30.105 \            #修改

master03设置

vim /opt/kubernetes/cfg/kube-apiserver
KUBE_APISERVER_OPTS="--logtostderr=true \
--v=4 \
--etcd-servers=https://192.168.30.100:2379,https://192.168.30.200:2379,https://192.168.30.104:2379 \
--bind-address=192.168.30.203 \                #修改
--secure-port=6443 \
--advertise-address=192.168.30.203 \            #修改

将master01  .kube 复制到 master02和master03上

scp -r .kube root@192.168.30.105:/opt

scp -r .kube root@192.168.30.203:/opt

master01节点

master02节点

将/opt中.kube移至家目录

mv .kube/ ~

master02节点

master02 和master03节点上启动各服务并设置开机自启

systemctl start kube-apiserver.service
systemctl enable kube-apiserver.service
systemctl start kube-controller-manager.service
systemctl enable kube-controller-manager.service
systemctl start kube-scheduler.service
systemctl enable kube-scheduler.service

查看node节点状态

master02和master03节点

ln -s /opt/kubernetes/bin/* /usr/local/bin/
kubectl get nodes
kubectl get nodes -o wide            #-o=wide:输出额外信息;对于Pod,将输出Pod所在的Node名

负载均衡部署

 在lb01、lb02节点上操作

配置load balancer集群双机热备负载均衡(nginx实现负载均衡,keepalived实现双机热备)

//配置nginx的官方在线yum源,配置本地nginx的yum源
cat > /etc/yum.repos.d/nginx.repo << 'EOF'
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
EOF

yum install nginx -y

//修改nginx配置文件,配置四层反向代理负载均衡,指定k8s群集2台master的节点ip和6443端口
vim /etc/nginx/nginx.conf
events {
    worker_connections  1024;
}

#添加
stream {

    upstream k8s-apiserver {
        server 192.168.30.100:6443;

        server 192.168.30.203:6443;

        server 192.168.30.105:6443;


    }
    server {
        listen 6443;
        proxy_pass k8s-apiserver;
    }
}

http {
......


//检查配置文件语法
nginx -t   

//启动nginx服务,查看已监听6443端口
systemctl start nginx
systemctl enable nginx
netstat -natp | grep nginx 

 在lb01、lb02节点上操作

//部署keepalived服务
yum install keepalived -y

//修改keepalived配置文件
vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {
   # 接收邮件地址
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   # 邮件发送地址
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id NGINX_MASTER    #lb01节点的为 NGINX_MASTER,lb02节点的为 NGINX_BACKUP
}

#添加一个周期性执行的脚本
vrrp_script check_nginx {
    script "/etc/nginx/check_nginx.sh"    #指定检查nginx存活的脚本路径
}

vrrp_instance VI_1 {
    state MASTER            #lb01节点的为 MASTER,lb02节点的为 BACKUP
    interface ens33            #指定网卡名称 ens33
    virtual_router_id 51    #指定vrid,两个节点要一致
    priority 100            #lb01节点的为 100,lb02节点的为 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.80.100/24    #指定 VIP
    }
    track_script {
        check_nginx            #指定vrrp_script配置的脚本
    }
}

 

 在lb01、lb02节点上操作

创建nginx状态检查脚本 
vim /etc/nginx/check_nginx.sh
#!/bin/bash
#egrep -cv "grep|$$" 用于过滤掉包含grep 或者 $$ 表示的当前Shell进程ID
count=$(ps -ef | grep nginx | egrep -cv "grep|$$")

if [ "$count" -eq 0 ];then
    systemctl stop keepalived
fi


chmod +x /etc/nginx/check_nginx.sh

//启动keepalived服务(一定要先启动了nginx服务,再启动keepalived服务)
systemctl start keepalived
systemctl enable keepalived
ip a                #查看VIP是否生成

lb02节点

lb01节点

node节点配置

//修改node节点上的bootstrap.kubeconfig,kubelet.kubeconfig配置文件为VIP
cd /opt/kubernetes/cfg/
vim bootstrap.kubeconfig 
server: https://192.168.80.100:6443
                      
vim kubelet.kubeconfig
server: https://192.168.80.100:6443
                        
vim kube-proxy.kubeconfig
server: https://192.168.80.100:6443

//重启kubelet和kube-proxy服务
systemctl restart kubelet.service 
systemctl restart kube-proxy.service

node01

node02

master02和master03上配置

lb01 上查看 nginx 和 node 、 master 节点的连接状态

netstat -natp | grep nginx

master01 节点上操作

//测试创建pod
kubectl run nginx --image=nginx

//查看Pod的状态信息
kubectl get pods

 

kubectl get pods
 

kubectl get pods -o wide

//READY为1/1,表示这个Pod中有1个容器

//在对应网段的node节点上操作,可以直接使用浏览器或者curl命令访问
curl 172.17.36.2

//这时在master01节点上查看nginx日志,发现没有权限查看
kubectl logs nginx-dbddb74b8-nf9sk

在对应网段的node节点上操作,可以直接使用浏览器或者curl命令访问(node02)

附件

1.k8s-cert.sh脚本

 #!/bin/bash
 #配置证书生成策略,让 CA 软件知道颁发有什么功能的证书,生成用来签发其他组件证书的根证书
 cat > ca-config.json <<EOF
 {
   "signing": {
     "default": {
       "expiry": "87600h"
     },
     "profiles": {
       "kubernetes": {
          "expiry": "87600h",
          "usages": [
             "signing",
             "key encipherment",
             "server auth",
             "client auth"
         ]
       }
     }
   }
 }
 EOF
 ​
 #生成CA证书和私钥(根证书和私钥)
 cat > ca-csr.json <<EOF
 {
     "CN": "kubernetes",
     "key": {
         "algo": "rsa",
         "size": 2048
     },
     "names": [
         {
             "C": "CN",
             "L": "Beijing",
             "ST": "Beijing",
             "O": "k8s",
             "OU": "System"
         }
     ]
 }
 EOF
 ​
 cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
 ​
 ​
 #-----------------------
 #生成 apiserver 的证书和私钥(apiserver和其它k8s组件通信使用)
 #hosts中将所有可能作为 apiserver 的 ip 添加进去,后面 keepalived 使用的VIP 也要加入
 cat > apiserver-csr.json <<EOF
 {
     "CN": "kubernetes",
     "hosts": [
       "10.0.0.1",
       "127.0.0.1",
       "192.168.30.100",    #master01。使用脚本时,要将这5行注释删除
       "192.168.30.105",    #master02
       "192.168.30.10",   #vip,后面keepalived要用到
       "192.168.30.14",    #负载均衡器01(master)
       "192.168.30.15",    #负载均衡器02(backup)
       "kubernetes",
       "kubernetes.default",
       "kubernetes.default.svc",
       "kubernetes.default.svc.cluster",
       "kubernetes.default.svc.cluster.local"
     ],
     "key": {
         "algo": "rsa",
         "size": 2048
     },
     "key": {
         "algo": "rsa",
         "size": 2048
     },
     "names": [
         {
             "C": "CN",
             "L": "BeiJing",
             "ST": "BeiJing",
             "O": "k8s",
             "OU": "System"
         }
     ]
 }
 EOF
 ​
 cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes apiserver-csr.json | cfssljson -bare apiserver
 ​
 ​
 #-----------------------
 #生成 kubectl 连接集群的证书和私钥,具有admin权限
 cat > admin-csr.json <<EOF
 {
   "CN": "admin",
   "hosts": [],
   "key": {
     "algo": "rsa",
     "size": 2048
   },
   "names": [
     {
       "C": "CN",
       "L": "BeiJing",
       "ST": "BeiJing",
       "O": "system:masters",
       "OU": "System"
     }
   ]
 }
 EOF
 ​
 cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin
 ​
 ​
 #-----------------------
 #生成 kube-proxy 的证书和私钥
 cat > kube-proxy-csr.json <<EOF
 {
   "CN": "system:kube-proxy",
   "hosts": [],
   "key": {
     "algo": "rsa",
     "size": 2048
   },
   "names": [
     {
       "C": "CN",
       "L": "BeiJing",
       "ST": "BeiJing",
       "O": "k8s",
       "OU": "System"
     }
   ]
 }
 EOF
 ​
 cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy

2.apiserver.sh

 #!/bin/bash
 #example: apiserver.sh 192.168.30.100 https://192.168.30.100:2379,https://192.168.30.200:2379,https://192.168.30.104:2379
 #创建 kube-apiserver 启动参数配置文件
 MASTER_ADDRESS=$1
 ETCD_SERVERS=$2
 ​
 cat >/opt/kubernetes/cfg/kube-apiserver <<EOF
 KUBE_APISERVER_OPTS="--logtostderr=false  \
 --v=2 \
 --log-dir=/opt/kubernetes/logs \
 --etcd-servers=${ETCD_SERVERS} \
 --bind-address=${MASTER_ADDRESS} \
 --secure-port=6443 \
 --advertise-address=${MASTER_ADDRESS} \
 --allow-privileged=true \
 --service-cluster-ip-range=10.0.0.0/24 \
 --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \
 --authorization-mode=RBAC,Node \
 --enable-bootstrap-token-auth=true \
 --token-auth-file=/opt/kubernetes/cfg/token.csv \
 --service-node-port-range=30000-50000 \
 --kubelet-client-certificate=/opt/kubernetes/ssl/apiserver.pem \
 --kubelet-client-key=/opt/kubernetes/ssl/apiserver-key.pem \
 --tls-cert-file=/opt/kubernetes/ssl/apiserver.pem  \
 --tls-private-key-file=/opt/kubernetes/ssl/apiserver-key.pem \
 --client-ca-file=/opt/kubernetes/ssl/ca.pem \
 --service-account-key-file=/opt/kubernetes/ssl/ca-key.pem \
 --service-account-issuer=api \
 --service-account-signing-key-file=/opt/kubernetes/ssl/apiserver-key.pem \
 --etcd-cafile=/opt/k8s/etcd-cert/ca.pem \
 --etcd-certfile=/opt/k8s/etcd-cert/server.pem \
 --etcd-keyfile=/opt/k8s/etcd-cert/server-key.pem \
 --requestheader-client-ca-file=/opt/kubernetes/ssl/ca.pem \
 --proxy-client-cert-file=/opt/kubernetes/ssl/apiserver.pem \
 --proxy-client-key-file=/opt/kubernetes/ssl/apiserver-key.pem \
 --requestheader-allowed-names=kubernetes \
 --requestheader-extra-headers-prefix=X-Remote-Extra- \
 --requestheader-group-headers=X-Remote-Group \
 --requestheader-username-headers=X-Remote-User \
 --enable-aggregator-routing=true \
 --audit-log-maxage=30 \
 --audit-log-maxbackup=3 \
 --audit-log-maxsize=100 \
 --audit-log-path=/opt/kubernetes/logs/k8s-audit.log"
 EOF
 ​
 #--logtostderr=true:启用日志。输出日志到标准错误控制台,不输出到文件
 #--v=4:日志等级。指定输出日志的级别,v=4为调试级别详细输出
 #--etcd-servers:etcd集群地址。指定etcd服务器列表(格式://ip:port),逗号分隔
 #--bind-address:监听地址。指定 HTTPS 安全接口的监听地址,默认值0.0.0.0
 #--secure-port:https安全端口。指定 HTTPS 安全接口的监听端口,默认值6443
 #--advertise-address:集群通告地址。通过该 ip 地址向集群其他节点公布 api server 的信息,必须能够被其他节点访问
 #--allow-privileged=true:启用授权。允许拥有系统特权的容器运行,默认值false
 #--service-cluster-ip-range:Service虚拟IP地址段。指定 Service Cluster IP 地址段
 #--enable-admission-plugins:准入控制模块。kuberneres集群的准入控制机制,各控制模块以>插件的形式依次生效,集群时必须包含ServiceAccount,运行在认证(Authentication)、授权(Authorization)之后,Admission Control是权限认证链上的最后一环, 对请求API资源对象进行修改和校验
 #--authorization-mode:认证授权,启用RBAC授权和节点自管理。在安全端口使用RBAC,Node授权模式,未通过授权的请求拒绝,默认值AlwaysAllow。RBAC是用户通过角色与权限进行关联的模式>;Node模式(节点授权)是一种特殊用途的授权模式,专门授权由kubelet发出的API请求,在进行认证时,先通过用户名、用户分组验证是否是集群中的Node节点,只有是Node节点的请求才能使用Node模式授权
 #--enable-bootstrap-token-auth:启用TLS bootstrap机制。在apiserver上启用Bootstrap Token 认证
 #--token-auth-file=/opt/kubernetes/cfg/token.csv:指定bootstrap token认证文件路径
 #--service-node-port-range:指定 Service  NodePort 的端口范围,默认值30000-32767
 #–-kubelet-client-xxx:apiserver访问kubelet客户端证书
 #--tls-xxx-file:apiserver https证书
 #1.20版本必须加的参数:–-service-account-issuer,–-service-account-signing-key-file
 #--etcd-xxxfile:连接Etcd集群证书
 #–-audit-log-xxx:审计日志
 #启动聚合层相关配置:–requestheader-client-ca-file,–proxy-client-cert-file,–proxy-client-key-file,–requestheader-allowed-names,–requestheader-extra-headers-prefix,–requestheader-group-headers,–requestheader-username-headers,–enable-aggregator-routing
 ​
 #创建 kube-apiserver.service 服务管理文件
 cat >/usr/lib/systemd/system/kube-apiserver.service <<EOF
 [Unit]
 Description=Kubernetes API Server
 Documentation=https://github.com/kubernetes/kubernetes
 ​
 [Service]
 EnvironmentFile=-/opt/kubernetes/cfg/kube-apiserver
 ExecStart=/opt/kubernetes/bin/kube-apiserver $KUBE_APISERVER_OPTS
 Restart=on-failure
 ​
 [Install]
 WantedBy=multi-user.target
 EOF
 ​
 systemctl daemon-reload
 systemctl enable kube-apiserver
 systemctl restart kube-apiserver

3.scheduler.sh

 #!/bin/bash
 ##创建 kube-scheduler 启动参数配置文件
 MASTER_ADDRESS=$1
 ​
 cat >/opt/kubernetes/cfg/kube-scheduler <<EOF
 KUBE_SCHEDULER_OPTS="--logtostderr=false \
 --v=2 \
 --log-dir=/opt/kubernetes/logs \
 --leader-elect=true \
 --kubeconfig=/opt/kubernetes/cfg/kube-scheduler.kubeconfig \
 --bind-address=127.0.0.1"
 EOF
 ​
 #-–kubeconfig:连接 apiserver 用的配置文件,用于识别 k8s 集群
 #--leader-elect=true:当该组件启动多个时,自动启动 leader 选举
 #k8s中Controller-Manager和Scheduler的选主逻辑:k8s中的etcd是整个集群所有状态信>息的存储,涉及数据的读写和多个etcd之间数据的同步,对数据的一致性要求严格,所以>使用较复杂的 raft 算法来选择用于提交数据的主节点。而 apiserver 作为集群入口,本身是无状态的web服务器,多个 apiserver 服务之间直接负载请求并不需要做选主。Controller-Manager 和 Scheduler 作为任务类型的组件,比如 controller-manager 内置的 k8s 各种资源对象的控制器实时的 watch apiserver 获取对象最新的变化事件做期望状态>和实际状态调整,调度器watch未绑定节点的pod做节点选择,显然多个这些任务同时工作>是完全没有必要的,所以 controller-manager 和 scheduler 也是需要选主的,但是选主逻辑和 etcd 不一样的,这里只需要保证从多个 controller-manager 和 scheduler 之间选出一个 leader 进入工作状态即可,而无需考虑它们之间的数据一致和同步。
 ​
 ​
 ##生成kube-scheduler证书
 cd /opt/k8s/k8s-cert/
 #创建证书请求文件
 cat > kube-scheduler-csr.json << EOF
 {
   "CN": "system:kube-scheduler",
   "hosts": [],
   "key": {
     "algo": "rsa",
     "size": 2048
   },
   "names": [
     {
       "C": "CN",
       "L": "BeiJing",
       "ST": "BeiJing",
       "O": "system:masters",
       "OU": "System"
     }
   ]
 }
 EOF
 ​
 #生成证书
 cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-scheduler-csr.json | cfssljson -bare kube-scheduler
 ​
 ​
 #生成kubeconfig文件
 KUBE_CONFIG="/opt/kubernetes/cfg/kube-scheduler.kubeconfig"
 KUBE_APISERVER="https://192.168.41.10:6443"   #master01的IP
 ​
 kubectl config set-cluster kubernetes \
   --certificate-authority=/opt/kubernetes/ssl/ca.pem \
   --embed-certs=true \
   --server=${KUBE_APISERVER} \
   --kubeconfig=${KUBE_CONFIG}
 kubectl config set-credentials kube-scheduler \
   --client-certificate=./kube-scheduler.pem \
   --client-key=./kube-scheduler-key.pem \
   --embed-certs=true \
   --kubeconfig=${KUBE_CONFIG}
 kubectl config set-context default \
   --cluster=kubernetes \
   --user=kube-scheduler \
   --kubeconfig=${KUBE_CONFIG}
 kubectl config use-context default --kubeconfig=${KUBE_CONFIG}
 ​
 ​
 ##创建 kube-scheduler.service 服务管理文件
 cat >/usr/lib/systemd/system/kube-scheduler.service <<EOF
 [Unit]
 Description=Kubernetes Scheduler
 Documentation=https://github.com/kubernetes/kubernetes
 ​
 [Service]
 EnvironmentFile=-/opt/kubernetes/cfg/kube-scheduler
 ExecStart=/opt/kubernetes/bin/kube-scheduler $KUBE_SCHEDULER_OPTS
 Restart=on-failure
 ​
 [Install]
 WantedBy=multi-user.target
 EOF
 ​
 systemctl daemon-reload
 systemctl enable kube-scheduler
 systemctl restart kube-scheduler

4.

 #!/bin/bash
 ##创建 kube-scheduler 启动参数配置文件
 MASTER_ADDRESS=$1
 ​
 cat >/opt/kubernetes/cfg/kube-scheduler <<EOF
 KUBE_SCHEDULER_OPTS="--logtostderr=false \
 --v=2 \
 --log-dir=/opt/kubernetes/logs \
 --leader-elect=true \
 --kubeconfig=/opt/kubernetes/cfg/kube-scheduler.kubeconfig \
 --bind-address=127.0.0.1"
 EOF
 ​
 #-–kubeconfig:连接 apiserver 用的配置文件,用于识别 k8s 集群
 #--leader-elect=true:当该组件启动多个时,自动启动 leader 选举
 #k8s中Controller-Manager和Scheduler的选主逻辑:k8s中的etcd是整个集群所有状态信>息的存储,涉及数据的读写和多个etcd之间数据的同步,对数据的一致性要求严格,所以>使用较复杂的 raft 算法来选择用于提交数据的主节点。而 apiserver 作为集群入口,本身是无状态的web服务器,多个 apiserver 服务之间直接负载请求并不需要做选主。Controller-Manager 和 Scheduler 作为任务类型的组件,比如 controller-manager 内置的 k8s 各种资源对象的控制器实时的 watch apiserver 获取对象最新的变化事件做期望状态>和实际状态调整,调度器watch未绑定节点的pod做节点选择,显然多个这些任务同时工作>是完全没有必要的,所以 controller-manager 和 scheduler 也是需要选主的,但是选主逻辑和 etcd 不一样的,这里只需要保证从多个 controller-manager 和 scheduler 之间选出一个 leader 进入工作状态即可,而无需考虑它们之间的数据一致和同步。
 ​
 ​
 ##生成kube-scheduler证书
 cd /opt/k8s/k8s-cert/
 #创建证书请求文件
 cat > kube-scheduler-csr.json << EOF
 {
   "CN": "system:kube-scheduler",
   "hosts": [],
   "key": {
     "algo": "rsa",
     "size": 2048
   },
   "names": [
     {
       "C": "CN",
       "L": "BeiJing",
       "ST": "BeiJing",
       "O": "system:masters",
       "OU": "System"
     }
   ]
 }
 EOF
 ​
 #生成证书
 cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-scheduler-csr.json | cfssljson -bare kube-scheduler
 ​
 ​
 #生成kubeconfig文件
 KUBE_CONFIG="/opt/kubernetes/cfg/kube-scheduler.kubeconfig"
 KUBE_APISERVER="https://192.168.41.10:6443"   #master01的IP
 ​
 kubectl config set-cluster kubernetes \
   --certificate-authority=/opt/kubernetes/ssl/ca.pem \
   --embed-certs=true \
   --server=${KUBE_APISERVER} \
   --kubeconfig=${KUBE_CONFIG}
 kubectl config set-credentials kube-scheduler \
   --client-certificate=./kube-scheduler.pem \
   --client-key=./kube-scheduler-key.pem \
   --embed-certs=true \
   --kubeconfig=${KUBE_CONFIG}
 kubectl config set-context default \
   --cluster=kubernetes \
   --user=kube-scheduler \
   --kubeconfig=${KUBE_CONFIG}
 kubectl config use-context default --kubeconfig=${KUBE_CONFIG}
 ​
 ​
 ##创建 kube-scheduler.service 服务管理文件
 cat >/usr/lib/systemd/system/kube-scheduler.service <<EOF
 [Unit]
 Description=Kubernetes Scheduler
 Documentation=https://github.com/kubernetes/kubernetes
 ​
 [Service]
 EnvironmentFile=-/opt/kubernetes/cfg/kube-scheduler
 ExecStart=/opt/kubernetes/bin/kube-scheduler $KUBE_SCHEDULER_OPTS
 Restart=on-failure
 ​
 [Install]
 WantedBy=multi-user.target
 EOF
 ​
 systemctl daemon-reload
 systemctl enable kube-scheduler
 systemctl restart kube-scheduler

4.controller-manager.sh

#!/bin/bash
 ##创建 kube-controller-manager 启动参数配置文件
 MASTER_ADDRESS=$1
 ​
 cat >/opt/kubernetes/cfg/kube-controller-manager <<EOF
 KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=false \
 --v=2 \
 --log-dir=/opt/kubernetes/logs \
 --leader-elect=true \
 --kubeconfig=/opt/kubernetes/cfg/kube-controller-manager.kubeconfig \
 --bind-address=127.0.0.1 \
 --allocate-node-cidrs=true \
 --cluster-cidr=10.244.0.0/16 \
 --service-cluster-ip-range=10.0.0.0/24 \
 --cluster-signing-cert-file=/opt/kubernetes/ssl/ca.pem \
 --cluster-signing-key-file=/opt/kubernetes/ssl/ca-key.pem  \
 --root-ca-file=/opt/kubernetes/ssl/ca.pem \
 --service-account-private-key-file=/opt/kubernetes/ssl/ca-key.pem \
 --cluster-signing-duration=87600h0m0s"
 EOF
 ​
 #––leader-elect:当该组件启动多个时,自动选举(HA)
 #-–kubeconfig:连接 apiserver 用的配置文件,用于识别 k8s 集群
 #--cluster-cidr=10.244.0.0/16:pod资源的网段,需与pod网络插件的值设置一致。通常,Flannel网络插件的默认为10.244.0.0/16,Calico插件的默认值为192.168.0.0/16
 #--cluster-signing-cert-file/–-cluster-signing-key-file:自动为kubelet颁发证书>的CA,与apiserver保持一致。指定签名的CA机构根证书,用来签名为 TLS BootStrapping 创建的证书和私钥
 #--root-ca-file:指定根CA证书文件路径,用来对 kube-apiserver 证书进行校验,指定该参数后,才会在 Pod 容器的 ServiceAccount 中放置该 CA 证书文件
 #--experimental-cluster-signing-duration:设置为 TLS BootStrapping 签署的证书有效时间为10年,默认为1年
 ​
 ​
 ##生成kube-controller-manager证书
 cd /opt/k8s/k8s-cert/
 #创建证书请求文件
 cat > kube-controller-manager-csr.json << EOF
 {
   "CN": "system:kube-controller-manager",
   "hosts": [],
   "key": {
     "algo": "rsa",
     "size": 2048
   },
   "names": [
     {
       "C": "CN",
       "L": "BeiJing",
       "ST": "BeiJing",
       "O": "system:masters",
       "OU": "System"
     }
   ]
 }
 EOF
 ​
 ​
 #生成证书
 cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager
 ​
 #生成kubeconfig文件
 KUBE_CONFIG="/opt/kubernetes/cfg/kube-controller-manager.kubeconfig"
 KUBE_APISERVER="https://192.168.41.10:6443"   #master01的IP
 ​
 kubectl config set-cluster kubernetes \
   --certificate-authority=/opt/kubernetes/ssl/ca.pem \
   --embed-certs=true \
   --server=${KUBE_APISERVER} \
   --kubeconfig=${KUBE_CONFIG}
 kubectl config set-credentials kube-controller-manager \
   --client-certificate=./kube-controller-manager.pem \
   --client-key=./kube-controller-manager-key.pem \
   --embed-certs=true \
   --kubeconfig=${KUBE_CONFIG}
 kubectl config set-context default \
   --cluster=kubernetes \
   --user=kube-controller-manager \
   --kubeconfig=${KUBE_CONFIG}
 kubectl config use-context default --kubeconfig=${KUBE_CONFIG}
 ​
 ​
 ##创建 kube-controller-manager.service 服务管理文件
 cat >/usr/lib/systemd/system/kube-controller-manager.service <<EOF
 [Unit]
 Description=Kubernetes Controller Manager
 Documentation=https://github.com/kubernetes/kubernetes
 ​
 [Service]
 EnvironmentFile=-/opt/kubernetes/cfg/kube-controller-manager
 ExecStart=/opt/kubernetes/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_OPTS
 Restart=on-failure
 ​
 [Install]
 WantedBy=multi-user.target
 EOF
 ​
 ​
 systemctl daemon-reload
 systemctl enable kube-controller-manager
 systemctl restart kube-controller-manager

5.admin.sh

 #!/bin/bash
 mkdir /root/.kube
 KUBE_CONFIG="/root/.kube/config"
 KUBE_APISERVER="https://192.168.30.100:6443"   #master01的IP
 ​
 cd /opt/k8s/k8s-cert/
 ​
 kubectl config set-cluster kubernetes \
   --certificate-authority=/opt/kubernetes/ssl/ca.pem \
   --embed-certs=true \
   --server=${KUBE_APISERVER} \
   --kubeconfig=${KUBE_CONFIG}
 kubectl config set-credentials cluster-admin \
   --client-certificate=./admin.pem \
   --client-key=./admin-key.pem \
   --embed-certs=true \
   --kubeconfig=${KUBE_CONFIG}
 kubectl config set-context default \
   --cluster=kubernetes \
   --user=cluster-admin \
   --kubeconfig=${KUBE_CONFIG}
 kubectl config use-context default --kubeconfig=${KUBE_CONFIG}

总结:

etcd数据库:

  • 分布式键值对型的数据库,服务发现系统(之前的docker-consul 就是服务发现)
  • go语言开发的,使用raft-a致性算法
  • 部署集群时需要3台或以上的奇数台
  • 2379 对外(客户端)通信的端口
  • 2380 对内(集群内部节点间)通信的端口

etcd安装步骤:

  1. 使用CFSSL工具,生成ca证书和私钥文件,再使用ca签发服务端证书和私钥文件
  2. 使用ca证书、服务端证书和私钥文件加上etcd集群配置文件,去启动etcd服务
  3. 解压etcd软件包
  4. 复制etcd工作目录和服务管理文件到另外几个节点上,修改etcd集群配置文件并启动etcd服务
  5. 使用v3版本的接口执行etcdctl +证书选项+ (endpoint health | endpoint status | member list) 查看etcd 集群和节点状态

正常情况etcd应该生成三套证书:客户端证书,服务端证书,对等体证书(内部)。初学者可以先只生成两套。

master组件安装步骤:

1.先安装apiserver

  • 准备组件的相关证书和私钥文件
  • 准备bootstraptoken认证文件(给kubelet启动时签发证书时使用)
  • 准备组件的启动配置文件
  • 启动apiserver 服务、端口号、6443、https

2.再启动controller-manager 和scheduler

  • 准备启动配置文件
  • 准备证书和私钥文件生成kubeconfig 文件(用于指定对接哪个apiserver,使用什么证书认证)
  • 启动服务

3.检查集群组件状态

  • 需要准备kubeconfig 文件,把kubectl 加入到集群中( 指定对接哪个apiserver,使用什么证书认证)
  • kubectl get cs

多master部署步骤:

  1. 先部署master92等其它master节点
  2. 搭建Nginx/Haproxy + keepalived 高可用 负载均衡对接
  3. master节点群集
  4. 修改node 节点上的kubelet kube-proxy 的kubeconfig 配置文件对接vip
  5. kubectl的配置文件也要对接VIP或者当前节点的IP

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1181749.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

指令手册术语缩写

指令手册术语缩写 1 指令汇总表中的操作码列(不带VEX前缀的指令)2 指令汇总表中的操作码列(带有VEX前缀的指令)3 操作码汇总表中的指令列 本文属于《 X86指令基础系列教程》之一&#xff0c;欢迎查看其它文章。 1 指令汇总表中的操作码列(不带VEX前缀的指令) 2 指令汇总表中的…

阿里云安全恶意程序检测(速通三)

阿里云安全恶意程序检测 特征工程进阶与方案优化pivot特征构建pivot特征pivot特征构建时间pivot特征构建细节特点 业务理解和结果分析结合模型理解业务多分类问题预测结果分析 特征工程进阶基于LightGBM模型验证模型结果分析模型测试 优化技巧与解决方案升级内存管理控制加速数…

【配置】如何在打包Spring Boot项目时按需使用日常、测试、预发、正式环境的配置文件

文章目录 前言1. 创建5个配置文件2. 在pom.xml文件中如下配置3. 在application.properties中加入环境变量 前言 在我们开发项目的时候&#xff0c;一般有四套环境&#xff1a;日常、测试、预发、正式。日常环境作为我们开发环境&#xff1b;测试环境给测试同学测试功能&#x…

基于厨师算法的无人机航迹规划-附代码

基于厨师算法的无人机航迹规划 文章目录 基于厨师算法的无人机航迹规划1.厨师搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用厨师算法来优化无人机航迹规划。 1.厨师搜索算法 …

Canal同步Mysql数据到ES以及Springboot项目查询ES数据

1、环境准备 服务器&#xff1a;Centos7 Jdk版本&#xff1a;1.8 Mysql版本&#xff1a;5.7.44 Canal版本&#xff1a;1.17 Es版本&#xff1a;7.12.1 kibana版本&#xff1a;7.12.1 软件包下载地址&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1jRpCJP0-hr9aI…

C++进阶篇4---番外-AVL树

一、AVL树的概念 二叉搜索树虽可以缩短查找的效率&#xff0c;但如果数据有序或接近有序二叉搜索树将退化为单支树&#xff0c;查 找元素相当于在顺序表中搜索元素&#xff0c;效率低下。因此&#xff0c;两位俄罗斯的数学家G.M.Adelson-Velskii 和E.M.Landis在1962年发明了一…

Microsoft Dynamics 365 CE 扩展定制 - 8. DevOps

在本章中,我们将介绍以下内容: 使用PowerShell导出Dynamics 365解决方案使用PowerShell部署解决方案构建解决方案层次结构修补解决方案暂存解决方案使用SolutionPackager在源代码管理中保存解决方案使用PackageDeployer将您的解决方案与配置数据打包基于解决方案版本增量触发…

缓存-基础理论和Guava Cache介绍

缓存-基础理论和Guava Cache介绍 缓存基础理论 缓存的容量和扩容 缓存初始容量、最大容量&#xff0c;扩容阈值以及相应的扩容实现。 缓存分类 本地缓存&#xff1a;运行于本进程中的缓存&#xff0c; 如Java的 concurrentHashMap, Ehcache&#xff0c;Guava Cache。 分布式缓…

3.Netty中Channel通道概述

Selector 模型 Java NIO 是基于 Selector 模型来实现非阻塞的 I/O。Netty 底层是基于 Java NIO 实现的&#xff0c;因此也使用了 Selector 模型。 Selector 模型解决了传统的阻塞 I/O 编程一个客户端一个线程的问题。Selector 提供了一种机制&#xff0c;用于监视一个或多个 …

如何成为C++大神?五个技巧助你提升编程水平

一名优秀的C程序员是如何炼成的&#xff1f;这个问题一直困扰着许多人&#xff0c;尤其是那些刚刚踏入编程的世界的新手。C作为一门强大而复杂的编程语言&#xff0c;的确需要一些特殊的技巧和策略才能掌握。但幸运的是&#xff0c;成为一名出色的C程序员并不是不可能的任务。在…

【算法练习Day41】买卖股票的最佳时机买卖股票的最佳时机 II

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 买卖股票的最佳时机买卖股票…

办公神器!2024年值得拥有的10款在线画板软件!

随着科技的进步和互联网的普及&#xff0c;我们工作、学习和生活方式发生了翻天覆地的变化。在线画板软件就是在这个背景下应运而生的一种便捷工具。它不仅满足了我们随时随地绘制图像、演示思路的需求&#xff0c;还提供了协同编辑、云存储等功能&#xff0c;使得团队协作变得…

Java面试题(高频、有答案,全网最强)

原文网址&#xff1a;Java面试题&#xff08;高频、有答案&#xff0c;全网最强&#xff09;-CSDN博客 这是一套全网最强的Java面试题&#xff0c;吊打网上所有Java面试题。 此套面试题的威力&#xff1a;看过这套题的朋友、同事、粉丝参加了面试后说&#xff0c;他们面试被问…

基于C#的GRPC

GRPC gRPC&#xff08;gRPC Remote Procedure Call&#xff09;是由Google开发的高性能、跨语言的远程过程调用框架。它基于HTTP/2协议进行通信&#xff0c;支持多种编程语言&#xff0c;包括C, C#, Java, Python等&#xff0c;使不同语言的应用程序可以通过远程调用相互通信。…

SPASS教程-入门

常用的统计工具 EXCEL 严格说来并不是统计软件&#xff0c;但作为数据表格软件&#xff0c;有一定统计计算功能。对于简单分析&#xff0c;Excel还算方便&#xff0c;但随着问题的深入&#xff0c;Excel就不那么“傻瓜”&#xff0c;需要使用函数&#xff0c;甚至根本没有相应…

​软考-高级-信息系统项目管理师教程 第四版【第19章-配置与变更管理-思维导图】​

软考-高级-信息系统项目管理师教程 第四版【第19章-配置与变更管理-思维导图】 课本里章节里所有蓝色字体的思维导图

Spire.Office for Java 8.10.2 同步更新Crk

Spire.Office for Java 是 E-iceblue 提供的企业级 Office Java API 的组合。它包括Spire.Doc for Java、Spire.XLS for Java、Spire.Presentation for Java、Spire.PDF for Java和Spire.Barcode for Java。 开发人员可以使用Spire.Office for Java在Java应用程序中执行各种办…

【electron】【附排查清单】记录一次逆向过程中,fetch无法请求http的疑难杂症(net::ERR_BLOCKED_BY_CLIENT)

▒ 目录 ▒ &#x1f6eb; 导读需求开发环境 1️⃣ Adblock等插件拦截2️⃣ 【失败】Content-Security-Policy启动服务器json-serverhtml中的meta字段 3️⃣ 【失败】https vs httpwebPreferences & allowRunningInsecureContent disable-features 4️⃣ 【失败】检测fetch…

技术分享 | app自动化测试(Android)--元素定位方式与隐式等待

元素定位是 UI 自动化测试中最关键的一步&#xff0c;假如没有定位到元素&#xff0c;也就无法完成对页面的操作。那么在页面中如何定位到想要的元素&#xff0c;本小节讨论 Appium 元素定位方式。 Appium的元素定位方式 定位页面的元素有很多方式&#xff0c;比如可以通过 I…

初识Java 17-2 反射

目录 转型前检查 构建例子&#xff1a;生成层次结构 优化Creator&#xff1a;使用类字面量 优化PetCounter&#xff1a;动态验证类型 更通用的递归计数 注册工厂 本笔记参考自&#xff1a; 《On Java 中文版》 转型前检查 当我们使用传统的类型转换&#xff0c;例如&…