Compare commits

...

8 Commits

Author SHA1 Message Date
Gerry S
d983592ddc Post-Friday 2022-09-18 13:43:09 -04:00
Gerry S
d759703f9a Friday/Day 5 2022-08-26 11:05:06 -04:00
Gerry S
ffbecd9e04 Thurs Day-4 2022-08-24 15:40:52 -04:00
Gerry S
6a235fae44 Wednesday/Day-3 2022-08-24 11:05:11 -04:00
Gerry S
d83a6232c4 Day 2 TOC 2022-08-23 10:50:36 -04:00
Jérôme Petazzoni
7b7c755b95 Bump up runtime version to fix Netlify deployment 2022-08-22 17:22:18 +02:00
Gerry S
6d0849eebb New Relic Gerry version (day 1) 2022-08-22 10:28:39 -04:00
Jérôme Petazzoni
b46dcd5157 🧭 New Relic August 2022 content (for Gerry) 2022-08-03 15:10:25 +02:00
42 changed files with 1928 additions and 59 deletions

View File

@@ -3,11 +3,13 @@ kind: Pod
metadata:
name: nginx-with-volume
spec:
volumes:
- name: www
containers:
- name: nginx
image: nginx
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html/
volumes:
- name: www
emptyDir: {}

View File

@@ -2,6 +2,7 @@
#/ /kube-halfday.yml.html 200!
#/ /kube-fullday.yml.html 200!
#/ /kube-twodays.yml.html 200!
/ /kube.yml.html 200!
# And this allows to do "git clone https://container.training".
/info/refs service=git-upload-pack https://github.com/jpetazzo/container.training/info/refs?service=git-upload-pack

1
slides/b Executable file
View File

@@ -0,0 +1 @@
./markmaker.py kube.yml >out.html

View File

@@ -100,7 +100,11 @@ _We will give more details about namespaces and cgroups later._
* But it is easier to use `docker exec`.
```bash
$ docker exec -ti ticktock sh
$ docker ps -lq # Get Last Container ID
17e4e95e2702
$ docker exec 17
$ docker exec -ti $(docker ps -lq) sh # bash-fu version
```
* This creates a new process (running `sh`) _inside_ the container.

View File

@@ -0,0 +1,20 @@
class: title
# High Level Discussion
![image](images/title-understanding-docker-images.png)
---
## White Board Topics
* What is the real problem that containers solve?
* What are the inputs to a Unix Process?
* What is the init Process?
* Userland vs Kernel
* The Root File System
* What is an Overlay File System?
* Wrapping it all up to represent a container image
* Deploying Container images

View File

