记一次Kubernetes完整集群的搭建
写在前面
太好了孩子们 这次基本全都是命令行操作 我不用截图了
以下几乎全是命令 几乎一张图片没有 如果你想做为参考的话请仔细阅读每一行
前言
昨天我在折腾Authentik认证服务的时候 一直在思考用什么反代服务
常见的可以用Nginx Proxy Manager,Caddy,Traefik
这里面我觉得比较好用的是Traefik,但是即使是Traefik想要自动申请证书之类的你也需要在docker compose里写一堆lable去定义
再加上我的服务越来越多 之前都是宝塔和1Panel混着用来管理docker
这太不健康了
我认为是时候开始大一统了
那么随着Docker慢慢被大企业抛弃 Kubernetes(以下简称K8s)越来越流行了
模块化 资源分配 负载均衡 统一管理 故障迁移 分布存储等等
事实上Docker你分开用一堆模块也可以做到这些东西
但是K8s是一整套解决方案 刚好我也想学习一下
让我们来搭建一个完整的K8s集群吧
为什么不用K3s 因为目的不只是为了方便 我认为学习K8s的组件也是很有必要的
折腾开始
大部分都可以参考K8s的官方文档 写的很详细,介绍了很多概念以及在生产环境中要学习的东西
我个人觉得学习的话收益还是很大的
而且还有中文 美滋滋
地址在这里https://kubernetes.io/zh-cn/docs/home/
1.1 主机配置说明
我首先搭建了三台相同的Ubuntu Server,我的打算是1Master 2Node
配置如下
| 配置 | CPU | RAM | 硬盘 | IP地址 |
|---|---|---|---|---|
| Master | 4Core | 4G | 40G | 192.168.0.100/24 |
| Worker01 | 4Core | 8G | 128G | 192.168.0.101/24 |
| Worker02 | 4Core | 8G | 128G | 192.168.0.102/24 |
我是ESXi虚拟机 实在不够用可以扩容 而且我可能会打算部署分布存储 所以先这样配置
1.2 主机配置
1.2.1 主机名配置
我们用xShell连接上三台机器 全部切换到root
为了方便我们先分别设定一下三台机器的主机名字
master节点
hostnamectl set-hostname k8s-master01Worker1
hostnamectl set-hostname k8s-worker01Worker2
hostnamectl set-hostname k8s-worker02然后上面菜单栏————查看————撰写————撰写栏
打开它 然后左下角有一个将命令发送到全部会话
这样我们可以统一执行一些命令
1.2.2 统一时区与时间
!!以下命令所有机器都要执行!!
apt updateapt upgrade -y #更新软件包timedatectl set-timezone Asia/Shanghai # 统一时间为了统一时间 防止时间偏移 我们可以定期让三台机器自动同步时间
这边用的最小化安装 还得安装一下cron
apt install cron -ysystemctl enable cronsystemctl start cronapt install ntpdate -yntpdate ntp.aliyun.comcrontab -e选择2 我们用vim编辑
我们想让他在每天 5点自动更新 那就写
0 5 * * * ntpdate ntp.aliyun.com然后
1.2.3 配置内核转发 网桥过滤
Ubuntu默认是不开启这个的 为了便于集群之间的通信 还有一些Pod的特殊需求 这个肯定是要打开的
cat <<EOF | sudo tee /etc/sysctl.d/k8s.confnet.bridge.bridge-nf-call-ip6tables = 1net.bridge.bridge-nf-call-iptables = 1net.ipv4.ip_forward = 1EOF然后给内核导入overlay br_netfilter这两个模块 这两个是K8s的必要模块
modprobe overlaymodprobe br_netfiltercat <<EOF | sudo tee /etc/modules-load.d/k8s.confoverlaybr_netfilterEOFsysctl --system然后既然是新搭建的,我们可以给kube-proxy用新的ipvs模式 性能更好
需要安装ipset和ipvsadm
apt install ipset ipvsadm -y#让其自动加载cat << EOF | tee /etc/modules-load.d/ipvs.confip_vsip_vs_rrip_vs_wrrip_vs_shnf_conntrackEOF# 立即加载模块modprobe ip_vsmodprobe ip_vs_rrmodprobe ip_vs_wrrmodprobe ip_vs_shmodprobe nf_conntrack1.2.4 关闭swap分区
K8s可以强行兼容swap分区 但是官方文档建议是关闭
因为K8s运行中显然需要的是真实的内存和CPU 为了防止出现奇奇怪怪的问题 关掉它
swapoff -avim /etc/fstab找到最下面一行带有swap关键字的 前面加个#给他注释掉
!!以上命令所有机器都要执行!!
完成之后机器的基本配置算是完成了
2.1 容器运行时的安装
K8s弃用了Docker作为容器运行时 转而使用Containerd
事实上这就是Docker的底层
依旧所有机器都要运行:
wget https://github.com/containerd/containerd/releases/download/v2.1.4/containerd-2.1.4-linux-amd64.tar.gz下不来可以配置一下proxy
这里的地址可以自己去Github下载最新的release
然后解压出来
tar Cxzvf /usr/local containerd-2.1.4-linux-amd64.tar.gzwhich containerd #检查是否成功然后旧版本的cri懒人包没了 我们需要手动安装runc和CNI
wget https://github.com/opencontainers/runc/releases/download/v1.3.2/runc.amd64wget https://github.com/containernetworking/plugins/releases/download/v1.8.0/cni-plugins-linux-amd64-v1.8.0.tgzinstall -m 755 runc.amd64 /usr/local/sbin/runcmkdir -p /opt/cni/bintar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.8.0.tgz然后生成containerd的基础配置文件
mkdir -p /etc/containerdcontainerd config default > /etc/containerd/config.toml
#sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml网上提到的systemd cgroup在新版Containerd中默认使用 我们等下可以验证
然后差点忘了我们手动安装的要注册一下才能用systemctl去调用
wget -O /etc/systemd/system/containerd.service https://raw.githubusercontent.com/containerd/containerd/main/containerd.servicesystemctl daemon-reloadsystemctl restart containerdsystemctl enable containerd跑起来之后我们ls /var/run/containerd/看看 有一个.sock结尾就是ok了
3.1 正式开始部署K8s
# 下载K8s仓库的公钥sudo apt-get install -y apt-transport-https ca-certificates curl gpgcurl -fsSL https://pkgs.k8s.io/core:/stable:/v1.34/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpgecho 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.34/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.listapt update# 查看版本apt-cache madison kubeadm我这里版本最新是1.34.1-1.1
直接安装
apt install kubeadm=1.34.1-1.1 kubelet=1.34.1-1.1 kubectl=1.34.1-1.1apt-mark hold kubelet kubeadm kubectl # 锁定版本防止自动更新炸刚3.2 配置kubelet
先配置kubelet的cgroup驱动
vim /etc/default/kubelet在后面加上”—cgroup-driver=systemd”
kubelet负责集群中Pod的生命周期管理,所以我们需要开机自启动 否则集群会炸
systemctl enable kubelet3.3 集群初始化
3.3.1 生成初始配置文件
请注意:以下命令只需要在Master节点中执行
kubeadm config print init-defaults > kubeadm-config.yaml配置文件太长了我直接贴出来
apiVersion: kubeadm.k8s.io/v1beta4bootstrapTokens:- groups: - system:bootstrappers:kubeadm:default-node-token token: abcdef.0123456789abcdef ttl: 24h0m0s usages: - signing - authenticationkind: InitConfigurationlocalAPIEndpoint: advertiseAddress: 192.168.0.100 #改这里 bindPort: 6443nodeRegistration: criSocket: unix:///var/run/containerd/containerd.sock imagePullPolicy: IfNotPresent imagePullSerial: true name: k8s-master01 #改这里 taints: nulltimeouts: controlPlaneComponentHealthCheck: 4m0s discovery: 5m0s etcdAPICall: 2m0s kubeletHealthCheck: 4m0s kubernetesAPICall: 1m0s tlsBootstrap: 5m0s upgradeManifests: 5m0s---kind: ClusterConfigurationkubernetesVersion: 1.34.0networking: dnsDomain: cluster.local serviceSubnet: 10.96.0.0/12 podSubnet: 10.244.0.0/16 #改这里proxy: {}scheduler: {}3.3.2 获取镜像
然后Pull相关镜像
kubeadm config images pull这里官方镜像是完全不可达的 由于Containerd默认不走系统设置的proxy变量 这里要么用镜像源要么就软路由给整个节点起飞走
下完之后就可以初始化集群了
3.3.3 正式初始化集群
kubeadm init --config kubeadm-config.yaml --upload-certs --v=9Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config当你看到这一坨 意味着控制平面搭建成功了
然后把它上面给的三行命令复制粘贴到控制台
mkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/config然后
kubectl get nodes如果得到这样的输出
NAME STATUS ROLES AGE VERSIONk8s-master01 NotReady control-plane 3m30s v1.34.1完事了
然后记得上面他给了一行让worker加入的命令 复制他粘贴到Workernodes 前期配置没有问题的话顺利加入肯定也没问题
重新get nodes之后能看到
NAME STATUS ROLES AGE VERSIONk8s-master01 NotReady control-plane 8m39s v1.34.1k8s-worker01 NotReady <none> 8s v1.34.1k8s-worker02 NotReady <none> 8s v1.34.1我们可以看到Status还是NotReady,怎么回事呢
我们可以看到pods里面的coredns 还属于pending状态 他作为核心pod之一还没有调度到节点里去
我们的节点还没有调度IP 所以我们需要网络插件CNI
4.1 网络插件
4.1.1 选择
常见的话有三个 Flannel Calico Cilium
复杂程度都是递增的
事实上的话Calico已经足够极其庞大的集群使用了
Cilium则是用于多集群 而且他会复杂非常多 我们暂时不考虑
为了练手 我这里还是选择Calico
后续换成了Cilium
4.1.2 Calico的安装
如果用Opertor安装的话其实很简单 只是还是网络环境的问题
如果之前你能成功init我相信是没问题的 我们偷懒用Operator就好
进入Tigera的文档https://docs.tigera.io/calico/latest/getting-started/kubernetes/self-managed-onprem/onpremises找到安装的命令
在Master节点上执行:
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.30.3/manifests/tigera-operator.yamlwget https://raw.githubusercontent.com/projectcalico/calico/v3.30.3/manifests/custom-resources.yamlvim custom-resources.yaml自定义一下Calico的配置 我们要改的就是默认的那个网段
apiVersion: operator.tigera.io/v1kind: Installationmetadata: name: defaultspec: # Configures Calico networking. calicoNetwork: ipPools: - name: default-ipv4-ippool blockSize: 26 cidr: 10.244.0.0/16 # 这里 encapsulation: VXLANCrossSubnet natOutgoing: Enabled nodeSelector: all()
---apiVersion: operator.tigera.io/v1改完保存然后
kubectl create -f custom-resources.yaml完事之后Calico就开始初始化了
watch kubectl get pods -n calico-system看里面的组件确保全部Running
这时候我们在看看nodes状态
root@k8s-master01:/home/cainong# kubectl get nodesNAME STATUS ROLES AGE VERSIONk8s-master01 Ready control-plane 83m v1.34.1k8s-worker01 Ready <none> 74m v1.34.1k8s-worker02 Ready <none> 74m v1.34.1完事 至此K8s已经完全启动了 撒花撒花
还没完全结束 我们还有Ingress Dashboard没有配置 我是不可能手敲命令行手写yml的
而且我们还要慢慢迁移之前的docker服务 以及Longhorn的配置
这是下一个坑
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!