kubernetes-sigs / kustomize

Customization of kubernetes YAML configurations
Apache License 2.0
11.07k stars 2.26k forks source link

`namespace` changes the name of `Namespace` resources #5282

Open lindhe opened 1 year ago

lindhe commented 1 year ago

What happened?

When having multiple Namespace resources, setting namespace in kustomization.yaml causes resource collision.

What did you expect to happen?

According to the documentation, the namespace field "Will override the existing namespace if it is set on a resource, or add it if it is not set on a resource".

This makes it sound like it sets .metadata.namespace for namespaced resources. That, however, is not all it does. It also changes the .metadata.name of Namespace resources!

I expect it to not change the name of my Namespace resources. But if that is the intended behavior, I would expect the documentation to be clear about this.

How can we reproduce it (as minimally and precisely as possible)?

# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: foo
resources:
- ns-bar.yaml
- ns-baz.yaml
# ns-bar.yaml
apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: null
  name: bar
spec: {}
status: {}
File: ns-baz.yaml
apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: null
  name: baz
spec: {}
status: {}

Expected output

apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: null
  name: bar
spec: {}
status: {}
---
apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: null
  name: baz
spec: {}
status: {}

Actual output

Error: namespace transformation produces ID conflict: [{"apiVersion":"v1","kind":"Namespace","metadata":{"annotations":{"internal.config.kubernetes.io/previousKinds":"Namespace","internal.config.kubernetes.io/previousNames":"bar","internal.config.kubernetes.io/previousNamespaces":"_non_namespaceable_"},"creationTimestamp":null,"name":"foo"},"spec":{},"status":{}} {"apiVersion":"v1","kind":"Namespace","metadata":{"annotations":{"internal.config.kubernetes.io/previousKinds":"Namespace","internal.config.kubernetes.io/previousNames":"baz","internal.config.kubernetes.io/previousNamespaces":"_non_namespaceable_"},"creationTimestamp":null,"name":"foo"},"spec":{},"status":{}}]

Kustomize version

v5.1.0

Operating system

Linux

annasong20 commented 11 months ago

Hi @lindhe, I see that this is expected behavior from https://github.com/kubernetes-sigs/kustomize/issues/2867. I'm personally leaning towards preserving the existing behavior because of both its history and my expectations. If I wanted all of my Kubernetes objects to be in the same namespace, I'd want to change my old Namespace object to the new one. In this case, I either

This is exactly to your point of the documentation being presently lacking. I agree that we should update the documentation to describe existing behavior. /kind documentation /remove-kind bug /triage accepted FYI @ncapps

lindhe commented 11 months ago

Hi!

Thanks for the response! I think it's great if we change the documentation first, so let's do that. While I do think that we should change the behavior too, we should probably hold off with that. I think it would have to be considered a breaking change, so maybe something to consider before the next major release.

Let me just try and clarify why I think that the behavior should change, so it's documented here for future reference.

[I] wouldn't expect there to be multiple Namespace objects (if I want to switch my objects from one namespace to another)

I follow your logic here. In my case, it's slightly different though. Since I posted this several months ago, I don't have the details fresh in memory right now. But the gist of my situation is that I use Argo CD to deploy most things in my cluster and I want Argo CD to create a number of namespaces for me. But for all other resources, except the namespaces, I want to ensure that they get deployed to one specific namespace. And that's where I run into issues.

I'll get back to you if I can recall the exact circumstances.

annasong20 commented 11 months ago

@lindhe I think that also makes sense. Yeah, let us know if you remember your use case!

I forgot to mention in my last comment that if you don't want to change the name of Namespaces, you can use the customizable version of the namespace field, which is https://github.com/kubernetes-sigs/kustomize/blob/master/plugin/builtin/namespacetransformer/NamespaceTransformer_test.go#L31, and just leave

- path: metadata/name
  kind: Namespace

out of the fieldSpecs.

lindhe commented 11 months ago

I did not know that! Thank you!! 🎉 It sounds like just the thing I needed to work around my case. Awesome.

lindhe commented 7 months ago

FYI: I just rediscovered my original use case!

I manage an Argo CD instance where users have their own Argo CD project with a corresponding namespace (User Alice would have an Argo CD AppProject called alice and a namspace called alice. User Bob would have an Argo CD AppProject called bob and a namspace called bob).

What I wanted to do was to include the creation of these projects and namespaces as part of the kustomization I use to deploy Argo CD, so they get deployed automatically alongside Argo CD. But I need to ensure that all Argo CD resources gets scoped to the argocd namespace, which is why I had to set namespace: argocd in my kustomization.yaml for Argo CD. That thus I could not deploy the alice and bob namespaces as part of the same kustomization.

So now I get back to the question of how to do that… I think I get what you mean by using the customizable namespace transformer and leaving out the element from fieldSpecs. But I'm not sure how to implement it in practice. Would it look something like this?

custom_namespace_transformer.yaml

apiVersion: builtin
kind: NamespaceTransformer
metadata:
  name: not-important-to-example
  namespace: test
setRoleBindingSubjects: none
unsetOnly: true
fieldSpecs: []

kustomization.yaml

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

transformers:
  - custom_namespace_transformer.yaml

I don't know where to find a full example of using custom transformers… 🤔