This page illustrates how to use Config Sync to manage namespaces and namespace-scoped objects.
Configure a namespace
Configuring a namespace functions differently for unstructured and hierarchical repositories. The following examples highlight the differences.
Unstructured repository
Configs for namespaces and namespace-scoped objects can be located anywhere in the repository's directory or subdirectories.
Complete the following steps to configure a namespace called gamestore
in
each enrolled cluster:
Create a file
namespace-gamestore.yaml
with the following content:apiVersion: v1 kind: Namespace metadata: name: gamestore
You only need to create one YAML file that contains the namespace config.
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 REMOTE_NAME BRANCH_NAME
Replace the following:
REMOTE_NAME
: the name of your remote repository.BRANCH_NAME
: the branch that you want to commit to.
This example adds the file to the root directory, but you can move this file to any of the repository's subdirectories.
Hierarchical repository
All configs for namespaces and namespace-scoped objects are located within the
namespaces/
directory of the
hierarchical repository and its
descendant directories.
Follow these steps to configure a namespace called gamestore
in each enrolled
cluster:
In the local clone of your repository, 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
In the namespace directory, create a file
gamestore.yaml
, with the following content:apiVersion: v1 kind: Namespace metadata: name: gamestore
The
metadata.name
must match the name of the namespace directory.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 REMOTE_NAME BRANCH_NAME
Replace the following:
REMOTE_NAME
: the name of your remote repository.BRANCH_NAME
: the branch that you want to commit to.
After 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,
create a new commit that removes the file, and push it to the remote
repository. Do not remove the config if you want to
configure an abstract namespace for a
hierarchical repository.
Configure a namespace-scoped object
In unstructured repositories, you can store namespace-scoped objects in any directory or subdirectory without requiring a Namespace config. If a Namespace config is missing, Config Sync automatically creates an implicit Namespace object, and applies all configs to that namespace.
This behavior can be modified using the namespaceStrategy
field. If
namespaceStrategy
is set to explicit
, then Config Sync won't
automatically create an implicit Namespace object. For more information, see
namespace strategy.
In hierarchical repositories, you must explicitly specify a Namespace config in
the namespaces/NAMESPACE
subdirectory, where NAMESPACE
must match the name of the namespace. All other namespace-scoped configs must
also be stored in the same subdirectory. If a Namespace config is missing,
Config Sync returns a KNV1044 error, indicating a missing Namespace config.
Configure an abstract namespace
This section only applies to hierarchical repositories because abstract namespaces are not supported in unstructured repositories.
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.
In the local clone of the repository, create an abstract namespace directory called
eng
:mkdir namespaces/eng
An abstract namespace directory does not contain a config for a namespace, but its descendant namespace directories do.
In the
eng
abstract namespace directory, create a config for a Role calledeng-viewer
, that grantsget
andlist
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"]
Create a config for a RoleBinding called
eng-admin
that binds theeng-viewer
Role to groupeng@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
Move the
gamestore
namespace directory from thenamespaces/
to thenamespaces/eng/
directory:mv namespaces/gamestore /namespaces/eng/
Commit all of your changes and push them to the remote for the repository.
Config Sync 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.
Limit which clusters a config affects
Normally, Config Sync applies a config to each enrolled cluster. However, if
the config is within the namespaces/
subdirectory of a hierarchical
repository, 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, use a ClusterSelector. To learn more, see
Use ClusterSelectors.
Limit which namespaces a config affects
To limit which namespaces a config affects, use a NamespaceSelector. 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 repository or a hierarchical repository to limit which namespaces can inherit that config. NamespaceSelectors are similar, but not identical, to ClusterSelectors. A NamespaceSelector narrows the pool of namespaces a config applies to.
To declare a NamespaceSelector, add either the metadata.namespace
or the
NamespaceSelector
annotation. Declaring both annotations is invalid. If
namespace-scoped resources don't declare metadata.namespace
or the
NamespaceSelector
annotation, then Config Sync uses the
"default" namespace of the cluster.
NamespaceSelectors in unstructured repositories
An unstructured repository does not have to declare
all namespaces for the namespace-scoped objects in the repository. An object can
define a metadata.namespace
without having a matching namespace object in an
unstructured repository. If the namespace already exists on the cluster,
Config Sync creates the object within that namespace. If the
namespace does not exist on the cluster yet, Config Sync creates the
namespace implicitly.
Before you create an unstructured repository with objects
that were previously used in a hierarchical repository, verify that your
NamespaceSelectors
do not apply to additional resources.
When you remove namespace-scoped objects from an unstructured repository, Config Sync deletes those objects, but it does not remove any namespaces that might have been created implicitly for those objects. This behavior happens because Config Sync can't infer when it's safe to delete a namespace that was created implicitly, so it's always left on the cluster.
NamespaceSelector mode
In an unstructured repository, objects that declare the NamespaceSelector
annotation are applied to all Namespaces that satisfy the conditions of a
NamespaceSelector
. Namespaces can be statically declared in the source of
truth, or they can be dynamic. To enable dynamic selection, set spec.mode
to
dynamic
. In dynamic mode, the selection extends to both statically-declared
Namespaces and those dynamically present on the cluster. Namespaces chosen
dynamically already exist on the cluster and are therefore not managed by
Config Sync. The default mode is static
.
NamespaceSelectors in hierarchical repositories
In a hierarchical repository, 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
In an unstructured repository, you can place the NamespaceSelectors in any directory or subdirectories.
In a hierarchical repository, you can place NamespaceSelectors in any abstract namespace directory, but not in a namespace directory.
The following example repository architecture shows valid and invalid locations for NamespaceSelectors if you are using a hierarchical repository:
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 represent actual namespaces, you can't put a
NamespaceSelector in them.
NamespaceSelector examples
You can use a NamespaceSelector
with label selectors to include or exclude
namespaces. Kubernetes supports
equality-based and set-based selectors.
You can combine both types of selectors to further refine which namespaces are
selected.
Equality-based label selector
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:
- Add labels to Namespaces.
- Create a NamespaceSelector config.
- Reference the NamespaceSelector object in another config.
Set-based label selector
You can use namespace selectors to exempt particular namespaces from inheriting a resource in the tree by using set-based label selectors.
In this example, when the ResourceQuota
is annotated with the NamespaceSelector
by setting the annotation configmanagement.gke.io/namespace-selector: excludes-exempt-namespaces
,
the ResourceQuota
is created in every namespace except any namespaces that are
labeled quota-exempt: exempt
:
kind: NamespaceSelector
apiVersion: configmanagement.gke.io/v1
metadata:
name: excludes-exempt-namespaces
spec:
selector:
matchExpressions:
- key: quota-exempt
operator: NotIn
values:
- exempt
Integration with team scopes and fleet namespaces
Fleet namespaces created in Google Cloud automatically have the label
fleet.gke.io/fleet-scope: your-scope
. All namespaces also have the Kubernetes
kubernetes.io/metadata.name: your-namespace
label. You can use these default
labels to set up the NamespaceSelector
for selecting fleet namespaces.
Disable inheritance for an object type
HierarchyConfig Kubernetes objects are not supported in unstructured repositories. The following example only applies to the hierarchical repositories.
You can selectively disable inheritance for any config by setting the
hierarchyMode
field to none
. HierarchyConfigs are stored in the system/
directory of the repository. 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
- Learn about configuring clusters and cluster-scoped objects