kubeadm搭建生产环境高可用集群

前言

搞了好多天(今天是20240819),中途遇到各种各样的问题,总算是可以用了
我这里用的vmware开了5台服务器做学习实践
K8S因为直接使用的 pkgs.k8s.io 仓库,所以直接拉取的最新release版(v1.31)
这里个人记录一下

友情提示:要使用 pkgs.k8s.io 仓库的话必须要科学上网哦

1. 环境准备

集群角色IP主机名
控制节点192.168.86.101weihengmaster1
控制节点192.168.86.101weihengmaster1
控制节点192.168.86.101weihengmaster1
控制节点192.168.86.101weihengmaster1
控制节点192.168.86.101weihengmaster1
Vip192.168.86.199

参考文档:https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#check-network-adapters

1.1 配置静态IP

注意:虚拟机克隆的,需要重新生成新的UUID和MachineID
重置MachineId:

rm -rf /etc/machine-id; systemd-machine-id-setup;reboot
#cat /etc/machine-id

重置UUID

nmcli con delete uuid acb2a913-945b-399d-815e-84a1a9d46485;nmcli con add type ethernet ifname ens160 con-name ens160;nmcli con up ens160# 查看当前的网卡列表和 UUID:
# nmcli con show
# 删除要更改 UUID 的网络连接:
# nmcli con delete uuid <原 UUID>
# 重新生成 UUID:
# nmcli con add type ethernet ifname <接口名称> con-name <新名称>
# 重新启用网络连接:
# nmcli con up <新名称>

设置IP

nmcli con mod ens160 ipv4.addresses 192.168.86.101/24; nmcli con mod ens160 ipv4.gateway  192.168.2.1; nmcli con mod ens160 ipv4.method manual; nmcli con mod ens160 ipv4.dns "192.168.2.1"; nmcli con up ens160

1.2 修改主机名

hostnamectl set-hostname <newhostname>

1.3 配置免密

vim /etc/hosts
#添加主机配置
192.168.86.101   weihengmaster1
192.168.86.102   weihengmaster2
192.168.86.103   weihengmaster3
192.168.86.201   weihengnode1
192.168.86.202   weihengnode2#每个服务节点执行如下命令即可添加上述配置
echo -e "192.168.86.101   weihengmaster1\n192.168.86.102   weihengmaster2\n192.168.86.103   weihengmaster3\n192.168.86.201   weihengnode1\n192.168.86.202   weihengnode2" | sudo tee -a /etc/hosts#生成公私钥
ssh-keygen -f /root/.ssh/id_rsa -P ''#把本地的ssh公钥文件安装到远程主机对应的账户
ssh-copy-id -i .ssh/id_rsa.pub weihengmaster1
ssh-copy-id -i .ssh/id_rsa.pub weihengmaster2
ssh-copy-id -i .ssh/id_rsa.pub weihengmaster3
ssh-copy-id -i .ssh/id_rsa.pub weihengnode1
ssh-copy-id -i .ssh/id_rsa.pub weihengnode2#测试免密登录
[root@weihengmaster1 ~]# ssh weihengnode2
Activate the web console with: systemctl enable --now cockpit.socketLast login: Tue Jul 30 20:00:52 2024 from 192.168.2.101
[root@weihengnode2 ~]#

1.4 关闭防火墙

systemctl stop firewalld; systemctl disable firewalld

1.5 关闭SELinux

setenforce 0
sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config# 参数解释
# 
# setenforce 0
# 此命令用于设置 SELinux 的执行模式。0 表示关闭 SELinux。
# 
# sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config
# 该命令使用 sed 工具来编辑 /etc/selinux/config 文件。其中 '-i' 参数表示直接修改原文件,而不是输出到终端或另一个文件。's#SELINUX=enforcing#SELINUX=disabled#g' 是 sed 的替换命令,它将文件中所有的 "SELINUX=enforcing" 替换为 "SELINUX=disabled"。这里的 '#' 是分隔符,用于替代传统的 '/' 分隔符,以避免与路径中的 '/' 冲突。#重启服务器,执行如下命令后显示 Disabled 则禁用成功
getenforce

1.6 关闭交换分区

#修改配置文件,永久关闭交换分区
sed -ri 's/.*swap.*/#&/' /etc/fstab
#修改内核参数
swapoff -a && sysctl -w vm.swappiness=0
#检查
cat /etc/fstab

1.7 配置ulimits

