基于命名空间注解验证Rancher共享K8s集群的Ingress主机名
解决方案:基于准入控制校验Ingress主机名规则
核心思路
利用Kubernetes的Validating Admission Webhook或声明式政策工具(如Kyverno),在Ingress资源创建/更新时自动完成两项校验:
- 从命名空间的名称或注解中提取所属项目的唯一标识(如
k12345) - 验证Ingress的
spec.rules[*].host是否严格符合something-<项目名>.cl01.k8s.domain.tld格式
不符合规则的请求会直接被拒绝并返回明确提示,同时复用集群统一的*.cl01.k8s.domain.tld通配符证书。
方案一:用Kyverno实现(推荐,无需自定义开发)
Kyverno是Kubernetes原生的声明式政策管理工具,无需编写代码即可实现复杂的资源校验逻辑,适合快速落地。
1. 安装Kyverno
通过官方提供的静态资源清单或Helm完成安装(可参考官方文档指引):
# 示例:用静态清单安装 kubectl create -f <官方安装清单本地路径或离线资源>
2. 定义校验政策
根据你的场景,有两种实现方式(优先选择基于注解的方式,更可靠):
方式A:基于命名空间注解提取项目名(推荐)
假设你已给所有命名空间添加project.name: <项目名>注解,创建如下ClusterPolicy:
apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: validate-ingress-host-format spec: validationFailureAction: Enforce background: false rules: - name: check-ingress-host match: any: - resources: kinds: - Ingress preconditions: all: - key: "{{request.object.metadata.annotations.project.name || ''}}" operator: NotEquals value: "" validate: message: "Ingress主机名必须符合格式: something-<项目名>.cl01.k8s.domain.tld" pattern: spec: rules: - host: "*{{request.object.metadata.annotations.project.name}}.cl01.k8s.domain.tld"
方式B:从命名空间名称提取项目名
如果依赖命名空间前缀(如k12345-default)提取项目名,使用正则匹配规则:
apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: validate-ingress-host-format spec: validationFailureAction: Enforce background: false rules: - name: check-ingress-host match: any: - resources: kinds: - Ingress preconditions: all: - key: "{{request.object.metadata.namespace}}" operator: MatchesRegex value: "^[a-z0-9]+-.+" validate: message: "Ingress主机名必须符合格式: something-<项目名>.cl01.k8s.domain.tld" pattern: spec: rules: - host: "*{{ regex_match('^([a-z0-9]+)-.+', request.object.metadata.namespace)[0] }}.cl01.k8s.domain.tld"
3. 验证政策生效
创建一个不符合规则的Ingress测试:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: test-invalid-ingress namespace: k12345-default spec: rules: - host: wrong-name.cl01.k8s.domain.tld http: paths: - path: / pathType: Prefix backend: service: name: test-service port: number: 80
执行创建命令会被拒绝,返回明确的格式错误提示。
方案二:自定义Validating Admission Webhook(适合高度定制场景)
如果需要更复杂的校验逻辑(如结合外部数据源),可以自行开发Webhook服务:
1. 核心校验逻辑示例(Python)
import re from admission_controller import AdmissionResponse def validate_ingress_host(request): # 从命名空间注解或名称提取项目名 namespace = request.object.metadata.namespace # 方式1:从注解提取 project_name = request.object.metadata.annotations.get("project.name") # 方式2:从命名空间前缀提取 if not project_name: project_name = namespace.split('-')[0] # 校验每个host格式 for rule in request.object.spec.rules: host = rule.host if not re.match(r'^[a-z0-9-]+-{}\.cl01\.k8s\.domain\.tld$'.format(project_name), host): return AdmissionResponse( allowed=False, message=f"Host {host}不符合要求,必须为something-{project_name}.cl01.k8s.domain.tld" ) return AdmissionResponse(allowed=True, message="")
2. 部署Webhook服务
将代码打包成镜像,部署到集群中并暴露Service,然后配置ValidatingWebhookConfiguration指向该服务:
apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: name: ingress-host-validator webhooks: - name: ingress-host-validator.yourdomain.com rules: - apiGroups: ["networking.k8s.io"] apiVersions: ["v1"] operations: ["CREATE", "UPDATE"] resources: ["ingresses"] scope: "Namespaced" clientConfig: service: namespace: <webhook部署命名空间> name: <webhook服务名> path: /validate-ingress-host caBundle: <Base64编码的CA证书> admissionReviewVersions: ["v1"] sideEffects: None timeoutSeconds: 5
额外优化:结合Rancher项目模板
由于你的命名空间由自助工具统一创建,可以在Rancher项目模板中预设:
- 自动给命名空间添加
project.name: <项目名>注解 - 自动绑定Kyverno校验政策
减少人工配置,确保规则统一落地。
内容的提问来源于stack exchange,提问作者Markus Radtke
相关产品推荐
相关产品推荐

