Configuring namespaces and namespace-scoped objects

This page illustrates how to use Config Sync to manage namespaces and namespace-scoped objects. You can also read about configuring clusters and cluster-scoped objects.

Configuring a namespace

Unstructured format

Configs for namespaces and namespace-scoped objects can be located anywhere in the directory or subdirectories.

Follow these steps to configure a namespace called gamestore in each enrolled cluster. You only need to create a YAML file that contains the namespace config. This example adds the file to the root directory. You can move it to any subdirectories.

  1. Create a file namespace-gamestore.yaml with the following content.

    apiVersion: v1
    kind: Namespace
    metadata:
      name: gamestore
    
  2. Create a commit that includes the namespace-gamestore.yaml config, and push the commit to the remote repository.

    git add multirepo/root/namespace-gamestore.yaml
    git commit -m "Created gamestore namespace config"
    git push [NAME-OF-REMOTE] [BRANCH-NAME]
    

Hierarchical format

All configs for namespaces and namespace-scoped objects are located within the namespaces/ directory of the hierarchical repo and its descendant directories.

Follow these steps to configure a namespace called gamestore in each enrolled cluster.

  1. In the local clone of the repo, create a namespace directory. A namespace directory contains a config for a namespace. The name of the namespace directory must match the name of the namespace. In this example, the directory is called namespaces/gamestore:

    mkdir namespaces/gamestore
    
  2. In the namespace directory, create a file gamestore.yaml, with the following contents. The metadata.name must match the name of the namespace (and the name of the namespace directory).

    apiVersion: v1
    kind: Namespace
    metadata:
      name: gamestore
    
  3. Create a commit that includes the gamestore.yaml config, and push the commit to the remote repository.

    git add namespaces/gamestore/gamestore.yaml
    git commit -m "Created gamestore namespace config"
    git push [NAME-OF-REMOTE] [BRANCH-NAME]
    

In a few moments, the gamestore namespace is created in each enrolled cluster. To verify, describe the namespace:

kubectl describe namespace gamestore

To remove the config and delete the gamestore namespace from enrolled clusters, you can create a new commit that removes the file, and push it to the remote repository.

Configuring an abstract namespace

This example extends the example in configuring a namespace by moving the gamestore namespace directory into an abstract namespace containing additional configs inherited by the gamestore namespace.

  1. In the local clone of the repo, create an abstract namespace directory called eng. An abstract namespace directory does not contain a config for a namespace, but its descendant namespace directories do.

    mkdir namespaces/eng
    
  2. In the eng abstract namespace directory, create a config for a Role called eng-viewer, that grants get and list on all resources in any namespace that eventually inherits the Role.

    # namespaces/eng/eng-role.yaml
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: eng-viewer
    rules:
    - apiGroups: [""]
      resources: ["*"]
      verbs: ["get", "list"]
    
  3. Create a config for a RoleBinding called eng-admin that binds the eng-viewer Role to group eng@example.com:

    # namespaces/eng/eng-rolebinding.yaml
    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: eng-admin
    subjects:
    - kind: Group
      name: eng@example.com
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: Role
      name: eng-viewer
      apiGroup: rbac.authorization.k8s.io
    
  4. Move the gamestore namespace directory from the namespaces/ to the namespaces/eng/ directory:

    mv namespaces/gamestore/ namespaces/eng/
    
  5. Commit all of your changes and push them to the remote for the repo.

The Config Management Operator notices the change and applies the new Role and RoleBinding to the gamestore namespace on all enrolled clusters.

To remove the configs and delete the gamestore namespace from enrolled clusters, you can create a new commit that removes the entire eng abstract namespace, and push it to the remote repository.

Limiting which clusters a config affects

Normally, Config Sync applies a config to each enrolled cluster. If the config is within the namespaces/ subdirectory of a hierarchical repo, Config Sync first creates the namespace within each cluster and then applies all inherited configs to that namespace.

To limit which clusters a particular config affects based on each cluster's labels, refer to Applying configs to a subset of clusters.

Limiting which namespaces a config affects

A NamespaceSelector is a special type of config that uses Kubernetes labelSelectors. You can declare NamespaceSelectors in combination with configs for namespace-scoped objects in an unstructured repo or a hierarchical repo to limit which namespaces can inherit that config.

NamespaceSelectors are similar to but not identical to ClusterSelectors. A NamespaceSelector narrows the pool of namespaces a config applies to. In an unstructured repo, Objects that declare the NamespaceSelector annotation are applied to all namespaces that satisfy the NamespaceSelector's conditions. In a hierarchical repo, Objects that declare the NamespaceSelector annotation are applied to namespaces that inherit a given config from an abstract namespace, regardless of the directory structure of the namespaces/ directory. A ClusterSelector narrows the pool of clusters a config applies to, whether the config targets a cluster-scoped or namespace-scoped object.

NamespaceSelector location

  • Unstructured format: In an unstructured repo, you can place the NamespaceSelectors in any directory or subdirectories.
  • Hierarchical format: In a hierarchical repo, you can place NamespaceSelectors in any abstract namespace directory, but not in a namespace directory.

    The following example repository shows you valid and invalid locations for NamespaceSelectors:

    namespace-inheritance
    ...
    ├── namespaces
    │   ├── eng
    │   │   ├── gamestore
    │   │   │   ├── namespace.yaml
    │   │   │   └── ns_selector.yaml  # invalid
    │   │   └── ns_selector.yaml  # valid
    │   ├── ns_selector.yaml  # valid
    │   ├── rnd
    │   │   ├── incubator-1
    │   │   │   ├── namespace.yaml
    │   │   │   └── ns_selector.yaml  # invalid
    │   │   └── ns_selector.yaml  # valid
    

    Since the namespaces, eng, and rnd directories represent abstract namespaces, you can put a selector in them. However, because the gamestore and incubator-1 directories represents actual namespaces, you can't put a NamespaceSelector in them.

Using a NamespaceSelector

The following config creates a NamespaceSelector called gamestore-selector. If another config references this NamespaceSelector, that config can only be applied to objects in namespaces that have the app: gamestore label.

kind: NamespaceSelector
apiVersion: configmanagement.gke.io/v1
metadata:
  name: gamestore-selector
spec:
  selector:
    matchLabels:
      app: gamestore

To reference a NamespaceSelector in a config, you set the configmanagement.gke.io/namespace-selector annotation to the name of the NamespaceSelector.

A NamespaceSelector has no effect until you reference it in another config. If the gamestore-selector NamespaceSelector is in the same hierarchy as the following ResourceQuota, quota, the ResourceQuota is only created in namespaces that have the app: gamestore label:

kind: ResourceQuota
apiVersion: v1
metadata:
  name: quota
  annotations:
    configmanagement.gke.io/namespace-selector: gamestore-selector
spec:
  hard:
    pods: "1"
    cpu: "200m"
    memory: "200Mi"

To summarize, using a NamespaceSelector is a three-step process:

  1. Add labels to namespaces.
  2. Create a NamespaceSelector config.
  3. Reference the NamespaceSelector object in another config.

Disabling inheritance for an object type

You can selectively disable inheritance for any config by setting the hierarchyMode field to none. HierarchyConfigs are stored in the system/ directory of the repo. This example disables inheritance for RoleBindings.

# system/hierarchy-config.yaml
kind: HierarchyConfig
apiVersion: configmanagement.gke.io/v1
metadata:
  name: rbac
spec:
  resources:
  # Configure Role to only be allowed in leaf namespaces.
  - group: rbac.authorization.k8s.io
    kinds: [ "RoleBinding" ]
    hierarchyMode: none

What's next