Docker + K8s集群搭建实战:1 Master+2 Node,含Harbor私有仓库与软路由

简介

本文从零开始搭建一套完整的Kubernetes学习环境,包含Harbor私有镜像仓库iKuai软路由网关 以及1 Master + 2 Node的K8s集群

与常规教程不同,本文将带你深入理解:

  • 为什么需要单独安装cri-dockerd?
  • Master和Node节点各自需要哪些组件?
  • 容器运行时(Docker vs containerd)该如何选择?
  • Pod创建背后的完整调用链路

无论你是刚入门K8s还是想理清底层原理,这篇实战指南都值得一读。

前言

主机规划:Harbor + iKuai + K8s 集群(1 Master + 2 Node)

网络说明

K8s 集群采用仅主机模式 部署,节点间可互通但无法访问外网。为实现镜像拉取、外部通信等需求,引入 iKuai 软路由 作为集群网关。iKuai 通过 NAT 模式提供外网出口,并为各节点分配网关(192.168.10.200)与 DNS,确保集群在一个隔离、可控、具备外网访问能力的网络环境中运行。

ikuai主机

1.下载与虚拟机创建

  1. 下载镜像:从 iKuai 官网下载 32 位 ISO(实验环境要求低,真实环境用 64 位)。
  2. 创建虚拟机
    • 使用 VMware 新建虚拟机,选择"稍后安装操作系统"。
    • 操作系统类型选择"其他"。
    • 配置处理器(至少 1 核)、内存(1GB)、磁盘(默认 IDE 类型,32 位 iKuai 仅支持 IDE)。
    • 网络:第一块网卡使用仅主机模式 (用于与 Kubernetes 集群通信),后续再添加第二块 NAT 模式网卡(用于访问外网)。
    • 择 I/O 控制器类型选推荐:BusLogic
    • 磁盘类型选推荐:IDE
    • 选创建新磁盘 & 磁盘存储为单个文件

2.虚拟机配置与系统安装

先不开机!!!

  1. 编辑虚拟机设置
    • 添加第二块网卡(NAT 模式)。
    • 将 CD/DVD 关联到下载的 iKuai ISO 镜像。
  2. 启动虚拟机 ,按提示输入 y 开始安装,安装完成后自动重启。

3.基本网络配置(控制台操作)

  1. 重启后进入控制台菜单,选择 2、设置 LAN/WAN 地址

  2. 输入 0 设置 LAN1 地址,例如:

    192.168.10.100/255.255.255.0

  3. Esc 返回上级菜单,输入 q 退出到控制台,再输入 q 锁定配置。


4.Web 管理页面配置

  1. 浏览器访问 http://192.168.10.100,默认用户名/密码:admin/admin

  2. 首次登录强制修改密码(如 Ikuai888,需大小写字母+数字,≥8位)。

  3. 进入管理页面后:

    • 点击 网络设置 → 内外网设置
    • 内网网口(仅主机模式)已自动启用(显示绿色)。
    • 点击灰色的外网网口图标 → 选择网卡 eth1 → 绑定。
    • 接入方式选择 DHCP(动态获取) → 保存。
  4. 返回内外网设置页面,确认外网网口也变为绿色,表示已正常工作。

5.作用说明

  • 该 iKuai 虚拟机作为 Kubernetes 集群的软路由
  • 为集群中的主机(Master/Node)提供:
    • 网关192.168.10.200
    • DNS 和 DHCP 服务(外网通过 NAT 转发)
    • 集群内部通信(仅主机模式隔离)

私人仓库harbor

不是必要的,但是推荐学习搭建一下!!!

之前搭建过,见:Harbor构建私有仓库---个人专属-CSDN博客,但是之前是NAT模式的一张网卡。

因为后面k8s集群可能要在harbor上拉取/推送镜像。

现在再加一张仅主机的网卡,通过ikuai主机通信。

1.改ip,主机名

bash 复制代码
[root@harbor ~]# nmcli c show
NAME                UUID                                  TYPE      DEVICE
ens160              54c13d54-3ae5-3f23-ab5e-a1b8bbe047f3  ethernet  ens160
Wired connection 1  c1c42f97-fcd6-3c02-9bd0-55b9fd924fe8  ethernet  ens224
br-d12a67195c76     9b37912d-12cf-492c-bada-b9e66647ed62  bridge    br-d12a67195c76
lo                  5605fb5c-0551-45ba-8154-ed65cbe9f646  loopback  lo
docker0             93814bc6-ad85-4fe2-8457-778cb279e74c  bridge    docker0


[root@harbor ~]# nmcli c m Wired\ connection\ 1 connection.id ens224

[root@harbor ~]# nmcli c show
NAME             UUID                                  TYPE      DEVICE
ens160           54c13d54-3ae5-3f23-ab5e-a1b8bbe047f3  ethernet  ens160
ens224           c1c42f97-fcd6-3c02-9bd0-55b9fd924fe8  ethernet  ens224
br-d12a67195c76  9b37912d-12cf-492c-bada-b9e66647ed62  bridge    br-d12a67195c76
lo               5605fb5c-0551-45ba-8154-ed65cbe9f646  loopback  lo
docker0          93814bc6-ad85-4fe2-8457-778cb279e74c  bridge    docker0


nmcli c m ens224 ipv4.method manual ipv4.addresses
192.168.10.20/24 ipv4.dns "223.5.5.5 8.8.8.8" ipv4.gateway 192.168.10.200
connection.autoconnect yes && nmcli c up ens224

