984 字
5 分钟
搭建 Kubernetes 集群

最近需要搭个 k8s 集群做测试,用的是 kubeadm 部署方式。集群镜像从私有 Harbor 仓库拉取,Harbor 的搭建可以参考上一篇文章

环境规划#

主机IP用途
k8s-master192.168.100.20控制平面节点
k8s-node1192.168.100.21工作节点
k8s-node2192.168.100.22工作节点
harbor192.168.100.14私有镜像仓库

k8s 版本:v1.33.5
网络插件:Calico v3.31.0
容器运行时:containerd

系统初始化#

所有节点都需要执行以下操作。

关闭 swap#

Terminal window
swapoff -a
sed -i '/swap/s/^/#/' /etc/fstab

调整内核参数#

Terminal window
cat <<EOF > /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
sysctl --system

配置主机名和解析#

Terminal window
# 在 master 节点
hostnamectl set-hostname k8s-master
# 在 node1 节点
hostnamectl set-hostname k8s-node1
# 在 node2 节点
hostnamectl set-hostname k8s-node2
# 所有节点添加 hosts 解析
cat >> /etc/hosts <<EOF
192.168.100.20 k8s-master
192.168.100.21 k8s-node1
192.168.100.22 k8s-node2
192.168.100.14 reg.westos.org
EOF

配置 k8s yum 源#

Terminal window
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.33/rpm/
enabled=1
gpgcheck=0
EOF

配置 SSH 免密(可选)#

方便后续操作,写个脚本批量配置:

#!/bin/bash
USER="root"
PASSWORD="123"
PORT=22
HOSTS=(
192.168.100.20
192.168.100.21
192.168.100.22
)
[ ! -f ~/.ssh/id_rsa.pub ] && ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
for entry in "${HOSTS[@]}"; do
host="$entry"
port="$PORT"
[[ "$entry" == *:* ]] && host="${entry%%:*}" && port="${entry##*:}"
sshpass -p "$PASSWORD" ssh-copy-id -o StrictHostKeyChecking=no -p "$port" "$USER@$host"
done

配置 IPVS#

k8s 用 IPVS 做负载均衡,需要加载相关内核模块:

Terminal window
cat > /etc/modules-load.d/ipvs.conf <<EOF
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
overlay
br_netfilter
EOF
# 立即加载
modprobe ip_vs ip_vs_rr ip_vs_wrr ip_vs_sh nf_conntrack overlay br_netfilter
# 安装管理工具
dnf install -y ipvsadm ipset

安装 containerd#

所有节点安装:

Terminal window
yum install -y containerd.io cri-tools
containerd config default > /etc/containerd/config.toml
# 启用 systemd cgroup 驱动
sed -i 's#SystemdCgroup = false#SystemdCgroup = true#g' /etc/containerd/config.toml
systemctl enable --now containerd
# 配置 crictl
cat <<EOF > /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
EOF

配置 Harbor 证书#

让 containerd 信任 Harbor 的证书:

Terminal window
# 所有节点创建目录
mkdir -p /etc/containerd/certs.d/reg.westos.org
# 在 harbor 节点上,将证书复制到各节点
scp /etc/docker/certs.d/reg.westos.org/ca.crt 192.168.100.20:/etc/containerd/certs.d/reg.westos.org/
scp /etc/docker/certs.d/reg.westos.org/ca.crt 192.168.100.21:/etc/containerd/certs.d/reg.westos.org/
scp /etc/docker/certs.d/reg.westos.org/ca.crt 192.168.100.22:/etc/containerd/certs.d/reg.westos.org/
# 在所有 k8s 节点上,修改 containerd 配置
sed -i 's#config_path = ""#config_path = "/etc/containerd/certs.d"#g' /etc/containerd/config.toml
sed -i 's#registry.k8s.io/pause:3.8#reg.westos.org/k8s/pause:3.10#g' /etc/containerd/config.toml
systemctl restart containerd

准备镜像#

安装 k8s 组件#

所有节点安装:

Terminal window
yum install -y kubelet kubeadm kubectl
systemctl enable --now kubelet

查看需要的镜像#

Terminal window
kubeadm config images list --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.33.5

会列出这些镜像:

  • kube-apiserver.33.5
  • kube-controller-manager.33.5
  • kube-scheduler.33.5
  • kube-proxy.33.5
  • coredns.12.0
  • pause:3.10
  • etcd:3.5.21-0

