Sharing secret across namespaces

NamespacesKubernetes

Namespaces Problem Overview


Is there a way to share secrets across namespaces in Kubernetes?

My use case is: I have the same private registry for all my namespaces and I want to avoid creating the same secret for each.

Namespaces Solutions


Solution 1 - Namespaces

Secret API objects reside in a namespace. They can only be referenced by pods in that same namespace. Basically, you will have to create the secret for every namespace.

https://kubernetes.io/docs/concepts/configuration/secret/#details

Solution 2 - Namespaces

They can only be referenced by pods in that same namespace. But you can just copy secret from one name space to other. Here is a example of copying localdockerreg secret from default namespace to dev:

kubectl get secret localdockerreg --namespace=default --export -o yaml | kubectl apply --namespace=dev -f -

###UPDATE### In Kubernetes v1.14 --export flag is deprecated. So, the following Command with -oyaml flag will work without a warning in forthcoming versions.

kubectl get secret localdockerreg --namespace=default -oyaml | kubectl apply --namespace=dev -f -

or below if source namespace is not necessarily default

kubectl get secret localdockerreg --namespace=default -oyaml | grep -v '^\s*namespace:\s' | kubectl apply --namespace=dev -f -

Solution 3 - Namespaces

The accepted answer is correct: Secrets can only be referenced by pods in that same namespace. So here is a hint if you are looking to automate the "sync" or just copy the secret between namespaces.

Automated (operator)

For automating the share or syncing secret across namespaces use ClusterSecret operator:

https://github.com/zakkg3/ClusterSecret

Using sed:
kubectl get secret <secret-name> -n <source-namespace> -o yaml \
| sed s/"namespace: <source-namespace>"/"namespace: <destination-namespace>"/\
| kubectl apply -n <destination-namespace> -f -
Use jq

If you have jq, we can use the @Evans Tucker solution

kubectl get secret cure-for-covid-19 -n china -o json \
 | jq 'del(.metadata["namespace","creationTimestamp","resourceVersion","selfLink","uid"])' \
 | kubectl apply -n rest-of-world -f -

Solution 4 - Namespaces

Secrets are namespaced resources, but you can use a Kubernetes extension to replicate them. We use this to propagate credentials or certificates stored in secrets to all namespaces automatically and keep them in sync (modify the source and all copies are updated). See Kubernetes Reflector (https://github.com/EmberStack/kubernetes-reflector).

The extension allows you to automatically copy and keep in sync a secret across namespaces via annotations:

On the source secret add the annotations:

 annotations:
   reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true"

This will create a copy of the secret in all namespaces. You can limit the namespaces in which a copy is created using:

reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: "namespace-1,namespace-2,namespace-[0-9]*"

The extension supports ConfigMaps and cert-manager certificates as well. Disclainer: I am the author of the Kubernetes Reflector extension.

Solution 5 - Namespaces

--export is deprecated

sed is not the appropriate tool for editing YAML or JSON.

Here's an example that uses jq to delete the namespace and other metadata we don't want:

kubectl get secret cure-for-covid-19 -n china -o json \
 | jq 'del(.metadata["namespace","creationTimestamp","resourceVersion","selfLink","uid"])' \
 | kubectl apply -n rest-of-world -f -

Solution 6 - Namespaces

Another option would be to use kubed, as recommended by the kind folks at Jetstack who gave us cert-manager. Here is what they link to.

Solution 7 - Namespaces

As answered by Innocent Anigbo, you need to have the secret in the same namespace. If you need to support that dynamicaly or avoid forgeting secret creation, it might be possible to create an initialiser for namespace object https://kubernetes.io/docs/admin/extensible-admission-controllers/ (have not done that on my own, so cant tell for sure)

Solution 8 - Namespaces

Improving from @NicoKowe

One liner to copy all secrets from one namespace to another

$ for i in `kubectl get secrets | awk '{print $1}'`; do  kubectl get secret $1 -n <source-namespace> -o yaml | sed s/"namespace: <source-namespace>"/"namespace: <target-namespace>"/ | kubectl apply -n <target-namespace> -f -  ; done

Solution 9 - Namespaces

Based on @Evans Tucker's answer but uses whitelisting rather than deletion within the jq filter to only keep what we want.

kubectl get secret cure-for-covid-19 -n china -o json | jq '{apiVersion,data,kind,metadata,type} | .metadata |= {"annotations", "name"}' | kubectl apply -n rest-of-world -f -

Essentially the same thing but preserves labels.

kubectl get secret cure-for-covid-19 -n china -o json | jq '{apiVersion,data,kind,metadata,type} | .metadata |= {"annotations", "name", "labels"}' | kubectl apply -n rest-of-world -f -

Solution 10 - Namespaces

Use RBAC to authorize the serviceaccoun to use the secret on the original namespaces. But, this is not recommended to have a shared secret between namesapces.

Solution 11 - Namespaces

Solution for copying all secrets.

kubectl delete secret --namespace $TARGET_NAMESPACE--all;
kubectl get secret --namespace default --output yaml \
    | sed "s/namespace: $SOURCE_NAMESPACE/namespace: $TARGET_NAMESPACE/" \
    | kubectl apply --namespace $TARGET_NAMESPACE --filename -;

Solution 12 - Namespaces

yq is a helpful command-line tool for editing YAML files. I utilized this in conjunction with the other answers to get this:

kubectl get secret <SECRET> -n <SOURCE_NAMESPACE> -o yaml | yq write - 'metadata.namespace' <TARGET_NAMESPACE> | kubectl apply -n <TARGET_NAMESPACE> -f -

Solution 13 - Namespaces

You may also think about using GoDaddy's Kubernetes External Secrets! where you will be storing your secrets in AWS Secret Manager(ASM) and GoDaddy's secret controller will create the secrets automatically. Moreover, there would be sync between ASM And K8S cluster.

Solution 14 - Namespaces

kubectl get secret gitlab-registry --namespace=revsys-com --export -o yaml |
kubectl apply --namespace=devspectrum-dev -f -

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionmatth3oView Question on Stackoverflow
Solution 1 - NamespacesInnocent AnigboView Answer on Stackoverflow
Solution 2 - NamespacesHansika WeerasenaView Answer on Stackoverflow
Solution 3 - NamespacesNicoKoweView Answer on Stackoverflow
Solution 4 - NamespaceswinromulusView Answer on Stackoverflow
Solution 5 - NamespacesEvans TuckerView Answer on Stackoverflow
Solution 6 - NamespacesKyleView Answer on Stackoverflow
Solution 7 - NamespacesRadek 'Goblin' PieczonkaView Answer on Stackoverflow
Solution 8 - NamespacesHalil KaskavalciView Answer on Stackoverflow
Solution 9 - NamespacesBruceView Answer on Stackoverflow
Solution 10 - NamespacesjmselmiView Answer on Stackoverflow
Solution 11 - NamespacesalextesView Answer on Stackoverflow
Solution 12 - NamespacesreinyView Answer on Stackoverflow
Solution 13 - NamespacesThileeView Answer on Stackoverflow
Solution 14 - Namespacesuser128364View Answer on Stackoverflow