[root@harbor ~]# tail -2 /etc/hosts
#192.168.64.134	hb.reg.com harbor
192.168.10.20  hb.reg.com harbor

2.创建个人镜像

运行nginx容器改首页即可,再把容器导出为新镜像,再推送到私人仓库

bash 复制代码
[root@harbor ~]# docker run --name myapp -d nginx:1.28.1
61f1b48a6ad6880d3965b417bc603c40af42a8bdca76c25320c79ae97fe3cdc0
[root@harbor ~]# 
[root@harbor ~]# 
[root@harbor ~]# docker ps | grep myapp
61f1b48a6ad6   nginx:1.28.1                          "/docker-entrypoint...."   11 seconds ago   Up 10 seconds            80/tcp                                                                               myapp
[root@harbor ~]# 

[root@harbor ~]# docker exec -it myapp /bin/bash
root@61f1b48a6ad6:/# 
root@61f1b48a6ad6:/# ls /usr/share/        
X11		 ca-certificates  doc-base    gdb	   lintian     nginx	    tabset
apt		 common-licenses  dpkg	      info	   locale      pam	    terminfo
base-files	 debconf	  fish	      java	   man	       pam-configs  util-linux
base-passwd	 debianutils	  fontconfig  keyrings	   maven-repo  perl5	    xml
bash-completion  dict		  fonts       libc-bin	   menu        pixmaps	    zoneinfo
bug		 doc		  gcc	      libgcrypt20  misc        polkit-1     zsh
root@61f1b48a6ad6:/# ls /usr/share/nginx/html/
50x.html  index.html
root@61f1b48a6ad6:/# echo "myapp | version:1.0 "> /usr/share/nginx/html/index.html 
root@61f1b48a6ad6:/# 
root@61f1b48a6ad6:/# cat /usr/share/nginx/html/index.html
myapp | version:1.0 
root@61f1b48a6ad6:/# 

root@61f1b48a6ad6:/# curl localhost 
myapp | version:1.0 
root@61f1b48a6ad6:/# 
root@61f1b48a6ad6:/# exit
exit
bash 复制代码
步骤1:将容器提交为新镜像
docker commit myapp myapp:1.0
#此时本地已经有改镜像
步骤2:标记镜像(准备推送到Harbor)
docker tag myapp:1.0 hb.reg.com/library/myapp:1.0

步骤3:登录Harbor仓库
docker login -u admin -p Harbor12345 hb.reg.com

步骤4:推送镜像到Harbor
docker push hb.reg.com/library/myapp:1.0

步骤5:验证推送结果

同理再创建并推送两个myapp镜像

bash 复制代码
[root@harbor ~]# docker exec -it myapp /bin/bash
root@61f1b48a6ad6:/# 
root@61f1b48a6ad6:/# echo "myapp | version:2.0 "> /usr/share/nginx/html/index.html
root@61f1b48a6ad6:/# 
root@61f1b48a6ad6:/# exit
exit
[root@harbor ~]# docker commit myapp myapp:2.0
sha256:90369ca73ddca863389f8c8eb807b5a70a02d2b116128c40333708450ba5396e
[root@harbor ~]# docker tag myapp:2.0 hb.reg.com/library/myapp:2.0
[root@harbor ~]# docker push hb.reg.com/library/myapp:2.0




[root@harbor ~]# docker exec -it myapp /bin/bash
root@61f1b48a6ad6:/# 
root@61f1b48a6ad6:/# echo "myapp | version:3.0 "> /usr/share/nginx/html/index.html
root@61f1b48a6ad6:/# 
root@61f1b48a6ad6:/# exit
exit
[root@harbor ~]# docker commit myapp myapp:3.0
sha256:f6c50086974e54fa45f61f6f531fac4da54e13bdff9e0cac9a273beb3d08f739
[root@harbor ~]# 
[root@harbor ~]# docker tag myapp:3.0 hb.reg.com/library/myapp:3.0
[root@harbor ~]# 
[root@harbor ~]# docker push hb.reg.com/library/myapp:3.0 

结果:

k8s集群

环境初始化&准备

克隆3台虚拟机。

条件包括:

  1. 已经关闭防火墙/selinux,搭建好本地仓库,安装好常用软件。

  2. 并且开启路由转发。

  3. 两张网卡(仅主机/NAT),并提前查看仅主机模式的网卡的网段。

  4. 关闭交换分区

可以做完这些再克隆。

再每太主机分别:

5.改主机名

  1. 改ip信息(特别注意网关改为ikuai主机的内网ip)
  2. 关闭NAT模式的网卡。暂时关闭NAT模式网卡,以防止安装集群时出现绑定网卡错误的问题。
  3. 配置主机映射(没有做harbor的就不用写harbor)

1.k8s-master

Node1和Node2同理。改IP相关配置,主机名,暂时关闭NAT网卡

bash 复制代码
hostnamectl hostname k8s-master01 && bash

#改网卡名
nmcli c m Wired\ connection\ 1 connection.id ens224

nmcli c m ens224 ipv4.method manual ipv4.addresses 192.168.10.11/24 ipv4.dns "223.5.5.5 8.8.8.8" ipv4.gateway 192.168.10.200 connection.autoconnect yes && nmcli c up ens224

暂时关闭NAT网卡,以防止安装集群时出现绑定网卡错误的问题。

bash 复制代码
ls /etc/NetworkManager/system-connections/

nmcli c m ens160 connection.autoconnect no && nmcli c up ens160

配置主机映射