推送镜像到 Harbor#

在 harbor 节点上拉取镜像并推送:

Terminal window
# 从阿里云拉取
docker pull registry.aliyuncs.com/google_containers/pause:3.10
docker pull registry.aliyuncs.com/google_containers/kube-apiserver:v1.33.5
docker pull registry.aliyuncs.com/google_containers/kube-controller-manager:v1.33.5
docker pull registry.aliyuncs.com/google_containers/kube-scheduler:v1.33.5
docker pull registry.aliyuncs.com/google_containers/kube-proxy:v1.33.5
docker pull registry.aliyuncs.com/google_containers/coredns:v1.12.0
docker pull registry.aliyuncs.com/google_containers/etcd:3.5.21-0
# 在 Harbor Web 界面创建 k8s 项目(设为公开)
# 批量打标签
docker images |grep google_containers | awk '{print $1":"$2}' | awk -F/ '{system("docker tag "$0" reg.westos.org/k8s/"$3"")}'
# 批量推送
docker images |grep reg.westos.org/k8s | awk '{system("docker push "$1":"$2"")}'

初始化 Master 节点#

在 k8s-master 上执行:

Terminal window
kubeadm init \
--pod-network-cidr=10.244.0.0/16 \
--image-repository reg.westos.org/k8s \
--kubernetes-version v1.33.5

初始化成功后会输出 join 命令,记下来给 node 节点用:

Terminal window
kubeadm join 192.168.100.20:6443 --token afmhpb.r5vcfet4ro49kg5i \
--discovery-token-ca-cert-hash sha256:69a36f40befb0f36e29c1afae2291be7ff652672ec730728aebb90b73f436192

配置 kubectl#

Terminal window
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
# 命令补全
echo "source <(kubectl completion bash)" >> ~/.bashrc
source ~/.bashrc

验证一下:

Terminal window
kubectl get nodes

此时 master 节点状态是 NotReady,因为还没装网络插件。

安装 Calico 网络插件#

准备 Calico 镜像#

在 harbor 节点上:

Terminal window
docker pull quay.io/calico/cni:v3.31.0
docker pull quay.io/calico/node:v3.31.0
docker pull quay.io/calico/kube-controllers:v3.31.0
# 在 Harbor Web 界面创建 calico 项目
# 打标签并推送
docker images |grep calico | awk '{print $1":"$2}' | awk -F/ '{system("docker tag "$0" reg.westos.org/calico/"$3"")}'
docker images |grep reg.westos.org/calico | awk '{system("docker push "$1":"$2"")}'

部署 Calico#

在 master 节点上:

Terminal window
wget https://raw.githubusercontent.com/projectcalico/calico/v3.31.0/manifests/calico.yaml
sed -i 's#quay.io/#reg.westos.org/#g' calico.yaml
kubectl apply -f calico.yaml

等待 calico pods 启动:

Terminal window
kubectl get pod -A |grep calico

全部 Running 后,再查看节点状态:

Terminal window
kubectl get node

master 节点应该变成 Ready 状态了。

加入 Worker 节点#

在 node1 和 node2 上执行之前保存的 join 命令:

Terminal window
kubeadm join 192.168.100.20:6443 --token afmhpb.r5vcfet4ro49kg5i \
--discovery-token-ca-cert-hash sha256:69a36f40befb0f36e29c1afae2291be7ff652672ec730728aebb90b73f436192

回到 master 节点查看:

Terminal window
kubectl get node

输出:

NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane 35m v1.33.5
k8s-node1 Ready <none> 2m v1.33.5
k8s-node2 Ready <none> 6m22s v1.33.5

全部 Ready,集群就搭好了。

常见问题#

遇到过几次镜像拉取失败的问题,排查下来是这几个原因:

  1. containerd 没配置 Harbor 证书路径
  2. Harbor 项目权限设为私有了(改成公开或配置 imagePullSecrets)
  3. 节点 /etc/hosts 没有 Harbor 域名解析

另外如果 token 过期了,可以在 master 上重新生成:

Terminal window
kubeadm token create --print-join-command
搭建 Kubernetes 集群
https://dev-null-sec.github.io/posts/搭建k8s集群/
作者
DevNull
发布于
2024-11-08
许可协议
CC BY-NC-SA 4.0