ulimit -SHn 65535
cat >> /etc/security/limits.conf <<EOF
* soft nofile 655360
* hard nofile 131072
* soft nproc 655350
* hard nproc 655350
* soft memlock unlimited
* hard memlock unlimited
EOF# 参数解释
#
# soft nofile 655360
# soft表示软限制,nofile表示一个进程可打开的最大文件数,默认值为1024。这里的软限制设置为655360,即一个进程可打开的最大文件数为655360。
#
# hard nofile 131072
# hard表示硬限制,即系统设置的最大值。nofile表示一个进程可打开的最大文件数,默认值为4096。这里的硬限制设置为131072,即系统设置的最大文件数为131072。
#
# soft nproc 655350
# soft表示软限制,nproc表示一个用户可创建的最大进程数,默认值为30720。这里的软限制设置为655350,即一个用户可创建的最大进程数为655350。
#
# hard nproc 655350
# hard表示硬限制,即系统设置的最大值。nproc表示一个用户可创建的最大进程数,默认值为4096。这里的硬限制设置为655350,即系统设置的最大进程数为655350。
#
# soft memlock unlimited
# soft表示软限制,memlock表示一个进程可锁定在RAM中的最大内存,默认值为64 KB。这里的软限制设置为unlimited,即一个进程可锁定的最大内存为无限制。
#
# hard memlock unlimited
# hard表示硬限制,即系统设置的最大值。memlock表示一个进程可锁定在RAM中的最大内存,默认值为64 KB。这里的硬限制设置为unlimited,即系统设置的最大内存锁定为无限制。

1.8 安装iptables

所有主机安装

#安装iptables
yum install iptables-services -y
#禁用iptables
service iptables stop   && systemctl disable iptables
#清空防火墙规则
iptables -F

1.9 安装基础软件包

在所有master和node节点执行

yum install -y yum-utils device-mapper-persistent-data lvm2 wget net-tools nfs-utils lrzsz gcc gcc-c++ make cmake libxml2-devel openssl-devel curl curl-devel unzip sudo libaio-devel wget vim ncurses-devel autoconf automake zlib-devel python-devel epel-release openssh-server socat ipvsadm conntrack telnet rsync

1.10 开启ipvs

不开启ipvs将会使用iptables进行数据包转发,但是效率低,所以官网推荐需要开通ipvs。
mkdir -p /etc/sysconfig/modules/

cat > /etc/sysconfig/modules/ipvs.modules << "EOF"
#!/bin/bash
ipvs_modules="ip_vs ip_vs_lc ip_vs_wlc ip_vs_rr ip_vs_wrr ip_vs_lblc ip_vs_lblcr ip_vs_dh ip_vs_sh ip_vs_nq ip_vs_sed ip_vs_ftp nf_conntrack"
for kernel_module in ${ipvs_modules}; do/sbin/modinfo -F filename ${kernel_module} > /dev/null 2>&1if [ 0 -eq 0 ]; then/sbin/modprobe ${kernel_module}fi
done
EOF#ip_vs:IPVS 是 Linux 内核中的一个模块,用于实现负载均衡和高可用性。它通过在前端代理服务器上分发传入请求到后端实际服务器上,提供了高性能和可扩展的网络服务。
#ip_vs_rr:IPVS 的一种调度算法之一,使用轮询方式分发请求到后端服务器,每个请求按顺序依次分发。ip_vs_wrr:IPVS 的一种调度算法之一,使用加权轮询方式分发请求到后端服务器,每个请求按照指定的权重比例分发。
#nf_conntrack:这是一个内核模块,用于跟踪和管理网络连接,包括 TCP、UDP 和 ICMP 等协议。它是实现防火墙状态跟踪的基础。
#其他的大家可以自己网上查一下...#授权并检查
chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep ip_vs#拷贝到其他主机(所有master和worker)
scp /etc/sysconfig/modules/ipvs.modules weihengmaster2:/etc/sysconfig/modules/

1.11 安装docker-ce

在所有master和node节点执行

#设置云源 - docker官方(我用的这个)
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo#阿里yum源 - 国内用这个
#sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo#刷新yum缓存
sudo yum makecache#安装
yum install docker-ce docker-ce-cli containerd.io  -y
#配置开机启动
systemctl start docker && systemctl enable docker.service
#查看状态
systemctl status docker

1.12 安装cri-dockerd

参考文档:https://mirantis.github.io/cri-dockerd/usage/install/
引用一段原文:

The easiest way to install cri-dockerd is to use one of the pre-built binaries or packages from the releases page. There are numerous supported platforms and using a pre-built package will install the binary and setup your system to run it as a service.

这就感觉有点坑爹,怎么就没有yum安装呢?那我们只能通过源码来安装了

容器运行时接口(Container Runtime Interface,CRI)
cri-dockerd 提供了一个接口,使得 Docker 能够符合 Kubernetes 的 CRI 标准,从而可以在 Kubernetes 中直接使用 Docker 作为容器运行时 ,通过 cri-dockerd,用户仍然可以使用 Docker 作为容器运行时,而无需修改现有的 Docker 工作流程。
我这边通过 releases page 手动下载并安装的cri-dockerd

在所有master和worker节点安装
目前(20240731)最新版本是0.3.15,我这里选了0.3.14(按照一般原则,不使用最新版本,以防踩坑)

#我切换下目录
#mkdir -p /data/work && cd /data/work#下载cri-docker 
#https://github.com/Mirantis/cri-dockerd/releases/
#wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.14/cri-dockerd-0.3.14.amd64.tgz#解压cri-docker
tar xvf cri-dockerd-*.amd64.tgz 
cp -r cri-dockerd/  /usr/bin/
chmod +x /usr/bin/cri-dockerd/cri-dockerd#scp -r cri-dockerd/ root@weihengmaster2:/usr/bin/

写入启动的配置文件