bash 复制代码
cat >> /etc/hosts <<EOF
192.168.10.11 k8s-master01 m1
192.168.10.12 k8s-node01 n1
192.168.10.13 k8s-node02 n2
192.168.10.20 hb.registry.com harbor
EOF

2.node1 & node2

bash 复制代码
hostnamectl hostname k8s-node1 && bash
nmcli c m Wired\ connection\ 1 connection.id ens224
nmcli c m ens224 ipv4.method manual ipv4.addresses 192.168.10.12/24 ipv4.dns "223.5.5.5 8.8.8.8" ipv4.gateway 192.168.10.200 connection.autoconnect yes && nmcli c up ens224
nmcli c m ens160 connection.autoconnect no && nmcli c up ens160


hostnamectl hostname k8s-node1 && bash
nmcli c m Wired\ connection\ 1 connection.id ens224
nmcli c m ens160 ipv4.method manual ipv4.addresses
192.168.10.13/24 ipv4.dns "223.5.5.5 8.8.8.8" ipv4.gateway 192.168.10.200
connection.autoconnect yes && nmcli c up ens160
nmcli c m ens160 connection.autoconnect no && nmcli c up ens160

主机映射同上

上面做了k8s三个节点的的基本网络设置(IP,网卡,防火墙等等)

搭建k8s集群

不知道大家有没有困惑:为什么要下载cri-dockerd,为什么要下载containerd?选择containerd作为容器运行时为什么要单独下载runc& cni-plugin,而如果cri-dockerd不用?

在阅读官网和别人的博客时,总是有很多额外的东西要自己去搞定,而这些东西很容易失败。

所以:我想在搭建k8s集群前,先了解这个集群的运行机制,底层原理。知道为什么需要单独去安装这些!!

如果你赶时间,可以跳过这部分,直接到:正式安装&部署部分

一些相关知识点

eg.我们现在搭建一个简单的k8s集群:1master,2node。其中master是管理节点,node是工作节点。

Master /Node节点功能

Master 节点 (控制平面)

  • API Server:所有请求的唯一入口,类似"前台/网关"
  • etcd:存储集群状态(Pod在哪、配置、Secret等)
  • Scheduler:决定新Pod放到哪个Node
  • Controller Manager:运行各种控制器(如Deployment控制器、Node控制器)

Node 节点

  • kubelet:Node的"管家",负责Pod生命周期,与Master通信
  • kube-proxy:负责Service的网络规则(iptables/IPVS)
  • CRI (容器运行时):真正拉镜像、启停容器。如 containerd、CRI‑dockerd

当我们要运行一个pod实例时,比如创建一个yaml文档去创建这个pod。

YAML → kubectl POST → API Server 存 etcd → Scheduler 设 nodeName → kubelet watch 到 → kubelet 调用 CRI 拉镜像+建 pause+启容器 → kubelet 更新状态为 Running

text 复制代码
┌─────────────────────────────────────────────┐
│              MASTER 节点                      │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐      │
│  │API Server│  │ etcd   │  │Scheduler│      │
│  │接收请求   │  │存Pod对象│  │分配节点  │      │
│  └─────────┘  └─────────┘  └─────────┘      │
└──────────────────┬──────────────────────────┘
                   │ watch & 回写
                   ↓
┌─────────────────────────────────────────────┐
│               NODE 节点 (node1)               │
│  ┌──────────────────────────────────────┐   │
│  │            kubelet                    │   │
│  │  1. 发现 Pod 分配给自己                │   │
│  │  2. 调用 CRI 拉镜像/创建容器/启停       │   │
│  │  3. 调用 CNI 配网络                    │   │
│  │  4. 回写状态                          │   │
│  └──────────────────────────────────────┘   │
│                                              │
│  ┌─────────┐         ┌─────────┐            │
│  │ pause   │ ←共享NS→ │  nginx  │            │
│  │(沙盒容器)│         │(业务容器)│            │
│  └─────────┘         └─────────┘            │
└─────────────────────────────────────────────┘

我们可以发现node节点:2. 调用 CRI 拉镜像/创建容器/启停,这里的CRI就是容器运行时。

容器运行时的选择&准备

目前比较常用的容器运行时就是Docker Engine (通过 cri-dockerd)和containerd

选择哪种其实我们要根据实际情况!!!

其实k8s集群管理就是:要么是通过k8s管理编排docker 容器,或者是 containerd 容器(和 docker 无关了)。

++现在k8s官方推荐的是containerd ,但是大多数人学习过程都是docker->k8s。从有docker环境开始入手会更平滑。++

生产环境是否继续用 Docker,取决于业务对 docker 命令和工具的依赖程度。

1.选择Docker Engine

第一种,肯定每一个节点都是要有docker环境的,这里我们可以不用太管docker所需的组件,docker比较集成,安装好docker后,这些组件已经ok了。

只需要安装cri-dockerd 作为容器运行时的适配器。

这里需要先明确一点:cri-dockerd 本身不是一个容器运行时,它只是一个适配器。它的作用是让Kubernetes可以通过标准的CRI(容器运行时接口)来调用传统的Docker Engine。

再安装**kubelet kubectl(master必须,node可略), kubeadm**(一些组件依赖其来自动安装)

2.选择containerd

第二种,则需要准备的部分有:containerd,runc, cni-plugin

再安装**kubelet kubectl(master必须,node可略), kubeadm**(一些组件依赖其来自动安装)

由组件决定安装什么

今天我们先介绍第一种。从组件的角度来部署安装。

