记一次Kubernetes完整集群的搭建

2257 字
11 分钟
记一次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

配置如下

配置CPURAM硬盘IP地址
Master4Core4G40G192.168.0.100/24
Worker014Core8G128G192.168.0.101/24
Worker024Core8G128G192.168.0.102/24

我是ESXi虚拟机 实在不够用可以扩容 而且我可能会打算部署分布存储 所以先这样配置

1.2 主机配置#

1.2.1 主机名配置#

我们用xShell连接上三台机器 全部切换到root

为了方便我们先分别设定一下三台机器的主机名字

master节点

Terminal window
hostnamectl set-hostname k8s-master01

Worker1

Terminal window
hostnamectl set-hostname k8s-worker01

Worker2

Terminal window
hostnamectl set-hostname k8s-worker02

然后上面菜单栏————查看————撰写————撰写栏

打开它 然后左下角有一个将命令发送到全部会话

这样我们可以统一执行一些命令

1.2.2 统一时区与时间#

!!以下命令所有机器都要执行!!

Terminal window
apt update
apt upgrade -y #更新软件包
timedatectl set-timezone Asia/Shanghai # 统一时间

为了统一时间 防止时间偏移 我们可以定期让三台机器自动同步时间

这边用的最小化安装 还得安装一下cron

Terminal window
apt install cron -y
systemctl enable cron
systemctl start cron
Terminal window
apt install ntpdate -y
ntpdate ntp.aliyun.com
crontab -e

选择2 我们用vim编辑

我们想让他在每天 5点自动更新 那就写

0 5 * * * ntpdate ntp.aliyun.com

然后保存

1.2.3 配置内核转发 网桥过滤#

Ubuntu默认是不开启这个的 为了便于集群之间的通信 还有一些Pod的特殊需求 这个肯定是要打开的

Terminal window
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

然后给内核导入overlay br_netfilter这两个模块 这两个是K8s的必要模块

Terminal window
modprobe overlay
modprobe br_netfilter
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sysctl --system

然后既然是新搭建的,我们可以给kube-proxy用新的ipvs模式 性能更好

需要安装ipset和ipvsadm

Terminal window
apt install ipset ipvsadm -y
#让其自动加载
cat << EOF | tee /etc/modules-load.d/ipvs.conf
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
EOF
# 立即加载模块
modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh
modprobe nf_conntrack

1.2.4 关闭swap分区#

K8s可以强行兼容swap分区 但是官方文档建议是关闭

因为K8s运行中显然需要的是真实的内存和CPU 为了防止出现奇奇怪怪的问题 关掉它

Terminal window
swapoff -a
vim /etc/fstab

找到最下面一行带有swap关键字的 前面加个#给他注释掉

!!以上命令所有机器都要执行!!

完成之后机器的基本配置算是完成了

2.1 容器运行时的安装#

K8s弃用了Docker作为容器运行时 转而使用Containerd

事实上这就是Docker的底层

依旧所有机器都要运行:

Terminal window
wget https://github.com/containerd/containerd/releases/download/v2.1.4/containerd-2.1.4-linux-amd64.tar.gz

下不来可以配置一下proxy

这里的地址可以自己去Github下载最新的release

然后解压出来

Terminal window
tar Cxzvf /usr/local containerd-2.1.4-linux-amd64.tar.gz
which containerd #检查是否成功

然后旧版本的cri懒人包没了 我们需要手动安装runc和CNI

Terminal window
wget https://github.com/opencontainers/runc/releases/download/v1.3.2/runc.amd64
wget https://github.com/containernetworking/plugins/releases/download/v1.8.0/cni-plugins-linux-amd64-v1.8.0.tgz
install -m 755 runc.amd64 /usr/local/sbin/runc
mkdir -p /opt/cni/bin
tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.8.0.tgz

然后生成containerd的基础配置文件

Terminal window
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
#sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

网上提到的systemd cgroup在新版Containerd中默认使用 我们等下可以验证

然后差点忘了我们手动安装的要注册一下才能用systemctl去调用

Terminal window
wget -O /etc/systemd/system/containerd.service https://raw.githubusercontent.com/containerd/containerd/main/containerd.service
systemctl daemon-reload
systemctl restart containerd
systemctl enable containerd

跑起来之后我们ls /var/run/containerd/看看 有一个.sock结尾就是ok了

3.1 正式开始部署K8s#

Terminal window
# 下载K8s仓库的公钥
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.34/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo '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.list
apt update
# 查看版本
apt-cache madison kubeadm

我这里版本最新是1.34.1-1.1

直接安装

Terminal window
apt install kubeadm=1.34.1-1.1 kubelet=1.34.1-1.1 kubectl=1.34.1-1.1
apt-mark hold kubelet kubeadm kubectl # 锁定版本防止自动更新炸刚

3.2 配置kubelet#

先配置kubelet的cgroup驱动

Terminal window
vim /etc/default/kubelet

在后面加上”—cgroup-driver=systemd”

kubelet负责集群中Pod的生命周期管理,所以我们需要开机自启动 否则集群会炸

Terminal window
systemctl enable kubelet

3.3 集群初始化#

3.3.1 生成初始配置文件#

请注意:以下命令只需要在Master节点中执行

Terminal window
kubeadm config print init-defaults > kubeadm-config.yaml