# 写入启动配置文件
cat >  /usr/lib/systemd/system/cri-docker.service <<EOF
[Unit]
Description=CRI Interface for Docker Application Container Engine
Documentation=https://docs.mirantis.com
After=network-online.target firewalld.service docker.service
Wants=network-online.target
Requires=cri-docker.socket[Service]
Type=notify
ExecStart=/usr/bin/cri-dockerd/cri-dockerd --network-plugin=cni --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.9
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
StartLimitBurst=3
StartLimitInterval=60s
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
Delegate=yes
KillMode=process[Install]
WantedBy=multi-user.target
EOF# [Unit]
# - Description:该参数用于描述该单元的功能,这里描述的是CRI与Docker应用容器引擎的接口。
# - Documentation:该参数指定了相关文档的网址,供用户参考。
# - After:该参数指定了此单元应该在哪些其他单元之后启动,确保在网络在线、防火墙和Docker服务启动之后再启动此单元。
# - Wants:该参数指定了此单元希望也启动的所有单元,此处是希望在网络在线之后启动。
# - Requires:该参数指定了此单元需要依赖的单元,此处是cri-docker.socket单元。
# 
# [Service]
# - Type:该参数指定了服务的类型,这里是notify,表示当服务启动完成时向系统发送通知。
# - ExecStart:该参数指定了将要运行的命令和参数,此处是执行/usr/bin/cri-dockerd/cri-dockerd命令,并指定了网络插件为cni和Pod基础设施容器的镜像为registry.aliyuncs.com/google_containers/pause:3.7。
# - ExecReload:该参数指定在服务重载时运行的命令,此处是发送HUP信号给主进程。
# - TimeoutSec:该参数指定了服务启动的超时时间,此处为0,表示无限制。
# - RestartSec:该参数指定了自动重启服务的时间间隔,此处为2秒。
# - Restart:该参数指定了在服务发生错误时自动重启,此处是始终重启。
# - StartLimitBurst:该参数指定了在给定时间间隔内允许的启动失败次数,此处为3次。
# - StartLimitInterval:该参数指定启动失败的时间间隔,此处为60秒。
# - LimitNOFILE:该参数指定了允许打开文件的最大数量,此处为无限制。
# - LimitNPROC:该参数指定了允许同时运行的最大进程数,此处为无限制。
# - LimitCORE:该参数指定了允许生成的core文件的最大大小,此处为无限制。
# - TasksMax:该参数指定了此服务的最大任务数,此处为无限制。
# - Delegate:该参数指定了是否将控制权委托给指定服务,此处为是。
# - KillMode:该参数指定了在终止服务时如何处理进程,此处是通过终止进程来终止服务。
# 
# [Install]
# - WantedBy:该参数指定了希望这个单元启动的多用户目标。在这里,这个单元希望在multi-user.target启动。

写入cri-docker的socket配置文件

cat > /usr/lib/systemd/system/cri-docker.socket <<EOF
[Unit]
Description=CRI Docker Socket for the API
PartOf=cri-docker.service[Socket]
ListenStream=%t/cri-dockerd.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker[Install]
WantedBy=sockets.target
EOF# 该配置文件是用于systemd的单元配置文件(unit file),用于定义一个socket单元。
# 
# [Unit]
# - Description:表示该单元的描述信息。
# - PartOf:表示该单元是cri-docker.service的一部分。
# 
# [Socket]
# - ListenStream:指定了该socket要监听的地址和端口,这里使用了%t占位符,表示根据单元的类型来决定路径。%t/cri-dockerd.sock表示将监听Unix域套接字cri-dockerd.sock。Unix域套接字用于在同一台主机上的进程之间通信。
# - SocketMode:指定了socket文件的权限模式,此处为0660,即用户和用户组有读写权限,其他用户无权限。
# - SocketUser:指定了socket文件的所有者,此处为root用户。
# - SocketGroup:指定了socket文件的所属用户组,此处为docker用户组。
# 
# [Install]
# - WantedBy:部分定义了该单元的安装配置信息。WantedBy=sockets.target表示当sockets.target单元启动时,自动启动该socket单元。sockets.target是一个系统服务,用于管理所有的socket单元。

启动cri-docker

systemctl daemon-reload
# 用于重新加载systemd管理的单位文件。当你新增或修改了某个单位文件(如.service文件、.socket文件等),需要运行该命令来刷新systemd对该文件的配置。systemctl enable --now cri-docker.service
# 启用并立即启动cri-docker.service单元。cri-docker.service是cri-docker守护进程的systemd服务单元。systemctl restart cri-docker.service
# 重启cri-docker.service单元,即重新启动cri-docker守护进程。systemctl status docker.service
systemctl status cri-docker.service
# 显示docker.service单元的当前状态,包括运行状态、是否启用等信息。

2. 开始安装高可用集群

2.1 安装 kubeadm、kubelet 和 kubectl

参考文档:https://kubernetes.io/zh-cn/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
你需要在每台机器上安装以下的软件包:

  • kubeadm:用来初始化集群的指令。
  • kubelet:在集群中的每个节点上用来启动 Pod 和容器等。
  • kubectl:用来与集群通信的命令行工具。

2.1.1 添加 Kubernetes 的 yum 仓库