先了解各节点到底需要什么!!!由上面Master /Node节点功能可知不同节点需要的组件也不同。

Master 节点

组件 如何获得
kube-apiserver、etcd、kube-scheduler、kube-controller-manager kubeadm 自动安装
kubectl yum/apt 安装
kubelet yum/apt 安装
kubeadm yum/apt 安装

需要安装kubeadm,kubectl,kubelet

Node 节点

组件 如何获得
kube-proxy kubeadm 自动安装
Docker + cri-dockerd 手动安装
kubelet yum/apt 安装
kubeadm yum/apt 安装

需要安装kubeadm,kubelet,Docker + cri-dockerd

注意:纯 Master(不跑 Pod)可以不装 Docker + cri-dockerd。但本文档的 Master 会运行 Calico等系统 Pod,所以也需要安装。

为了方便,最后我们决定所有节点都先安装docker环境后,再安装cri-dockerd,再安装kubelet,kubeadm,kubectl。

正式安装&部署

1.安装docker环境
1.1添加dock5er源
bash 复制代码
yum install -y yum-utils

yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/rhel/docker-ce.repo

可以检查一下

bash 复制代码
[root@k8s-master01 ~]# dnf repolist
repo id                         repo name
AppStream                       AppStream
BaseOS                          BaseOS
docker-ce-stable                Docker CE Stable - x86_64
#其它节点一样
1.2安装docker
bash 复制代码
yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
1.3配置docker

配置了 Docker 的数据目录、日志限制、cgroup 驱动、私有仓库支持和镜像加速器,目的是让 Docker 在 K8s 集群环境下稳定、高效、合规地运行。

bash 复制代码
cat > /etc/docker/daemon.json <<EOF
{
	"default-ipc-mode": "shareable",
	"data-root": "/data/docker",
	"exec-opts": ["native.cgroupdriver=systemd"],
	"log-driver": "json-file",
	"log-opts": {
		"max-size": "100m",
		"max-file": "50"
	},
    "insecure-registries": ["https://harbor.registry.com"],
	"registry-mirrors":[
		"https://docker.m.daocloud.io",
		"https://docker.imgdb.de",
		"https://docker-0.unsee.tech",
		"https://docker.hlmirror.com",
		"https://docker.1ms.run",
		"https://func.ink",
		"https://lispy.org",
		"https://docker.xiaogenban1993.com"
	]
}
EOF

详细解释:

配置项 作用
default-ipc-mode "shareable" 允许容器共享 IPC 命名空间(Pod 内多容器通信需要)
data-root "/data/docker" 修改 Docker 数据存储目录(默认 /var/lib/docker),避免根分区占满
exec-opts ["native.cgroupdriver=systemd"] 关键配置:让 Docker 使用 systemd 作为 cgroup 驱动,与 kubelet 保持一致
log-driver "json-file" 日志驱动类型(Docker 默认)
log-opts max-size: 100m max-file: 50 每个容器日志文件最大 100MB,最多保留 50 个文件,防止日志暴涨
insecure-registries ["https://hb.registry.com"] 允许访问的私有镜像仓库(跳过 HTTPS 证书验证)
registry-mirrors 8 个国内加速器地址 拉取镜像时优先从这些镜像站下载,解决 registry.k8s.iodocker.io 访问慢/被墙问题
1.4启动docker
bash 复制代码
systemctl  enable --now docker
1.5验证docker
bash 复制代码
docker --version
结果:Docker version 29.5.2, build 79eb04c

docker info
结果:略
2.安装CRI

CRI 为容器运行时,常见的有 cri-docker 和 containerd,两者任选其一安装即可,不要两者都安装。

这里我们是选择 cri-docker,能够去兼容docker环境

2.1.下载cri-docker
bash 复制代码
wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.17/cri-dockerd-0.3.17.amd64.tgz

比较慢,可以在一台机器下载再传输给另外两台

bash 复制代码
scp cri-dockerd-0.3.17.amd64.tgz n1:~
scp cri-dockerd-0.3.17.amd64.tgz n2:~
2.2解压
bash 复制代码
tar -xf cri-dockerd-0.3.17.amd64.tgz
2.3将解压文件复制到可执行目录下
bash 复制代码
cp cri-dockerd/cri-dockerd /usr/bin/
2.4设置文件可执行权限
bash 复制代码
chmod +x /usr/bin/cri-dockerd
2.5配置cri-docker服务

目的是:让 kubelet 能够通过 cri-dockerd 适配器,使用 pause:3.10 镜像作为每个 Pod 的"基础沙箱"来管理 Docker 容器。

简单来说,它就是打通 Kubernetes 与 Docker 之间的关键桥梁服务。

bash 复制代码
cat > /usr/lib/systemd/system/cri-docker.service <<EOF
[Unit]
Description=CRI Interface for Docker Application Container Engine
Documentation=https://docs.mirantis.com
After=network-online.target firewalld.service docker.service
Wants=network-online.target
Requires=cri-docker.socket
[Service]
Type=notify
ExecStart=/usr/bin/cri-dockerd --network-plugin=cni --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.10
#ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd:// --network-plugin=cni --pod-infra-container-image=registry.k8s.io/pause:3.10
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
StartLimitBurst=3
StartLimitInterval=60s
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
Delegate=yes
KillMode=process
[Install]
WantedBy=multi-user.target
EOF
2.6 配置cri-docker套接字

