diff --git a/slides/k8s/cni-internals.md b/slides/k8s/cni-internals.md index c9bee582..726fc67c 100644 --- a/slides/k8s/cni-internals.md +++ b/slides/k8s/cni-internals.md @@ -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 diff --git a/slides/k8s/crd.md b/slides/k8s/crd.md index 9d1b5522..5f086eea 100644 --- a/slides/k8s/crd.md +++ b/slides/k8s/crd.md @@ -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 ---