#这会覆盖 /etc/yum.repos.d/kubernetes.repo 中现存的所有配置
#如果要下载其他版本,在这里改对应的版本号就可以了
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.31/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.31/rpm/repodata/repomd.xml.key
EOF

#备一个阿里云的仓库,不过我是用的 pkgs.k8s.io
[kubernetes-aliyun]
name=Kubernetes from Aliyun
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0

2.1.2 安装 kubelet kubeadm kubectl

#使用 yum 安装 kubectl
sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
sudo systemctl enable --now kubelet#检查可用版本
#yum list --showduplicates kubelet kubeadm kubectl#安装指定版本示例 - 我安装时没有指定版本号,安装的是 1.31.1
#sudo yum install -y kubelet-1.28.2 kubeadm-1.28.2 kubectl-1.28.2 --disableexcludes=kubernetes#删除
#sudo yum remove -y kubelet kubeadm kubectl#查看安装状态
kubectl cluster-info
#如果提示下面的内容,表示安装出现异常
The connection to the server <server-name:port> was refused - did you specify the right host or port?
#官方提示的解决办法:For example, if you are intending to run a Kubernetes cluster on your laptop (locally), you will need a tool like Minikube to be installed first and then re-run the commands stated above.
#按照提示安装minikube后问题得到解决

在这里插入图片描述
kubectl 命令自动补全插件、API版本转换插件等:
https://kubernetes.io/zh-cn/docs/tasks/tools/install-kubectl-linux/#verify-kubectl-configuration

2.1.3 配置cgroup driver

参考文档:https://kubernetes.io/docs/setup/production-environment/container-runtimes/#container-runtimes
K8S的容器运行时有 4种(推荐使用containerd):

  • containerd
  • CRI-O
  • Docker Engine
  • Mirantis Container

v1.22版本以后不需要在 KubeletConfiguration 中指定cgroupDriver,他默认就会是systemd

我这里仅做官方推荐的containerd的配置
参考:https://github.com/containerd/containerd/blob/main/docs/getting-started.md

这里有段原文,打印默认配置,感觉有点用:
The default configuration can be generated via containerd config default > /etc/containerd/config.toml

vim /etc/containerd/config.toml
#添加SystemdCgroup = true 的配置
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]...[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]SystemdCgroup = true#重启containerd
sudo systemctl restart containerd

2.1.4 docker镜像加速器配置

把这个 native.cgroupdriver 也顺带调整下

# 这个加到所有master和node节点
tee /etc/docker/daemon.json << 'EOF'
{"registry-mirrors":["https://rsbud4vc.mirror.aliyuncs.com","https://registry.docker-cn.com","https://docker.mirrors.ustc.edu.cn","https://dockerhub.azk8s.cn","http://hub-mirror.c.163.com","http://qtid6917.mirror.aliyuncs.com", "https://rncxm540.mirror.aliyuncs.com"],"exec-opts": ["native.cgroupdriver=systemd"],"log-opts": {"max-size": "100m"}
} 
EOF# 都重启一下吧
systemctl daemon-reload
systemctl restart docker
systemctl restart cri-docker
systemctl restart containerd

2.1.5 设置IPv4数据包转发

默认情况下,Linux 内核不允许 IPv4 数据包在接口之间路由。 大多数 Kubernetes 集群网络实现都会更改此设置(如果需要)

# 设置所需的 sysctl 参数,参数在重新启动后保持不变
# 这里顺带把 允许 iptables 进行桥接的参数配置加上,确保流量在 Kubernetes 网络插件中正确过滤和路由
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF# 应用 sysctl 参数而不重新启动
sudo sysctl --system
# 验证 ipv4转发 是否设置成功
sysctl net.ipv4.ip_forward

2.1.6 修改sandbox_image【可选】

sudo vi /etc/containerd/config.toml#修改sandbox_image - 可选项操作
[plugins."io.containerd.grpc.v1.cri".containerd]...sandbox_image = "registry.k8s.io/pause:3.10"...#重启container
sudo systemctl restart containerd#查看
#sudo crictl info | grep sandboxImage

2.2 通过keepalive+nginx实现 k8s apiserver 节点高可用

