4. Kubernetes核心概念
在完成Kubernetes集群的部署与基础验证之后,真正进入日常运维与业务交付时,我们面对的核心对象不再是物理节点或虚拟机,而是Kubernetes抽象出的各类资源对象(Resource Objects)。这些资源对象共同构成了声明式应用管理的基石。本章将深入剖析Pod、Deployment、Service、Ingress、ConfigMap与Secret这六大核心资源,从原理、操作到实战排障,帮助学员建立从“能用”到“会用”的认知跨越。理解这些资源之间的关系,是掌握Kubernetes调度、网络、存储与配置管理的关键前提。
上图清晰地展示了用户请求从外部进入集群后的完整路径,以及Deployment、ConfigMap、Secret与Pod之间的管理或注入关系。在后续的实战中,我们将围绕这张图逐一展开每个资源的细节。
4.1 Pod:最小调度单元与容器共享模型
核心原理
Pod是Kubernetes中可创建和部署的最小单元,也是调度、网络、存储的最小边界。一个Pod可以包含一个或多个容器,这些容器共享同一个网络命名空间(即共享IP和端口空间)、同一个UTS命名空间(主机名)以及可选的共享存储卷。这种设计使得Pod内的容器可以通过localhost直接通信,非常适合“主容器+辅助容器(Sidecar)”的协作模式,例如日志收集、流量代理、健康检查等。
Pod的生命周期是短暂的,它不会自愈。当Pod因节点故障、资源不足或应用崩溃而被删除时,Kubernetes不会直接重建同一个Pod,而是通过上层控制器(如Deployment)创建新的Pod来替代。因此,在生产环境中,我们几乎从不直接创建裸Pod,而是通过控制器管理。
判断方法与操作流程
判断一个Pod是否健康,通常需要结合存活探针(LivenessProbe)和就绪探针(ReadinessProbe)。存活探针决定何时重启容器,就绪探针决定何时将Pod加入Service的负载均衡池。创建Pod的常用命令如下:
# 直接创建Pod(不推荐生产使用)
kubectl run nginx-pod --image=nginx:1.25
# 查看Pod详情,重点关注Events字段
kubectl describe pod nginx-pod
# 查看Pod日志(多容器时需指定-c容器名)
kubectl logs nginx-pod -c main-container
案例拆解:多容器Pod的日志采集
假设我们有一个Java应用需要采集日志。传统方式是在虚拟机中安装Agent,但在Kubernetes中,我们采用Sidecar模式。在同一个Pod中,主容器运行Java应用,Sidecar容器运行Filebeat。两个容器共享一个emptyDir卷,Java应用将日志写入该卷,Filebeat读取并转发至Elasticsearch。这种模式的优点在于:日志采集逻辑与应用解耦,且随着Pod的扩缩容,日志采集能力自动伸缩。
restartPolicy默认为Always,适用于Deployment管理的Pod。但对于执行一次性任务的Job,应设置为OnFailure或Never,避免任务完成后容器反复重启。
常见误区与复盘
- 误区1:认为Pod内的多个容器可以分别暴露不同端口给外部访问。实际上,Pod只有一个IP,端口共享,外部访问必须通过Service。
- 误区2:忽略Pod的资源请求(requests)与限制(limits)。不设置资源限制可能导致节点资源被单个Pod耗尽,引发雪崩。
- 复盘:在排查Pod一直处于
Pending状态时,应优先检查kubectl describe pod中的调度事件,常见原因包括节点资源不足、节点亲和性不满足或存在污点。
4.2 Deployment:声明式应用管理控制器
核心原理
Deployment是Kubernetes中最常用的无状态应用控制器,它负责管理Pod的副本数、滚动更新、回滚以及故障自愈。Deployment通过ReplicaSet来间接管理Pod。每次更新Deployment的Pod模板时,Deployment会创建一个新的ReplicaSet,并逐步增加新ReplicaSet的副本数,同时减少旧ReplicaSet的副本数,从而实现平滑升级。
操作流程与策略
Deployment支持两种更新策略:RollingUpdate(默认)和Recreate。滚动更新允许我们控制maxSurge(最大峰值副本数)和maxUnavailable(最大不可用副本数)。例如,设置maxSurge: 25%和maxUnavailable: 25%,意味着在更新过程中,Pod总数最多比期望副本数多25%,且至少有75%的副本保持可用。
# 创建Deployment
kubectl create deployment web-app --image=nginx:1.25 --replicas=3
# 滚动更新镜像版本
kubectl set image deployment/web-app nginx=nginx:1.26
# 查看滚动更新状态
kubectl rollout status deployment/web-app
# 如果更新失败,回滚到上一个版本
kubectl rollout undo deployment/web-app
案例拆解:一次失败的滚动更新
某团队将web-app的镜像从v1.0升级到v2.0。升级后,新版本的Pod启动时因依赖的数据库配置错误而崩溃。由于设置了就绪探针,新Pod一直处于未就绪状态。此时,maxUnavailable为25%,意味着有1个旧Pod被终止,但新Pod未就绪,导致服务容量下降。监控系统告警后,运维人员执行kubectl rollout undo deployment/web-app,集群立即将ReplicaSet回滚至v1.0,服务恢复。复盘发现,问题根源在于CI流水线未在测试环境验证v2.0的配置兼容性。
kubectl edit deployment修改镜像版本,应通过kubectl set image或修改YAML文件并kubectl apply,确保变更可审计、可回滚。
常见误区与总结
- 误区:将Deployment用于有状态应用(如数据库)。Deployment无法保证Pod的稳定标识和持久化存储,应使用StatefulSet。
- 总结:Deployment是“无状态服务”的标配,掌握其滚动更新机制是保障发布安全的核心技能。
4.3 Service:稳定的访问入口与负载均衡
核心原理
由于Pod的IP是动态变化的,我们需要Service为一组Pod提供稳定的虚拟IP(ClusterIP)和DNS名称。Service通过Label Selector选择后端Pod,并自动维护Endpoints列表。当Pod发生扩缩容或重建时,Service无需修改,客户端始终通过固定的ClusterIP或域名访问。
Service的四种类型中,ClusterIP是默认类型,仅在集群内部可访问;NodePort在ClusterIP基础上,在每个节点上开放一个静态端口(30000-32767),供外部访问;LoadBalancer通常由云提供商实现,创建外部负载均衡器;ExternalName用于将服务映射到集群外部的DNS名称。
操作流程与排查
# 创建Service,暴露Deployment的80端口
kubectl expose deployment web-app --port=80 --target-port=8080 --type=ClusterIP
# 查看Service的Endpoints
kubectl get endpoints web-app
# 临时端口转发,用于本地调试
kubectl port-forward service/web-app 8080:80
当访问Service不通时,排查路径应为:Service → Endpoints → Pod IP → 容器端口。最常见的问题是Label Selector不匹配,导致Endpoints为空。
案例拆解:NodePort端口冲突
某集群中,运维人员手动创建了一个NodePort Service,指定nodePort: 30080。但随后另一个团队部署应用时,也尝试使用30080端口,导致创建失败。Kubernetes默认的NodePort端口范围是30000-32767,且不允许冲突。解决方案是:除非有特殊合规要求,否则不显式指定nodePort,让集群自动分配。
targetPort是容器实际监听的端口,而port是Service暴露的端口。两者可以不同,这为应用迁移提供了灵活性。
4.4 Ingress:七层路由与统一入口
核心原理
Ingress是Kubernetes的API对象,用于管理集群外部访问集群内服务的HTTP/HTTPS路由。与Service的4层负载均衡不同,Ingress工作在7层,可以根据域名、URL路径将请求转发到不同的Service。Ingress本身不提供流量转发能力,它需要配合Ingress Controller(如Nginx Ingress Controller、Traefik)才能生效。Ingress Controller是一个运行在集群中的负载均衡器,它监听Ingress资源的变化并动态更新其配置。
配置示例与判断方法
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
spec:
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
判断Ingress是否生效,可以执行kubectl get ingress查看ADDRESS字段是否已分配,以及kubectl logs -n ingress-nginx查看Controller日志。
案例拆解:灰度发布中的Ingress应用
某电商平台需要将新版本推荐服务灰度上线。团队创建了两个Deployment:recommend-v1和recommend-v2,分别对应两个Service。通过Ingress的nginx.ingress.kubernetes.io/canary注解,将5%的流量转发至v2版本。观察监控指标无异常后,逐步将权重调整至100%,最终完成全量发布。这种基于Ingress的灰度策略无需修改应用代码,且回滚迅速。
tls字段中引用。证书过期是Ingress HTTPS访问失败的常见原因。
4.5 ConfigMap与Secret:配置与敏感信息管理
核心原理
ConfigMap用于存储非敏感的配置信息,如环境变量、配置文件内容。Secret用于存储敏感信息,如密码、、TLS证书。Secret的存储格式为Base64编码,但这只是编码,并非加密。在Kubernetes 1.24及以上版本,Secret支持可选的静态加密(Encryption at Rest)。
两者都可以通过环境变量或挂载卷的方式注入Pod。挂载卷方式支持热更新(ConfigMap更新后,Pod内的文件内容会同步更新,但环境变量方式不会)。
操作流程与安全实践
# 从字面值创建ConfigMap
kubectl create configmap app-config --from-literal=LOG_LEVEL=info
# 从文件创建Secret
kubectl create secret generic db-secret --from-file=./password.txt
# 在Pod中通过卷挂载Secret
# volumes:
# - name: secret-volume
# secret:
# secretName: db-secret
案例拆解:配置热更新与不可变ConfigMap
一个Java应用从/etc/config/application.yml读取配置。运维人员更新了ConfigMap中的数据,但应用并未感知。排查发现,应用只在启动时读取一次配置文件。解决方案有两种:一是应用支持监听文件变化并重载;二是使用sha256sum注解,在ConfigMap内容变化时触发Deployment滚动更新。此外,对于生产环境,建议将ConfigMap设置为immutable: true,防止误修改。
常见误区与总结
- 误区:认为Secret是安全的。实际上,任何有权访问集群的人都可以通过
kubectl get secret -o yaml解码查看。 - 总结:ConfigMap与Secret是应用配置与代码分离的最佳实践,也是实现12-Factor应用的关键。
| 资源对象 | 作用层级 | 核心作用 | 是否自愈 | 典型使用场景 |
|---|---|---|---|---|
| Pod | 计算 | 最小调度与运行单元 | 否 | 单实例容器组、Sidecar模式 |
| Deployment | 工作负载 | 管理无状态Pod的副本与更新 | 是 | Web服务、API服务、Worker |
| Service | 网络 | 提供稳定的虚拟IP与负载均衡 | - | 集群内部服务发现与访问 |
| Ingress | 网络 | 七层HTTP/HTTPS路由 | - | 域名访问、URL路径转发、TLS终止 |
| ConfigMap | 配置 | 存储非敏感配置 | - | 环境变量、配置文件注入 |
| Secret | 配置 | 存储敏感信息(Base64) | - | 数据库密码、TLS证书、 |
通过本章的详解,我们应当明确:Pod是基础,Deployment是保障,Service是桥梁,Ingress是门户,ConfigMap与Secret是养分。在实际部署中,这六大资源往往协同工作。掌握它们之间的依赖关系与排查思路,是进行后续集群运维、监控告警与故障恢复的必备能力。在下一阶段的实战中,我们将基于这些核心概念,构建一个完整的微服务应用,并模拟多种故障场景进行演练。