17

In the following scenario I have my containers defined in ../base/.

In this /dev/ directory I want to start all the deployments and statefulsets in namespace dev.

The rub is that I also want to run the local-path-storage CSI in the local-path-storage namespace. kustomize will override it and create it in the "dev" namespace.

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: dev
bases:
  - ../base    
resources:
  - local-path-storage.yaml

How can I undo the namespace override for just local-path-storage.yaml?

Dan Garthwaite
  • 3,436
  • 4
  • 22
  • 32

4 Answers4

12

This functionality doesn't exist in Kustomize yet. There's an open issue addressing this, but no open PRs at the time of this writing.

The quickest solution here is to remove the namespace setting in the dev/kustomize.yaml and hand-set the namespace in all resources in dev.

Another option, shamelessly copied from the issue I cited earlier, is to create a transformer to get around this:

#!/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)
Bruce
  • 464
  • 5
  • 9
erstaples
  • 1,986
  • 16
  • 31
12

It is possible since kustomize 4.5.6 by adding a namespaceTransformer. You want to set the field unsetOnly to true.

Here is an example:

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

This should set the namespace to dev for all resources that DO NOT have a namespace set.

Link to namespaceTransformer spec: https://kubectl.docs.kubernetes.io/references/kustomize/builtins/#_namespacetransformer_

andreasmh
  • 136
  • 1
  • 3
9

Unfortunately it is not possible, the namespace override in kustomization assume all resources should belong to the same namespace.

Your alternative are:

  • Create separate kustomization for resources that does not belong to the same namespace.
  • Deploy resources that does not need kustomization by using kubectl apply -f .
  • Use alternative replacement approach like suggested by Eric staples.

I generally create one kustomization per set of resources, that are deployed together in a namespace to make the kustomization simple and independent from any other resources.

Diego Mendes
  • 10,631
  • 2
  • 32
  • 36
  • 1
    I'm torn. Both answered my question and I chose to implement this solution yet mark the other as THE solution. Tactics vs. Strategy I guess. Thanks Diego. – Dan Garthwaite Oct 01 '19 at 12:47
  • This is what I tend to do as I'm a fan of KISS, I'm sure that python works, but it's not readable at a glance. I'll create a dedicated kustomization.yaml file for random stuff that belongs in other namespaces, and only make resources: [object1.yaml, object2.yaml] references and then write namespace1 in object1.yaml and namespace2 in object2.yaml – neoakris Jan 26 '21 at 01:37
2

I am faced with the same problem.
My approach to this problem is to break it up into multiple steps.

I would have stepone, steptwo folders.

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

Now I can move the part of the deployment that should not have the namespace override into steptwo or vice versa. Depending on your deployment needs. I am working on complex transitions from a heml template with over 200 files outputted from the templates.

I am simply breaking up the deployment into different steps and use kustomize at each step to manage just the portion of the deployment where isolation is required.

It does add some effort, but it still gives the isolation I need till kustomize finds a good way to handle this complexity of the namespace overide. This takes @Diego-mendes answer and encapsulates the different parts into their own folders.

nelaaro
  • 3,006
  • 5
  • 38
  • 56