Kubernetes K8S
一、基础
1、概述:k8s是谷歌在2014年开源的容器化集群管理系统,可以使用k8s进行容器化应用部署,利于应用扩展,让部署容器化应用更加简洁高效。
2、特性:自动装箱、自我修复、水平扩展、服务发现、滚动更新、版本回退、秘钥和配置管理、存储编排、批处理
K8s控制器的设计哲学:"声明式"(只需告诉系统“要什么”——“我要3个Nginx Pod永远运行,而非命令式告诉系统“怎么做”)与"调谐循环"(背后的控制器Controller一直在做无限循环)
3、架构:Master node(主控节点)和Worker node(工作节点)

(1)master组件
apiserver:集群的统一入口,restful方式,交给etcd存储
scheduler:节点调度,选择node节点
controller-mannager:处理集群中的常规后台任务,一个资源对应一个控制器
etcd:存储系统,用于保存集群相关的数据
(2)node组件
kubelet:是master派到node节点的代表,管理本机容器
kube-proxy:提供网络代理,实现负载均衡等操作
docker:用来实现容器化
4、核心概念
pod:是k8s的最小部署单元,共享网络,生命周期是短暂的,是一组容器的集合
controlle:创建pod,确保预期的pod副本数量,确保所有的node运行同一个pod,无状态应用部署
service:统一入口,定义一组pod的访问规则
5、硬件要求
master 至少2核 4G 20G,node至少4核 8G 40G
6、主要部署方式有两种:
kubeadm工具,简单,步骤:安装及初始化操作系统、安装docker/kubectl/kubelet/kubeadm、master节点kubeadm init初始化、node节点kubeadm join把节点加入到当前集群、配置网络插件
二进制包,复杂
7、平台规划:单master集群、多master集群(node和master之间通过负载均衡组件过渡)
二、安装前的初始化
1、临时关闭防火墙:systemctl stop firewalld
永久禁用防火墙(防止开机自启):systemctl disable firewalld
2、关闭 selinux:不是为了关掉安全性,而是为了绕过由于默认策略不匹配导致的各种奇怪故障(文件访问失败、日志无法写入、网络不通等)
3、关闭 swap:是为了给 kube-scheduler 提供准确的决策依据,避免不可预测的磁盘 I/O 瓶颈,避免不可控的性能波动,保证容器应用性能的稳定和可预测。swap 的本质是用磁盘 I/O 换内存空间,而磁盘速度比内存慢几个数量级。一旦触发 swap,节点可能依赖慢速的磁盘作为“假内存”,导致调度器做出错误决策,让过多 Pod 挤在一个节点上,而且应用延迟会急剧飙升,尤其对数据库这类应用是灾难性的。
4、主机名:hostnamectl set-hostname
5、在 master 添加 hosts:
$ cat >> /etc/hosts << EOF
192.168.31.61 k8s-master
192.168.31.62 k8s-node1
192.168.31.63 k8s-node2
EOF
6、将桥接的 IPv4 流量传递到 iptables 的链
$ cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
$ sysctl --system # 生效
6.时间同步:
$ yum install ntpdate -y
$ ntpdate time.windows.com
三、安装docker并更改yum源,然后安装kubeadm、kubectl、kubelet,最后执行kubectl init命令部署k8s Master,执行kubeadm join把node节点加入到master,并在完成后安装CNI网络插件
四、kubectl命令
格式:kubectl [command] [Type] [Name] [flags]
如:kubectl creat deployment nginx --image=nginx
帮助命令:kubectl --help
查看具体某个操作:kubectl get --help
五、Yaml文件:资源清单文件
通过锁紧表示层级关系
不能使用TAB进行缩进,只能使用空格,一般开头缩进两个空格,字符(冒号,逗号等)后缩进1个空格
使用#代表注释
使用--表示新的yaml文件开始
使用kubectl creat快速创建yaml文件
kubectl creat deployment web --image=nginx -o yaml --dry-run >my001.yaml
- --dry-run=client:完整的参数写法,表示在客户端进行试运行,不实际创建资源
- -o yaml:也可以写作 --output=yaml,指定输出格式为YAML(-o 后面需要跟格式类型)
-
my001.yaml:将输出的 YAML 内容重定向到文件
- 生成模板后,可以执行 kubectl apply -f my001.yaml 来创建资源
使用kubectl get快速创建yaml文件
kubectl get deploy nginx -o=yaml --export > my2.yaml
- -o=yaml 和 -o yaml 是等价的,空格和等号都可以
- deploy 是 deployment 的合法短名称
- --export命令 已在新版本中移除
六、POD
- 最小部署单元
- 包含多个容器(一组容器的集合)
- 一个pod中容器共享网络命名空间
- pod是短暂的
创建容器使用的是docker(单进程设计),一个docker对应一个容器,一个容器对应一个进程,一个进程对应运行一个应用程序
Pod是多进程的,一个pod里可以运行多个容器,容器本身之间是相互隔离的,每个进程只对应一个容器,即可运行多个应用程序,且便于管理
pod存在的意义:为了亲密性应用(同一个pod里,应用之间的网络调用、交互、频繁调用,相当于是在同一个内网,性能更好 )
pod实现机制:
(1)共享网络机制:
Pause 容器作为网络命名空间的锚点,让同一个 Pod 内的其他容器共享同一个网络命名空间
1.每个 Pod 在创建时会先启动一个 Pause 容器(info容器,生命周期等于 Pod 的生命周期),它负责持有网络命名空间
2.创建业务容器,并使用 Linux 的 setns() 系统调用,将业务容器加入到同一个NameSpace命名空间
3.通过 CRI 接口实现容器运行时的网络共享(共享ip mac port)
4.localhost 零开销通信,通信效率高,不需要网络地址转换,减少网络资源消耗,性能接近本地
(2)共享存储机制:引入数据卷volume的概念,使用数据卷进行持久化数据。
Volume 是 Pod 级别的存储抽象,独立于容器存在,Pod 内所有容器都可以挂载和访问。
emptyDir - 临时共享存储,Pod 创建时自动创建,Pod 删除时永久删除,适合临时缓存、共享临时数据
hostPath - 宿主机路径,持久化到宿主机磁盘,Pod 删除后数据保留,适用于 DaemonSet 或单节点测试
七、POD的镜像拉取策略:通过spec.containers[].imagePullPolicy来控制
IfNotPresent:默认值,镜像在宿主机上不存在时才拉取
Always:每次创建Pod都会重新拉取一次镜像
Never:pod永远不会主动拉取这个镜像
POD的资源限制(通过docker实现):通过配置spec.containers[].resource.request(调度)、spec.containers[].resource.limits(最大)来限制memory和cpu
POD的重启机制:通过参数spec.containers[].restartPolicy来控制
Always:默认值,当容器终止退出后,总是重启容器
OnFailure:当容器异常退出(退出状态码非0)时才重启
Never:当容器终止退出,从不重启容器
八、POD健康检查
存活检查livenessProbe:如果检查失败,将杀死容器,根据pod的重启策略来操作
就绪检查readinessProbe:如果检查失败,k8s会把pod从service endpoints中剔除。
Probe支持三种检查方式:
httpGet:发送HTTP请求,返回200-400范围内的状态码为成功
exec:执行shell命令返回状态是0的为成功
tcpSocket:发起tcp socket建立成功
真实业界实践:
两个探针使用不同的HTTP路径,liveness探针检查死锁(简单自检),readiness探针检查就绪状态(含依赖)
liveness:检查 /healthz(仅返回200,证明没有死锁),只检查"进程是否还能响应",使用独立简单逻辑
readiness:检查 /ready(延迟初始化、依赖检查等),检查"是否可以处理业务流量",依赖外部服务
九、POD节点调度的影响因素:
request最小/limits最大资源限制、选择器NodeSelector、亲和性、污点和污点容忍
亲和性NodeAffinity
配置关键词:key(env_role) Operator (In、NotIn) value (dev、prod)
硬亲和性:约束条件必须满足
软亲和性:尝试满足,尽量满足,不保证
污点Taint
NoSchedule:一定不被调度
PreferNoSchedule:尽量不被调度
NoExecute:不会调度,并且还会驱逐Node上已有的不容忍的Pod


