Debian12安装k8s,配置节点

大概只会维护一版安装指引。
  • k8s版本1.31.1

采用的机器

使用了2台物理机。安装了pve虚拟机,使用集群的方式配置。

  • 物理机器H
    • i7-6700 4C8T
    • 8G+16G 24G DRAM
    • 1t 机械盘
  • 物理机器L
    • i7-4590 4C4T
    • 8G+8G 16G DRAM
    • 500G 机械盘
      构成:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11

      ├── 物理机器H
      │ ├── shellclash(软件包加速)
      │ └── pve VM
      │ ├── windows11 无意义,只是装了。
      │ ├── master 主节点
      │ └── node1 工作负载1

      └── 物理机器L
      └── pve VM
      └── node2 工作负载2

准备工作

在前面,介绍完了物理机器,以及部署情况,接下来就是漫长的前置配置环节。

配置加速

!!!!
shellcrash 使用linux模式,开放局域网代理。并自行购买加速节点。
最终你会获得一个http://你安装shellcalsh的主机IP地址:7890/这样一个内网ip+端口的代理接口。
!!!!
将下面所有步骤的 “http://192.168.1.0:7890/“ 修改为你获得的地址(http://你安装shellclash的主机IP地址:7890/)。

加速apt

1
echo "Acquire::http::Proxy "http://192.168.1.0:7890/";" >> /etc/apt/apt.conf

加速bash环境

1
2
3
echo "export http_proxy=http://192.168.1.0:7890
export https_proxy=http://192.168.1.0:7890" >> /etc/profile
source /etc/profile

安装常用软件包

1
apt install vim wget net-tools gcc sudo ca-certificates curl git make gpg -y

设置host

设置hostname

1
2
# 作为master节点的机器执行
sudo hostnamectl set-hostname master && hostname
1
2
# 作为工作负载节点1的机器执行
sudo hostnamectl set-hostname node1 && hostname
1
2
# 作为工作负载节点2的机器执行
sudo hostnamectl set-hostname node2 && hostname

此时你的三台机器的名字就变成了 “master” “node1” “node2”

编辑host文件

1
2
# 获取网络ip地址
ifconfig

记住你的ip地址,这里就不放图了,要是不会找ip还是回家种红薯吧。

1
2
# 编辑hosts文件
sudo vim /etc/hosts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# hosts 文件内容
# ipv4 部分
127.0.0.1 localhost
##### 编辑的部分开始 #####
# 假设你的master是192.168.1.100 node1是192.168.1.101 node2 是192.168.1.102
127.0.0.1 node2 # 回环地址,代表本机是node2 也可以写192.168.1.102。
192.168.1.100 master
192.168.1.101 node1
##### 编辑的部分结束 #####

# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

关闭swap分区

为什么要关闭swap分区

K8S 官方文档认为,如果一台机器准备部署 Kubernetes,则首先应该关闭该机器的交换分区。以下是一些主要原因:

- 资源分配和调度
    - 预测性: Kubernetes 使用其自己的方式来管理和调度系统资源。如果 swap 被启用,这可能会干扰 Kubernetes 的资源调度算法,导致不可预测的行为。
    - QoS(服务质量): Kubernetes 提供了不同级别的服务质量(QoS)保证。启用 swap 可能会影响这些 QoS 级别的准确性。比如 pod 的调度会以主机的内存占用为触发条件,swap 的存在会使得内存占用降下来,但应用在读取被 swap 的页时却有明显的服务质量降低。
- 性能
    - 延迟: 使用 swap 通常会增加 I/O 延迟,这对于需要快速响应的应用程序(如数据库和高性能计算应用)是不可接受的。
    - 内存压缩: 现代操作系统和 Kubernetes 有更高效的方式来处理内存压缩和回收,而不是依赖于交换分区。
- 简化运维
    - 一致性: 禁用 swap 可以简化集群的运维,因为这消除了不同节点可能因为不同的 swap 配置而表现不同的风险。

因此,为了确保 Kubernetes 集群的性能和稳定性,通常建议在安装和运行 Kubernetes 时禁用 swap. 这也是 Kubernetes 官方文档中的推荐做法。

1
2
3
# 关闭swap分区以及取消开机挂载脚本文件
sudo swapoff -a
sudo sed -i 's/^.*swap.*$/#&/' /etc/fstab

