How to create Kubernetes Namespace if it does not Exist?

7/28/2020

It's a simple question, but I could not find a definite answer for it. Is it possible to create a namespace only if it doesn't exist. My objective is to create some service accounts without caring if their namespaces exist or not (if not, then they should be created on the fly).
The thing is I'm using CDK to deploy some basics K8S resources (including service accounts). To safely do this, I need to make sure the namespace (given in the service account manifest) already exists. However I'm not able to find any solution.
I tried patch, but it seems to expect the resource to exist already (i.e. it fails with NotFound error).

Two limitations:
a. I can't query to see if the namespace exists or not.
b. I can't use apply since I don't have the exact definition of the namespace.

Is there any way to achieve this?

-- Rad
kubernetes

8 Answers

12/22/2020

i wouldn't go for any other solution except the following code snippet:

kubernetes 1.19 and above (included)

kubectl create namespace <add-namespace-here> --dry-run=client -o yaml | kubectl apply -f -

kubernetes 1.18 and below (included)

kubectl create namespace <add-namespace-here> --dry-run -o yaml | kubectl apply -f -

it creates a namespace in dry-run and outputs it as a yaml. The output will be passed as stdin to kubectl apply -f -

The last hyphen is important while passing kubectl to read from stdin.

Also see the examples in:

kubectl apply --help
-- Manuel
Source: StackOverflow

7/28/2020

Given the limitations I can only think of one way which is to apply a namespace yaml always before you apply the service account yaml. If the namespace exists already it will give you a message that namespace already exists.You can ignore that message and move ahead.

apiVersion: v1
kind: Namespace
metadata:
  name: test

So here we are being declarative and it does not matter what exists and what does not. You just define what the desired state should look like and kubernetes will take care of making sure that happens.

-- Arghya Sadhu
Source: StackOverflow

11/29/2020

The options highlighted by @Panoptik and @Arghya Sadhu got me to use this one liner in a deployment pipeline:

echo -e "apiVersion: v1\nkind: Namespace\nmetadata:\n  name: ${NS_NAME}" | kubectl 
apply -f - 

Why an one liner: I needed to avoid line breaks in the pipeline. The code was tested on Debian and also the official Google Cloud Build image "gcloud".

-- MarcoK
Source: StackOverflow

7/21/2021

You can also consider using helm for this. Helm has a feature that creates the namespace for you if it doesn't exist and it simplifies the deployment of whatever app you want to deploy into that namespace. Notice the use of "--create-namespace", this will create my-namespace for you.

helm -n my-namespace upgrade --install --create-namespace my-app my-app-folder/

Tips:

  • Always use upgrade --install because it can do both those things
  • Use the option --set to set specific values in values.yaml at runtime of the command (useful i.e for secrets)
-- dom
Source: StackOverflow

11/17/2020

I have tried most of the options but the latest works for my deployment script best:

if ! kubectl get namespaces -o json | jq -r ".items[].metadata.name" | grep staging;then
  echo 'HALLO'
fi
-- Yuriy
Source: StackOverflow

11/23/2020

It is not the answer to specified question, but it is ready to use solution for those who google for subject question.

Based on @Arghya Sadhu answer my bash solution for creating if not exist namespace looks next:

    echo "apiVersion: v1
kind: Namespace
metadata:
  name: ${NS_NAME}" | kubectl apply -f -
-- Panoptik
Source: StackOverflow

9/18/2021

I was able to solve this problem using,

myNamespace="new-namespace"
kubectl get namespace | grep -q "^$myNamespace " || kubectl create namespace $myNamespace

The command kubectl get namespace gives an output like,

NAME                STATUS   AGE
alpha               Active   29m
default             Active   112m
gatekeeper-system   Active   111m
kube-node-lease     Active   112m
kube-public         Active   112m
kube-system         Active   112m
some-branch         Active   26m
something           Active   7m28s
something-else      Active   5m7s

Then, | grep -q "^$my-namespace " will look for your namespace in the output. The q will cause the command to return a 0 if your namespace is found. Otherwise it'll return a 1.

Note: the ^ the beginning and white-space at the end are important. This ensures the whole namespace is matched, and not just part of it. For example, if you were searching for the namespace something and did NOT include the space at the end, it would match both something and something-else from the example above.

Finally, || kubectl create namespace $my-namespace will create the namespace if it was found (i.e. the grep returned 1). Otherwise, it will not be created.

-- Corey P
Source: StackOverflow

4/27/2021

I mostly agree with @arghya-sadhu so far as declarative is nearly always the way to go. However, you could test for the existance of a namespace in bash, something like this:

#!/bin/bash

NAMESPACE_NAME=${1:-default};

export KUBECONFIG=your-kubeconfig.yml;

NS=$(kubectl get namespace $NAMESPACE_NAME --ignore-not-found);
if [[ "$NS" ]]; then
  echo "Skipping creation of namespace $NAMESPACE_NAME - already exists";
else
  echo "Creating namespace $NAMESPACE_NAME";
  kubectl create namespace $NAMESPACE_NAME;
fi;
-- Fraser Goffin
Source: StackOverflow