十、Controller:在集群上管理和运行容器的对象,确保预期的POD副本数量,确保所有的node运行同一个pod,管理一次性任务和定时任务
deployment是controller的一种具体实现
pod是通过controller实现应用的运维,比如伸缩、滚动升级
pod和Controller之间通过label标签和selector标签建立关系
controller:
selector:
app:nginx
pod:
labels:
app:nginx
1、导出yaml文件(试执行)
kubectl create deployment web --image=nginx --dry-run -o yaml >web.yaml
2、使用yaml部署应用
kubectl apply -f web.yaml
3、对外发布(暴露对外端口)
kubectl expose deployment web --port=80 --type=NodePort --target-port=80 --name=web1 -o yaml > web1.yaml
/# 使用 -o yaml 参数将 Service 的 YAML 定义输出到终端,通过 > web1.yaml 将这个 YAML 内容保存到本地文件,注意:这个命令没有实际创建 Service,只是生成了 YAML 文件
kubectl apply -f web1.yaml
应用升级回滚
应用升级:kubectl set image deployment web nginx=nginx:1.14
查看应用升级状态:kubectl rollout status deployment web
查看升级版本:kubectl rollout history deployment web
回滚到上一个版本:kubectl rollout undo deployment web
回滚到指定版本:kubectl rollout undo deployment web --to-revision=2
弹性伸缩:kubectl scale deployment web --replicas=3
/# 可以通过spec.revisionHistoryLimit字段控制保留多少个旧版本,默认保留10个
/# K8s的控制器模式,指的是“观察(Observe)、比较(Diff)、行动(Act)”的循环,这是一个经典的调谐循环,目标是 “让当前状态始终等于期望状态”
观察:通过 API Server 获取资源的期望状态(例如:replicas: 3)。
比较:比较期望状态与当前状态(例如:当前只有 2 个 Pod 在运行)。
行动:采取措施纠正差异,让当前状态向期望状态靠拢(例如:再创建一个新的 Pod、剔除多出的pod)
十一、service:定义一组Pod的访问规则
pod和service,与Controller一样,是通过label标签和selector标签建立关系
1、服务发现:防止pod失联(POD的IP发生变化时由service作为注册中心进行调度)
2、负载均衡:定义一组POD的访问策略,通过service实现pod的负载均衡
3、常见类型:ClusterIP(集群内部使用,默认值)、Nodeport(对外访问应用使用,暴露端口)、LoadBalancer(对外访问应用使用,适用于公用云,控制负载均衡的控制器)
kubectl get svc
十二、有状态和无状态
1、无状态:
认为POD都是一样的,没有顺序要求
不用考虑在哪个NODE运行,随意进行伸缩和扩展
2、有状态
无状态的因素都需要考虑到
让每个pod独立,保持pod启动顺序和唯一性
唯一性:唯一的网络标识符,持久存储
有序:比如mysql主从
无头的service:Cluster-Ip是None
使用statefulSet部署有状态应用
每个POD有唯一的主机名
唯一域名:根据主机名+一定规则生成域名,格式:主机名称.service名称.命名空间.svc.cluster.local
其他:
scale,丝盖欧,按比例缩放调整
replicas,瑞普利卡兹,仿制品,复制品,副本
daemon,迪蒙,守护进程,精灵进程
affinity,额费讷提,亲和性
taints,污点
terminated,特米奈提德,已结束
pending,盆鼎,准备中
缩写:
deployment->deploy
namespace->ns
service->svc
pod->po
node->no
--replicas=5 -> -r=5或-r 5(在scale后面缩写)
-o ->output
kubectl describe pod pod-name 输出静态快照
前加:watch -n 2 每2秒刷新一次
后加:| grep -A 5 Event: -w 只盯着事件看
kubectl get nodes -o wide 以宽格式输出,显示默认列表中省略的额外信息


