4、Kubernetes入门:K8s架构与核心组件、Pod与Deployment、Service与Ingress
好,咱们进入Kubernetes的世界。说实话,K8s是云原生流水线的核心底座。没有它,你那些容器化的应用就像散落一地的乐高积木,拼不成城堡。
我个人习惯把K8s看作一个「数据中心操作系统」。它管理的不再是单个进程,而是整个集群的资源。你告诉它「我要跑3个Nginx实例」,它自己会去找三台机器部署好,挂了还会自动重启。是不是很省心?
4.1 K8s架构:Master与Node的分工
K8s集群分两拨人:Master节点(控制面)和Worker节点(数据面)。
Master节点负责决策和调度。它里面有几个关键组件:
- API Server:整个集群的入口。你所有操作(kubectl命令)都走它。它就像公司的前台,谁来了都得先登记。
- etcd:集群的数据库。存着所有状态信息。这玩意儿挂了,集群就失忆了。我在生产环境遇到过etcd磁盘写满导致集群瘫痪的事故,嗯,从那以后我给它配了独立的SSD和定期快照。
- Scheduler:调度器。决定一个新Pod该放到哪个Worker节点上。它会看节点资源够不够、有没有污点等。
- Controller Manager:控制器大脑。确保集群的实际状态符合你的期望状态。比如你声明要3个Pod,它发现只有2个,就会立刻创建第3个。
Worker节点是真正跑应用的地方。每个节点上都有:
- Kubelet:节点上的「监工」。负责跟Master通信,管理Pod的生命周期。它要是罢工了,这个节点就失联了。
- Kube-proxy:网络代理。负责实现Service的网络规则,让Pod之间能互相通信。
- 容器运行时:比如Docker、containerd。真正拉镜像、跑容器的底层工具。
一句话总结:Master负责想(调度决策),Worker负责干(跑容器)。
4.2 Pod:最小的调度单元
Pod是K8s里你能创建和部署的最小单元。它里面可以有一个或多个容器。这些容器共享网络栈和存储卷。
你可能会问:为什么不用容器直接作为最小单元?
我举个例子。假设你有个日志采集器(Filebeat),它需要跟你的业务容器跑在一起,共享日志目录。如果它们是两个独立的容器,调度时可能被分到不同机器上。但放在同一个Pod里,K8s保证它们永远在一起。
Pod的生命周期是短暂的。它可能因为节点故障、资源不足、更新版本等原因被销毁重建。所以,永远不要直接创建Pod,而是通过控制器来管理。
# 一个简单的Pod定义
apiVersion: v1
kind: Pod
metadata:
name: my-nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80
避坑指南:我曾经在生产环境直接删了一个Pod,以为它会自动重建。结果发现它没有控制器管理,直接消失了。那是一个没有配置Deployment的测试Pod,导致服务中断了5分钟。从那以后,我要求团队所有Pod必须通过Deployment或StatefulSet创建。
4.3 Deployment:声明式更新与扩缩容
Deployment是K8s里最常用的工作负载控制器。它负责管理一组Pod的副本,并保证它们按你期望的方式运行。
说白了,你告诉Deployment「我要5个Nginx Pod」,它会创建5个。如果某个Pod挂了,它会自动再创建一个。如果你想升级版本,它支持滚动更新,逐个替换Pod,保证服务不中断。
# Deployment示例
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80
Deployment有几个核心能力:
- 滚动更新:逐步替换旧版本Pod,可以控制更新速度和暂停。
- 回滚:如果新版本有问题,一键回滚到上一个版本。
- 扩缩容:修改replicas字段,K8s会自动增加或减少Pod数量。
注意:滚动更新时,如果新Pod启动失败,Deployment会停止更新。我曾经遇到过新镜像拉取失败,导致更新卡住,旧Pod也被删了一半。所以,一定要配置存活探针(livenessProbe)和就绪探针(readinessProbe),让K8s知道你的应用是否真的准备好了。
4.4 Service:稳定的网络入口
Pod是动态的,IP地址会变。那客户端怎么访问你的应用?Service就是来解决这个问题的。
Service为一组Pod提供一个稳定的虚拟IP和DNS名称。客户端只需要访问这个Service,K8s会自动把流量转发到后端的Pod上。
# Service示例
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
Service有几种类型:
| 类型 | 说明 | 使用场景 |
|---|---|---|
| ClusterIP | 集群内部IP,外部无法访问 | 内部服务间调用 |
| NodePort | 在每个节点上开放一个端口 | 开发测试环境 |
| LoadBalancer | 云厂商提供负载均衡器 | 生产环境对外暴露 |
我的经验:NodePort只适合临时调试。生产环境一定要用LoadBalancer或Ingress。我曾经见过有人用NodePort暴露生产服务,结果端口被扫描攻击,差点出事。
4.5 Ingress:七层路由与域名管理
Service的LoadBalancer类型每个服务都要一个公网IP,成本高且管理麻烦。Ingress就是来解决这个问题的。
Ingress工作在七层(HTTP/HTTPS),可以根据域名、路径把请求路由到不同的Service。它就像Nginx的反向代理,但配置是声明式的。
# Ingress示例
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-service
port:
number: 80
要实现Ingress,集群里需要安装Ingress Controller,比如Nginx Ingress Controller、Traefik。它负责读取Ingress规则并配置实际的负载均衡器。
核心要点:
- Pod是临时工,Deployment是项目经理
- Service是内部电话总机,Ingress是前台接待
- 永远不要依赖Pod的IP,用Service或Ingress访问
好了,这一章的内容就到这里。K8s的入门其实不难,关键是理解它的设计思想:声明式、控制器模式、分层抽象。下一章我们会深入实战,用K8s部署一个完整的微服务应用。