diff --git a/README.md b/README.md index a838a42a..914cfa60 100644 --- a/README.md +++ b/README.md @@ -14,15 +14,17 @@ --- # Kubernetes multi-tenancy made simple -**Capsule** helps to implement a multi-tenancy and policy-based environment in your Kubernetes cluster. It is not intended to be yet another _PaaS_, instead, it has been designed as a micro-services based ecosystem with minimalist approach, leveraging only on upstream Kubernetes. +**Capsule** helps to implement a multi-tenancy and policy-based environment in your Kubernetes cluster. It is not intended to be yet another _PaaS_, instead, it has been designed as a micro-services-based ecosystem with the minimalist approach, leveraging only on upstream Kubernetes. # What's the problem with the current status? + Kubernetes introduces the _Namespace_ object type to create logical partitions of the cluster as isolated *slices*. However, implementing advanced multi-tenancy scenarios, it soon becomes complicated because of the flat structure of Kubernetes namespaces and the impossibility to share resources among namespaces belonging to the same tenant. To overcome this, cluster admins tend to provision a dedicated cluster for each groups of users, teams, or departments. As an organization grows, the number of clusters to manage and keep aligned becomes an operational nightmare, described as the well know phenomena of the _clusters sprawl_. -# Entering Capsule -Capsule takes a different approach. In a single cluster, the Capsule Controller aggregates multiple namespaces in a lightweight abstraction called _Tenant_. Within each tenant, users are free to create their namespaces and share all the assigned resources while the Capsule Policy Engine keeps the different tenants isolated from each other. -The _Network and Security Policies_, _Resource Quota_, _Limit Ranges_, _RBAC_, and other policies defined at the tenant level are automatically inherited by all the namespaces in the tenant. And users are free to operate their tenants in authonomy, without the intervention of the cluster administrator. Take a look at following diagram: +# Entering Capsule +Capsule takes a different approach. In a single cluster, the Capsule Controller aggregates multiple namespaces in a lightweight abstraction called _Tenant_, basically a grouping of Kubernetes Namespaces. Within each tenant, users are free to create their namespaces and share all the assigned resources while the Capsule Policy Engine keeps the different tenants isolated from each other. + +The _Network and Security Policies_, _Resource Quota_, _Limit Ranges_, _RBAC_, and other policies defined at the tenant level are automatically inherited by all the namespaces in the tenant. Then users are free to operate their tenants in autonomy, without the intervention of the cluster administrator. Take a look at following diagram:

