kubeadm安装k8s 1.26集群

安装准备步骤

  • 修改机器IP,变成静态IP (云主机无需配置这个)
vim /etc/sysconfig/network-scripts/ifcfg-ens33
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static #static表示静态ip地址
IPADDR=192.168.40.180 #ip地址,需要跟自己电脑所在网段一致
NETMASK=255.255.255.0  #子网掩码,需要跟自己电脑所在网段一致
GATEWAY=192.168.40.2 #网关,在自己电脑打开cmd,输入ipconfig /all可看到
DNS1=192.168.40.2 #DNS,在自己电脑打开cmd,输入ipconfig /all可看到 
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33 #网卡名字,跟DEVICE名字保持一致即可
DEVICE=ens33 #网卡设备名,大家ip addr可看到自己的这个网卡设备名,每个人的机器可能这个名字不一样,需要写自己的
ONBOOT=yes #开机自启动网络,必须是yes

#修改配置文件之后需要重启网络服务才能使配置生效,重启网络服务命令如下:
service network restart
  • 关闭selinux
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config #修改selinux配置文件之后,重启机器,selinux配置才能永久生效
reboot -f
getenforce #显示Disabled说明selinux已经关闭
  • 修改hostname
hostnamectl set-hostname master-01 && bash
hostnamectl set-hostname node-01 && bash
  • 配Hosts文件
#修改每台机器的/etc/hosts文件,增加如下三行:
192.168.40.4 master-01
192.168.40.5 node-01
192.168.40.6 node-02
  • 配主机间无密码登录
passwd root #设一个root密码
ssh-keygen #一路回车
ssh-copy-id master-01 #输入root密码
ssh-copy-id node-01
#在另外两台上也执行同样操作#
  • 升级系统,7.6 - 7.9
yum update -y
cat /etc/redhat-release
#CentOS Linux release 7.9.2009 (Core)
  • 安装基础软件包
yum install -y 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 ntp libaio-devel wget vim ncurses-devel autoconf automake zlib-devel  python-devel epel-release openssh-server socat  ipvsadm conntrack telnet ipvsadm
  • 配置时间同步
#安装ntpdate命令
yum install ntpdate -y
#跟网络时间做同步
ntpdate cn.pool.ntp.org
#把时间同步做成计划任务
crontab -e
* */1 * * * /usr/sbin/ntpdate   cn.pool.ntp.org
#重启crond服务
service crond restart
  • 关闭交换分区
#临时关闭
swapoff -a
#永久关闭:注释掉fatab的swap挂载
vim /etc/fstab
#/dev/mapper/centos-swap swap      swap    defaults        0 0
  • 修改内核参数,开路由转发
modprobe br_netfilter 
echo "modprobe br_netfilter" >> /etc/profile
cat > /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1 
EOF
sysctl -p /etc/sysctl.d/k8s.conf 
  • 禁用firewalld防火墙
systemctl stop firewalld && systemctl disable firewalld
  • 配置阿里云的repo源
#安装rzsz命令
yum install lrzsz -y
#安装scp:
yum install -y openssh-clients
#备份基础repo源
mkdir /root/repo.bak
cd /etc/yum.repos.d/
mv * /root/repo.bak/
#下载阿里云的repo源
###注意:用GLobalAzure的VM就不需要这面手动修改源了,用自带的源即可###
#把CentOS-Base.repo和epel.repo文件上传到master1主机的/etc/yum.repos.d/目录下
chmod o+w /etc/yum.repos.d
#通过vscode拖进来
  • 配置阿里云docker的repo源
yum install yum-utils -y
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 
#会把阿里云的docker源的配置给拉下来。
  • 配置安装k8s组件的阿里云repo源
cat >  /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0
EOF

安装k8s组件

安装containerd并配置

yum install containerd.io-1.6.6 -y #1.27也是用这个版本
#生成 containerd 的配置文件:
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml

#修改配置文件,1.26和1.27配置一样
#SystemdCgroup = true表示containerd驱动用systemd,在 Kubernetes 中,容器运行时需要与宿主机的 cgroup 和 namespace 进行交互,以管理容器的资源。
#对于 cgroup 的驱动程序,Docker 和 Containerd 默认都使用的是 cgroupfs。#systemd-cgroup 则是 Systemd 对 cgroup 的一个实现。
#相比 cgroupfs,systemd-cgroup 在资源隔离方面提供了更好的性能和更多的特性。例如,systemd-cgroup 可以使用更多的内存压缩算法,以便更有效地使用内存。此外,systemd-cgroup 还提供了更好的 cgroup 监控和控制机制,可以更精确地调整容器的资源使用量。总之,使用 systemd-cgroup 作为容器运行时的 cgroup 驱动程序,可以提高 Kubernetes 集群中容器的资源管理效率,从而提升整个集群的性能。

