如何在K8s中无需create权限触发已存在的Job和CronJob?
解决方案:触发已有Job/CronJob同时避免安全风险
能不能不给create权限就触发已有Job/CronJob?
答案是不行。原因很直接:
- 手动触发CronJob运行,本质是基于它的模板新建一个Job实例,这个操作必须要有
jobs资源的create权限; - 要重新运行已经完成的Job,同样得创建新的Job副本,也离不开
jobs的create权限。
只给get/list这类只读权限,根本没法完成触发动作。
能不能只允许基于已有Job/CronJob执行create?
单纯靠RBAC做不到。RBAC的create权限是针对“新建资源”的,没法直接限定你只能基于已有资源的模板来创建Job。你之前的配置给了cronjobs和jobs的create权限,等于放开了创建任意镜像Job/CronJob的口子,确实会让别人能跑危险Pod,风险很大。
安全实现的正确姿势:RBAC+准入控制
要实现“允许触发已有Job/CronJob,但禁止瞎建任意镜像的Job”,得把RBAC和准入控制结合起来用:
第一步:锁死最小权限的RBAC
只给必要的权限,绝对不能给cronjobs的create权限,具体配置如下:
# 允许读取已有Job和CronJob(用来获取模板) apiGroups: - batch resources: - cronjobs - jobs verbs: - get - list - watch --- # 允许创建新Job(用来触发运行) apiGroups: - batch resources: - jobs verbs: - create
第二步:用准入控制限制Job的镜像
光靠RBAC还不够,得用准入控制工具(比如Kyverno、OPA Gatekeeper,或者Kubernetes 1.26+的原生ValidatingAdmissionPolicy)来卡Job的镜像来源:
- 要么只允许用指定仓库/名称的镜像;
- 要么强制Job的Pod模板必须和集群里已有的Job/CronJob模板一致(也就是只能基于已有资源生成新Job)。
举个Kyverno的规则例子,强制Job镜像必须是已有Job/CronJob用过的:
apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: restrict-job-to-approved-images spec: validationFailureAction: Enforce rules: - name: job-matches-existing-images match: any: - resources: kinds: - Job validate: message: "你只能创建使用集群中已有Job/CronJob镜像的Job" deny: conditions: all: - key: "{{ request.object.spec.template.spec.containers[0].image }}" operator: NotIn value: "{{ images }}" context: - name: images apiCall: url: "/apis/batch/v1/jobs" jmesPath: "items[].spec.template.spec.containers[0].image[]" - name: images apiCall: url: "/apis/batch/v1/cronjobs" jmesPath: "items[].jobTemplate.spec.template.spec.containers[0].image[]"
额外优化:只允许触发CronJob
如果你的需求只是触发CronJob,还可以再加一条规则,限制创建的Job必须是关联某个合法CronJob的——比如检查Job的元数据注解里有没有kubernetes.io/created-by指向已存在的CronJob,或者直接验证Job模板和目标CronJob的模板完全一致,进一步缩小权限范围。
这样一套组合拳下来,既能满足触发已有Job/CronJob的需求,又能彻底堵上创建任意镜像Pod的漏洞。
内容的提问来源于stack exchange,提问作者greenboi
相关产品推荐
相关产品推荐

