核心原理阐述
- Kubernetes 架构原理 (Master-Node 模型)
-
控制平面 (Master):集群的大脑。
-
API Server:集群网关,所有操作都必须通过它。
-
Scheduler:负责调度 Pod 到合适的 Node。
-
Controller Manager:维护集群状态(如副本数、故障恢复)。
-
etcd:分布式键值存储,保存集群所有关键数据。
-
工作节点 (Node):干活的单元。
-
kubelet:节点代理,负责与 Master 通信并管理 Pod 生命周期。
-
容器运行时 (Docker/containerd):真正负责运行容器。
-
kube-proxy:维护网络规则,实现 Service 的负载均衡和服务发现。
Kubernetes 资源基础
-
核心概念
- Kubernetes 中所有内容抽象为资源,最小管理单元是 Pod
- 通常通过 Pod 控制器管理 Pod,而非直接管理
- 服务访问通过 Service 实现,数据持久化通过存储系统实现
-
资源管理方式
|---------|------|-----------------|-------------------------------------|
| 类型 | 适用场景 | 特点 | 示例命令 |
| 命令式对象管理 | 测试 | 简单直接,无法审计跟踪 | kubectl run nginx-pod --image=nginx |
| 命令式对象配置 | 开发 | 可审计跟踪,配置文件多时有麻烦 | kubectl create -f nginx-pod.yaml |
| 声明式对象配置 | 开发 | 支持目录操作,意外情况调试难 | kubectl apply -f nginx-pod.yaml | -
Pod 核心知识
Pod 定义
最小可部署单元,代表集群中运行的一个进程
包含一个或多个容器,共享 IPC、Network 和 UTC 命名空间每个 Pod 拥有唯一 IP 地址
1.基础环境准备(4台虚拟机)
核心目标
搭建一个高可用的 Kubernetes 生产级集群,实现容器化应用的自动化部署、扩展和管理。
整体流程
-
理论准备:理解 K8S 架构、组件及其协作原理。
-
环境规划:规划节点角色、网络、存储等资源。
-
基础准备:在所有节点上完成系统初始化(关闭 swap、配置网络、安装 Docker 等)。
-
核心安装:安装 K8S 核心组件 (`kubeadm`, `kubelet`, `kubectl`) 和容器运行时接口 (`cri-dockerd`)。
-
私有仓库:配置 Harbor 作为私有镜像仓库,供集群拉取镜像。
-
集群初始化:在 Master 节点使用 `kubeadm init` 初始化控制平面。
-
网络部署:安装 Flannel CNI 插件,为 Pod 提供网络通信能力。
-
节点扩容:将 Worker 节点加入集群,形成多节点集群。
-
功能验证:创建测试 Pod 验证集群基本功能是否正常。
1.1 reg节点
先开一台reg节点的虚拟机,IP为192.168.1.222
关闭selinux

部署Harbor
下载安装所需依赖包:这里已经提前下好,直接拖进来了





使用OpenSSL生成自签名证书,保障HTTPS通信
bash
[root@reg ~]# 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
国家,省,市,...


提供私有Docker镜像仓库,仓库地址为reg.timinglee.org,供集群内其他节点拉取镜像。。


等待构建完成,通过Docker Compose启动Harbor服务。配置所有节点信任自签名证书,并登录私有仓库。
bash
ps:第一次启动用./install.sh --with-chartmuseum
后面启动时进入harbor目录通过Docker Compose启动
cd harbor/
docker compose up -d
注意:每次关闭虚拟机后重启时,都要通过该命令重启Harbor服务


成功后就可以访问了


此时reg虚拟机就可以后台运行了,接下来我们看另外的
1.2 Kubernetes集群搭建
克隆三台主机:master100 ,node1:10,node2:20


关闭swap和本地解析
关闭Swap以确保内存管理一致性。


关闭当前三个节点的所有swap,并且重启之后也不能有

修改/etc/hosts,确保节点间可通过主机名通信。



所有节点安装Docker,
前面我们在reg节点上已经配置好docker了,现在把安装包拷贝到其他三个节点上。






