Configuring Namespaces and Namespace-scoped objects

This topic 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

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

Follow these steps to configure a Namespace called audit 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/audit:

    mkdir namespaces/audit
    
  2. In the namespace directory, create a file audit.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: audit
    
  3. Create a commit that includes the audit.yaml config, and push the commit to the remote repository.

    git add namespaces/audit/audit.yaml
    git commit -m "Created audit Namespace config"
    git push name-of-remote branch-name
    
  4. In a few moments, the audit Namespace is created in each enrolled cluster. To verify, describe the Namespace:

    kubectl describe namespace audit
    
  5. To remove the config and delete the audit 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 audit namespace directory into an abstract namespace containing additional configs inherited by the audit Namespace.

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

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

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

    # namespaces/regulatory/regulator_rolebinding.yaml
    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: regulatory-admin
    subjects:
    - kind: Group
      name: regulators@example.com
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: Role
      name: regulator
      apiGroup: rbac.authorization.k8s.io
    
  4. Move the audit namespace directory from the namespaces/ to the namespaces/regulatory/ directory:

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

The Config Sync Operator notices the change and applies the new Role and RoleBinding to the audit Namespace on all enrolled clusters.

To remove the configs and delete the audit Namespace from enrolled clusters, you can create a new commit that removes the entire regulatory 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, 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 use a NamespaceSelector in combination with a config in namespaces/ to limit which Namespaces can inherit that config.

The following config creates a NamespaceSelector called sre-supported. If another config references this NamespaceSelector, that config can only be applied to objects in Namespaces that have the env: prod label.

kind: NamespaceSelector
apiVersion: configmanagement.gke.io/v1
metadata:
  name: sre-supported
spec:
  selector:
    matchLabels:
      env: prod

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 sre-supported NamespaceSelector is in the same hierarchy as the following RoleBinding, sre-admin, the RoleBinding is only created in Namespaces that have the env: prod label:

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: sre-admin
  annotations:
    configmanagement.gke.io/namespace-selector: sre-supported
subjects:
- kind: Group
  name: sre@foo-corp.com
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: admin
  apiGroup: rbac.authorization.k8s.io

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?