配置文件太长了我直接贴出来

apiVersion: kubeadm.k8s.io/v1beta4
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 192.168.0.100 #改这里
bindPort: 6443
nodeRegistration:
criSocket: unix:///var/run/containerd/containerd.sock
imagePullPolicy: IfNotPresent
imagePullSerial: true
name: k8s-master01 #改这里
taints: null
timeouts:
controlPlaneComponentHealthCheck: 4m0s
discovery: 5m0s
etcdAPICall: 2m0s
kubeletHealthCheck: 4m0s
kubernetesAPICall: 1m0s
tlsBootstrap: 5m0s
upgradeManifests: 5m0s
---
kind: ClusterConfiguration
kubernetesVersion: 1.34.0
networking:
dnsDomain: cluster.local
serviceSubnet: 10.96.0.0/12
podSubnet: 10.244.0.0/16 #改这里
proxy: {}
scheduler: {}

3.3.2 获取镜像#

然后Pull相关镜像

Terminal window
kubeadm config images pull

这里官方镜像是完全不可达的 由于Containerd默认不走系统设置的proxy变量 这里要么用镜像源要么就软路由给整个节点起飞走

下完之后就可以初始化集群了

3.3.3 正式初始化集群#

Terminal window
kubeadm init --config kubeadm-config.yaml --upload-certs --v=9
Your 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

当你看到这一坨 意味着控制平面搭建成功了

然后把它上面给的三行命令复制粘贴到控制台

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

然后

Terminal window
kubectl get nodes

如果得到这样的输出

NAME STATUS ROLES AGE VERSION
k8s-master01 NotReady control-plane 3m30s v1.34.1

完事了

然后记得上面他给了一行让worker加入的命令 复制他粘贴到Workernodes 前期配置没有问题的话顺利加入肯定也没问题

重新get nodes之后能看到

NAME STATUS ROLES AGE VERSION
k8s-master01 NotReady control-plane 8m39s v1.34.1
k8s-worker01 NotReady <none> 8s v1.34.1
k8s-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节点上执行:

Terminal window
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.30.3/manifests/tigera-operator.yaml
wget https://raw.githubusercontent.com/projectcalico/calico/v3.30.3/manifests/custom-resources.yaml
vim custom-resources.yaml

自定义一下Calico的配置 我们要改的就是默认的那个网段

apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
name: default
spec:
# 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

改完保存然后

Terminal window
kubectl create -f custom-resources.yaml

完事之后Calico就开始初始化了

Terminal window
watch kubectl get pods -n calico-system

看里面的组件确保全部Running

这时候我们在看看nodes状态

Terminal window
root@k8s-master01:/home/cainong# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master01 Ready control-plane 83m v1.34.1
k8s-worker01 Ready <none> 74m v1.34.1
k8s-worker02 Ready <none> 74m v1.34.1

完事 至此K8s已经完全启动了 撒花撒花

还没完全结束 我们还有Ingress Dashboard没有配置 我是不可能手敲命令行手写yml的

而且我们还要慢慢迁移之前的docker服务 以及Longhorn的配置

这是下一个坑

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

记一次Kubernetes完整集群的搭建
https://cainongw.github.io/posts/kubernetes-buildup/
作者
Cainong
发布于
2025-10-05
许可协议
CC BY-NC-SA 4.0
相关文章 智能推荐
1
记一次Kubernetes集群的完善
HomeLab 前言 我们成功搭建起了K8s 接下来我们需要搭建一些额外的服务来满足我的需求
2
记一次filebrowser的搭建
Kubernetes 起因 我以为这个就是写个Deployment然后挂载NFS就得了 本来都不打算写blog的 结果后面发现折腾了我几个小时才好 还是有一点坑的 所以就写一下
3
开源WAF 雷池在K8s上的搭建
HomeLab 前言 换了条宽带,现在我拥有动态的公网IPV4地址了 我打算暴露一些服务出去以便我使用 例如Openlist RDP Gitlab 但是 我并不打算公开 我只打算自己使用 前面我们搭建了Authentik作为SSO单点登录,刚好雷池WAF支持通过单点登录鉴权来允许访问 这样我就可以实现把ESXi挂到公网 但是不登录都过不了防火墙
4
记一次基于small-step对局域网内证书的自签名
HomeLab 我们已经解决了K8s内集群的证书 现在需要解决我们直接跑在虚拟机上的一些服务的证书签名了 之前是自己签名 现在发现可以用根证书+ACME统一签名 因为是根证书 实际上可以在Ingress里设置任何一个域名(即使他已经存在) 甚至可以把baidu换成google(
5
记一次基于OpenWRT+Nginx反代的局域网服务小改造
HomeLab 前言 随着服务器上面跑的东西越来越多,docker跑的服务也越来越多了 我常访问所以我可以记住每个虚拟机的ip或者docker的端口 但是每次在浏览器输入都得输入192然后手动补全,有时候甚至得冒号加端口号才可以 太特么麻烦了
随机文章 随机推荐
Profile Image of the Author
Cainong
Caiw there 👋
公告
欢迎来到我的博客!这是一则示例公告。
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
站点统计
文章
38
分类
16
标签
48
总字数
57,650
运行时长
0
最后活动
0 天前

文章目录