Master编辑配置文件

拷到其他两个node节点


配置仓库的加速器
并配置镜像加速器指向私有Harbor仓库。重启Docker服务并登录Harbor。

bash
[root@docker1 ~]# cat /etc/docker/daemon.json
{
"registry-mirrors": [
"https://reg.timinglee.org",
]
}

bash
[root@master docker]# for i in 10 20; do scp daemon.json root@192.168.1.$i:/etc/docker/; done
daemon.json 100% 57 85.4KB/s 00:00
daemon.json 100% 57 117.3KB/s 00:00
[root@master docker]# for i in 100 10 20; do ssh root@192.168.1.$i systemctl enable --now docker; done

Docker info

这三个主机都检查一下复制的文件成功没,一般这个时候就可以登陆了,但是
登陆报错,发现少了一个目录
cd /etc/docker/certs.d/



记得检查是否复制成功


再次登陆,成功
登陆其他主机(所有主机都必须登陆,否则下不来东西)

1.3 安装k8s
1.3.1 修改cri-dockerd启动文件添加
将需要安装的包下载下来,这里是有文件包直接拖进来了,没有的话可以去官网上搜索包下载'

对于其他的节点前面下载了docker包,现在可以先把包删除,再从master把新包拷过去


node2同理

配置kubelet使用cri-dockerd作为容器运行时。启动kubelet服务。









1.3.2 安装K8s部署工具

在【master】配置环境变量,设置kubectl命令补齐功能、
bash
dnf install bash-completion -y
echo "source <(kubectl completion bash)" >> ~/.bashrc
source ~/.bashrc
1.4 拉取k8s镜像
导入镜像

$0所有
root@master docker-images# docker images | awk '/google/{print 1":"2}' |awk -F / '{system("docker tag "0" reg.timinglee.org/k8s/"3)}'

bash
[root@master docker-images] docker images | awk '/reg/{print $0}'
我们要的是这些
[root@master docker-images] docker images | awk '/reg/{print $1":"$2}'
就可以开始推了
如果拉取失败仓库拒绝可能是没开启重启一下reg的harbor
进入到harbor的目录下面
docker compose down 再docker compose up -d
root@master docker-images# docker images | awk '/timinglee/{system("docker push " 1":"2)}'



【三个节点】
打开服务



bash
指定容器网络
kubeadm init --pod-network-cidr=10.244.0.0/16 \
--image-repository reg.timinglee.org/k8s \
--kubernetes-version v1.30.0 \
--cri-socket=unix:///var/run/cri-dockerd.sock
先导入配置
[root@master docker-images] echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
[root@master docker-images] source ~/.bash_profile
[root@master docker-images] kubectl get nodes
NAME STATUS ROLES AGE VERSION
master.timinglee.org NotReady control-plane 2m v1.30.0

notready未运行成功
其他节点

现在节点加不进去,因为还没有网络插件flannel
1.5 拉取Flannel镜像
先导入镜像:有俩个镜像显示

从Docker Hub拉取Flannel镜像,推送到私有Harbor。
分为三步 tag-新建项目-push
#先创建项目再拉取push,否则会拉取失败

cs
两个镜像就要操作两次
docker tag flannel/flannel:v0.25.5 reg.timinglee.org/flannel/flannel:v0.25.5
#push 仓库网站/项目目录/镜像名 如果有了该目录,就不需要新建
docker push reg.timinglee.org/flannel/flannel:v0.25.5
bash
打标签
docker tag flannel/flannel-cni-plugin:v1.5.1-flannel1 reg.timinglee.org/flannel/fl annel-cni-plugin:v1.5.1-flannel1
上传
docker push reg.timinglee.org/flannel/flannel-cni-plugin:v1.5.1-flannel1
修改kube-flannel.yml中的镜像地址为私有仓库路径。

修改文件kube-flannel.yml
cs
把前缀去掉即可
[root@master ~]# kubectl apply -f kube-flannel.yml
[root@master ~]# kubectl get nodes


应用Flannel配置,等待Pod就绪。




要等插件运行起来后才能看到


