Kubernetes集群部署完整指南(基于Rocky Linux 9.4)

本文档详细整理了Kubernetes(简称K8s)集群的部署流程,涵盖集群规划、操作系统准备、Docker环境配置、cri-docker配置、K8s集群部署及Ingress-Nginx可选安装,所有步骤均经过验证,可直接参考执行,同时对关键操作的原理和注意事项进行扩展说明,确保部署过程清晰可追溯。

1. Kubernetes集群规划

K8s集群采用“1主2从”架构,即1个管理节点(Master)负责集群控制,2个工作节点(Node)负责运行容器化应用。各节点资源规划如下表所示,硬件配置满足K8s最小部署要求(2核CPU、4G内存),同时预留足够存储用于系统和应用数据。

主机名 IP地址 角色 操作系统 硬件配置 核心作用
master01 192.168.100.60 管理节点 Rocky Linux 9.4 2core/4G内存/50G 运行K8s控制平面组件(API Server、etcd、Controller Manager、Scheduler)
node01 192.168.100.70 工作节点 Rocky Linux 9.4 2core/4G内存/50G 运行用户部署的容器化应用,由Master节点调度管理
node02 192.168.100.80 工作节点 Rocky Linux 9.4 2core/4G内存/50G 同node01,提供应用运行的冗余能力,避免单点故障

扩展说明

  • 操作系统选择Rocky Linux 9.4,因其是CentOS的兼容替代版,稳定性高且支持K8s官方推荐的内核版本;
  • 硬件配置若用于生产环境,建议Master节点升级至4核8G内存(确保控制平面稳定),工作节点根据应用需求增加CPU/内存/存储。

2. 操作系统准备工作

所有节点(master01、node01、node02)均需执行以下操作,确保系统环境满足K8s部署要求。操作前需以root用户登录,或通过sudo -i切换至root权限。

2.1 配置主机名称

为每个节点设置唯一主机名,便于集群管理和识别(默认主机名为localhost,需修改)。

2.1.1 Master01节点

执行以下命令设置主机名为master01,设置后可通过hostname命令验证:

[root@localhost ~]# hostnamectl hostname master01
2.1.2 Node01节点

同理,设置node01节点主机名:

[root@localhost ~]# hostnamectl hostname node01
2.1.3 Node02节点

设置node02节点主机名:

[root@localhost ~]# hostnamectl hostname node02

扩展说明

  • hostnamectl是Systemd工具集中的主机名管理命令,修改后立即生效,且重启后不会失效(无需编辑/etc/hostname文件);
  • 若需临时修改主机名(重启后失效),可使用hostname 新主机名命令,但生产环境建议使用hostnamectl进行永久修改。

2.2 配置系统hosts文件(全部节点)

通过hosts文件配置节点间的静态域名解析,避免依赖外部DNS,确保集群内节点通信稳定。需在所有节点执行以下命令,将IP与主机名的映射关系写入/etc/hosts

[root@localhost ~]# echo "192.168.100.60 master01" >> /etc/hosts
[root@localhost ~]# echo "192.168.100.70 node01" >> /etc/hosts
[root@localhost ~]# echo "192.168.100.80 node02" >> /etc/hosts

验证方法
执行ping master01ping node01命令,若能正常收到响应,说明hosts配置生效。

扩展说明

  • /etc/hosts文件的优先级高于DNS解析,集群内节点间的通信(如Master与Node的心跳、容器跨节点网络)会依赖此配置;
  • 若后续节点IP或主机名变更,需同步更新所有节点的hosts文件,否则会导致集群通信故障。

2.3 关闭防火墙和SELinux(全部节点)

K8s集群内节点间需要频繁通信(如API Server端口6443、etcd端口2379等),防火墙会拦截这些流量;SELinux(安全增强型Linux)会限制容器对系统资源的访问,因此需关闭两者以避免部署异常。

2.3.1 关闭并禁用防火墙
# 临时停止防火墙服务(立即生效,重启后失效)
[root@localhost ~]# systemctl stop firewalld.service
# 永久禁用防火墙服务(重启后不自动启动)
[root@localhost ~]# systemctl disable firewalld.service
2.3.2 关闭并禁用SELinux
# 临时关闭SELinux(立即生效,重启后失效)
[root@localhost ~]# setenforce 0
# 永久禁用SELinux(修改配置文件,重启后生效)
[root@localhost ~]# sed -i 's#SELINUX=enforcing#SELINUX=disabled#' /etc/selinux/config

验证方法

  • 防火墙:执行systemctl status firewalld,输出“inactive (dead)”表示已关闭;
  • SELinux:执行getenforce,输出“Permissive”表示临时关闭;重启节点后再次执行getenforce,输出“Disabled”表示永久禁用。

扩展说明

  • 生产环境若需开启防火墙,需手动放行K8s所需端口(如6443、2379、2380、10250等),但配置复杂,建议在集群部署完成后再按需调整;
  • SELinux的“Permissive”模式为宽容模式(仅记录日志不拦截操作),“Disabled”为完全禁用,K8s官方推荐使用“Disabled”模式。

2.4 配置国内系统镜像源和安装EPEL源

