一.核心原理解释
1. 控制平面(Master)与工作节点(Worker Node)
Master 节点:负责集群的管理和调度,运行 API Server、Scheduler、Controller Manager、etcd 等核心组件。
Node 节点:负责运行实际的应用容器,运行 kubelet、kube-proxy 和容器运行时。
后面的实验我们使用以下插件
master-node 安装了 kubeadm、kubelet、kubectl
node1、node2 安装了 kubeadm、kubelet

1 Master(控制平面)节点
作用:整个 Kubernetes 集群的大脑,不执行业务 Pod(默认),做集群管理、调度、状态维护、数据存储。
内部四大核心组件:
kube‑apiserver
集群唯一入口,所有操作 (kubectl、其他组件) 都访问它;
对外暴露 REST API;做鉴权、校验;所有读写请求都经过 apiserver;
唯一可以读写 etcd 的组件。
etcd
分布式键值数据库,集群的 "数据库";
保存集群全部状态:节点信息、Pod、Deployment、Service、配置、密钥;
只被 apiserver 访问,其他组件不能直接读写 etcd。
etcd分布式键值数据库,集群的 "数据库";
保存集群全部状态:节点信息、Pod、Deployment、Service、配置、密钥;
只被 apiserver 访问,其他组件不能直接读写 etcd。
kube‑scheduler(调度器)监听 apiserver,发现未绑定节点的 Pod;
根据资源、策略,挑选最合适的 Worker 节点运行 Pod;
只做决策,不创建容器,把调度结果写回 apiserver。
kube‑controller‑manager(控制器管理器)一堆控制器集合:节点控制器、副本控制器等;
持续对比「期望状态」和「实际集群状态」,不断调谐,让现状向期望靠拢;
例如 Deployment 声明要 3 个 Pod,挂掉一个就自动新建一个。
实验环境:master‑node 安装 kubeadm、kubelet、kubectl
kubeadm:集群初始化工具,kubeadm init搭建控制平面;
kubelet:Master 节点上也会运行 kubelet,负责管理控制平面静态 Pod(apiserver/etcd 等是以 Pod 形式跑在 master 上);
kubectl:客户端命令行工具,给人操作集群,发送请求到 apiserver。
2 Worker Node 工作节点
作用:真正执行业务应用,跑业务 Pod 容器。
三个核心组件:
kubelet(每个 node 必跑)
节点代理,跟 apiserver 通信;
接收分配过来的 Pod 指令,调用容器运行时创建 / 销毁 Pod;上报节点、Pod 状态给控制平面。
kube‑proxy(每个 node 必跑)实现 Service 网络;维护 iptables/ipvs 规则,完成 Service 负载均衡、转发 Pod 流量;
容器运行时(containerd/docker)底层引擎,真正拉镜像、启动容器。
实验环境 node1、node2:只装 kubeadm、kubelet
kubeadm:用于kubeadm join命令,把节点加入集群;
kubelet:节点核心代理,启动后向 apiserver 注册本节点;
⚠注意:node1/node2不需要安装 kubectl,kubectl 只是管理客户端,worker 节点不需要操作集群;kube‑proxy 和容器运行时是 kubeadm join 之后自动部署。
3.K8S 各组件之间的调用关系
当我们要运行一个web服务时
- kubernetes环境启动之后,master和node都会将自身的信息存储到etcd数据库中
- web服务的安装请求会首先被发送到master节点的apiServer组件
- apiServer组件会调用scheduler组件来决定到底应该把这个服务安装到哪个node节点上
在此时,它会从etcd中读取各个node节点的信息,然后按照一定的算法进行选择,并将结果告知
apiServer - apiServer调用controller-manager去调度Node节点安装web服务
- kubelet接收到指令后,会通知docker,然后由docker来启动一个web服务的pod
- 如果需要访问web服务,就需要通过kube-proxy来对pod产生访问的代理
4.K8S 的 常用名词感念
- Master:集群控制节点,每个集群需要至少一个master节点负责集群的管控
- Node:工作负载节点,由master分配容器到这些node工作节点上,然后node节点上的
- Pod:kubernetes的最小控制单元,容器都是运行在pod中的,一个pod中可以有1个或者多个容器
- Controller:控制器,通过它来实现对pod的管理,比如启动pod、停止pod、伸缩pod的数量等等
- Service:pod对外服务的统一入口,下面可以维护者同一类的多个pod
- Label:标签,用于对pod进行分类,同一类pod会拥有相同的标签
- NameSpace:命名空间,用来隔离pod的运行环境
2. 容器运行时(Container Runtime)
Kubernetes 本身不直接运行容器,而是通过 CRI(Container Runtime Interface) 与容器运行时通信。
Docker 作为容器引擎
cri-dockerd 作为 Docker 与 Kubernetes 之间的适配器(因为新版 Kubernetes 不再直接支持 Docker 作为运行时)
3. 镜像仓库(Harbor)
Kubernetes 需要从镜像仓库拉取容器镜像。你的文档中搭建了 Harbor 私有镜像仓库,作用包括:
统一管理集群所需镜像
加速镜像拉取(内网)
安全控制(TLS 证书 + 用户认证)
后面实验使用 reg.timinglee.org 作为私有仓库地址
将 k8s 所需镜像(kube-apiserver、kube-proxy、coredns、pause、flannel 等)推送到 Harbor
所有节点配置 Docker 信任该仓库的证书
4. 网络插件(CNI)
Kubernetes 需要 CNI(Container Network Interface) 插件来实现 Pod 之间的网络通信。
后面实验使用了 Flannel网络插件:
提供跨节点的 Pod 网络
通过 VXLAN 或 host-gateway 实现 overlay 网络
配置了 --pod-network-cidr=10.244.0.0/16 与 Flannel 默认网段匹配
5. 集群初始化与节点加入
kubeadm init:在 Master 上初始化集群,生成证书、配置文件、启动控制平面组件。
kubeadm join:Node 节点通过 token 和 CA 证书哈希加入集群。
6. 安全机制
TLS 证书:Harbor 使用自签名证书,所有节点信任该证书。
认证授权:Harbor 使用 admin 用户登录,Kubernetes 使用 token 和 CA 哈希验证节点身份。
二.实验环境配置
1.构建harbor镜像仓库
habor,master,node1,node2都要做"1.安装docker"
1.安装docker
bash
[root@harbor ~]# cat > /etc/yum.repos.d/docker.repo <<EOF
[docker]
name = docker
baseurl = https://mirrors.aliyun.com/docker-ce/linux/rhel/9.6/x86_64/stable/
gpgcheck = 0
EOF
[root@harbor ~]# dnf install docker-ce-3:28.5.2-1.el9 -y
[root@harbor ~]# echo br_netfilter > /etc/modules-load.d/docker_mod.conf
[root@harbor ~]# modprobe -a br_netfilter
[root@harbor ~]# vim /etc/sysctl.d/docker.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
[root@harbor ~]# sysctl --system
[root@harbor ~]# vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=true
[root@harbor ~]# systemctl daemon-reload
[root@harbor ~]# systemctl enable --now docker
2.在harbor上生成key
bash
[root@harbor ~]# mkdir /data/certs -p
[root@harbor ~]# mkdir /data/certs -p
[root@harbor ~]# openssl req -newkey rsa:4096 \
-nodes -sha256 -keyout /data/certs/timinglee.org.key \
-addext "subjectAltName = DNS:reg.timinglee.org" \
-x509 -days 365 -out /data/certs/timinglee.org.crt
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:Shannxi
Locality Name (eg, city) [Default City]:Xi'an
Organization Name (eg, company) [Default Company Ltd]:kubernetes
Organizational Unit Name (eg, section) []:harbor
Common Name (eg, your name or your server's hostname) []:reg.timinglee.org
Email Address []:admin@timinglee.org
3.编辑harbor配置文件
bash
(https://mirrors.tuna.tsinghua.edu.cn/github-release/goharbor/harbor/v2.5.4/harbor-offline-installer-v2.5.4.tgz1)
[root@harbor ~]# tar zxf harbor-offline-installer-v2.5.4.tgz -C /opt/
[root@harbor ~]# cd /opt/harbor/
[root@harbor harbor]# ls
common.sh harbor.v2.5.4.tar.gz harbor.yml.tmpl install.sh LICENSE prepare
[root@harbor harbor]# cp harbor.yml.tmpl harbor.yml
[root@harbor harbor]# vim harbor.yml
hostname: reg.timinglee.org
certificate: /data/certs/timinglee.org.crt
private_key: /data/certs/timinglee.org.key
harbor_admin_password: lee
[root@harbor harbor]# ./install.sh --with-chartmuseum
4.启动并验证
bash
[root@harbor harbor]# mkdir /etc/docker/certs.d/reg.timinglee.org/ -p
[root@harbor harbor]# cp /data/certs/timinglee.org.crt /etc/docker/certs.d/reg.timinglee.org/ca.crt
[root@harbor harbor]# vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.254.200 harbor reg.timinglee.org
#切换到harbor目录下
[root@harbor harbor]# systemctl restart docker
[root@harbor harbor]# docker compose up -d
[root@harbor harbor]# docker login reg.timinglee.org -u admin
Password:
WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/
Login Succeeded
2.构建部署kubernetes所需主机
| 主机名 | ip | 配置 | 角色 |
|---|---|---|---|
| harbor.timinglee.org | 172.25.254.254 | cpu1、mem 1G | harbor仓库 |
| master-node | 172.25.254.100 | cpu4、mem>4G | master,k8s集群控制节点 |
| node1 | 172.25.254.10 | cpu2、mem 2G | worker,k8s集群工作节点 |
| node2 | 172.25.254.20 | cpu2、mem 2G | worker,k8s集群工作节点 |
1.所有主机配置
关闭swap
bash
systemctl disable --now swap.target
systemctl mask swap.target
sed '/swap/s/^/#/g' -i /etc/fstab
安装docker
配置可以使用harbor仓库
bash
mkdir /etc/docker/certs.d/reg.timinglee.org/ -p
#在harbor主机中分发证书到所有主机
[root@harbor ~]# for i in 100 10 20
> do
> scp /data/certs/timinglee.org.crt root@172.25.254.$i:/etc/docker/certs.d/reg.timinglee.org/ca.crt
> done
systemctl enable docker
systemctl restart docker
所有主机配置docker加速器
bash
cat >/etc/docker/daemon.json <<EOF
{
"registry-mirrors":["https://reg.timinglee.org"]
}
EOF
systemctl restart docker
docker info
可以看到
Registry Mirrors:
https://reg.timinglee.org/
所有主机彼此建立解析
bash
vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.254.100 master
172.25.254.10 node1
172.25.254.20 node2
172.25.254.200 reg.timinglee.org
所有主机配置kubernetes安装源
bash
vim /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name = kubernetes
baseurl = https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.35/rpm/
gpgcheck = 0
#检测
dnf list kubelet
以上操作完成后重启主机检测swap分区
bash
swapoff -a
swapon -s 没有任何输出表示ok
3.kubernetes的部署
1.安装cri-dockerd(所有主机中安装)
bash
(wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.14/cri-dockerd-0.3.14-3.el8.x86_64.rpm
wget https://kojihub.stream.centos.org/kojifiles/packages/libcgroup/0.41/19.el8/x86_64/libcgroup-0.41-19.el8.x86_64.rpm
)
[root@master ~]# ls
anaconda-ks.cfg cri-dockerd-0.3.14-3.el8.x86_64.rpm libcgroup-0.41-19.el8.x86_64.rpm
[root@master ~]# rpm -ivh *.rpm
警告:libcgroup-0.41-19.el8.x86_64.rpm: 头V4 RSA/SHA256 Signature, 密钥 ID 6d745a60: NOKEY
Verifying... ################################# [100%]
准备中... ################################# [100%]
正在升级/安装...
1:libcgroup-0.41-19.el8 ################################# [ 50%]
2:cri-dockerd-3:0.3.14-3.el8 ################################# [100%]
#添加这个才能让集群里的node节点添加上网路插件
vim /lib/systemd/system/cri-docker.service
ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd:// --network-plugin=cni --pod-infra-container-image=reg.timinglee.org/k8s/pause:3.10.1
# 重新加载 systemd 配置并启动服务
systemctl daemon-reload
systemctl enable --now cri-docker
ll /var/run/cri-dockerd.sock
2.安装构建kubernetes 集群所需软件
master节点
bash
dnf install kubelet kubeadm kubectl -y
systemctl enable --now kubelet.service
node节点
bash
dnf install kubelet kubeadm -y
systemctl enable --now kubelet.service
master节点中 kubectl 和kubeadm 补齐
bash
[root@master ~]# echo "source <(kubectl completion bash)" >> ~/.bashrc
[root@master ~]# echo "source <(kubeadm completion bash)" >> ~/.bashrc
[root@master ~]# source ~/.bashrc
3.下载kubernetes集群所需镜像
下载镜像
bash
[root@master ~]# kubeadm config images pull \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.35.3 \
--cri-socket=unix:///var/run/cri-dockerd.sock
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-apiserver:v1.35.3
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-controller-manager:v1.35.3
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-scheduler:v1.35.3
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-proxy:v1.35.3
[config/images] Pulled registry.aliyuncs.com/google_containers/coredns:v1.13.1
[config/images] Pulled registry.aliyuncs.com/google_containers/pause:3.10.1
[config/images] Pulled registry.aliyuncs.com/google_containers/etcd:3.6.6-0
上传镜像到本地harbor
bash
[root@master ~]# docker login reg.timinglee.org -u admin
Password:
WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/
Login Succeeded
#提前在harbor上创建k8s目录
[root@master ~]# docker images --format "{{.Repository}}:{{.Tag}}" | awk -F "/" '/google/{system("docker tag "$0" reg.timinglee.org/k8s/"$3)}'
[root@master ~]# docker images --format "{{.Repository}}:{{.Tag}}" | awk -F "/" '/timinglee/{system("docker push "$0)}'
4.在master中初始化kubernetes集群
在master中完成集群初始化
bash
[root@master ~]# kubeadm init --pod-network-cidr=10.244.0.0/16 \
--image-repository reg.timinglee.org/k8s \
--kubernetes-version v1.35.3 \
--cri-socket=unix:///var/run/cri-dockerd.sock
。。。
#每个人不一样,其他主机加入本集群的凭证
kubeadm join 172.25.254.100:6443 --token tdwjoc.8d1yw3wl4r4tm6c4 \
--discovery-token-ca-cert-hash sha256:6b5950ef2cdba85d6dfdb564ee90d4187fa3d341767dc9852cbdd5c9dee4f927
#如果忘记
[root@master ~]# kubeadm token create --print-join-command
kubeadm join 172.25.254.100:6443 --token jl4ztx.cax3iysvu7onsh5s --discovery-token-ca-cert-hash sha256:6b5950ef2cdba85d6dfdb564ee90d4187fa3d341767dc9852cbdd5c9dee4f927
#如果初始化出问题
[root@master ~]# systemctl daemon-reload
[root@master ~]# systemctl restart cri-docker [root@master ~]# systemctl restart docker
[root@master ~]# systemctl restart kubelet
[root@master ~]# kubeadm reset --cri-socket=unix:///var/run/cri-dockerd.sock #可以重置集群设定
如果还是不行看看是不是/usr/lib/systemd/system/cri-docker.service里的ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd://后面是不是没有加 --network-plugin=cni --pod-infra-container-image=reg.timinglee.org/k8s/pause:3.10.1或者是加错了
添加kubernets环境变量到本机
bash
[root@master ~]# echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
[root@master ~]# source ~/.bash_profile
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master NotReady control-plane 102s v1.35.3
添加node节点到本集群
bash
[root@node1 ~]# kubeadm join 172.25.254.100:6443 --token jl4ztx.cax3iysvu7onsh5s --discovery-token-ca-cert-hash sha256:6b5950ef2cdba85d6dfdb564ee90d4187fa3d341767dc9852cbdd5c9dee4f927 --cri-socket=unix:///var/run/cri-dockerd.sock
#测试
[root@master ~]# kubectl get nodes #可以看到集群中主机但是因为网络插件问题状态是NotReady
NAME STATUS ROLES AGE VERSION
master NotReady control-plane 5m16s v1.35.3
node1 NotReady <none> 66s v1.35.3
node2 NotReady <none> 58s v1.35.3
5.安装网络插件
bash
[root@master ~]# ls
anaconda-ks.cfg flannel-0.28.1.tar libcgroup-0.41-19.el8.x86_64.rpm
cri-dockerd-0.3.14-3.el8.x86_64.rpm kube-flannel.yml
[root@master ~]# docker load -i flannel-0.28.1.tar
# 在harbor里面创建flannel-io文件
[root@master ~]# docker tag ghcr.io/flannel-io/flannel-cni-plugin:v1.9.0-flannel1 reg.timinglee.org/flannel-io/flannel-cni-plugin:v1.9.0-flannel1
[root@master ~]# docker push reg.timinglee.org/flannel-io/flannel-cni-plugin:v1.9.0-flannel1
The push refers to repository [reg.timinglee.org/flannel-io/flannel-cni-plugin]
2c8aa52d4746: Pushed
5aa68bbbc67e: Pushed
v1.9.0-flannel1: digest: sha256:b3d30c221113b30fea3e8a7fccb145e929b097d0319b9eeb6b5a591b10b5c671 size: 739
[root@master ~]# docker tag ghcr.io/flannel-io/flannel:v0.28.1 reg.timinglee.org/flannel-io/flannel:v0.28.1
[root@master ~]# docker push reg.timinglee.org/flannel-io/flannel:v0.28.1
The push refers to repository [reg.timinglee.org/flannel-io/flannel]
5668da16a30b: Pushed
5f70bf18a086: Pushed
00012e17b6cc: Pushed
9738bb9596cf: Pushed
b6233bc105d7: Pushed
03767449b95b: Pushed
9a7d8cf9ff51: Pushed
13a60c10faeb: Pushed
70dc5e033175: Pushed
256f393e029f: Pushed
v0.28.1: digest: sha256:e671adbc267460164555159210066d3304a43e3b5dd85cc0b5b6ad62e83aab52 size: 2414
#使用/image:然后回车,把后面的删掉一些,因为docker info配置了https://reg.timinglee.org/
[root@master ~]# vim kube-flannel.yml
image: flannel-io/flannel:v0.28.1
image: flannel-io/flannel-cni-plugin:v1.9.0-flannel1
image: flannel-io/flannel:v0.28.1
[root@master ~]# docker info
Registry Mirrors:
https://reg.timinglee.org/
Live Restore Enabled: false
Firewall Backend: iptables
[root@master ~]# kubectl apply -f kube-flannel.yml
namespace/kube-flannel created
serviceaccount/flannel created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created
#测试,之后过一会就能看见了
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready control-plane 13m v1.35.3
node1 Ready <none> 9m44s v1.35.3
node2 Ready <none> 9m36s v1.35.3