#将sandbox_image设置为阿里云镜像仓库中的pause:3.7,在 Kubernetes 中,每个 Pod 中都有一个 pause 容器,这个容器不会运行任何应用,只是简单地 sleep。它的作用是为了保证 Pod 中所有的容器共享同一个网络命名空间和 IPC 命名空间。pause 容器会在 Pod 的初始化过程中首先启动,然后为 Pod 中的其他容器创建对应的网络和 IPC 命名空间,并且在其他容器启动之前保持运行状态,以保证其他容器可以加入到共享的命名空间中。
#简单来说,pause 容器就是一个占位符,它为 Pod 中的其他容器提供了一个共享的环境,使它们可以共享同一个网络和 IPC 命名空间。这也是 Kubernetes 实现容器间通信和网络隔离的重要机制之一。
vim /etc/containerd/config.toml
SystemdCgroup = false ==> SystemdCgroup = true
sandbox_image = "k8s.gcr.io/pause:3.6" ==> sandbox_image="registry.aliyuncs.com/google_containers/pause:3.7"

#配置 containerd 开机启动,并启动 containerd
systemctl enable containerd --now

#修改/etc/crictl.yaml文件,指定k8s的运行时和拉取镜像都使用containerd
#这个文件是 crictl 工具的配置文件,用于指定与 containerd 交互的相关设置:
#指定unix:///run/containerd/containerd.sock 是为了告诉 crictl 使用 Unix 域套接字的方式来连接 containerd 的 API。containerd 提供了一个 socket 文件 /run/containerd/containerd.sock,crictl 通过连接该 socket 文件,可以与 containerd 进行通信,管理容器和镜像等操作。
#runtime-endpoint:指定 containerd 的运行时接口地址:crictl 可以与 containerd 通信来管理容器生命周期和资源隔离。
#image-endpoint:指定 containerd 的镜像接口地址:以便 crictl 可以与 containerd 通信来管理镜像的拉取和推送。
#timeout:指定 crictl 等待 containerd 响应的最大时间,避免出现无响应的情况。
#debug:开启或关闭 crictl 的调试模式,方便排查问题。

cat > /etc/crictl.yaml <<EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF
systemctl restart containerd

#配置containerd镜像加速器,k8s所有节点均按照以下配置:
mkdir /etc/containerd/certs.d/docker.io/ -p
vim /etc/containerd/certs.d/docker.io/hosts.toml
#写入如下内容:
[host."https://docker.m.daocloud.io"]
  capabilities = ["pull"]

vim /etc/containerd/config.toml
config_path = "" ==> config_path = "/etc/containerd/certs.d"
#保存退出
systemctl restart containerd

安装docker并配置

#docker也要安装,docker跟containerd不冲突,安装docker是为了能基于dockerfile构建镜像
yum install docker-ce -y
systemctl enable docker --now

#配置docker镜像加速器,k8s所有节点均按照以下配置
vim /etc/docker/daemon.json
{
 "registry-mirrors":["https://docker.m.daocloud.io"]
} 

#重启docker:
systemctl daemon-reload && systemctl restart docker && systemctl status docker

安装初始化k8s需要的软件包

yum install -y kubelet-1.26.0 kubeadm-1.26.0 kubectl-1.26.0 #1.27版本就装1.27.0的工具包
systemctl enable kubelet

初始化集群

  • 设置容器运行时
crictl config runtime-endpoint unix:///run/containerd/containerd.sock
#这个在先前/etc/crictl.yaml中已经配置过了
  • 使用kubeadm初始化k8s集群
#在控制节点上
cd /root/
kubeadm config print init-defaults > kubeadm.yaml
#根据我们自己的需求修改配置,比如修改 imageRepository 的值,kube-proxy 的模式为 ipvs,需要注意的是由于我们使用的containerd作为运行时,所以在初始化节点的时候需要指定cgroupDriver为systemd
  • kubeadm.yaml配置文件如下:
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 192.168.40.4 #控制节点的ip
  bindPort: 6443
nodeRegistration:
  criSocket: unix:///run/containerd/containerd.sock ##指定containerd容器运行时
  imagePullPolicy: IfNotPresent
  name: master-01 #控制节点主机名
  taints: null
