'How can I create a namespace with kustomize?

I've a simple project that use kustomize like this:

base/
  namespace.yaml
  kustomization.yaml
  service.yaml

With kustomization.yaml is:

resources:
  - namespace.yaml
  - service.yaml
namespace: my_wanted_namespace

And namespace.yaml is:

apiVersion: v1
kind: Namespace
metadata:
  name: default

The problem is that when I do: kustomize build ./base

I've this:

apiVersion: v1
kind: Namespace
metadata:
  name: default

How can I have

apiVersion: v1
kind: Namespace
metadata:
  name: my_wanted_namespace

Thanks.



Solution 1:[1]

If you want to create your namespace with kustomize, your kustomize file should look like this. It has to use the namespace.

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: my-wanted-namespace
resources:
- ./namespace.yml

And your namespace file should be a normal namespace deployment like this:

apiVersion: v1
kind: Namespace
metadata:
  name: my-wanted-namespace

Solution 2:[2]

You can remove the namespace resource from base and only include it in the overlay. E.g:

overlay/kustomization.yaml

namespace: my_wanted_namespace
bases:
- ../base
resources:
- namespace.yaml

overlay/namespace.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: my_wanted_namespace

It is important that the namespace property in the kustomization.yaml file matches the name in the namespace.yaml resource and that base/service.yaml doesn't set the namespace property.


EDIT: original response below

As an alternative to Hadrien's answer, JSON Patch also worked for me:

namespace: my-wanted-namespace
patchesJSON6902:
- target:
    version: v1
    kind: Namespace
    name: base-namespace
  patch: |-
    - op: replace
      path: /metadata/name
      value: my-wanted-namespace

The key of this method is transforming the base Namespace name to match exactly the namespace key in the overlay kustomization.yaml file.

Solution 3:[3]

In order to be able to create a namespace on the fly and use it for the other resources Kustomize will customize, you can use this trick:


namespace=${1:-"my-namespace-meaning"}

rm -rf ./base
mkdir ./base

cat <<EOF > ./base/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: suffix
EOF

cat <<EOF > ./base/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: docker-registry
  labels:
    name: docker-registry
spec:
  ports:
    - port: 5001
      targetPort: 5000
  selector:
    name: docker-registry
  type: ClusterIP
EOF

cat <<EOF > ./base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: docker-registry
spec:
  replicas: 1
  selector:
    matchLabels:
      app: docker-registry
  template:
    metadata:
      labels:
        app: docker-registry
    spec:
      containers:
        - name: docker-registry
          image: registry
          ports:
            - containerPort: 5000
          resources:
            limits:
              memory: 200Mi
              cpu: 300m
            requests:
              memory: 100Mi
              cpu: 100m
EOF

cat <<EOF > ./kustomization.yaml
namePrefix: "${namespace}-"

namespace: "${namespace}-suffix"

resources:
- base/deployment.yaml
- base/namespace.yaml
- base/service.yaml
EOF

kubectl kustomize ./

Running this script will output:

apiVersion: v1
kind: Namespace
metadata:
  name: my-namespace-meaning-suffix
---
apiVersion: v1
kind: Service
metadata:
  labels:
    name: docker-registry
  name: my-namespace-meaning-docker-registry
  namespace: my-namespace-meaning-suffix
spec:
  ports:
  - port: 5001
    targetPort: 5000
  selector:
    name: docker-registry
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-namespace-meaning-docker-registry
  namespace: my-namespace-meaning-suffix
spec:
  replicas: 1
  selector:
    matchLabels:
      app: docker-registry
  template:
    metadata:
      labels:
        app: docker-registry
    spec:
      containers:
      - image: registry
        name: docker-registry
        ports:
        - containerPort: 5000
        resources:
          limits:
            cpu: 300m
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 100Mi

The idea is to first use the namePrefix keyword (doc here) in order to deterministically define the value of the namespace after customization. Then this customized namespace can be used for each other resource thanks to the namespace keyword (doc here).

Solution 4:[4]

Old post, but the above answers are more complicated than needed.

In kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

namespace: my-desired-namespace
resources:
- namespace.yaml

and in namespace.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: intentionally.broken.namespace

Realistically, I have a folder elsewhere with a kustomization and the dummy namespace that I can include as a resource from any of my kustomizations. The kustomization will replace the Namespace name with the namespace transformer, and create it.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 azak
Solution 2
Solution 3
Solution 4 Brian C