cri-dockerd 创建一个监听套接字(socket),让 kubelet 能通过这个 socket 与 cri-dockerd 通信,并支持按需启动服务。

bash 复制代码
cat > /usr/lib/systemd/system/cri-docker.socket <<EOF
[Unit]
Description=CRI Docker socket for the API
PartOf=cri-docker.service

[Socket]
ListenStream=%t/cri-dockerd.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker

[Install]
WantedBy=sockets.target
EOF
2.7启动cri-docker服务
bash 复制代码
systemctl daemon-reload
systemctl enable --now cri-docker
systemctl is-active cri-docker#检验
3.安装kubernete&初始化集群
3.1添加kubenete源
bash 复制代码
cat <<EOF | tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.33/rpm/
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.33/rpm/repodata/repomd.xml.key
EOF
3.2安装kubenete

kubelet kubeadm kubectl

bash 复制代码
dnf install -y kubelet kubeadm kubectl
3.3启动kubelet服务
bash 复制代码
systemctl enable --now kubelet
3.4验证安装
bash 复制代码
kubeadm version
结果:kubeadm version: &version.Info{Major:"1", Minor:"33", EmulationMajor:"", EmulationMinor:"", MinCompatibilityMajor:"", MinCompatibilityMinor:"", GitVersion:"v1.33.12", GitCommit:"1f348c8e82cf0f170df4ac2b1e859ea0d398ff09", GitTreeState:"clean", BuildDate:"2026-05-12T09:45:31Z", GoVersion:"go1.25.9", Compiler:"gc", Platform:"linux/amd64"}
3.5 查看所需镜像

主节点需要导入全部镜像,从节点只需导入 kube-proxy、coredns、pause 这三个镜像。

bash 复制代码
kubeadm config images list
结果:
registry.k8s.io/kube-apiserver:v1.33.12
registry.k8s.io/kube-controller-manager:v1.33.12
registry.k8s.io/kube-scheduler:v1.33.12
registry.k8s.io/kube-proxy:v1.33.12
registry.k8s.io/coredns/coredns:v1.12.0
registry.k8s.io/pause:3.10
registry.k8s.io/etcd:3.5.24-0

可以看出:kubeadm 支持 v1.33.12 版本

3.6初始化节点

此操作只需要在 k8s-master01 节点上执行。

先拉取镜像,否则初始化很慢,且极有可能不成功

bash 复制代码
[root@k8s-master01 ~]# kubeadm config images pull \
  --kubernetes-version=v1.33.12 \
  --image-repository=registry.aliyuncs.com/google_containers \
  --cri-socket unix:///var/run/cri-dockerd.sock

[config/images] Pulled registry.aliyuncs.com/google_containers/kube-apiserver:v1.33.12
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-controller-manager:v1.33.12
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-scheduler:v1.33.12
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-proxy:v1.33.12
[config/images] Pulled registry.aliyuncs.com/google_containers/coredns:v1.12.0
[config/images] Pulled registry.aliyuncs.com/google_containers/pause:3.10
[config/images] Pulled registry.aliyuncs.com/google_containers/etcd:3.5.24-0
[root@k8s-master01 ~]# 

初始化(master上执行)

bash 复制代码
kubeadm init --apiserver-advertise-address=192.168.10.11 \
--image-repository=registry.aliyuncs.com/google_containers \
--kubernetes-version=v1.33.12 \
--service-cidr=10.10.0.0/12 \
--pod-network-cidr=10.244.0.0/16 \
--ignore-preflight-errors=all \
--cri-socket unix:///var/run/cri-dockerd.sock

命令解析如下:

--apiserver-advertise-address=192.168.10.11:指定主服务器的地是多少,也就是 master

主机的地址

--image-repository:指定控制平面镜像的仓库地址(默认 registry.k8s.io),当前为阿里镜

像仓库地址,也可指向自己的私有镜像仓库地址如my-registry.com/k8s

--kubernetes-version=v1.33.12:因为 kubeadm 版本是 v1.33.12 ,所以 --kubernetes-version 必须指定为 v1.33.12

--service-cidr=10.10.0.0/12:指定service资源的网络范围

--pod-network-cidr=10.244.0.0/16:指定pos的网络范围

--ignore-preflight-errors=all:跳过所有前置的错误检测

--cri-socket unix:///var/run/cri-dockerd.sock:指定 CRI(容器运行时)的 socket 路径,如

果是containerd则为unix:///run/containerd/containerd.sock

初始化信息