---
apiServer:
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers #registry.k8s.io #这是kubeadm安装控制节点组件时用的镜像源
kind: ClusterConfiguration
kubernetesVersion: 1.26.0 #这里的版本要和kubeadm\kubectl\kubelet的版本一致
networking:
  dnsDomain: cluster.local
  podSubnet: 10.244.0.0/16 #指定pod网段
  serviceSubnet: 10.96.0.0/12
scheduler: {}

---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs

---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd

kubeadm.yaml文件参数解释

  • localAPIEndpoint: Kubernetes API Server 监听的地址和端口。

  • advertiseAddress: 指定控制节点的 IP 地址,即 API Server 暴露给集群内其他节点的地址。

  • bindPort: 指定 API Server 监听的端口,默认为 6443。

  • nodeRegistration: 控制节点的注册信息。

  • criSocket: 指定容器运行时使用的 CRI Socket,即容器与 Kubernetes API Server 之间的通信通道。这里指定为 Containerd 的 Socket 地址。

  • imagePullPolicy: 指定容器镜像拉取策略,这里指定为如果本地已有镜像则不拉取。

  • name: 控制节点的主机名

  • taints: 控制节点的 taints,即节点的标记,用于限制哪些 Pod 可以调度到该节点。这里指定为空,即不对 Pod 的调度进行限制。

  • podSubnet\ServiceSubnet

  • 在Kubernetes集群中,每个Pod都会被分配一个IP地址,这些IP地址需要从一个预定义的IP地址池中分配。 podSubnet参数用于指定Pod IP地址池的范围,它定义了Pod的IP地址范围,例如10.244.0.0/16表示IP地址从10.244.0.1到10.244.255.255。

  • 同样地,Kubernetes服务(Service)也会被分配一个IP地址,用于暴露Kubernetes服务的端口。 serviceSubnet参数用于指定Service IP地址池的范围,它定义了Service的IP地址范围,例如10.96.0.0/12表示IP地址从10.96.0.1到10.111.255.255。
  • 上传并解压K8s组件镜像离线包
#解压
ctr -n=k8s.io images import k8s_1.26.0.tar.gz
#ctr是containerd自带的工具,有命名空间的概念,若是k8s相关的镜像,都默认在k8s.io这个命名空间,所以导入镜像时需要指定命令空间为k8s.io
#crictl是k8s中CRI(容器运行时接口)的客户端,k8s使用该客户端和containerd进行交互
#查看镜像
crictl images 
#或者
ctr -n=k8s.io image ls
  • 初始化集群
kubeadm init --config=kubeadm.yaml --ignore-preflight-errors=SystemVerification
#配置kubectl的配置文件config,相当于对kubectl进行授权,这样kubectl命令可以使用这个证书对k8s集群进行管理
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

#1. 设置kubectl的alias为k:
whereis kubectl # kubectl: /usr/bin/kubectl
echo "alias k=/usr/bin/kubectl">>/etc/profile
source /etc/profile
#2. 设置alias的自动补全:
source <(kubectl completion bash | sed 's/kubectl/k/g')
#3. 解决每次启动k都会失效,要重新刷新环境变量(source /etc/profile)的问题:在~/.bashrc文件中添加以下代码:source /etc/profile
echo "source /etc/profile" >> ~/.bashrc
#4. 给alias k也配置补全
tee -a ~/.bashrc <<'EOF'
alias k='kubectl'
complete -o default -F __start_kubectl k
source <(kubectl completion bash)
EOF
##使命令生效
source ~/.bashrc

扩容工作节点

kubeadm token create --print-join-command
#在node-01上加参数 --ignore-preflight-errors=SystemVerification
#工作节点打标签
kubectl label nodes node-01 node-role.kubernetes.io/work=worker

mkdir -p $HOME/.kube
#master-01的kubectl的config文件拷到node1上
scp $HOME/.kube/config node-01:/root/.kube/

安装calico

#上传了Caclio.yaml
kubectl apply -f calico.yaml
#在线下载地址为:https://docs.projectcalico.org/manifests/calico.yaml
#验证calico功能
kubectl run busybox --image docker.io/library/busybox:1.28  --image-pull-policy=IfNotPresent --restart=Never --rm -it busybox -- sh
#ping外网
ping www.baidu.com
#nslookup svc
nslookup kubernetes.default.svc.cluster.local

扩容控制节点

  • 准备步骤和master-01的步骤一样。

  • 装好kuneadm之后,需要额外执行的步骤:

  • 拷贝证书

#把master-01节点的证书拷贝到master-02
#在master2创建证书存放目录:
cd /root && mkdir -p /etc/kubernetes/pki/etcd &&mkdir -p ~/.kube/

