mirror of
https://github.com/jpetazzo/container.training.git
synced 2026-03-02 17:30:20 +00:00
Compare commits
2 Commits
2023-09-en
...
2023-05-en
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a8e00fc7d | ||
|
|
e8c2b29c8f |
@@ -59,27 +59,6 @@ You don't **have to** install the CLI tools of the cloud provider(s) that you wa
|
||||
|
||||
If you want to provide your cloud credentials through other means, you will have to adjust the Terraform configuration files in `terraform/provider-config` accordingly.
|
||||
|
||||
Here is where we look for credentials for each provider:
|
||||
|
||||
- AWS: Terraform defaults; see [AWS provider documentation][creds-aws] (for instance, you can use the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables, or AWS config and profile files)
|
||||
- Azure: Terraform defaults; see [AzureRM provider documentation][creds-azure] (typically, you can authenticate with the `az` CLI and Terraform will pick it up automatically)
|
||||
- Civo: CLI configuration file (`~/.civo.json`)
|
||||
- Digital Ocean: CLI configuration file (`~/.config/doctl/config.yaml`)
|
||||
- Exoscale: CLI configuration file (`~/.config/exoscale/exoscale.toml`)
|
||||
- Google Cloud: FIXME, note that the project name is currently hard-coded to `prepare-tf`
|
||||
- Hetzner: CLI configuration file (`~/.config/hcloud/cli.toml`)
|
||||
- Linode: CLI configuration file (`~/.config/linode-cli`)
|
||||
- OpenStack: you will need to write a tfvars file (check [that exemple](terraform/virtual-machines/openstack/tfvars.example))
|
||||
- Oracle: Terraform defaults; see [OCI provider documentation][creds-oci] (for instance, you can set up API keys; or you can use a short-lived token generated by the OCI CLI with `oci session authenticate`)
|
||||
- OVH: Terraform defaults; see [OVH provider documentation][creds-ovh] (this typically involves setting up 5 `OVH_...` environment variables)
|
||||
- Scaleway: Terraform defaults; see [Scaleway provider documentation][creds-scw] (for instance, you can set environment variables, but it will also automatically pick up CLI authentication from `~/.config/scw/config.yaml`)
|
||||
|
||||
[creds-aws]: https://registry.terraform.io/providers/hashicorp/aws/latest/docs#authentication-and-configuration
|
||||
[creds-azure]: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs#authenticating-to-azure
|
||||
[creds-oci]: https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/terraformproviderconfiguration.htm#authentication
|
||||
[creds-ovh]: https://registry.terraform.io/providers/ovh/ovh/latest/docs#provider-configuration
|
||||
[creds-scw]: https://registry.terraform.io/providers/scaleway/scaleway/latest/docs#authentication
|
||||
|
||||
## General Workflow
|
||||
|
||||
- fork/clone repo
|
||||
|
||||
@@ -21,11 +21,6 @@ digitalocean-pvc)
|
||||
jq '.[] | select(.name | startswith("pvc-")) | .id' |
|
||||
xargs -n1 -P10 doctl compute volume delete --force
|
||||
;;
|
||||
scaleway-pvc)
|
||||
scw instance volume list --output json |
|
||||
jq '.[] | select(.name | contains("_pvc-")) | .id' |
|
||||
xargs -n1 -P10 scw instance volume delete
|
||||
;;
|
||||
*)
|
||||
echo "Unknown combination of provider ('$1') and resource ('$2')."
|
||||
;;
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
# deploy big cluster
|
||||
#TF_VAR_node_size=g6-standard-6 \
|
||||
#TF_VAR_nodes_per_cluster=5 \
|
||||
#TF_VAR_location=eu-west \
|
||||
|
||||
TF_VAR_node_size=PRO2-XS \
|
||||
TF_VAR_node_size=g6-standard-6 \
|
||||
TF_VAR_nodes_per_cluster=5 \
|
||||
TF_VAR_location=fr-par-2 \
|
||||
./labctl create --mode mk8s --settings settings/mk8s.env --provider scaleway --tag konk
|
||||
TF_VAR_location=eu-west \
|
||||
./labctl create --mode mk8s --settings settings/mk8s.env --provider linode --tag konk
|
||||
|
||||
# set kubeconfig file
|
||||
cp tags/konk/stage2/kubeconfig.101 ~/kubeconfig
|
||||
@@ -20,4 +16,4 @@ while read node address; do
|
||||
done
|
||||
|
||||
# vcluster all the things
|
||||
./labctl create --settings settings/mk8s.env --provider vcluster --mode mk8s --students 50
|
||||
./labctl create --settings settings/mk8s.env --provider vcluster --mode mk8s --students 27
|
||||
|
||||
@@ -126,7 +126,6 @@ set number
|
||||
set shiftwidth=2
|
||||
set softtabstop=2
|
||||
set nowrap
|
||||
set laststatus=2
|
||||
SQRL
|
||||
|
||||
pssh -I "sudo -u $USER_LOGIN tee /home/$USER_LOGIN/.tmux.conf" <<SQRL
|
||||
@@ -422,22 +421,9 @@ _cmd_kubebins() {
|
||||
need_tag
|
||||
|
||||
##VERSION##
|
||||
if [ "$KUBEVERSION" = "" ]; then
|
||||
KUBEVERSION="$(curl -fsSL https://cdn.dl.k8s.io/release/stable.txt | sed s/^v//)"
|
||||
fi
|
||||
|
||||
case "$KUBEVERSION" in
|
||||
1.19.*)
|
||||
ETCD_VERSION=v3.4.13
|
||||
CNI_VERSION=v0.8.7
|
||||
;;
|
||||
*)
|
||||
ETCD_VERSION=v3.5.9
|
||||
CNI_VERSION=v1.3.0
|
||||
;;
|
||||
esac
|
||||
|
||||
K8SBIN_VERSION="v$KUBEVERSION"
|
||||
ETCD_VERSION=v3.4.13
|
||||
K8SBIN_VERSION=v1.19.11 # Can't go to 1.20 because it requires a serviceaccount signing key.
|
||||
CNI_VERSION=v0.8.7
|
||||
ARCH=${ARCHITECTURE-amd64}
|
||||
pssh --timeout 300 "
|
||||
set -e
|
||||
@@ -461,12 +447,13 @@ _cmd_kubebins() {
|
||||
"
|
||||
}
|
||||
|
||||
_cmd kubepkgs "Install Kubernetes packages (kubectl, kubeadm, kubelet)"
|
||||
_cmd_kubepkgs() {
|
||||
_cmd kube "Setup kubernetes clusters with kubeadm (must be run AFTER deploy)"
|
||||
_cmd_kube() {
|
||||
TAG=$1
|
||||
need_tag
|
||||
|
||||
if [ "$KUBEVERSION" ]; then
|
||||
CLUSTER_CONFIGURATION_KUBERNETESVERSION='kubernetesVersion: "v'$KUBEVERSION'"'
|
||||
pssh "
|
||||
sudo tee /etc/apt/preferences.d/kubernetes <<EOF
|
||||
Package: kubectl kubeadm kubelet
|
||||
@@ -493,18 +480,6 @@ EOF"
|
||||
kubectl completion bash | sudo tee /etc/bash_completion.d/kubectl &&
|
||||
echo 'alias k=kubectl' | sudo tee /etc/bash_completion.d/k &&
|
||||
echo 'complete -F __start_kubectl k' | sudo tee -a /etc/bash_completion.d/k"
|
||||
}
|
||||
|
||||
_cmd kubeadm "Setup kubernetes clusters with kubeadm"
|
||||
_cmd_kubeadm() {
|
||||
TAG=$1
|
||||
need_tag
|
||||
|
||||
if [ "$KUBEVERSION" ]; then
|
||||
CLUSTER_CONFIGURATION_KUBERNETESVERSION='kubernetesVersion: "v'$KUBEVERSION'"'
|
||||
IGNORE_SYSTEMVERIFICATION="- SystemVerification"
|
||||
IGNORE_SWAP="- Swap"
|
||||
fi
|
||||
|
||||
# Install a valid configuration for containerd
|
||||
# (first, the CRI interface needs to be re-enabled;
|
||||
@@ -525,8 +500,6 @@ bootstrapTokens:
|
||||
nodeRegistration:
|
||||
ignorePreflightErrors:
|
||||
- NumCPU
|
||||
$IGNORE_SYSTEMVERIFICATION
|
||||
$IGNORE_SWAP
|
||||
---
|
||||
kind: JoinConfiguration
|
||||
apiVersion: kubeadm.k8s.io/v1beta3
|
||||
@@ -538,8 +511,6 @@ discovery:
|
||||
nodeRegistration:
|
||||
ignorePreflightErrors:
|
||||
- NumCPU
|
||||
$IGNORE_SYSTEMVERIFICATION
|
||||
$IGNORE_SWAP
|
||||
---
|
||||
kind: KubeletConfiguration
|
||||
apiVersion: kubelet.config.k8s.io/v1beta1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
CLUSTERSIZE=3
|
||||
CLUSTERSIZE=1
|
||||
|
||||
CLUSTERPREFIX=polykube
|
||||
CLUSTERPREFIX=dmuc
|
||||
|
||||
USER_LOGIN=k8s
|
||||
USER_PASSWORD=training
|
||||
@@ -10,11 +10,12 @@ STEPS="
|
||||
standardize
|
||||
clusterize
|
||||
tools
|
||||
kubepkgs
|
||||
kubebins
|
||||
docker
|
||||
disabledocker
|
||||
createuser
|
||||
webssh
|
||||
tailhist
|
||||
kubebins
|
||||
kubetools
|
||||
ips
|
||||
"
|
||||
@@ -1,26 +0,0 @@
|
||||
CLUSTERSIZE=1
|
||||
|
||||
CLUSTERPREFIX=monokube
|
||||
|
||||
# We're sticking to this in the first DMUC lab,
|
||||
# because it still works with Docker, and doesn't
|
||||
# require a ServiceAccount signing key.
|
||||
KUBEVERSION=1.19.11
|
||||
|
||||
USER_LOGIN=k8s
|
||||
USER_PASSWORD=training
|
||||
|
||||
STEPS="
|
||||
wait
|
||||
standardize
|
||||
clusterize
|
||||
tools
|
||||
docker
|
||||
disabledocker
|
||||
createuser
|
||||
webssh
|
||||
tailhist
|
||||
kubebins
|
||||
kubetools
|
||||
ips
|
||||
"
|
||||
@@ -18,8 +18,7 @@ STEPS="
|
||||
createuser
|
||||
webssh
|
||||
tailhist
|
||||
kubepkgs
|
||||
kubeadm
|
||||
kube
|
||||
kubetools
|
||||
kubetest
|
||||
"
|
||||
|
||||
@@ -14,8 +14,7 @@ STEPS="
|
||||
createuser
|
||||
webssh
|
||||
tailhist
|
||||
kubepkgs
|
||||
kubeadm
|
||||
kube
|
||||
kubetools
|
||||
kubetest
|
||||
"
|
||||
"
|
||||
@@ -14,8 +14,7 @@ STEPS="
|
||||
createuser
|
||||
webssh
|
||||
tailhist
|
||||
kubepkgs
|
||||
kubeadm
|
||||
kube
|
||||
kubetools
|
||||
kubetest
|
||||
"
|
||||
"
|
||||
@@ -15,8 +15,7 @@ STEPS="
|
||||
createuser
|
||||
webssh
|
||||
tailhist
|
||||
kubepkgs
|
||||
kubeadm
|
||||
kube
|
||||
kubetools
|
||||
kubetest
|
||||
"
|
||||
|
||||
@@ -7,7 +7,7 @@ STUDENTS=2
|
||||
#export TF_VAR_location=eu-north-1
|
||||
export TF_VAR_node_size=S
|
||||
|
||||
SETTINGS=admin-monokube
|
||||
SETTINGS=admin-dmuc
|
||||
TAG=$PREFIX-$SETTINGS
|
||||
./labctl create \
|
||||
--tag $TAG \
|
||||
@@ -15,7 +15,15 @@ TAG=$PREFIX-$SETTINGS
|
||||
--settings settings/$SETTINGS.env \
|
||||
--students $STUDENTS
|
||||
|
||||
SETTINGS=admin-polykube
|
||||
SETTINGS=admin-kubenet
|
||||
TAG=$PREFIX-$SETTINGS
|
||||
./labctl create \
|
||||
--tag $TAG \
|
||||
--provider $PROVIDER \
|
||||
--settings settings/$SETTINGS.env \
|
||||
--students $STUDENTS
|
||||
|
||||
SETTINGS=admin-kuberouter
|
||||
TAG=$PREFIX-$SETTINGS
|
||||
./labctl create \
|
||||
--tag $TAG \
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
#!/bin/sh
|
||||
exo zone
|
||||
@@ -1,8 +1,7 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
aws = {
|
||||
source = "hashicorp/aws"
|
||||
version = "~> 4.47.0"
|
||||
source = "hashicorp/aws"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../common.tf
|
||||
@@ -1 +0,0 @@
|
||||
../../providers/azure/config.tf
|
||||
@@ -1,22 +0,0 @@
|
||||
resource "azurerm_resource_group" "_" {
|
||||
name = var.cluster_name
|
||||
location = var.location
|
||||
}
|
||||
|
||||
resource "azurerm_kubernetes_cluster" "_" {
|
||||
name = var.cluster_name
|
||||
location = var.location
|
||||
dns_prefix = var.cluster_name
|
||||
identity {
|
||||
type = "SystemAssigned"
|
||||
}
|
||||
resource_group_name = azurerm_resource_group._.name
|
||||
default_node_pool {
|
||||
name = "x86"
|
||||
node_count = var.min_nodes_per_pool
|
||||
min_count = var.min_nodes_per_pool
|
||||
max_count = var.max_nodes_per_pool
|
||||
vm_size = local.node_size
|
||||
enable_auto_scaling = true
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
output "cluster_id" {
|
||||
value = azurerm_kubernetes_cluster._.id
|
||||
}
|
||||
|
||||
output "has_metrics_server" {
|
||||
value = true
|
||||
}
|
||||
|
||||
output "kubeconfig" {
|
||||
value = azurerm_kubernetes_cluster._.kube_config_raw
|
||||
sensitive = true
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
azurerm = {
|
||||
source = "hashicorp/azurerm"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../providers/azure/variables.tf
|
||||
@@ -11,23 +11,17 @@ data "oci_containerengine_cluster_option" "_" {
|
||||
locals {
|
||||
compartment_id = oci_identity_compartment._.id
|
||||
kubernetes_version = data.oci_containerengine_cluster_option._.kubernetes_versions[0]
|
||||
images = [
|
||||
for image in data.oci_containerengine_node_pool_option._.sources : image
|
||||
if can(regex("OKE", image.source_name))
|
||||
&& can(regex(substr(local.kubernetes_version, 1, -1), image.source_name))
|
||||
&& !can(regex("GPU", image.source_name))
|
||||
&& !can(regex("aarch64", image.source_name))
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
data "oci_identity_availability_domains" "_" {
|
||||
compartment_id = local.compartment_id
|
||||
}
|
||||
|
||||
data "oci_containerengine_node_pool_option" "_" {
|
||||
compartment_id = local.compartment_id
|
||||
node_pool_option_id = oci_containerengine_cluster._.id
|
||||
data "oci_core_images" "_" {
|
||||
compartment_id = local.compartment_id
|
||||
operating_system = "Oracle Linux"
|
||||
operating_system_version = "8"
|
||||
shape = local.shape
|
||||
}
|
||||
|
||||
resource "oci_containerengine_cluster" "_" {
|
||||
@@ -62,7 +56,7 @@ resource "oci_containerengine_node_pool" "_" {
|
||||
}
|
||||
}
|
||||
node_source_details {
|
||||
image_id = local.images[0].image_id
|
||||
image_id = data.oci_core_images._.images[0].id
|
||||
source_type = "image"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../common.tf
|
||||
@@ -1 +0,0 @@
|
||||
../../providers/ovh/config.tf
|
||||
@@ -1,18 +0,0 @@
|
||||
resource "ovh_cloud_project_kube" "_" {
|
||||
name = var.cluster_name
|
||||
region = var.location
|
||||
version = local.k8s_version
|
||||
}
|
||||
|
||||
resource "ovh_cloud_project_kube_nodepool" "_" {
|
||||
kube_id = ovh_cloud_project_kube._.id
|
||||
name = "x86"
|
||||
flavor_name = local.node_size
|
||||
desired_nodes = var.min_nodes_per_pool
|
||||
min_nodes = var.min_nodes_per_pool
|
||||
max_nodes = var.max_nodes_per_pool
|
||||
}
|
||||
|
||||
locals {
|
||||
k8s_version = "1.26"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
output "cluster_id" {
|
||||
value = ovh_cloud_project_kube._.id
|
||||
}
|
||||
|
||||
output "has_metrics_server" {
|
||||
value = false
|
||||
}
|
||||
|
||||
output "kubeconfig" {
|
||||
sensitive = true
|
||||
value = ovh_cloud_project_kube._.kubeconfig
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
ovh = {
|
||||
source = "ovh/ovh"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../providers/ovh/variables.tf
|
||||
@@ -44,5 +44,5 @@ locals {
|
||||
guest_api_server_port = local.node_port
|
||||
guest_api_server_url_new = "https://${local.guest_api_server_host}:${local.guest_api_server_port}"
|
||||
guest_api_server_url_old = yamldecode(local.kubeconfig_raw).clusters[0].cluster.server
|
||||
kubeconfig = replace(local.kubeconfig_raw, local.guest_api_server_url_old, local.guest_api_server_url_new)
|
||||
kubeconfig = replace(local.kubeconfig_raw, local.guest_api_server_url_old, local.guest_api_server_url_new)
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
variable "node_sizes" {
|
||||
type = map(any)
|
||||
default = {
|
||||
S = "d2-4"
|
||||
M = "d2-4"
|
||||
L = "d2-8"
|
||||
}
|
||||
}
|
||||
|
||||
variable "location" {
|
||||
type = string
|
||||
default = "BHS5"
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
variable "node_sizes" {
|
||||
type = map(any)
|
||||
type = map(any)
|
||||
default = {}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +1,14 @@
|
||||
resource "openstack_compute_instance_v2" "_" {
|
||||
for_each = local.nodes
|
||||
name = each.value.node_name
|
||||
image_name = data.openstack_images_image_v2._.name
|
||||
image_name = var.image
|
||||
flavor_name = each.value.node_size
|
||||
key_pair = openstack_compute_keypair_v2._.name
|
||||
key_pair = openstack_compute_keypair_v2._.name
|
||||
network {
|
||||
port = openstack_networking_port_v2._[each.key].id
|
||||
}
|
||||
}
|
||||
|
||||
data "openstack_images_image_v2" "_" {
|
||||
most_recent = true
|
||||
properties = {
|
||||
os = "ubuntu"
|
||||
version = "22.04"
|
||||
}
|
||||
}
|
||||
|
||||
resource "openstack_networking_port_v2" "_" {
|
||||
for_each = local.nodes
|
||||
network_id = openstack_networking_network_v2._.id
|
||||
|
||||
@@ -31,6 +31,10 @@ variable "external_network_id" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "image" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "node_sizes" {
|
||||
type = map(any)
|
||||
default = {}
|
||||
|
||||
@@ -4,11 +4,6 @@
|
||||
# another set of clusters while a first one is still running)
|
||||
# you should set the TF_VAR_cluster_name environment variable.
|
||||
|
||||
if ! [ "$TF_VAR_cluster_name" ]; then
|
||||
echo "Please set TF_VAR_cluster_name. Thanks."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd terraform/one-kubernetes
|
||||
|
||||
case "$1" in
|
||||
|
||||
@@ -5,7 +5,7 @@ chat: "[Mattermost](https://highfive.container.training/mattermost)"
|
||||
|
||||
gitrepo: github.com/jpetazzo/container.training
|
||||
|
||||
slides: https://2023-09-enix.container.training/
|
||||
slides: https://2023-05-enix.container.training/
|
||||
|
||||
#slidenumberprefix: "#SomeHashTag — "
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ chat: "[Mattermost](https://highfive.container.training/mattermost)"
|
||||
|
||||
gitrepo: github.com/jpetazzo/container.training
|
||||
|
||||
slides: https://2023-09-enix.container.training/
|
||||
slides: https://2023-05-enix.container.training/
|
||||
|
||||
#slidenumberprefix: "#SomeHashTag — "
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ chat: "[Mattermost](https://highfive.container.training/mattermost)"
|
||||
|
||||
gitrepo: github.com/jpetazzo/container.training
|
||||
|
||||
slides: https://2023-09-enix.container.training/
|
||||
slides: https://2023-05-enix.container.training/
|
||||
|
||||
#slidenumberprefix: "#SomeHashTag — "
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ chat: "[Mattermost](https://highfive.container.training/mattermost)"
|
||||
|
||||
gitrepo: github.com/jpetazzo/container.training
|
||||
|
||||
slides: https://2023-09-enix.container.training/
|
||||
slides: https://2023-05-enix.container.training/
|
||||
|
||||
#slidenumberprefix: "#SomeHashTag — "
|
||||
|
||||
|
||||
12
slides/5.yml
12
slides/5.yml
@@ -5,7 +5,7 @@ chat: "[Mattermost](https://highfive.container.training/mattermost)"
|
||||
|
||||
gitrepo: github.com/jpetazzo/container.training
|
||||
|
||||
slides: https://2023-09-enix.container.training/
|
||||
slides: https://2023-05-enix.container.training/
|
||||
|
||||
#slidenumberprefix: "#SomeHashTag — "
|
||||
|
||||
@@ -27,14 +27,14 @@ content:
|
||||
- shared/handson.md
|
||||
- k8s/architecture.md
|
||||
- k8s/deploymentslideshow.md
|
||||
- k8s/dmuc-easy.md
|
||||
- k8s/dmuc.md
|
||||
-
|
||||
- k8s/multinode.md
|
||||
- k8s/cni.md
|
||||
- k8s/interco.md
|
||||
-
|
||||
- k8s/dmuc-medium.md
|
||||
- k8s/dmuc-hard.md
|
||||
- k8s/cni-internals.md
|
||||
#- k8s/interco.md
|
||||
- k8s/apilb.md
|
||||
-
|
||||
- k8s/internal-apis.md
|
||||
- k8s/staticpods.md
|
||||
- k8s/cluster-upgrade.md
|
||||
|
||||
@@ -113,16 +113,22 @@ class: pic
|
||||
## Results
|
||||
|
||||
* [Dev-to-prod reduced from 9 months to 15 minutes (ING)](
|
||||
https://gallant-turing-d0d520.netlify.com/docker-case-studies/CS_ING_01.25.2015_1.pdf)
|
||||
https://www.docker.com/sites/default/files/CS_ING_01.25.2015_1.pdf)
|
||||
|
||||
* [Continuous integration job time reduced by more than 60% (BBC)](
|
||||
https://gallant-turing-d0d520.netlify.com/docker-case-studies/CS_BBCNews_01.25.2015_1.pdf)
|
||||
https://www.docker.com/sites/default/files/CS_BBCNews_01.25.2015_1.pdf)
|
||||
|
||||
* [Deploy 100 times a day instead of once a week (GILT)](
|
||||
https://gallant-turing-d0d520.netlify.com/docker-case-studies/CS_Gilt_Groupe_03.18.2015_0.pdf)
|
||||
https://www.docker.com/sites/default/files/CS_Gilt%20Groupe_03.18.2015_0.pdf)
|
||||
|
||||
* [70% infrastructure consolidation (MetLife)](
|
||||
https://www.youtube.com/watch?v=Bwt3xigvlj0)
|
||||
https://www.docker.com/customers/metlife-transforms-customer-experience-legacy-and-microservices-mashup)
|
||||
|
||||
* [60% infrastructure consolidation (Intesa Sanpaolo)](
|
||||
https://blog.docker.com/2017/11/intesa-sanpaolo-builds-resilient-foundation-banking-docker-enterprise-edition/)
|
||||
|
||||
* [14x application density; 60% of legacy datacenter migrated in 4 months (GE Appliances)](
|
||||
https://www.docker.com/customers/ge-uses-docker-enable-self-service-their-developers)
|
||||
|
||||
* etc.
|
||||
|
||||
|
||||
@@ -11,103 +11,103 @@
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td>Mardi 26 septembre 2023</td>
|
||||
<td>Mardi 9 mai 2023</td>
|
||||
<td>
|
||||
<a href="1.yml.html">Docker Intensif</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mercredi 27 septembre 2023</td>
|
||||
<td>Mercredi 10 mai 2023</td>
|
||||
<td>
|
||||
<a href="1.yml.html">Docker Intensif</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jeudi 28 septembre 2023</td>
|
||||
<td>Jeudi 11 mai 2023</td>
|
||||
<td>
|
||||
<a href="1.yml.html">Docker Intensif</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Vendredi 29 septembre 2023</td>
|
||||
<td>Vendredi 12 mai 2023</td>
|
||||
<td>
|
||||
<a href="1.yml.html">Docker Intensif</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mardi 3 octobre 2023</td>
|
||||
<td>Lundi 15 mai 2023</td>
|
||||
<td>
|
||||
<a href="2.yml.html">Fondamentaux Kubernetes</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mercredi 4 octobre 2023</td>
|
||||
<td>Mardi 16 mai 2023</td>
|
||||
<td>
|
||||
<a href="2.yml.html">Fondamentaux Kubernetes</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jeudi 5 octobre 2023</td>
|
||||
<td>Mercredi 17 mai 2023</td>
|
||||
<td>
|
||||
<a href="2.yml.html">Fondamentaux Kubernetes</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Vendredi 6 octobre 2023</td>
|
||||
<td>Lundi 22 mai 2023</td>
|
||||
<td>
|
||||
<a href="2.yml.html">Fondamentaux Kubernetes</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mardi 10 octobre 2023</td>
|
||||
<td>Mardi 23 mai 2023</td>
|
||||
<td>
|
||||
<a href="4.yml.html">Kubernetes Avancé</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mercredi 11 octobre 2023</td>
|
||||
<td>Mercredi 24 mai 2023</td>
|
||||
<td>
|
||||
<a href="4.yml.html">Kubernetes Avancé</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jeudi 12 octobre 2023</td>
|
||||
<td>Jeudi 25 mai 2023</td>
|
||||
<td>
|
||||
<a href="4.yml.html">Kubernetes Avancé</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Vendredi 13 octobre 2023</td>
|
||||
<td>Vendredi 26 mai 2023</td>
|
||||
<td>
|
||||
<a href="4.yml.html">Kubernetes Avancé</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Lundi 16 octobre 2023</td>
|
||||
<td>Mardi 30 mai 2023</td>
|
||||
<td>
|
||||
<a href="3.yml.html">Packaging d'applications pour Kubernetes</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mardi 17 octobre 2023</td>
|
||||
<td>Mercredi 31 mai 2023</td>
|
||||
<td>
|
||||
<a href="3.yml.html">Packaging d'applications pour Kubernetes</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mercredi 18 octobre 2023</td>
|
||||
<td>Jeudi 1er juin 2023</td>
|
||||
<td>
|
||||
<a href="3.yml.html">Packaging d'applications pour Kubernetes</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jeudi 19 octobre 2023</td>
|
||||
<td>Mardi 6 juin 2023</td>
|
||||
<td>
|
||||
<a href="5.yml.html">Opérer Kubernetes</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Vedredi 20 octobre 2023</td>
|
||||
<td>Mercredi 7 juin 2023</td>
|
||||
<td>
|
||||
<a href="5.yml.html">Opérer Kubernetes</a>
|
||||
</td>
|
||||
|
||||
@@ -981,6 +981,10 @@
|
||||
# event: LISA
|
||||
# title: Deploying and Scaling Applications with Docker Swarm
|
||||
|
||||
#2015-09-24-strangeloop
|
||||
|
||||
|
||||
|
||||
- title: Introduction to Docker and Containers
|
||||
slides: intro-selfpaced.yml.html
|
||||
|
||||
|
||||
@@ -111,6 +111,34 @@
|
||||
|
||||
---
|
||||
|
||||
## General guidelines
|
||||
|
||||
- To update a component, use whatever was used to install it
|
||||
|
||||
- If it's a distro package, update that distro package
|
||||
|
||||
- If it's a container or pod, update that container or pod
|
||||
|
||||
- If you used configuration management, update with that
|
||||
|
||||
---
|
||||
|
||||
## Know where your binaries come from
|
||||
|
||||
- Sometimes, we need to upgrade *quickly*
|
||||
|
||||
(when a vulnerability is announced and patched)
|
||||
|
||||
- If we are using an installer, we should:
|
||||
|
||||
- make sure it's using upstream packages
|
||||
|
||||
- or make sure that whatever packages it uses are current
|
||||
|
||||
- make sure we can tell it to pin specific component versions
|
||||
|
||||
---
|
||||
|
||||
## Important questions
|
||||
|
||||
- Should we upgrade the control plane before or after the kubelets?
|
||||
@@ -178,34 +206,6 @@ and kubectl, which can be one MINOR ahead or behind API server.]
|
||||
|
||||
---
|
||||
|
||||
## General guidelines
|
||||
|
||||
- To update a component, use whatever was used to install it
|
||||
|
||||
- If it's a distro package, update that distro package
|
||||
|
||||
- If it's a container or pod, update that container or pod
|
||||
|
||||
- If you used configuration management, update with that
|
||||
|
||||
---
|
||||
|
||||
## Know where your binaries come from
|
||||
|
||||
- Sometimes, we need to upgrade *quickly*
|
||||
|
||||
(when a vulnerability is announced and patched)
|
||||
|
||||
- If we are using an installer, we should:
|
||||
|
||||
- make sure it's using upstream packages
|
||||
|
||||
- or make sure that whatever packages it uses are current
|
||||
|
||||
- make sure we can tell it to pin specific component versions
|
||||
|
||||
---
|
||||
|
||||
## In practice
|
||||
|
||||
- We are going to update a few cluster components
|
||||
|
||||
@@ -1,374 +0,0 @@
|
||||
# Building our own cluster (hard)
|
||||
|
||||
- This section assumes that you already went through
|
||||
|
||||
*“Building our own cluster (medium)”*
|
||||
|
||||
- In that previous section, we built a cluster with a single node
|
||||
|
||||
- In this new section, we're going to add more nodes to the cluster
|
||||
|
||||
- Note: we will need the lab environment of that previous section
|
||||
|
||||
- If you haven't done it yet, you should go through that section first
|
||||
|
||||
---
|
||||
|
||||
## Our environment
|
||||
|
||||
- On `polykube1`, we should have our Kubernetes control plane
|
||||
|
||||
- We're also assuming that we have the kubeconfig file created earlier
|
||||
|
||||
(in `~/.kube/config`)
|
||||
|
||||
- We're going to work on `polykube2` and add it to the cluster
|
||||
|
||||
- This machine has exactly the same setup as `polykube1`
|
||||
|
||||
(Ubuntu LTS with CNI, etcd, and Kubernetes binaries installed)
|
||||
|
||||
- Note that we won't need the etcd binaries here
|
||||
|
||||
(the control plane will run solely on `polykube1`)
|
||||
|
||||
---
|
||||
|
||||
## Checklist
|
||||
|
||||
We need to:
|
||||
|
||||
- generate the kubeconfig file for `polykube2`
|
||||
|
||||
- install a container engine
|
||||
|
||||
- generate a CNI configuration file
|
||||
|
||||
- start kubelet
|
||||
|
||||
---
|
||||
|
||||
## Generating the kubeconfig file
|
||||
|
||||
- Ideally, we should generate a key pair and certificate for `polykube2`...
|
||||
|
||||
- ...and generate a kubeconfig file using these
|
||||
|
||||
- At the moment, for simplicity, we'll use the same key pair and certificate as earlier
|
||||
|
||||
- We have a couple of options:
|
||||
|
||||
- copy the required files (kubeconfig, key pair, certificate)
|
||||
|
||||
- "flatten" the kubeconfig file (embed the key and certificate within)
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## To flatten or not to flatten?
|
||||
|
||||
- "Flattening" the kubeconfig file can seem easier
|
||||
|
||||
(because it means we'll only have one file to move around)
|
||||
|
||||
- But it's easier to rotate the key or renew the certificate when they're in separate files
|
||||
|
||||
---
|
||||
|
||||
## Flatten and copy the kubeconfig file
|
||||
|
||||
- We'll flatten the file and copy it over
|
||||
|
||||
.lab[
|
||||
|
||||
- On `polykube1`, flatten the kubeconfig file:
|
||||
```bash
|
||||
kubectl config view --flatten > kubeconfig
|
||||
```
|
||||
|
||||
- Then copy it to `polykube2`:
|
||||
```bash
|
||||
scp kubeconfig polykube2:
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Generate CNI configuration
|
||||
|
||||
Back on `polykube2`, put the following in `/etc/cni/net.d/kube.conf`:
|
||||
|
||||
```json
|
||||
{
|
||||
"cniVersion": "0.3.1",
|
||||
"name": "kube",
|
||||
"type": "bridge",
|
||||
"bridge": "cni0",
|
||||
"isDefaultGateway": true,
|
||||
"ipMasq": true,
|
||||
"hairpinMode": true,
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": `"10.1.2.0/24"`
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note how we changed the subnet!
|
||||
|
||||
---
|
||||
|
||||
## Install container engine and start `kubelet`
|
||||
|
||||
.lab[
|
||||
|
||||
- Install `containerd`:
|
||||
```bash
|
||||
sudo apt-get install containerd -y
|
||||
```
|
||||
|
||||
- Start `containerd`:
|
||||
```bash
|
||||
sudo systemctl start containerd
|
||||
```
|
||||
|
||||
- Start `kubelet`:
|
||||
```bash
|
||||
sudo kubelet --kubeconfig kubeconfig
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
We're getting errors looking like:
|
||||
```
|
||||
"Post \"https://localhost:6443/api/v1/nodes\": ... connect: connection refused"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Updating the kubeconfig file
|
||||
|
||||
- Our kubeconfig file still references `localhost:6443`
|
||||
|
||||
- This was fine on `polykube1`
|
||||
|
||||
(where `kubelet` was connecting to the control plane running locally)
|
||||
|
||||
- On `polykube2`, we need to change that and put the address of the API server
|
||||
|
||||
(i.e. the address of `polykube1`)
|
||||
|
||||
.lab[
|
||||
|
||||
- Update the `kubeconfig` file:
|
||||
```bash
|
||||
sed -i s/localhost:6443/polykube1:6443/ kubeconfig
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Starting `kubelet`
|
||||
|
||||
- `kubelet` should now start correctly (hopefully!)
|
||||
|
||||
.lab[
|
||||
|
||||
- On `polykube2`, start `kubelet`:
|
||||
```bash
|
||||
sudo kubelet --kubeconfig kubeconfig
|
||||
```
|
||||
|
||||
- On `polykube1`, check that `polykube2` shows up and is `Ready`:
|
||||
```bash
|
||||
kubectl get nodes
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Testing connectivity
|
||||
|
||||
- From `polykube1`, can we connect to Pods running on `polykube2`? 🤔
|
||||
|
||||
.lab[
|
||||
|
||||
- Scale the test Deployment:
|
||||
```bash
|
||||
kubectl scale deployment blue --replicas=5
|
||||
```
|
||||
|
||||
- Get the IP addresses of the Pods:
|
||||
```bash
|
||||
kubectl get pods -o wide
|
||||
```
|
||||
|
||||
- Pick a Pod on `polykube2` and try to connect to it:
|
||||
```bash
|
||||
curl `10.1.2.2`
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
--
|
||||
|
||||
At that point, it doesn't work.
|
||||
|
||||
---
|
||||
|
||||
## Refresher on the *pod network*
|
||||
|
||||
- The *pod network* (or *pod-to-pod network*) has a few responsibilities:
|
||||
|
||||
- allocating and managing Pod IP addresses
|
||||
|
||||
- connecting Pods and Nodes
|
||||
|
||||
- connecting Pods together on a given node
|
||||
|
||||
- *connecting Pods together across nodes*
|
||||
|
||||
- That last part is the one that's not functioning in our cluster
|
||||
|
||||
- It typically requires some combination of routing, tunneling, bridging...
|
||||
|
||||
---
|
||||
|
||||
## Connecting networks together
|
||||
|
||||
- We can add manual routes between our nodes
|
||||
|
||||
- This requires adding `N x (N-1)` routes
|
||||
|
||||
(on each node, add a route to every other node)
|
||||
|
||||
- This will work on home labs where nodes are directly connected
|
||||
|
||||
(e.g. on an Ethernet switch, or same WiFi network, or a bridge between local VMs)
|
||||
|
||||
- ...Or on clouds where IP address filtering has been disabled
|
||||
|
||||
(by default, most cloud providers will discard packets going to unknown IP addresses)
|
||||
|
||||
- If IP address filtering is enabled, you'll have to use e.g. tunneling or overlay networks
|
||||
|
||||
---
|
||||
|
||||
## Important warning
|
||||
|
||||
- The technique that we are about to use doesn't work everywhere
|
||||
|
||||
- It only works if:
|
||||
|
||||
- all the nodes are directly connected to each other (at layer 2)
|
||||
|
||||
- the underlying network allows the IP addresses of our pods
|
||||
|
||||
- If we are on physical machines connected by a switch: OK
|
||||
|
||||
- If we are on virtual machines in a public cloud: NOT OK
|
||||
|
||||
- on AWS, we need to disable "source and destination checks" on our instances
|
||||
|
||||
- on OpenStack, we need to disable "port security" on our network ports
|
||||
|
||||
---
|
||||
|
||||
## Routing basics
|
||||
|
||||
- We need to tell *each* node:
|
||||
|
||||
"The subnet 10.1.N.0/24 is located on node N" (for all values of N)
|
||||
|
||||
- This is how we add a route on Linux:
|
||||
```bash
|
||||
ip route add 10.1.N.0/24 via W.X.Y.Z
|
||||
```
|
||||
|
||||
(where `W.X.Y.Z` is the internal IP address of node N)
|
||||
|
||||
- We can see the internal IP addresses of our nodes with:
|
||||
```bash
|
||||
kubectl get nodes -o wide
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Adding our route
|
||||
|
||||
- Let's add a route from `polykube1` to `polykube2`
|
||||
|
||||
.lab[
|
||||
|
||||
- Check the internal address of `polykube2`:
|
||||
```bash
|
||||
kubectl get node polykube2 -o wide
|
||||
```
|
||||
|
||||
- Now, on `polykube1`, add the route to the Pods running on `polykube2`:
|
||||
```bash
|
||||
sudo ip route add 10.1.2.0/24 via `A.B.C.D`
|
||||
```
|
||||
|
||||
- Finally, check that we can now connect to a Pod running on `polykube2`:
|
||||
```bash
|
||||
curl 10.1.2.2
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## What's next?
|
||||
|
||||
- The network configuration feels very manual:
|
||||
|
||||
- we had to generate the CNI configuration file (in `/etc/cni/net.d`)
|
||||
|
||||
- we had to manually update the nodes' routing tables
|
||||
|
||||
- Can we automate that?
|
||||
|
||||
**YES!**
|
||||
|
||||
- We could install something like [kube-router](https://www.kube-router.io/)
|
||||
|
||||
(which specifically takes care of the CNI configuration file and populates routing tables)
|
||||
|
||||
- Or we could also go with e.g. [Cilium](https://cilium.io/)
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## If you want to try Cilium...
|
||||
|
||||
- Add the `--root-ca-file` flag to the controller manager:
|
||||
|
||||
- use the certificate automatically generated by the API server
|
||||
<br/>
|
||||
(it should be in `/var/run/kubernetes/apiserver.crt`)
|
||||
|
||||
- or generate a key pair and certificate for the API server and point to
|
||||
that certificate
|
||||
|
||||
- without that, you'll get certificate validation errors
|
||||
<br/>
|
||||
(because in our Pods, the `ca.crt` file used to validate the API server will be empty)
|
||||
|
||||
- Check the Cilium [without kube-proxy][ciliumwithoutkubeproxy] instructions
|
||||
|
||||
(make sure to pass the API server IP address and port!)
|
||||
|
||||
- Other pod-to-pod network implementations might also require additional steps
|
||||
|
||||
[ciliumwithoutkubeproxy]: https://docs.cilium.io/en/stable/network/kubernetes/kubeproxy-free/#kubeproxy-free
|
||||
|
||||
???
|
||||
|
||||
:EN:- Connecting nodes and pods
|
||||
:FR:- Interconnecter les nœuds et les pods
|
||||
@@ -1,891 +0,0 @@
|
||||
# Building our own cluster (medium)
|
||||
|
||||
- This section assumes that you already went through
|
||||
|
||||
*“Building our own cluster (easy)”*
|
||||
|
||||
- In that section, we saw how to run each control plane component manually...
|
||||
|
||||
...but with an older version of Kubernetes (1.19)
|
||||
|
||||
- In this section, we're going to do something similar...
|
||||
|
||||
...but with recent versions of Kubernetes!
|
||||
|
||||
- Note: we won't need the lab environment of that previous section
|
||||
|
||||
(we're going to build a new cluster from scratch)
|
||||
|
||||
---
|
||||
|
||||
## What remains the same
|
||||
|
||||
- We'll use machines with Kubernetes binaries pre-downloaded
|
||||
|
||||
- We'll run individual components by hand
|
||||
|
||||
(etcd, API server, controller manager, scheduler, kubelet)
|
||||
|
||||
- We'll run on a single node
|
||||
|
||||
(but we'll be laying the groundwork to add more nodes)
|
||||
|
||||
- We'll get the cluster to the point where we can run and expose pods
|
||||
|
||||
---
|
||||
|
||||
## What's different
|
||||
|
||||
- We'll need to generate TLS keys and certificates
|
||||
|
||||
(because it's mandatory with recent versions of Kubernetes)
|
||||
|
||||
- Things will be *a little bit more* secure
|
||||
|
||||
(but still not 100% secure, far from it!)
|
||||
|
||||
- We'll use containerd instead of Docker
|
||||
|
||||
(you could probably try with CRI-O or another CRI engine, too)
|
||||
|
||||
- We'll need to set up CNI for networking
|
||||
|
||||
- *And we won't do everything as root this time (but we might use `sudo` a lot)*
|
||||
|
||||
---
|
||||
|
||||
## Our environment
|
||||
|
||||
- We will use the machine indicated as `polykube1`
|
||||
|
||||
- This machine:
|
||||
|
||||
- runs Ubuntu LTS
|
||||
|
||||
- has Kubernetes, etcd, and CNI binaries installed
|
||||
|
||||
- but nothing is running
|
||||
|
||||
---
|
||||
|
||||
## Checking our environment
|
||||
|
||||
- Let's make sure we have everything we need first
|
||||
|
||||
.lab[
|
||||
|
||||
- Log into the `polykube1` machine
|
||||
|
||||
- Check available versions:
|
||||
```bash
|
||||
etcd -version
|
||||
kube-apiserver --version
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## The plan
|
||||
|
||||
We'll follow the same methodology as for the "easy" section
|
||||
|
||||
1. Start API server
|
||||
|
||||
2. Interact with it (create Deployment and Service)
|
||||
|
||||
3. See what's broken
|
||||
|
||||
4. Fix it and go back to step 2 until it works!
|
||||
|
||||
---
|
||||
|
||||
## Dealing with multiple processes
|
||||
|
||||
- Again, we are going to start many processes
|
||||
|
||||
- Depending on what you're comfortable with, you can:
|
||||
|
||||
- open multiple windows and multiple SSH connections
|
||||
|
||||
- use a terminal multiplexer like screen or tmux
|
||||
|
||||
- put processes in the background with `&`
|
||||
<br/>(warning: log output might get confusing to read!)
|
||||
|
||||
---
|
||||
|
||||
## Starting API server
|
||||
|
||||
.lab[
|
||||
|
||||
- Try to start the API server:
|
||||
```bash
|
||||
kube-apiserver
|
||||
# It will complain about permission to /var/run/kubernetes
|
||||
|
||||
sudo kube-apiserver
|
||||
# Now it will complain about a bunch of missing flags, including:
|
||||
# --etcd-servers
|
||||
# --service-account-issuer
|
||||
# --service-account-signing-key-file
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
Just like before, we'll need to start etcd.
|
||||
|
||||
But we'll also need some TLS keys!
|
||||
|
||||
---
|
||||
|
||||
## Generating TLS keys
|
||||
|
||||
- There are many ways to generate TLS keys (and certificates)
|
||||
|
||||
- A very popular and modern tool to do that is [cfssl]
|
||||
|
||||
- We're going to use the old-fashioned [openssl] CLI
|
||||
|
||||
- Feel free to use cfssl or any other tool if you prefer!
|
||||
|
||||
[cfssl]: https://github.com/cloudflare/cfssl#using-the-command-line-tool
|
||||
[openssl]: https://www.openssl.org/docs/man3.0/man1/
|
||||
|
||||
---
|
||||
|
||||
## How many keys do we need?
|
||||
|
||||
At the very least, we need the following two keys:
|
||||
|
||||
- ServiceAccount key pair
|
||||
|
||||
- API client key pair, aka "CA key"
|
||||
|
||||
(technically, we will need a *certificate* for that key pair)
|
||||
|
||||
But if we wanted to tighten the cluster security, we'd need many more...
|
||||
|
||||
---
|
||||
|
||||
## The other keys
|
||||
|
||||
These keys are not strictly necessary at this point:
|
||||
|
||||
- etcd key pair
|
||||
|
||||
*without that key, communication with etcd will be insecure*
|
||||
|
||||
- API server endpoint key pair
|
||||
|
||||
*the API server will generate this one automatically if we don't*
|
||||
|
||||
- kubelet key pair (used by API server to connect to kubelets)
|
||||
|
||||
*without that key, commands like kubectl logs/exec will be insecure*
|
||||
|
||||
---
|
||||
|
||||
## Would you like some auth with that?
|
||||
|
||||
If we want to enable authentication and authorization, we also need various API client key pairs signed by the "CA key" mentioned earlier. That would include (non-exhaustive list):
|
||||
|
||||
- controller manager key pair
|
||||
|
||||
- scheduler key pair
|
||||
|
||||
- in most cases: kube-proxy (or equivalent) key pair
|
||||
|
||||
- in most cases: key pairs for the nodes joining the cluster
|
||||
|
||||
(these might be generated through TLS bootstrap tokens)
|
||||
|
||||
- key pairs for users that will interact with the clusters
|
||||
|
||||
(unless another authentication mechanism like OIDC is used)
|
||||
|
||||
---
|
||||
|
||||
## Generating our keys and certificates
|
||||
|
||||
.lab[
|
||||
|
||||
- Generate the ServiceAccount key pair:
|
||||
```bash
|
||||
openssl genrsa -out sa.key 2048
|
||||
```
|
||||
|
||||
- Generate the CA key pair:
|
||||
```bash
|
||||
openssl genrsa -out ca.key 2048
|
||||
```
|
||||
|
||||
- Generate a self-signed certificate for the CA key:
|
||||
```bash
|
||||
openssl x509 -new -key ca.key -out ca.cert -subj /CN=kubernetes/
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Starting etcd
|
||||
|
||||
- This one is easy!
|
||||
|
||||
.lab[
|
||||
|
||||
- Start etcd:
|
||||
```bash
|
||||
etcd
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
Note: if you want a bit of extra challenge, you can try
|
||||
to generate the etcd key pair and use it.
|
||||
|
||||
(You will need to pass it to etcd and to the API server.)
|
||||
|
||||
---
|
||||
|
||||
## Starting API server
|
||||
|
||||
- We need to use the keys and certificate that we just generated
|
||||
|
||||
.lab[
|
||||
|
||||
- Start the API server:
|
||||
```bash
|
||||
sudo kube-apiserver \
|
||||
--etcd-servers=http://localhost:2379 \
|
||||
--service-account-signing-key-file=sa.key \
|
||||
--service-account-issuer=https://kubernetes \
|
||||
--service-account-key-file=sa.key \
|
||||
--client-ca-file=ca.cert
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
The API server should now start.
|
||||
|
||||
But can we really use it? 🤔
|
||||
|
||||
---
|
||||
|
||||
## Trying `kubectl`
|
||||
|
||||
- Let's try some simple `kubectl` command
|
||||
|
||||
.lab[
|
||||
|
||||
- Try to list Namespaces:
|
||||
```bash
|
||||
kubectl get namespaces
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
We're getting an error message like this one:
|
||||
|
||||
```
|
||||
The connection to the server localhost:8080 was refused -
|
||||
did you specify the right host or port?
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What's going on?
|
||||
|
||||
- Recent versions of Kubernetes don't support unauthenticated API access
|
||||
|
||||
- The API server doesn't support listening on plain HTTP anymore
|
||||
|
||||
- `kubectl` still tries to connect to `localhost:8080` by default
|
||||
|
||||
- But there is nothing listening there
|
||||
|
||||
- Our API server listens on port 6443, using TLS
|
||||
|
||||
---
|
||||
|
||||
## Trying to access the API server
|
||||
|
||||
- Let's use `curl` first to confirm that everything works correctly
|
||||
|
||||
(and then we will move to `kubectl`)
|
||||
|
||||
.lab[
|
||||
|
||||
- Try to connect with `curl`:
|
||||
```bash
|
||||
curl https://localhost:6443
|
||||
# This will fail because the API server certificate is unknown.
|
||||
```
|
||||
|
||||
- Try again, skipping certificate verification:
|
||||
```bash
|
||||
curl --insecure https://localhost:6443
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
We should now see an `Unauthorized` Kubernetes API error message.
|
||||
</br>
|
||||
We need to authenticate with our key and certificate.
|
||||
|
||||
---
|
||||
|
||||
## Authenticating with the API server
|
||||
|
||||
- For the time being, we can use the CA key and cert directly
|
||||
|
||||
- In a real world scenario, we would *never* do that!
|
||||
|
||||
(because we don't want the CA key to be out there in the wild)
|
||||
|
||||
.lab[
|
||||
|
||||
- Try again, skipping cert verification, and using the CA key and cert:
|
||||
```bash
|
||||
curl --insecure --key ca.key --cert ca.cert https://localhost:6443
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
We should see a list of API routes.
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## Doing it right
|
||||
|
||||
In the future, instead of using the CA key and certificate,
|
||||
we should generate a new key, and a certificate for that key,
|
||||
signed by the CA key.
|
||||
|
||||
Then we can use that new key and certificate to authenticate.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
### Generate a key pair
|
||||
openssl genrsa -out user.key
|
||||
|
||||
### Extract the public key
|
||||
openssl pkey -in user.key -out user.pub -pubout
|
||||
|
||||
### Generate a certificate signed by the CA key
|
||||
openssl x509 -new -key ca.key -force_pubkey user.pub -out user.cert \
|
||||
-subj /CN=kubernetes-user/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Writing a kubeconfig file
|
||||
|
||||
- We now want to use `kubectl` instead of `curl`
|
||||
|
||||
- We'll need to write a kubeconfig file for `kubectl`
|
||||
|
||||
- There are many way to do that; here, we're going to use `kubectl config`
|
||||
|
||||
- We'll need to:
|
||||
|
||||
- set the "cluster" (API server endpoint)
|
||||
|
||||
- set the "credentials" (the key and certficate)
|
||||
|
||||
- set the "context" (referencing the cluster and credentials)
|
||||
|
||||
- use that context (make it the default that `kubectl` will use)
|
||||
|
||||
---
|
||||
|
||||
## Set the cluster
|
||||
|
||||
The "cluster" section holds the API server endpoint.
|
||||
|
||||
.lab[
|
||||
|
||||
- Set the API server endpoint:
|
||||
```bash
|
||||
kubectl config set-cluster polykube --server=https://localhost:6443
|
||||
```
|
||||
|
||||
- Don't verify the API server certificate:
|
||||
```bash
|
||||
kubectl config set-cluster polykube --insecure-skip-tls-verify
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Set the credentials
|
||||
|
||||
The "credentials" section can hold a TLS key and certificate, or a token, or configuration information for a plugin (for instance, when using AWS EKS or GCP GKE, they use a plugin).
|
||||
|
||||
.lab[
|
||||
|
||||
- Set the client key and certificate:
|
||||
```bash
|
||||
kubectl config set-credentials polykube \
|
||||
--client-key ca.key \
|
||||
--client-certificate ca.cert
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Set and use the context
|
||||
|
||||
The "context" section references the "cluster" and "credentials" that we defined earlier.
|
||||
|
||||
(It can also optionally reference a Namespace.)
|
||||
|
||||
.lab[
|
||||
|
||||
- Set the "context":
|
||||
```bash
|
||||
kubectl config set-context polykube --cluster polykube --user polykube
|
||||
```
|
||||
|
||||
- Set that context to be the default context:
|
||||
```bash
|
||||
kubectl config use-context polykube
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Review the kubeconfig filfe
|
||||
|
||||
The kubeconfig file should look like this:
|
||||
|
||||
.small[
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
insecure-skip-tls-verify: true
|
||||
server: https://localhost:6443
|
||||
name: polykube
|
||||
contexts:
|
||||
- context:
|
||||
cluster: polykube
|
||||
user: polykube
|
||||
name: polykube
|
||||
current-context: polykube
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: polykube
|
||||
user:
|
||||
client-certificate: /root/ca.cert
|
||||
client-key: /root/ca.key
|
||||
```
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Trying the kubeconfig file
|
||||
|
||||
- We should now be able to access our cluster's API!
|
||||
|
||||
.lab[
|
||||
|
||||
- Try to list Namespaces:
|
||||
```bash
|
||||
kubectl get namespaces
|
||||
```
|
||||
]
|
||||
|
||||
This should show the classic `default`, `kube-system`, etc.
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## Do we need `--client-ca-file` ?
|
||||
|
||||
Technically, we didn't need to specify the `--client-ca-file` flag!
|
||||
|
||||
But without that flag, no client can be authenticated.
|
||||
|
||||
Which means that we wouldn't be able to issue any API request!
|
||||
|
||||
---
|
||||
|
||||
## Running pods
|
||||
|
||||
- We can now try to create a Deployment
|
||||
|
||||
.lab[
|
||||
|
||||
- Create a Deployment:
|
||||
```bash
|
||||
kubectl create deployment blue --image=jpetazzo/color
|
||||
```
|
||||
|
||||
- Check the results:
|
||||
```bash
|
||||
kubectl get deployments,replicasets,pods
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
Our Deployment exists, but not the Replica Set or Pod.
|
||||
|
||||
We need to run the controller manager.
|
||||
|
||||
---
|
||||
|
||||
## Running the controller manager
|
||||
|
||||
- Previously, we used the `--master` flag to pass the API server address
|
||||
|
||||
- Now, we need to authenticate properly
|
||||
|
||||
- The simplest way at this point is probably to use the same kubeconfig file!
|
||||
|
||||
.lab[
|
||||
|
||||
- Start the controller manager:
|
||||
```bash
|
||||
kube-controller-manager --kubeconfig .kube/config
|
||||
```
|
||||
|
||||
- Check the results:
|
||||
```bash
|
||||
kubectl get deployments,replicasets,pods
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## What's next?
|
||||
|
||||
- Normally, the last commands showed us a Pod in `Pending` state
|
||||
|
||||
- We need two things to continue:
|
||||
|
||||
- the scheduler (to assign the Pod to a Node)
|
||||
|
||||
- a Node!
|
||||
|
||||
- We're going to run `kubelet` to register the Node with the cluster
|
||||
|
||||
---
|
||||
|
||||
## Running `kubelet`
|
||||
|
||||
- Let's try to run `kubelet` and see what happens!
|
||||
|
||||
.lab[
|
||||
|
||||
- Start `kubelet`:
|
||||
```bash
|
||||
sudo kubelet
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
We should see an error about connecting to `containerd.sock`.
|
||||
|
||||
We need to run a container engine!
|
||||
|
||||
(For instance, `containerd`.)
|
||||
|
||||
---
|
||||
|
||||
## Running `containerd`
|
||||
|
||||
- We need to install and start `containerd`
|
||||
|
||||
- You could try another engine if you wanted
|
||||
|
||||
(but there might be complications!)
|
||||
|
||||
.lab[
|
||||
|
||||
- Install `containerd`:
|
||||
```bash
|
||||
sudo apt-get install containerd
|
||||
```
|
||||
|
||||
- Start `containerd`:
|
||||
```bash
|
||||
sudo containerd
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## Configuring `containerd`
|
||||
|
||||
Depending on how we install `containerd`, it might need a bit of extra configuration.
|
||||
|
||||
Watch for the following symptoms:
|
||||
|
||||
- `containerd` refuses to start
|
||||
|
||||
(rare, unless there is an *invalid* configuration)
|
||||
|
||||
- `containerd` starts but `kubelet` can't connect
|
||||
|
||||
(could be the case if the configuration disables the CRI socket)
|
||||
|
||||
- `containerd` starts and things work but Pods keep being killed
|
||||
|
||||
(may happen if there is a mismatch in the cgroups driver)
|
||||
|
||||
---
|
||||
|
||||
## Starting `kubelet` for good
|
||||
|
||||
- Now that `containerd` is running, `kubelet` should start!
|
||||
|
||||
.lab[
|
||||
|
||||
- Try to start `kubelet`:
|
||||
```bash
|
||||
sudo kubelet
|
||||
```
|
||||
|
||||
- In another terminal, check if our Node is now visible:
|
||||
```bash
|
||||
sudo kubectl get nodes
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
`kubelet` should now start, but our Node doesn't show up in `kubectl get nodes`!
|
||||
|
||||
This is because without a kubeconfig file, `kubelet` runs in standalone mode:
|
||||
<br/>
|
||||
it will not connect to a Kubernetes API server, and will only start *static pods*.
|
||||
|
||||
---
|
||||
|
||||
## Passing the kubeconfig file
|
||||
|
||||
- Let's start `kubelet` again, with our kubeconfig file
|
||||
|
||||
.lab[
|
||||
|
||||
- Stop `kubelet` (e.g. with `Ctrl-C`)
|
||||
|
||||
- Restart it with the kubeconfig file:
|
||||
```bash
|
||||
sudo kubelet --kubeconfig .kube/config
|
||||
```
|
||||
|
||||
- Check our list of Nodes:
|
||||
```bash
|
||||
kubectl get nodes
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
This time, our Node should show up!
|
||||
|
||||
---
|
||||
|
||||
## Node readiness
|
||||
|
||||
- However, our Node shows up as `NotReady`
|
||||
|
||||
- If we wait a few minutes, the `kubelet` logs will tell us why:
|
||||
|
||||
*we're missing a CNI configuration!*
|
||||
|
||||
- As a result, the containers can't be connected to the network
|
||||
|
||||
- `kubelet` detects that and doesn't become `Ready` until this is fixed
|
||||
|
||||
---
|
||||
|
||||
## CNI configuration
|
||||
|
||||
- We need to provide a CNI configuration
|
||||
|
||||
- This is a file in `/etc/cni/net.d`
|
||||
|
||||
(the name of the file doesn't matter; the first file in lexicographic order will be used)
|
||||
|
||||
- Usually, when installing a "CNI plugin¹", this file gets installed automatically
|
||||
|
||||
- Here, we are going to write that file manually
|
||||
|
||||
.footnote[¹Technically, a *pod network*; typically running as a DaemonSet, which will install the file with a `hostPath` volume.]
|
||||
|
||||
---
|
||||
|
||||
## Our CNI configuration
|
||||
|
||||
Create the following file in e.g. `/etc/cni/net.d/kube.conf`:
|
||||
|
||||
```json
|
||||
{
|
||||
"cniVersion": "0.3.1",
|
||||
"name": "kube",
|
||||
"type": "bridge",
|
||||
"bridge": "cni0",
|
||||
"isDefaultGateway": true,
|
||||
"ipMasq": true,
|
||||
"hairpinMode": true,
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.1.0/24"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
That's all we need - `kubelet` will detect and validate the file automatically!
|
||||
|
||||
---
|
||||
|
||||
## Checking our Node again
|
||||
|
||||
- After a short time (typically about 10 seconds) the Node should be `Ready`
|
||||
|
||||
.lab[
|
||||
|
||||
- Wait until the Node is `Ready`:
|
||||
```bash
|
||||
kubectl get nodes
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
If the Node doesn't show up as `Ready`, check the `kubelet` logs.
|
||||
|
||||
---
|
||||
|
||||
## What's next?
|
||||
|
||||
- At this point, we have a `Pending` Pod and a `Ready` Node
|
||||
|
||||
- All we need is the scheduler to bind the former to the latter
|
||||
|
||||
.lab[
|
||||
|
||||
- Run the scheduler:
|
||||
```bash
|
||||
kube-scheduler --kubeconfig .kube/config
|
||||
```
|
||||
|
||||
- Check that the Pod gets assigned to the Node and becomes `Running`:
|
||||
```bash
|
||||
kubectl get pods
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Check network access
|
||||
|
||||
- Let's check that we can connect to our Pod, and that the Pod can connect outside
|
||||
|
||||
.lab[
|
||||
|
||||
- Get the Pod's IP address:
|
||||
```bash
|
||||
kubectl get pods -o wide
|
||||
```
|
||||
|
||||
- Connect to the Pod (make sure to update the IP address):
|
||||
```bash
|
||||
curl `10.1.1.2`
|
||||
```
|
||||
|
||||
- Check that the Pod has external connectivity too:
|
||||
```bash
|
||||
kubectl exec `blue-xxxxxxxxxx-yyyyy` -- ping -c3 1.1
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Expose our Deployment
|
||||
|
||||
- We can now try to expose the Deployment and connect to the ClusterIP
|
||||
|
||||
.lab[
|
||||
|
||||
- Expose the Deployment:
|
||||
```bash
|
||||
kubectl expose deployment blue --port=80
|
||||
```
|
||||
|
||||
- Retrieve the ClusterIP:
|
||||
```bash
|
||||
kubectl get services
|
||||
```
|
||||
|
||||
- Try to connect to the ClusterIP:
|
||||
```bash
|
||||
curl `10.0.0.42`
|
||||
```
|
||||
]
|
||||
|
||||
At this point, it won't work - we need to run `kube-proxy`!
|
||||
|
||||
---
|
||||
|
||||
## Running `kube-proxy`
|
||||
|
||||
- We need to run `kube-proxy`
|
||||
|
||||
(also passing it our kubeconfig file)
|
||||
|
||||
.lab[
|
||||
|
||||
- Run `kube-proxy`:
|
||||
```bash
|
||||
sudo kube-proxy --kubeconfig .kube/config
|
||||
```
|
||||
|
||||
- Try again to connect to the ClusterIP:
|
||||
```bash
|
||||
curl `10.0.0.42`
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
This time, it should work.
|
||||
|
||||
---
|
||||
|
||||
## What's next?
|
||||
|
||||
- Scale up the Deployment, and check that load balancing works properly
|
||||
|
||||
- Enable RBAC, and generate individual certificates for each controller
|
||||
|
||||
(check the [certificate paths][certpath] section in the Kubernetes documentation
|
||||
for a detailed list of all the certificates and keys that are used by the
|
||||
control plane, and which flags are used by which components to configure them!)
|
||||
|
||||
- Add more nodes to the cluster
|
||||
|
||||
*Feel free to try these if you want to get additional hands-on experience!*
|
||||
|
||||
[certpath]: https://kubernetes.io/docs/setup/best-practices/certificates/#certificate-paths
|
||||
|
||||
???
|
||||
|
||||
:EN:- Setting up control plane certificates
|
||||
:EN:- Implementing a basic CNI configuration
|
||||
:FR:- Mettre en place les certificats du plan de contrôle
|
||||
:FR:- Réaliser un configuration CNI basique
|
||||
@@ -1,4 +1,4 @@
|
||||
# Building our own cluster (easy)
|
||||
# Building our own cluster
|
||||
|
||||
- Let's build our own cluster!
|
||||
|
||||
@@ -33,7 +33,10 @@
|
||||
|
||||
## Our environment
|
||||
|
||||
- We will use the machine indicated as `monokube1`
|
||||
- We will use the machine indicated as `dmuc1`
|
||||
|
||||
(this stands for "Dessine Moi Un Cluster" or "Draw Me A Sheep",
|
||||
<br/>in homage to Saint-Exupery's "The Little Prince")
|
||||
|
||||
- This machine:
|
||||
|
||||
@@ -45,33 +48,13 @@
|
||||
|
||||
---
|
||||
|
||||
## The fine print
|
||||
|
||||
- We're going to use a *very old* version of Kubernetes
|
||||
|
||||
(specifically, 1.19)
|
||||
|
||||
- Why?
|
||||
|
||||
- It's much easier to set up than recent versions
|
||||
|
||||
- it's compatible with Docker (no need to set up CNI)
|
||||
|
||||
- it doesn't require a ServiceAccount keypair
|
||||
|
||||
- it can be exposed over plain HTTP (insecure but easier)
|
||||
|
||||
- We'll do that, and later, move to recent versions of Kubernetes!
|
||||
|
||||
---
|
||||
|
||||
## Checking our environment
|
||||
|
||||
- Let's make sure we have everything we need first
|
||||
|
||||
.lab[
|
||||
|
||||
- Log into the `monokube1` machine
|
||||
- Log into the `dmuc1` machine
|
||||
|
||||
- Get root:
|
||||
```bash
|
||||
@@ -545,38 +528,7 @@ clusters:
|
||||
|
||||
]
|
||||
|
||||
If it works: great!
|
||||
|
||||
If it complains about a "cgroup driver", check the next slide.
|
||||
|
||||
---
|
||||
|
||||
## Cgroup drivers
|
||||
|
||||
- Cgroups ("control groups") are a Linux kernel feature
|
||||
|
||||
- They're used to account and limit resources
|
||||
|
||||
(e.g.: memory, CPU, block I/O...)
|
||||
|
||||
- There are multiple ways to manipulate cgroups, including:
|
||||
|
||||
- through a pseudo-filesystem (typically mounted in /sys/fs/cgroup)
|
||||
|
||||
- through systemd
|
||||
|
||||
- Kubelet and the container engine need to agree on which method to use
|
||||
|
||||
---
|
||||
|
||||
## Setting the cgroup driver
|
||||
|
||||
- If kubelet refused to start, mentioning a cgroup driver issue, try:
|
||||
```bash
|
||||
kubelet --kubeconfig ~/.kube/config --cgroup-driver=systemd
|
||||
```
|
||||
|
||||
- That *should* do the trick!
|
||||
Success!
|
||||
|
||||
---
|
||||
|
||||
@@ -595,7 +547,7 @@ If it complains about a "cgroup driver", check the next slide.
|
||||
|
||||
Our node should show up.
|
||||
|
||||
Its name will be its hostname (it should be `monokube1`).
|
||||
Its name will be its hostname (it should be `dmuc1`).
|
||||
|
||||
---
|
||||
|
||||
@@ -100,7 +100,7 @@ class: extra-details
|
||||
|
||||
- We present 3 methods to obtain a certificate
|
||||
|
||||
- We suggest that you use method 1 (self-signed certificate)
|
||||
- We suggest that we use method 1 (self-signed certificate)
|
||||
|
||||
- it's the simplest and fastest method
|
||||
|
||||
|
||||
@@ -429,11 +429,11 @@ troubleshoot easily, without having to poke holes in our firewall.
|
||||
|
||||
- The API documentation has a lot of detail about the format of various objects: <!-- ##VERSION## -->
|
||||
|
||||
- [NetworkPolicy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#networkpolicy-v1-networking-k8s-io)
|
||||
- [NetworkPolicy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#networkpolicy-v1-networking-k8s-io)
|
||||
|
||||
- [NetworkPolicySpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#networkpolicyspec-v1-networking-k8s-io)
|
||||
- [NetworkPolicySpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#networkpolicyspec-v1-networking-k8s-io)
|
||||
|
||||
- [NetworkPolicyIngressRule](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#networkpolicyingressrule-v1-networking-k8s-io)
|
||||
- [NetworkPolicyIngressRule](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#networkpolicyingressrule-v1-networking-k8s-io)
|
||||
|
||||
- etc.
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
|
||||
- plugins (compiled in API server; enabled/disabled by reconfiguration)
|
||||
|
||||
- webhooks (registered dynamically)
|
||||
- webhooks (registesred dynamically)
|
||||
|
||||
- Admission control has many other uses
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
## Pre-requirements
|
||||
# Pre-requirements
|
||||
|
||||
- Kubernetes concepts
|
||||
|
||||
|
||||
@@ -32,14 +32,12 @@ content:
|
||||
- k8s/architecture.md
|
||||
#- k8s/internal-apis.md
|
||||
- k8s/deploymentslideshow.md
|
||||
- k8s/dmuc-easy.md
|
||||
- k8s/dmuc.md
|
||||
-
|
||||
- k8s/dmuc-medium.md
|
||||
- k8s/dmuc-hard.md
|
||||
#- k8s/multinode.md
|
||||
#- k8s/cni.md
|
||||
- k8s/multinode.md
|
||||
- k8s/cni.md
|
||||
- k8s/cni-internals.md
|
||||
#- k8s/interco.md
|
||||
- k8s/interco.md
|
||||
-
|
||||
- k8s/apilb.md
|
||||
#- k8s/setup-overview.md
|
||||
|
||||
@@ -32,13 +32,11 @@ content:
|
||||
- k8s/architecture.md
|
||||
- k8s/internal-apis.md
|
||||
- k8s/deploymentslideshow.md
|
||||
- k8s/dmuc-easy.md
|
||||
- - k8s/dmuc-medium.md
|
||||
- k8s/dmuc-hard.md
|
||||
#- k8s/multinode.md
|
||||
#- k8s/cni.md
|
||||
- k8s/dmuc.md
|
||||
- - k8s/multinode.md
|
||||
- k8s/cni.md
|
||||
- k8s/cni-internals.md
|
||||
#- k8s/interco.md
|
||||
- k8s/interco.md
|
||||
- - k8s/apilb.md
|
||||
- k8s/setup-overview.md
|
||||
#- k8s/setup-devel.md
|
||||
|
||||
@@ -30,15 +30,13 @@ content:
|
||||
- k8s/architecture.md
|
||||
- k8s/internal-apis.md
|
||||
- k8s/deploymentslideshow.md
|
||||
- k8s/dmuc-easy.md
|
||||
- k8s/dmuc.md
|
||||
- #2
|
||||
- k8s/dmuc-medium.md
|
||||
- k8s/dmuc-hard.md
|
||||
#- k8s/multinode.md
|
||||
#- k8s/cni.md
|
||||
#- k8s/interco.md
|
||||
- k8s/cni-internals.md
|
||||
- k8s/multinode.md
|
||||
- k8s/cni.md
|
||||
- k8s/interco.md
|
||||
- #3
|
||||
- k8s/cni-internals.md
|
||||
- k8s/apilb.md
|
||||
- k8s/control-plane-auth.md
|
||||
- |
|
||||
|
||||
@@ -151,11 +151,9 @@ content:
|
||||
- k8s/owners-and-dependents.md
|
||||
- k8s/events.md
|
||||
-
|
||||
- k8s/dmuc-easy.md
|
||||
- k8s/dmuc-medium.md
|
||||
- k8s/dmuc-hard.md
|
||||
#- k8s/multinode.md
|
||||
#- k8s/cni.md
|
||||
- k8s/dmuc.md
|
||||
- k8s/multinode.md
|
||||
- k8s/cni.md
|
||||
- k8s/cni-internals.md
|
||||
- k8s/apilb.md
|
||||
- k8s/staticpods.md
|
||||
|
||||
@@ -61,11 +61,12 @@
|
||||
|
||||
(sauf le dernier jour)
|
||||
|
||||
- Mardi: 16h30-17h30
|
||||
- Mardi: 15h-16h
|
||||
|
||||
- Mercredi: 15h30-16h30
|
||||
- Mercredi: 16h-17h
|
||||
|
||||
- Jeudi: 17h-18h
|
||||
|
||||
- Jeudi: 14h30-15h30
|
||||
|
||||
- Sur [Jitsi][jitsi] (lien "visioconf" sur le portail de formation)
|
||||
|
||||
@@ -73,4 +74,4 @@
|
||||
|
||||
[qdnd]: https://www.youtube.com/channel/UCOAhkxpryr_BKybt9wIw-NQ
|
||||
[ndeloof]: https://github.com/ndeloof
|
||||
[jitsi]: https://training.enix.io/jitsi-magic/jitsi.container.training/AlloDockerAutomne2023
|
||||
[jitsi]: https://training.enix.io/jitsi-magic/jitsi.container.training/AlloDockerMai2023
|
||||
|
||||
@@ -1019,7 +1019,7 @@ class: prom-manual
|
||||
--mount type=bind,source=/,target=/rootfs \
|
||||
prom/node-exporter \
|
||||
--path.procfs /host/proc \
|
||||
--path.sysfs /host/sys \
|
||||
--path.sysfs /host/proc \
|
||||
--collector.filesystem.ignored-mount-points "^/(sys|proc|dev|host|etc)($|/)"
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user