但是在debian上面仅仅只操作这两个是无法彻底关闭swap分区的,systememd会在启动时自动扫描磁盘分区并自动挂载。
因此想彻底关闭swap分区需要删除swap分区才行,具体可以看stackexchange
的帖子。
因此需要再执行

1
2
3
4
5
systemctl mask  "dev-*.swap"
# Glob pattern passed to mask, but globs are not supported for this.
# Invalid unit name "dev-*.swap" escaped as "dev-\x2a.swap".
# Unit dev-\x2a.swap does not exist, proceeding anyway.
# Created symlink /etc/systemd/system/dev-\x2a.swap -> /dev/null.

安装docker

1
2
3
4
5
# 卸载旧的docker
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done
# 使用脚本安装docker
curl -fsSL https://get.docker.com |sh
sudo systemctl enable docker --now

加速docker pull 命令的镜像拉取

  • 这一步因人而异,假如你有自己的镜像仓库,请自行百度换镜像仓库,不在本教程内。
    是否要进行下一步可以使用docker pull nginx查看是否可以拉取镜像。
  • 这里的配置是必要的,k8s组件需要从docker仓库中拉取。
    1
    2
    3
    4
    5
    6
    7
    mkdir -p /etc/systemd/system/docker.service.d/
    echo "[Service]
    Environment="HTTP_PROXY=http://192.168.1.0:7890"
    Environment="HTTPS_PROXY=http://192.168.1.0:7890"" >> /etc/systemd/system/docker.service.d/http-proxy.conf
    # 重启docker服务生效
    sudo systemctl daemon-reload
    sudo systemctl restart docker

开启转发

1
2
3
4
5
# 创建配置文件
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

允许内核检查桥接设备上的流量

  • modprobe br_netfilter 命令用于在 Linux 系统中加载 br_netfilter 内核模块。该模块是桥接(bridging)网络过滤的一部分,通常用于与 Linux 容器(如 Docker)或虚拟机进行通信,以及在使用 Linux 网桥时进行网络包过滤。加载 br_netfilter 模块后,你可以使用 iptables 或 nftables 等工具对经过网桥的数据包进行过滤、转发或拦截。这个模块在一些特定的网络设置中是非常有用的,尤其是当你需要在一个物理主机上运行多个网络隔离的虚拟机或容器时。modprobe br_netfilter 用于启用网桥相关的网络过滤功能,以便你可以更灵活地控制数据包的流动。
    1
    2
    sudo modprobe overlay
    sudo modprobe br_netfilter
    基于官方文档开启ipv4转发
  • 默认情况下,Linux 内核不允许 IPv4 数据包在接口之间路由。 大多数 Kubernetes 集群网络实现都会更改此设置(如果需要),但有些人可能希望管理员为他们执行此操作。 (有些人可能还期望设置其他 sysctl 参数、加载内核模块等;请参阅你的特定网络实施的文档。)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # sysctl params required by setup, params persist across reboots
    cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
    net.ipv4.ip_forward = 1
    EOF

    # Apply sysctl params without reboot
    sudo sysctl --system
    # 查看返回的结果是否为1
    sudo sysctl net.ipv4.ip_forward

安装cri-dockerd

由于我的debian使用国内镜像,cri-dockerd 和 golang版本偏低(并不清楚是不是国内镜像的锅)。
因此采用源码编译方式。
进入golang官网,选择一个1.22之后的版本。这里选择新出的1.23.0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 安装golang 并配置环境变量
wget https://go.dev/dl/go1.23.0.linux-amd64.tar.gz
sudo tar -zxvf go1.23.0.linux-amd64.tar.gz
sudo rm go1.23.0.linux-amd64.tar.gz
mv go /usr/local
echo 'export GOPATH=/root/go
export GOROOT=/usr/local/go
export GOBIN=$GOROOT/bin
export GOPROXY=https://goproxy.cn,direct
export PATH="$PATH:$GOPATH/bin:$GOBIN:$GOROOT/bin"' | sudo tee -a /etc/profile
source /etc/profile
go version
# 安装 cri-dockerd
# 进入cri-dockerd的github界面,拉取最新的release分支,当前最新分支是0.3
git clone https://github.com/Mirantis/cri-dockerd.git -b release/0.3
cd cri-dockerd
make cri-dockerd
sudo mkdir -p /usr/local/bin
sudo install -o root -g root -m 0755 cri-dockerd /usr/local/bin/cri-dockerd
sudo install 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
cd
rm -rf cri-dockerd