bash 复制代码
[init] Using Kubernetes version: v1.33.12
[preflight] Running pre-flight checks
	[WARNING Mem]: the system RAM (1673 MB) is less than the minimum 1700 MB
	[WARNING Port-6443]: Port 6443 is in use
	[WARNING Port-10259]: Port 10259 is in use
	[WARNING Port-10257]: Port 10257 is in use
	[WARNING FileAvailable--etc-kubernetes-manifests-kube-apiserver.yaml]: /etc/kubernetes/manifests/kube-apiserver.yaml already exists
	[WARNING FileAvailable--etc-kubernetes-manifests-kube-controller-manager.yaml]: /etc/kubernetes/manifests/kube-controller-manager.yaml already exists
	[WARNING FileAvailable--etc-kubernetes-manifests-kube-scheduler.yaml]: /etc/kubernetes/manifests/kube-scheduler.yaml already exists
	[WARNING FileAvailable--etc-kubernetes-manifests-etcd.yaml]: /etc/kubernetes/manifests/etcd.yaml already exists
	[WARNING Port-10250]: Port 10250 is in use
	[WARNING Port-2379]: Port 2379 is in use
	[WARNING Port-2380]: Port 2380 is in use
	[WARNING DirAvailable--var-lib-etcd]: /var/lib/etcd is not empty
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action beforehand using 'kubeadm config images pull'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Using existing ca certificate authority
[certs] Using existing apiserver certificate and key on disk
[certs] Using existing apiserver-kubelet-client certificate and key on disk
[certs] Using existing front-proxy-ca certificate authority
[certs] Using existing front-proxy-client certificate and key on disk
[certs] Using existing etcd/ca certificate authority
[certs] Using existing etcd/server certificate and key on disk
[certs] Using existing etcd/peer certificate and key on disk
[certs] Using existing etcd/healthcheck-client certificate and key on disk
[certs] Using existing apiserver-etcd-client certificate and key on disk
[certs] Using the existing "sa" key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/admin.conf"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/super-admin.conf"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/kubelet.conf"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/controller-manager.conf"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/scheduler.conf"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests"
[kubelet-check] Waiting for a healthy kubelet at http://127.0.0.1:10248/healthz. This can take up to 4m0s
[kubelet-check] The kubelet is healthy after 502.255841ms
[control-plane-check] Waiting for healthy control plane components. This can take up to 4m0s
[control-plane-check] Checking kube-apiserver at https://192.168.10.11:6443/livez
[control-plane-check] Checking kube-controller-manager at https://127.0.0.1:10257/healthz
[control-plane-check] Checking kube-scheduler at https://127.0.0.1:10259/livez
[control-plane-check] kube-apiserver is healthy after 3.006452ms
[control-plane-check] kube-controller-manager is healthy after 3.026871ms
[control-plane-check] kube-scheduler is healthy after 4.116445ms
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node k8s-master01 as control-plane by adding the labels: [node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers]
[mark-control-plane] Marking the node k8s-master01 as control-plane by adding the taints [node-role.kubernetes.io/control-plane:NoSchedule]
[bootstrap-token] Using token: ma44bu.m6ku932h1b9yrmap
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Configured RBAC rules to allow the API server kubelet client certificate to access the kubelet API
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

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.10.11:6443 --token ma44bu.m6ku932h1b9yrmap \
	--discovery-token-ca-cert-hash sha256:4d4dea5b8ca94a671d5115fdfd6237df2cb1f485f1492e8f6a801c3f0191b7e4
3.7创建.kube目录
bash 复制代码
[root@k8s-master01 ~]# mkdir -p $HOME/.kube
[root@k8s-master01 ~]# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[root@k8s-master01 ~]# chown $(id -u):$(id -g) $HOME/.kube/config


[root@k8s-master01 ~]# kubectl get node
NAME           STATUS     ROLES           AGE     VERSION
k8s-master01   NotReady   control-plane   5m31s   v1.33.12
3.8 增加工作节点
bash 复制代码
kubeadm join 192.168.10.11:6443 --token ma44bu.m6ku932h1b9yrmap \
	--discovery-token-ca-cert-hash sha256:4d4dea5b8ca94a671d5115fdfd6237df2cb1f485f1492e8f6a801c3f0191b7e4  \
	--cri-socket unix:///var/run/cri-dockerd.sock

如果不加--cri-socket会冲突。kubeadm 发现系统里有 两个 可用的容器运行时(containerdcri-dockerd),不知道该用哪个来创建容器,所以就报错停止了。

虽然没有主动安装 containerd,它是在你之前执行安装 Docker 的命令时,作为依赖包被自动安装进来的

Tips:

如果这里加入不成功,在再次尝试前要先删掉之前的一些残留

bash 复制代码
# 1. 彻底清理之前的 Kubernetes 痕迹
kubeadm reset --cri-socket unix:///var/run/cri-dockerd.sock -f

# 2. 删除残留文件(可选,reset 应该已经清理)
rm -rf /etc/kubernetes/
rm -rf /var/lib/kubelet/
rm -rf ~/.kube/

# 3. 重启 kubelet
systemctl restart kubelet

# 4. 重新执行 join 命令
kubeadm join 192.168.10.11:6443 \
  --token ma44bu.m6ku932h1b9yrmap \
  --discovery-token-ca-cert-hash sha256:4d4dea5b8ca94a671d5115fdfd6237df2cb1f485f1492e8f6a801c3f0191b7e4 \
  --cri-socket unix:///var/run/cri-dockerd.sock

3.9查看集群状态

bash 复制代码
[root@k8s-master01 ~]# kubectl get nodes
NAME           STATUS     ROLES           AGE     VERSION
k8s-master01   NotReady   control-plane   26m     v1.33.12
k8s-node1      NotReady   <none>          7m55s   v1.33.12
k8s-node2      NotReady   <none>          6s      v1.33.12
4.部署网络插件

Kubernetes 集群如果要能够正常工作,所有容器都必须工作在一个扁平的网络空间中。

接下来我们就需要部署网络插件来实现这个扁平化网络空间,让 Kubernetes 集群可以正常工作。

官网可看:

Calico

选择第2个。按照上面的步骤。

4.1 下载配置文件
bash 复制代码
curl https://raw.githubusercontent.com/projectcalico/calico/v3.30.7/manifests/calico-typha.yaml -o calico.yaml


