如何覆盖命名空间的覆盖?

18
在以下场景中,我已经在“../base/”中定义了我的容器。
在此/dev/目录中,我希望在dev命名空间中启动所有部署和有状态集。难点在于我还想在local-path-storage命名空间中运行local-path-storage CSI。kustomize将覆盖它并在“dev”命名空间中创建它。
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: dev
bases:
  - ../base    
resources:
  - local-path-storage.yaml

我如何仅撤消local-path-storage.yaml的命名空间覆盖?

4个回答

13
自kustomize 4.5.6版本以来,通过添加namespaceTransformer可以实现。您需要将字段unsetOnly设置为true
以下是一个示例:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
 - ../base    
resources:
 - local-path-storage.yaml
transformers:
  - |-
    apiVersion: builtin
    kind: NamespaceTransformer
    metadata:
      name: notImportantHere
      namespace: dev
    unsetOnly: true

如果所有资源都未设置命名空间,这应将命名空间设置为dev。

命名空间转换器规范链接:https://kubectl.docs.kubernetes.io/references/kustomize/builtins/#_namespacetransformer_


12

目前Kustomize还没有这种功能。有一个未解决的问题在处理这个问题,但在撰写本文时,没有公开的PR。

在这里最快的解决方案是在dev / kustomize.yaml中删除namespace设置,并手动设置dev中所有资源的命名空间。

另一个选择是从我之前引用的问题中无耻地复制一个转换器来解决此问题:

#!/usr/bin/env /usr/bin/python3

import sys
import yaml

with open(sys.argv[1], "r") as stream:
    try:
        data = yaml.safe_load(stream)
    except yaml.YAMLError as exc:
        print("Error parsing NamespaceTransformer input", file=sys.stderr)

# See kubectl api-resources --namespaced=false
denylist = [
    "ComponentStatus",
    "Namespace",
    "Node",
    "PersistentVolume",
    "MutatingWebhookConfiguration",
    "ValidatingWebhookConfiguration",
    "CustomResourceDefinition",
    "APIService",
    "MeshPolicy",
    "TokenReview",
    "SelfSubjectAccessReview",
    "SelfSubjectRulesReview",
    "SubjectAccessReview",
    "CertificateSigningRequest",
    "ClusterIssuer",
    "BGPConfiguration",
    "ClusterInformation",
    "FelixConfiguration",
    "GlobalBGPConfig",
    "GlobalFelixConfig",
    "GlobalNetworkPolicy",
    "GlobalNetworkSet",
    "HostEndpoint",
    "IPPool",
    "PodSecurityPolicy",
    "NodeMetrics",
    "PodSecurityPolicy",
    "ClusterRoleBinding",
    "ClusterRole",
    "ClusterRbacConfig",
    "PriorityClass",
    "StorageClass",
    "VolumeAttachment",
]

try:
    for yaml_input in yaml.safe_load_all(sys.stdin):
        if yaml_input['kind'] not in denylist:
            if "namespace" not in yaml_input["metadata"]:
                yaml_input["metadata"]["namespace"] = data["namespace"]
        print("---")
        print(yaml.dump(yaml_input, default_flow_style=False))
except yaml.YAMLError as exc:
    print("Error parsing YAML input\n\n%s\n\n" % input, file=sys.stderr)

这确实是长期解决方案。 - Dan Garthwaite

9
很遗憾,这是不可能的。在Kustomization中,命名空间重写假定所有资源都应该属于同一个命名空间。
你可以考虑以下替代方案:
  • 为不属于同一命名空间的资源创建单独的Kustomization。
  • 通过使用“kubectl apply -f .”部署不需要定制的资源。
  • 使用像Eric Staples建议的替代替换方法。
通常,我会针对每组在命名空间中一起部署的资源创建一个Kustomization,以使Kustomization简单并独立于任何其他资源。

1
我很矛盾。两个回答都解决了我的问题,但我选择实现其中一个并将另一个标记为“解决方案”。这是战术与策略的区别吧。谢谢Diego。 - Dan Garthwaite
这是我作为KISS的粉丝倾向于做的事情,我确信Python可以工作,但一眼看上去并不易读。我将创建一个专用的kustomization.yaml文件来存放属于其他命名空间的随机内容,并仅引用resources: [object1.yaml, object2.yaml],然后在object1.yaml中写入namespace1,在object2.yaml中写入namespace2。 - neokyle

2

我面临着同样的问题。
我的解决方法是将它分成多个步骤。

我会创建stepone、steptwo文件夹。

tree ./project/
./project/
├── stepone
│   ├── base
│   └── overlay
└── steptwo
    ├── base
    └── overlay

现在我可以将不应该有命名空间覆盖的部署移动到第二步,或者反过来。这取决于您的部署需求。我正在处理复杂的转换,从一个包含超过200个文件的heml模板中输出模板。我只是将部署分成不同的步骤,并在每个步骤中使用kustomize来管理需要隔离的部分。虽然这增加了一些工作量,但它仍然提供了我需要的隔离,直到kustomize找到处理命名空间覆盖复杂性的好方法。这需要@Diego-mendes的答案,并将不同的部分封装到它们自己的文件夹中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接