安装k8s

终于经过紧张的准备工作,排除万难,终于到了正式安装k8s的环节
### 安装k8s三件套
#### 引入新的k8s仓库
以下是google的公告

为什么我们要引入新的包仓库?
  • 由于我们只有一个包仓库。因此,我们无法发布预发行版本 (Alpha、Beta 和 RC)的包。这使得任何有兴趣测试的人都更难测试 Kubernetes 预发布版本。 我们从测试这些版本的人员那里收到的反馈对于确保版本的最佳质量至关重要, 因此我们希望尽可能轻松地测试这些版本。最重要的是,只有一个仓库限制了我们对 cri-tools 和 kubernetes-cni 等依赖进行发布,
  • 新的 Debian 和 RPM 仓库托管在 pkgs.k8s.io。
托管在 Google 的仓库和 Kubernetes 仓库之间有哪些显著差异?

你应该注意三个显著差异:
- 每个 Kubernetes 次要版本都有一个专用的仓库。例如, 名为 core:/stable:/v1.28 的仓库仅托管稳定 Kubernetes v1.28 版本的包。 这意味着你可以从此仓库安装 v1.28.0,但无法安装 v1.27.0 或 v1.28 之外的任何其他次要版本。 升级到另一个次要版本后,你必须添加新的仓库并可以选择删除旧的仓库
- 每个 Kubernetes 仓库中可用的 cri-tools 和 kubernetes-cni 包版本有所不同
这两个包是 kubelet 和 kubeadm 的依赖项
- v1.24 到 v1.27 的 Kubernetes 仓库与托管在 Google 的仓库具有这些包的相同版本
- v1.28 及更高版本的 Kubernetes 仓库将仅发布该 Kubernetes 次要版本
就 v1.28 而言,Kubernetes v1.28 的仓库中仅提供 kubernetes-cni 1.2.0 和 cri-tools v1.28
与 v1.29 类似,我们只计划发布 cri-tools v1.29 以及 Kubernetes v1.29 将使用的 kubernetes-cni 版本
包版本的修订部分(1.28.0-00 中的 -00 部分)现在由 OpenBuildService 平台自动生成,并具有不同的格式。修订版本现在采用 -x.y 格式,例如 1.28.0-1.1

由于新仓库的发布解决了k8s固定版本和不能更新的痛点,这里我默认选择了(pkgs.k8s.io)仓库。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 更新软件包并安装三件套
sudo apt-get update
sudo apt-get install -y apt-transport-https

# !!!采用google k8s apt仓库!!!
# curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg
# echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

# !!!采用(pkgs.k8s.io)仓库 下方命令的链接https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key 可以保证你的k8s可以使用apt更新,并且不会迁移大版本。!!!
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.31/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl

启动集群

1
2
3
4
5
6
# 模拟启动,查看是否会报错
sudo kubeadm init \
--pod-network-cidr 192.168.0.0/16 \
--cri-socket unix:///var/run/cri-dockerd.sock \
--control-plane-endpoint master \
--dry-run

假如一切正常就可以执行

1
2
3
4
5
# 初始化集群master
sudo kubeadm init \
--pod-network-cidr 192.168.0.0/16 \
--cri-socket unix:///var/run/cri-dockerd.sock \
--control-plane-endpoint master

初始化成功根据提示执行

1
2
3
4
5
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 如果是root 用户可以执行
export KUBECONFIG=/etc/kubernetes/admin.conf

安装网络插件

网络插件有很多种,这里我选择了泛用度最高的Calico
安装 Calico

  • 官网,找到最符合你需求的安装方式.
    这里我的node小于50,大概也不会多于50.所以选择了基本安装方式。
    1
    2
    curl https://raw.githubusercontent.com/projectcalico/calico/v3.28.1/manifests/calico.yaml -O
    kubectl apply -f calico.yaml
1
2
3
kubectl get node
kubectl get pod
kubectl get pods --all-namespaces

节点加入集群

主节点初始化完成后会生成一条工作负载加入集群的命令

1
2
3
sudo kubeadm join master:6443 --token 2jt59e.sfnmza3li4qphgsl \
--discovery-token-ca-cert-hash sha256:c91d01dc335c94f3c22c955639083f74272f22201cfd7dd3725c375641a3404c \
--cri-socket unix:///var/run/cri-dockerd.sock