写在前面
太好了孩子们 这次基本全都是命令行操作 我不用截图了
以下几乎全是命令 几乎一张图片没有 如果你想做为参考的话请仔细阅读每一行
起因
昨天我在折腾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-master01
Worker1
hostnamectl set-hostname k8s-worker01
Worker2
hostnamectl set-hostname k8s-worker02
然后上面菜单栏————查看————撰写————撰写栏
打开它 然后左下角有一个将命令发送到全部会话
这样我们可以统一执行一些命令
1.2.2 统一时区与时间
!!以下命令所有机器都要执行!!
apt update
apt upgrade -y #更新软件包
timedatectl set-timezone Asia/Shanghai # 统一时间
为了统一时间 防止时间偏移 我们可以定期让三台机器自动同步时间
这边用的最小化安装 还得安装一下cron
apt install cron -y
systemctl enable cron
systemctl start cron
apt install ntpdate -y
ntpdate ntp.aliyun.com
crontab -e
选择2 我们用vim编辑
我们想让他在每天 5点自动更新 那就写
0 5 * * * ntpdate ntp.aliyun.com
然后:wq保存
1.2.3 配置内核转发 网桥过滤
Ubuntu默认是不开启这个的 为了便于集群之间的通信 还有一些Pod的特殊需求 这个肯定是要打开的
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的必要模块
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
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 为了防止出现奇奇怪怪的问题 关掉它
swapoff -a
vim /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.gz
which containerd #检查是否成功
然后旧版本的cri懒人包没了 我们需要手动安装runc和CNI
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的基础配置文件
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去调用
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
# 下载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
直接安装
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驱动
vim /etc/default/kubelet
在后面加上”–cgroup-driver=systemd”
kubelet负责集群中Pod的生命周期管理,所以我们需要开机自启动 否则集群会炸
systemctl enable kubelet
3.3 集群初始化
3.3.1 生成初始配置文件
请注意:以下命令只需要在Master节点中执行
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相关镜像
kubeadm config images pull
这里官方镜像是完全不可达的 由于Containerd默认不走系统设置的proxy变量 这里要么用镜像源要么就软路由给整个节点起飞走
下完之后就可以初始化集群了
3.3.3 正式初始化集群
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
当你看到这一坨 意味着控制平面搭建成功了
然后把它上面给的三行命令复制粘贴到控制台
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
然后
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
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.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
改完保存然后
kubectl create -f custom-resources.yaml
完事之后Calico就开始初始化了
watch kubectl get pods -n calico-system
看里面的组件确保全部Running
这时候我们在看看nodes状态
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的配置
这是下一个坑