众说周知，Kubernetes 从 1.24 起就删除了 Dockershim 相关代码，现在整理了一下国内网络环境下使用 containerd 作为运行时的集群搭建步骤1. 系统准备# 允许 iptables 检查桥接流量 sudo tee /etc/modules-load.d/containerd.conf << EOF overlay br_netfilter EOF sudo tee /etc/sysctl.d/k8s.conf << EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 EOF # 使设置生效 sudo modprobe overlay br_netfilter sudo sysctl --system # 禁用虚拟内存 sudo swapoff -a2. 安装 Kubernetes 组件2.1 Debian/Ubuntu# 安装 containerd curl -sL http://mirrors.aliyun.com/docker-ce/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/docker-ce.gpg echo "deb http://mirrors.aliyun.com/docker-ce/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list sudo apt update sudo apt install -y containerd.io # 安装 kubeadm curl -sL https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/kubernetes-archive-keyring.gpg echo "deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list sudo apt update sudo apt install -y kubeadm=1.21.14-00 kubectl=1.21.14-00 kubelet=1.21.14-002.2 CentOS# 安装 containerd sudo curl https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker-ce.repo sudo yum install -y containerd.io sudo systemctl enable containerd # 安装 kubeadm sudo tee /etc/yum.repos.d/kubernetes.repo << EOF [kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64 enabled=0 gpgcheck=1 repo_gpgcheck=0 gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF sudo yum install -y --enablerepo=kubernetes kubeadm-1.21.14 kubelet-1.21.14 kubectl-1.21.14 sudo systemctl enable kubelet2.3 配置容器运行时# 配置容器运行时 sudo tee /etc/containerd/config.toml << EOF version = 2 [plugins."io.containerd.grpc.v1.cri"] sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.6" [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc] runtime_type = "io.containerd.runc.v2" [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] SystemdCgroup = true [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] endpoint = ["https://hub-mirror.c.163.com"] [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:5000"] endpoint = ["http://registry.lan:5000"] EOF sudo systemctl restart containerd # 添加自动填充 sudo tee /etc/profile.d/kubectl.sh << EOF source <(kubectl completion bash) source <(crictl completion bash) export KUBECONFIG=/etc/kubernetes/admin.conf EOF # 配置 crictl sudo tee /etc/crictl.yaml << EOF runtime-endpoint: unix:///run/containerd/containerd.sock image-endpoint: unix:///run/containerd/containerd.sock EOF3. 使用 Kubeadm 引导集群sudo kubeadm init --kubernetes-version=1.21.14 --token=abcdef.0123456789abcdef \ --apiserver-advertise-address=$(ip addr show dev eth0 | grep -Po 'inet \K[\d.]+') \ --cri-socket=unix:///run/containerd/containerd.sock \ --image-repository=registry.aliyuncs.com/google_containers稍等几分钟，K8S 的 Master 节点就启动起来了# 其他节点加入集群 sudo kubeadm join node1.lan:6443 --token=abcdef.0123456789abcdef --discovery-token-unsafe-skip-ca-verification3.1 kubernetes 组件安装# 链接 kubeconfig sudo chmod +r /etc/kubernetes/admin.conf # 配置网络插件 kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml # 去除污点 kubectl taint node --all node-role.kubernetes.io/master- # 安装 Helm curl -sL https://get.helm.sh/helm-v3.9.2-linux-amd64.tar.gz | sudo tar zxf - --strip-components=1 -C /usr/local/bin # 安装 Traefik Ingress Controller helm install traefik -n kube-system --repo https://helm.traefik.io/traefik traefik3.2 集群清理sudo kubeadm reset --cri-socket=unix:///run/containerd/containerd.sock -f sudo rm -rf /var/lib/{calico,etcd,kubelet,kubernetes,cni} /etc/cni/net.d /etc/kubernetes /opt/cni/bin/*参考资料弃用 Dockershim 的常见问题生产环境
Kubernetes (以下简称 K8S) 是 Docker 推出之后最热门的容器编排技术，然而想在本地将 K8S 跑起来，并不像我们想象的那么容易。存在以下几点「问题」：网络：K8S 里面的一些镜像在国内很难将其 pull 下来，当然这可以通过代理、镜像站等方式解决。资源：在内存资源不这么充裕的本地开发环境，去部署一个 K8S 集群，这无疑不是一个明智的选择。那么有没有什么方案可以更优雅更轻量更快速搭建一个 K8S 集群呢？答案就是 K3D目前主流的本地 k8s 运行方式有很多minikube 仅支持单节点，但是我们期望可以跑一个集群的方式，方便我们去 Mock 节点宕机之后 K8S 自动调度的 case ✖️microk8s 是 Ubuntu 生态里提供的一个可以单机运行的 k8s 版本，配合 Ubuntu 生态的 multipass，可以模拟多节点，但是在本就资源紧张的本地环境，通过虚拟机的方式模拟多节点，显然并不是我想要的 ✖️kind 是一个基于 Docker 构建 Kubernetes 集群的工具，Kubernetes in Docker ✔️k3d 是一个可以让 k3s 运行在 Docker 中的工具，相比于 kind ，启动速度更快，占用资源更小，也是本文采取的方案 ✅关于 k3d 以及 kind 的对比，可以参考 K3d vs Kind 谁更适合本地研发。1. 什么是 K3Dk3s 是 Rancher 公司推出非常快速且轻量级的完全兼容的 Kubernetes 发行版（CNCF 认证） k3d 是一个可以让 k3s 运行在 Docker 中的工具，它提供了一个简单的 CLI 来创建、运行和删除具有 1 到 N 个节点的 Kubernetes 集群最大程度减轻了外部依赖性，仅需要 kernel 和 cgroup 挂载。占用资源比完整版的 K8S 少了不少内置了很多组件，开箱即用，而且每一个组件都是可替换的详情参考官方文档 什么是 K3s?2. 通过 docker-machine 启动 Docker 服务官方提供的 Docker Desktop 是基于 WSL2 实现的，需要开启 Hyper-V 功能。 这样会使整个 Windows 都跑在虚拟机中，导致某些虚拟化相关的应用不正常 (比如某些模拟器)，而且内存占用也不太可控。 本文采用了基于 boot2docker 的方式运行 Docker 服务，定制性更灵活一些。2.1 安装必备工这里强烈推荐使用 Git for Windows 自带的 MinGW 命令行SHELL，使开发体验更加贴近与 Linux。以下操作均在 Git Bash 中进行首先需要安装虚拟机软件 VirtualBox 然后需要下载如下命令工具并添加到环境变量 PATH 中docker-machine 下载后重命名为 docker-machine.exek3d 下载后重命名为 k3d.exekubectl 官方的 K8S本文中上面这些工具下载到了 D:\Docker\bin，并将 D:\Docker\bin 添加到环境变量中同时也配置了如下环境变量，将虚拟机文件的储存位置修改为 D 盘，避免占用系统空间MACHINE_STORAGE_PATH=D:\Docker在 ~/.profile 文件添加如下内容配置命令行自动补全sudo tee /etc/profile.d/kubectl.sh << EOF source <(kubectl completion bash) source <(k3d completion bash) 2.2 使用 boot2docker 启动 Docker 引擎下面创建了一个磁盘大小为 60000 MB，CPU 使用 2 个核心的虚拟机docker-machine create --virtualbox-cpu-count 2 \ --engine-registry-mirror https://hub-mirror.c.163.com \ --virtualbox-disk-size 60000 --virtualbox-memory 2048 \ --virtualbox-no-share default # 每次使用 docker 时都需要执行如下命令 eval $(docker-machine env --shell bash default)稍等片刻，当出现以下日志时，说明 Docker 服务已启动完成第一次创建 Docker 实例会下载 boot2docker.iso 作为启动镜像，国内用户可以通过添加参数 --virtualbox-boot2docker-url https://github.com.cnpmjs.org/dragonflylee/boot2docker/releases/latest/download/boot2docker.iso 加速镜像下载3 使用 k3d 启动 k3s 集群3.1 创建 k3s 节点首先我们尝试创建包含主节点和容器仓库的集群eval $(docker-machine env --shell bash) k3d cluster create --api-port 6443 \ -p 0.0.0.0:80:80@loadbalancer \ --k3s-arg "--disable=traefik@server:0" \ --registry-create registry:0.0.0.0:5000当出现下面的日志时，k3s 集群就创建成功了此时，我们按照日志提示，运行 kubectl cluster-info 查看下当前集群的信息运行 kubectl get pod -o wide -A 命令，当所有 Pod 的状态都是 Running 或者 Done 的时候，集群就初始化完毕了如果遇到 cgroups: cannot find cgroup mount destination: unknown. 的错误提示，请执行如下命令docker-machine ssh default sudo sh - << EOF mkdir /sys/fs/cgroup/systemd mount -t cgroup -o none,name=systemd cgroup /sys/fs/cgroup/systemd EOF3.2 安装 K3S 组件Helm 是 Kubernetes 的首选包管理工具而 K3s 不需要任何特殊的配置就可以使用 Helm 命令行工具，如下命令使用 Helm CRD 部署 traefik 服务kubectl create -f - << EOF apiVersion: helm.cattle.io/v1 kind: HelmChart metadata: name: traefik namespace: kube-system spec: chart: traefik repo: https://helm.traefik.io/traefik valuesContent: |- ports: websecure: expose: false EOFTraefik Ingress 是原生支持 K8S 的反向代理工具下面的例子是使用 Traefik CRD 开启内置的仪表盘kubectl apply -f - << EOF apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: traefik-dashboard namespace: kube-system spec: entryPoints: - web routes: - match: Host(\`traefik.domain.com\`) kind: Rule services: - name: api@internal kind: TraefikService EOF更多配置参考 https://docs.rancher.cn/docs/k3s/helm/_index4. 使用 KinD 启动 k8s 集群KinD 顾名思义 Kubernetes in Docker，是一个使用 Docker 容器在本地运行 Kubernetes 集群的工具。相比 k3d，Kind 更贴近原生 Kubernetes，适合用于开发测试 Kubernetes 原生组件。4.1 安装 KinD 命令行工具首先下载最新版本的 KinD https://kind.sigs.k8s.io/dl/latest/kind-windows-amd64kind create cluster --image kindest/node:v1.21.14 --config=- << EOF kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 networking: apiServerAddress: "$(docker-machine ip)" apiServerPort: 6443 nodes: - role: control-plane extraPortMappings: - containerPort: 80 hostPort: 80 kubeadmConfigPatches: - | kind: ClusterConfiguration etcd: local: extraArgs: listen-metrics-urls: http://0.0.0.0:2381 controllerManager: extraArgs: bind-address: 0.0.0.0 scheduler: extraArgs: bind-address: 0.0.0.0 containerdConfigPatches: - |- [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] endpoint = ["https://hub-mirror.c.163.com"] [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:5000"] endpoint = ["http://registry:5000"] EOF参数描述参考 https://kind.sigs.k8s.io/docs/user/quick-start#configuring-your-kind-cluster4.2 使用 Helm 部署 Ingress部署 Nginxhttps://docs.nginx.com/nginx-ingress-controller/# 生成测试用 SSL 证书 openssl req -x509 -nodes -newkey rsa:4096 -keyout tls.key -out tls.crt -days 3650 -subj "/CN=kube" kubectl create secret tls ingress-wildcard-tls -n kube-system --cert=tls.crt --key=tls.key # 安装控制器 helm install nginx -n kube-system --repo https://helm.nginx.com/stable nginx-ingress --values - << EOF controller: image: tag: latest-alpine service: create: false controller: hostNetwork: true setAsDefaultIngress: true EOF部署 traefik 控制器helm install traefik -n kube-system --repo https://helm.traefik.io/traefik traefik --values - << EOF service: enabled: false ports: web: hostPort: 80 websecure: expose: false deployment: kind: DaemonSet ingressClass: enabled: true isDefaultClass: true EOF4.3 部署 K8S 控制台kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.2.0/aio/deploy/alternative.yaml # 添加 ingress 路由 kubectl create ing -n kubernetes-dashboard dashboard --rule="domain.com/*=kubernetes-dashboard:80,tls" # 添加用户权限 kubectl create serviceaccount admin-user -n kubernetes-dashboard kubectl create clusterrolebinding admin-user --serviceaccount=kubernetes-dashboard:admin-user --clusterrole=cluster-admin # 获取 Token kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')参考文档:KinD 参考Kubernetes 文档Kubernetes APIK3S 文档