Rocky Linux默认镜像源位于国外,下载速度慢且易失败,需替换为国内阿里云镜像源;同时安装EPEL(Extra Packages for Enterprise Linux)源,获取更多第三方软件包(如后续需要的性能分析工具)。

2.4.1 配置阿里云系统源(全部节点)

Rocky Linux的系统源配置文件位于/etc/yum.repos.d/目录,文件名为rocky-*.repo(如rocky-baseos.reporocky-appstream.repo)。执行以下命令替换为阿里云镜像源,并备份原配置文件(后缀为.bak):

[root@master01 ~]# sed -e 's|^mirrorlist=|#mirrorlist=|g' \
-e 's|^#baseurl=http://dl.rockylinux.org/$contentdir|baseurl=https://mirrors.aliyun.com/rockylinux|g' \
-i.bak \
/etc/yum.repos.d/rocky-*.repo

# 生成yum缓存,加速后续软件安装
[root@master01 ~]# yum makecache

扩展说明

  • sed命令的作用:① 将所有mirrorlist=开头的行注释(#mirrorlist=),避免使用国外镜像列表;② 将baseurl替换为阿里云的Rocky Linux镜像地址;③ -i.bak表示修改文件前先备份原文件(如rocky-baseos.repo.bak),便于后续回滚;
  • yum makecache会将镜像源的软件包信息缓存到本地,后续安装软件时无需重复从远程获取,提升速度。
2.4.2 配置EPEL源(全部节点)

EPEL源由Fedora项目维护,提供大量Enterprise Linux缺失的软件包。此处使用华为云的EPEL源(国内速度快),通过vi编辑/etc/yum.repos.d/epel.repo文件:

[root@master01 ~]# vi /etc/yum.repos.d/epel.repo

将以下内容写入文件(覆盖原有内容,若文件不存在则新建):

[epel]
name=Extra Packages for Enterprise Linux $releasever - $basearch
baseurl=https://repo.huaweicloud.com/epel/$releasever/Everything/$basearch/
enabled=1
gpgcheck=1
countme=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-$releasever

[epel-debuginfo]
name=Extra Packages for Enterprise Linux $releasever - $basearch - Debug
baseurl=https://repo.huaweicloud.com/epel/$releasever/Everything/$basearch/debug/
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-$releasever
gpgcheck=1

[epel-source]
name=Extra Packages for Enterprise Linux $releasever - $basearch - Source
baseurl=https://repo.huaweicloud.com/epel/$releasever/Everything/source/tree/
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-$releasever
gpgcheck=1

保存退出后,执行yum makecache更新缓存:

[root@master01 ~]# yum makecache

扩展说明

  • 配置项说明:① enabled=1表示启用该源(epel主源启用,debuginfosource源禁用,因日常无需调试和源码包);② gpgcheck=1表示校验软件包签名,确保安全性;③ $releasever$basearch是变量,自动匹配系统版本(如9.4)和架构(如x86_64);
  • gpgkey文件不存在,可执行yum install -y epel-release自动安装EPEL源及对应的GPG密钥(但此方法可能使用国外源,建议优先手动配置国内源)。
2.4.3 安装会用到的工具
yum -y install vim bash-completion net-tools lrzsz

2.5 时区和时间(全部节点)

K8s集群对时间同步要求极高,若节点间时间偏差超过5分钟,会导致证书验证失败、容器调度异常等问题。此处使用系统自带的chrony工具进行时间同步(Rocky Linux 9默认预装)。

2.5.1 检查当前时区和时间

执行以下命令查看当前系统时间和时区:

[root@master01 ~]# systemctl restart chronyd
[root@master01 ~]# systemctl enable chronyd
[root@master01 ~]# hwclock -w
[root@master01 ~]# timedatectl
[root@master01 ~]# date

示例输出(正确配置应为Asia/Shanghai时区,时间与当前北京时间一致):

Local time: Fri 2024-05-31 18:26:23 CST  # 北京时间(CST=UTC+8)
Universal time: Fri 2024-05-31 10:26:23 UTC  # 世界协调时间
RTC time: Fri 2024-05-31 10:26:23
Time zone: Asia/Shanghai (CST, +0800)  # 正确时区
System clock synchronized: yes  # 已同步
NTP service: active  # chrony服务已启动
RTC in local TZ: no

2.5 修改系统最大打开文件数(全部节点)

Linux系统默认的最大打开文件数(nofile)较低(通常为1024),而K8s和Docker运行时会同时打开大量文件(如日志、配置、网络连接),若超过限制会导致服务异常。需通过/etc/security/limits.conf文件修改默认值。

  1. 编辑配置文件:

    [root@master01 ~]# vi /etc/security/limits.conf
    
  2. 在文件末尾添加以下两行(*表示所有用户生效):

    * soft nofile 65535
    * hard nofile 65535
    

扩展说明

  • soft nofile:软限制,用户可临时超过该值,但系统会给出警告;
  • hard nofile:硬限制,用户无法超过该值,是系统的强制限制;
  • 修改后需重新登录(或重启节点)生效,验证方法:执行ulimit -n,输出65535表示配置成功。

2.6 修改内核参数(全部节点)

K8s对Linux内核有特定要求(如TCP连接优化、网络转发等),需通过/etc/sysctl.conf文件调整内核参数,确保集群性能和稳定性。

  1. 编辑内核参数配置文件:

    [root@master01 ~]# vi /etc/sysctl.conf
    
  2. 在文件末尾添加以下参数:

    # 启用TCP SYN Cookie,防止SYN洪水攻击
    net.ipv4.tcp_syncookies = 1
    # 最大TCP TIME_WAIT连接数,减少连接堆积
    net.ipv4.tcp_max_tw_buckets = 20480
    # 最大TCP SYN等待队列长度,提升高并发能力
    net.ipv4.tcp_max_syn_backlog = 20480
    # 最大网络设备接收队列长度,避免数据包丢失
    net.core.netdev_max_backlog = 262144
    # TCP连接关闭后,FIN_WAIT_2状态的超时时间(秒),加速连接回收
    net.ipv4.tcp_fin_timeout = 20
    
  3. 执行以下命令使内核参数立即生效(无需重启节点):

    [root@master01 ~]# sysctl -p
    

扩展说明

  • sysctl -p命令会加载/etc/sysctl.conf文件中的所有参数,若需加载其他文件,可指定路径(如sysctl -p /etc/sysctl.d/k8s.conf);
  • 这些参数是K8s官方推荐的基础优化项,生产环境可根据实际负载进一步调整(如增加net.ipv4.tcp_tw_reuse = 1允许复用TIME_WAIT连接)。

2.7 关闭Swap(全部节点)

Swap是Linux系统的虚拟内存,当物理内存不足时会使用磁盘作为内存。但K8s要求禁用Swap,原因是:① 磁盘IO速度远低于内存,启用Swap会导致容器性能大幅下降;② K8s依赖内存限制(resources.limits.memory)进行调度,Swap会干扰内存限制的生效。

  1. 临时关闭Swap(立即生效,重启后失效):

    [root@master01 ~]# swapoff -a
    
  2. 永久关闭Swap(修改/etc/fstab文件,注释Swap挂载项):

    [root@master01 ~]# sed -ri 's/.*swap.*/#&/' /etc/fstab
    

验证方法
执行free -m,若Swap行的totalusedfree均为00B,表示Swap已关闭。

扩展说明

  • sed -ri 's/.*swap.*/#&/' /etc/fstab命令的作用:匹配所有包含“swap”的行,在行首添加#注释,从而禁止系统启动时挂载Swap;
  • 若后续需重新启用Swap,可编辑/etc/fstab,删除Swap行前的#,然后执行swapon -a

2.8 安装系统性能分析工具和其他(全部节点)

安装常用的系统工具,用于后续集群部署和运维过程中的性能监控、问题排查(如gcc用于编译源码,sysstat用于查看系统资源使用情况)。

执行以下命令安装工具:

[root@master01 ~]# yum install -y gcc autoconf sysstat

工具说明

  • gcc:C语言编译器,部分软件(如后续可能用到的自定义插件)需要编译源码;
  • autoconf:自动化配置工具,配合gcc使用,生成软件的编译配置文件;
  • sysstat:包含iostat(磁盘IO监控)、mpstat(CPU使用监控)、sar(系统资源统计)等命令,用于排查集群性能瓶颈。

2.9 开启Bridge网桥过滤(全部节点)

K8s的网络插件(如Calico、Flannel)依赖Linux Bridge(网桥)的流量过滤功能,需开启bridge-nf-call-iptablesbridge-nf-call-ip6tables参数,确保网桥能转发IPv4和IPv6流量,并应用iptables规则;同时开启ip_forward,允许节点转发IP数据包(跨节点容器通信必需)。

2.9.1 配置网桥过滤参数
  1. 创建并编辑/etc/sysctl.d/k8s.conf文件(专门用于K8s相关的内核参数):

    [root@master01 ~]# vi /etc/sysctl.d/k8s.conf
    
  2. 在文件中写入以下参数:

    # 允许网桥转发IPv6流量时应用iptables规则
    net.bridge.bridge-nf-call-ip6tables = 1
    # 允许网桥转发IPv4流量时应用iptables规则
    net.bridge.bridge-nf-call-iptables = 1
    # 开启IP数据包转发(跨节点容器通信必需)
    net.ipv4.ip_forward = 1
    
2.9.2 加载br_netfilter内核模块

br_netfilter模块是网桥过滤功能的核心,需手动加载(部分系统默认未加载):

# 加载模块并查看是否加载成功
[root@master01 ~]# modprobe br_netfilter && lsmod | grep br_netfilter

若输出br_netfilter 24576 0,表示模块加载成功。

2.9.3 使网桥过滤参数生效

执行以下命令加载/etc/sysctl.d/k8s.conf文件,使参数立即生效:

[root@master01 ~]# sysctl -p /etc/sysctl.d/k8s.conf

扩展说明

  • 若需br_netfilter模块开机自动加载,可执行echo "br_netfilter" > /etc/modules-load.d/br_netfilter.conf
  • 这些参数是K8s网络插件的基础,若未配置,后续安装Calico等插件会出现容器无法跨节点通信的问题。

3. Docker环境准备

K8s支持多种容器运行时(如Docker、containerd、CRI-O),本文选择Docker作为容器运行时(需配合cri-docker实现CRI接口,因Docker本身不直接支持K8s的CRI标准)。所有节点均需安装Docker并配置。

3.1 配置阿里云Docker源(全部节点)

Docker默认镜像源位于国外,下载速度慢,需替换为阿里云Docker源。首先安装yum-utils工具(用于管理yum源),然后添加阿里云Docker源:

# 安装yum-utils(包含yum-config-manager命令)
[root@master01 ~]# yum install -y yum-utils
# 添加阿里云Docker CE源(Docker CE为社区版,免费使用)
[root@master01 ~]# yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

扩展说明

  • 阿里云Docker源地址为http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo,适用于CentOS/Rocky Linux系统(两者兼容);
  • 若执行yum-config-manager时提示“command not found”,说明yum-utils未安装成功,可重新执行yum install -y yum-utils

3.2 查看可用的Docker版本(全部节点)

执行以下命令查看阿里云源中可用的Docker CE版本,选择稳定版本进行安装(本文选择25.0.5-1.el9,适配Rocky Linux 9):

[root@master01 ~]# yum list docker-ce.x86_64 --showduplicates | sort -r

示例输出(版本号从高到低排序):

docker-ce.x86_64            3:26.1.4-1.el9             docker-ce-stable
docker-ce.x86_64            3:26.1.3-1.el9             docker-ce-stable
...
docker-ce.x86_64            3:25.0.5-1.el9             docker-ce-stable  # 本文选择的版本
...

扩展说明

  • 版本号格式说明:3:25.0.5-1.el9中,25.0.5是Docker主版本,1.el9表示适配Rocky Linux 9;
  • 建议选择K8s官方兼容的Docker版本(可参考K8s文档),避免版本过高或过低导致兼容性问题。

3.3 安装Docker,指定安装25.0.5-1.el9版本(全部节点)

执行以下命令安装指定版本的Docker CE(避免默认安装最新版本,确保稳定性):

[root@master01 ~]# yum -y install docker-ce-25.0.5-1.el9

验证方法
执行docker --version,输出Docker version 25.0.5, build 2456e98表示安装成功。

扩展说明

  • 安装过程中会自动安装Docker依赖(如containerd.iodocker-ce-cli),无需手动安装;
  • 若安装失败(如依赖冲突),可执行yum clean all && yum makecache清理缓存后重新尝试。

3.4 配置Docker Cgroup控制组(全部节点)

Cgroup(Control Group)是Linux内核的资源管理工具,用于限制容器的CPU、内存等资源。K8s默认使用systemd作为Cgroup驱动,而Docker默认Cgroup驱动可能为cgroupfs,需将Docker的Cgroup驱动修改为systemd,确保K8s与Docker的Cgroup驱动一致(否则会导致Kubelet启动失败)。

  1. 创建并编辑Docker配置文件/etc/docker/daemon.json(默认不存在):

    [root@master01 ~]# vi /etc/docker/daemon.json
    
  2. 在文件中写入以下内容(指定Cgroup驱动为systemd):

    { "registry-mirrors":
            [ "https://docker.m.daocloud.io",
              "https://dockerproxy.com",
              "https://docker.mirrors.ustc.edu.cn",
              "https://docker.nju.edu.cn"
            ],
             "exec-opts": ["native.cgroupdriver=systemd"]
    }
    

3.5 启动Docker服务并设置开机自启(全部节点)

配置完成后,启动Docker服务,并设置为开机自启(确保节点重启后Docker自动运行):

# 启动Docker服务并设置开机自启(--now表示立即启动)
[root@master01 ~]# systemctl enable docker --now

验证方法

  • 执行systemctl status docker,输出“active (running)”表示Docker服务正常运行;
  • 执行docker info | grep Cgroup Driver,输出Cgroup Driver: systemd表示Cgroup驱动配置成功。

4. 配置cri-docker

K8s从1.24版本开始不再直接支持Docker(因Docker未实现K8s的CRI接口),需通过cri-docker(Docker的CRI适配器)实现K8s与Docker的通信。所有节点均需配置cri-docker。

4.1 下载cri-docker(Master节点先执行,再复制到其他节点)(如果下载不了,有安装包)

从GitHub下载cri-docker的二进制包(版本为0.3.9,适配Docker 25.x和K8s 1.28.x):

# 下载cri-docker二进制包(-c表示断点续传,避免下载中断)
[root@master01 ~]# wget -c https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.9/cri-dockerd-0.3.9.amd64.tgz

扩展说明

  • 若GitHub下载速度慢,可通过国内镜像(如Gitee)或代理工具加速;
  • 确认cri-docker版本与Docker、K8s版本兼容(可参考cri-docker官方文档)。

4.2 解压cri-docker(Master节点先执行)

将下载的压缩包解压到/usr/local/bin/目录(系统可执行路径,便于后续调用):

# 解压到/usr/local/bin/,--strip-components=1表示去掉压缩包内的顶层目录
[root@master01 ~]# tar -xvf cri-dockerd-0.3.9.amd64.tgz --strip-components=1 -C /usr/local/bin/

验证方法
执行cri-dockerd --version,输出cri-dockerd 0.3.9 (xxxx)表示解压成功。

4.3 下载cri-docker的systemd服务文件(Master节点先执行)

从GitHub下载cri-docker的systemd服务文件(cri-docker.servicecri-docker.socket),用于通过systemd管理cri-docker服务:

# 下载cri-docker.service文件
[root@master01 ~]# wget -O /etc/systemd/system/cri-docker.service https://raw.githubusercontent.com/Mirantis/cri-dockerd/master/packaging/systemd/cri-docker.service

# 下载cri-docker.socket文件
[root@master01 ~]# wget -O /etc/systemd/system/cri-docker.socket https://raw.githubusercontent.com/Mirantis/cri-dockerd/master/packaging/systemd/cri-docker.socket

4.4 编辑cri-docker.service文件(Master节点先执行)

修改cri-docker.service中的ExecStart行,指定Docker镜像仓库(避免拉取国外镜像失败)和cri-docker的运行参数:

  1. 编辑服务文件:

    [root@master01 ~]# vi /etc/systemd/system/cri-docker.service
    
  2. 找到ExecStart行,替换为以下内容:

    ExecStart=/usr/local/bin/cri-dockerd --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.9 --container-runtime-endpoint=unix:///var/run/cri-dockerd.sock --cri-dockerd-root-directory=/var/lib/dockershim --cri-dockerd-root-directory=/var/lib/docker
    

参数说明

  • --pod-infra-container-image:指定Pod的基础镜像(pause镜像),用于创建Pod的网络命名空间,此处使用阿里云镜像(避免拉取k8s.gcr.io/pause失败);
  • --container-runtime-endpoint:指定cri-docker的通信端点(Unix socket),K8s通过该端点与Docker通信;
  • --cri-dockerd-root-directory:指定cri-docker的工作目录(存储容器元数据等)。

4.5 编辑cri-docker.socket文件(Master节点先执行)

修改cri-docker.socket中的ListenStream行,指定cri-docker的监听地址(与ExecStart中的--container-runtime-endpoint一致):

  1. 编辑socket文件:

    [root@master01 ~]# vi /etc/systemd/system/cri-docker.socket
    
  2. 找到ListenStream行,替换为以下内容:

    ListenStream=/var/run/cri-dockerd.sock
    

4.6 复制cri-docker文件到其他节点(Master节点执行)

将Master节点下载的cri-docker压缩包、服务文件复制到node01和node02节点,避免重复下载和配置:

  1. 复制压缩包到node01:

    [root@master01 ~]# scp cri-dockerd-0.3.9.amd64.tgz root@192.168.100.70:/root/
    
  2. 复制压缩包到node02:

    [root@master01 ~]# scp cri-dockerd-0.3.9.amd64.tgz root@192.168.100.80:/root/
    
  3. 复制修改后的服务文件到node01:

    [root@master01 ~]# scp /etc/systemd/system/cri-docker.s* root@192.168.100.70:/etc/systemd/system/
    
  4. 复制修改后的服务文件到node02:

    [root@master01 ~]# scp /etc/systemd/system/cri-docker.s* root@192.168.100.80:/etc/systemd/system/
    

扩展说明

  • scp命令用于跨节点复制文件,格式为scp 源文件 目标用户@目标IP:目标路径
  • 执行scp时若提示“Host key verification failed”,可删除~/.ssh/known_hosts文件后重新尝试(或手动确认主机密钥)。

4.7 其他节点解压cri-docker(node01和node02节点执行)

在node01和node02节点,执行与Master节点相同的解压命令:

node01节点:
[root@node01 ~]# tar -xvf cri-dockerd-0.3.9.amd64.tgz --strip-components=1 -C /usr/local/bin/
node02节点:
[root@node02 ~]# tar -xvf cri-dockerd-0.3.9.amd64.tgz --strip-components=1 -C /usr/local/bin/

4.8 启动并设置cri-docker开机自启(全部节点)

所有节点执行以下命令,启动cri-docker服务并设置开机自启:

# 重新加载systemd配置(因修改了服务文件)
[root@master01 ~]# systemctl daemon-reload
# 启动cri-docker服务并设置开机自启
[root@master01 ~]# systemctl enable cri-docker.service --now

验证方法

  • 执行systemctl status cri-docker,输出“active (running)”表示cri-docker服务正常运行;
  • 执行ls -l /var/run/cri-dockerd.sock,若文件存在,说明cri-docker的通信端点已正常创建。

5. kubeadm部署Kubernetes集群

kubeadm是K8s官方提供的集群部署工具,可快速初始化Master节点、添加工作节点。本节步骤中,部分操作仅需在Master节点执行,部分需在所有节点执行,已明确标注。

5.1 配置阿里云K8s源(全部节点)

K8s默认源位于国外,需替换为阿里云K8s源(适配K8s 1.28版本),确保kubeletkubeadmkubectl能正常下载。

  1. 编辑K8s源配置文件/etc/yum.repos.d/k8s.repo

    [root@master01 ~]# vi /etc/yum.repos.d/k8s.repo
    
  2. 将以下内容写入文件:

    [kubernetes]
    name=Kubernetes
    baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.28/rpm/
    enabled=1
    gpgcheck=1
    gpgkey=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.28/rpm/repodata/repomd.xml.key
    

扩展说明

  • baseurl中的v1.28对应K8s 1.28版本,若需部署其他版本,需修改版本号(如v1.27);
  • gpgcheck=1表示校验软件包签名,确保安全性,gpgkey指定签名密钥的地址。

5.2 安装K8s集群所需软件包(全部节点)

安装K8s的核心组件:kubelet(运行在所有节点,负责管理容器生命周期)、kubeadm(集群部署工具)、kubectl(K8s命令行客户端,用于管理集群):

[root@master01 ~]# yum install -y kubelet kubeadm kubectl

验证方法
执行kubelet --versionkubeadm --versionkubectl --version,均输出对应版本号(如v1.28.10)表示安装成功。

扩展说明

  • yum install -y会自动安装与当前源匹配的最新稳定版本(如1.28.10),无需指定版本;
  • 若安装失败,可执行yum clean all && yum makecache清理缓存后重新尝试。

5.3 配置K8s Cgroup控制组(全部节点)

K8s的kubelet组件也需要指定Cgroup驱动,需与Docker的Cgroup驱动(systemd)一致,否则kubelet无法启动。

  1. 编辑kubelet配置文件/etc/sysconfig/kubelet

    [root@master01 ~]# vi /etc/sysconfig/kubelet
    
  2. 在文件中写入以下内容(指定Cgroup驱动为systemd):

    KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"
    

扩展说明

  • KUBELET_EXTRA_ARGS用于传递kubelet的额外参数,除了Cgroup驱动,还可添加其他参数(如--node-ip=节点IP指定节点IP);
  • 修改后无需重启kubelet,后续kubeadm init会自动应用该配置。

5.4 配置kubelet开机自启(全部节点)

kubelet是K8s的核心组件,需设置为开机自启,确保节点重启后kubelet自动运行(kubeadm init会自动启动kubelet,此处仅设置自启):

[root@master01 ~]# systemctl enable kubelet.service

5.5 初始化K8s集群(仅Master节点执行)

通过kubeadm init初始化Master节点,生成集群控制平面,并输出工作节点加入集群的命令。

5.5.1 打印Master节点所需的镜像文件(验证镜像源)

执行以下命令,查看初始化Master节点需要拉取的K8s镜像列表(确保镜像源配置正确):

[root@master01 ~]# kubeadm config images list

示例输出(镜像地址已自动替换为阿里云镜像):

registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver:v1.28.10
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager:v1.28.10
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler:v1.28.10
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy:v1.28.10
registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9
registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.5.9-0
registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.10.1

扩展说明

  • 若输出的镜像地址为k8s.gcr.io/xxx(国外地址),说明K8s源配置有误,需重新检查/etc/yum.repos.d/k8s.repo文件;
  • 这些镜像是K8s控制平面的核心组件,初始化过程会自动拉取。
5.5.2 生成集群初始化配置文件

通过kubeadm config print init-defaults生成默认的初始化配置文件(kubeadm-config.yaml),便于后续修改参数:

[root@master01 ~]# kubeadm config print init-defaults > kubeadm-config.yaml
5.5.3 修改初始化配置文件

编辑kubeadm-config.yaml,修改关键参数(如Master节点IP、容器运行时端点、镜像仓库):

[root@master01 ~]# vi kubeadm-config.yaml

需修改的参数如下(其他参数保持默认):

localAPIEndpoint:
  advertiseAddress: 192.168.100.60  # 修改为Master节点的IP地址(192.168.100.60)
  bindPort: 6443  # K8s API Server端口(默认6443,无需修改)
nodeRegistration:
  criSocket: unix:///var/run/cri-dockerd.sock  # 修改为cri-docker的通信端点(指定使用Docker)
  imagePullPolicy: IfNotPresent  # 镜像拉取策略(本地存在则不重新拉取,无需修改)
  name: master01  # 修改为Master节点的主机名(master01)
  taints: null  # 清除Master节点的污点(允许工作负载调度到Master,可选,默认null)
# 新增或修改镜像仓库地址(使用阿里云镜像,避免拉取国外镜像失败)
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers

扩展说明

  • advertiseAddress:Master节点的IP地址,用于向其他节点广播API Server的地址;
  • criSocket:指定容器运行时的通信端点,此处为cri-docker的端点(unix:///var/run/cri-dockerd.sock),若使用containerd,需修改为unix:///run/containerd/containerd.sock
  • imageRepository:指定K8s镜像的仓库地址,阿里云镜像仓库registry.cn-hangzhou.aliyuncs.com/google_containers与官方仓库k8s.gcr.io的镜像完全一致。
5.5.4 执行集群初始化

使用修改后的配置文件初始化Master节点,--upload-certs参数用于将集群证书上传到etcd(便于后续添加其他Master节点,实现高可用):

[root@master01 ~]# kubeadm init --config kubeadm-config.yaml --upload-certs

初始化过程说明

  1. 检查系统环境(如Swap是否关闭、内核参数是否正确);
  2. 拉取K8s控制平面镜像(如kube-apiserver、etcd);
  3. 启动控制平面组件(运行在容器中);
  4. 生成admin.conf(集群管理员配置文件);
  5. 输出工作节点加入集群的命令(需保存,后续用于node01和node02节点)。

成功标志
初始化完成后,输出类似以下内容(关键信息已标注):

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

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.100.60:6443 --token abcdef.0123456789abcdef \
  --discovery-token-ca-cert-hash sha256:fedc160482922f0c5c4077121fb45ed13ca9e169f937628eda2cbfcbba99015e \
  --cri-socket=unix:///var/run/cri-dockerd.sock

扩展说明

  • 若初始化失败(如镜像拉取超时、端口被占用),可执行kubeadm reset清理环境后重新尝试;
  • --upload-certs参数仅在需要部署多Master节点(高可用集群)时必需,单Master节点可省略,但建议保留(便于后续扩展)。
5.5.5 配置kubectl环境变量(仅Master节点执行)

kubectl需要通过admin.conf文件连接K8s API Server,需将该文件复制到当前用户的.kube目录(或设置KUBECONFIG环境变量):

  1. 若当前为root用户,执行以下命令设置环境变量(立即生效,重启后失效):

    [root@master01 ~]# export KUBECONFIG=/etc/kubernetes/admin.conf
    
  2. 若需永久生效(推荐),将环境变量写入/etc/profile文件:

    [root@master01 ~]# echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> /etc/profile
    # 使环境变量立即生效
    [root@master01 ~]# source /etc/profile
    
  3. 若为普通用户(如ubuntu),执行以下命令(推荐生产环境使用普通用户操作kubectl):

    [ubuntu@master01 ~]$ mkdir -p $HOME/.kube
    [ubuntu@master01 ~]$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    [ubuntu@master01 ~]$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
    

验证方法
执行kubectl version,输出Client Version: v1.28.10Server Version: v1.28.10表示kubectl已成功连接到API Server。

5.5.6 工作节点加入集群(仅node01和node02节点执行)

在node01和node02节点,执行Master节点初始化完成后输出的kubeadm join命令(需包含--cri-socket参数,指定使用Docker):

node01节点:
[root@node01 ~]# kubeadm join 192.168.100.60:6443 --token abcdef.0123456789abcdef \
  --discovery-token-ca-cert-hash sha256:fedc160482922f0c5c4077121fb45ed13ca9e169f937628eda2cbfcbba99015e \
  --cri-socket=unix:///var/run/cri-dockerd.sock
node02节点:
[root@node02 ~]# kubeadm join 192.168.100.60:6443 --token abcdef.0123456789abcdef \
  --discovery-token-ca-cert-hash sha256:fedc160482922f0c5c4077121fb45ed13ca9e169f937628eda2cbfcbba99015e \
  --cri-socket=unix:///var/run/cri-dockerd.sock

成功标志
执行后输出This node has joined the cluster successfully!表示工作节点已成功加入集群。

扩展说明

  • kubeadm join命令中的token过期(默认24小时),可在Master节点执行kubeadm token create --print-join-command重新生成加入命令;
  • --discovery-token-ca-cert-hash用于验证Master节点的CA证书,确保加入的是可信集群,不可修改。

5.6 下载Calico网络插件配置文件(仅Master节点执行)

K8s集群初始化后,需部署网络插件(如Calico、Flannel),否则Pod无法跨节点通信。本文选择Calico(功能强大,支持网络策略),下载其部署配置文件:

# 下载Calico 3.24.1版本的配置文件(适配K8s 1.28)
[root@master01 ~]# wget https://raw.githubusercontent.com/projectcalico/calico/v3.24.1/manifests/calico.yaml

扩展说明

  • Calico版本需与K8s版本兼容(可参考Calico官方文档),3.24.1版本适配K8s 1.24-1.28;
  • 若GitHub下载速度慢,可手动复制配置文件内容到本地calico.yaml文件。

5.7 部署Calico网络插件(仅Master节点执行)

通过kubectl apply命令部署Calico,所有节点会自动拉取Calico镜像并启动相关组件:

[root@master01 ~]# kubectl apply -f calico.yaml

部署过程说明

  • Calico会在所有节点启动calico-node容器(负责网络转发和策略 enforcement);
  • 在Master节点启动calico-kube-controllers容器(负责管理Calico资源,如网络策略)。

验证方法
执行kubectl get pods -n kube-system -l k8s-app=calico-node,若所有calico-nodePod的状态为Running,表示Calico部署成功。

5.8 查看集群节点状态(仅Master节点执行)

执行以下命令查看所有节点的状态,确认节点已成功加入集群且状态正常:

[root@master01 ~]# kubectl get nodes

示例输出(所有节点状态为Ready,表示集群正常):

NAME       STATUS   ROLES           AGE   VERSION
master01   Ready    control-plane   16h   v1.28.10
node01     Ready    <none>          16h   v1.28.10
node02     Ready    <none>          16h   v1.28.10

状态说明

  • Ready:节点正常,可调度Pod;
  • NotReady:节点异常(如Calico未部署、kubelet未运行),需排查日志(journalctl -u kubelet);
  • control-plane:Master节点的角色标签,工作节点默认无角色标签(可通过kubectl label node node01 node-role.kubernetes.io/worker=worker添加标签)。

5.9 查看K8s集群核心组件状态(仅Master节点执行)

执行以下命令查看kube-system命名空间下的所有Pod(K8s核心组件均运行在该命名空间),确认组件正常运行:

[root@master01 ~]# kubectl get pod -n kube-system

示例输出(所有Pod状态为Running,表示核心组件正常):

NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-9d57d8f49-dkkkn    1/1     Running   1 (15h ago)   16h
calico-node-jllq5                          1/1     Running   1 (15h ago)   16h
calico-node-q8fhr                          1/1     Running   1 (15h ago)   16h
calico-node-tbdqk                          1/1     Running   1 (15h ago)   16h
coredns-6554b8b87f-55k4c                   1/1     Running   1 (15h ago)   16h
coredns-6554b8b87f-c6hrv                   1/1     Running   1 (15h ago)   16h
etcd-master01                               1/1     Running   1 (15h ago)   16h
kube-apiserver-master01                     1/1     Running   1 (15h ago)   16h
kube-controller-manager-master01            1/1     Running   1 (15h ago)   16h
kube-proxy-7xl56                             1/1     Running   1 (15h ago)   16h
kube-proxy-9x4dp                             1/1     Running   1 (15h ago)   16h
kube-proxy-trgk8                             1/1     Running   1 (15h ago)   16h
kube-scheduler-master01                     1/1     Running   1 (15h ago)   16h

核心组件说明

  • etcd:K8s的数据库,存储集群所有资源信息(如Pod、Service);
  • kube-apiserver:K8s的API网关,所有集群操作均通过API Server执行;
  • kube-controller-manager:运行各种控制器(如Node控制器、Deployment控制器),确保集群状态与期望状态一致;
  • kube-scheduler:负责Pod的调度(将Pod分配到合适的工作节点);
  • kube-proxy:运行在所有节点,负责Service的负载均衡和网络规则配置;
  • coredns:负责集群内的DNS解析(如Pod解析Service名称);
  • calico-*:Calico网络插件组件。

问题排查
若某个Pod状态为CrashLoopBackOff(反复重启),可执行kubectl logs Pod名称 -n kube-system查看日志,定位问题(如镜像拉取失败、配置错误)。

6. 安装Ingress-Nginx(可选,不用域名访问可不装)

Ingress-Nginx是K8s的Ingress控制器,用于管理外部流量进入集群(如通过域名访问Pod)。本文因镜像拉取问题未完成部署,若需使用域名访问,可参考以下步骤部署(需解决镜像拉取问题)。

6.1 下载Ingress-Nginx部署文件(仅Master节点执行)

从K8s官方GitHub下载Ingress-Nginx的部署文件(适用于裸金属集群):

[root@master01 ~]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/baremetal/deploy.yaml

扩展说明

  • 部署文件deploy.yaml包含Ingress-Nginx的所有资源(Deployment、Service、ConfigMap等);
  • 裸金属集群(非云环境)需使用该部署文件,云环境(如AWS、阿里云)需选择对应的Provider部署文件。

6.2 部署Ingress-Nginx到K8s集群(仅Master节点执行)

执行以下命令部署Ingress-Nginx:

[root@master01 ~]# kubectl apply -f deploy.yaml

部署说明

  • Ingress-Nginx会在工作节点启动ingress-nginx-controllerPod(负责处理外部流量);
  • 创建ingress-nginx-controllerService(默认类型为NodePort,可修改为LoadBalancer,但裸金属集群需额外配置MetalLB)。

镜像拉取问题解决
若部署过程中ingress-nginx-controllerPod因镜像拉取失败(如k8s.gcr.io/ingress-nginx/controller:xxx无法拉取),可手动替换为国内镜像(如阿里云镜像):

  1. 编辑deploy.yaml文件,找到image字段:

    [root@master01 ~]# vi deploy.yaml
    
  2. image: k8s.gcr.io/ingress-nginx/controller:v1.10.0@sha256:xxx替换为阿里云镜像:

    image: registry.cn-hangzhou.aliyuncs.com/google_containers/ingress-nginx-controller:v1.10.0
    
  3. 重新部署:

    [root@master01 ~]# kubectl apply -f deploy.yaml
    

验证方法
执行kubectl get pods -n ingress-nginx,若ingress-nginx-controllerPod状态为Running,表示Ingress-Nginx部署成功。

总结

本文档详细梳理了K8s集群从环境准备到部署完成的全流程,核心步骤包括:

  1. 规划“1主2从”集群架构,明确各节点资源配置;
  2. 配置操作系统(主机名、hosts、防火墙、镜像源、内核参数等),满足K8s部署要求;
  3. 安装Docker并配置Cgroup驱动,确保与K8s兼容;
  4. 配置cri-docker,实现K8s与Docker的CRI接口通信;
  5. 使用kubeadm初始化Master节点、添加工作节点,部署Calico网络插件;
  6. 可选部署Ingress-Nginx,实现域名访问。

部署完成后,可通过kubectl runkubectl apply等命令部署应用,验证集群功能(如Pod创建、Service访问、跨节点通信)。生产环境中,建议进一步配置高可用(多Master节点)、监控(Prometheus+Grafana)、日志(ELK Stack)等组件,确保集群稳定运行。

更多推荐