4. Kubernetes核心概念:Pod、Service、Deployment、StatefulSet、ConfigMap、Secret、Namespace、RBAC权限控制
好,咱们进入Kubernetes的核心概念部分。说实话,K8s刚出来那会儿,我第一反应是「这玩意儿也太复杂了」。但用久了你会发现,它的设计其实很优雅——每个概念都解决一个具体问题。今天我就把这些核心概念掰开揉碎了讲给你听。
4.1 Pod:最小的调度单元
Pod是Kubernetes里最小的部署单元。你可以把它理解成「一组容器的集合」。为什么要有Pod?因为有些容器需要共享网络和存储,比如一个日志收集容器和一个业务容器,它们得待在一起。
核心要点:Pod内的容器共享同一个网络命名空间和存储卷。它们可以通过localhost互相访问。
我在项目中遇到过一个问题:两个容器需要共享一个临时目录来交换数据。如果不用Pod,你得自己配置网络和卷挂载,麻烦得很。用Pod就简单了——直接声明一个共享卷就行。
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: app
image: nginx
ports:
- containerPort: 80
- name: sidecar
image: busybox
command: ["sh", "-c", "tail -f /var/log/nginx/access.log"]
个人习惯:我一般不会直接创建Pod,而是通过Deployment或StatefulSet来管理。直接操作Pod就像手动部署应用——出了问题很难回滚。
4.2 Service:稳定的网络入口
Pod是动态的,随时可能被销毁重建。那问题来了——客户端怎么找到它?这就是Service的作用。
Service为一组Pod提供稳定的网络入口。它通过标签选择器(Label Selector)来匹配Pod。说白了,你给Pod打上标签,Service就自动发现它们。
| Service类型 | 适用场景 | 访问方式 |
|---|---|---|
| ClusterIP | 集群内部访问 | 虚拟IP + 端口 |
| NodePort | 外部访问(开发测试) | 节点IP + 固定端口 |
| LoadBalancer | 云环境外部访问 | 云负载均衡器 |
嗯,这里要注意:ClusterIP是默认类型,只能在集群内部用。如果你想让外部访问,得用NodePort或LoadBalancer。我曾经在生产环境里直接用NodePort暴露服务,结果端口冲突了——教训就是,生产环境还是用LoadBalancer或者Ingress吧。
4.3 Deployment:无状态应用的理想选择
Deployment是我用得最多的控制器。它管理Pod的声明式更新和回滚。你只需要告诉它「我要3个副本,镜像版本是v2」,剩下的它自己搞定。
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时忘了设置maxSurge和maxUnavailable,结果滚动更新期间服务中断了。建议生产环境至少保留一个Pod可用。
Deployment适合无状态应用——比如Web服务、API网关。为什么?因为它的Pod是无状态的,挂了就重建,数据丢了也不怕。
4.4 StatefulSet:有状态应用的救星
那有状态应用怎么办?比如数据库、消息队列。StatefulSet就是为这个设计的。
StatefulSet和Deployment最大的区别是:它给每个Pod一个稳定的网络标识和持久化存储。Pod的名字是有序的(比如db-0、db-1、db-2),重启后名字不变。
关键特性:StatefulSet的Pod是有序部署、有序缩容的。比如你要部署3个副本,它会先启动db-0,等它Ready了再启动db-1。
我记得有一次帮客户迁移数据库到K8s,他们一开始用Deployment部署MySQL,结果Pod重启后数据全丢了。后来换成StatefulSet,配合PersistentVolumeClaim,问题就解决了。
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: mysql
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
volumeMounts:
- name: data
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
4.5 ConfigMap与Secret:配置管理
应用配置怎么管理?硬编码在镜像里?那每次改配置都得重新构建镜像,太傻了。ConfigMap和Secret就是用来解耦配置和镜像的。
ConfigMap存明文配置,比如数据库地址、日志级别。Secret存敏感信息,比如密码、API密钥。Secret的数据是Base64编码的,但注意——这只是编码,不是加密。真要安全,得用外部密钥管理工具。
我的做法:ConfigMap用字面量创建,方便调试。Secret用文件创建,避免在命令行里暴露密码。
# 创建ConfigMap
kubectl create configmap app-config --from-literal=DB_HOST=localhost
# 创建Secret
kubectl create secret generic db-secret --from-file=./password.txt
你想想看,如果不用ConfigMap,每次改配置都得改YAML、重新部署。有了它,改个配置就一行命令的事。
4.6 Namespace:逻辑隔离
Namespace是Kubernetes里的虚拟集群。一个物理集群可以划分成多个Namespace,每个Namespace里的资源是隔离的。
我习惯按环境划分Namespace:dev、test、prod。这样开发人员只能在dev里折腾,不会影响到生产环境。
| 场景 | 推荐Namespace | 说明 |
|---|---|---|
| 多环境 | dev、test、prod | 环境隔离,权限控制 |
| 多团队 | team-a、team-b | 资源配额,互不干扰 |
| 系统组件 | kube-system | K8s核心组件专用 |
注意:Namespace不是完全隔离的。比如Pod可以通过Service跨Namespace访问。要实现真正的网络隔离,得用NetworkPolicy。
4.7 RBAC权限控制
最后说说RBAC——基于角色的访问控制。说白了,就是谁可以干什么。
RBAC有四个核心概念:
- User/ServiceAccount:谁在操作
- Role/ClusterRole:能做什么(权限集合)
- RoleBinding/ClusterRoleBinding:把角色绑定到用户
举个例子:给开发人员只读权限。
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: dev
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: dev
subjects:
- kind: User
name: dev-user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
我曾经犯过一个错:给一个ServiceAccount绑定了ClusterRole,结果它能在所有Namespace里删Pod。还好是在测试环境发现的。所以记住:权限最小化原则,给多少权限就够用多少。
总结一下:Pod是基础单元,Service提供稳定入口,Deployment管无状态应用,StatefulSet管有状态应用,ConfigMap和Secret管配置,Namespace做隔离,RBAC管权限。这些概念串起来,就是K8s的核心骨架。
嗯,今天就讲到这里。下一章咱们聊聊Kubernetes的网络模型和存储方案,那才是真正让人头疼的地方。