[root@k8s-master01 ~]# grep image* calico.yaml
          image: docker.io/calico/cni:v3.30.7
          imagePullPolicy: IfNotPresent
          image: docker.io/calico/cni:v3.30.7
          imagePullPolicy: IfNotPresent
          image: docker.io/calico/node:v3.30.7
          imagePullPolicy: IfNotPresent
          image: docker.io/calico/node:v3.30.7
          imagePullPolicy: IfNotPresent
          image: docker.io/calico/kube-controllers:v3.30.7
          imagePullPolicy: IfNotPresent
      - image: docker.io/calico/typha:v3.30.7
        imagePullPolicy: IfNotPresent
[root@k8s-master01 ~]# 
4.2修改配置文件calico.yaml
bash 复制代码
# Enable IPIP
            - name: CALICO_IPV4POOL_IPIP
              value: "Off"
            # Enable or Disable VXLAN on the default IP pool.
            - name: CALICO_IPV4POOL_VXLAN
              value: "Never"
            # Enable or Disable VXLAN on the default IPv6 IP pool.
            - name: CALICO_IPV6POOL_VXLAN
              value: "Never"
。。。。。。

- name: CALICO_IPV4POOL_CIDR
  value: "10.244.0.0/16"

1.将 CALICO_IPV4POOL_IPIP 和CALICO_IPV4POOL_VXLAN 都关闭,即使用 BGP 模式。

2.CALICO_IPV4POOL_CIDR 修改为初始集群时指定的 Pod 地址,即 --pod

network-cidr=10.244.0.0/16 参数所指定的地址。

4.3安装网络插件
bash 复制代码
kubectl apply -f calico.yaml
4.4查看集群状态
bash 复制代码
[root@k8s-master01 ~]# kubectl get node
NAME           STATUS   ROLES           AGE   VERSION
k8s-master01   Ready    control-plane   42m   v1.33.12
k8s-node1      Ready    <none>          24m   v1.33.12
k8s-node2      Ready    <none>          16m   v1.33.12

[root@k8s-master01 ~]# kubectl get node -o wide
NAME           STATUS   ROLES           AGE   VERSION    INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                                   KERNEL-VERSION                 CONTAINER-RUNTIME
k8s-master01   Ready    control-plane   43m   v1.33.12   192.168.10.11   <none>        Red Hat Enterprise Linux 10.1 (Coughlan)   6.12.0-124.8.1.el10_1.x86_64   docker://29.5.2
k8s-node1      Ready    <none>          24m   v1.33.12   192.168.10.12   <none>        Red Hat Enterprise Linux 10.1 (Coughlan)   6.12.0-124.8.1.el10_1.x86_64   docker://29.5.2
k8s-node2      Ready    <none>          17m   v1.33.12   192.168.10.13   <none>        Red Hat Enterprise Linux 10.1 (Coughlan)   6.12.0-124.8.1.el10_1.x86_64   docker://29.5.2

查看所有命名空间的 Pod

bash 复制代码
[root@k8s-master01 ~]# kubectl get pods --all-namespaces
NAMESPACE     NAME                                       READY   STATUS    RESTARTS   AGE
kube-system   calico-kube-controllers-75545bc648-6xhb9   1/1     Running   0          9m10s
kube-system   calico-node-6drsp                          1/1     Running   0          9m10s
kube-system   calico-node-fw9gj                          1/1     Running   0          9m10s
kube-system   calico-node-ww6s5                          1/1     Running   0          9m10s
kube-system   calico-typha-79c48599db-7rhp5              1/1     Running   0          9m10s
kube-system   coredns-757cc6c8f8-r7xw9                   1/1     Running   0          39m
kube-system   coredns-757cc6c8f8-wrljm                   1/1     Running   0          39m
kube-system   etcd-k8s-master01                          1/1     Running   0          42m
kube-system   kube-apiserver-k8s-master01                1/1     Running   0          42m
kube-system   kube-controller-manager-k8s-master01       1/1     Running   0          42m
kube-system   kube-proxy-lb44f                           1/1     Running   0          39m
kube-system   kube-proxy-m5z8c                           1/1     Running   0          24m
kube-system   kube-proxy-phdxn                           1/1     Running   0          16m
kube-system   kube-scheduler-k8s-master01                1/1     Running   0          42m

查看指定命名空间(kube-system)

bash 复制代码
[root@k8s-master01 ~]# kubectl get pods -n kube-system
NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-75545bc648-6xhb9   1/1     Running   0          9m19s
calico-node-6drsp                          1/1     Running   0          9m19s
calico-node-fw9gj                          1/1     Running   0          9m19s
calico-node-ww6s5                          1/1     Running   0          9m19s
calico-typha-79c48599db-7rhp5              1/1     Running   0          9m19s
coredns-757cc6c8f8-r7xw9                   1/1     Running   0          39m
coredns-757cc6c8f8-wrljm                   1/1     Running   0          39m
etcd-k8s-master01                          1/1     Running   0          42m
kube-apiserver-k8s-master01                1/1     Running   0          42m
kube-controller-manager-k8s-master01       1/1     Running   0          42m
kube-proxy-lb44f                           1/1     Running   0          39m
kube-proxy-m5z8c                           1/1     Running   0          24m
kube-proxy-phdxn                           1/1     Running   0          16m
kube-scheduler-k8s-master01                1/1     Running   0          42m

Kubernetes 集群已经完全正常运行!

