k8s
Kubeadm
Kubeadm 是一个出色的工具,可以在更短的时间内建立一个工作的 kubernetes 集群。它完成了设置所有 kubernetes 集群组件方面的所有繁重工作。此外,它遵循 kubernetes 集群的所有配置最佳实践。
简介
Kubeadm 是一个无需太多复杂配置即可设置最小可行 Kubernetes 集群的工具。此外,Kubeadm 通过运行一系列预检查来确保服务器具有运行 Kubernetes 所需的所有必要组件和配置,从而使整个过程变得简单,它由官方 Kubernetes 社区开发和维护。 但如果您想使用属于集群管理一部分的集群组件或测试实用程序,Kubeadm 是最佳选择。此外,您还可以在工作站上本地创建类似生产的集群,以用于开发和测试目的。
先决条件
- 至少两个 Ubuntu 节点(一个主节点和一个工作节点)。您可以根据需要拥有更多工作节点。
- 主节点应至少具有 2 个 vCPU 和 2GB RAM。
- 对于工作节点,建议至少使用 1vCPU 和 2 GB RAM。
- 10.X.X.X/X 网络范围,具有主节点和工作节点的静态 IP。我们将使用 192.x.x.x 系列作为 Calico 网络插件将使用的 pod 网络范围。确保节点 IP 范围和 pod IP 范围不重叠。
端口要求
请参考下图并确保控制平面(主节点)和工作节点允许所有端口。如果您要设置 kubeadm 集群云服务器,请确保在防火墙配置中允许这些端口。