@@ -0,0 +1,318 @@
class: title
# A Macroscopic View
---
## Macroscopic Items
* The business case for containers
* The problem containers are solving
* What applications need
* What is the OS doing provides?
---
## What do CIOs worry about?
Who are the CIO's customers?
* Business Units: Need Computers to Run Applications
* Peak Capacity
* CFO: Demanding Budget Justifications
* Spend Less
---
## History of Solutions
For Each Business Application Buy a Machine
* Buy a machine for each application
* Big enough for Peak Load (CPU, Memory, Disk)
The Age of VMs
* Buy bigger machines and chop them up into logical machines
* Distribute your applications as VMs theses machines
* Observe what and when the application load actually is
* Possibly rebalance be to inform possibly moving
But Maintaining Machines (Bare Metal or VM) is hard (Patches, Packages, Drivers, etc)
---
## What Developers and Ops worry about
* Getting Software deployed
* Mysterious reasons why deployed application doesn't work
* Developer to Ops:
* "Hey it works on my development machine..."
* "I don't know why it isn't working for ***you***"
* "Everything ***looks*** the same"
* "I have no idea what could be different"
---
## The History of Software Deployment
Software Deployment is just a reproducible way to install files:
* Cards
* Tapes
* Floppy Disks
* Zip/Tar Files
* Installation "Files" (rpm/deb/msi)
* VM Images
---
## What is the Problem Containers are Solving?
It depends on who you are:
* For the CIO: Better resource utilization
* For Ops: Software Distribution
* For the Developer & Ops: Reproducible Environment
<BR><BR>
Ummm, but what exactly are containers....
* Wait a few more slides...
---
## Macroscopic view: Applications and the OS
Applications:
* What are the inputs/outputs to a program?
The OS:
* What does the OS provide?
---
## What are the inputs/outputs to a program?
Explicitly:
* Command Line Arguments
* Environment Variables
* Standard In
* Standard Out/Err
Implicitly (via the File System):
* Configuration Files
* Other Installed Applications
* Any other files
Also Implicitly
* Memory
* Network
---
## What does the OS provide?
* OS Kernel
* Kernel loded at boot time
* Sets up disk drives, network cards, other hardware, etc
* Manages all hardware, processes, memory, etc
* Kernel Space
* Low level innards of Kernel (fluid internal API)
* No direct access by applications of most Kernel functionality
* User Space (userland) Processes
* Code running outside the Kernel
* Very stable shim library access from User Space to Kernel Space (Think "fopen")
* The "init" Process
* User Space Process run after Kernel has booted
* Always PID 1
---
## OS Processes
* Created when an application is launched
* Each has a unique Process ID (PID)
* Provides it its own logical 'view' of all implicit inputs/output when launching app
* File System ( root directory, / )
* Memory
* Network Adaptors
* Other running processes
---
## What do we mean by "The OS"
Different Linux's
* Ubuntu / Debian; Centos / RHEL; Raspberry Pi; etc
What do they have in common?
* They all have a kernel that provides access to Userland (ie fopen)
* They typically have all the commands (bash, sh, ls, grep, ...)
What may be different?
* May use different versions of the Kernel (4.18, 5.4, ...)
* Internally different, but providing same Userland API
* Many other bundled commands, packages and package management tools
* Namely what makes it 'Debian' vs 'Centos'
---
## What might a 'Minimal' Linux be?
You could actually just have:
* A Linux Kernel
* An application (for simplicity a statically linked C program)
* The kernel configured to run that application as its 'init' process
Would you ever do this?
* Why not?
* It certainly would be very secure
---
## So Finally... What are Containers?
Containers just a Linux process that 'thinks' it is it's own machine
* With its own 'view' of things like:
* File System ( root directory, / ), Memory, Network Adaptors, Other running processes
* Leverages our understanding that a (logical) Linux Machine is
* A kernel
* A bunch of files ( Maybe a few Environment Variables )
Since it is a process running on a host machine
* It uses the kernel of the host machine
* And of course you need some tools to create the running container process
---
## Container Runtimes and Container Images
The Linux kernel actually has no concept of a container.
* There have been many 'container' technologies
* See [A Brief History of containers: From the 1970's till now](https://blog.aquasec.com/a-brief-history-of-containers-from-1970s-chroot-to-docker-2016)
* Over the years more capabilities have been added to the kernel to make it easier
<BR>
A 'Container technology' is:
* A Container Image Format of the unit of software deployment
* A bundle of all the files and miscellaneous configuration
* A Container Runtime Engine
* Software that takes a Container Image and creates a running container
---
## The Container Runtime War is now Over
The Cloud Native Computing Foundation (CNCF) has standardized containers
* A standard container image format
* A standard for building and configuring container runtimes
* A standard REST API for loading/downloading container image to a registries
There primary Container Runtimes are:
* containerd: using the 'docker' Command Line Interface (or Kubernetes)
* CRI-O: using the 'podman' Command Line Interface (or Kubernetes/OpenShift)
* Others exists, for example Singularity which has a history in HPC
---
## Linux Namespaces Makes Containers Possible
- Provide processes with their own isolated view of the system.
- Namespaces limit what you can see (and therefore, what you can use).
- These namespaces are available in modern kernels:
- pid: processes
- net: network
- mnt: root file system (ie chroot)
- uts: hostname
- ipc
- user: UID/GID mapping
- time: time
- cgroup: Resource Monitoring and Limiting
- Each process belongs to one namespace of each type.
---
## Namespaces are always active
- Namespaces exist even when you don't use containers.
- This is a bit similar to the UID field in UNIX processes:
- all processes have the UID field, even if no user exists on the system
- the field always has a value / the value is always defined
<br/>
(i.e. any process running on the system has some UID)
- the value of the UID field is used when checking permissions
<br/>
(the UID field determines which resources the process can access)
- You can replace "UID field" with "namespace" above and it still works!
- In other words: even when you don't use containers,
<br/>there is one namespace of each type, containing all the processes on the system.

View File

@@ -0,0 +1,224 @@
class: title
# Our training environment
![SSH terminal](images/title-our-training-environment.jpg)
---
class: in-person
## Connecting to your Virtual Machine
You need an SSH client.
* On OS X, Linux, and other UNIX systems, just use `ssh`:
```bash
$ ssh <login>@<ip-address>
```
* On Windows, if you don't have an SSH client, you can download:
* Putty (www.putty.org)
* Git BASH (https://git-for-windows.github.io/)
* MobaXterm (https://mobaxterm.mobatek.net/)
---
class: in-person
## Connecting to our lab environment
.lab[
- Log into your VM with your SSH client:
```bash
ssh `user`@`A.B.C.D`
```
(Replace `user` and `A.B.C.D` with the user and IP address provided to you)
]
You should see a prompt looking like this:
```
[A.B.C.D] (...) user@node1 ~
$
```
If anything goes wrong — ask for help!
---
## Our Docker VM
About the Lab VM
- The VM is created just before the training.
- It will stay up during the whole training.
- It will be destroyed shortly after the training.
- It comes pre-loaded with Docker and some other useful tools.
---
## Why don't we run Docker locally?
- I can log into your VMs to help you with labs
- Installing docker is out of the scope of this class (lots of online docs)
- It's better to spend time learning containers than fiddling with the installer!
---
class: in-person
## `tailhist`
- The shell history of the instructor is available online in real time
- Note the IP address of the instructor's virtual machine (A.B.C.D)
- Open http://A.B.C.D:1088 in your browser and you should see the history
- The history is updated in real time (using a WebSocket connection)
- It should be green when the WebSocket is connected
(if it turns red, reloading the page should fix it)
- If you want to play with it on your lab machine, tailhist is installed
- sudo apt install firewalld
- sudo firewall-cmd --add-port=1088/tcp
---
## Checking your Virtual Machine
Once logged in, make sure that you can run a basic Docker command:
.small[
```bash
$ docker version
Client:
Version: 18.03.0-ce
API version: 1.37
Go version: go1.9.4
Git commit: 0520e24
Built: Wed Mar 21 23:10:06 2018
OS/Arch: linux/amd64
Experimental: false
Orchestrator: swarm
Server:
Engine:
Version: 18.03.0-ce
API version: 1.37 (minimum version 1.12)
Go version: go1.9.4
Git commit: 0520e24
Built: Wed Mar 21 23:08:35 2018
OS/Arch: linux/amd64
Experimental: false
```
]
If this doesn't work, raise your hand so that an instructor can assist you!
???
:EN:Container concepts
:FR:Premier contact avec les conteneurs
:EN:- What's a container engine?
:FR:- Qu'est-ce qu'un *container engine* ?
---
## Doing or re-doing the workshop on your own?
- Use something like
[Play-With-Docker](http://play-with-docker.com/) or
[Play-With-Kubernetes](https://training.play-with-kubernetes.com/)
Zero setup effort; but environment are short-lived and
might have limited resources
- Create your own cluster (local or cloud VMs)
Small setup effort; small cost; flexible environments
- Create a bunch of clusters for you and your friends
([instructions](https://@@GITREPO@@/tree/master/prepare-vms))
Bigger setup effort; ideal for group training
---
class: self-paced
## Get your own Docker nodes
- If you already have some Docker nodes: great!
- If not: let's get some thanks to Play-With-Docker
.lab[
- Go to http://www.play-with-docker.com/
- Log in
- Create your first node
<!-- ```open http://www.play-with-docker.com/``` -->
]
You will need a Docker ID to use Play-With-Docker.
(Creating a Docker ID is free.)
---
## Terminals
Once in a while, the instructions will say:
<br/>"Open a new terminal."
There are multiple ways to do this:
- create a new window or tab on your machine, and SSH into the VM;
- use screen or tmux on the VM and open a new window from there.
You are welcome to use the method that you feel the most comfortable with.
---
## Tmux cheat sheet
[Tmux](https://en.wikipedia.org/wiki/Tmux) is a terminal multiplexer like `screen`.
*You don't have to use it or even know about it to follow along.
<br/>
But some of us like to use it to switch between terminals.
<br/>
It has been preinstalled on your workshop nodes.*
- Ctrl-b c → creates a new window
- Ctrl-b n → go to next window
- Ctrl-b p → go to previous window
- Ctrl-b " → split window top/bottom
- Ctrl-b % → split window left/right
- Ctrl-b Alt-1 → rearrange windows in columns
- Ctrl-b Alt-2 → rearrange windows in rows
- Ctrl-b arrows → navigate to other windows
- Ctrl-b d → detach session
- tmux attach → re-attach to session

View File

@@ -0,0 +1,27 @@
```bash
$ docker run -it debian
root@ef22f9437171:/# apt-get update
root@ef22f9437171:/# apt-get install skopeo
root@ef22f9437171:/# apt-get wget curl jq
root@ef22f9437171:/# skopeo login docker.io -u containertraining -p testaccount
$ docker commit $(docker ps -lq) skop
```
```bash
root@0ab665194c4f:~# skopeo copy docker://docker.io/containertraining/test-image-0 dir:/root/test-image-0
root@0ab665194c4f:~# cd /root/test-image-0
root@0ab665194c4f:~# jq <manifest.json .layers[].digest
```
Stuff in Exploring-images
image-test-0/1/2 + jpg

View File

@@ -0,0 +1,20 @@
FROM busybox
ADD verifyImageFiles.sh /
WORKDIR /play
RUN echo "== LAYER 0 ==" && \
echo "A is for Aardvark" >A && \
echo "B is for Beetle" >B && \
mkdir C/ && \
echo "A is for Cowboy Allan" >C/CA && \
mkdir -p C/CB && \
echo "A is for Cowboy Buffalo Alex" >C/CB/CBA && \
echo "B is for Cowboy Buffalo Bill" >C/CB/CBB && \
echo "Z is for Cowboy Zeke" >> C/CZ && \
mkdir D/ && \
echo "A is for Detective Alisha" >D/DA && \
echo "B is for Detective Betty" >D/DB && \
echo "E is for Elephant" >E && \
find . >../state.layer-0

View File

@@ -0,0 +1,17 @@
FROM test-image-0
WORKDIR /play
RUN echo "== LAYER 1 == Change File B, Create File C/CC, Add Dir C/CD, Remove File E, Create Dir F, Add File G, Create Empty Dir H" && \
echo "B is for Butterfly" >B && \
echo "C is for Cowboy Chuck">C/CC && \
mkdir -p C/CD && \
echo "A is for Cowboy Dandy Austin" >C/CD/CDA && \
rm E && \
mkdir F && \
echo "A is for Ferret Albert" >F/FA && \
echo "G is for Gorilla" >G && \
mkdir H && \
find . >../state.layer-1

View File

@@ -0,0 +1,18 @@
FROM test-image-1
WORKDIR /play
RUN echo "== LAYER 2 == Remove File C/CA, Remove Dir G, Remove Dir D / Replace with new Dir D, Remove Dir C/CB, Remove Dir C/CB, Remove Dir F, Add File G, Remove Dir H / Create File H" && \
rm C/CA && \
rm -rf C/CB && \
echo "Z is for Cowboy Zoe" >> CZ && \
rm -rf D && \
mkdir -p D && \
echo "A is for Duplicitous Albatros" >D/DA && \
rm -rf F && \
rm G && \
echo "G is for Geccos" >G && \
rmdir H \
echo "H is for Human" >H && \
find . >../state.layer-2

View File

@@ -0,0 +1,87 @@
clear
baseDir=$(pwd)
rm -rf /tmp/exploringImags
mkdir -p /tmp/exploringImags
cd /tmp/exploringImags
echo "== LAYER 0 =="
echo "A is for Aardvark" >A
echo "B is for Beetle" >B
mkdir C/
echo "A is for Cowboy Allan" >C/CA
mkdir -p C/CB
echo "A is for Cowboy Buffalo Alex" >C/CB/CBA
echo "B is for Cowboy Buffalo Bill" >C/CB/CBB
echo "Z is for Cowboy Zeke" >C/CZ
mkdir D/
echo "A is for Detective Alisha" >D/DA
echo "B is for Detective Betty" >D/DB
echo "E is for Elephant" >E
find . >../state.layer-0
tree | grep -v directories | tee ../tree.layer-0
$baseDir/verifyImageFiles.sh 0 $(pwd)
echo "== LAYER 1 == Change File B, Create File C/CC, Add Dir C/CD, Remove File E, Create Dir F, Add File G, Create Empty Dir H"
echo "B is for Butterfly" >B
echo "C is for Cowboy Chuck">C/CC
mkdir -p C/CD
echo "A is for Cowboy Dandy Austin" >C/CD/CDA
rm E
mkdir F
echo "A is for Ferret Albert" >F/FA
echo "G is for Gorilla" >G
mkdir H
find . >../state.layer-1
tree | grep -v directories | tee ../tree.layer-1
$baseDir/verifyImageFiles.sh 1 $(pwd)
echo "== LAYER 2 == Remove File C/CA, Remove Dir G, Remove Dir D Replace with new Dir D, Remove Dir C/CB, Remove Dir C/CB, Add File H/HA, Add File, Create Dir I"
rm C/CA
rm -rf C/CB
echo "Z is for Cowboy Zoe" >C/CZ
rm -rf D
mkdir -p D
echo "A is for Duplicitous Albatros" >D/DA
rm -rf F
rm -rf G
echo "G is for Geccos" >G
rmdir H
echo "H is for Human" >H
find . >../state.layer-2
tree | grep -v directories | tee ../tree.layer-2
$baseDir/verifyImageFiles.sh 2 $(pwd)

View File

@@ -0,0 +1,88 @@
fileContentsCompare() {
layer=$1
text=$2
file=$(pwd)/$3
if [ -f "$file" ]; then
fileContents=$(cat $file)
if [ "$fileContents" != "$text" ]; then
echo In Layer $layer Unexpected contents in file: $file
echo -- Contents: $fileContents
echo -- Expected: $text
fi
else
echo Missing File $file in Layer $layer
fi
}
checkLayer() {
layer=$1
find . >/tmp/state
if [[ $(diff /tmp/state $targetDir/../state.layer-$layer) ]]; then
echo Directory Structure mismatch in layer: $layer
diff /tmp/state $targetDir/../state.layer-$layer
fi
case $layer in
0)
fileContentsCompare $layer "A is for Aardvark" A
fileContentsCompare $layer "B is for Beetle" B
fileContentsCompare $layer "A is for Cowboy Allan" C/CA
fileContentsCompare $layer "A is for Cowboy Buffalo Alex" C/CB/CBA
fileContentsCompare $layer "B is for Cowboy Buffalo Bill" C/CB/CBB
fileContentsCompare $layer "Z is for Cowboy Zeke" C/CZ
fileContentsCompare $layer "A is for Detective Alisha" D/DA
fileContentsCompare $layer "B is for Detective Betty" D/DB
fileContentsCompare $layer "E is for Elephant" E
;;
# echo "== LAYER 1 == Change File B, Create File C/CC, Add Dir C/CD, Remove File E, Create Dir F, Add File G, Create Empty Dir H"
1)
fileContentsCompare $layer "A is for Aardvark" A
fileContentsCompare $layer "B is for Butterfly" B ## CHANGED FILE B
fileContentsCompare $layer "A is for Cowboy Allan" C/CA
fileContentsCompare $layer "A is for Cowboy Buffalo Alex" C/CB/CBA
fileContentsCompare $layer "B is for Cowboy Buffalo Bill" C/CB/CBB
fileContentsCompare $layer "C is for Cowboy Chuck" C/CC ## ADDED FILE C/CC
fileContentsCompare $layer "A is for Cowboy Dandy Austin" C/CD/CDA ## ADDED DIR C/CD, ADDED FILE C/CD/CDA
fileContentsCompare $layer "Z is for Cowboy Zeke" C/CZ
fileContentsCompare $layer "A is for Detective Alisha" D/DA
fileContentsCompare $layer "B is for Detective Betty" D/DB
## REMOVED FILE E
fileContentsCompare $layer "A is for Ferret Albert" F/FA ## ADDED DIR F, ADDED FILE F/A
fileContentsCompare $layer "G is for Gorilla" G ## ADDED G
## CREATED EMPTY DIR H
;;
# echo "== LAYER 2 == Remove File C/CA, Remove Dir C/CB, Remove Dir C/CB, Remove Dir D Replace with new Dir D, Delete and Recreatee File G, Add File H/HA Create Dir I"
2)
fileContentsCompare $layer "A is for Aardvark" A
fileContentsCompare $layer "B is for Butterfly" B
## REMOVED FILE C/CA
## REMOVED DIR C/CB
fileContentsCompare $layer "C is for Cowboy Chuck" C/CC
fileContentsCompare $layer "A is for Cowboy Dandy Austin" C/CD/CDA
fileContentsCompare $layer "Z is for Cowboy Zoe" C/CZ ## CHANGED FILE C/CZ
## REMOVE DIR D
fileContentsCompare $layer "A is for Duplicitous Albatros" D/DA ## RECREATE DIR D, ADD FILE D/DA
fileContentsCompare $layer "G is for Geccos" G ## DELETED FILE G, ADDED FILE G (Implicit CHANGED)
fileContentsCompare $layer "H is for Human" H ## ADDED FILE H
;;
esac
}
layer=$1
targetDir=$2
echo VERIFYING LAYER $layer
checkLayer $layer

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 KiB

View File

@@ -0,0 +1,120 @@
# Container Based Software Deployment
---
class: pic
![dummmy](containers/software-deployment/slide-1.jpg)
---
class: pic
![dummmy](containers/software-deployment/slide-2.jpg)
---
class: pic
![dummmy](containers/software-deployment/slide-3.jpg)
---
class: pic
![dummmy](containers/software-deployment/slide-4.jpg)
---
class: pic
![dummmy](containers/software-deployment/slide-5.jpg)
---
class: pic
![dummmy](containers/software-deployment/slide-6.jpg)
---
class: pic
![dummmy](containers/software-deployment/slide-7.jpg)
---
class: pic
![dummmy](containers/software-deployment/slide-8.jpg)
---
class: pic
![dummmy](containers/software-deployment/slide-9.jpg)
---
class: pic
![dummmy](containers/software-deployment/slide-10.jpg)
---
class: pic
![dummmy](containers/software-deployment/slide-11.jpg)
---
class: pic
![dummmy](containers/software-deployment/slide-12.jpg)
---
class: pic
![dummmy](containers/software-deployment/slide-13.jpg)
---
class: pic
![dummmy](containers/software-deployment/slide-14.jpg)
---
class: pic
![dummmy](containers/software-deployment/slide-15.jpg)
---
class: pic
![dummmy](containers/software-deployment/slide-16.jpg)
---
class: pic
![dummmy](containers/software-deployment/slide-17.jpg)

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

View File

@@ -0,0 +1,45 @@
# External References && kubectl Aliases
Class Slides: https://2022-08-nr.container.training/
Kubectl Cheat Sheet: https://kubernetes.io/docs/reference/kubectl/cheatsheet/
Kubernetes API Object and kubectl Explorers
- https://github.com/GerrySeidman/Kubernetes-Explorer
Gerry Kubernetes Storage Converence Talks
- Vault '20: https://www.usenix.org/conference/vault20/presentation/seidman
- Data and Dev '21: https://www.youtube.com/watch?v=k_8rWPwJ_38
Gerry Seidmans Info
- gerry.seidman@ardanlabs.com
- https://www.linkedin.com/in/gerryseidman/
---
## Kubectl Aliases
```bash
alias k='kubectl'
alias kg='kubectl get'
alias kl='kubctl logs'
alias ka='kubectl apply -f'
alias kd='kubectl delete'
alias kdf='kubectl delete -f'
alias kb='kubectl describe'
alias kex='kubectl explain'
alias ke='kubectl edit'
alias kx='kubectl exec -it $1 -- /bin/sh'
```
Note the below is only because of a quirk in how the lab VMs were installed:
```bash
echo 'kubectl exec -it $1 -- /bin/sh' >kx
chmod +x kx
sudo mv kx /usr/local/bin/kx
```

View File

@@ -0,0 +1,51 @@
## Basic Commands
run
create
get
delete
logs
explain
describe
exec
## Modifying Objects
apply (upsert)
set
edit
patch
label
annotate
https://blog.atomist.com/kubernetes-apply-replace-patch/
diff
replace
wait
## NetCommands
expose
port-forward
proxy
## Deploy Command
rollout
scale
autoscale
## Cluster Management Commands
certificate
cluster-info
cordon
uncordon
drain
taint
## Troubleshooting and Debugging Commands
top
attach
cp
auth
debug
## Settings Commands
completion
## Other Commands
alpha
api-resources
api-versions
config
plugin
version
Please Share this API Explorer

251
slides/k8s/kubectl-first.md Normal file
View File

@@ -0,0 +1,251 @@
# First contact with `kubectl`
- `kubectl` is (almost) the only tool we'll need to talk to Kubernetes
- It is a rich CLI tool around the Kubernetes API
(Everything you can do with `kubectl`, you can do directly with the API)
- On our machines, there is a `~/.kube/config` file with:
- the Kubernetes API address
- the path to our TLS certificates used to authenticate
- You can also use the `--kubeconfig` flag to pass a config file
- Or directly `--server`, `--user`, etc.
- `kubectl` can be pronounced "Cube C T L", "Cube cuttle", "Cube cuddle"...
---
class: extra-details
## `kubectl` is the new SSH
- We often start managing servers with SSH
(installing packages, troubleshooting ...)
- At scale, it becomes tedious, repetitive, error-prone
- Instead, we use config management, central logging, etc.
- In many cases, we still need SSH:
- as the underlying access method (e.g. Ansible)
- to debug tricky scenarios
- to inspect and poke at things
---
class: extra-details
## The parallel with `kubectl`
- We often start managing Kubernetes clusters with `kubectl`
(deploying applications, troubleshooting ...)
- At scale (with many applications or clusters), it becomes tedious, repetitive, error-prone
- Instead, we use automated pipelines, observability tooling, etc.
- In many cases, we still need `kubectl`:
- to debug tricky scenarios
- to inspect and poke at things
- The Kubernetes API is always the underlying access method
---
## `kubectl get`
- Let's look at our `Node` resources with `kubectl get`!
.lab[
- Look at the composition of our cluster:
```bash
kubectl get node
```
- These commands are equivalent:
```bash
kubectl get no
kubectl get node
kubectl get nodes
```
]
---
## Obtaining machine-readable output
- `kubectl get` can output JSON, YAML, or be directly formatted
.lab[
- Give us more info about the nodes:
```bash
kubectl get nodes -o wide
```
- Let's have some YAML:
```bash
kubectl get no -o yaml
```
See that `kind: List` at the end? It's the type of our result!
]
---
## (Ab)using `kubectl` and `jq`
- It's super easy to build custom reports
.lab[
- Show the capacity of all our nodes as a stream of JSON objects:
```bash
kubectl get nodes -o json |
jq ".items[] | {name:.metadata.name} + .status.capacity"
```
]
---
class: extra-details
## Exploring types and definitions
- We can list all available resource types by running `kubectl api-resources`
<br/>
(In Kubernetes 1.10 and prior, this command used to be `kubectl get`)
- We can view the definition for a resource type with:
```bash
kubectl explain type
```
- We can view the definition of a field in a resource, for instance:
```bash
kubectl explain node.spec
```
- Or get the full definition of all fields and sub-fields:
```bash
kubectl explain node --recursive
```
---
class: extra-details
## Introspection vs. documentation
- We can access the same information by reading the [API documentation](https://kubernetes.io/docs/reference/#api-reference)
- The API documentation is usually easier to read, but:
- it won't show custom types (like Custom Resource Definitions)
- we need to make sure that we look at the correct version
- `kubectl api-resources` and `kubectl explain` perform *introspection*
(they communicate with the API server and obtain the exact type definitions)
---
## Type names
- The most common resource names have three forms:
- singular (e.g. `node`, `service`, `deployment`)
- plural (e.g. `nodes`, `services`, `deployments`)
- short (e.g. `no`, `svc`, `deploy`)
- Some resources do not have a short name
- `Endpoints` only have a plural form
(because even a single `Endpoints` resource is actually a list of endpoints)
---
## Viewing details
- We can use `kubectl get -o yaml` to see all available details
- However, YAML output is often simultaneously too much and not enough
- For instance, `kubectl get node node1 -o yaml` is:
- too much information (e.g.: list of images available on this node)
- not enough information (e.g.: doesn't show pods running on this node)
- difficult to read for a human operator
- For a comprehensive overview, we can use `kubectl describe` instead
---
## `kubectl describe`
- `kubectl describe` needs a resource type and (optionally) a resource name
- It is possible to provide a resource name *prefix*
(all matching objects will be displayed)
- `kubectl describe` will retrieve some extra information about the resource
.lab[
- Look at the information available for `node1` with one of the following commands:
```bash
kubectl describe node/node1
kubectl describe node node1
```
]
(We should notice a bunch of control plane pods.)
---
## Listing running containers
- Containers are manipulated through *pods*
- A pod is a group of containers:
- running together (on the same node)
- sharing resources (RAM, CPU; but also network, volumes)
.lab[
- List pods on our cluster:
```bash
kubectl get pods
```
]
--
*Where are the pods that we saw just a moment earlier?!?*

340
slides/k8s/kubectl-more.md Normal file
View File

@@ -0,0 +1,340 @@
# More contact with `kubectl`
- Namespaces
- Clusters
- Proxy
---
## Namespaces
- Namespaces allow us to segregate resources
.lab[
- List the namespaces on our cluster with one of these commands:
```bash
kubectl get namespaces
kubectl get namespace
kubectl get ns
```
]
--
*You know what ... This `kube-system` thing looks suspicious.*
*In fact, I'm pretty sure it showed up earlier, when we did:*
`kubectl describe node node1`
---
## Accessing namespaces
- By default, `kubectl` uses the `default` namespace
- We can see resources in all namespaces with `--all-namespaces`
.lab[
- List the pods in all namespaces:
```bash
kubectl get pods --all-namespaces
```
- Since Kubernetes 1.14, we can also use `-A` as a shorter version:
```bash
kubectl get pods -A
```
]
*Here are our system pods!*
---
## What are all these control plane pods?
- `etcd` is our etcd server
- `kube-apiserver` is the API server
- `kube-controller-manager` and `kube-scheduler` are other control plane components
- `coredns` provides DNS-based service discovery ([replacing kube-dns as of 1.11](https://kubernetes.io/blog/2018/07/10/coredns-ga-for-kubernetes-cluster-dns/))
- `kube-proxy` is the (per-node) component managing port mappings and such
- `weave` is the (per-node) component managing the network overlay
- the `READY` column indicates the number of containers in each pod
(1 for most pods, but `weave` has 2, for instance)
---
## Scoping another namespace
- We can also look at a different namespace (other than `default`)
.lab[
- List only the pods in the `kube-system` namespace:
```bash
kubectl get pods --namespace=kube-system
kubectl get pods -n kube-system
```
]
---
## Namespaces and other `kubectl` commands
- We can use `-n`/`--namespace` with almost every `kubectl` command
- Example:
- `kubectl create --namespace=X` to create something in namespace X
- We can use `-A`/`--all-namespaces` with most commands that manipulate multiple objects
- Examples:
- `kubectl delete` can delete resources across multiple namespaces
- `kubectl label` can add/remove/update labels across multiple namespaces
---
class: extra-details
## What about `kube-public`?
.lab[
- List the pods in the `kube-public` namespace:
```bash
kubectl -n kube-public get pods
```
]
Nothing!
`kube-public` is created by kubeadm & [used for security bootstrapping](https://kubernetes.io/blog/2017/01/stronger-foundation-for-creating-and-managing-kubernetes-clusters).
---
class: extra-details
## Exploring `kube-public`
- The only interesting object in `kube-public` is a ConfigMap named `cluster-info`
.lab[
- List ConfigMap objects:
```bash
kubectl -n kube-public get configmaps
```
- Inspect `cluster-info`:
```bash
kubectl -n kube-public get configmap cluster-info -o yaml
```
]
Note the `selfLink` URI: `/api/v1/namespaces/kube-public/configmaps/cluster-info`
We can use that!
---
class: extra-details
## Accessing `cluster-info`
- Earlier, when trying to access the API server, we got a `Forbidden` message
- But `cluster-info` is readable by everyone (even without authentication)
.lab[
- Retrieve `cluster-info`:
```bash
curl -k https://10.96.0.1/api/v1/namespaces/kube-public/configmaps/cluster-info
```
]
- We were able to access `cluster-info` (without auth)
- It contains a `kubeconfig` file
---
class: extra-details
## Retrieving `kubeconfig`
- We can easily extract the `kubeconfig` file from this ConfigMap
.lab[
- Display the content of `kubeconfig`:
```bash
curl -sk https://10.96.0.1/api/v1/namespaces/kube-public/configmaps/cluster-info \
| jq -r .data.kubeconfig
```
]
- This file holds the canonical address of the API server, and the public key of the CA
- This file *does not* hold client keys or tokens
- This is not sensitive information, but allows us to establish trust
---
class: extra-details
## What about `kube-node-lease`?
- Starting with Kubernetes 1.14, there is a `kube-node-lease` namespace
(or in Kubernetes 1.13 if the NodeLease feature gate is enabled)
- That namespace contains one Lease object per node
- *Node leases* are a new way to implement node heartbeats
(i.e. node regularly pinging the control plane to say "I'm alive!")
- For more details, see [Efficient Node Heartbeats KEP] or the [node controller documentation]
[Efficient Node Heartbeats KEP]: https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/589-efficient-node-heartbeats/README.md
[node controller documentation]: https://kubernetes.io/docs/concepts/architecture/nodes/#node-controller
---
## Services
- A *service* is a stable endpoint to connect to "something"
(In the initial proposal, they were called "portals")
.lab[
- List the services on our cluster with one of these commands:
```bash
kubectl get services
kubectl get svc
```
]
--
There is already one service on our cluster: the Kubernetes API itself.
---
## ClusterIP services
- A `ClusterIP` service is internal, available from the cluster only
- This is useful for introspection from within containers
.lab[
- Try to connect to the API:
```bash
curl -k https://`10.96.0.1`
```
- `-k` is used to skip certificate verification
- Make sure to replace 10.96.0.1 with the CLUSTER-IP shown by `kubectl get svc`
]
The command above should either time out, or show an authentication error. Why?
---
## Time out
- Connections to ClusterIP services only work *from within the cluster*
- If we are outside the cluster, the `curl` command will probably time out
(Because the IP address, e.g. 10.96.0.1, isn't routed properly outside the cluster)
- This is the case with most "real" Kubernetes clusters
- To try the connection from within the cluster, we can use [shpod](https://github.com/jpetazzo/shpod)
---
## Authentication error
This is what we should see when connecting from within the cluster:
```json
$ curl -k https://10.96.0.1
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {
},
"status": "Failure",
"message": "forbidden: User \"system:anonymous\" cannot get path \"/\"",
"reason": "Forbidden",
"details": {
},
"code": 403
}
```
---
## Explanations
- We can see `kind`, `apiVersion`, `metadata`
- These are typical of a Kubernetes API reply
- Because we *are* talking to the Kubernetes API
- The Kubernetes API tells us "Forbidden"
(because it requires authentication)
- The Kubernetes API is reachable from within the cluster
(many apps integrating with Kubernetes will use this)
---
## DNS integration
- Each service also gets a DNS record
- The Kubernetes DNS resolver is available *from within pods*
(and sometimes, from within nodes, depending on configuration)
- Code running in pods can connect to services using their name
(e.g. https://kubernetes/...)
???
:EN:- Getting started with kubectl
:FR:- Se familiariser avec kubectl

99
slides/kube.orig.yml Normal file
View File

@@ -0,0 +1,99 @@
title: |
Kubernetes
Intermediate
Training
chat: "`Zoom Chat`"
gitrepo: github.com/jpetazzo/container.training
slides: https://2022-08-nr.container.training/
#slidenumberprefix: "#SomeHashTag &mdash; "
exclude:
- self-paced
content:
- shared/title.md
- logistics-gerry.md
- k8s/intro.md
- shared/about-slides.md
#- shared/chat-room-im.md
- shared/chat-room-slack.md
#- shared/chat-room-zoom-meeting.md
#- shared/chat-room-zoom-webinar.md
- shared/toc.md
- exercises/k8sfundamentals-brief.md
- exercises/localcluster-brief.md
- exercises/healthchecks-brief.md
- exercises/ingress-brief.md
- exercises/appconfig-brief.md
- # DAY 1
- shared/prereqs.md
- shared/webssh.md
- shared/connecting.md
#- k8s/versions-k8s.md
- shared/sampleapp.md
- shared/composedown.md
- k8s/concepts-k8s.md
- k8s/kubectlget.md
- k8s/kubectl-run.md
- k8s/kubenet.md
- k8s/kubectlexpose.md
- k8s/shippingimages.md
#- k8s/buildshiprun-selfhosted.md
- k8s/buildshiprun-dockerhub.md
- exercises/k8sfundamentals-details.md
- # DAY 2
- k8s/ourapponkube.md
- shared/declarative.md
- k8s/declarative.md
- k8s/deploymentslideshow.md
- k8s/labels-annotations.md
- k8s/kubectl-logs.md
- k8s/logs-cli.md
- k8s/namespaces.md
- k8s/yamldeploy.md
- k8s/setup-overview.md
- k8s/setup-devel.md
- k8s/localkubeconfig.md
- k8s/accessinternal.md
#- k8s/kubectlproxy.md
- k8s/k9s.md
- k8s/tilt.md
- exercises/localcluster-details.md
- # DAY 3
- k8s/scalingdockercoins.md
- shared/hastyconclusions.md
- k8s/daemonset.md
- k8s/rollout.md
- k8s/healthchecks.md
- exercises/healthchecks-details.md
- k8s/ingress.md
#- k8s/ingress-tls.md
- exercises/ingress-details.md
- # DAY 4
- k8s/netpol.md
- k8s/authn-authz.md
- k8s/resource-limits.md
- k8s/metrics-server.md
- k8s/cluster-sizing.md
- # DAY 5
- k8s/volumes.md
- k8s/configuration.md
- k8s/secrets.md
- exercises/appconfig-details.md
- k8s/statefulsets.md
- k8s/consul.md
- k8s/pv-pvc-sc.md
- k8s/volume-claim-templates.md
#- k8s/portworx.md
#- k8s/openebs.md
#- k8s/stateful-failover.md
- # Extra
- |
# (Extra content)
- k8s/horizontal-pod-autoscaler.md
- k8s/dashboard.md
- k8s/batch-jobs.md

120
slides/kube.yml Normal file
View File

@@ -0,0 +1,120 @@
title: |
Kubernetes
Intermediate
Training
chat: "`Zoom Chat`"
gitrepo: github.com/jpetazzo/container.training
slides: https://2022-08-nr.container.training/
#slidenumberprefix: "#SomeHashTag &mdash; "
exclude:
- self-paced
content:
- shared/title.md
- logistics-gerry.md
- k8s/intro.md
- shared/about-slides.md
#- shared/chat-room-im.md
# - shared/chat-room-slack.md
#- shared/chat-room-zoom-meeting.md
- shared/chat-room-zoom-webinar.md
- shared/prereqs.md
- shared/webssh.md
- shared/connecting.md
- shared/toc.md
- exercises/k8sfundamentals-brief.md
- exercises/localcluster-brief.md
- exercises/healthchecks-brief.md
- exercises/ingress-brief.md
- exercises/appconfig-brief.md
-
# DAY 1
- containers/Macro_View.md
#- shared/webssh.md
#- k8s/versions-k8s.md
#- shared/composescale.md
- k8s/concepts-k8s.md
- k8s/deploymentslideshow.md
- shared/declarative.md
- k8s/declarative.md
#- shared/hastyconclusions.md
# - k8s/shippingimages.md
- k8s/kubectl-first.md
- k8s/authoring-yaml.md
#- k8s/buildshiprun-selfhosted.md
- k8s/alias-and-references.md
- # DAY 2
- k8s/labels-annotations.md
- k8s/kubectl-logs.md
- k8s/logs-cli.md
- k8s/kubectl-run.md
- k8s/kubectl-more.md
- k8s/kubectlexpose.md
- k8s/rollout.md
- k8s/yamldeploy.md
- # DAY 3 (Started with 2 hour's lab and discussion)
- k8s/daemonset.md
- k8s/namespaces.md
- k8s/healthchecks.md
- k8s/kubenet.md
- exercises/healthchecks-details.md
- # DAY 4
- k8s/netpol.md
- k8s/accessinternal.md
- k8s/ingress.md
- containers/software-deployment.md
- k8s/volumes.md
- k8s/configuration.md
- k8s/secrets.md
- k8s/volume-claim-templates.md
- exercises/ingress-details.md
- exercises/appconfig-details.md
- # DAY 5
# - k8s/kubectlproxy.md
- k8s/consul.md
- k8s/statefulsets.md
- k8s/pv-pvc-sc.md
- k8s/authn-authz.md
- k8s/resource-limits.md
- k8s/metrics-server.md
- k8s/setup-overview.md
- k8s/setup-devel.md
- k8s/cluster-sizing.md
- k8s/localkubeconfig.md
- k8s/k9s.md
- k8s/tilt.md
- exercises/localcluster-details.md
- shared/thankyou.md
- # DockerCoins
- |
# (Docker Coins Example)
- shared/sampleapp.md
- shared/composedown.md
- k8s/buildshiprun-dockerhub.md
- k8s/shippingimages.md
- exercises/k8sfundamentals-details.md
- k8s/ourapponkube.md
- k8s/scalingdockercoins.md
- shared/hastyconclusions.md
- # Extra
- |
# (Extra content)
- k8s/horizontal-pod-autoscaler.md
- k8s/dashboard.md
- k8s/batch-jobs.md
- k8s/helm-intro.md
- k8s/helm-chart-format.md
- k8s/helm-create-basic-chart.md
- k8s/helm-create-better-chart.md

60
slides/logistics-gerry.md Normal file
View File

@@ -0,0 +1,60 @@
## While We are Waiting To Get Started ...
- If you have not already done so, please complete this survey: [https://tinyurl.com/mrx6fsrh
](https://docs.google.com/forms/d/1w6wmnvbzyBPbt6f-k0B1ueA-pnkY_zmvROoeRj-vdFU)
- Your lab computers are assigned on this Google Sheet: [https://tinyurl.com/53dm9b66](https://docs.google.com/spreadsheets/d/1aXF46q5jtQUOEQGniPffljmrPX0PmYRc0x7XKogFmQU/edit)
- Enter your name in column 1 in one of the unclaimed rows
- Your Lab Computer IP address is found in the ** node1 ** column
- Log into your lab computer: ** ssh -l k8s node1 **
- Password is: ** relics **
- Verify all is good with the command: ** kubectl version --short **
- Class Starts at 9AM PST / 11AM EST each day
---
## Introductions
- Hello! I'm [Gerry Seidman](https://www.linkedin.com/in/gerryseidman), Ardan Labs (gerry.seidman@ardanlabs.com)
- The training will run Monday to Friday, from 8:00AM to 12:00PM PST (11AM-3PM EST)
- There will be breaks!
- Feel free to interrupt for questions at any time
- *Especially when you see full screen container pictures!*
- Live feedback, questions, help: @@CHAT@@
<!-- -->
[@alexbuisine]: https://twitter.com/alexbuisine
[EphemeraSearch]: https://ephemerasearch.com/
[@jpetazzo]: https://twitter.com/jpetazzo
[@s0ulshake]: https://twitter.com/s0ulshake
[Quantgene]: https://www.quantgene.com/
---
## Exercises
- At the end of each day, there is a series of exercises
- To make the most out of the training, please try the exercises!
(it will help to practice and memorize the content of the day)
- We'll try to finish a bit earlier each day so that you can have lab time
(and if you can put some extra time that's even better ♥)
- Each day will start with a quick review of the exercises of the previous day
- If you have any questions, blockers, curiosities ... Ping me in the zoom chat

View File

@@ -1,62 +1,16 @@
## Introductions
⚠️ This slide should be customized by the tutorial instructor(s).
- Hello! I'm FIXME
<!--
- The training will run Monday to Friday:
- Hello! We are:
- 11am-3pm (New-York)
- 👷🏻‍♀️ AJ ([@s0ulshake], [EphemeraSearch], [Quantgene])
- 4pm-8pm (London)
- 🚁 Alexandre ([@alexbuisine], Enix SAS)
- 5pm-9pm (Barcelona, Paris, Berlin)
- 🐳 Jérôme ([@jpetazzo], Ardan Labs)
- 🐳 Jérôme ([@jpetazzo], Enix SAS)
- 🐳 Jérôme ([@jpetazzo], Tiny Shell Script LLC)
-->
<!--
- The training will run for 4 hours, with a 10 minutes break every hour
(the middle break will be a bit longer)
-->
<!--
- The workshop will run from XXX to YYY
- There will be a lunch break at ZZZ
(And coffee breaks!)
-->
<!--
- Feel free to interrupt for questions at any time
- *Especially when you see full screen container pictures!*
- Live feedback, questions, help: @@CHAT@@
-->
<!--
- You ~~should~~ must ask questions! Lots of questions!
(especially when you see full screen container pictures)
- Use @@CHAT@@ to ask questions, get help, etc.
-->
<!-- -->
- There will be a short break (\~10 min) every hour
[@alexbuisine]: https://twitter.com/alexbuisine
[EphemeraSearch]: https://ephemerasearch.com/
@@ -74,8 +28,10 @@
(it will help to practice and memorize the content of the day)
- We recommend to take at least one hour to work on the exercises
- We'll try to finish a bit earlier each day so that you can have lab time
(if you understood the content of the day, it will be much faster)
(and if you can put some extra time that's even better)
- Each day will start with a quick review of the exercises of the previous day
- Ping us on @@CHAT@@!

View File

@@ -1 +1 @@
3.7
3.8

View File

@@ -1,4 +1,4 @@
# Pre-requirements
## Pre-requirements
- Be comfortable with the UNIX command line