1.6 其他主机加入集群
使用kubeadm join命令将node10和node20加入集群。检查节点状态和网络连通性。
火墙是不是没关

记得检查火墙

bash
kubeadm join 192.168.1.100:6443 --token w6p5gc.a5halrlwz735s7rb --discovery-token-ca-cert-hash sha256:9166dd9826643972c931f34a0ace7e663cd69efa8f32c6e931b3f89ed3b90224 --cri-socket=unix:///var/run/cri-dockerd.sock

加载的比较慢可能是火墙

cpp
出现问题重新加载
[root@node2 ~]# kubeadm reset --cri-socket=unix:///var/run/cri-dockerd.sock
再执行刚才的命令
kubeadm join 192.168.1.100:6443 --token w6p5gc.a5halrlwz735s7rb --discovery-token-ca-cert-hash sha256:9166dd9826643972c931f34a0ace7e663cd69efa8f32c6e931b3f89ed3b90224 --cri-socket=unix:///var/run/cri-dockerd.sock
到此为止安装完成

1.7 测试


登不上去,没认证



有点慢


先登录再认证



可以看到两个节点各自运行了一个nginx

容器编排原理
Pod:K8S 最小调度单元,包含一个或多个共享网络/存储的容器。
Controller:通过定义期望状态(如 replicas: 3)来管理 Pod 的生命周期,确保实际状态始终向期望状态收敛(声明式管理)。
Service:为一组 Pod 提供稳定的访问入口和负载均衡。
CNI (Container Network Interface):Flannel 等插件负责为每个 Pod 分配 IP 并实现跨节点网络通信。
2. 基础Pod与控制器实验
2.1 Pod镜像准备




bash
docker tag busyboxplus:latest reg.timinglee.org/library/busyboxplus:latest
docker push reg.timinglee.org/library/busyboxplus

bash
docker tag timinglee/myapp:v1 reg.timinglee.org/library/myapp:v1
#记得push要新建项目
docker push reg.timinglee.org/library/myapp:v1



导入nginx镜像

bash
#创建一个webcluster控制器,控制器中pod数量为2
把nginx上传到harbor仓库
docker tag nginx:latest reg.timinglee.org/library/nginx:latest
新建项目后再push
docker push reg.timinglee.org/library/nginx:latest
直接创建自主式Pod,生命周期与Pod绑定。创建Deployment管理Pod副本,支持滚动更新和回滚。通过kubectl edit实时修改配置如镜像版本。
bash
[root@k8s-master ~] kubectl create deployment webcluseter --image nginx --replicas 2
#查看控制器
[root@k8s-master ~] kubectl get deployments.apps
这是在 Kubernetes 环境中创建一个名为 webcluseter 的 Deployment 资源,指定使用 nginx 镜像,期望副本数(--replicas)为 2 ,输出 deployment.apps/webcluseter created 表示 Deployment 创建成功
一个Pod内运行多个容器,共享网络和存储空间。注意端口冲突问题需配置不同端口或协议。在Pod主容器启动前运行Init容器执行初始化任务。
Pod运行后修改不了配置文件了
控制器可以直接进到文件里面修改
#编辑控制器配置
root@k8s-master \~# kubectl edit deployments.apps web

只是进去看了一下,什么都没改,所以显示no changes made
bash
#删除资源
[root@k8s-master ~] kubectl delete deployments.apps web
deployment.apps "web" deleted
[root@k8s-master ~] kubectl get deployments.apps
No resources found in default namespace.
一个pod运行两个容器个
test里面有两个基于nginx的容器test1和test2

会自动生成配置文件


STATUS会刷新,一会运行一会error,因为我们配置了两个test1,test2,两个共享网路资源端口冲突

修改

现在两个都运行
Kubectl describe pod查看状态

进入容器内部输入指令

可以访问本地

每次小实验结束后都把该pod删除,以免影响后续实验