#把master-01节点的证书拷贝到master-02上:
scp /etc/kubernetes/pki/ca.crt master2:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/ca.key master2:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/sa.key master2:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/sa.pub master2:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/front-proxy-ca.crt master2:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/front-proxy-ca.key master2:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/etcd/ca.crt master2:/etc/kubernetes/pki/etcd/
scp /etc/kubernetes/pki/etcd/ca.key master2:/etc/kubernetes/pki/etcd/
  • master-01的kubeadm-config ConfigMap 配置controlPlaneEndpoint
kubectl -n kube-system edit cm kubeadm-config -o yaml
#在apiversion字段平行下面添加如下字段:
controlPlaneEndpoint: 192.168.40.4:6443 #是master-01的ip
systemctl restart kubelet
- 这里有个问题:master-01上面的configMap两个字段controlPlaneEndpoint和localAPIEndpoint:advertiseAddress都写的是master-01自己的,那么两台master如何做到负载均衡?如果关掉master-01,master-02会接收到流量吗?
  • kubeadm join
#join命令添加参数:--control-plane --ignore-preflight-errors=SystemVerification

etcd高可用配置

  • kubeadm安装的多master集群中,可以将etcd做成高可用集群

  • 在所有master节点上:

vim /etc/kubernetes/manifests/etcd.yaml
- --initial-cluster=master1=https://192.168.40.180:2380
变成如下:
- --initial-cluster=master1=https://192.168.40.180:2380,master2=https://192.168.40.181:2380,master3=https://192.168.40.183:2380
  • 修改成功之后重启kubelet:
systemctl restart kubelet
  • 测试etcd集群是否配置成功:
docker run --rm -it --net host -v /etc/kubernetes:/etc/kubernetes  registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.5.4-0 etcdctl --cert /etc/kubernetes/pki/etcd/peer.crt --key /etc/kubernetes/pki/etcd/peer.key --cacert /etc/kubernetes/pki/etcd/ca.crt member list
docker run --rm -it --net host -v /etc/kubernetes:/etc/kubernetes  registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.5.4-0 etcdctl --cert /etc/kubernetes/pki/etcd/peer.crt --key /etc/kubernetes/pki/etcd/peer.key --cacert /etc/kubernetes/pki/etcd/ca.crt --endpoints=https://192.168.40.180:2379,https://192.168.40.181:2379,https://192.168.40.182:2379 endpoint health  --cluster

模拟剔除故障节点重新加入

  • K8s集群,公司里有3个控制节点和1个工作节点,有一个控制节点master1出问题关机了,修复不成功,然后我们kubectl delete nodes master1把master1移除,移除之后,我把机器恢复了,上架了,我打算还这个机器加到k8s集群,还是做控制节点,如何做?

  • 把master1这个机器的etcd从etcd集群删除(可以在master2上执行)

docker run --rm -it --net host -v /etc/kubernetes:/etc/kubernetes  registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.5.4-0 etcdctl --cert /etc/kubernetes/pki/etcd/peer.crt --key /etc/kubernetes/pki/etcd/peer.key --cacert /etc/kubernetes/pki/etcd/ca.crt --endpoints=https://192.168.40.181:2379,https://192.168.40.182:2379 member list
#拿到故障节点上的etcd的id。
  1. 通过如下命令:删除master1上的etcd
docker run --rm -it --net host -v /etc/kubernetes:/etc/kubernetes  registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.5.4-0 etcdctl --cert /etc/kubernetes/pki/etcd/peer.crt --key /etc/kubernetes/pki/etcd/peer.key --cacert /etc/kubernetes/pki/etcd/ca.crt --endpoints=https://192.168.40.181:2379,https://192.168.40.182:2379 member remove 75e64910a4405073
  1. 在master1上,创建存放证书目录
cd /root && mkdir -p /etc/kubernetes/pki/etcd &&mkdir -p ~/.kube/
  1. 把其他控制节点的证书拷贝到master1上
scp /etc/kubernetes/pki/ca.crt master1:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/ca.key master1:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/sa.key master1:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/sa.pub master1:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/front-proxy-ca.crt master1:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/front-proxy-ca.key master1:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/etcd/ca.crt master1:/etc/kubernetes/pki/etcd/
scp /etc/kubernetes/pki/etcd/ca.key master1:/etc/kubernetes/pki/etcd/
  1. 把master1加入到集群
#其他节点上查看加入集群的命令
kubeadm token create --print-join-command
#在master1上执行,使其加入集群。