所有系统组件都是 Running 状态:

  1. Calico 网络插件(CNI)
  • calico-node-xxx (3个):每个节点一个,负责网络连通性
  • calico-kube-controllers:Calico 的控制器,管理网络策略
  • calico-typha:Calico 的代理,减少 API 负载
  1. CoreDNS(DNS 服务)
  • coredns-xxx (2个):为集群提供 DNS 解析服务,让 Pod 之间可以通过服务名通信
  1. Kubernetes 核心组件(仅在 master 节点)
  • kube-apiserver:API 服务器,集群的入口
  • kube-controller-manager:控制器管理器,管理各种控制器
  • kube-scheduler:调度器,负责将 Pod 分配到节点
  • etcd:集群的数据库,存储所有配置和状态
  • kube-proxy (3个):每个节点一个,负责网络代理和负载均衡
Tips:

如果**kubectl apply -f calico.yaml安装失败,多半是镜像拉取失败**

1.上传镜像文件

由于 calico 镜像在国内很难下载,因此我已经提前将所需要的镜像下载好

通过网盘分享的文件:calico-images-v3.30.2.tar 和calico.yaml

链接: https://pan.baidu.com/s/122ubjrO8CotnXCl7NJ4vAw?pwd=zlpz 提取码: zlpz

2.导入镜像文件

bash 复制代码
tar -xvf calico-v3.30.2.tar
cni:v3.30.2.tar.gz
kube-controllers:v3.30.2.tar.gz
node:v3.30.2.tar.gz
typha:v3.30.2.tar.gz


docker load -i xxx#导入上面解压的4个到3个节点

3.安装网络插件

bash 复制代码
#先下载
curl https://raw.githubusercontent.com/projectcalico/calico/v3.30.2/manifests/calico-typha.yaml -o calico.yaml

#再安装
kubectl apply -f calico.yaml

应该就OK了。

简单测试:创建一个pod

bash 复制代码
[root@k8s-master01 ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.0.0.1     <none>        443/TCP   62m
[root@k8s-master01 ~]# 
[root@k8s-master01 ~]# 
[root@k8s-master01 ~]# kubectl create deployment nginx --image=nginx
deployment.apps/nginx created
[root@k8s-master01 ~]# 
[root@k8s-master01 ~]# kubectl expose deployment nginx --port=80 --type=NodePort
service/nginx exposed
[root@k8s-master01 ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.0.0.1       <none>        443/TCP        62m
nginx        NodePort    10.1.229.182   <none>        80:31568/TCP   5s
[root@k8s-master01 ~]# kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
nginx-5869d7778c-26mlm   1/1     Running   0          24s
[root@k8s-master01 ~]# kubectl get node
NAME           STATUS   ROLES           AGE   VERSION
k8s-master01   Ready    control-plane   63m   v1.33.12
k8s-node1      Ready    <none>          44m   v1.33.12
k8s-node2      Ready    <none>          37m   v1.33.12
[root@k8s-master01 ~]# 

#通过集群内部地址访问
[root@k8s-master01 ~]# curl http://10.1.229.182:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, nginx is successfully installed and working.
Further configuration is required for the web server, reverse proxy, 
API gateway, load balancer, content cache, or other features.</p>

<p>For online documentation and support please refer to
<a href="https://nginx.org/">nginx.org</a>.<br/>
To engage with the community please visit
<a href="https://community.nginx.org/">community.nginx.org</a>.<br/>
For enterprise grade support, professional services, additional 
security features and capabilities please refer to
<a href="https://f5.com/nginx">f5.com/nginx</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

在查看nginx容器在哪个节点

bash 复制代码
[root@k8s-master01 ~]# kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP             NODE        NOMINATED NODE   READINESS GATES
nginx-5869d7778c-26mlm   1/1     Running   0          9m45s   10.244.36.64   k8s-node1   <none>           <none>


[root@k8s-node1 ~]#  docker ps | grep nginx
2c5f23018cf7   5aca99593157                                         "/docker-entrypoint...."   7 minutes ago    Up 7 minutes              k8s_nginx_nginx-5869d7778c-26mlm_default_1504b5a4-ff13-4a77-9076-8109391a9d24_0
36edf5fe5c6b   registry.aliyuncs.com/google_containers/pause:3.10   "/pause"                 7 minutes ago    Up 7 minutes              k8s_POD_nginx-5869d7778c-26mlm_default_1504b5a4-ff13-4a77-9076-8109391a9d24_0
相关推荐
xier_ran2 小时前
【infra之路】模块三:Kubernetes (下) — 阶段一毕业项目:在集群里跑 PyTorch 训练
pytorch·容器·kubernetes
Waay2 小时前
K8s新手实操|emptyDir卷超详细实战(附完整命令+核心理解)
云原生·容器·kubernetes
liux35282 小时前
K8s 核心接口:CNI、CSI、CRI、LB 一篇讲透
云原生·容器·kubernetes
香气袭人知骤暖3 小时前
人大金仓(KingbaseES)Docker 容器自动备份方案
运维·docker·容器
Devin~Y3 小时前
从内容社区到AIGC客服:Spring Boot、Redis、Kafka、K8s、RAG的三轮大厂Java面试对话(附标准答案)
java·spring boot·redis·spring cloud·kafka·kubernetes·micrometer
大熊程序猿3 小时前
MarkItDown Docker安装
运维·docker·容器
Hello_worlds4 小时前
Kafka InconsistentClusterIdException 导致容器无限重启,磁盘打满排查与修复
docker·kafka·磁盘·排障
wgc2k4 小时前
Nest.js基础-6:关于Claude Code
人工智能·docker·node.js
IT策士4 小时前
第25篇 k8s之Deployment 基础:声明式管理与副本控制
云原生·容器·kubernetes