二十、Kubernetes基础-67-docker-k8s128-cluster-deployment

二十、Kubernetes基础-67-docker-k8s128-cluster-deployment 基于Docker-CE与cri-dockerd部署Kubernetes 1.28高可用集群——从容器运行时到控制平面的全链路实战摘要Kubernetes 1.24 正式移除内置 dockershim 后以 Docker 作为容器运行时的集群必须通过 cri-dockerd 适配器桥接 CRI 接口。本文以K8S 1.28 Docker-CE 24.x cri-dockerd 0.3.x为技术栈从内核参数调优、容器运行时编译安装、镜像加速、kubeadm 引导初始化到多节点 join 全流程深入剖析每一步的底层原理与工程细节覆盖生产级部署中常见的坑点与调优策略。一、技术背景与架构演进1.1 dockershim 的移除与 CRI 架构Kubernetes 自 1.5 引入CRIContainer Runtime Interface规范旨在解耦 kubelet 与具体容器运行时。然而早期 Docker 并未实现 CRIKubernetes 在 kubelet 内部维护了一个名为dockershim的垫片层┌─────────────────────────────────────────────────┐ │ kubelet │ │ ┌───────────┐ ┌──────────────────────────┐ │ │ │ CRI API │───│ dockershim (内置垫片) │ │ │ └───────────┘ └──────────┬───────────────┘ │ └──────────────────────────────┼──────────────────┘ │ Docker Engine API ┌─────────▼─────────┐ │ Docker Daemon │ │ ┌──────────────┐ │ │ │ containerd │ │ │ │ ┌─────────┐ │ │ │ │ │ runc │ │ │ │ │ └─────────┘ │ │ │ └──────────────┘ │ └───────────────────┘这条调用链为kubelet → dockershim → Docker Daemon → containerd → runc存在两个核心问题维护成本dockershim 约 2000 行代码嵌入 kubelet 主干每次 Docker API 变更都需要同步适配性能开销请求经过 Docker Daemon 的额外序列化/反序列化创建 Pod 的延迟增加 ~200msKubernetes 1.20 发布弃用通知1.24 正式移除 dockershim。此后若仍使用 Docker 作为运行时必须部署外部适配器cri-dockerd。1.2 cri-dockerd 的定位cri-dockerd是 Mirantis 维护的开源项目其本质是将原 dockershim 代码从 kubelet 中剥离为独立的 gRPC 服务┌──────────┐ CRI gRPC ┌──────────────┐ Docker API ┌──────────────┐ │ kubelet │ ──────────────────│ cri-dockerd │ ────────────────│ Docker Daemon│ └──────────┘ unix:///var/run/ └──────────────┘ └──────┬───────┘ cri-dockerd.sock │ ┌──────▼───────┐ │ containerd │ └──────┬───────┘ ┌──────▼───────┐ │ runc │ └──────────────┘为什么还要用 Docker在企业环境中Docker 的docker build、docker compose、镜像调试docker exec等开发者工具链仍有不可替代的地位。cri-dockerd 让团队在保留 Docker 工作流的同时接入 CRI 标准。1.3 版本矩阵组件版本说明OSCentOS 7.9 / Ubuntu 22.04内核 ≥ 5.4 推荐Docker-CE24.0.x稳定长期支持cri-dockerd0.3.8适配 CRI v1Kubernetes1.28.x2023 LTSCalico3.26.x网络插件下篇二、环境规划与系统预配置2.1 节点规划──────────────────────────────────────────────────────── │ 角色 │ 主机名 │ IP │ 配置 │ ──────────────────────────────────────────────────────── │ Master-01 │ k8s-master01 │ 10.0.0.10 │ 4C/8G/50G │ │ Worker-01 │ k8s-worker01 │ 10.0.0.11 │ 4C/8G/50G │ │ Worker-02 │ k8s-worker02 │ 10.0.0.12 │ 4C/8G/50G │ ────────────────────────────────────────────────────────生产建议Master 至少 3 节点实现 etcd 多数派仲裁Worker 根据业务规模横向扩展。2.2 主机名与 hosts 解析# 所有节点执行hostnamectl set-hostname k8s-master01# 各节点对应修改cat/etc/hostsEOF 10.0.0.10 k8s-master01 10.0.0.11 k8s-worker01 10.0.0.12 k8s-worker02 EOF2.3 关闭 swapkubelet 默认拒绝在开启 swap 的节点上运行可通过--fail-swap-onfalse覆盖但生产环境不推荐swapoff-ased-ris/.*swap.*/#//etc/fstab# 验证free-h# Swap 行应全部为 0底层原因Kubernetes 的 QoS 模型Guaranteed / Burstable / BestEffort依赖 cgroup 的内存限制精确控制。swap 的存在使得 OOM Killer 的触发时机不可预测导致 Pod 驱逐策略失效。2.4 关闭防火墙与 SELinux# 防火墙systemctl stop firewalldsystemctl disable firewalld# SELinuxsetenforce0sed-is/^SELINUXenforcing$/SELINUXdisabled//etc/selinux/config生产替代方案不关闭防火墙而是精确放行所需端口Master6443API Server、2379-2380etcd、10250-10252kubelet/controller/schedulerWorker10250kubelet、30000-32767NodePort2.5 内核参数与模块加载# 加载必要内核模块cat/etc/modules-load.d/k8s.confEOF overlay br_netfilter EOFmodprobe overlay modprobe br_netfilter# 网络桥接与转发参数cat/etc/sysctl.d/k8s.confEOF net.bridge.bridge-nf-call-iptables 1 net.bridge.bridge-nf-call-ip6tables 1 net.ipv4.ip_forward 1 EOFsysctl--system参数解析参数作用overlay为 Docker 的 overlay2 存储驱动提供联合文件系统支持br_netfilter使桥接流量经过 iptables/netfilter 处理Pod 跨节点通信必需bridge-nf-call-iptables二层桥接帧经过三层 iptables 规则Service 的 DNAT/SNAT 依赖此项ip_forward允许内核在不同网络接口间转发数据包Pod 网络路由必需2.6 时间同步yuminstall-ychrony# CentOS# apt install -y chrony # Ubuntusystemctlenablechronyd--nowchronyc sources-v节点间时钟偏差超过数秒将导致 etcd 选举异常、证书验证失败。三、Docker-CE 安装与配置3.1 配置 Docker 仓库# CentOSyuminstall-yyum-utils device-mapper-persistent-data lvm2 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo# Ubuntuapt-getupdateapt-getinstall-yca-certificatescurlgnupginstall-m0755-d/etc/apt/keyringscurl-fsSLhttps://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg|gpg--dearmor-o/etc/apt/keyrings/docker.gpgechodeb [arch$(dpkg --print-architecture)signed-by/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu$(lsb_release-cs)stable/etc/apt/sources.list.d/docker.listapt-getupdate3.2 安装指定版本# 查看可用版本yum list docker-ce--showduplicates|sort-r|head-20# 安装 Docker-CE 24.0yuminstall-ydocker-ce-24.0.7-1.el7 docker-ce-cli-24.0.7-1.el7 containerd.io# Ubuntu# apt-get install -y docker-ce5:24.0.7-1~ubuntu.22.04~jammy docker-ce-cli5:24.0.7-1~ubuntu.22.04~jammy containerd.io3.3 配置 Docker Daemonmkdir-p/etc/dockercat/etc/docker/daemon.jsonEOF { exec-opts: [native.cgroupdriversystemd], log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 }, storage-driver: overlay2, storage-opts: [ overlay2.override_kernel_checktrue ], registry-mirrors: [ https://hub-mirror.c.163.com, https://mirror.baidubce.com ], data-root: /data/docker, live-restore: true } EOF关键配置深度解析配置项值原理说明cgroupdriversystemdsystemdK8S 1.22 强制要求 kubelet 与运行时使用同一 cgroup 驱动。systemd 作为 PID 1 进程管理者由它管理 cgroup 层级树可避免两套 cgroup 管理器竞争导致的资源泄漏overlay2存储驱动基于 OverlayFS 的 CoW 文件系统相比 aufs 性能更优顺序读提升 ~20%且为内核原生支持live-restoretrueDocker Daemon 重启时不中断运行中容器对于 Daemon 升级场景至关重要data-root/data/docker分离数据目录至独立磁盘避免镜像/容器数据撑满系统盘log-opts100m × 3单容器日志滚动上限 300MB防止日志洪泛导致磁盘耗尽生产中曾有容器日志单文件达 TB 级别的事故3.4 启动与验证systemctl daemon-reload systemctlenabledocker--now# 验证dockerinfo|grep-ECgroup Driver|Storage Driver|Docker Root Dir# 期望输出# Cgroup Driver: systemd# Storage Driver: overlay2# Docker Root Dir: /data/dockerdockerrun--rmhello-world四、cri-dockerd 编译安装与配置4.1 安装 Go 编译环境cri-dockerd 使用 Go 语言开发需要 Go 1.20 编译wgethttps://go.dev/dl/go1.21.5.linux-amd64.tar.gztar-C/usr/local-xzfgo1.21.5.linux-amd64.tar.gzcat/etc/profile.d/go.shEOF export GOROOT/usr/local/go export GOPATH/opt/gopath export PATH$GOROOT/bin:$GOPATH/bin:$PATH export GOPROXYhttps://goproxy.cn,direct EOFsource/etc/profile.d/go.sh go version# go version go1.21.5 linux/amd644.2 编译 cri-dockerdcd/optgitclone https://github.com/Mirantis/cri-dockerd.gitcdcri-dockerdgitcheckout v0.3.8# 编译makecri-dockerd# 产物位于 cri-dockerd/cri-dockerd# 安装二进制install-oroot-groot-m0755 cri-dockerd /usr/local/bin/cri-dockerd# 验证cri-dockerd--version# cri-dockerd 0.3.8 (commit-hash)无法科学上网时的替代方案从 GitHub Releases 页面直接下载预编译二进制wgethttps://github.com/Mirantis/cri-dockerd/releases/download/v0.3.8/cri-dockerd-0.3.8.amd64.tgztarxf cri-dockerd-0.3.8.amd64.tgzinstall-oroot-groot-m0755 cri-dockerd/cri-dockerd /usr/local/bin/4.3 配置 systemd 服务cat/usr/lib/systemd/system/cri-docker.serviceEOF [Unit] DescriptionCRI Interface for Docker Application Container Engine Documentationhttps://docs.mirantis.com Afternetwork-online.target firewalld.service docker.service Wantsnetwork-online.target Requiresdocker.service [Service] Typenotify ExecStart/usr/local/bin/cri-dockerd \ --container-runtime-endpointunix:///var/run/cri-dockerd.sock \ --pod-infra-container-imageregistry.aliyuncs.com/google_containers/pause:3.9 \ --network-plugincni \ --cni-bin-dir/opt/cni/bin \ --cni-conf-dir/etc/cni/net.d ExecReload/bin/kill -s HUP $MAINPID TimeoutSec0 RestartSec2 Restartalways StartLimitBurst3 StartLimitInterval60s LimitNOFILEinfinity LimitNPROCinfinity LimitCOREinfinity [Install] WantedBymulti-user.target EOFcat/usr/lib/systemd/system/cri-docker.socketEOF [Unit] DescriptionCRI Docker Socket for the API PartOfcri-docker.service [Socket] ListenStream/var/run/cri-dockerd.sock SocketMode0660 SocketUserroot SocketGroupdocker [Install] WantedBysockets.target EOF关键参数解析--pod-infra-container-image指定 pause 容器镜像国内需替换为阿里云镜像。pause 容器是 Pod 中所有容器的父容器它创建并持有 Pod 的网络命名空间Network Namespace其他容器通过--netcontainer:pause-id共享该命名空间实现 Pod 内容器间 localhost 通信--network-plugincni声明使用 CNI 插件管理网络Calico/Flannel而非 Docker 的原生桥接网络Requiresdocker.service确保 Docker Daemon 先于 cri-dockerd 启动构成强依赖链4.4 启动服务systemctl daemon-reload systemctlenablecri-docker--now# 验证 socket 存在ls-la/var/run/cri-dockerd.sock# srw-rw---- 1 root docker 0 ... /var/run/cri-dockerd.sock# 验证服务状态systemctl status cri-docker# Active: active (running)# 功能验证通过 crictl 连接cat/etc/crictl.yamlEOF runtime-endpoint: unix:///var/run/cri-dockerd.sock image-endpoint: unix:///var/run/cri-dockerd.sock timeout: 10 debug: false EOFcrictl info# 应返回运行时信息五、Kubernetes 1.28 组件安装5.1 配置 K8S 仓库# CentOScat/etc/yum.repos.d/kubernetes.repoEOF [kubernetes] nameKubernetes baseurlhttps://mirrors.aliyun.com/kubernetes-new/core/stable/v1.28/rpm/ enabled1 gpgcheck1 gpgkeyhttps://mirrors.aliyun.com/kubernetes-new/core/stable/v1.28/rpm/repodata/repomd.xml.key EOF# Ubuntucurl-fsSLhttps://mirrors.aliyun.com/kubernetes-new/core/stable/v1.28/deb/Release.key|gpg--dearmor-o/etc/apt/keyrings/kubernetes-apt-keyring.gpgechodeb [signed-by/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.28/deb/ //etc/apt/sources.list.d/kubernetes.listapt-getupdate5.2 安装 kubeadm / kubelet / kubectl# CentOSyuminstall-ykubelet-1.28.2 kubeadm-1.28.2 kubectl-1.28.2--disableexcludeskubernetes# Ubuntu# apt-get install -y kubelet1.28.2-1.1 kubeadm1.28.2-1.1 kubectl1.28.2-1.1# apt-mark hold kubelet kubeadm kubectlsystemctlenablekubelet# 注意此时 kubelet 会反复重启CrashLoop这是正常行为——它在等待 kubeadm init 提供配置三组件职责组件职责kubeadm集群引导工具负责生成 CA 证书、静态 Pod 清单、bootstrap token 等kubelet节点代理通过 CRI 接口管理 Pod 生命周期向 API Server 上报节点状态kubectl命令行客户端与 API Server 交互的主要工具5.3 配置 kubelet 使用 cri-dockerdcat/etc/sysconfig/kubeletEOF KUBELET_EXTRA_ARGS--container-runtime-endpointunix:///var/run/cri-dockerd.sock EOF此配置确保 kubelet 连接 cri-dockerd 的 socket 而非默认的 containerd socket。六、kubeadm 初始化 Master 节点6.1 生成初始化配置文件kubeadm config print init-defaultskubeadm-config.yaml编辑关键字段apiVersion:kubeadm.k8s.io/v1beta3kind:InitConfigurationnodeRegistration:criSocket:unix:///var/run/cri-dockerd.sock# 指定 CRI socketname:k8s-master01localAPIEndpoint:advertiseAddress:10.0.0.10# Master IPbindPort:6443---apiVersion:kubeadm.k8s.io/v1beta3kind:ClusterConfigurationkubernetesVersion:v1.28.2controlPlaneEndpoint:10.0.0.10:6443# HA 场景替换为 VIPimageRepository:registry.aliyuncs.com/google_containers# 国内镜像networking:serviceSubnet:10.96.0.0/12podSubnet:10.244.0.0/16# 与 Calico 配置一致dnsDomain:cluster.localetcd:local:dataDir:/var/lib/etcd---apiVersion:kubelet.config.k8s.io/v1beta1kind:KubeletConfigurationcgroupDriver:systemd# 与 Docker 一致6.2 预拉取镜像kubeadm config images pull\--configkubeadm-config.yaml\--cri-socket unix:///var/run/cri-dockerd.sock# 验证dockerimages|grep-Ekube-|etcd|coredns|pause6.3 执行初始化kubeadm init--configkubeadm-config.yaml --upload-certs--v5初始化流程深度解析kubeadm init 的 13 个阶段[init] → 版本校验、配置验证 [preflight] → 系统预检端口、swap、cgroup、CRI 连通性 [certs] → 生成 PKI 证书CA、API Server、etcd、front-proxy 等共 ~10 对 [kubeconfig] → 生成 kubeconfigadmin、controller-manager、scheduler、kubelet [kubelet-start] → 写入 kubelet 配置并启动 [control-plane] → 生成静态 Pod 清单/etc/kubernetes/manifests/ [etcd] → 生成 etcd 静态 Pod 清单 [upload-config] → 将配置存入 ConfigMapkube-system/kubeadm-config [upload-certs] → 加密上传证书到 SecretHA join 使用 [mark-control] → 给 Master 节点打 taintNoSchedule [bootstrap-token] → 创建 bootstrap tokenWorker join 使用 [kubelet-finalize] → 更新 kubelet 的客户端证书轮转配置 [addon] → 安装 CoreDNS 和 kube-proxy 附加组件6.4 配置 kubectlmkdir-p$HOME/.kubecp-i/etc/kubernetes/admin.conf$HOME/.kube/configchown$(id-u):$(id-g)$HOME/.kube/config# 验证kubectl get nodes# NAME STATUS ROLES AGE VERSION# k8s-master01 NotReady control-plane 60s v1.28.2# NotReady 是正常的——尚未安装网络插件6.5 证书体系详解kubeadm 生成的证书位于/etc/kubernetes/pki//etc/kubernetes/pki/ ├── ca.crt / ca.key # 集群根 CA ├── apiserver.crt / apiserver.key # API Server 服务端证书 ├── apiserver-kubelet-client.crt/key # API Server → kubelet 客户端证书 ├── apiserver-etcd-client.crt/key # API Server → etcd 客户端证书 ├── front-proxy-ca.crt/key # 聚合 API 层 CA ├── front-proxy-client.crt/key # 聚合 API 客户端证书 ├── etcd/ │ ├── ca.crt / ca.key # etcd 独立 CA │ ├── server.crt / server.key # etcd 服务端证书 │ ├── peer.crt / peer.key # etcd 节点间通信证书 │ └── healthcheck-client.crt/key # etcd 健康检查证书 └── sa.key / sa.pub # ServiceAccount 签发密钥对安全要点ca.key、sa.key、etcd/ca.key是集群最高权限密钥泄露等同于集群完全失控。生产环境应严格管控其访问权限chmod 0600并考虑硬件安全模块HSM存储。七、Worker 节点加入集群7.1 在 Worker 节点执行 joinMaster 初始化成功后输出的 join 命令kubeadmjoin10.0.0.10:6443\--tokentoken\--discovery-token-ca-cert-hash sha256:hash\--cri-socket unix:///var/run/cri-dockerd.sock关键必须追加--cri-socket参数指向 cri-dockerd否则 kubeadm 会尝试连接默认的 containerd socket 导致失败。7.2 Token 过期处理Token 默认 24 小时过期。若需重新生成# Master 上执行kubeadm token create --print-join-command# 获取 ca-cert-hashopenssl x509-pubkey-in/etc/kubernetes/pki/ca.crt|\openssl rsa-pubin-outformder2/dev/null|\openssl dgst-sha256-hex|seds/^.* //7.3 验证集群状态kubectl get nodes-owide# NAME STATUS ROLES AGE VERSION INTERNAL-IP OS-IMAGE# k8s-master01 NotReady control-plane 5m v1.28.2 10.0.0.10 CentOS 7.9# k8s-worker01 NotReady none 2m v1.28.2 10.0.0.11 CentOS 7.9# k8s-worker02 NotReady none 1m v1.28.2 10.0.0.12 CentOS 7.9所有节点显示NotReady是预期行为——需要安装 CNI 网络插件Calico这将在下一篇文章中详细介绍。八、常见问题与排查8.1 kubelet 启动失败journalctl-xeukubelet|tail-50错误信息原因解决failed to run Kubelet: running with swap on is not supportedswap 未关闭swapoff -aError getting node...connection refusedAPI Server 未就绪检查静态 Podcrictl psfailed to get sandbox image...pause 镜像拉取失败配置 cri-dockerd 的--pod-infra-container-imagecgroup driver cgroupfs ! systemdcgroup 驱动不一致Docker daemon.json 和 kubelet 配置统一为 systemd8.2 cri-dockerd 连接失败# 检查 socket 是否存在ls-la/var/run/cri-dockerd.sock# 检查服务日志journalctl-ucri-docker-f# 手动测试 CRI 连通性crictl --runtime-endpoint unix:///var/run/cri-dockerd.sock info8.3 镜像拉取超时# 检查 Docker 镜像加速是否生效dockerinfo|grep-A5Registry Mirrors# 手动预拉取并重命名dockerpull registry.aliyuncs.com/google_containers/kube-apiserver:v1.28.2dockertag registry.aliyuncs.com/google_containers/kube-apiserver:v1.28.2\registry.k8s.io/kube-apiserver:v1.28.28.4 kubeadm reset重置重来kubeadm reset --cri-socket unix:///var/run/cri-dockerd.sock-frm-rf/etc/kubernetes/ /var/lib/etcd/ /var/lib/kubelet/$HOME/.kube iptables-Fiptables-tnat-Fiptables-tmangle-Fiptables-X九、总结本文完整覆盖了基于 Docker-CE cri-dockerd 部署 Kubernetes 1.28 集群的全流程架构理解厘清 dockershim 移除后的 CRI 架构演进理解 cri-dockerd 的桥接角色系统预配置内核参数、cgroup 驱动、网络模块——每项配置都有其 Kubernetes 网络模型层面的必然性Docker-CEoverlay2 存储驱动、systemd cgroup 驱动、日志滚动策略的生产级配置cri-dockerd从源码编译到 systemd 服务配置深入 pause 容器与 CNI 的关联kubeadm 引导13 个初始化阶段的逐步解析PKI 证书体系的安全要点Worker 加入token 管理与 CRI socket 指定下一篇将介绍 Calico 网络插件的部署与集群可用性全面验证包括 Pod 跨节点通信、Service 负载均衡、DNS 解析、网络策略等内容。参考资料Kubernetes 官方文档 - Container Runtimescri-dockerd GitHub 仓库Docker 官方安装文档kubeadm 参考文档