diff --git a/slides/containers/Dockerfile_Tips.md b/slides/containers/Dockerfile_Tips.md
index f30e55d1..fed55f49 100644
--- a/slides/containers/Dockerfile_Tips.md
+++ b/slides/containers/Dockerfile_Tips.md
@@ -76,6 +76,78 @@ CMD ["python", "app.py"]
---
+## Be careful with `chown`, `chmod`, `mv`
+
+* Layers cannot store efficiently changes in permissions or ownership.
+
+* Layers cannot represent efficiently when a file is moved either.
+
+* As a result, operations like `chown`, `chown`, `mv` can be expensive.
+
+* For instance, in the Dockerfile snippet below, each `RUN` line
+ creates a layer with an entire copy of `some-file`.
+
+ ```dockerfile
+ COPY some-file .
+ RUN chown www-data:www-data some-file
+ RUN chmod 644 some-file
+ RUN mv some-file /var/www
+ ```
+
+* How can we avoid that?
+
+---
+
+## Put files on the right place
+
+* Instead of using `mv`, directly put files at the right place.
+
+* When extracting archives (tar, zip...), merge operations in a single layer.
+
+ Example:
+
+ ```dockerfile
+ ...
+ RUN wget http://.../foo.tar.gz \
+ && tar -zxf foo.tar.gz \
+ && mv foo/fooctl /usr/local/bin \
+ && rm -rf foo
+ ...
+ ```
+
+---
+
+## Use `COPY --chown`
+
+* The Dockerfile instruction `COPY` can take a `--chown` parameter.
+
+ Examples:
+
+ ```dockerfile
+ ...
+ COPY --chown=1000 some-file .
+ COPY --chown=1000:1000 some-file .
+ COPY --chown=www-data:www-data some-file .
+ ```
+
+* The `--chown` flag can specify a user, or a user:group pair.
+
+* The user and group can be specified as names or numbers.
+
+* When using names, the names must exist in `/etc/passwd` or `/etc/group`.
+
+ *(In the container, not on the host!)*
+
+---
+
+## Set correct permissions locally
+
+* Instead of using `chmod`, set the right file permissions locally.
+
+* When files are copied with `COPY`, permissions are preserved.
+
+---
+
## Embedding unit tests in the build process
```dockerfile
diff --git a/slides/k8s/metrics-server.md b/slides/k8s/metrics-server.md
index e7e4189a..b0023ef6 100644
--- a/slides/k8s/metrics-server.md
+++ b/slides/k8s/metrics-server.md
@@ -59,7 +59,7 @@ If it shows our nodes and their CPU and memory load, we're good!
- Show resource usage across all containers:
```bash
- kuebectl top pods --containers --all-namespaces
+ kubectl top pods --containers --all-namespaces
```
]
diff --git a/slides/k8s/record.md b/slides/k8s/record.md
new file mode 100644
index 00000000..a76fc903
--- /dev/null
+++ b/slides/k8s/record.md
@@ -0,0 +1,169 @@
+# Recording deployment actions
+
+- Some commands that modify a Deployment accept an optional `--record` flag
+
+ (Example: `kubectl set image deployment worker worker=alpine --record`)
+
+- That flag will store the command line in the Deployment
+
+ (Technically, using the annotation `kubernetes.io/change-cause`)
+
+- It gets copied to the corresponding ReplicaSet
+
+ (Allowing to keep track of which command created or promoted this ReplicaSet)
+
+- We can view this information with `kubectl rollout history`
+
+---
+
+## Using `--record`
+
+- Let's make a couple of changes to a Deployment and record them
+
+.exercise[
+
+- Roll back `worker` to image version 0.1:
+ ```bash
+ kubectl set image deployment worker worker=dockercoins/worker:v0.1 --record
+ ```
+
+- Promote it to version 0.2 again:
+ ```bash
+ kubectl set image deployment worker worker=dockercoins/worker:v0.2 --record
+ ```
+
+- View the change history:
+ ```bash
+ kubectl rollout history deployment worker
+ ```
+
+]
+
+---
+
+## Pitfall #1: forgetting `--record`
+
+- What happens if we don't specify `--record`?
+
+.exercise[
+
+- Promote `worker` to image version 0.3:
+ ```bash
+ kubectl set image deployment worker worker=dockercoins/worker:v0.3
+ ```
+
+- View the change history:
+ ```bash
+ kubectl rollout history deployment worker
+ ```
+
+]
+
+--
+
+It recorded version 0.2 instead of 0.3! Why?
+
+---
+
+## How `--record` really works
+
+- `kubectl` adds the annotation `kubernetes.io/change-cause` to the Deployment
+
+- The Deployment controller copies that annotation to the ReplicaSet
+
+- `kubectl rollout history` shows the ReplicaSets' annotations
+
+- If we don't specify `--record`, the annotation is not updated
+
+- The previous value of that annotation is copied to the new ReplicaSet
+
+- In that case, the ReplicaSet annotation does not reflect reality!
+
+---
+
+## Pitfall #2: recording `scale` commands
+
+- What happens if we use `kubectl scale --record`?
+
+.exercise[
+
+- Check the current history:
+ ```bash
+ kubectl rollout history deployment worker
+ ```
+
+- Scale the deployment:
+ ```bash
+ kubectl scale deployment worker --replicas=3 --record
+ ```
+
+- Check the change history again:
+ ```bash
+ kubectl rollout history deployment worker
+ ```
+
+]
+
+--
+
+The last entry in the history was overwritten by the `scale` command! Why?
+
+---
+
+## Actions that don't create a new ReplicaSet
+
+- The `scale` command updates the Deployment definition
+
+- But it doesn't create a new ReplicaSet
+
+- Using the `--record` flag sets the annotation like before
+
+- The annotation gets copied to the existing ReplicaSet
+
+- This overwrites the previous annotation that was there
+
+- In that case, we lose the previous change cause!
+
+---
+
+## Updating the annotation directly
+
+- Let's see what happens if we set the annotation manually
+
+.exercise[
+
+- Annotate the Deployment:
+ ```bash
+ kubectl annotate deployment worker kubernetes.io/change-cause="Just for fun"
+ ```
+
+- Check that our annotation shows up in the change history:
+ ```bash
+ kubectl rollout history deployment worker
+ ```
+
+]
+
+--
+
+Our annotation shows up (and overwrote whatever was there before).
+
+---
+
+## Using change cause
+
+- It sounds like a good idea to use `--record`, but:
+
+ *"Incorrect documentation is often worse than no documentation."*
+
+ (Bertrand Meyer)
+
+- If we use `--record` once, we need to either:
+
+ - use it every single time after that
+
+ - or clear the Deployment annotation after using `--record`
+
+ (subsequent changes will show up with a `` change cause)
+
+- A safer way is to set it through our tooling
diff --git a/slides/k8s/rollout.md b/slides/k8s/rollout.md
index 958ad5e2..5783c020 100644
--- a/slides/k8s/rollout.md
+++ b/slides/k8s/rollout.md
@@ -265,6 +265,8 @@ Note the `3xxxx` port.
---
+class: extra-details
+
## Changing rollout parameters
- We want to:
@@ -294,6 +296,8 @@ spec:
---
+class: extra-details
+
## Applying changes through a YAML patch
- We could use `kubectl edit deployment worker`
diff --git a/slides/kube-fullday.yml b/slides/kube-fullday.yml
index e60f6184..0c60c85b 100644
--- a/slides/kube-fullday.yml
+++ b/slides/kube-fullday.yml
@@ -48,6 +48,7 @@ chapters:
- shared/hastyconclusions.md
- k8s/daemonset.md
- - k8s/rollout.md
+ #- k8s/record.md
- k8s/namespaces.md
#- k8s/kustomize.md
#- k8s/helm.md
diff --git a/slides/kube-halfday.yml b/slides/kube-halfday.yml
index 53bc677b..8d86a65e 100644
--- a/slides/kube-halfday.yml
+++ b/slides/kube-halfday.yml
@@ -51,6 +51,7 @@ chapters:
- shared/hastyconclusions.md
- k8s/daemonset.md
- k8s/rollout.md
+ #- k8s/record.md
- - k8s/logs-cli.md
# Bridget hasn't added EFK yet
#- k8s/logs-centralized.md
diff --git a/slides/kube-selfpaced.yml b/slides/kube-selfpaced.yml
index fc178e46..2c23b1d7 100644
--- a/slides/kube-selfpaced.yml
+++ b/slides/kube-selfpaced.yml
@@ -48,6 +48,7 @@ chapters:
# - shared/hastyconclusions.md
- k8s/daemonset.md
- k8s/rollout.md
+ - k8s/record.md
- k8s/namespaces.md
- - k8s/kustomize.md
- k8s/helm.md
diff --git a/slides/two.yml b/slides/two.yml
index 1d6bf72b..95249444 100644
--- a/slides/two.yml
+++ b/slides/two.yml
@@ -44,6 +44,7 @@ chapters:
- shared/hastyconclusions.md
- k8s/daemonset.md
- - k8s/rollout.md
+ - k8s/record.md
- k8s/logs-centralized.md
- k8s/ingress.md
# DAY 2