十三、ingress
Ingress 是集群的"统一流量大门",只用一个对外入口(一个 LB 或一个 NodePort),然后根据请求的 域名(host) 和 路径(path) 把流量分发到不同 Service。本质上就是个"七层反向代理"。
• 访问 api.example.com/orders/* → 转发到 orders-service
• 访问 api.example.com/users/* → 转发到 users-service
• 访问 admin.example.com/* → 转发到 admin-service
说人话就是:一个入口、多个域名、多个服务,这就是 Ingress 的核心价值。

一句话总结:Ingress 就是 K8s 集群的"七层路由器",用一个对外入口 + 域名/路径规则,把流量精准分发到后端各个 Service,替代了"一服务一 LB"的浪费模式。


NGINX 是"前台接待 + 邮差 + 保安"三位一体:
• 前台接待——直接把静态资源递给访客
• 邮差——把动态请求送到对应的后端
• 保安——做负载均衡、限流、TLS 卸载、缓存,把脏活累活全包了
它和 Ingress 的关系是:Ingress 是 K8s 里的"路由规则"(一份 YAML),NGINX 是真正执行这些规则的"程序"。你写 Ingress YAML → Ingress Controller 读到 → 翻译成 nginx.conf → NGINX 按配置转发流量。

① 静态资源服务(最原始的定位):NGINX 最早就是个 Web 服务器,直接把磁盘上的文件返回给客户端
动静分离(最经典场景),网站有静态资源(图片/CSS/JS)和动态接口(API),让 NGINX 处理静态、转发动态
② 反向代理(最常用的功能):把客户端请求转发给后端应用,客户端只跟 NGINX 打交道,感知不到后端是谁。应用场景:微服务 API 网关
为什么需要反向代理: • 后端服务不直接暴露,安全 • 后端可以横向扩展,NGINX 做统一入口 • 后端挂了 NGINX 可以返回降级页面
③ 负载均衡(反向代理的进阶版):把一个请求按规则分发到多台后端服务器,规则如:轮询、权重(灰度发布)、固定IP(会话保持)、优先连接数最少的、固定URL(缓存友好)
④ TLS 终止(HTTPS 卸载):证书放在 NGINX 这一层,后端只跑 HTTP,不用管证书续期、轮换,一次加解密集中处理,省 CPU
⑤ 缓存:把后端的响应缓存在 NGINX 本地,下次相同请求直接返回
⑥ 限流 / 重写 / 鉴权:相当于在 NGINX 这一层就把恶意流量挡住,不让它们打到后端。
浙公网安备 33010602011771号