2.2 创建自助式pod(生产不推荐
优点是灵活性高,可以精确控制 Pod 的各种配置参数,通过手动创建 Pod 可以深入了解 Pod 的结构和配置方式。在调试问题时,可以更直接地观察和调整 Pod 的设置。
缺点是手动创建和维护pod在数量较多时非常繁琐,容易出错,且缺乏高级功能,如自动部署、滚动更新、服务发现等。这可能导致应用的部署和管理效率低下。
cs
#查看所有pods
[root@k8s-master ~]# kubectl get pods
No resources found in default namespace.
#建立一个名为timinglee的pod
[root@k8s-master ~]# kubectl run timinglee --image nginx
pod/timinglee created
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
timinglee 1/1 Running 0 6s
#显示pod的较为详细的信息
[root@k8s-master ~]# kubectl get pods -o wide
配置存活探针检测容器是否健康,失败时重启容器。配置就绪探针检测容器是否准备好接收流量,失败则从Service负载均衡中移除。
3. 运用控制器管理pod
在 Kubernetes (k8s) 中,控制器(Controller)是实现 Pod 自动化管理的核心组件,它们通过监控集群状态并调整实际状态以匹配期望状态,确保 Pod 按照预设规则稳定运行。
以下是控制器的核心作用和常见使用场景:
3.1、控制器的核心作用
维持期望状态
控制器通过 watch 机制监控 Pod 和其他资源的状态,当实际状态与用户定义的期望状态(如副本数、运行节点等)不一致时,会自动触发调整(如创建 / 删除 Pod、重启故障实例等)。
简化 Pod 管理
直接管理 Pod 存在局限性(如 Pod 故障后不会自动重建),而控制器通过抽象层(如 Deployment、StatefulSet)简化了复杂操作(如滚动更新、扩缩容)。
实现高级功能
支持自愈、弹性伸缩、滚动更新、有状态服务管理等 Kubernetes 核心特性。
3.2、常见控制器及使用场景
以下是 Kubernetes 主要控制器的对比与适用场景的表格整理:
| 控制器类型 | 核心用途 | 关键特性 | 适用场景 | 替代/关联组件 |
|---|---|---|---|---|
| ReplicationController | 确保指定数量的 Pod 副本运行(已废弃) | 最早的副本管理控制器,支持基本扩缩容和自愈,功能有限 | 历史遗留场景,不再推荐使用 | 被 ReplicaSet 完全替代 |
| ReplicaSet | 确保任意时刻有指定数量的 Pod 副本运行 | 通过标签选择器关联 Pod,自动创建/删除以维持副本数 | 作为 Deployment 的底层组件,不建议直接使用 | 被 Deployment 间接管理 |
| Deployment | 提供 Pod 和 ReplicaSet 的声明式更新能力 | 支持滚动更新、版本回滚、扩缩容,自动管理 ReplicaSet | Web 服务、API 服务等无状态应用 | 基于 ReplicaSet 实现 |
| DaemonSet | 确保每个指定节点上运行一个 Pod 副本 | 新节点加入时自动部署,支持节点亲和性筛选 | 日志收集(Fluentd)、监控代理(Node Exporter) | 无 |
| StatefulSet | 管理有状态应用的稳定运行 | 固定 Pod 名称/网络标识(DNS)、有序部署/更新/删除、存储与 Pod 解绑(PVC) | 数据库(MySQL)、分布式系统(ZooKeeper) | 需配合 Headless Service 使用 |
| Job | 执行一次性批处理任务 | 任务完成后 Pod 自动终止,支持并行执行和重试 | 数据备份、离线计算、一次性脚本执行 | 无 |
| CronJob | 基于时间调度周期性任务 | 类似 Linux crontab,支持 cron 表达式定义调度规则 | 定时日志清理、周期性数据同步 | 基于 Job 实现 |
| HPA | 根据资源使用率自动调整 Pod 副本数 | 支持 CPU/内存或自定义指标(如 QPS),动态扩缩容 | 流量波动大的应用(如电商促销) | 需与 Deployment/StatefulSet 配合 |
关键说明
- 废弃组件:ReplicationController 已完全被 ReplicaSet 替代。
- 间接使用:ReplicaSet 通常由 Deployment 管理,无需手动操作。
- 有状态与无状态:StatefulSet 适用于需稳定标识和存储的场景,Deployment 适用于无状态服务。
- 自动化扩展:HPA 需配置指标源(如 Metrics Server)才能生效。
ReplicaSet(副本集)
作用
确保指定数量的 Pod 副本始终运行。
特点
通过 selector 关联 Pod,自动调整 Pod 数量。
虽然 ReplicaSets 可以独立使用,但今天它主要被Deployments 用作协调 Pod 创建、删除和更新的机制
cpp
#生成yml文件.名字自取不固定
[root@k8s-master ~]# kubectl create deployment replicaset --image reg.timinglee.org/library/myapp:v1 --replicas 2 --dry-run=client -o yaml > replicaset.yml
#生成一个 Deployment 的 YAML 配置文件,文件名为 replicaset.yml。
#这个配置会创建一个名为 "replicaset" 的 Deployment,使用指定的镜像并保持 2 个副本。
[root@k8s-master ~]# vim replicaset.yml
apiVersion: apps/v1
kind: ReplicaSet #控制器类型
metadata:
labels: #给控制器标签,让微服务可以发现它
app: replicaset
name: replicaset #指定pod名称,一定小写,如果出现大写报错
spec:
replicas: 2 #指定维护pod数量为2
selector: #指定检测匹配方式
matchLabels: #指定匹配方式为匹配标签
app: replicaset #指定容器匹配的标签为app=replicaset ,让控制器可以检测到它
template: #模板,当副本数量不足时,会根据下面的模板创建pod副本
metadata:
labels:
app: replicas
spec:
containers:
- image: reg.timinglee.org/library/myapp:v1
name: myapp
[root@k8s-master ~]# kubectl apply -f replicaset.yml
replicaset.apps/replicaset created
cpp
[root@k8s-master ~]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
replicaset-l4xnr 1/1 Running 0 96s app=myapp
replicaset-t2s5p 1/1 Running 0 96s app=myapp
#replicaset是通过标签匹配pod
[root@k8s-master ~]# kubectl label pod replicaset-l4xnr app=timinglee --overwrite
pod/replicaset-l4xnr labeled
[root@k8s-master ~]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
replicaset-gd5fh 1/1 Running 0 2s app=myapp #新开启的pod
replicaset-l4xnr 1/1 Running 0 3m19s app=timinglee
replicaset-t2s5p 1/1 Running 0 3m19s app=myapp
#恢复标签后
[root@k8s2 pod]# kubectl label pod replicaset-example-q2sq9 app-
[root@k8s2 pod]# kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
replicaset-example-q2sq9 1/1 Running 0 3m14s app=nginx
replicaset-example-th24v 1/1 Running 0 3m14s app=nginx
replicaset-example-w7zpw 1/1 Running 0 3m14s app=nginx
#replicaset自动控制副本数量,pod可以自愈
[root@k8s-master ~]# kubectl delete pods replicaset-t2s5p
pod "replicaset-t2s5p" deleted
#即如果我们删除pods,它还会自动创建一个新的
[root@k8s-master ~]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
replicaset-l4xnr 1/1 Running 0 5m43s app=myapp
replicaset-nxmr9 1/1 Running 0 15s app=myapp
#如果想删除,直接删除控制器,指明控制器类型和名字
[root@k8s-master ~]kubectl delete replicaset replicaset
回收资源
[root@k8s2 pod]# kubectl delete -f replicaset.yml
deployment控制器
-
Deployment控制器并不直接管理pod,而是通过管理ReplicaSet来间接管理Pod
-
Deployment管理ReplicaSet,ReplicaSet管理Pod
cs
#生成yaml文件
[root@k8s-master ~]# kubectl create deployment dep --image myapp:v1 --dry-run=client -o yaml > dep.yml
[root@k8s-master ~]# vim dep.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment
spec:
replicas: 4
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- image: myapp:v1
name: myapp
#建立pod
root@k8s-master ~]# kubectl apply -f dep.yml
deployment.apps/deployment created
#查看pod信息
[root@k8s-master ~]# kubectl get pods --show-labels
版本更新
版本回滚
滚动更新策略
暂停及恢复
deamonset控制器
作用:确保集群中所有(或指定)节点运行相同的 Pod 副本,新节点 加入时自动部署 。
适用场景:日志收集(如 Fluentd)、监控代理(如 Prometheus Node Exporter)、网络插件(如 Calico)等节点级服务。
示例:在所有节点部署pod副本