Vagrantfile, Kubeadm Scripts & Manifests
所有脚本都托管在github上,可以通过
git clone https://github.com/techiescamp/kubeadm-scripts获取
使用Kubeadm配置Kubenetes Cluster
以下是设置基于 kubeadm 的 Kubernetes 集群所涉及的高级步骤。
Step 1: Enable iptables Bridged Traffic on all the Nodes
在 IPtables 的所有节点上执行以下命令以查看桥接流量。这里我们调整一些内核参数并使用 sysctl 设置它们。
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# sysctl params required by setup, params persist across reboots
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
# Apply sysctl params without reboot
sudo sysctl --systemStep 2: Disable swap on all the Nodes
sudo swapoff -a
# 若要持久,需要修改/etc/fstab 注释掉swap部分
# (crontab -l 2>/dev/null; echo "@reboot /sbin/swapoff -a") | crontab - || trueStep 3: Install CRI
containerd
当前不知道什么问题,worker节点中的proxy和calico-node会反复重启,暂时先不用了
就是安装docker步骤安装
# 重新生成containerd的配置文件
sudo containerd config default > /etc/containerd/config.toml如果拉不下来可能需要配置代理(注意拉完镜像记得关掉代理,不然pod间通信有问题会导致coredns等启动不起来):
# 如果使用containerd作为k8s的cri的话
# 配置代理需要配置containerd的代理
sudo mkdir -p /etc/systemd/system/containerd.service.d
sudo tee /etc/systemd/system/containerd.service.d/http-proxy.conf <<EOF
[Service]
Environment="HTTP_PROXY=http://192.168.0.52:7890"
Environment="HTTPS_PROXY=http://192.168.0.52:7890"
Environment="NO_PROXY=localhost,127.0.0.1,10.244.0.0/16,192.168.0.0/16,0.0.0.0/0,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,10.96.0.0/12,.svc,.cluster.local"
EOF
sudo systemctl daemon-reload
sudo systemctl restart containerd
sudo systemctl show --property=Environment containerdCRI-O
这里使用CRI-O而不是Docker/Containerd作为k8s的CRI。
sudo apt-get update -y
sudo apt-get install -y software-properties-common gpg curl apt-transport-https ca-certificates
curl -fsSL https://pkgs.k8s.io/addons:/cri-o:/prerelease:/main/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/cri-o-apt-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/cri-o-apt-keyring.gpg] https://pkgs.k8s.io/addons:/cri-o:/prerelease:/main/deb/ /" | sudo tee /etc/apt/sources.list.d/cri-o.list
sudo apt-get update -y
sudo apt-get install -y cri-o
sudo systemctl daemon-reload
sudo systemctl enable crio --now
sudo systemctl start crio.service如果拉不下来可能需要配置kubelet的代理(注意拉完镜像记得关掉代理,不然pod间通信有问题会导致coredns等启动不起来):
# 如果使用cri-o作为k8s的cri的话
# 配置代理需要配置cri-o的代理
# 这里NO_PROXY的域名通配符是. 也就是.insvc.cn这样
sudo mkdir -p /etc/systemd/system/crio.service.d/
sudo tee /etc/systemd/system/crio.service.d/10-http-proxy.conf <<EOF
[Service]
Environment="HTTP_PROXY=http://192.168.0.52:7890"
Environment="HTTPS_PROXY=http://192.168.0.52:7890"
Environment="NO_PROXY=localhost,127.0.0.1,10.244.0.0/16,192.168.0.0/16,0.0.0.0/0,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,10.96.0.0/12,.svc,.cluster.local"
EOF
sudo systemctl daemon-reload
sudo systemctl restart crionvidia-container支持
见NVIDIA/k8s-device-plugin: NVIDIA device plugin for Kubernetes 主要步骤是:
- 首先参照配置方式安装nvidia container runtime。
- 添加crio配置:
# 99- 的话优先级会高于10-crio.conf 所以会优先使用nvidia runtime
sudo tee /etc/crio/crio.conf.d/99-nvidia.conf <<EOF
[crio]
[crio.runtime]
default_runtime = "nvidia"
[crio.runtime.runtimes.nvidia]
runtime_path = "/usr/bin/nvidia-container-runtime"
monitor_path = "/usr/libexec/crio/conmon"
runtime_type = "oci"
EOF- 添加
nvidia-container-runtime配置/etc/nvidia-container-runtime/config.toml中的runtimes = ["crun", "docker-runc", "runc"]增加crun,因为crun是crio的默认容器。 - 随后重启
sudo systemctl restart crio - 然后control-pannel安装插件:
kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.17.0/deployments/static/nvidia-device-plugin.yml - 关于
helm的配置可以见[NVIDIA/k8s-device-plugin: NVIDIA device plugin for Kubernetes](https://github.com/NVIDIA/k8s-device-plugin?tab=readme-ov-file#deployment-via-helm)
Step 4: Install Kubeadm & Kubelet & Kubectl on all Nodes
KUBERNETES_VERSION=1.30
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v$KUBERNETES_VERSION/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:/v$KUBERNETES_VERSION/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list
# Update apt
sudo apt-get update -y
# 您可以使用以下命令来查找最新版本。安装1.30中的第一个版本,以便您可以练习集群升级任务。您可以使用以下命令来查找最新版本。安装1.30中的第一个版本,以便您可以练习集群升级任务。
apt-cache madison kubeadm | tac指定版本,如下所示。这里我使用的是1.30.0-1.1
sudo apt-get install -y kubelet=1.30.0-1.1 kubectl=1.30.0-1.1 kubeadm=1.30.0-1.1或者,要从存储库安装最新版本,请使用以下命令而不指定任何版本。
sudo apt-get install -y kubelet kubeadm kubectl向软件包添加保留以防止升级。
sudo apt-mark hold kubelet kubeadm kubectl现在我们拥有使用 kubeadm 配置 Kubernetes 组件所需的所有实用程序和工具。
将节点 IP 添加到 KUBELET_EXTRA_ARGS。
sudo apt-get install -y jq
local_ip="$(ip --json addr show eth0 | jq -r '.[0].addr_info[] | select(.family == "inet") | .local')"
cat > /etc/default/kubelet << EOF
KUBELET_EXTRA_ARGS=--node-ip=$local_ip
EOFStep 5: Initialize Kubeadm On Master Node To Setup Control Plane
这里您需要考虑两个选择。
- Master Node with Private IP: 如果您的节点仅具有私有 IP 地址,则将通过主节点的私有 IP 访问 API 服务器。
- Master Node With Public IP: 如果您在云平台上设置 Kubeadm 集群,并且需要通过主节点服务器的公共 IP 访问主 Api 服务器。 对于公共 IP 和私有 IP,只有 Kubeadm 初始化命令有所不同。
首先手动拉取镜像:
sudo kubeadm config images pull --cri-socket=unix:///var/run/crio/crio.sock
# 这些镜像可以通过以下指令看到
sudo crictl images仅在主节点上执行本节中的命令。 对于Private IP:
IPADDR="192.168.0.211"
NODENAME=$(hostname -s)
POD_CIDR="10.244.0.0/16" # 通常Calico默认为192.168.0.0/16,我们后面会修改随后执行以下指令初始化主节点:
sudo kubeadm init --apiserver-advertise-address=$IPADDR --apiserver-cert-extra-sans=$IPADDR --pod-network-cidr=$POD_CIDR --node-name $NODENAME --cri-socket=unix:///var/run/crio/crio.sock对于Public IP:
IPADDR=$(curl ifconfig.me && echo "")
NODENAME=$(hostname -s)
POD_CIDR="192.168.0.0/16"随后执行以下指令:
sudo kubeadm init --control-plane-endpoint=$IPADDR --apiserver-cert-extra-sans=$IPADDR --pod-network-cidr=$POD_CIDR --node-name $NODENAME # --cri-socket=/var/run/crio/crio.sock crio不支持nvidia-containerd 所以还是要用containerd搞定之后,会打印一些配置信息和worker node加入的指令,这些需要记录一下:

使用输出中的以下命令在 master 中创建 kubeconfig,以便您可以使用 kubectl 与集群 API 交互。
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config随后输入以下指令验证kubeconfig:
kubectl get po -n kube-system您使用以下命令验证所有集群组件的运行状况。
kubectl get --raw='/readyz?verbose'您可以使用以下命令获取集群信息。
kubectl cluster-info默认情况下,应用程序不会在主节点上调度。如果您想使用主节点来调度应用程序,请污染主节点。
kubectl taint nodes --all node-role.kubernetes.io/control-plane-另外,你也可以通过配置文件进行初始化。
Step 6: Join Worker Nodes To Kubernetes Master Node
在worker node上,安装所需要的组件,然后执行join
# 以下指令在主节点初始化的时候就会打印出来
sudo kubeadm join 192.168.0.211:6443 --token hj4l4n.umx6mo436r0qy95j \
--discovery-token-ca-cert-hash sha256:ae18e9f2e2d4a6bcb555c88ddf7f1e972c9ce0d06eb5b2ebcfaf5b9d3f94b9dd
# 如果没有了,或者证书过期了,主节点可以执行
sudo kubeadm token create --print-join-command加入成功之后,可以在主节点上查看:
kubectl get nodes
这里看到,我们的fu04不是worker,这是因为新加入的节点需要手动指定roles
kubectl label node fu04 node-role.kubernetes.io/worker=""Step 7: Install Calico Network Plugin for Pod Networking
Kubeadm 不配置任何网络插件。您需要为 kubernetes pod 网络安装您选择的网络插件并启用网络策略。
这里我们要使用Calico,默认的网段是192.168.0.0/16,可能和我们内网的网段冲突了,所以需要下载Calico的配置文件进行修改
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
# 随后修改CALICO_IPV4POOL_CIDR部分到你要的网段
# 比如这里我们想要10.244.0.0/16查看pod,看是否添加成功
# -o wide 可以看到所在节点等额外信息
kubectl get po -n kube-systemStep 8: Setup Kubernetes Metrics Server
Kubeadm 在初始化期间不会安装指标服务器组件。我们必须单独安装它。
为了验证这一点,如果您运行 top 命令,您将看到 Metrics API 不可用错误。
$ kubectl top nodes
error: Metrics API not available要安装指标服务器,请执行以下指标服务器清单文件。它部署了metrics服务器版本v0.7.1
wget -O metrics-server.yaml https://raw.githubusercontent.com/techiescamp/kubeadm-scripts/main/manifests/metrics-server.yaml
kubectl apply -f ./metrics-server.yaml
# 删除metrics-server
kubectl delete -f ./metrics-server.yaml
# 如果遇到说找不到/etc/cni/net.d下的网络配置,而且你的网络插件正常运行
# 这个时候删除网络插件重新安装即可。该清单取自官方指标服务器存储库。我已将--kubelet-insecure-tls标志添加到容器中,以使其在本地设置中工作并单独托管。否则,您将收到以下错误。
because it doesn't contain any IP SANs" node=""部署指标服务器对象后,您需要一分钟时间才能使用 top 命令查看节点和 Pod 指标。
kubectl top nodes清除有问题的pod
# 比如我想删掉calico-node
kubectl delete pod -n kube-system -l k8s-app=calico-node
# 如果terminating过长时间,可以强制删除--grace-period表示等待pod优雅退出的时间
kubectl delete pod -n kube-system -l k8s-app=calico-node --force --grace-period=0Step 9: 配置默认的StorageClass
StorageClass是一个存储类,通过创建StorageClass可以动态生成一个存储卷,供 k8s 使用; 使用 StorageClass 可以根据PVC动态的创建PV,减少管理员手工创建PV的工作;
StorageClass的定义主要包括名称、后端存储的提供者 (privisioner) 和后端存储的相关参数配置;
注意:StorageClass一旦被创建,就无法修改,如需修改,只能删除重建!
接下来就需要使用 nfs-subdir-external-provisioner Provisioner; 这个 Provisioner 使用已经配置好的 nfs 服务器,来自动创建持久卷,即自动帮我们创建 PV;
同时:
- 自动创建的 PV 以
{namespace}-{pvcName}-{pvName}这样的命名! - 格式创建在 NFS 服务器上的共享数据目录中;
- 当这个 PV 被回收后会以
archieved-{namespace}-{pvcName}-{pvName}这样的命名格式存在 NFS 服务器上;
我们可以直接通过 Helm 安装:
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner --set nfs.server=192.168.0.211 --set nfs.path=/data/disk-0/sub/Data/k8s-nfs等待安装完成之后,可以设置该StorageClass作为默认:
kubectl patch storageclass nfs-client -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'Step 10: 卸载集群
# 卸载集群
sudo kubeadm reset --cri-socket=unix:///var/run/crio/crio.sock
# 清空iptable表
sudo iptables -F && sudo iptables -t nat -F && sudo iptables -t mangle -F && sudo iptables -X
# 以上命令会清空所有的iptables信息,包括docker的,这时候需要重启docker重建相关的iptables
sudo systemctl restart docker配置文件路径
| Configuration | Location |
|---|---|
| Static Pods Location (etcd, api-server, controller manager and scheduler) | /etc/kubernetes/manifests |
| TLS Certificates location (kubernetes-ca, etcd-ca and kubernetes-front-proxy-ca) | /etc/kubernetes/pki |
| Admin Kubeconfig File | /etc/kubernetes/admin.conf |
| Kubelet configuration | /var/lib/kubelet/config.yaml |
其他工具
calicoctl
wget -O calicoctl https://github.com/projectcalico/calico/releases/download/v3.25.0/calicoctl-linux-amd64
chmod a+x calicoctl
sudo mv calicoctl /usr/local/bin
# 获取ip池范围
calicoctl get ippoolcrictl
当您使用 Docker 以外的容器运行时时,可以使用 crictl 实用程序来调试节点上的容器。
VERSION="v1.30.0"
wget https://github.com/kubernetes-sigs/cri-tools/releases/download/$VERSION/crictl-$VERSION-linux-amd64.tar.gz
sudo tar zxvf crictl-$VERSION-linux-amd64.tar.gz -C /usr/local/bin
rm -f crictl-$VERSION-linux-amd64.tar.gz
# 配置文件在/etc/crictl.yaml中,可以修改cri对于k8s启动的容器,均可以利用crictl进行操作(类似于docker)
nerdctl
可以像docker命令一样操作containerd。
- 安装:去github上下载Releases · containerd/nerdctl
- 随后解压放到
/usr/local/bin中。 - 配置
/etc/nerdctl/nerdctl.toml,添加address = "/run/k3s/containerd/containerd.sock" # 如果是k3s的话,这样写,如果是别的的话,填写对应的container.sock路径 namespace = "k8s.io" - 随后就可以使用命令了
常用命令
Secret
Kubernetes中,Secret是用来存储敏感数据的(如密码、令牌、密钥等)的资源。虽然它在设计上是为了提高安全性,但存储的数值是通过Base64编码的,因此如果有足够的权限,Secret的内容可以直接被解码查看。
kubectl get secret -n <namespace> -o yamlContext
# 修改当前的namespace为argocd,默认是default
kubectl config set-context --current --namespace=argocd