From 2ce50007d20e6d00cd458f6e598ddb366ded445b Mon Sep 17 00:00:00 2001 From: Bret Fisher Date: Mon, 16 Mar 2020 17:57:41 -0400 Subject: [PATCH 01/15] update k8s dashboard versions --- k8s/insecure-dashboard.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/k8s/insecure-dashboard.yaml b/k8s/insecure-dashboard.yaml index ebf49362..f1ed0ee1 100644 --- a/k8s/insecure-dashboard.yaml +++ b/k8s/insecure-dashboard.yaml @@ -187,7 +187,7 @@ spec: spec: containers: - name: kubernetes-dashboard - image: kubernetesui/dashboard:v2.0.0-rc2 + image: kubernetesui/dashboard:v2.0.0-rc6 imagePullPolicy: Always ports: - containerPort: 8443 @@ -272,7 +272,7 @@ spec: spec: containers: - name: dashboard-metrics-scraper - image: kubernetesui/metrics-scraper:v1.0.2 + image: kubernetesui/metrics-scraper:v1.0.3 ports: - containerPort: 8000 protocol: TCP From b0bff595cf002be223ba9cf283f4a040023a46ec Mon Sep 17 00:00:00 2001 From: Guilhem Lettron Date: Wed, 29 Apr 2020 22:31:49 +0200 Subject: [PATCH 02/15] psp: update generator helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit kubectl run → kubectl create deployment kubectl run --restart=Never → kubectl run --- slides/k8s/podsecuritypolicy.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/slides/k8s/podsecuritypolicy.md b/slides/k8s/podsecuritypolicy.md index 8e0e9a0c..b15a6d3b 100644 --- a/slides/k8s/podsecuritypolicy.md +++ b/slides/k8s/podsecuritypolicy.md @@ -280,14 +280,14 @@ - Try to create a Pod directly: ```bash - kubectl run testpsp1 --image=nginx --restart=Never + kubectl run testpsp1 --image=nginx ``` - Try to create a Deployment: ```bash - kubectl run testpsp2 --image=nginx + kubectl create deployment testpsp2 --image=nginx ``` - Look at existing resources: @@ -345,12 +345,12 @@ We can get hints at what's happening by looking at the ReplicaSet and Events. - Check that we can now create a Pod directly: ```bash - kubectl run testpsp3 --image=nginx --restart=Never + kubectl run testpsp3 --image=nginx ``` - Create a Deployment as well: ```bash - kubectl run testpsp4 --image=nginx + kubectl create deployment testpsp4 --image=nginx ``` - Confirm that the Deployment is *not* creating any Pods: From a6c7d699865597bfc8dcaeafd9543864deee97f9 Mon Sep 17 00:00:00 2001 From: Guilhem Lettron Date: Wed, 29 Apr 2020 22:37:49 +0200 Subject: [PATCH 03/15] volume: add missing pod nginx-with-init creating --- slides/k8s/volumes.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/slides/k8s/volumes.md b/slides/k8s/volumes.md index 2870877b..a5a9c730 100644 --- a/slides/k8s/volumes.md +++ b/slides/k8s/volumes.md @@ -417,6 +417,11 @@ spec: .exercise[ +- Create the pod: + ```bash + kubectl create -f ~/container.training/k8s/nginx-4-with-init.yaml + ``` + - Repeat the same operation as earlier (try to send HTTP requests as soon as the pod comes up) From 7402c8e6a86c3fc373a77042be304c739f9110f0 Mon Sep 17 00:00:00 2001 From: Guilhem Lettron Date: Wed, 29 Apr 2020 22:46:33 +0200 Subject: [PATCH 04/15] psp: update psp apiVersion to policy/v1beta1 --- k8s/psp-restricted.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/k8s/psp-restricted.yaml b/k8s/psp-restricted.yaml index a73e7049..962685d0 100644 --- a/k8s/psp-restricted.yaml +++ b/k8s/psp-restricted.yaml @@ -1,5 +1,5 @@ --- -apiVersion: extensions/v1beta1 +apiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata: annotations: From 0d6c364a959bc9075c6cc77c24ffbebc551c075b Mon Sep 17 00:00:00 2001 From: Jerome Petazzoni Date: Sun, 3 May 2020 13:40:01 +0200 Subject: [PATCH 05/15] Add MacPorts instructions for stern --- slides/k8s/logs-cli.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/slides/k8s/logs-cli.md b/slides/k8s/logs-cli.md index 288d929a..93485ab2 100644 --- a/slides/k8s/logs-cli.md +++ b/slides/k8s/logs-cli.md @@ -45,7 +45,7 @@ Exactly what we need! --- -## Installing Stern +## Checking if Stern is installed - Run `stern` (without arguments) to check if it's installed: @@ -57,7 +57,17 @@ Exactly what we need! stern pod-query [flags] ``` -- If it is not installed, the easiest method is to download a [binary release](https://github.com/wercker/stern/releases) +- If it's missing, let's see how to install it + +--- + +## Installing Stern + +- Stern is written in Go, and Go programs are usually shipped as a single binary + +- We just need to download that binary and put it in our `PATH`! + +- Binary releases are available [here](https://github.com/wercker/stern/releases) on GitHub - The following commands will install Stern on a Linux Intel 64 bit machine: ```bash @@ -66,7 +76,7 @@ Exactly what we need! sudo chmod +x /usr/local/bin/stern ``` -- On OS X, just `brew install stern` +- On macOS, we can also `brew install stern` or `port install stern` From af0762a0a20e4ffbb085b6201189e5731e260a2b Mon Sep 17 00:00:00 2001 From: Jerome Petazzoni Date: Sun, 3 May 2020 15:49:37 +0200 Subject: [PATCH 06/15] Remove ':' from file names Colons are not allowed in file names on Windows. Let's use something else instead. (Initially reported by @DenisBalan. This closes #549.) --- ...users:jean.doe.yaml => user=jean.doe.yaml} | 8 ++-- slides/k8s/csr-api.md | 48 +++++++++++++++---- 2 files changed, 42 insertions(+), 14 deletions(-) rename k8s/{users:jean.doe.yaml => user=jean.doe.yaml} (85%) diff --git a/k8s/users:jean.doe.yaml b/k8s/user=jean.doe.yaml similarity index 85% rename from k8s/users:jean.doe.yaml rename to k8s/user=jean.doe.yaml index ef96d39e..4789038d 100644 --- a/k8s/users:jean.doe.yaml +++ b/k8s/user=jean.doe.yaml @@ -8,24 +8,24 @@ metadata: apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - name: users:jean.doe + name: user=jean.doe rules: - apiGroups: [ certificates.k8s.io ] resources: [ certificatesigningrequests ] verbs: [ create ] - apiGroups: [ certificates.k8s.io ] - resourceNames: [ users:jean.doe ] + resourceNames: [ user=jean.doe ] resources: [ certificatesigningrequests ] verbs: [ get, create, delete, watch ] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: users:jean.doe + name: user=jean.doe roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: users:jean.doe + name: user=jean.doe subjects: - kind: ServiceAccount name: jean.doe diff --git a/slides/k8s/csr-api.md b/slides/k8s/csr-api.md index 47c83cac..fabf5c5f 100644 --- a/slides/k8s/csr-api.md +++ b/slides/k8s/csr-api.md @@ -132,11 +132,33 @@ For a user named `jean.doe`, we will have: - ServiceAccount `jean.doe` in Namespace `users` -- CertificateSigningRequest `users:jean.doe` +- CertificateSigningRequest `user=jean.doe` -- ClusterRole `users:jean.doe` giving read/write access to that CSR +- ClusterRole `user=jean.doe` giving read/write access to that CSR -- ClusterRoleBinding `users:jean.doe` binding ClusterRole and ServiceAccount +- ClusterRoleBinding `user=jean.doe` binding ClusterRole and ServiceAccount + +--- + +class: extra-details + +## About resource name constraints + +- Most Kubernetes identifiers and names are fairly restricted + +- They generally are DNS-1123 *labels* or *subdomains* (from [RFC 1123](https://tools.ietf.org/html/rfc1123)) + +- A label is lowercase letters, numbers, dashes; can't start or finish with a dash + +- A subdomain is one or multiple labels separated by dots + +- Some resources have more relaxed constraints, and can be "path segment names" + + (uppercase are allowed, as well as some characters like `#:?!,_`) + +- This includes RBAC objects (like Roles, RoleBindings...) and CSRs + +- See the [Identifiers and Names](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/architecture/identifiers.md) design document and the [Object Names and IDs](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#path-segment-names) documentation page for more details --- @@ -153,7 +175,7 @@ For a user named `jean.doe`, we will have: - Create the ServiceAccount, ClusterRole, ClusterRoleBinding for `jean.doe`: ```bash - kubectl apply -f ~/container.training/k8s/users:jean.doe.yaml + kubectl apply -f ~/container.training/k8s/user=jean.doe.yaml ``` ] @@ -195,7 +217,13 @@ For a user named `jean.doe`, we will have: - Add a new context using that identity: ```bash - kubectl config set-context jean.doe --user=token:jean.doe --cluster=kubernetes + kubectl config set-context jean.doe --user=token:jean.doe --cluster=`kubernetes` + ``` + (Make sure to adapt the cluster name if yours is different!) + +- Use that context: + ```bash + kubectl config use-context jean.doe ``` ] @@ -216,7 +244,7 @@ For a user named `jean.doe`, we will have: - Try to access "our" CertificateSigningRequest: ```bash - kubectl get csr users:jean.doe + kubectl get csr user=jean.doe ``` (This should tell us "NotFound") @@ -273,7 +301,7 @@ The command above generates: apiVersion: certificates.k8s.io/v1beta1 kind: CertificateSigningRequest metadata: - name: users:jean.doe + name: user=jean.doe spec: request: $(base64 -w0 < csr.pem) usages: @@ -324,12 +352,12 @@ The command above generates: - Inspect the CSR: ```bash - kubectl describe csr users:jean.doe + kubectl describe csr user=jean.doe ``` - Approve it: ```bash - kubectl certificate approve users:jean.doe + kubectl certificate approve user=jean.doe ``` ] @@ -347,7 +375,7 @@ The command above generates: - Retrieve the updated CSR object and extract the certificate: ```bash - kubectl get csr users:jean.doe \ + kubectl get csr user=jean.doe \ -o jsonpath={.status.certificate} \ | base64 -d > cert.pem ``` From efdcf4905d2ea9ee560ba995754542432bca46c0 Mon Sep 17 00:00:00 2001 From: Jerome Petazzoni Date: Sun, 3 May 2020 16:01:19 +0200 Subject: [PATCH 07/15] Bump up Kubernetes dashboard to 2.0.0 --- k8s/insecure-dashboard.yaml | 15 +- k8s/kubernetes-dashboard.yaml | 313 +++++++++++++++++++++++++--------- 2 files changed, 239 insertions(+), 89 deletions(-) diff --git a/k8s/insecure-dashboard.yaml b/k8s/insecure-dashboard.yaml index f1ed0ee1..373ec001 100644 --- a/k8s/insecure-dashboard.yaml +++ b/k8s/insecure-dashboard.yaml @@ -1,3 +1,10 @@ +# This file is based on the following manifest: +# https://github.com/kubernetes/dashboard/blob/master/aio/deploy/recommended.yaml +# It adds the "skip login" flag, as well as an insecure hack to defeat SSL. +# As its name implies, it is INSECURE and you should not use it in production, +# or on clusters that contain any kind of important or sensitive data, or on +# clusters that have a life span of more than a few hours. + # Copyright 2017 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -187,7 +194,7 @@ spec: spec: containers: - name: kubernetes-dashboard - image: kubernetesui/dashboard:v2.0.0-rc6 + image: kubernetesui/dashboard:v2.0.0 imagePullPolicy: Always ports: - containerPort: 8443 @@ -226,7 +233,7 @@ spec: emptyDir: {} serviceAccountName: kubernetes-dashboard nodeSelector: - "beta.kubernetes.io/os": linux + "kubernetes.io/os": linux # Comment the following tolerations if Dashboard must not be deployed on master tolerations: - key: node-role.kubernetes.io/master @@ -272,7 +279,7 @@ spec: spec: containers: - name: dashboard-metrics-scraper - image: kubernetesui/metrics-scraper:v1.0.3 + image: kubernetesui/metrics-scraper:v1.0.4 ports: - containerPort: 8000 protocol: TCP @@ -293,7 +300,7 @@ spec: runAsGroup: 2001 serviceAccountName: kubernetes-dashboard nodeSelector: - "beta.kubernetes.io/os": linux + "kubernetes.io/os": linux # Comment the following tolerations if Dashboard must not be deployed on master tolerations: - key: node-role.kubernetes.io/master diff --git a/k8s/kubernetes-dashboard.yaml b/k8s/kubernetes-dashboard.yaml index ee6977bf..b2e5802b 100644 --- a/k8s/kubernetes-dashboard.yaml +++ b/k8s/kubernetes-dashboard.yaml @@ -1,3 +1,6 @@ +# This is a copy of the following file: +# https://github.com/kubernetes/dashboard/blob/master/aio/deploy/recommended.yaml + # Copyright 2017 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,19 +15,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -# ------------------- Dashboard Secret ------------------- # - apiVersion: v1 -kind: Secret +kind: Namespace metadata: - labels: - k8s-app: kubernetes-dashboard - name: kubernetes-dashboard-certs - namespace: kube-system -type: Opaque + name: kubernetes-dashboard --- -# ------------------- Dashboard Service Account ------------------- # apiVersion: v1 kind: ServiceAccount @@ -32,62 +28,147 @@ metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard - namespace: kube-system + namespace: kubernetes-dashboard + +--- + +kind: Service +apiVersion: v1 +metadata: + labels: + k8s-app: kubernetes-dashboard + name: kubernetes-dashboard + namespace: kubernetes-dashboard +spec: + ports: + - port: 443 + targetPort: 8443 + selector: + k8s-app: kubernetes-dashboard + +--- + +apiVersion: v1 +kind: Secret +metadata: + labels: + k8s-app: kubernetes-dashboard + name: kubernetes-dashboard-certs + namespace: kubernetes-dashboard +type: Opaque + +--- + +apiVersion: v1 +kind: Secret +metadata: + labels: + k8s-app: kubernetes-dashboard + name: kubernetes-dashboard-csrf + namespace: kubernetes-dashboard +type: Opaque +data: + csrf: "" + +--- + +apiVersion: v1 +kind: Secret +metadata: + labels: + k8s-app: kubernetes-dashboard + name: kubernetes-dashboard-key-holder + namespace: kubernetes-dashboard +type: Opaque + +--- + +kind: ConfigMap +apiVersion: v1 +metadata: + labels: + k8s-app: kubernetes-dashboard + name: kubernetes-dashboard-settings + namespace: kubernetes-dashboard --- -# ------------------- Dashboard Role & Role Binding ------------------- # kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: - name: kubernetes-dashboard-minimal - namespace: kube-system + labels: + k8s-app: kubernetes-dashboard + name: kubernetes-dashboard + namespace: kubernetes-dashboard rules: - # Allow Dashboard to create 'kubernetes-dashboard-key-holder' secret. -- apiGroups: [""] - resources: ["secrets"] - verbs: ["create"] - # Allow Dashboard to create 'kubernetes-dashboard-settings' config map. -- apiGroups: [""] - resources: ["configmaps"] - verbs: ["create"] # Allow Dashboard to get, update and delete Dashboard exclusive secrets. -- apiGroups: [""] - resources: ["secrets"] - resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs"] - verbs: ["get", "update", "delete"] - # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map. -- apiGroups: [""] - resources: ["configmaps"] - resourceNames: ["kubernetes-dashboard-settings"] - verbs: ["get", "update"] - # Allow Dashboard to get metrics from heapster. -- apiGroups: [""] - resources: ["services"] - resourceNames: ["heapster"] - verbs: ["proxy"] -- apiGroups: [""] - resources: ["services/proxy"] - resourceNames: ["heapster", "http:heapster:", "https:heapster:"] - verbs: ["get"] + - apiGroups: [""] + resources: ["secrets"] + resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"] + verbs: ["get", "update", "delete"] + # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map. + - apiGroups: [""] + resources: ["configmaps"] + resourceNames: ["kubernetes-dashboard-settings"] + verbs: ["get", "update"] + # Allow Dashboard to get metrics. + - apiGroups: [""] + resources: ["services"] + resourceNames: ["heapster", "dashboard-metrics-scraper"] + verbs: ["proxy"] + - apiGroups: [""] + resources: ["services/proxy"] + resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"] + verbs: ["get"] --- + +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + labels: + k8s-app: kubernetes-dashboard + name: kubernetes-dashboard +rules: + # Allow Metrics Scraper to get metrics from the Metrics server + - apiGroups: ["metrics.k8s.io"] + resources: ["pods", "nodes"] + verbs: ["get", "list", "watch"] + +--- + apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: kubernetes-dashboard-minimal - namespace: kube-system + labels: + k8s-app: kubernetes-dashboard + name: kubernetes-dashboard + namespace: kubernetes-dashboard roleRef: apiGroup: rbac.authorization.k8s.io kind: Role - name: kubernetes-dashboard-minimal -subjects: -- kind: ServiceAccount name: kubernetes-dashboard - namespace: kube-system +subjects: + - kind: ServiceAccount + name: kubernetes-dashboard + namespace: kubernetes-dashboard + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: kubernetes-dashboard +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: kubernetes-dashboard +subjects: + - kind: ServiceAccount + name: kubernetes-dashboard + namespace: kubernetes-dashboard --- -# ------------------- Dashboard Deployment ------------------- # kind: Deployment apiVersion: apps/v1 @@ -95,7 +176,7 @@ metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard - namespace: kube-system + namespace: kubernetes-dashboard spec: replicas: 1 revisionHistoryLimit: 10 @@ -108,55 +189,117 @@ spec: k8s-app: kubernetes-dashboard spec: containers: - - name: kubernetes-dashboard - image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1 - ports: - - containerPort: 8443 - protocol: TCP - args: - - --auto-generate-certificates - # Uncomment the following line to manually specify Kubernetes API server Host - # If not specified, Dashboard will attempt to auto discover the API server and connect - # to it. Uncomment only if the default does not work. - # - --apiserver-host=http://my-address:port - volumeMounts: - - name: kubernetes-dashboard-certs - mountPath: /certs - # Create on-disk volume to store exec logs - - mountPath: /tmp - name: tmp-volume - livenessProbe: - httpGet: - scheme: HTTPS - path: / - port: 8443 - initialDelaySeconds: 30 - timeoutSeconds: 30 + - name: kubernetes-dashboard + image: kubernetesui/dashboard:v2.0.0 + imagePullPolicy: Always + ports: + - containerPort: 8443 + protocol: TCP + args: + - --auto-generate-certificates + - --namespace=kubernetes-dashboard + # Uncomment the following line to manually specify Kubernetes API server Host + # If not specified, Dashboard will attempt to auto discover the API server and connect + # to it. Uncomment only if the default does not work. + # - --apiserver-host=http://my-address:port + volumeMounts: + - name: kubernetes-dashboard-certs + mountPath: /certs + # Create on-disk volume to store exec logs + - mountPath: /tmp + name: tmp-volume + livenessProbe: + httpGet: + scheme: HTTPS + path: / + port: 8443 + initialDelaySeconds: 30 + timeoutSeconds: 30 + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsUser: 1001 + runAsGroup: 2001 volumes: - - name: kubernetes-dashboard-certs - secret: - secretName: kubernetes-dashboard-certs - - name: tmp-volume - emptyDir: {} + - name: kubernetes-dashboard-certs + secret: + secretName: kubernetes-dashboard-certs + - name: tmp-volume + emptyDir: {} serviceAccountName: kubernetes-dashboard + nodeSelector: + "kubernetes.io/os": linux # Comment the following tolerations if Dashboard must not be deployed on master tolerations: - - key: node-role.kubernetes.io/master - effect: NoSchedule + - key: node-role.kubernetes.io/master + effect: NoSchedule --- -# ------------------- Dashboard Service ------------------- # kind: Service apiVersion: v1 metadata: labels: - k8s-app: kubernetes-dashboard - name: kubernetes-dashboard - namespace: kube-system + k8s-app: dashboard-metrics-scraper + name: dashboard-metrics-scraper + namespace: kubernetes-dashboard spec: ports: - - port: 443 - targetPort: 8443 + - port: 8000 + targetPort: 8000 selector: - k8s-app: kubernetes-dashboard + k8s-app: dashboard-metrics-scraper + +--- + +kind: Deployment +apiVersion: apps/v1 +metadata: + labels: + k8s-app: dashboard-metrics-scraper + name: dashboard-metrics-scraper + namespace: kubernetes-dashboard +spec: + replicas: 1 + revisionHistoryLimit: 10 + selector: + matchLabels: + k8s-app: dashboard-metrics-scraper + template: + metadata: + labels: + k8s-app: dashboard-metrics-scraper + annotations: + seccomp.security.alpha.kubernetes.io/pod: 'runtime/default' + spec: + containers: + - name: dashboard-metrics-scraper + image: kubernetesui/metrics-scraper:v1.0.4 + ports: + - containerPort: 8000 + protocol: TCP + livenessProbe: + httpGet: + scheme: HTTP + path: / + port: 8000 + initialDelaySeconds: 30 + timeoutSeconds: 30 + volumeMounts: + - mountPath: /tmp + name: tmp-volume + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsUser: 1001 + runAsGroup: 2001 + serviceAccountName: kubernetes-dashboard + nodeSelector: + "kubernetes.io/os": linux + # Comment the following tolerations if Dashboard must not be deployed on master + tolerations: + - key: node-role.kubernetes.io/master + effect: NoSchedule + volumes: + - name: tmp-volume + emptyDir: {} From 40b2b8e62ea09f3175aa94bf6c3aec291ad02806 Mon Sep 17 00:00:00 2001 From: Jerome Petazzoni Date: Sun, 3 May 2020 16:53:21 +0200 Subject: [PATCH 08/15] Fix deployment name in labels/selector intro (Fixes #552) --- slides/k8s/labels-annotations.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slides/k8s/labels-annotations.md b/slides/k8s/labels-annotations.md index 790841ba..a295c289 100644 --- a/slides/k8s/labels-annotations.md +++ b/slides/k8s/labels-annotations.md @@ -26,12 +26,12 @@ - Create a Deployment: ```bash - kubectl create deployment web --image=nginx + kubectl create deployment clock --image=jpetazzo/clock ``` - Look at its annotations and labels: ```bash - kubectl describe deployment web + kubectl describe deployment clock ``` ] From ce4e2ffe46a35051e2517551e1ce3589a767ce3f Mon Sep 17 00:00:00 2001 From: Jerome Petazzoni Date: Sun, 3 May 2020 17:01:59 +0200 Subject: [PATCH 09/15] Add sleep command in init container example It can be tricky to illustrate what's going on here, since installing git and cloning the repo can be so fast. So we're sleeping a few seconds to help with this demo and make it easier to show the race condition. --- k8s/nginx-4-with-init.yaml | 2 +- slides/k8s/volumes.md | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/k8s/nginx-4-with-init.yaml b/k8s/nginx-4-with-init.yaml index d41ecd7a..c3023070 100644 --- a/k8s/nginx-4-with-init.yaml +++ b/k8s/nginx-4-with-init.yaml @@ -14,7 +14,7 @@ spec: initContainers: - name: git image: alpine - command: [ "sh", "-c", "apk add --no-cache git && git clone https://github.com/octocat/Spoon-Knife /www" ] + command: [ "sh", "-c", "apk add git && sleep 5 && git clone https://github.com/octocat/Spoon-Knife /www" ] volumeMounts: - name: www mountPath: /www/ diff --git a/slides/k8s/volumes.md b/slides/k8s/volumes.md index a5a9c730..8e408c2f 100644 --- a/slides/k8s/volumes.md +++ b/slides/k8s/volumes.md @@ -404,7 +404,7 @@ spec: initContainers: - name: git image: alpine - command: [ "sh", "-c", "apk add --no-cache git && git clone https://github.com/octocat/Spoon-Knife /www" ] + command: [ "sh", "-c", "apk add git && git clone https://github.com/octocat/Spoon-Knife /www" ] volumeMounts: - name: www mountPath: /www/ @@ -422,9 +422,7 @@ spec: kubectl create -f ~/container.training/k8s/nginx-4-with-init.yaml ``` -- Repeat the same operation as earlier - - (try to send HTTP requests as soon as the pod comes up) +- Try to send HTTP requests as soon as the pod comes up @@ -345,7 +345,7 @@ We can get hints at what's happening by looking at the ReplicaSet and Events. - Check that we can now create a Pod directly: ```bash - kubectl run testpsp3 --image=nginx + kubectl run testpsp3 --image=nginx --restart=Never ``` - Create a Deployment as well: From c31c81a286a8cb087187574f3335241a6a558ee2 Mon Sep 17 00:00:00 2001 From: Jerome Petazzoni Date: Mon, 4 May 2020 00:54:34 +0200 Subject: [PATCH 11/15] Allow overriding YAML desc through env vars --- slides/markmaker.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/slides/markmaker.py b/slides/markmaker.py index 5e2b20ca..00ea6be2 100755 --- a/slides/markmaker.py +++ b/slides/markmaker.py @@ -89,6 +89,11 @@ def flatten(titles): def generatefromyaml(manifest, filename): manifest = yaml.safe_load(manifest) + for k in manifest: + override = os.environ.get("OVERRIDE_"+k) + if override: + manifest[k] = override + if "zip" not in manifest: if manifest["slides"].endswith('/'): manifest["zip"] = manifest["slides"] + "slides.zip" From 8d98431ba032394dd66f6e57f26173057b9c8868 Mon Sep 17 00:00:00 2001 From: Jerome Petazzoni Date: Mon, 4 May 2020 02:09:00 +0200 Subject: [PATCH 12/15] Add Helm graduation status --- slides/k8s/helm-intro.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/slides/k8s/helm-intro.md b/slides/k8s/helm-intro.md index e98cd8a9..2db93989 100644 --- a/slides/k8s/helm-intro.md +++ b/slides/k8s/helm-intro.md @@ -18,6 +18,25 @@ --- +## CNCF graduation status + +- On April 30th 2020, Helm was the 10th project to *graduate* within the CNCF + + .emoji[🎉] + + (alongside Containerd, Prometheus, and Kubernetes itself) + +- This is an acknowledgement by the CNCF for projects that + + *demonstrate thriving adoption, an open governance process, +
+ and a strong commitment to community, sustainability, and inclusivity.* + +- See [CNCF announcement](https://www.cncf.io/announcement/2020/04/30/cloud-native-computing-foundation-announces-helm-graduation/) + and [Helm announcement](https://helm.sh/blog/celebrating-helms-cncf-graduation/) + +--- + ## Helm concepts - `helm` is a CLI tool From 1bbfba0531980cde0a9e6f9a08d38001046af07f Mon Sep 17 00:00:00 2001 From: Jerome Petazzoni Date: Mon, 4 May 2020 02:18:05 +0200 Subject: [PATCH 13/15] Add definition of idempotent --- slides/k8s/helm-create-better-chart.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/slides/k8s/helm-create-better-chart.md b/slides/k8s/helm-create-better-chart.md index a96d46dc..992f7fd2 100644 --- a/slides/k8s/helm-create-better-chart.md +++ b/slides/k8s/helm-create-better-chart.md @@ -121,7 +121,7 @@ This creates a basic chart in the directory `helmcoins`. helm install COMPONENT-NAME CHART-DIRECTORY ``` -- We can also use the following command, which is idempotent: +- We can also use the following command, which is *idempotent*: ```bash helm upgrade COMPONENT-NAME CHART-DIRECTORY --install ``` @@ -139,6 +139,28 @@ This creates a basic chart in the directory `helmcoins`. --- +class: extra-details + +## "Idempotent" + +- Idempotent = that can be applied multiple times without changing the result + + (the word is commonly used in maths and computer science) + +- In this context, this means: + + - if the action (installing the chart) wasn't done, do it + + - if the action was already done, don't do anything + +- Ideally, when such an action fails, it can be retried safely + + (as opposed to, e.g., installing a new release each time we run it) + +- Other example: `kubectl -f some-file.yaml` + +--- + ## Checking what we've done - Let's see if DockerCoins is working! From 5a24df3fd44f9649a8581d19cd2080f24027cace Mon Sep 17 00:00:00 2001 From: Jerome Petazzoni Date: Mon, 4 May 2020 16:25:35 +0200 Subject: [PATCH 14/15] Add details on Kustomize --- slides/k8s/kustomize.md | 212 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 193 insertions(+), 19 deletions(-) diff --git a/slides/k8s/kustomize.md b/slides/k8s/kustomize.md index 84fa9d19..db3dd89d 100644 --- a/slides/k8s/kustomize.md +++ b/slides/k8s/kustomize.md @@ -8,45 +8,164 @@ - They are left untouched by Kustomize -- Kustomize lets us define *overlays* that extend or change the resource files +- Kustomize lets us define *kustomizations* + +- A *kustomization* is conceptually similar to a *layer* + +- Technically, a *kustomization* is a file named `kustomization.yaml` + + (or a directory containing that files + additional files) --- -## Differences with Helm +## What's in a kustomization -- Helm charts use placeholders `{{ like.this }}` +- A kustomization can do any combination of the following: -- Kustomize "bases" are standard Kubernetes YAML + - include other kustomizations -- It is possible to use an existing set of YAML as a Kustomize base + - include Kubernetes resources defined in YAML files -- As a result, writing a Helm chart is more work ... + - patch Kubernetes resources (change values) -- ... But Helm charts are also more powerful; e.g. they can: + - add labels or annotations to all resources - - use flags to conditionally include resources or blocks + - specify ConfigMaps and Secrets from literal values or local files - - check if a given Kubernetes API group is supported - - - [and much more](https://helm.sh/docs/chart_template_guide/) +(... And a few more advanced features that we won't cover today!) --- -## Kustomize concepts +## A simple kustomization -- Kustomize needs a `kustomization.yaml` file +This features a Deployment, Service, and Ingress (in separate files), +and a couple of patches (to change the number of replicas and the hostname +used in the Ingress). -- That file can be a *base* or a *variant* +```yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +patchesStrategicMerge: +- scale-deployment.yaml +- ingress-hostname.yaml +resources: +- deployment.yaml +- service.yaml +- ingress.yaml +``` -- If it's a *base*: +On the next slide, let's see a more complex example ... - - it lists YAML resource files to use +--- -- If it's a *variant* (or *overlay*): +```yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +commonLabels: + add-this-to-all-my-resources: please +patchesStrategicMerge: +- prod-scaling.yaml +- prod-healthchecks.yaml +bases: +- api/ +- frontend/ +- db/ +- github.com/example/app?ref=tag-or-branch +resources: +- ingress.yaml +- permissions.yaml +configMapGenerator: +- name: appconfig + files: + - global.conf + - local.conf=prod.conf +``` - - it refers to (at least) one *base* +--- - - and some *patches* +## Glossary + +- A *base* is a kustomization that is referred to by other kustomizations + +- An *overlay* is a kustomization that refers to other kustomizations + +- A kustomization can be both a base and an overlay at the same time + + (a kustomization can refer to another, which can refer to a third) + +- A *patch* describes how to alter an existing resource + + (e.g. to change the image in a Deployment; or scaling parameters; etc.) + +- A *variant* is the final outcome of applying bases + overlays + +(See the [kustomize glossary](https://github.com/kubernetes-sigs/kustomize/blob/master/docs/glossary.md) for more definitions!) + +--- + +## What Kustomize *cannot* do + +- By design, there are a number of things that Kustomize won't do + +- For instance: + + - using command-line arguments or environment variables to generate a variant + + - overlays can only *add* resources, not *remove* them + +- See the full list of [eschewed features](https://github.com/kubernetes-sigs/kustomize/blob/master/docs/eschewedFeatures.md) for more details + +--- + +## Kustomize workflows + +- The Kustomize documentation proposes two different workflows + +- *Bespoke configuration* + + - base and overlays managed by the same team + +- *Off-the-shelf configuration* (OTS) + + - base and overlays managed by different teams + + - base is regularly updated by "upstream" (e.g. a vendor) + + - our overlays and patches should (hopefully!) apply cleanly + + - we may regularly update the base, or use a remote base + +--- + +## Remote bases + +- Kustomize can fetch remote bases using Hashicorp go-getter library + +- Examples: + + github.com/jpetazzo/kubercoins (remote git repository) + + github.com/jpetazzo/kubercoins?ref=kustomize (specific tag or branch) + + https://releases.hello.io/k/1.0.zip (remote archive) + + https://releases.hello.io/k/1.0.zip//some-subdir (subdirectory in archive) + +- See [hashicorp/go-getter URL format docs](https://github.com/hashicorp/go-getter#url-format) for more examples + +--- + +## Managing `kustomization.yaml` + +- There are many ways to manage `kustomization.yaml` files, including: + + - web wizards like [Replicated Ship](https://www.replicated.com/ship/) + + - the `kustomize` CLI + + - opening the file with our favorite text editor + +- Let's see these in action! --- @@ -200,7 +319,62 @@ Note: it might take a minute or two for the worker to start. +--- + +## Working with the `kustomize` CLI + +- This is another way to get started + +- General workflow: + + `kustomize create` to generate an empty `kustomization.yaml` file + + `kustomize edit add resource` to add Kubernetes YAML files to it + + `kustomize edit add patch` to add patches to said resources + + `kustomize build | kubectl apply -f-` or `kubectl apply -k .` + +--- + +## `kubectl apply -k` + +- Kustomize has been integrated in `kubectl` + +- The `kustomize` tool is still needed if we want to use `create`, `edit`, ... + +- Also, warning: `kubectl apply -k` is a slightly older version than `kustomize`! + +- In recent versions of `kustomize`, bases can be listed in `resources` + + (and `kustomize edit add base` will add its arguments to `resources`) + +- `kubectl apply -k` requires bases to be listed in `bases` + + (so after using `kustomize edit add base`, we need to fix `kustomization.yaml`) + +--- + +## Differences with Helm + +- Helm charts use placeholders `{{ like.this }}` + +- Kustomize "bases" are standard Kubernetes YAML + +- It is possible to use an existing set of YAML as a Kustomize base + +- As a result, writing a Helm chart is more work ... + +- ... But Helm charts are also more powerful; e.g. they can: + + - use flags to conditionally include resources or blocks + + - check if a given Kubernetes API group is supported + + - [and much more](https://helm.sh/docs/chart_template_guide/) + ??? :EN:- Packaging and running apps with Kustomize :FR:- *Packaging* d'applications avec Kustomize + From 3fafbb8d4e4c42700c7731c9565f6783f0f8d340 Mon Sep 17 00:00:00 2001 From: Jerome Petazzoni Date: Mon, 4 May 2020 16:47:26 +0200 Subject: [PATCH 15/15] Add kustomize CLI and completion --- prepare-vms/lib/commands.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/prepare-vms/lib/commands.sh b/prepare-vms/lib/commands.sh index 5493f62f..e6934124 100644 --- a/prepare-vms/lib/commands.sh +++ b/prepare-vms/lib/commands.sh @@ -246,6 +246,14 @@ EOF" helm completion bash | sudo tee /etc/bash_completion.d/helm fi" + # Install kustomize + pssh " + if [ ! -x /usr/local/bin/kustomize ]; then + curl -L https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v3.5.4/kustomize_v3.5.1_linux_amd64.tar.gz | + sudo tar -C /usr/local/bin -zx kustomize + echo complete -C /usr/local/bin/kustomize kustomize | sudo tee /etc/bash_completion.d/kustomize + fi" + # Install ship pssh " if [ ! -x /usr/local/bin/ship ]; then