Updating docs (#48)

* update documents to fix #38

* resolve comments

Co-authored-by: Dario Tranchitella <dario@tranchitella.eu>
This commit is contained in:
Adriano Pezzuto
2020-08-11 08:52:36 +02:00
committed by GitHub
co-authored by Dario Tranchitella
parent 1767bcee12
commit 7661bbb0ad
3 changed files with 461 additions and 461 deletions
+85 -83
View File
@@ -1,15 +1,43 @@
# ![icon](assets/logo/space-capsule3.png) Capsule
# Capsule
# A Kubernetes multi-tenant operator
<p align="center">
<img src="assets/logo/space-capsule3.png" />
</p>
This project aims to provide a custom operator for implementing a strong
multi-tenant environment in _Kubernetes_, especially suited for public
_Container-as-a-Service_ (CaaS) platforms.
<p align="center">
<img src="https://img.shields.io/github/license/clastix/capsule"/>
<img src="https://img.shields.io/github/go-mod/go-version/clastix/capsule"/>
<a href="https://github.com/clastix/capsule/releases">
<img src="https://img.shields.io/github/v/release/clastix/capsule"/>
</a>
</p>
---
# A multi-tenant operator for Kubernetes
This project provides a custom operator for implementing a strong
multi-tenant environment in _Kubernetes_. **Capsule** is not intended to be yet another _PaaS_, instead, it has been designed as a lightweight tool with a minimalist approach leveraging only the standard features of upstream Kubernetes.
# Which is the problem to solve?
Kubernetes introduced the _namespace_ resource to create logical partitions of the
cluster. A Kubernetes namespace creates a sort of isolated *slice* in the
cluster: _Network and Security Policies_, _Resource Quota_, _Limit Ranges_, and
_RBAC_ can be used to enforce isolation among different namespaces. Namespace isolation shines when Kubernetes is used to isolate the different environments or the different types of applications. Also, it works well to isolate applications serving different users when implementing the SaaS delivery model.
However, implementing advanced multi-tenancy scenarios, for example, a private or public _Container-as-a-Service_ platform, it becomes soon complicated because of the flat structure of Kubernetes namespaces. In such scenarios, different groups of users get assigned a pool of namespaces with a limited amount of resources (e.g.: _nodes_, _vCPU_, _RAM_, _ephemeral and persistent storage_). When users need more namespaces or move resources from one namespace to another, they always need the intervention of the cluster admin because each namespace still works as an isolated environment. To work around this, and not being overwhelmed by continuous users' requests, cluster admins often choose to create multiple smaller clusters and assign a dedicated cluster to each organization or group of users leading to the well know and painful phenomena of the _clusters sprawl_.
**Capsule** takes a different approach. It aggregates multiple namespaces assigned to an organization or group of users in a lightweight abstraction called _Tenant_. Within each tenant, users are free to create their namespaces and share all the assigned resources between the namespaces of the tenant. The _Network and Security Policies_, _Resource Quota_, _Limit Ranges_, _RBAC_, and other constraints defined at the tenant level are automatically inherited by all the namespaces in the tenant leaving the tenant's users to freely allocate resources without any intervention of the cluster administrator.
# Use cases for Capsule
Please, refer to the corresponding [section](use_cases.md) for a more detailed list of use cases that Capsule can address.
# Installation
Ensure you have `kubectl` and [`kustomize`](https://github.com/kubernetes-sigs/kustomize)
installed in your `PATH`. Also, make sure you have access to a Kubernetes cluster as an administrator.
Ensure you have [`kustomize`](https://github.com/kubernetes-sigs/kustomize)
installed in your `PATH`:
Clone this repository and move to the repo folder:
```
make deploy
@@ -34,97 +62,60 @@ make deploy
# validatingwebhookconfiguration.admissionregistration.k8s.io/capsule-validating-webhook-configuration created
```
## Webhooks and CA Bundle
Log verbosity of the Capsule controller can be increased by passing the `--zap-log-level` option with a value from `1` to `10` or the [basic keywords](https://godoc.org/go.uber.org/zap/zapcore#Level) although it is suggested to use the `--zap-devel` flag to get also stack traces.
Capsule is leveraging Kubernetes Multi-Tenant capabilities using the
[Dynamic Admission Controller](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/),
providing callbacks to add further validation or resource patching.
## Admission Controllers
Capsule implements Kubernetes multi-tenancy capabilities using a minimum set of standard [Admission Controllers](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/) enabled on the Kubernetes APIs server: `--enable-admission-plugins=PodNodeSelector,LimitRanger,ResourceQuota,MutatingAdmissionWebhook,ValidatingAdmissionWebhook`. In addition to these default controllers, Capsule implements its own set of Admission Controllers through the [Dynamic Admission Controller](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/), providing callbacks to add further validation or resource patching.
All this requests must be server via HTTPS and a CA must be provided to ensure that
the API Server is communicating with the right client.
Capsule upon installation is setting its custom Certificate Authority as
client certificate as well, updating all the required resources to minimize
the operational tasks.
All these requests must be served via HTTPS and a CA must be provided to ensure that
the API Server is communicating with the right client. Capsule upon installation is setting its custom Certificate Authority as a client certificate as well, updating all the required resources to minimize the operational tasks.
## Tenant users
Each tenant comes with a delegated user acting as the tenant admin. In the Capsule jargon, this user is called the _Tenant Owner_. Other users can operate inside a tenant with different levels of permissions and authorizations assigned directly by the Tenant owner.
All Tenant owner needs to be granted with a X.509 certificate with
`capsule.clastix.io` as _Organization_.
Capsule does not care about the authentication strategy used in the cluster and all the Kubernetes methods of [authentication](https://kubernetes.io/docs/reference/access-authn-authz/authentication/) are supported. The only requirement to use Capsule is to assign tenant users to the `capsule.clastix.io` group.
> the [hack/create-user.sh](hack/create-user.sh) can help you setting up a
> dummy kubeconfig
>
> ```
> #. /create-user.sh alice oil
> creating certs in TMPDIR /tmp/tmp.4CLgpuime3
> Generating RSA private key, 2048 bit long modulus (2 primes)
> ............+++++
> ........................+++++
> e is 65537 (0x010001)
> certificatesigningrequest.certificates.k8s.io/alice-oil created
> certificatesigningrequest.certificates.k8s.io/alice-oil approved
> kubeconfig file is: alice-oil.kubeconfig
> to use it as alice export KUBECONFIG=alice-oil.kubeconfig
> ```
Assignment to a group depends on the authentication strategy in your cluster. For example, users authenticated through a _X.509_ certificate must have `capsule.clastix.io` as _Organization_: `-subj "/CN=${USER}/O=capsule.clastix.io"`
Users authenticated through an _OIDC token_ must have
```json
...
"users_groups": [
"/capsule.clastix.io",
"other_group"
]
```
in their token.
The [hack/create-user.sh](hack/create-user.sh) can help you set up a dummy `kubeconfig` for the `alice` user acting as owner of a tenant called `oil`
```bash
./hack/create-user.sh alice oil
creating certs in TMPDIR /tmp/tmp.4CLgpuime3
Generating RSA private key, 2048 bit long modulus (2 primes)
............+++++
........................+++++
e is 65537 (0x010001)
certificatesigningrequest.certificates.k8s.io/alice-oil created
certificatesigningrequest.certificates.k8s.io/alice-oil approved
kubeconfig file is: alice-oil.kubeconfig
to use it as alice export KUBECONFIG=alice-oil.kubeconfig
```
## How to create a Tenant
Use the [scaffold Tenant](config/samples/capsule_v1alpha1_tenant.yaml)
and simply apply as Cluster Admin.
```
# kubectl apply -f config/samples/capsule_v1alpha1_tenant.yaml
kubectl apply -f config/samples/capsule_v1alpha1_tenant.yaml
tenant.capsule.clastix.io/oil created
```
The related Tenant owner can create Namespaces according to their quota:
happy Kubernetes cluster administration!
# Which is the problem to solve?
Kubernetes uses _Namespace_ resources to create logical partitions of the
cluster. A Kubernetes namespace provides the scope for some kind of resources
in the cluster. Users interacting with one namespace do not see the content in
another Namespace.
Kubernetes comes with few Namespace resources and leave the administrator to
create further namespaces in order to create sort of isolated *slices* of the
cluster: _Network and Security Policies_, _Resource Quota_, _Limit Ranges_, and
_RBAC_ are used to enforce isolation among namespaces.
Namespace isolation shines when Kubernetes is used as an enterprise container
platform, for example, to isolate the production environment from the
development and/or to isolate different types of applications.
Also it works well to isolate applications serving different users when
implementing the SaaS business model.
When implementing a public _CaaS_ platform, the flat namespace structure in
Kubernetes shows its main limitations. In this model, each new user receives
their own namespace where to deploy workloads. The user buys a limited amount
of resources (e.g.: _vCPU_, _RAM_, _ephemeral and persistent storage_) and
cannot use more than that.
If the user needs for multiple namespaces, they can buy other namespaces.
However, resources cannot shared easily between namespaces which still work as
fully isolated environments.
_Capsule_ aggregates multiple namespaces belonging to the same user by leaving
the user to freely share resources among all their namespaces.
All the constraints, defined by _Network and Security Policies_,
_Resource Quota_, _Limit Ranges_, and RBAC can be freely shared between
namespaces in a fully self-provisioning fashion without any intervention of the
cluster admin.
# Use cases for Capsule
Please refer to the corresponding [section](use_cases.md)
# How to contribute
Please refer to the corresponding [section](contributing.md)
The related Tenant owner `alice` can create Namespaces according to their assigned quota: happy Kubernetes cluster administration!
# Removal
Similar to `deploy`, you can get rid of Capsule using the `remove` target.
```
@@ -149,6 +140,17 @@ make remove
# validatingwebhookconfiguration.admissionregistration.k8s.io "capsule-validating-webhook-configuration" deleted
```
# Production Grade status
# How to contribute
Any contribution is welcome! Please refer to the corresponding [section](contributing.md).
Capsule is still in an _alpha_ stage, so **don't use it in production**!
# Production Grade
Capsule is still in an _alpha_ stage, so **don't use it in production!**
# FAQ
tbd
# Changelog
tbd
# Roadmap
tbd
+16 -16
View File
@@ -1,8 +1,8 @@
# How to contribute to Capsule
First, thanks for your interest on Capsule, any contribution is welcome!
First, thanks for your interest in Capsule, any contribution is welcome!
The first step is to setup your local development environment
The first step is to set up your local development environment
## Setting up the development environment
@@ -18,7 +18,7 @@ The following dependencies are mandatory:
### Installing Go dependencies
After cloning Capsule on any folder, access it and issue the following command
to ensure all dependencies are properly download.
to ensure all dependencies are properly downloaded.
```
go mod download
@@ -39,11 +39,11 @@ binaries available from the _Releases_ GitHub page and place them into the
### Installing KinD
Capsule is able to run on any certified Kubernetes installation and locally
Capsule can run on any certified Kubernetes installation and locally
the whole development is performed on _KinD_, also knows as
[Kubernetes in Docker](https://github.com/kubernetes-sigs/kind).
> N.B.: Docker is hard requirement since it's based on it
> N.B.: Docker is a hard requirement since it's based on it
According to your operative system and architecture, download the right binary
and place it on your `PATH`.
@@ -171,10 +171,11 @@ I0803 15:16:02.042022 1 main.go:281] Starting TCP socket on 0.0.0.0:8443
I0803 15:16:02.042364 1 main.go:288] Listening securely on 0.0.0.0:8443
```
Since Capsule is built using _OperatorSDK_, logging is handled by the `zap`
module: verbosity increase can be controlled using the CLI flag `--zap-level`
with a value from `1` to `10` or the [basic keywords](https://godoc.org/go.uber.org/zap/zapcore#Level)
although is suggested to use the `zap-devel` flag to get also stacktraces.
Since Capsule is built using _OperatorSDK_, logging is handled by the zap
module: log verbosity of the Capsule controller can be increased by passing
the `--zap-log-level` option with a value from `1` to `10` or the
[basic keywords](https://godoc.org/go.uber.org/zap/zapcore#Level) although
it is suggested to use the `--zap-devel` flag to get also stack traces.
> CA generation
>
@@ -217,7 +218,7 @@ kubectl -n capsule-system get secret capsule-tls -o jsonpath='{.data.tls\.key}'
#### Starting NGROK
In another session we need a `ngrok` session, mandatory to debug also webhooks
In another session, we need a `ngrok` session, mandatory to debug also webhooks
(YMMV).
```
@@ -271,7 +272,7 @@ webhooks:
#### Run Capsule
Finally, it's time to run locally Capsule using your preferred IDE (or not):
from the project root path you can issue the following command.
from the project root path, you can issue the following command.
```
make run
@@ -296,7 +297,7 @@ golangci-lint run
### goimports
Also the Go import statements must be sorted following the best practice:
Also, the Go import statements must be sorted following the best practice:
```
<STANDARD LIBRARY>
@@ -315,10 +316,9 @@ goimports -w -l -local "github.com/clastix/capsule" .
### Commits
All the Pull Requests must reference to an already open issue: this is the
first phase to contribute also for informing maintainers about the issue.
All the Pull Requests must refer to an already open issue: this is the first phase to contribute also for informing maintainers about the issue.
Commit first line should not exceed 50 columns.
Commit's first line should not exceed 50 columns.
A commit description is welcomed to explain more the changes: just ensure
to put a blank line and an arbitrary number of maximum 72 characters long
@@ -328,4 +328,4 @@ Please, split changes into several and documented small commits: this will help
us to perform a better review.
> In case of errors or need of changes to previous commits,
> fix them squashing in order to make changes atomic.
> fix them squashing to make changes atomic.
+360 -362
View File
File diff suppressed because it is too large Load Diff