kustomize-controller icon indicating copy to clipboard operation
kustomize-controller copied to clipboard

targetNamespace should create the namespace if not exists

Open saltyblu opened this issue 1 year ago • 5 comments

Currently there is a gap between kustomize and helm. Helm creates the namespaces itself on creation. Kustomize is not doing this.

I would love to see that as feature in flux/kustomize

saltyblu avatar Jul 18 '22 07:07 saltyblu

The helm-controller is capable of doing this because it is a Helm feature. Which comes with limitations, as on uninstall the namespace will not be garbage collected.

Given this, I do not think the kustomize-controller will support this feature.

hiddeco avatar Jul 18 '22 08:07 hiddeco

but the flux kustomize could handle that? is this the wrong place than :(

saltyblu avatar Jul 18 '22 08:07 saltyblu

Also this leads into several issues, if the kustomize exists inside a custom namespace, but this needs to be created by another kustomize out of flux-system.

for example:

gotk-sync.yaml

---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
  name: flux-system
  namespace: flux-system
spec:
  interval: 1m0s
  ref:
    branch: main
  secretRef:
    name: flux-system
  url: https://github.com/
---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
  name: flux-system
  namespace: flux-system
spec:
  interval: 5m0s
  path: ./clusters/pt-dev
  prune: true
  sourceRef:
    kind: GitRepository
    name: flux-system

inside: clusters/pt-dev/playground component.yaml

apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
  name: example-nginx
spec:
  interval: 5m0s
  path: ./deployment/k8s/dev
  prune: true
  force: true
  sourceRef:
    kind: GitRepository
    name: example-nginx
----- kustomize.yaml
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: playground
resources:
- component.yaml

this deployment will not work because the namepsace playground needs to be created before in another yaml inside of flux-system to handle the namespace. That would separate component stuff, that should belong together :(

inside: clusters/pt-dev/playground component.yaml

apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
  name: example-nginx
spec:
  targetNamespace: playground # <- creates namespace if not exists
  interval: 5m0s
  path: ./deployment/k8s/dev
  prune: true
  force: true
  sourceRef:
    kind: GitRepository
    name: example-nginx
----- kustomize.yaml
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- component.yaml

saltyblu avatar Jul 18 '22 08:07 saltyblu

The kustomize-controller can handle the creation of the namespace (and garbage collection of it) fine, by simply declaring the namespace object in a Kustomization. Whatever other Kustomization then depends on the existence of this namespace, can hierarchically depend on this being applied first using dependsOn: https://fluxcd.io/docs/components/kustomize/kustomization/#kustomization-dependencies.

hiddeco avatar Jul 18 '22 08:07 hiddeco

This would split a component into two separate kustomize.toolkit.fluxcd.io/v1beta2 inside of two different namespaces.

This isn't that and a strange dependency :(.

Also, both kustomize.toolkit.fluxcd.io/v1beta2 belong to the flux-system ks and that would lead to a deployment failure when bootstrapping a new environment because one of the ks is not valid due to the fact that the namespace is missing.

saltyblu avatar Jul 18 '22 08:07 saltyblu

This would split a component into two separate kustomize.toolkit.fluxcd.io/v1beta2 inside of two different namespaces

I don't understand this limitation you described. It doesn't limit that way, because the Kustomize controller understands namespaced and non-namespaced resources and the order they should apply. If you create a Namespace inside of a Flux Kustomization, the controller reconciler does the apply in steps: first any Namespaces (and any other Non-Namespaced resources, like CRDs) are created, and second after that any Namespaced Resources and Custom Resources are created.

This is done in steps but in a single transaction via Server-Side Apply, so you should never hit an issue where Kustomize Controller fails to create a resource in the namespace because that namespace had not been declared "upstream." They can be declared in the same Flux Kustomization.

Please reach out if there's some reason this still doesn't meet your needs. I am pretty sure this can be closed.

kingdonb avatar Aug 25 '22 17:08 kingdonb

just use my example and you will see that flux stop working because the namespace playground does not exists.

It's a chicken egg issue, putting a kustomization (flux) inside a namespace this ks reconcilation does not work, because flux can't put a flux kustomization into a namespace that does not exist. To solve this, I need to create another kustomization (flux) to create and handle namespaces, which is part of flux-system. Disaster recovery is not possible or onboarding a new cluster.

There are two steps to implementing a new service inside a new namespace.

saltyblu avatar Aug 26 '22 05:08 saltyblu

Your example simply seems to be missing the Namespace definition:

apiVersion: v1
kind: Namespace
metadata:
  name: playground

If you add this definition within the Flux Kustomization or adjacent to the Flux Kustomization, assuming nothing else is different from what you've shown here, I am certain that it will work.

I haven't understood clearly what reason you don't want to define the Namespace directly in either one of those places, but unless you have locked down your cluster for Flux's multi-tenancy, there should be nothing stopping you from creating Namespaces where they are needed.

The Flux Kustomization's targetNamespace directive will even do you the extra solid of overwriting the name field on the Namespace definition above, if it's defined inside of the path at the target as some Namespace with any different name. A good example of an overlay which defines its own namespace is in Podinfo, here is the production overlay, which pulls in different services from bases, and joins them together in a Namespace that's defined there, within the overlay.

https://github.com/stefanprodan/podinfo/blob/master/deploy/overlays/production/kustomization.yaml

This is the expected pattern, if you have a different approach that didn't work, and you don't understand why, the best way to provide reproduction is with a public repository. Copying and pasting manifests from your partial description inside of a thread is not the ideal way to help you debug your issue.

It is also suggested to start Q&A threads on the fluxcd/flux2 Discussions Q&A label.

Feature requests can go there, Proposals are preferred to feature requests, and PRs generally follow after Proposals turn into RFCs, as we like to help folks implement their own "scratch their own itch."

But these proposals must be thought-out and designed, and given to the community with enough space for feedback and understanding the impact. Flux project does try not to make any fast moves outside of planned roadmap issues and other important fixes we encountered on our way to GA.

Please take a look at the example that I linked, and I hope that it helps unblock you. I do not think there's any strong compelling argument or reason to add targetNamespace here, it's not compelling to do so just because Helm Controller has this feature. There is no namespace chicken and egg issue for Kustomize controller by itself that I can observe.

kingdonb avatar Aug 27 '22 14:08 kingdonb

Lets try an example:

clusters/dev/flux-system # default flux-system stuff defining the GitRepo to reconcile 

---
# clusters/dev/example, inside this git repo
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
  name: example-nginx
spec:
  targetNamespace: playground
  interval: 5m0s
  path: ./k8s/dev
  prune: true
  force: true
  sourceRef:
    kind: GitRepository
    name: example-nginx

This simple flux example does not work, because the targetNamespace: playground does not exist.

This means I need to create it first with another flux kustomization that is part of flux-system or if created the default namespace. I could also create the namespace inside the main git where everything is stored but this would mix up deployment information and deployments. And the namespace would not be properly versioned anymore.

The flux-system reconciliation stops completely. I hope that helps.

saltyblu avatar Aug 29 '22 05:08 saltyblu

I could also create the namespace inside the main git where everything is stored but this would mix up deployment information and deployments.

IMO namespaces are not part of an app deployment, being cluster wide objects, these should be managed by a Flux Kustomization that's own by cluster admins. The recommended setup, is where the namespaces and the app Flux Kustomizations are placed together in the same dir and applied by the flux-system root Kustomization.

Please see the example repos:

  • https://github.com/fluxcd/flux2-kustomize-helm-example
  • https://github.com/fluxcd/flux2-multi-tenancy

stefanprodan avatar Aug 29 '22 09:08 stefanprodan

that's own by cluster admins.

That is exactly what we don't want. :( Giving developers two kustomizations in hand one "only for namespaces" and the other for the service deployment feels wrong.

And helm solves this issue. That's why I reported this.

saltyblu avatar Aug 30 '22 05:08 saltyblu

@saltyblu If the Flux Kustomization can create namespaces on-demand then it has cluster admin rights. Adding a flag to create namespaces wouldn't solve this, the Flux Kustomization still needs a service account attached to it, either one with the capability to create namespaces or one without it.

If we added the flag to createNamespace to the Flux Kustomization, then we would need more code to solve the problem that you described here, because the Flux Kustomization can either create cluster resources or it cannot. This goes similar for resources that are named and described for creation by the user, with manifests inside the path from the source. There is only one Service Account for each Flux Kustomization.

For rigorous multi-tenancy, you need separate Flux kustomizations and some of them should be isolated within a namespace. That namespace has to be created externally, even if you assign a namespaced cluster-admin so the user has full control within the namespace, the scopes in RBAC are designed so that the damage a user can do is constrained to at most "delete the namespace that I am in, and all of its contents." *Notably this does not include the create namespace perm.

Those Helm releases with createNamespace are also in a position to create cluster-wide resources. They are not separated from the cluster-admin permission if they can create namespaces. If you want rigorous multi-tenancy then you must follow the hardening guide and steps in flux2-multi-tenancy. It's not something that createNamespace is in position to offer in the way that you expect here.

The developers wouldn't be managing the Kustomization with namespaces in it. They are assigned a namespace by the cluster admin (a platform team, or someone who should have admin rights on the cluster), and the developers' access should generally be limited to only service accounts which do not have permission to write cluster scoped objects.

kingdonb avatar Aug 30 '22 12:08 kingdonb

Okay thanks got the point. I guess.

saltyblu avatar Aug 31 '22 06:08 saltyblu