3. Namespace深度解析:隔离的艺术
说实话,刚接触Kubernetes那会儿,我对Namespace的理解特别肤浅。就觉得它是个“文件夹”,把资源分门别类放好。直到有一次,我在生产环境里把测试服务的Pod误删了——嗯,就是因为没做Namespace隔离。从那以后,我才真正重视起这个看似简单的概念。
3.1 Namespace到底是什么?
Namespace,说白了就是K8s里的虚拟集群。一个物理集群可以拆成多个虚拟集群,每个虚拟集群之间资源是隔离的。你想想看,这就像一栋大楼里的不同房间——房间之间互不干扰,但都在同一栋楼里。
我个人习惯把Namespace比作“租户”。每个租户有自己的Pod、Service、ConfigMap,但看不到别的租户的东西。这在多团队协作的场景下特别有用。
3.2 查看Namespace
查看Namespace很简单,就一条命令:
# 查看所有Namespace
kubectl get namespaces
# 或者简写
kubectl get ns
输出大概长这样:
NAME STATUS AGE
default Active 30d
kube-node-lease Active 30d
kube-public Active 30d
kube-system Active 30d
看到这四个默认的Namespace了吗?default是你没指定Namespace时默认使用的;kube-system跑的是系统组件;kube-public是公开的;kube-node-lease跟节点心跳有关。我刚开始学的时候,老是把Pod丢到default里,后来发现这样特别乱。
3.3 创建Namespace
创建Namespace有两种方式。先看命令行的:
kubectl create namespace my-namespace
或者用YAML文件:
apiVersion: v1
kind: Namespace
metadata:
name: my-namespace
然后执行:
kubectl apply -f namespace.yaml
我个人更推荐用YAML方式。为什么?因为可以版本化管理。我曾经在一个项目里,所有Namespace都是手敲命令创建的,结果后来想回溯谁在什么时候创建了什么,完全查不到。用YAML文件配合Git,这些问题就迎刃而解了。
3.4 删除Namespace
删除Namespace要特别小心:
kubectl delete namespace my-namespace
所以我的建议是:
- 删除前先确认里面有什么资源:
kubectl get all -n my-namespace - 考虑先用
kubectl delete加上--grace-period=0强制删除?不,别这么干。先正常删,等5分钟,不行再考虑强制。 - 实在不行了,可以编辑Namespace的finalizers:
kubectl edit namespace my-namespace,把finalizers清空。
3.5 资源配额(ResourceQuota)
有了Namespace,资源怎么分配?这就是ResourceQuota出场的时候了。
ResourceQuota说白了就是给Namespace“画个圈”。比如,你给某个团队分配了10个CPU、20G内存,他们最多只能用这么多,用完了就得等。
来看个例子:
apiVersion: v1
kind: ResourceQuota
metadata:
name: my-quota
namespace: my-namespace
spec:
hard:
requests.cpu: "4"
requests.memory: "8Gi"
limits.cpu: "8"
limits.memory: "16Gi"
pods: "10"
services: "5"
persistentvolumeclaims: "3"
这里我设置了:
- 最多请求4个CPU、8G内存
- 最多限制8个CPU、16G内存
- 最多10个Pod、5个Service、3个PVC
我记得有一次,一个团队疯狂创建Pod,把集群资源全吃光了。后来加了ResourceQuota,他们想创建也创建不了,报错信息也很明确:exceeded quota。嗯,这就是规矩。
requests和limits要区分清楚。requests是“保证能拿到的”,limits是“最多能用到的”。我一般建议requests设小一点,limits设大一点,这样资源利用率更高。
3.6 限制范围(LimitRange)
ResourceQuota管的是Namespace的总量,那单个Pod或容器的资源限制谁来管?LimitRange。
LimitRange的作用是给Pod或容器设置默认的资源请求和限制。比如,你希望每个容器默认请求0.1个CPU、256M内存,限制0.5个CPU、512M内存,就可以用LimitRange。
看个例子:
apiVersion: v1
kind: LimitRange
metadata:
name: my-limits
namespace: my-namespace
spec:
limits:
- max:
cpu: "2"
memory: "4Gi"
min:
cpu: "0.1"
memory: "128Mi"
default:
cpu: "0.5"
memory: "512Mi"
defaultRequest:
cpu: "0.2"
memory: "256Mi"
type: Container
这里我设置了:
- 每个容器最多2个CPU、4G内存
- 每个容器最少0.1个CPU、128M内存
- 默认限制0.5个CPU、512M内存
- 默认请求0.2个CPU、256M内存
你想想看,如果没有LimitRange,开发人员可能随手写个resources: {},结果Pod跑起来后资源不受控。有了LimitRange,就算YAML里没写资源限制,系统也会自动加上默认值。
- ResourceQuota:管的是Namespace的总量上限
- LimitRange:管的是单个Pod/容器的资源范围
3.7 知识体系图
下面这张图展示了Namespace、ResourceQuota、LimitRange之间的关系:
3.8 实战建议
最后,分享几个我在项目中积累的经验:
- 命名规范要统一:我习惯用
项目名-环境的格式,比如vllm-prod、vllm-staging。别用拼音,也别用乱七八糟的缩写。 - ResourceQuota和LimitRange要一起配:光配ResourceQuota,单个Pod可能把配额全占了;光配LimitRange,总量可能失控。两者配合才是王道。
- 定期检查资源使用情况:用
kubectl describe resourcequota -n my-namespace可以查看当前使用量。我一般每周看一次,发现某个Namespace快满了就提前扩容。 - 别滥用Namespace:不是所有东西都要分Namespace。我见过有人每个微服务一个Namespace,结果管理成本比收益还高。一般来说,按团队或环境分就够了。
metadata.labels,后来想用Label Selector筛选Namespace,发现根本筛不了。所以,创建Namespace时就加上标签,比如env: prod、team: ai,方便后续管理。
好了,Namespace这块的内容就这些。记住一句话:Namespace是K8s资源隔离的基石,ResourceQuota和LimitRange是资源管控的左膀右臂。用好它们,你的集群管理会轻松很多。
公众号:蓝海资料掘金营,微信deep3321