yum install nginx keepalived nginx-mod-stream -y# 写入nginx配置文件
vim /etc/nginx/nginx.conf
# 添加负载均衡配置
stream {log_format main '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent';access_log /var/log/nginx/k8s-access.log main;upstream backend {least_conn;hash $remote_addr consistent;server 192.168.86.101:6443        max_fails=3 fail_timeout=30s;server 192.168.86.102:6443        max_fails=3 fail_timeout=30s;server 192.168.86.103:6443        max_fails=3 fail_timeout=30s;}server {listen 16443;proxy_connect_timeout 1s;proxy_pass backend;}
}# 这段配置是一个nginx的stream模块的配置,用于代理TCP和UDP流量。
# 
# 首先,`worker_processes 1;`表示启动一个worker进程用于处理流量。
# 接下来,`events { worker_connections 1024; }`表示每个worker进程可以同时处理最多1024个连接。
# 在stream块里面,定义了一个名为`backend`的upstream,用于负载均衡和故障转移。
# `least_conn`表示使用最少连接算法进行负载均衡。
# `hash $remote_addr consistent`表示用客户端的IP地址进行哈希分配请求,保持相同IP的请求始终访问同一台服务器。
# `server`指令用于定义后端的服务器,每个服务器都有一个IP地址和端口号,以及一些可选的参数。
# `max_fails=3`表示当一个服务器连续失败3次时将其标记为不可用。
# `fail_timeout=30s`表示如果一个服务器被标记为不可用,nginx将在30秒后重新尝试。
# 在server块内部,定义了一个监听地址为127.0.0.1:8443的服务器。
# `proxy_connect_timeout 1s`表示与后端服务器建立连接的超时时间为1秒。
# `proxy_pass backend`表示将流量代理到名为backend的上游服务器组。
# 
# 总结起来,这段配置将流量代理到一个包含3个后端服务器的上游服务器组中,使用最少连接算法进行负载均衡,并根据客户端的IP地址进行哈希分配请求。如果一个服务器连续失败3次,则将其标记为不可用,并在30秒后重新尝试。# keepalive 配置
# cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak
cat > /etc/keepalived/keepalived.conf << EOF
! Configuration File for keepalived# 内容如下
global_defs {notification_email {acassen@firewall.locfailover@firewall.locsysadmin@firewall.loc}notification_email_from weihengtest@firewall.locsmtp_server 127.0.0.1smtp_connect_timeout 30router_id NGINX_MASTER
}
vrrp_script check_nginx {script "/etc/keepalived/check_nginx.sh"
}
vrrp_instance VI_1 {state MASTER# 修改为实际网卡名interface ens160 virtual_router_id 51 # VRRP 路由 ID 实例,每个实例是唯一的priority 80 #优先级,备服务器设置 90、80advert_int 1 #指定 VRRP 心跳包通告间隔时间,默认1秒authentication {auth_type PASSauth_pass 1111}#  虚拟  IPvirtual_ipaddress {192.168.86.199/24}track_script {check_nginx}
}
EOF
# vrrp_script :指定检查 nginx  工作状态脚本(根据 nginx  状态判断是否故障转移)
# virtual_ipaddress :虚拟IP(VIP)# 配置检查脚本
cat > /etc/keepalived/check_nginx.sh << "EOF"
#!/bin/bash
count=$(ps -ef |grep nginx | grep sbin | egrep -cv "grep|$$")
if [ "$count" -eq 0 ];thenecho "systemctl stop keepalived"systemctl stop keepalived
fi
EOF
# 授权
chmod +x /etc/keepalived/check_nginx.sh# 启动服务
systemctl daemon-reload
systemctl start nginx && systemctl start keepalived && systemctl enable nginx keepalived
# 查看
systemctl status keepalivedsystemctl restart nginx && systemctl start keepalived

测试vip 是否绑定成功
在这里插入图片描述

2.2.1 测试 keepalived

停掉master1服务器的nginx,IP漂移到了master2
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
重新启动master1 的nginx 和 keepalived,IP又重新回到了master1,master2上的192.168.86.199消失了

systemctl start nginx && systemctl start keepalived
在这里插入图片描述

2.3 使用 kubeadm 初始化k8s集群

参考文档:https://kubernetes.io/zh-cn/docs/reference/config-api/kubeadm-config.v1beta3/#kubeadm-k8s-io-v1beta3-ClusterConfiguration

在 weihengmaster1 上创建 kubeadm-config.yaml

