部署 Kubernetes 集群#

下载并安装 CentOS 7:http://isoredirect.centos.org/centos/7/isos/x86_64/

警告

以 3 个节点为例,创建集群:(一个 master 节点,两个 node 节点)

  • uname -m:集群内每个节点必须为 x86 架构(不支持 ARM 架构)。

  • lscpu:最少 2 核处理器。

  • free -mh:最小 2GB 内存。

  • vim /etc/hostname 修改 hostname,使集群内每个节点的 hostname 不同。

  • vim /etc/sysconfig/network-scripts/ifcfg-ens33:修改为静态 IP 地址。

  • vim /etc/hosts:配置主机名和 IP 地址映射,确保各节点 ping <hostname> 互通。

  • ip link:集群内每个节点的网络接口的 MAC 地址不同。

  • sudo cat /sys/class/dmi/id/product_uuid:集群内每个节点的 product_uuid 不同。

  • firewall-cmd --state:确保防火墙关闭。

  • sestatus:确保 SELinux 被禁止。

  • date:确保集群内各节点的时间保持一致。

确保网络通畅的——这听起来像是废话,但确实有相当一部分的云主机不对 SELinux、iptables、安全组、防火墙进行设置的话,内网各个节点之间、与外网之间会存在默认的访问障碍,导致部署失败。

初始化集群前的准备工作#

# 每台主机的名字不同
hostnamectl set-hostname master # 在主机 1 上操作
hostnamectl set-hostname node01 # 在主机 2 上操作
hostnamectl set-hostname node02 # 在主机 3 上操作

# 升级 Linux 内核到 5.4
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
yum -y install https://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm
yum --enablerepo="elrepo-kernel" -y install kernel-lt.x86_64
grub2-set-default 0
grub2-mkconfig -o /boot/grub2/grub.cfg
reboot
uname -r

# 同步时间
sudo systemctl stop chronyd
sudo systemctl disable chronyd
sudo yum install ntp ntpdate
sudo ntpdate ntp.aliyun.com
sudo rm -rf /etc/localtime
sudo ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

# 永久关闭Swap分区
yes | sudo cp /etc/fstab /etc/fstab_bak
sudo cat /etc/fstab_bak | grep -v swap > /etc/fstab

# 永久关闭防火墙,确保网络通畅
sudo systemctl stop firewalld
sudo systemctl disable firewalld
firewall-cmd --state

# 关闭 SELinux 防火墙
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config

# 允许 iptables 检查桥接流量
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

# 配置端口转发和网桥过滤
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
vm.swappiness                       = 0
EOF

# 应用 sysctl 参数而不重新启动
sudo sysctl --system

# 配置 IPVS
yum -y install ipset ipvsadm

cat > /etc/sysconfig/modules/ipvs.modules <<EOF
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack
EOF

chmod 755 /etc/sysconfig/modules/ipvs.modules
bash /etc/sysconfig/modules/ipvs.modules

安装容器运行时:Docker Engine#

删除 Docker 的旧版本#

sudo yum remove docker \
    docker-client \
    docker-client-latest \
    docker-common \
    docker-latest \
    docker-latest-logrotate \
    docker-logrotate \
    docker-engine

使用仓库安装 Docker#

sudo yum install -y yum-utils device-mapper-persistent-data lvm2

sudo yum-config-manager \
    --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

更新系统软件仓库#

sudo yum update

安装最新版的 Docker 引擎#

sudo yum makecache fast
sudo yum install docker-ce docker-ce-cli containerd.io
sudo service docker start

测试 Docker 是否安装成功#

sudo docker run hello-world

安装 cri-dockerd#

因为 K8s 1.24 及以上的版本移除了 dockershim,需要 cri-dockerd 才能初始化 K8s 集群。

# 安装 Go
wget https://go.dev/dl/go1.19.3.linux-amd64.tar.gz
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.19.3.linux-amd64.tar.gz
echo 'export PATH=$PATH:/usr/local/go/bin' >> /etc/profile
source /etc/profile

# 安装 cri-dockerd
git clone https://github.com/Mirantis/cri-dockerd.git
cd cri-dockerd
mkdir bin
go build -o bin/cri-dockerd
mkdir -p /usr/local/bin
sudo install -o root -g root -m 0755 bin/cri-dockerd /usr/local/bin/cri-dockerd
sudo cp -a packaging/systemd/* /etc/systemd/system
sudo sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service
sudo systemctl daemon-reload
sudo systemctl enable cri-docker.service
sudo systemctl enable --now cri-docker.socket

让 Docker 能够开机启动#

sudo systemctl enable docker
sudo systemctl start docker

安装 Docker-Compose#

sudo curl -L "https://get.daocloud.io/docker/compose/releases/download/v2.12.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

使用 kubeadm 创建生产集群#

安装 kubeadm、kubelet 和 kubectl#

cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF

sudo yum install -y --nogpgcheck kubelet kubeadm kubectl --disableexcludes=kubernetes

使 kubelet 与容器的运行时驱动保持一致#

# 修改 docker 的驱动
cat <<EOF | sudo tee /etc/docker/daemon.json
{
    "exec-opts": ["native.cgroupdriver=systemd"]
}
EOF

systemctl daemon-reload
systemctl restart docker

# 修改 kubelet 的驱动
echo 'KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"' > /etc/sysconfig/kubelet

systemctl enable --now kubelet

使 kubelet 开机启动#

systemctl start kubelet
systemctl enable kubelet

后续操作仅 master 节点需要运行#

初始化集群控制平面#

首先使用 kubeadm config print init-defaults > kubeadm-config.yaml 创建配置文件,并进行如下修改

apiVersion: kubeadm.k8s.io/v1beta3
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 192.168.163.139
bindPort: 6443
nodeRegistration:
criSocket: unix:///var/run/cri-dockerd.sock
imagePullPolicy: IfNotPresent
name: master
taints: null
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: master
controllerManager: {}
dns: {}
etcd:
local:
    dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: 1.25.4
networking:
dnsDomain: cluster.local
serviceSubnet: 10.96.0.0/12
scheduler: {}
---
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
cgroupDriver: systemd

之后进行初始化集群:

kubeadm init --config kubeadm-config.yaml

警告

如果出现下面的报错:

[ERROR CRI]: container runtime is not running

请尝试 rm /etc/containerd/config.tomlsystemctl restart containerd,然后重新运行 kubeadm init 命令。

为当前用户生成 kubeconfig#

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

安装 CNI 插件#

curl --insecure -sfL https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml | kubectl apply -f -

移除 master 节点上的污点#

kubectl taint nodes --all node-role.kubernetes.io/master-

启用 kubectl 的自动补全功能#

echo 'source <(kubectl completion bash)' >> ~/.bashrc
echo 'source /usr/share/bash-completion/bash_completion' >> ~/.bashrc

重新生成 token#

备注

把下面这条命令的输出,在需要加入当前集群的节点上运行一次,即可完成集群的横向扩展。

kubeadm token create --print-join-command

查看当前集群中节点的信息#

kubectl cluster-info
kubectl get nodes