Update CRD section

This commit is contained in:
Jerome Petazzoni
2020-11-13 12:50:55 +01:00
parent b4c76ad11d
commit b5d3b213b1
2 changed files with 192 additions and 12 deletions

View File

@@ -187,7 +187,7 @@ Save this script as `/opt/cni/bin/debug` and make it executable.
❓️ What is calling our plugins?
---
???
:EN:- Deep dive into CNI internals
:FR:- La Container Network Interface (CNI) en détails

View File

@@ -14,9 +14,7 @@
## A very simple CRD
The YAML below describes a very simple CRD representing different kinds of coffee:
@@LINK[k8s/coffee-1.yaml]
The file @@LINK[k8s/coffee-1.yaml] describes a very simple CRD representing different kinds of coffee:
```yaml
@@INCLUDE[k8s/coffee-1.yaml]
@@ -81,7 +79,7 @@ spec:
]
- We can improve that, but it's outside the scope of this section!
- We'll see in a bit how to improve that
---
@@ -108,16 +106,180 @@ There are many possibilities!
---
## Little details
## What's next?
- Creating a basic CRD is quick and easy
- But there is a lot more that we can (and probably should) do:
- improve input with *data validation*
- improve output with *custom columns*
- And of course, we probably need a *controller* to go with our CRD!
(otherwise, we're just using the Kubernetes API as a fancy data store)
---
## Additional printer columns
- We can specify `additionalPrinterColumns` in the CRD
- This is similar to `-o custom-columns`
(map a column name to a path in the object, e.g. `.spec.taste`)
```yaml
additionalPrinterColumns:
- jsonPath: .spec.taste
description: Subjective taste of that kind of coffee bean
name: Taste
type: string
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
```
---
## Using additional printer columns
- Let's update our CRD using @@LINK[k8s/coffee-3.yaml]
.exercise[
- Update the CRD:
```bash
kubectl apply -f ~/container.training/k8s/coffee-3.yaml
```
- Look at our Coffee resources:
```bash
kubectl get coffees
```
]
Note: we can update a CRD without having to re-create the corresponding resources.
(Good news, right?)
---
## Data validation
- By default, CRDs are not *validated*
(we can put anything we want in the `spec`)
- When creating a CRD, we can pass an OpenAPI v3 schema (BETA!)
- When creating a CRD, we can pass an OpenAPI v3 schema
(which will then be used to validate resources)
- More advanced validation can also be done with admission webhooks, e.g.:
- consistency between parameters
- advanced integer filters (e.g. odd number of replicas)
- things that can change in one direction but not the other
---
## OpenAPI v3 scheme exapmle
This is what we have in @@INC[k8s/coffee-3.yaml]:
```yaml
schema:
openAPIV3Schema:
type: object
required: [ spec ]
properties:
spec:
type: object
properties:
taste:
description: Subjective taste of that kind of coffee bean
type: string
required: [ taste ]
```
---
## Validation *a posteriori*
- Some of the "coffees" that we defined earlier *do not* pass validation
- How is that possible?
--
- Validation happens at *admission*
(when resources get written into the database)
- Therefore, we can have "invalid" resources in etcd
(they are invalid from the CRD perspective, but the CRD can be changed)
🤔 How should we handle that ?
---
## Versions
- If the data format changes, we can roll out a new version of the CRD
(e.g. go from `v1alpha1` to `v1alpha2`)
- In a CRD we can specify the versions that exist, that are *served*, and *stored*
- multiple versions can be *served*
- only one can be *stored*
- Kubernetes doesn't automatically migrate the content of the database
- However, it can convert between versions when resources are read/written
---
## Conversion
- When *creating* a new resource, the *stored* version is used
(if we create it with another version, it gets converted)
- When *getting* or *watching* resources, the *requested* version is used
(if it is stored with another version, it gets converted)
- By default, "conversion" only changes the `apiVersion` field
- ... But we can register *conversion webhooks*
(see [that doc page](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definition-versioning/#webhook-conversion) for details)
---
## Migrating database content
- We need to *serve* a version as long as we *store* objects in that version
(=as long as the database has at least one object with that version)
- If we want to "retire" a version, we need to migrate these objects first
- All we have to do is to read and re-write them
(the [kube-storage-version-migrator](https://github.com/kubernetes-sigs/kube-storage-version-migrator) tool can help)
---
## What's next?
- Generally, when creating a CRD, we also want to run a *controller*
(otherwise nothing will happen when we create resources of that type)
@@ -126,11 +288,29 @@ There are many possibilities!
(and take action when they are created/updated)
*
Examples:
[YAML to install the gitkube CRD](https://storage.googleapis.com/gitkube/gitkube-setup-stable.yaml),
[YAML to install a redis operator CRD](https://github.com/amaizfinance/redis-operator/blob/master/deploy/crds/k8s_v1alpha1_redis_crd.yaml)
*
---
## CRDs in the wild
- [gitkube](https://storage.googleapis.com/gitkube/gitkube-setup-stable.yaml)
- [A redis operator](https://github.com/amaizfinance/redis-operator/blob/master/deploy/crds/k8s_v1alpha1_redis_crd.yaml)
- [cert-manager](https://github.com/jetstack/cert-manager/releases/download/v1.0.4/cert-manager.yaml)
*How big are these YAML files?*
*What's the size (e.g. in lines) of each resource?*
---
## CRDs in practice
- Production-grade CRDs can be extremely verbose
(because of the openAPI schema validation)
- This can (and usually will) be managed by a framework
---