vim kubeadm-config.yaml
# 内容如下
apiVersion: kubeadm.k8s.io/v1beta4
kind: InitConfiguration
nodeRegistration:criSocket: unix:///var/run/cri-dockerd.socktaints: []
---  
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
kubernetesVersion: v1.31.0
controlPlaneEndpoint: 192.168.86.199:16443
imageRepository: registry.k8s.io
pauseImage: registry.k8s.io/pause:3.10
#imageRepository: registry.aliyuncs.com/google_containers
apiServer:certSANs:- 192.168.86.101- 192.168.86.102- 192.168.86.103- 192.168.86.199
networking:podSubnet: 10.244.0.0/16serviceSubnet: 10.10.0.0/16
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs#使用 kubeadm 初始化 k8s 集群
#配置文件中已经添加了podSubnet 初始化时不需要再指定CIDR --pod-network-cidr
kubeadm init --config kubeadm-config.yaml --ignore-preflight-errors=SystemVerification# 初始化完毕后提示如下信息:
[root@weihengmaster1 yaml]# kubeadm init --config kubeadm-config.yaml --ignore-preflight-errors=SystemVerification
W0819 11:06:23.675801   65456 initconfiguration.go:332] error unmarshaling configuration schema.GroupVersionKind{Group:"kubeadm.k8s.io", Version:"v1beta4", Kind:"ClusterConfiguration"}: strict decoding error: unknown field "pauseImage"
[init] Using Kubernetes version: v1.31.0
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action beforehand using 'kubeadm config images pull'
W0819 11:06:23.877235   65456 checks.go:846] detected that the sandbox image "registry.aliyuncs.com/google_containers/pause:3.9" of the container runtime is inconsistent with that used by kubeadm.It is recommended to use "registry.k8s.io/pause:3.10" as the CRI sandbox image.
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local weihengmaster1] and IPs [10.10.0.1 192.168.86.101 192.168.86.199 192.168.86.102 192.168.86.103]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [localhost weihengmaster1] and IPs [192.168.86.101 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [localhost weihengmaster1] and IPs [192.168.86.101 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
W0819 11:06:26.509456   65456 endpoint.go:57] [endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address
[kubeconfig] Writing "admin.conf" kubeconfig file
W0819 11:06:26.659190   65456 endpoint.go:57] [endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address
[kubeconfig] Writing "super-admin.conf" kubeconfig file
W0819 11:06:26.831919   65456 endpoint.go:57] [endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address
[kubeconfig] Writing "kubelet.conf" kubeconfig file
W0819 11:06:27.072574   65456 endpoint.go:57] [endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
W0819 11:06:27.154376   65456 endpoint.go:57] [endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests"
[kubelet-check] Waiting for a healthy kubelet at http://127.0.0.1:10248/healthz. This can take up to 4m0s
[kubelet-check] The kubelet is healthy after 1.001501701s
[api-check] Waiting for a healthy API server. This can take up to 4m0s
[api-check] The API server is healthy after 31.076338846s
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node weihengmaster1 as control-plane by adding the labels: [node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers]
[bootstrap-token] Using token: ont7fm.zuejdf6esu3dndvf
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
W0819 11:07:01.130325   65456 endpoint.go:57] [endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address
[addons] Applied essential addon: kube-proxyYour Kubernetes control-plane has initialized successfully!To start using your cluster, you need to run the following as a regular user:mkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/configAlternatively, if you are the root user, you can run:export KUBECONFIG=/etc/kubernetes/admin.confYou should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:https://kubernetes.io/docs/concepts/cluster-administration/addons/You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:kubeadm join 192.168.86.199:16443 --token ont7fm.zuejdf6esu3dndvf \--discovery-token-ca-cert-hash sha256:c2db25caebdb3de354eeec4b3c80cf5f6baa13d9aad7d590a52bd32eb3d1ede3 \--control-plane Then you can join any number of worker nodes by running the following on each as root:kubeadm join 192.168.86.199:16443 --token ont7fm.zuejdf6esu3dndvf \--discovery-token-ca-cert-hash sha256:c2db25caebdb3de354eeec4b3c80cf5f6baa13d9aad7d590a52bd32eb3d1ede3 
[root@weihengmaster1 yaml]# # 下面命令是把 master  节点加入集群 ,需要保存下来,每个人的都不一样kubeadm join 192.168.86.199:16443 --token ont7fm.zuejdf6esu3dndvf \--discovery-token-ca-cert-hash sha256:c2db25caebdb3de354eeec4b3c80cf5f6baa13d9aad7d590a52bd32eb3d1ede3 \--control-plane \--cri-socket unix:///var/run/cri-dockerd.sock
# 下面命令是把 node  节点加入集群 ,需要保存下来
kubeadm join 192.168.86.199:16443 --token ont7fm.zuejdf6esu3dndvf \--discovery-token-ca-cert-hash sha256:c2db25caebdb3de354eeec4b3c80cf5f6baa13d9aad7d590a52bd32eb3d1ede3 #配置kubectl的配置文件 config,相当于对kubectl 进行授权,这样kubectl命令可以使用这个证书对k8s集群进行管理
[root@weihengmaster1 yaml]# mkdir -p $HOME/.kube
[root@weihengmaster1 yaml]# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[root@weihengmaster1 yaml]# sudo chown $(id -u):$(id -g) $HOME/.kube/config
[root@weihengmaster1 yaml]# kubectl get nodes
NAME             STATUS     ROLES           AGE    VERSION
weihengmaster1   NotReady   control-plane   3m2s   v1.31.0
[root@weihengmaster1 yaml]#
# 此时集群状态还是 NotReady 状态,因为没有安装网络插件 

在这里插入图片描述

2.4 扩容k8s集群

2.4.1 添加 master 节点

#创建证书存放目录 - 所有master和worker都执行
cd /root && mkdir -p /etc/kubernetes/pki/etcd &&mkdir -p ~/.kube/
#将配置拷贝到master2、master3、node1、node2
scp -r /root/.kube weihengmaster3:/root/#把 master1 节点的证书拷贝到 master2、master3 上 
scp /etc/kubernetes/pki/ca.crt weihengmaster2:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/ca.key weihengmaster2:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/sa.key weihengmaster2:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/sa.pub weihengmaster2:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/front-proxy-ca.crt weihengmaster2:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/front-proxy-ca.key weihengmaster2:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/etcd/ca.crt weihengmaster2:/etc/kubernetes/pki/etcd/
scp /etc/kubernetes/pki/etcd/ca.key weihengmaster2:/etc/kubernetes/pki/etcd/scp /etc/kubernetes/pki/ca.crt weihengmaster3:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/ca.key weihengmaster3:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/sa.key weihengmaster3:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/sa.pub weihengmaster3:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/front-proxy-ca.crt weihengmaster3:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/front-proxy-ca.key weihengmaster3:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/etcd/ca.crt weihengmaster3:/etc/kubernetes/pki/etcd/
scp /etc/kubernetes/pki/etcd/ca.key weihengmaster3:/etc/kubernetes/pki/etcd/#证书拷贝之后在 master2、master3 上执行如下命令
#kubeadm token create --print-join-commandkubeadm join 192.168.86.199:16443 --token ont7fm.zuejdf6esu3dndvf \--discovery-token-ca-cert-hash sha256:c2db25caebdb3de354eeec4b3c80cf5f6baa13d9aad7d590a52bd32eb3d1ede3 \--control-plane \--cri-socket unix:///var/run/cri-dockerd.sock

在这里插入图片描述
检查
在这里插入图片描述

2.4.2 添加node节点

kubeadm join 192.168.86.199:16443 --token ont7fm.zuejdf6esu3dndvf \--discovery-token-ca-cert-hash sha256:c2db25caebdb3de354eeec4b3c80cf5f6baa13d9aad7d590a52bd32eb3d1ede3 \--cri-socket unix:///var/run/cri-dockerd.sock

在这里插入图片描述
在这里插入图片描述

#把角色调整下
kubectl label node weihengnode1 node-role.kubernetes.io/worker=worker

在这里插入图片描述
上面状态都是 NotReady 状态,是因为还没有安装网络插件

2.5 安装 kubernetes 网络插件 - Calico

参考文章:https://docs.tigera.io/calico/latest/getting-started/kubernetes/quickstart

#安装calico网络插件 - 这个yaml可以下载下来
[root@weihengmaster1 ~]# kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
#这个yaml可以下载下来
#kubectl apply -f calico.yaml
#kubectl delete -f <calico.yaml>kubectl get pods -n kube-system

在这里插入图片描述
在这里插入图片描述

2.6 测试在集群上创建pod,网络是否正常

[root@weihengnode1 ~]# docker pull busybox
[root@weihengnode1 ~]# kubectl run busybox --image busybox --restart=Never --rm -it busybox  -- sh
If you don't see a command prompt, try pressing enter.
/ # ping www.baidu.comPING www.baidu.com (103.235.46.96): 56 data bytes

2.7 测试集群中部署 tomcat 服务

创建一个tomcat的pod,再创建一个service对象将端口暴露出去
kubectl apply -f tomcat.yaml
kubectl apply -f tomcat-service.yaml
在这里插入图片描述
测试 → 宿主机访问vmware的K8S集群 → 测试OK
在这里插入图片描述
OK,就到这里了

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

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

相关文章

SIRA-PCR: Sim-to-Real Adaptation for 3D Point Cloud Registration 论文解读

目录 一、导言 二、 相关工作 1、三维点云配准工作 2、无监督域适应 三、SIRA-PCR 1、FlyingShape数据集 2、Sim-to-real自适应方法 3、配准 4、损失函数 一、导言 该论文来自于ICCV2023&#xff0c;论文提出了一种新的方法SIRA-PCR&#xff0c;通过利用合成数据Flying…

网易云音乐故障 2 小时,这次到底谁背锅?(今天记得领补偿)

大家好&#xff0c;我是程序员鱼皮&#xff0c;8 月 19 日下午&#xff0c;网易云音乐突发严重故障&#xff0c;并登顶微博热搜&#xff0c;跟黑神话悟空抢了热度。 根据用户的反馈&#xff0c;故障的具体表现为&#xff1a;用户无法登录、歌单加载失败、播放信息获取失败、无法…

了解数据库中常用存储引擎数据结构(2)

目录 深入了解B树及其变种 BTree BTree B*Tree BTree并发机制 B-Link Tree 深入了解B树及其变种 先把我们要解释的B树变种都列出来&#xff0c;B树的变种主要有B树、B*树、B-Link树、COW B树、惰性B树、Bw树等。 下面具体来分析这些变种的优势和发展趋势。 BTree 下图…

Taro+Vue 创建微信小程序

TaroVue 创建微信小程序 一、全局安装 tarojs/cli二、项目初始化三、现在去启动项目吧 一、全局安装 tarojs/cli npm install -g tarojs/cli //安装 npm info tarojs/cli //查看安装信息 如果正常显示版本说明成功了&#xff0c;就直接跳到第二步吧官网说&#xff1a;…

AI产品经理如何入门?零基础入门到精通,收藏这一篇就够了

现在做产品经理&#xff0c;真的挺累的。 现在产品越来越难做&#xff0c;晋升困难&#xff0c;工资迟迟不涨……公司裁员&#xff0c;产品经理首当其冲&#xff01;&#xff01; 做产品几年了&#xff0c;还没升职&#xff0c;就先到了“职业天花板”。 想凭工作几年积累的…

BFS解决单源最短路问题

目录 迷宫中离入口最近的出口 最小基因变化 单词接龙 为高尔夫比赛砍树 迷宫中离入口最近的出口 题目 思路 使用宽度优先遍历解决这道题&#xff0c;需要一个二维数组标记是否被遍历过&#xff0c;也需要一个队列辅助完成宽度优先遍历&#xff0c;类似于水波纹一样&#x…

JAVA基础:File类

目录 前言 file对象的创建 file的常用方法 前言 file类表示的是系统中的一个文件或者文件夹 file类和系统中的文件或者文件夹不需要是一一对应的&#xff0c;我们可以在file类中写你系统中不存在的文件或文件夹 file类中存储的实际上是文件或文件夹的抽象路径&#xff0c…

面试经典算法150题系列-最长公共前缀

最长公共前缀 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀&#xff0c;返回空字符串 ""。 示例 1&#xff1a; 输入&#xff1a;strs ["flower","flow","flight"] 输出&#xff1a;"fl"示例 2&…

软件测试 - 自动化测试(概念)(Java)(自动化测试分类、web自动化测试、驱动、selenium自动化测试工具的安装)

一、自动化的概念 ⾃动洒⽔机&#xff0c;主要通上⽔就可以⾃动化洒⽔并且可以⾃动的旋转。 ⾃动洗⼿液&#xff0c;免去了⼿动挤压可以⾃动感应出洗⼿液 超市⾃动闸⻔&#xff0c;不需要⼿动的开⻔关⻔ ⽣活中的⾃动化案例有效的减少了⼈⼒的消耗&#xff0c;同时也提⾼了⽣…

C语言程序设计(初识C语言后部分)

代码是一门艺术&#xff0c;键盘是我的画笔。 3.递归和迭代&#xff08;循环就是一种迭代&#xff0c;迭代不仅仅是循环&#xff09; 求n&#xff01; 递归方式&#xff1a; n!---> 1 (n1); n*(n-1)! (n>1) #include <stdio.h> //n!-->递归方式 int fac(in…

Kafka运行机制(一):Kafka集群启动,controller选举,生产消费流程

前置知识 Kafka基本概念https://blog.csdn.net/dxh9231028/article/details/141270920?spm1001.2014.3001.5501 1. Kafka集群启动 Kafka在启动集群中的各个broker时&#xff0c;broker会向controller注册自己&#xff0c;并且从controller节点同步集群元数据。 broker是Kaf…

C++入门——16C++11新特性

1.列表初始化 初始化列表时&#xff0c;可添加等号()&#xff0c;也可不添加。 struct Point {int _x;int _y; };int main() {int x1 1;int x2{ 2 };int array1[]{ 1, 2, 3, 4, 5 };int array2[5]{ 0 };Point p{ 1, 2 };// C11中列表初始化也可以适用于new表达式中int* pa …

jstack结果提取特定线程池线程的堆栈

这里假设你已经知道如何定位java进程PID&#xff0c;以及如何执行jstack命令进行导出&#xff0c;下面仅提供相关命令&#xff0c;及示例 ps aux|grep java jstack 8229 > jstack_output.log v1版本 grep second jstack_output.log 如果此时我们想重点关注一下下面这个线程…

高性价比全屋智能家居解决方案,提升生活幸福感!

在快节奏的城市生活中&#xff0c;公司、住宅两点一线的上班族不在少数。近年来&#xff0c;随着物联网、大数据技术的不断发展与5G的广泛普及&#xff0c;生活品质的提升成为上班族新的关注焦点。忙碌的工作时间结束后&#xff0c;智慧家居系统打造便捷、安全、智能、舒适的居…

(javaweb)SpringBootWeb案例(毕业设计)案例--部门管理

目录 1.准备工作 2.部门管理--查询功能 3.前后端联调 3.部门管理--新增功能 1.准备工作 mapper数据访问层相当于dao层 根据页面原型和需求分析出接口文档--前后端必须遵循这种规范 大部分情况下 接口文档由后端人员来编写 前后端进行交互基于restful风格接口 http的请求方式…

文书智能助手

背景 司法、医疗等行业存在着大量的文书&#xff0c;一份文书或者卷宗少则几十页&#xff0c;多则几万页。在查看和检查这些文书时&#xff0c;会遇到大量的信息。当需要查询进一步的详细内容时&#xff0c;往往需要选择一下文字&#xff0c;然后再在各种系统中 查询详细的信息…

日拱一卒(4)——leetcode学习记录:路径总和

一、任务&#xff1a; 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 叶…

二叉树(四)

一、二叉树的性质 二、练习 1.某二叉树共有399个节点&#xff0c;其中有199个度为2的节点&#xff0c;则二叉树中的叶子节点数为&#xff08; &#xff09;。 A.不存在这样的树 B.200 C.198 D.199 答案&#xff1a;B 参考二叉树的性质第三条 2.在具有2…

【Hadoop】核心组件深度剖析:HDFS、YARN与MapReduce的奥秘

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《大数据前沿&#xff1a;技术与应用并进》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、Hadoop简介 2、Hadoop生态系统概览 二、Hadoo…

如何做萤石开放平台的物联网卡定向?

除了用萤石自带的4G卡外&#xff0c;我们也可以自己去电信、移动和联通办物联网卡连接萤石云平台。 1、说在前面 注意&#xff1a;以下流程必须全部走完&#xff0c;卡放在设备上才能连接到萤石云平台。 2、大致流程 登录官网→下载协议→盖章&#xff08;包括骑缝章&#…