@@ -42,7 +44,7 @@ Leverage Kubernetes Admission Controllers to enforce the industry security best Take control of the resources consumed by users while preventing them to overtake. ## Native Experience -Provide multi-tenancy with a native Kubernetes experience without introducing additional management layers, plugins, or customised binaries. +Provide multi-tenancy with a native Kubernetes experience without introducing additional management layers, plugins, or customized binaries. ## GitOps ready Capsule is completely declarative and GitOps ready. @@ -166,7 +168,7 @@ $ make remove ``` # FAQ -- Q. How to pronunce Capsule? +- Q. How to pronounce Capsule? A. It should be pronounced as `/ˈkæpsjuːl/`. @@ -180,7 +182,7 @@ $ make remove - Q. Does it work with my Kuberentes XYZ distribution? - A. We tested Capsule with vanilla Kubernetes 1.16+ on private envirnments and public clouds. We expect it works smootly on any other distribution. Please, let us know if you find it doesn't. + A. We tested Capsule with vanilla Kubernetes 1.16+ on private environments and public clouds. We expect it to work smoothly on any other Kubernetes distribution. Please, let us know if you find it doesn't. - Q. Do you provide commercial support? diff --git a/docs/index.md b/docs/index.md index 9ee0a45d..845de881 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,5 +1,5 @@ # Capsule Documentation -**Capsule** helps to implement a multi-tenancy and policy-based environment in your Kubernetes cluster. It has been designed as a micro-services based ecosystem with minimalist approach, leveraging only on upstream Kubernetes. +**Capsule** helps to implement a multi-tenancy and policy-based environment in your Kubernetes cluster. It has been designed as a micro-services based ecosystem with the minimalist approach, leveraging only on upstream Kubernetes. Currently, the Capsule ecosystem comprises the following: @@ -39,4 +39,4 @@ docs ├── resources-quota-limits.md ├── storage-classes.md └── taint-namespaces.md -``` \ No newline at end of file +``` diff --git a/docs/operator/use-cases/create-namespaces.md b/docs/operator/use-cases/create-namespaces.md index 8d555c13..d88c8b15 100644 --- a/docs/operator/use-cases/create-namespaces.md +++ b/docs/operator/use-cases/create-namespaces.md @@ -10,9 +10,9 @@ alice@caas# kubectl create ns oil-production > it is likely that many different tenants would like to call their namespaces > as `production`, `test`, or `demo`, etc. > -> The enforcement of this naming convention, however, is optional and can be controlled by the cluster administrator with the `--force-tenant-prefix` option as argument of the Capsule controller. +> The enforcement of this naming convention is optional and can be controlled by the cluster administrator with the `--force-tenant-prefix` option as an argument of the Capsule controller. -When Alice creates the namespace, the Capsule controller, listening for creation and deletion events assigns to Alice the following roles: +When Alice creates the namespace, the Capsule controller listening for creation and deletion events assigns to Alice the following roles: ```yaml --- @@ -69,7 +69,7 @@ alice@caas# kubectl create ns oil-development alice@caas# kubectl create ns oil-test ``` -While Alice creates namespace resources, the Capsule controller updates the status of the tenant so Bill, the cluster admin, can check its status: +While Alice creates namespace resources the Capsule controller updates the status of the tenant so Bill, the cluster admin, can check its status: ``` bill@caas# kubectl describe tenant oil @@ -92,8 +92,7 @@ Once the namespace quota assigned to the tenant has been reached, Alice cannot c alice@caas# kubectl create ns oil-training Error from server (Cannot exceed Namespace quota: please, reach out the system administrators): admission webhook "quota.namespace.capsule.clastix.io" denied the request. ``` - -The enforcement on the maximum number of Namespace resources per Tenant is in charge of the Capsule controller via its Dynamic Admission Webhook capability. +The enforcement on the maximum number of Namespace resources per Tenant is the responsibility of the Capsule controller via its Dynamic Admission Webhook capability. # What’s next -See how Alice, the tenant owner, can assign different user roles in the tenant. [Assign permissions](./permissions.md). \ No newline at end of file +See how Alice, the tenant owner, can assign different user roles in the tenant. [Assign permissions](./permissions.md). diff --git a/docs/operator/use-cases/custom-resources.md b/docs/operator/use-cases/custom-resources.md index 3ad0519b..0ba82b56 100644 --- a/docs/operator/use-cases/custom-resources.md +++ b/docs/operator/use-cases/custom-resources.md @@ -1,5 +1,5 @@ # Create Custom Resources -Capsule operator the admin permissions to the tenant's users but only limited to their namespaces. To achieve that, it assign the ClusterRole [admin](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) to the tenant owner. This ClusterRole does not permit the installation of custom resources in the namespaces. +Capsule operator can grant the admin permissions to the tenant's users but only limited to their namespaces. To achieve that, it assigns the ClusterRole [admin](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) to the tenant owner. This ClusterRole does not permit the installation of custom resources in the namespaces. In order to leave the tenant owner to create Custom Resources in their namespaces, the cluster admin defines a proper Cluster Role. For example: @@ -85,7 +85,7 @@ roleRef: With the above example, Capsule is leaving the tenant owner to create namespaced custom resources. -> Nota bene: a tenant owner having the admin scope on its namespaces only, does not have the permission to create Custom Resources Definitions (CRDs) because this requires a cluster admin permission level. Only Bill, the cluster admin, can create CRDs. This is a known limitation of any multi-tenancy environment based on a single Kubernetes cluster. +> Take Note: a tenant owner having the admin scope on its namespaces only, does not have the permission to create Custom Resources Definitions (CRDs) because this requires a cluster admin permission level. Only Bill, the cluster admin, can create CRDs. This is a known limitation of any multi-tenancy environment based on a single Kubernetes cluster. # What’s next -See how Bill, the cluster admin, can set taints on the Alice's namespaces. [Taint namespaces](./taint-namespaces.md). \ No newline at end of file +See how Bill, the cluster admin, can set taints on the Alice's namespaces. [Taint namespaces](./taint-namespaces.md). diff --git a/docs/operator/use-cases/images-registries.md b/docs/operator/use-cases/images-registries.md index a5c5c3a3..bb117826 100644 --- a/docs/operator/use-cases/images-registries.md +++ b/docs/operator/use-cases/images-registries.md @@ -20,9 +20,9 @@ spec: allowedRegex: '' ``` -> In case of naked and official images hosted on Docker Hub, Capsule is going +> In case of `non FQDI` (non fully qualified Docker image) and official images hosted on Docker Hub, Capsule is going > to retrieve the registry even if it's not explicit: a `busybox:latest` Pod -> running on a Tenant allowing `docker.io` will not blocked, even if the image +> running on a Tenant allowing `docker.io` will not be blocked, even if the image > field is not explicit as `docker.io/busybox:latest`. @@ -44,10 +44,10 @@ spec: A Pod running `internal.registry.foo.tld` as registry will be allowed, as well `internal.registry.bar.tld` since these are matching the regular expression. -> You can also set a catch-all as .* to allow every kind of registry, +> You can also set a catch-all regex entry as .* to allow every kind of registry, > that would be the same result of unsetting `containerRegistries` at all -As per Ingress and Storage classes, also the allowed registries can be inspected from the Tenant's namespace +As per Ingress and Storage classes the allowed registries can be inspected from the Tenant's namespace ``` alice@caas# kubectl describe ns oil-production @@ -60,4 +60,3 @@ Annotations: capsule.clastix.io/allowed-registries: docker.io # What’s next See how Bill, the cluster admin, can assign Pod Security Policies to Alice's tenant. [Assign Pod Security Policies](./pod-security-policies.md). - diff --git a/docs/operator/use-cases/ingress-classes.md b/docs/operator/use-cases/ingress-classes.md index 31681c68..af649656 100644 --- a/docs/operator/use-cases/ingress-classes.md +++ b/docs/operator/use-cases/ingress-classes.md @@ -66,10 +66,10 @@ spec: path: / ``` -Any tentative of Alice to use a not valid Ingress Class, e.g. `default`, will fail. +Any attempt of Alice to use a non valid Ingress Class, e.g. `default`, will fail. > The effect of this policy is that the services created in the tenant will be published > only on the Ingress Controller designated by Bill to accept one of the allowed Ingress Classes. # What’s next -See how Bill, the cluster admin, can assign a set of dedicated ingress hostnames to Alice's tenant. [Assign Ingress Hostnames](./ingress-hostnames.md). \ No newline at end of file +See how Bill, the cluster admin, can assign a set of dedicated ingress hostnames to Alice's tenant. [Assign Ingress Hostnames](./ingress-hostnames.md). diff --git a/docs/operator/use-cases/ingress-hostnames.md b/docs/operator/use-cases/ingress-hostnames.md index b0937b54..070c08a5 100644 --- a/docs/operator/use-cases/ingress-hostnames.md +++ b/docs/operator/use-cases/ingress-hostnames.md @@ -59,7 +59,7 @@ spec: ``` -Any tentative of Alice to use a not valid hostname, e.g. `web.gas.acmecorp.org`, will fail. +Any attempt of Alice to use a non valid hostname, e.g. `web.gas.acmecorp.org`, will fail. # What’s next -See how Bill, the cluster admin, can assign a Storage Class to Alice's tenant. [Assign Storage Classes](./storage-classes.md). \ No newline at end of file +See how Bill, the cluster admin, can assign a Storage Class to Alice's tenant. [Assign Storage Classes](./storage-classes.md). diff --git a/docs/operator/use-cases/multiple-tenants.md b/docs/operator/use-cases/multiple-tenants.md index c21875f7..15b1bf74 100644 --- a/docs/operator/use-cases/multiple-tenants.md +++ b/docs/operator/use-cases/multiple-tenants.md @@ -1,5 +1,5 @@ # Assign multiple tenants to an owner -In some scenarios, it's likely that a single team is responsible for multiple lines of business. For example, in our sample organization Acme Corp., Alice is responsible for both the Oil and Gas lines of business. Ans it's more probable that Alice requires two different tenants, for example `oil` and `gas` to keep things isolated. +In some scenarios, it's likely that a single team is responsible for multiple lines of business. For example, in our sample organization Acme Corp., Alice is responsible for both the Oil and Gas lines of business. It's more likely that Alice requires two different tenants, for example `oil` and `gas` to keep things isolated. By design, the Capsule operator does not permit hierarchy of tenants, since all tenants are at the same levels. However, we can assign the ownership of multiple tenants to the same user or group of users. @@ -107,4 +107,4 @@ kubectl create -f gas-production-ns.yaml >`Unable to assign namespace to tenant. Please use capsule.clastix.io/tenant label when creating a namespace.` # What’s next -This end our tour in Capsule use cases. As we improve Capsule, more use cases about multi-tenancy, policy admission control, and cluster governance will be covered in the future. Stay tuned! \ No newline at end of file +This end our tour in Capsule use cases. As we improve Capsule, more use cases about multi-tenancy, policy admission control, and cluster governance will be covered in the future. Stay tuned! diff --git a/docs/operator/use-cases/nodes-pool.md b/docs/operator/use-cases/nodes-pool.md index 0b1b1546..96855b9f 100644 --- a/docs/operator/use-cases/nodes-pool.md +++ b/docs/operator/use-cases/nodes-pool.md @@ -33,7 +33,7 @@ The Capsule controller makes sure that any namespace created in the tenant has t The effect is that all the pods deployed by Alice are placed only on the designated pool of nodes. -Any tentative of Alice to change the selector on the pods will result in the following error from +Any attempt of Alice to change the selector on the pods will result in the following error from the `PodNodeSelector` Admission Controller plugin: ``` diff --git a/docs/operator/use-cases/onboarding.md b/docs/operator/use-cases/onboarding.md index 0bcb81e5..bf7556e6 100644 --- a/docs/operator/use-cases/onboarding.md +++ b/docs/operator/use-cases/onboarding.md @@ -1,5 +1,5 @@ # Onboard a new tenant -Bill receives a new request from the Acme Corp.'s CTO asking a new tenant for Alice's organization has to be on board. Bill assigns the Alice's identity `alice` in the Acme Corp. identity management system. And because, Alice is a tenant owner, Bill needs to assign `alice` the Capsule group defined by `--capsule-user-group` option, which defaults to `capsule.clastix.io`. +Bill receives a new request from Acme Corp.'s CTO asking for a new tenant to be onboarded in Alice’s organization. Bill then assigns Alice's identity of `alice` in Acme Corp. identity management system. Since Alice is a tenant owner, Bill needs to assign `alice` the Capsule group defined by `--capsule-user-group` option, which defaults to `capsule.clastix.io`. To keep the things simple, we assume that Bill just creates a client certificate for authentication using X.509 Certificate Signing Request, so Alice's certificate has `"/CN=alice/O=capsule.clastix.io"`. @@ -17,7 +17,7 @@ spec: namespaceQuota: 3 ``` -Bill checks the new tenant is created and operational: +Bill checks if the new tenant is created and operational: ``` bill@caas# kubectl get tenant oil @@ -31,7 +31,7 @@ oil 9 0 alice User Once the new tenant `oil` is in place, Bill sends the login credentials to Alice. -Alice can log in to the CaaS platform and checks if she can create a namespace +Alice can log in to the CaaS platform and check if she can create a namespace ``` alice@caas# kubectl auth can-i create namespaces @@ -72,7 +72,7 @@ no ``` ## Assign a group of users as tenant owner -In the example above, Bill assigned the ownership of `oil` tenant to `alice` user. However, is more likely that multiple users in the Alice's oraganization, need to admin the `oil` tenant. In such cases, Bill can assign the ownership of the `oil` tenant to a group of users instead of a single one. +In the example above, Bill assigned the ownership of `oil` tenant to `alice` user. However, is more likely that multiple users in the Alice's organization, need to administer the `oil` tenant. In such cases, Bill can assign the ownership of the `oil` tenant to a group of users instead of a single one. Bill creates a new group account `oil` in the Acme Corp. identity management system and then he assigns Alice's identity `alice` to the `oil` group. diff --git a/docs/operator/use-cases/overview.md b/docs/operator/use-cases/overview.md index f3647dc2..f5ffe429 100644 --- a/docs/operator/use-cases/overview.md +++ b/docs/operator/use-cases/overview.md @@ -1,31 +1,31 @@ # Use cases for Capsule -Using Capsule, a cluster admin can implement complex multi-tenants scenarios for both public and private deployments. Here a list of common scenarios addressed by Capsule. +Using Capsule, a cluster admin can implement complex multi-tenant scenarios for both public and private deployments. Here a list of common scenarios addressed by Capsule. # Container as a Service (CaaS) -***Acme Corp***, our sample organization, built a Container as a Service platform (CaaS), based on Kubernetes, to serve multiple lines of business. Each line of business, has its own team of engineers that are responsible for development, deployment, and operating their digital products. +***Acme Corp***, our sample organization, built a Container as a Service platform (CaaS), based on Kubernetes to serve multiple lines of business. Each line of business, has its own team of engineers that are responsible for development, deployment, and operating their digital products. To simplify the usage of Capsule in this scenario, we'll work with the following actors: * ***Bill***: - he is the cluster administrator from the operations department of Acme Corp. and he is in charge of admin and maintains the CaaS platform. + he is the cluster administrator from the operations department of Acme Corp. and he is in charge of administration and maintains the CaaS platform. * ***Alice***: - she works as IT Project Leader at Oil & Gas Business Units, two new lines of business at Acme Corp. Alice is responsible for all the strategic IT projects and she is responsible also for a team made of different background (developers, administrators, SRE engineers, etc.) and organized in separate departments. - + she works as the IT Project Leader in the Oil & Gas Business Units. These are two new lines of business at Acme Corp. Alice is responsible for all the strategic IT projects in the two LOB's. She also is responsible for a team made of different job responsibilities (developers, administrators, SRE engineers, etc.) working in separate departments. + * ***Joe***: - he works at Acme Corp, as a lead developer of a distributed team in Alice's organization. - Joe is responsible for developing a mission-critical project in the Oil market. + he works at Acme Corp, as a lead developer of a distributed team in Alice's organization. Joe is responsible for developing a mission-critical project in the Oil market. * ***Bob***: - he is the head of Engineering for the main and historical line of business at Acme Corp, the Water Business Unit. He is responsible for development, deployment, and operating multiple digital products in production for a large set of customers. + + he is the head of Engineering for the Water Business Unit, the main and historical line of business at Acme Corp. He is responsible for development, deployment, and operating multiple digital products in production for a large set of customers. Bill, at Acme Corp. can use Capsule to address any of the following scenarios: -* [Onboard a New Tenant](./onboarding.md) +* [Onboard a new Tenant](./onboarding.md) * [Create Namespaces](./create-namespaces.md) * [Assign Permissions](./permissions.md) -* [Enforce Resource Quotas and Limits](./resources-quota-limits.md) -* [Assign a Node's Pool](./nodes-pool.md) +* [Enforce Resources Quotas and Limits](./resources-quota-limits.md) +* [Assign specific Node Pools](./nodes-pool.md) * [Assign Ingress Classes](./ingress-classes.md) * [Assign Ingress Hostnames](./ingress-hostnames.md) * [Assign Storage Classes](./storage-classes.md) @@ -34,10 +34,11 @@ Bill, at Acme Corp. can use Capsule to address any of the following scenarios: * [Assign Pod Security Policies](./pod-security-policies.md) * [Create Custom Resources](./custom-resources.md) * [Taint Namespaces](./taint-namespaces.md) -* [Assign Multiple Tenants to an Owner](./multiple-tenants.md) + +* [Assign multiple Tenants to an owner](./multiple-tenants.md) > NB: as we improve Capsule, more use cases about multi-tenancy and cluster governance will be covered. # What’s next -See how the cluster admin puts a new tenant onboard. [Onboard a new tenant](./onboarding.md). \ No newline at end of file +Now let's see how the cluster admin onboards a new tenant. [Onboarding a new tenant](./onboarding.md). diff --git a/docs/operator/use-cases/permissions.md b/docs/operator/use-cases/permissions.md index cac2b5f7..e97ee63f 100644 --- a/docs/operator/use-cases/permissions.md +++ b/docs/operator/use-cases/permissions.md @@ -3,9 +3,9 @@ Alice acts as the tenant admin. Other users can operate inside the tenant with d One of the key design principles of the Capsule is the self-provisioning management from the tenant owner's perspective. Alice, the tenant owner, does not need to interact with Bill, the cluster admin, to complete her day-by-day duties. On the other side, Bill has not to deal with multiple requests coming from multiple tenant owners that probably will overwhelm him. -Capsule leaves Alice the freedom to create RBAC roles at the namespace level, or using the pre-defined cluster roles already available in Kubernetes, and assign them to other users in the tenant. Being roles and rolebindings, limited to a namespace scope, Alice can assign the roles to the other users accessing the same tenant only after the namespace is created. This gives Alice the power to admin the tenant without the inteervention of the cluster admin. +Capsule leaves Alice the freedom to create RBAC roles at the namespace level, or using the pre-defined cluster roles already available in Kubernetes, and assign them to other users in the tenant. Since roles and rolebindings are limited to a namespace scope, Alice can assign the roles to the other users accessing the same tenant only after the namespace is created. This gives Alice the power to administer the tenant without the intervention of the cluster admin. -From the cluster admin perspective, the only required action to Bill is to provision the other identities, eg. `joe` in the Identity Management system of Acme Corp. But this task can be done once, when onboarding the tenant and the users accessing the tenant can be part of the tenant business profile. +From the cluster admin perspective, the only required action for Bill is to provision the other identities, eg. `joe` in the Identity Management system of Acme Corp. but this task can be done once, when onboarding the tenant and the users accessing the tenant can be part of the tenant business profile. Alice can create Roles and RoleBindings only in the namespaces she owns @@ -40,4 +40,4 @@ subjects: Joe now can operate on the namespace `oil-development` as admin but he has no access to the other namespaces `oil-production`, and `oil-test` that are part of the same tenant. # What’s next -See how Bill, the cluster admin, set resources quota and limits for Alice's tenant. [Enforce resources quota and limits](./resources-quota-limits.md). \ No newline at end of file +See how Bill, the cluster admin, set resources quota and limits for Alice's tenant. [Enforce resources quota and limits](./resources-quota-limits.md). diff --git a/docs/operator/use-cases/resources-quota-limits.md b/docs/operator/use-cases/resources-quota-limits.md index 0b7f0e1a..6ae91c08 100644 --- a/docs/operator/use-cases/resources-quota-limits.md +++ b/docs/operator/use-cases/resources-quota-limits.md @@ -1,5 +1,5 @@ # Enforce resources quota and limits -With help of Capsule, Bill, the cluster admin, can set and enforce resources quota and limits for the Alice's tenant +With help of Capsule, Bill and the cluster admin can set and enforce resources quota and limits for the Alice's tenant ```yaml apiVersion: capsule.clastix.io/v1alpha1 @@ -199,7 +199,7 @@ PersistentVolumeClaim storage 1Gi 10Gi - - - Being the limit range specific of single resources, there is no aggregate to count. -Having access to resource quota and limits, however, Alice is not able to change or delete it according to the assigned RBAC profile. +Having access to resource quotas and limits, Alice still doesn't have permissions to change or delete the resources according to the assigned RBAC profile. ``` alice@caas# kubectl -n oil-production auth can-i patch resourcequota diff --git a/docs/operator/use-cases/storage-classes.md b/docs/operator/use-cases/storage-classes.md index 58a28ef3..6c7ed473 100644 --- a/docs/operator/use-cases/storage-classes.md +++ b/docs/operator/use-cases/storage-classes.md @@ -17,7 +17,7 @@ spec: ... ``` -It is also possible to use regular expression for assigning Storage Classes: +It is also possible to use a regular expression for assigning Storage Classes: ```yaml apiVersion: capsule.clastix.io/v1alpha1 @@ -63,7 +63,7 @@ spec: storage: 12Gi ``` -Any tentative of Alice to use a not valid Storage Class, e.g. `default`, will fail:: +Any attempt of Alice to use a non valid Storage Class, e.g. `default`, will fail:: ``` Error from server: error when creating persistent volume claim pvc: admission webhook "pvc.capsule.clastix.io" denied the request: @@ -71,4 +71,4 @@ Storage Class default is forbidden for the current Tenant ``` # What’s next -See how Bill, the cluster admin, can assign Network Policies to Alice's tenant. [Assign Network Policies](./network-policies.md). \ No newline at end of file +See how Bill, the cluster admin, can assign Network Policies to Alice's tenant. [Assign Network Policies](./network-policies.md).