cs
进入之前的yml文件目录
创建yml文件
[root@master 2.pod]# vi daemonset-example.yml
[root@master 2.pod]# kubectl apply -f daemonset-example.yml
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
run: daemonset-example
name: daemonset-example
spec:
selector:
matchLabels:
app: daemonset-example
template:
metadata:
labels:
app: daemonset-example
spec:
containers:
- image: myapp:v1
name: myapp
格式非常严格!一个空格也不能少!

DaemonSet 的设计逻辑是 "在集群中每个符合条件的节点上运行且仅运行一个 Pod 副本" :
我们前面集群创建了三个节点,3 个节点对应 3 个 Pod,确保每个节点(无论当前是否就绪)都有一个关联的 Pod,节点就绪后会自动启动 Pod。所以这里有三个

正常状态下三个都是running
root@master 2.pod# kubectl describe pod daemonset-example-c2njr查看状态,未运行原因
由于我为节省运行内存只开了三台机子(master,node1,reg),也就是master只有一个子节点,另一个节点本身未就绪,无法运行 Pod,所以有一个节点是就绪状态pending


cs
# 查看所有 DaemonSet 管控的 Pod
kubectl get pods -l app=daemonset-example
# 删除 DaemonSet(会自动删除所有关联 Pod)
kubectl delete -f daemonset-example.yml
或者kubectl delete daemonset daemonset-example
# 扩容/缩容(虽然 DaemonSet 通常按节点数自动管理,但可强制更新)
kubectl rollout restart daemonset daemonset-example
通过标签筛选 Pod:
因为 Pod 有 app: daemonset-example 标签,也能精准筛选:
kubectl get pods -l app=daemonset-example
Job 与 CronJob(一次性/定时任务)
Job
执行一次性任务,任务完成后 Pod 自动终止。适合批量处理短暂的一次性任务(要指定任务数量)
CronJob
基于时间调度的 Job,如定时备份、日志清理。
job:指定任务
cs
[root@k8s-master ~]# kubectl create job job-example --image myapp:v1 --dry-run=client -o yaml > job-example.yml
[root@k8s2 pod]# vim job-exampleb.yml
apiVersion: batch/v1
kind: job
metadata:
name:job-example
spec:
completions: 6 #一共完成任务数为6
parallelism: 2 #每次并行完成2个
backoffLimit: 4 #运行失败后尝试4重新运行
template:
spec:
containers:
- name: pai
image: perl:5.34.0
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] 计算Π的后2000位
restartPolicy: Never #关闭后不自动重启
backoffLimit: 4 #运行失败后尝试4重新运行
[root@k8s2 pod]# kubectl apply -f job.yml
每次要用到什么镜像时,如果镜像没有导入,我们都要导入该镜像上传到harbor仓库,否则拉取不到镜像,配置无法生效

push 仓库网站/项目目录/镜像名
上传成功后再apply配置文件
cpp
查看有没有建立成功
kubectl get pods -o wide
刚开始是两个两个开始建立
创建需要时间
直到完成六个的创建


cronjob:指定时间

比如:每天凌晨 2 点执行备份 "0 2 * * *"
cpp
[root@k8s2 pod]# vim cronjob.yml
apiVersion: batch/v1
kind: CronJob
metadata:
name: hello
spec:
schedule: "* * * * *" #位置要在job前面,*表示默认值1,每分钟新建一个
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
imagePullPolicy: IfNotPresent #镜像拉取策略
command:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure #拉取失败不计入次数
[root@k8s2 pod]# kubectl apply -f cronjob.yml
两个必须写一个
否则默认值是always,一直会反复重新运行
测试





