TT Lab
开始
学习 学习路径 课程

KCNA — Kubernetes 与云原生入门

默认值、配额与准入拒绝的账本

在 TT Lab 中继续学习

一句话总结

LimitRange 处理单个对象的默认值和范围,ResourceQuota 处理命名空间的合计。触发配额的请求,不是让 Pod 处于 Pending 等待,而是可能在创建阶段就被拒绝。

为什么需要它

如果一个小团队不小心创建了数千个对象,集群中的其他团队也会受到影响。资源策略不仅限制恶意攻击,也限制一个循环中的笔误所造成的损害。但是,设置了限制这件事本身并不能保证想要的行为。必须实际确认它适用于哪些请求、是否会动到已有对象、用量统计的又是什么。

假设想创建新 Pod 时出现了 Forbidden。如果一概把它看作账号权限问题,就会导致授予更多 RBAC 权限这种错误的应对。即使是同样的 HTTP 状态,响应正文里的原因和相关对象才是关键。配额超限不会因为增加权限而解决。通过删除限制来让它成功,也不是理解了策略的解决方式。

工作原理

这次实验为一个容器设置默认请求 CPU 100m、内存 32Mi,默认限制 CPU 200m、内存 64Mi。并排读取输入中省略了 resources 的新 Pod 和保存在 API 中的 Pod。如果保存的对象里出现了值,它可能不是用户文件里的值,而是 admission 过程中应用的默认值。不要假设已经明确写了 CPU 50m 创建的旧 Pod 被改成了 100m。

ResourceQuota 的 requests.cpu 限制属于该空间的目标 Pod 的 CPU 请求合计。它不是测量当前实际使用了百分之几 CPU 的数字。这个例子中的账簿是这样变化的。

状态 已保存的请求合计 允许上限 新请求的结果
fit 50m + defaulted 100m 150m 200m 再加 extra 100m 就是 250m,因此被拒绝
调整上限之后 150m 300m 同样的 extra 请求进来,合计 250m
再次调低上限 250m 100m 已有 Pod 保持不变,新的 small 请求被拒绝
回收 extra、重新调整上限 150m 200m small 50m 进来,合计 200m

这张表中对上限的修改,是在一次性命名空间中学习策略含义的实验。在生产中,应由审阅过用量、业务需求和团队分配的、有权限的负责人来修改策略。这并不是为了消除报错而建议增加配额。

把配额降到低于当前用量,并不会自动终止已有的 Pod。因此可以观测到 status.used 大于 spec.hard 的状态。这不是策略无效的证据。要确认的是,它是否在保留已有对象的同时拒绝新增创建。如果必须强制降低用量,就要另外做出运维决策,决定终止哪些任务。

ResourceQuota 可能不只限制一条轴。它可以同时检查 requests.cpu、requests.memory、limits.cpu、limits.memory、Pod 数量等,所以不能只算 CPU 就断定成功。这次实验让其余的上限留有余量,以分离出 CPU 请求量的效果。还要区分,是违反了 LimitRange 的单项上限,还是违反了 ResourceQuota 的合计上限。

在现场相遇的样子

把创建 Pod 之前的输入、API 响应和创建之后的查询结果,当作一个证据包来看。对于配额拒绝,要确认真实的 HTTP 403,以及 Kubernetes Status 的 Forbidden 原因、出现 team-budget 和 requests.cpu 的说明。接着确认同名的 Pod 不存在。不要在收到账号权限错误或 TLS 错误的情况下,就记录为想要的策略已生效。

相反,HTTP 201 表示对象创建被接受,并不是应用启动完成。要继续查看新的 Pod UID 是否与响应一致,以及是否已被放置到节点上、处于 Running 和 Ready。调度和 admission 是不同的阶段,所以“这个请求在 quota 之内”和“有运行这个 Pod 的节点”是两回事。

kubectl -n kcna-capacity get limitrange defaults -o json
kubectl -n kcna-capacity get resourcequota team-budget -o json
kubectl -n kcna-capacity get pods -o json

状态账簿在变更之后,可能仍然显示之前的值。删除自己拥有的 extra Pod 之后,要确认对象确实不存在以及 quota 用量已减少,再发送下一个请求。不要只凭固定的短 sleep 就假定已经完成。等待要设置时限,超时后不要用成功来掩盖,而是保留观测结果。

下一项实验要做什么

直接比较在资源看起来还有剩余的情况下也会发生的两种失败。放置失败用真实的 Pod UID 和调度器事件来证明,准入拒绝用 API 状态和对象不存在来证明。在配额缩减之后,确认原有 fit、defaulted、extra 的 UID 和容器保持不变,然后只回收调查过的 extra,并重新接受一个小请求。不要改动其他命名空间中的正常对比组。

官方依据