mirror of
https://github.com/jpetazzo/container.training.git
synced 2026-03-03 01:40:19 +00:00
Compare commits
52 Commits
2020-05-ar
...
2020-09-fw
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c0411d6b8f | ||
|
|
f7b38325d4 | ||
|
|
14679999be | ||
|
|
29c6d2876a | ||
|
|
a02e7429ad | ||
|
|
fee0be7f09 | ||
|
|
d98fcbce87 | ||
|
|
35320837e5 | ||
|
|
d73e597198 | ||
|
|
b4c0378114 | ||
|
|
efdc4fcfa9 | ||
|
|
c32fcc81bb | ||
|
|
f6930042bd | ||
|
|
2e2767b090 | ||
|
|
115cc5e0c0 | ||
|
|
d252fe254b | ||
|
|
7d96562042 | ||
|
|
4ded8c699d | ||
|
|
620a3df798 | ||
|
|
d28723f07a | ||
|
|
f2334d2d1b | ||
|
|
ddf79eebc7 | ||
|
|
6467264ff5 | ||
|
|
55fcff9333 | ||
|
|
8fb7ea3908 | ||
|
|
7dd72f123f | ||
|
|
ff95066006 | ||
|
|
8146c4dabe | ||
|
|
17aea33beb | ||
|
|
9770f81a1c | ||
|
|
0cb9095303 | ||
|
|
ffded8469b | ||
|
|
0e892cf8b4 | ||
|
|
b87efbd6e9 | ||
|
|
1a24b530d6 | ||
|
|
122ffec5c2 | ||
|
|
276a2dbdda | ||
|
|
2836b58078 | ||
|
|
0d065788a4 | ||
|
|
14271a4df0 | ||
|
|
412d029d0c | ||
|
|
f960230f8e | ||
|
|
774c8a0e31 | ||
|
|
4671a981a7 | ||
|
|
b9743a5f8c | ||
|
|
df4980750c | ||
|
|
9467c7309e | ||
|
|
86b0380a77 | ||
|
|
eb9052ae9a | ||
|
|
8f85332d8a | ||
|
|
0479ad2285 | ||
|
|
986d7eb9c2 |
@@ -9,21 +9,21 @@ services:
|
||||
|
||||
etcd:
|
||||
network_mode: "service:pause"
|
||||
image: k8s.gcr.io/etcd:3.4.3
|
||||
image: k8s.gcr.io/etcd:3.4.9
|
||||
command: etcd
|
||||
|
||||
kube-apiserver:
|
||||
network_mode: "service:pause"
|
||||
image: k8s.gcr.io/hyperkube:v1.17.2
|
||||
image: k8s.gcr.io/hyperkube:v1.18.8
|
||||
command: kube-apiserver --etcd-servers http://127.0.0.1:2379 --address 0.0.0.0 --disable-admission-plugins=ServiceAccount --allow-privileged
|
||||
|
||||
kube-controller-manager:
|
||||
network_mode: "service:pause"
|
||||
image: k8s.gcr.io/hyperkube:v1.17.2
|
||||
image: k8s.gcr.io/hyperkube:v1.18.8
|
||||
command: kube-controller-manager --master http://localhost:8080 --allocate-node-cidrs --cluster-cidr=10.CLUSTER.0.0/16
|
||||
"Edit the CLUSTER placeholder first. Then, remove this line.":
|
||||
|
||||
kube-scheduler:
|
||||
network_mode: "service:pause"
|
||||
image: k8s.gcr.io/hyperkube:v1.17.2
|
||||
image: k8s.gcr.io/hyperkube:v1.18.8
|
||||
command: kube-scheduler --master http://localhost:8080
|
||||
|
||||
@@ -9,20 +9,20 @@ services:
|
||||
|
||||
etcd:
|
||||
network_mode: "service:pause"
|
||||
image: k8s.gcr.io/etcd:3.4.3
|
||||
image: k8s.gcr.io/etcd:3.4.9
|
||||
command: etcd
|
||||
|
||||
kube-apiserver:
|
||||
network_mode: "service:pause"
|
||||
image: k8s.gcr.io/hyperkube:v1.17.2
|
||||
image: k8s.gcr.io/hyperkube:v1.18.8
|
||||
command: kube-apiserver --etcd-servers http://127.0.0.1:2379 --address 0.0.0.0 --disable-admission-plugins=ServiceAccount
|
||||
|
||||
kube-controller-manager:
|
||||
network_mode: "service:pause"
|
||||
image: k8s.gcr.io/hyperkube:v1.17.2
|
||||
image: k8s.gcr.io/hyperkube:v1.18.8
|
||||
command: kube-controller-manager --master http://localhost:8080
|
||||
|
||||
kube-scheduler:
|
||||
network_mode: "service:pause"
|
||||
image: k8s.gcr.io/hyperkube:v1.17.2
|
||||
image: k8s.gcr.io/hyperkube:v1.18.8
|
||||
command: kube-scheduler --master http://localhost:8080
|
||||
|
||||
@@ -4,6 +4,10 @@ metadata:
|
||||
name: coffees.container.training
|
||||
spec:
|
||||
group: container.training
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
scope: Namespaced
|
||||
names:
|
||||
plural: coffees
|
||||
@@ -11,25 +15,4 @@ spec:
|
||||
kind: Coffee
|
||||
shortNames:
|
||||
- cof
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
properties:
|
||||
spec:
|
||||
required:
|
||||
- taste
|
||||
properties:
|
||||
taste:
|
||||
description: Subjective taste of that kind of coffee bean
|
||||
type: string
|
||||
additionalPrinterColumns:
|
||||
- jsonPath: .spec.taste
|
||||
description: Subjective taste of that kind of coffee bean
|
||||
name: Taste
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: Age
|
||||
type: date
|
||||
|
||||
|
||||
37
k8s/coffee-3.yaml
Normal file
37
k8s/coffee-3.yaml
Normal file
@@ -0,0 +1,37 @@
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: coffees.container.training
|
||||
spec:
|
||||
group: container.training
|
||||
scope: Namespaced
|
||||
names:
|
||||
plural: coffees
|
||||
singular: coffee
|
||||
kind: Coffee
|
||||
shortNames:
|
||||
- cof
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [ spec ]
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
taste:
|
||||
description: Subjective taste of that kind of coffee bean
|
||||
type: string
|
||||
required: [ taste ]
|
||||
additionalPrinterColumns:
|
||||
- jsonPath: .spec.taste
|
||||
description: Subjective taste of that kind of coffee bean
|
||||
name: Taste
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: Age
|
||||
type: date
|
||||
@@ -9,9 +9,9 @@ spec:
|
||||
kind: Coffee
|
||||
apiVersion: container.training/v1alpha1
|
||||
metadata:
|
||||
name: robusta
|
||||
name: excelsa
|
||||
spec:
|
||||
taste: stronger
|
||||
taste: fruity
|
||||
---
|
||||
kind: Coffee
|
||||
apiVersion: container.training/v1alpha1
|
||||
@@ -23,7 +23,12 @@ spec:
|
||||
kind: Coffee
|
||||
apiVersion: container.training/v1alpha1
|
||||
metadata:
|
||||
name: excelsa
|
||||
name: robusta
|
||||
spec:
|
||||
taste: fruity
|
||||
|
||||
taste: stronger
|
||||
bitterness: high
|
||||
---
|
||||
kind: Coffee
|
||||
apiVersion: container.training/v1alpha1
|
||||
metadata:
|
||||
name: java
|
||||
|
||||
@@ -52,7 +52,7 @@ data:
|
||||
- add_kubernetes_metadata:
|
||||
in_cluster: true
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: filebeat
|
||||
@@ -60,6 +60,9 @@ metadata:
|
||||
labels:
|
||||
k8s-app: filebeat
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
k8s-app: filebeat
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
|
||||
@@ -27,7 +27,7 @@ spec:
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- "apk update && apk add curl && curl https://github.com/jpetazzo.keys > /root/.ssh/authorized_keys"
|
||||
- "mkdir -p /root/.ssh && apk update && apk add curl && curl https://github.com/jpetazzo.keys > /root/.ssh/authorized_keys"
|
||||
containers:
|
||||
- name: web
|
||||
image: nginx
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,10 @@ spec:
|
||||
command: ["sh", "-c", "if [ -d /vol/lost+found ]; then rmdir /vol/lost+found; fi"]
|
||||
containers:
|
||||
- name: postgres
|
||||
image: postgres:11
|
||||
image: postgres:12
|
||||
env:
|
||||
- name: POSTGRES_HOST_AUTH_METHOD
|
||||
value: trust
|
||||
volumeMounts:
|
||||
- mountPath: /var/lib/postgresql/data
|
||||
name: postgres
|
||||
|
||||
@@ -1,28 +1,17 @@
|
||||
apiVersion: extensions/v1beta1
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
deployment.kubernetes.io/revision: "2"
|
||||
creationTimestamp: null
|
||||
generation: 1
|
||||
labels:
|
||||
app: socat
|
||||
name: socat
|
||||
namespace: kube-system
|
||||
selfLink: /apis/extensions/v1beta1/namespaces/kube-system/deployments/socat
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: socat
|
||||
strategy:
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 1
|
||||
type: RollingUpdate
|
||||
template:
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app: socat
|
||||
spec:
|
||||
@@ -34,34 +23,19 @@ spec:
|
||||
image: alpine
|
||||
imagePullPolicy: Always
|
||||
name: socat
|
||||
resources: {}
|
||||
terminationMessagePath: /dev/termination-log
|
||||
terminationMessagePolicy: File
|
||||
dnsPolicy: ClusterFirst
|
||||
restartPolicy: Always
|
||||
schedulerName: default-scheduler
|
||||
securityContext: {}
|
||||
terminationGracePeriodSeconds: 30
|
||||
status: {}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app: socat
|
||||
name: socat
|
||||
namespace: kube-system
|
||||
selfLink: /api/v1/namespaces/kube-system/services/socat
|
||||
spec:
|
||||
externalTrafficPolicy: Cluster
|
||||
ports:
|
||||
- port: 80
|
||||
protocol: TCP
|
||||
targetPort: 80
|
||||
selector:
|
||||
app: socat
|
||||
sessionAffinity: None
|
||||
type: NodePort
|
||||
status:
|
||||
loadBalancer: {}
|
||||
|
||||
103
k8s/traefik-v1.yaml
Normal file
103
k8s/traefik-v1.yaml
Normal file
@@ -0,0 +1,103 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: traefik-ingress-controller
|
||||
namespace: kube-system
|
||||
---
|
||||
kind: DaemonSet
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
name: traefik-ingress-controller
|
||||
namespace: kube-system
|
||||
labels:
|
||||
k8s-app: traefik-ingress-lb
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
k8s-app: traefik-ingress-lb
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: traefik-ingress-lb
|
||||
name: traefik-ingress-lb
|
||||
spec:
|
||||
tolerations:
|
||||
- effect: NoSchedule
|
||||
operator: Exists
|
||||
hostNetwork: true
|
||||
serviceAccountName: traefik-ingress-controller
|
||||
terminationGracePeriodSeconds: 60
|
||||
containers:
|
||||
- image: traefik:1.7
|
||||
name: traefik-ingress-lb
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
hostPort: 80
|
||||
- name: admin
|
||||
containerPort: 8080
|
||||
hostPort: 8080
|
||||
securityContext:
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
add:
|
||||
- NET_BIND_SERVICE
|
||||
args:
|
||||
- --api
|
||||
- --kubernetes
|
||||
- --logLevel=INFO
|
||||
---
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: traefik-ingress-service
|
||||
namespace: kube-system
|
||||
spec:
|
||||
selector:
|
||||
k8s-app: traefik-ingress-lb
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
name: web
|
||||
- protocol: TCP
|
||||
port: 8080
|
||||
name: admin
|
||||
---
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
metadata:
|
||||
name: traefik-ingress-controller
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- services
|
||||
- endpoints
|
||||
- secrets
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- extensions
|
||||
resources:
|
||||
- ingresses
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
metadata:
|
||||
name: traefik-ingress-controller
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: traefik-ingress-controller
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: traefik-ingress-controller
|
||||
namespace: kube-system
|
||||
111
k8s/traefik-v2.yaml
Normal file
111
k8s/traefik-v2.yaml
Normal file
@@ -0,0 +1,111 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: traefik-ingress-controller
|
||||
namespace: kube-system
|
||||
---
|
||||
kind: DaemonSet
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
name: traefik-ingress-controller
|
||||
namespace: kube-system
|
||||
labels:
|
||||
k8s-app: traefik-ingress-lb
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
k8s-app: traefik-ingress-lb
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: traefik-ingress-lb
|
||||
name: traefik-ingress-lb
|
||||
spec:
|
||||
tolerations:
|
||||
- effect: NoSchedule
|
||||
operator: Exists
|
||||
hostNetwork: true
|
||||
serviceAccountName: traefik-ingress-controller
|
||||
terminationGracePeriodSeconds: 60
|
||||
containers:
|
||||
- image: traefik
|
||||
name: traefik-ingress-lb
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
hostPort: 80
|
||||
- name: admin
|
||||
containerPort: 8080
|
||||
hostPort: 8080
|
||||
securityContext:
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
add:
|
||||
- NET_BIND_SERVICE
|
||||
args:
|
||||
- --accesslog
|
||||
- --api
|
||||
- --api.insecure
|
||||
- --log.level=INFO
|
||||
- --metrics.prometheus
|
||||
- --providers.kubernetescrd
|
||||
- --providers.kubernetesingress
|
||||
---
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: traefik-ingress-service
|
||||
namespace: kube-system
|
||||
annotations:
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/port: "8080"
|
||||
prometheus.io/path: "/metrics"
|
||||
spec:
|
||||
selector:
|
||||
k8s-app: traefik-ingress-lb
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
name: web
|
||||
- protocol: TCP
|
||||
port: 8080
|
||||
name: admin
|
||||
---
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
metadata:
|
||||
name: traefik-ingress-controller
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- services
|
||||
- endpoints
|
||||
- secrets
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- extensions
|
||||
resources:
|
||||
- ingresses
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
metadata:
|
||||
name: traefik-ingress-controller
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: traefik-ingress-controller
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: traefik-ingress-controller
|
||||
namespace: kube-system
|
||||
103
k8s/traefik.yaml
103
k8s/traefik.yaml
@@ -1,103 +0,0 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: traefik-ingress-controller
|
||||
namespace: kube-system
|
||||
---
|
||||
kind: DaemonSet
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
name: traefik-ingress-controller
|
||||
namespace: kube-system
|
||||
labels:
|
||||
k8s-app: traefik-ingress-lb
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
k8s-app: traefik-ingress-lb
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: traefik-ingress-lb
|
||||
name: traefik-ingress-lb
|
||||
spec:
|
||||
tolerations:
|
||||
- effect: NoSchedule
|
||||
operator: Exists
|
||||
hostNetwork: true
|
||||
serviceAccountName: traefik-ingress-controller
|
||||
terminationGracePeriodSeconds: 60
|
||||
containers:
|
||||
- image: traefik:1.7
|
||||
name: traefik-ingress-lb
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
hostPort: 80
|
||||
- name: admin
|
||||
containerPort: 8080
|
||||
hostPort: 8080
|
||||
securityContext:
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
add:
|
||||
- NET_BIND_SERVICE
|
||||
args:
|
||||
- --api
|
||||
- --kubernetes
|
||||
- --logLevel=INFO
|
||||
---
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: traefik-ingress-service
|
||||
namespace: kube-system
|
||||
spec:
|
||||
selector:
|
||||
k8s-app: traefik-ingress-lb
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
name: web
|
||||
- protocol: TCP
|
||||
port: 8080
|
||||
name: admin
|
||||
---
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
metadata:
|
||||
name: traefik-ingress-controller
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- services
|
||||
- endpoints
|
||||
- secrets
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- extensions
|
||||
resources:
|
||||
- ingresses
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
metadata:
|
||||
name: traefik-ingress-controller
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: traefik-ingress-controller
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: traefik-ingress-controller
|
||||
namespace: kube-system
|
||||
1
k8s/traefik.yaml
Symbolic link
1
k8s/traefik.yaml
Symbolic link
@@ -0,0 +1 @@
|
||||
traefik-v1.yaml
|
||||
24
prepare-vms/infra/example.openstack-cli
Normal file
24
prepare-vms/infra/example.openstack-cli
Normal file
@@ -0,0 +1,24 @@
|
||||
INFRACLASS=openstack-cli
|
||||
|
||||
# Copy that file to e.g. openstack or ovh, then customize it.
|
||||
# Some Openstack providers (like OVHcloud) will let you download
|
||||
# a file containing credentials. That's what you need to use.
|
||||
# The file below contains some example values.
|
||||
export OS_AUTH_URL=https://auth.cloud.ovh.net/v3/
|
||||
export OS_IDENTITY_API_VERSION=3
|
||||
export OS_USER_DOMAIN_NAME=${OS_USER_DOMAIN_NAME:-"Default"}
|
||||
export OS_PROJECT_DOMAIN_NAME=${OS_PROJECT_DOMAIN_NAME:-"Default"}
|
||||
export OS_TENANT_ID=abcd1234
|
||||
export OS_TENANT_NAME="0123456"
|
||||
export OS_USERNAME="user-xyz123"
|
||||
export OS_PASSWORD=AbCd1234
|
||||
export OS_REGION_NAME="GRA7"
|
||||
|
||||
# And then some values to indicate server type, image, etc.
|
||||
# You can see available flavors with `openstack flavor list`
|
||||
export OS_FLAVOR=s1-4
|
||||
# You can see available images with `openstack image list`
|
||||
export OS_IMAGE=896c5f54-51dc-44f0-8c22-ce99ba7164df
|
||||
# You can create a key with `openstack keypair create --public-key ~/.ssh/id_rsa.pub containertraining`
|
||||
export OS_KEY=containertraining
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
INFRACLASS=openstack
|
||||
INFRACLASS=openstack-tf
|
||||
|
||||
# If you are using OpenStack, copy this file (e.g. to "openstack" or "enix")
|
||||
# and customize the variables below.
|
||||
export TF_VAR_user="jpetazzo"
|
||||
@@ -6,4 +7,4 @@ export TF_VAR_tenant="training"
|
||||
export TF_VAR_domain="Default"
|
||||
export TF_VAR_password="..."
|
||||
export TF_VAR_auth_url="https://api.r1.nxs.enix.io/v3"
|
||||
export TF_VAR_flavor="GP1.S"
|
||||
export TF_VAR_flavor="GP1.S"
|
||||
5
prepare-vms/infra/hetzner
Normal file
5
prepare-vms/infra/hetzner
Normal file
@@ -0,0 +1,5 @@
|
||||
INFRACLASS=hetzner
|
||||
if ! [ -f ~/.config/hcloud/cli.toml ]; then
|
||||
warn "~/.config/hcloud/cli.toml not found."
|
||||
warn "Make sure that the Hetzner CLI (hcloud) is installed and configured."
|
||||
fi
|
||||
1
prepare-vms/infra/scaleway
Normal file
1
prepare-vms/infra/scaleway
Normal file
@@ -0,0 +1 @@
|
||||
INFRACLASS=scaleway
|
||||
@@ -65,6 +65,27 @@ _cmd_deploy() {
|
||||
sleep 1
|
||||
done"
|
||||
|
||||
# Special case for scaleway since it doesn't come with sudo
|
||||
if [ "$INFRACLASS" = "scaleway" ]; then
|
||||
pssh -l root "
|
||||
grep DEBIAN_FRONTEND /etc/environment || echo DEBIAN_FRONTEND=noninteractive >> /etc/environment
|
||||
grep cloud-init /etc/sudoers && rm /etc/sudoers
|
||||
apt-get update && apt-get install sudo -y"
|
||||
fi
|
||||
|
||||
# FIXME
|
||||
# Special case for hetzner since it doesn't have an ubuntu user
|
||||
#if [ "$INFRACLASS" = "hetzner" ]; then
|
||||
# pssh -l root "
|
||||
#[ -d /home/ubuntu ] ||
|
||||
# useradd ubuntu -m -s /bin/bash
|
||||
#echo 'ubuntu ALL=(ALL:ALL) NOPASSWD:ALL' > /etc/sudoers.d/ubuntu
|
||||
#[ -d /home/ubuntu/.ssh ] ||
|
||||
# install --owner=ubuntu --mode=700 --directory /home/ubuntu/.ssh
|
||||
#[ -f /home/ubuntu/.ssh/authorized_keys ] ||
|
||||
# install --owner=ubuntu --mode=600 /root/.ssh/authorized_keys --target-directory /home/ubuntu/.ssh"
|
||||
#fi
|
||||
|
||||
# Copy settings and install Python YAML parser
|
||||
pssh -I tee /tmp/settings.yaml <tags/$TAG/settings.yaml
|
||||
pssh "
|
||||
@@ -131,19 +152,19 @@ _cmd_kubebins() {
|
||||
cd /usr/local/bin
|
||||
if ! [ -x etcd ]; then
|
||||
##VERSION##
|
||||
curl -L https://github.com/etcd-io/etcd/releases/download/v3.4.3/etcd-v3.4.3-linux-amd64.tar.gz \
|
||||
curl -L https://github.com/etcd-io/etcd/releases/download/v3.4.9/etcd-v3.4.9-linux-amd64.tar.gz \
|
||||
| sudo tar --strip-components=1 --wildcards -zx '*/etcd' '*/etcdctl'
|
||||
fi
|
||||
if ! [ -x hyperkube ]; then
|
||||
##VERSION##
|
||||
curl -L https://dl.k8s.io/v1.17.2/kubernetes-server-linux-amd64.tar.gz \
|
||||
curl -L https://dl.k8s.io/v1.18.8/kubernetes-server-linux-amd64.tar.gz \
|
||||
| sudo tar --strip-components=3 -zx \
|
||||
kubernetes/server/bin/kube{ctl,let,-proxy,-apiserver,-scheduler,-controller-manager}
|
||||
fi
|
||||
sudo mkdir -p /opt/cni/bin
|
||||
cd /opt/cni/bin
|
||||
if ! [ -x bridge ]; then
|
||||
curl -L https://github.com/containernetworking/plugins/releases/download/v0.7.6/cni-plugins-amd64-v0.7.6.tgz \
|
||||
curl -L https://github.com/containernetworking/plugins/releases/download/v0.8.6/cni-plugins-linux-amd64-v0.8.6.tgz \
|
||||
| sudo tar -zx
|
||||
fi
|
||||
"
|
||||
@@ -179,7 +200,7 @@ _cmd_kube() {
|
||||
pssh --timeout 200 "
|
||||
if i_am_first_node && [ ! -f /etc/kubernetes/admin.conf ]; then
|
||||
kubeadm token generate > /tmp/token &&
|
||||
sudo kubeadm init $EXTRA_KUBEADM --token \$(cat /tmp/token) --apiserver-cert-extra-sans \$(cat /tmp/ipv4)
|
||||
sudo kubeadm init $EXTRA_KUBEADM --token \$(cat /tmp/token) --apiserver-cert-extra-sans \$(cat /tmp/ipv4) --ignore-preflight-errors=NumCPU
|
||||
fi"
|
||||
|
||||
# Put kubeconfig in ubuntu's and docker's accounts
|
||||
@@ -216,13 +237,13 @@ _cmd_kube() {
|
||||
# Install kubectx and kubens
|
||||
pssh "
|
||||
[ -d kubectx ] || git clone https://github.com/ahmetb/kubectx &&
|
||||
sudo ln -sf /home/ubuntu/kubectx/kubectx /usr/local/bin/kctx &&
|
||||
sudo ln -sf /home/ubuntu/kubectx/kubens /usr/local/bin/kns &&
|
||||
sudo cp /home/ubuntu/kubectx/completion/*.bash /etc/bash_completion.d &&
|
||||
sudo ln -sf \$HOME/kubectx/kubectx /usr/local/bin/kctx &&
|
||||
sudo ln -sf \$HOME/kubectx/kubens /usr/local/bin/kns &&
|
||||
sudo cp \$HOME/kubectx/completion/*.bash /etc/bash_completion.d &&
|
||||
[ -d kube-ps1 ] || git clone https://github.com/jonmosco/kube-ps1 &&
|
||||
sudo -u docker sed -i s/docker-prompt/kube_ps1/ /home/docker/.bashrc &&
|
||||
sudo -u docker tee -a /home/docker/.bashrc <<EOF
|
||||
. /home/ubuntu/kube-ps1/kube-ps1.sh
|
||||
. \$HOME/kube-ps1/kube-ps1.sh
|
||||
KUBE_PS1_PREFIX=""
|
||||
KUBE_PS1_SUFFIX=""
|
||||
KUBE_PS1_SYMBOL_ENABLE="false"
|
||||
@@ -249,16 +270,19 @@ EOF"
|
||||
# Install kustomize
|
||||
pssh "
|
||||
if [ ! -x /usr/local/bin/kustomize ]; then
|
||||
curl -L https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v3.5.4/kustomize_v3.5.1_linux_amd64.tar.gz |
|
||||
##VERSION##
|
||||
curl -L https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v3.6.1/kustomize_v3.6.1_linux_amd64.tar.gz |
|
||||
sudo tar -C /usr/local/bin -zx kustomize
|
||||
echo complete -C /usr/local/bin/kustomize kustomize | sudo tee /etc/bash_completion.d/kustomize
|
||||
fi"
|
||||
|
||||
# Install ship
|
||||
# Note: 0.51.3 is the last version that doesn't display GIN-debug messages
|
||||
# (don't want to get folks confused by that!)
|
||||
pssh "
|
||||
if [ ! -x /usr/local/bin/ship ]; then
|
||||
##VERSION##
|
||||
curl -L https://github.com/replicatedhq/ship/releases/download/v0.40.0/ship_0.40.0_linux_amd64.tar.gz |
|
||||
curl -L https://github.com/replicatedhq/ship/releases/download/v0.51.3/ship_0.51.3_linux_amd64.tar.gz |
|
||||
sudo tar -C /usr/local/bin -zx ship
|
||||
fi"
|
||||
|
||||
@@ -292,23 +316,26 @@ _cmd_kubetest() {
|
||||
set -e
|
||||
if i_am_first_node; then
|
||||
which kubectl
|
||||
for NODE in \$(awk /[0-9]\$/\ {print\ \\\$2} /etc/hosts); do
|
||||
for NODE in \$(grep [0-9]\$ /etc/hosts | grep -v ^127 | awk {print\ \\\$2}); do
|
||||
echo \$NODE ; kubectl get nodes | grep -w \$NODE | grep -w Ready
|
||||
done
|
||||
fi"
|
||||
}
|
||||
|
||||
_cmd ids "(FIXME) List the instance IDs belonging to a given tag or token"
|
||||
_cmd_ids() {
|
||||
_cmd ips "Show the IP addresses for a given tag"
|
||||
_cmd_ips() {
|
||||
TAG=$1
|
||||
need_tag $TAG
|
||||
|
||||
info "Looking up by tag:"
|
||||
aws_get_instance_ids_by_tag $TAG
|
||||
|
||||
# Just in case we managed to create instances but weren't able to tag them
|
||||
info "Looking up by token:"
|
||||
aws_get_instance_ids_by_client_token $TAG
|
||||
SETTINGS=tags/$TAG/settings.yaml
|
||||
CLUSTERSIZE=$(awk '/^clustersize:/ {print $2}' $SETTINGS)
|
||||
while true; do
|
||||
for I in $(seq $CLUSTERSIZE); do
|
||||
read ip || return 0
|
||||
printf "%s\t" "$ip"
|
||||
done
|
||||
printf "\n"
|
||||
done < tags/$TAG/ips.txt
|
||||
}
|
||||
|
||||
_cmd list "List available groups for a given infrastructure"
|
||||
@@ -337,7 +364,7 @@ _cmd_maketag() {
|
||||
if [ -z $USER ]; then
|
||||
export USER=anonymous
|
||||
fi
|
||||
MS=$(($(date +%N)/1000000))
|
||||
MS=$(($(date +%N | tr -d 0)/1000000))
|
||||
date +%Y-%m-%d-%H-%M-$MS-$USER
|
||||
}
|
||||
|
||||
@@ -408,16 +435,6 @@ _cmd_opensg() {
|
||||
infra_opensg
|
||||
}
|
||||
|
||||
_cmd portworx "Prepare the nodes for Portworx deployment"
|
||||
_cmd_portworx() {
|
||||
TAG=$1
|
||||
need_tag
|
||||
|
||||
pssh "
|
||||
sudo truncate --size 10G /portworx.blk &&
|
||||
sudo losetup /dev/loop4 /portworx.blk"
|
||||
}
|
||||
|
||||
_cmd disableaddrchecks "Disable source/destination IP address checks"
|
||||
_cmd_disableaddrchecks() {
|
||||
TAG=$1
|
||||
@@ -462,18 +479,6 @@ _cmd_quotas() {
|
||||
infra_quotas
|
||||
}
|
||||
|
||||
_cmd retag "(FIXME) Apply a new tag to a group of VMs"
|
||||
_cmd_retag() {
|
||||
OLDTAG=$1
|
||||
NEWTAG=$2
|
||||
TAG=$OLDTAG
|
||||
need_tag
|
||||
if [[ -z "$NEWTAG" ]]; then
|
||||
die "You must specify a new tag to apply."
|
||||
fi
|
||||
aws_tag_instances $OLDTAG $NEWTAG
|
||||
}
|
||||
|
||||
_cmd ssh "Open an SSH session to the first node of a tag"
|
||||
_cmd_ssh() {
|
||||
TAG=$1
|
||||
@@ -491,6 +496,7 @@ _cmd_start() {
|
||||
--settings) SETTINGS=$2; shift 2;;
|
||||
--count) COUNT=$2; shift 2;;
|
||||
--tag) TAG=$2; shift 2;;
|
||||
--students) STUDENTS=$2; shift 2;;
|
||||
*) die "Unrecognized parameter: $1."
|
||||
esac
|
||||
done
|
||||
@@ -502,8 +508,14 @@ _cmd_start() {
|
||||
die "Please add --settings flag to specify which settings file to use."
|
||||
fi
|
||||
if [ -z "$COUNT" ]; then
|
||||
COUNT=$(awk '/^clustersize:/ {print $2}' $SETTINGS)
|
||||
warning "No --count option was specified. Using value from settings file ($COUNT)."
|
||||
CLUSTERSIZE=$(awk '/^clustersize:/ {print $2}' $SETTINGS)
|
||||
if [ -z "$STUDENTS" ]; then
|
||||
warning "Neither --count nor --students was specified."
|
||||
warning "According to the settings file, the cluster size is $CLUSTERSIZE."
|
||||
warning "Deploying one cluster of $CLUSTERSIZE nodes."
|
||||
STUDENTS=1
|
||||
fi
|
||||
COUNT=$(($STUDENTS*$CLUSTERSIZE))
|
||||
fi
|
||||
|
||||
# Check that the specified settings and infrastructure are valid.
|
||||
@@ -521,11 +533,41 @@ _cmd_start() {
|
||||
infra_start $COUNT
|
||||
sep
|
||||
info "Successfully created $COUNT instances with tag $TAG"
|
||||
sep
|
||||
echo created > tags/$TAG/status
|
||||
|
||||
info "To deploy Docker on these instances, you can run:"
|
||||
info "$0 deploy $TAG"
|
||||
# If the settings.yaml file has a "steps" field,
|
||||
# automatically execute all the actions listed in that field.
|
||||
# If an action fails, retry it up to 10 times.
|
||||
python -c 'if True: # hack to deal with indentation
|
||||
import sys, yaml
|
||||
settings = yaml.safe_load(sys.stdin)
|
||||
print ("\n".join(settings.get("steps", [])))
|
||||
' < tags/$TAG/settings.yaml \
|
||||
| while read step; do
|
||||
if [ -z "$step" ]; then
|
||||
break
|
||||
fi
|
||||
sep
|
||||
info "Automatically executing step '$step'."
|
||||
TRY=1
|
||||
MAXTRY=10
|
||||
while ! $0 $step $TAG ; do
|
||||
TRY=$(($TRY+1))
|
||||
if [ $TRY -gt $MAXTRY ]; then
|
||||
error "This step ($step) failed after $MAXTRY attempts."
|
||||
info "You can troubleshoot the situation manually, or terminate these instances with:"
|
||||
info "$0 stop $TAG"
|
||||
die "Giving up."
|
||||
else
|
||||
sep
|
||||
info "Step '$step' failed. Let's wait 10 seconds and try again."
|
||||
info "(Attempt $TRY out of $MAXTRY.)"
|
||||
sleep 10
|
||||
fi
|
||||
done
|
||||
done
|
||||
sep
|
||||
info "Deployment successful."
|
||||
info "To terminate these instances, you can run:"
|
||||
info "$0 stop $TAG"
|
||||
}
|
||||
@@ -623,11 +665,12 @@ _cmd_webssh() {
|
||||
sudo apt-get update &&
|
||||
sudo apt-get install python-tornado python-paramiko -y"
|
||||
pssh "
|
||||
[ -d webssh ] || git clone https://github.com/jpetazzo/webssh"
|
||||
cd /opt
|
||||
[ -d webssh ] || sudo git clone https://github.com/jpetazzo/webssh"
|
||||
pssh "
|
||||
for KEYFILE in /etc/ssh/*.pub; do
|
||||
read a b c < \$KEYFILE; echo localhost \$a \$b
|
||||
done > webssh/known_hosts"
|
||||
done | sudo tee /opt/webssh/known_hosts"
|
||||
pssh "cat >webssh.service <<EOF
|
||||
[Unit]
|
||||
Description=webssh
|
||||
@@ -636,7 +679,7 @@ Description=webssh
|
||||
WantedBy=multi-user.target
|
||||
|
||||
[Service]
|
||||
WorkingDirectory=/home/ubuntu/webssh
|
||||
WorkingDirectory=/opt/webssh
|
||||
ExecStart=/usr/bin/env python run.py --fbidhttp=false --port=1080 --policy=reject
|
||||
User=nobody
|
||||
Group=nogroup
|
||||
@@ -659,11 +702,6 @@ _cmd_www() {
|
||||
python3 -m http.server
|
||||
}
|
||||
|
||||
greet() {
|
||||
IAMUSER=$(aws iam get-user --query 'User.UserName')
|
||||
info "Hello! You seem to be UNIX user $USER, and IAM user $IAMUSER."
|
||||
}
|
||||
|
||||
pull_tag() {
|
||||
# Pre-pull a bunch of images
|
||||
pssh --timeout 900 'for I in \
|
||||
@@ -753,27 +791,3 @@ make_key_name() {
|
||||
SHORT_FINGERPRINT=$(ssh-add -l | grep RSA | head -n1 | cut -d " " -f 2 | tr -d : | cut -c 1-8)
|
||||
echo "${SHORT_FINGERPRINT}-${USER}"
|
||||
}
|
||||
|
||||
sync_keys() {
|
||||
# make sure ssh-add -l contains "RSA"
|
||||
ssh-add -l | grep -q RSA \
|
||||
|| die "The output of \`ssh-add -l\` doesn't contain 'RSA'. Start the agent, add your keys?"
|
||||
|
||||
AWS_KEY_NAME=$(make_key_name)
|
||||
info "Syncing keys... "
|
||||
if ! aws ec2 describe-key-pairs --key-name "$AWS_KEY_NAME" &>/dev/null; then
|
||||
aws ec2 import-key-pair --key-name $AWS_KEY_NAME \
|
||||
--public-key-material "$(ssh-add -L \
|
||||
| grep -i RSA \
|
||||
| head -n1 \
|
||||
| cut -d " " -f 1-2)" &>/dev/null
|
||||
|
||||
if ! aws ec2 describe-key-pairs --key-name "$AWS_KEY_NAME" &>/dev/null; then
|
||||
die "Somehow, importing the key didn't work. Make sure that 'ssh-add -l | grep RSA | head -n1' returns an RSA key?"
|
||||
else
|
||||
info "Imported new key $AWS_KEY_NAME."
|
||||
fi
|
||||
else
|
||||
info "Using existing key $AWS_KEY_NAME."
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
if ! command -v aws >/dev/null; then
|
||||
warn "AWS CLI (aws) not found."
|
||||
fi
|
||||
|
||||
infra_list() {
|
||||
aws_display_tags
|
||||
}
|
||||
|
||||
infra_quotas() {
|
||||
greet
|
||||
aws_greet
|
||||
|
||||
max_instances=$(aws ec2 describe-account-attributes \
|
||||
--attribute-names max-instances \
|
||||
@@ -21,10 +25,10 @@ infra_start() {
|
||||
COUNT=$1
|
||||
|
||||
# Print our AWS username, to ease the pain of credential-juggling
|
||||
greet
|
||||
aws_greet
|
||||
|
||||
# Upload our SSH keys to AWS if needed, to be added to each VM's authorized_keys
|
||||
key_name=$(sync_keys)
|
||||
key_name=$(aws_sync_keys)
|
||||
|
||||
AMI=$(aws_get_ami) # Retrieve the AWS image ID
|
||||
if [ -z "$AMI" ]; then
|
||||
@@ -61,7 +65,7 @@ infra_start() {
|
||||
aws_tag_instances $TAG $TAG
|
||||
|
||||
# Wait until EC2 API tells us that the instances are running
|
||||
wait_until_tag_is_running $TAG $COUNT
|
||||
aws_wait_until_tag_is_running $TAG $COUNT
|
||||
|
||||
aws_get_instance_ips_by_tag $TAG > tags/$TAG/ips.txt
|
||||
}
|
||||
@@ -98,7 +102,7 @@ infra_disableaddrchecks() {
|
||||
done
|
||||
}
|
||||
|
||||
wait_until_tag_is_running() {
|
||||
aws_wait_until_tag_is_running() {
|
||||
max_retry=100
|
||||
i=0
|
||||
done_count=0
|
||||
@@ -214,3 +218,32 @@ aws_get_ami() {
|
||||
##VERSION##
|
||||
find_ubuntu_ami -r $AWS_DEFAULT_REGION -a amd64 -v 18.04 -t hvm:ebs -N -q
|
||||
}
|
||||
|
||||
aws_greet() {
|
||||
IAMUSER=$(aws iam get-user --query 'User.UserName')
|
||||
info "Hello! You seem to be UNIX user $USER, and IAM user $IAMUSER."
|
||||
}
|
||||
|
||||
aws_sync_keys() {
|
||||
# make sure ssh-add -l contains "RSA"
|
||||
ssh-add -l | grep -q RSA \
|
||||
|| die "The output of \`ssh-add -l\` doesn't contain 'RSA'. Start the agent, add your keys?"
|
||||
|
||||
AWS_KEY_NAME=$(make_key_name)
|
||||
info "Syncing keys... "
|
||||
if ! aws ec2 describe-key-pairs --key-name "$AWS_KEY_NAME" &>/dev/null; then
|
||||
aws ec2 import-key-pair --key-name $AWS_KEY_NAME \
|
||||
--public-key-material "$(ssh-add -L \
|
||||
| grep -i RSA \
|
||||
| head -n1 \
|
||||
| cut -d " " -f 1-2)" &>/dev/null
|
||||
|
||||
if ! aws ec2 describe-key-pairs --key-name "$AWS_KEY_NAME" &>/dev/null; then
|
||||
die "Somehow, importing the key didn't work. Make sure that 'ssh-add -l | grep RSA | head -n1' returns an RSA key?"
|
||||
else
|
||||
info "Imported new key $AWS_KEY_NAME."
|
||||
fi
|
||||
else
|
||||
info "Using existing key $AWS_KEY_NAME."
|
||||
fi
|
||||
}
|
||||
|
||||
50
prepare-vms/lib/infra/hetzner.sh
Normal file
50
prepare-vms/lib/infra/hetzner.sh
Normal file
@@ -0,0 +1,50 @@
|
||||
if ! command -v hcloud >/dev/null; then
|
||||
warn "Hetzner CLI (hcloud) not found."
|
||||
fi
|
||||
if ! [ -f ~/.config/hcloud/cli.toml ]; then
|
||||
warn "~/.config/hcloud/cli.toml not found."
|
||||
fi
|
||||
|
||||
infra_start() {
|
||||
COUNT=$1
|
||||
|
||||
HETZNER_INSTANCE_TYPE=${HETZNER_INSTANCE_TYPE-cx21}
|
||||
HETZNER_DATACENTER=${HETZNER_DATACENTER-nbg1-dc3}
|
||||
HETZNER_IMAGE=${HETZNER_IMAGE-168855}
|
||||
|
||||
for I in $(seq 1 $COUNT); do
|
||||
NAME=$(printf "%s-%03d" $TAG $I)
|
||||
sep "Starting instance $I/$COUNT"
|
||||
info " Datacenter: $HETZNER_DATACENTER"
|
||||
info " Name: $NAME"
|
||||
info " Instance type: $HETZNER_INSTANCE_TYPE"
|
||||
hcloud server create \
|
||||
--type=${HETZNER_INSTANCE_TYPE} \
|
||||
--datacenter=${HETZNER_DATACENTER} \
|
||||
--image=${HETZNER_IMAGE} \
|
||||
--name=$NAME \
|
||||
--label=tag=$TAG \
|
||||
--ssh-key ~/.ssh/id_rsa.pub
|
||||
done
|
||||
|
||||
hetzner_get_ips_by_tag $TAG > tags/$TAG/ips.txt
|
||||
}
|
||||
|
||||
infra_stop() {
|
||||
for ID in $(hetzner_get_ids_by_tag $TAG); do
|
||||
info "Scheduling deletion of instance $ID..."
|
||||
hcloud server delete $ID &
|
||||
done
|
||||
info "Waiting for deletion to complete..."
|
||||
wait
|
||||
}
|
||||
|
||||
hetzner_get_ids_by_tag() {
|
||||
TAG=$1
|
||||
hcloud server list --selector=tag=$TAG -o json | jq -r .[].name
|
||||
}
|
||||
|
||||
hetzner_get_ips_by_tag() {
|
||||
TAG=$1
|
||||
hcloud server list --selector=tag=$TAG -o json | jq -r .[].public_net.ipv4.ip
|
||||
}
|
||||
48
prepare-vms/lib/infra/openstack-cli.sh
Normal file
48
prepare-vms/lib/infra/openstack-cli.sh
Normal file
@@ -0,0 +1,48 @@
|
||||
infra_start() {
|
||||
COUNT=$1
|
||||
|
||||
sep "Starting $COUNT instances"
|
||||
info " Region: $OS_REGION_NAME"
|
||||
info " User: $OS_USERNAME"
|
||||
info " Flavor: $OS_FLAVOR"
|
||||
info " Image: $OS_IMAGE"
|
||||
openstack server create \
|
||||
--flavor $OS_FLAVOR \
|
||||
--image $OS_IMAGE \
|
||||
--key-name $OS_KEY \
|
||||
--min $COUNT --max $COUNT \
|
||||
--property workshopctl=$TAG \
|
||||
$TAG
|
||||
|
||||
sep "Waiting for IP addresses to be available"
|
||||
GOT=0
|
||||
while [ "$GOT" != "$COUNT" ]; do
|
||||
echo "Got $GOT/$COUNT IP addresses."
|
||||
oscli_get_ips_by_tag $TAG > tags/$TAG/ips.txt
|
||||
GOT="$(wc -l < tags/$TAG/ips.txt)"
|
||||
done
|
||||
|
||||
}
|
||||
|
||||
infra_stop() {
|
||||
info "Counting instances..."
|
||||
oscli_get_instances_json $TAG |
|
||||
jq -r .[].Name |
|
||||
wc -l
|
||||
info "Deleting instances..."
|
||||
oscli_get_instances_json $TAG |
|
||||
jq -r .[].Name |
|
||||
xargs -P10 -n1 openstack server delete
|
||||
info "Done."
|
||||
}
|
||||
|
||||
oscli_get_instances_json() {
|
||||
TAG=$1
|
||||
openstack server list -f json --name "${TAG}-[0-9]*"
|
||||
}
|
||||
|
||||
oscli_get_ips_by_tag() {
|
||||
TAG=$1
|
||||
oscli_get_instances_json $TAG |
|
||||
jq -r .[].Networks | cut -d= -f2 | cut -d, -f1 | grep . || true
|
||||
}
|
||||
46
prepare-vms/lib/infra/scaleway.sh
Normal file
46
prepare-vms/lib/infra/scaleway.sh
Normal file
@@ -0,0 +1,46 @@
|
||||
if ! command -v scw >/dev/null; then
|
||||
warn "Scaleway CLI (scw) not found."
|
||||
fi
|
||||
if ! [ -f ~/.config/scw/config.yaml ]; then
|
||||
warn "~/.config/scw/config.yaml not found."
|
||||
fi
|
||||
|
||||
infra_start() {
|
||||
COUNT=$1
|
||||
|
||||
SCW_INSTANCE_TYPE=${SCW_INSTANCE_TYPE-DEV1-M}
|
||||
SCW_ZONE=${SCW_ZONE-fr-par-1}
|
||||
|
||||
for I in $(seq 1 $COUNT); do
|
||||
NAME=$(printf "%s-%03d" $TAG $I)
|
||||
sep "Starting instance $I/$COUNT"
|
||||
info " Zone: $SCW_ZONE"
|
||||
info " Name: $NAME"
|
||||
info " Instance type: $SCW_INSTANCE_TYPE"
|
||||
scw instance server create \
|
||||
type=${SCW_INSTANCE_TYPE} zone=${SCW_ZONE} \
|
||||
image=ubuntu_bionic name=${NAME}
|
||||
done
|
||||
sep
|
||||
|
||||
scw_get_ips_by_tag $TAG > tags/$TAG/ips.txt
|
||||
}
|
||||
|
||||
infra_stop() {
|
||||
info "Counting instances..."
|
||||
scw_get_ids_by_tag $TAG | wc -l
|
||||
info "Deleting instances..."
|
||||
scw_get_ids_by_tag $TAG |
|
||||
xargs -n1 -P10 -I@@ \
|
||||
scw instance server delete force-shutdown=true server-id=@@
|
||||
}
|
||||
|
||||
scw_get_ids_by_tag() {
|
||||
TAG=$1
|
||||
scw instance server list name=$TAG -o json | jq -r .[].id
|
||||
}
|
||||
|
||||
scw_get_ips_by_tag() {
|
||||
TAG=$1
|
||||
scw instance server list name=$TAG -o json | jq -r .[].public_ip.address
|
||||
}
|
||||
23
prepare-vms/lib/infra/unimplemented.sh
Normal file
23
prepare-vms/lib/infra/unimplemented.sh
Normal file
@@ -0,0 +1,23 @@
|
||||
infra_disableaddrchecks() {
|
||||
die "unimplemented"
|
||||
}
|
||||
|
||||
infra_list() {
|
||||
die "unimplemented"
|
||||
}
|
||||
|
||||
infra_opensg() {
|
||||
die "unimplemented"
|
||||
}
|
||||
|
||||
infra_quotas() {
|
||||
die "unimplemented"
|
||||
}
|
||||
|
||||
infra_start() {
|
||||
die "unimplemented"
|
||||
}
|
||||
|
||||
infra_stop() {
|
||||
die "unimplemented"
|
||||
}
|
||||
@@ -37,7 +37,7 @@ def system(cmd):
|
||||
td = str(t2-t1)[:5]
|
||||
f.write(bold("[{}] in {}s\n".format(retcode, td)))
|
||||
STEP += 1
|
||||
with open("/home/ubuntu/.bash_history", "a") as f:
|
||||
with open(os.environ["HOME"] + "/.bash_history", "a") as f:
|
||||
f.write("{}\n".format(cmd))
|
||||
if retcode != 0:
|
||||
msg = "The following command failed with exit code {}:\n".format(retcode)
|
||||
|
||||
@@ -18,7 +18,13 @@ pssh() {
|
||||
echo "[parallel-ssh] $@"
|
||||
export PSSH=$(which pssh || which parallel-ssh)
|
||||
|
||||
$PSSH -h $HOSTFILE -l ubuntu \
|
||||
if [ "$INFRACLASS" = hetzner ]; then
|
||||
LOGIN=root
|
||||
else
|
||||
LOGIN=ubuntu
|
||||
fi
|
||||
|
||||
$PSSH -h $HOSTFILE -l $LOGIN \
|
||||
--par 100 \
|
||||
-O LogLevel=ERROR \
|
||||
-O UserKnownHostsFile=/dev/null \
|
||||
|
||||
@@ -1,21 +1,44 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
There are two ways to use this script:
|
||||
|
||||
1. Pass a tag name as a single argument.
|
||||
It will then take the clusters corresponding to that tag, and assign one
|
||||
domain name per cluster. Currently it gets the domains from a hard-coded
|
||||
path. There should be more domains than clusters.
|
||||
Example: ./map-dns.py 2020-08-15-jp
|
||||
|
||||
2. Pass a domain as the 1st argument, and IP addresses then.
|
||||
It will configure the domain with the listed IP addresses.
|
||||
Example: ./map-dns.py open-duck.site 1.2.3.4 2.3.4.5 3.4.5.6
|
||||
|
||||
In both cases, the domains should be configured to use GANDI LiveDNS.
|
||||
"""
|
||||
import os
|
||||
import requests
|
||||
import sys
|
||||
import yaml
|
||||
|
||||
# configurable stuff
|
||||
domains_file = "../../plentydomains/domains.txt"
|
||||
config_file = os.path.join(
|
||||
os.environ["HOME"], ".config/gandi/config.yaml")
|
||||
tag = "test"
|
||||
tag = None
|
||||
apiurl = "https://dns.api.gandi.net/api/v5/domains"
|
||||
|
||||
if len(sys.argv) == 2:
|
||||
tag = sys.argv[1]
|
||||
domains = open(domains_file).read().split()
|
||||
ips = open(f"tags/{tag}/ips.txt").read().split()
|
||||
settings_file = f"tags/{tag}/settings.yaml"
|
||||
clustersize = yaml.safe_load(open(settings_file))["clustersize"]
|
||||
else:
|
||||
domains = [sys.argv[1]]
|
||||
ips = sys.argv[2:]
|
||||
clustersize = len(ips)
|
||||
|
||||
# inferred stuff
|
||||
domains = open(domains_file).read().split()
|
||||
apikey = yaml.safe_load(open(config_file))["apirest"]["key"]
|
||||
ips = open(f"tags/{tag}/ips.txt").read().split()
|
||||
settings_file = f"tags/{tag}/settings.yaml"
|
||||
clustersize = yaml.safe_load(open(settings_file))["clustersize"]
|
||||
|
||||
# now do the fucking work
|
||||
while domains and ips:
|
||||
|
||||
@@ -21,3 +21,9 @@ machine_version: 0.15.0
|
||||
|
||||
# Password used to connect with the "docker user"
|
||||
docker_user_password: training
|
||||
|
||||
steps:
|
||||
- deploy
|
||||
- webssh
|
||||
- tailhist
|
||||
- cards
|
||||
|
||||
@@ -20,3 +20,10 @@ machine_version: 0.14.0
|
||||
# Password used to connect with the "docker user"
|
||||
docker_user_password: training
|
||||
|
||||
steps:
|
||||
- deploy
|
||||
- webssh
|
||||
- tailhist
|
||||
- kube
|
||||
- cards
|
||||
- kubetest
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
resource "openstack_compute_instance_v2" "machine" {
|
||||
count = "${var.count}"
|
||||
name = "${format("%s-%04d", "${var.prefix}", count.index+1)}"
|
||||
image_name = "Ubuntu 16.04.5 (Xenial Xerus)"
|
||||
image_name = "Ubuntu 18.04.4 20200324"
|
||||
flavor_name = "${var.flavor}"
|
||||
security_groups = ["${openstack_networking_secgroup_v2.full_access.name}"]
|
||||
key_pair = "${openstack_compute_keypair_v2.ssh_deploy_key.name}"
|
||||
|
||||
@@ -15,7 +15,6 @@ for lib in lib/*.sh; do
|
||||
done
|
||||
|
||||
DEPENDENCIES="
|
||||
aws
|
||||
ssh
|
||||
curl
|
||||
jq
|
||||
|
||||
@@ -1,17 +1,24 @@
|
||||
# Uncomment and/or edit one of the the following lines if necessary.
|
||||
#/ /kube-halfday.yml.html 200
|
||||
#/ /kube-fullday.yml.html 200
|
||||
#/ /kube-twodays.yml.html 200
|
||||
#/ /kube-halfday.yml.html 200!
|
||||
/ /kube-fullday.yml.html 200!
|
||||
#/ /kube-twodays.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
|
||||
|
||||
#/dockermastery https://www.udemy.com/course/docker-mastery/?referralCode=1410924A733D33635CCB
|
||||
#/kubernetesmastery https://www.udemy.com/course/kubernetesmastery/?referralCode=7E09090AF9B79E6C283F
|
||||
/dockermastery https://www.udemy.com/course/docker-mastery/?couponCode=SWEETFEBSALEC1
|
||||
/kubernetesmastery https://www.udemy.com/course/kubernetesmastery/?couponCode=SWEETFEBSALEC4
|
||||
/dockermastery https://www.udemy.com/course/docker-mastery/?couponCode=DOCKERALLDAY
|
||||
/kubernetesmastery https://www.udemy.com/course/kubernetesmastery/?couponCode=DOCKERALLDAY
|
||||
|
||||
# Shortlink for the QRCode
|
||||
/q /qrcode.html 200
|
||||
/next https://www.eventbrite.com/e/intensive-kubernetes-advanced-concepts-live-stream-tickets-102358725704
|
||||
|
||||
# Shortlinks for next training in English and French
|
||||
#/next https://www.eventbrite.com/e/livestream-intensive-kubernetes-bootcamp-tickets-103262336428
|
||||
/next https://skillsmatter.com/courses/700-advanced-kubernetes-concepts-workshop-jerome-petazzoni
|
||||
/hi5 https://enix.io/fr/services/formation/online/
|
||||
|
||||
/chat https://gitter.im/jpetazzo/workshop-20200912-online
|
||||
/vms https://docs.google.com/spreadsheets/d/1LkxnxGpMWWWTdpDhz-mF1noYrfc_BlI8yi71EyxwmM4
|
||||
|
||||
|
||||
@@ -233,7 +233,7 @@ def setup_tmux_and_ssh():
|
||||
ipaddr = "$IPADDR"
|
||||
uid = os.getuid()
|
||||
|
||||
raise Exception("""
|
||||
raise Exception(r"""
|
||||
1. If you're running this directly from a node:
|
||||
|
||||
tmux
|
||||
@@ -247,6 +247,16 @@ rm -f /tmp/tmux-{uid}/default && ssh -t -L /tmp/tmux-{uid}/default:/tmp/tmux-100
|
||||
3. If you cannot control a remote tmux:
|
||||
|
||||
tmux new-session ssh docker@{ipaddr}
|
||||
|
||||
4. If you are running this locally with a remote cluster, make sure your prompt has the expected format:
|
||||
|
||||
tmux
|
||||
IPADDR=$(
|
||||
kubectl get nodes -o json |
|
||||
jq -r '.items[0].status.addresses[] | select(.type=="ExternalIP") | .address'
|
||||
)
|
||||
export PS1="\n[{ipaddr}] \u@\h:\w\n\$ "
|
||||
|
||||
""".format(uid=uid, ipaddr=ipaddr))
|
||||
else:
|
||||
logging.info("Found tmux session. Trying to acquire shell prompt.")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
class: title
|
||||
|
||||
# Advanced Dockerfiles
|
||||
# Advanced Dockerfile Syntax
|
||||
|
||||

|
||||
|
||||
@@ -12,7 +12,10 @@ class: title
|
||||
We have seen simple Dockerfiles to illustrate how Docker build
|
||||
container images.
|
||||
|
||||
In this section, we will see more Dockerfile commands.
|
||||
In this section, we will give a recap of the Dockerfile syntax,
|
||||
and introduce advanced Dockerfile commands that we might
|
||||
come across sometimes; or that we might want to use in some
|
||||
specific scenarios.
|
||||
|
||||
---
|
||||
|
||||
@@ -420,3 +423,8 @@ ONBUILD COPY . /src
|
||||
|
||||
* You can't chain `ONBUILD` instructions with `ONBUILD`.
|
||||
* `ONBUILD` can't be used to trigger `FROM` instructions.
|
||||
|
||||
???
|
||||
|
||||
:EN:- Advanced Dockerfile syntax
|
||||
:FR:- Dockerfile niveau expert
|
||||
|
||||
@@ -22,7 +22,7 @@ TEMPLATE="""<html>
|
||||
<tr><td class="header" colspan="3">{{ title }}</td></tr>
|
||||
<tr><td class="details" colspan="3">Note: while some workshops are delivered in other languages, slides are always in English.</td></tr>
|
||||
|
||||
<tr><td class="title" colspan="3">Free video of our latest workshop</td></tr>
|
||||
<tr><td class="title" colspan="3">Free Kubernetes intro course</td></tr>
|
||||
|
||||
<tr>
|
||||
<td>Getting Started With Kubernetes and Container Orchestration</td>
|
||||
@@ -40,7 +40,7 @@ TEMPLATE="""<html>
|
||||
</tr>
|
||||
|
||||
{% if coming_soon %}
|
||||
<tr><td class="title" colspan="3">Coming soon near you</td></tr>
|
||||
<tr><td class="title" colspan="3">Coming soon</td></tr>
|
||||
|
||||
{% for item in coming_soon %}
|
||||
<tr>
|
||||
@@ -141,13 +141,26 @@ import yaml
|
||||
|
||||
items = yaml.safe_load(open("index.yaml"))
|
||||
|
||||
|
||||
def prettyparse(date):
|
||||
months = [
|
||||
"January", "February", "March", "April", "May", "June",
|
||||
"July", "August", "September", "October", "November", "December"
|
||||
]
|
||||
month = months[date.month-1]
|
||||
suffix = {
|
||||
1: "st", 2: "nd", 3: "rd",
|
||||
21: "st", 22: "nd", 23: "rd",
|
||||
31: "st"}.get(date.day, "th")
|
||||
return date.year, month, "{}{}".format(date.day, suffix)
|
||||
|
||||
|
||||
# Items with a date correspond to scheduled sessions.
|
||||
# Items without a date correspond to self-paced content.
|
||||
# The date should be specified as a string (e.g. 2018-11-26).
|
||||
# It can also be a list of two elements (e.g. [2018-11-26, 2018-11-28]).
|
||||
# The latter indicates an event spanning multiple dates.
|
||||
# The first date will be used in the generated page, but the event
|
||||
# will be considered "current" (and therefore, shown in the list of
|
||||
# The event will be considered "current" (shown in the list of
|
||||
# upcoming events) until the second date.
|
||||
|
||||
for item in items:
|
||||
@@ -157,19 +170,23 @@ for item in items:
|
||||
date_begin, date_end = date
|
||||
else:
|
||||
date_begin, date_end = date, date
|
||||
suffix = {
|
||||
1: "st", 2: "nd", 3: "rd",
|
||||
21: "st", 22: "nd", 23: "rd",
|
||||
31: "st"}.get(date_begin.day, "th")
|
||||
# %e is a non-standard extension (it displays the day, but without a
|
||||
# leading zero). If strftime fails with ValueError, try to fall back
|
||||
# on %d (which displays the day but with a leading zero when needed).
|
||||
try:
|
||||
item["prettydate"] = date_begin.strftime("%B %e{}, %Y").format(suffix)
|
||||
except ValueError:
|
||||
item["prettydate"] = date_begin.strftime("%B %d{}, %Y").format(suffix)
|
||||
y1, m1, d1 = prettyparse(date_begin)
|
||||
y2, m2, d2 = prettyparse(date_end)
|
||||
if (y1, m1, d1) == (y2, m2, d2):
|
||||
# Single day event
|
||||
pretty_date = "{} {}, {}".format(m1, d1, y1)
|
||||
elif (y1, m1) == (y2, m2):
|
||||
# Multi-day event within a single month
|
||||
pretty_date = "{} {}-{}, {}".format(m1, d1, d2, y1)
|
||||
elif y1 == y2:
|
||||
# Multi-day event spanning more than a month
|
||||
pretty_date = "{} {}-{} {}, {}".format(m1, d1, m2, d2, y1)
|
||||
else:
|
||||
# Event spanning the turn of the year (REALLY???)
|
||||
pretty_date = "{} {}, {}-{} {}, {}".format(m1, d1, y1, m2, d2, y2)
|
||||
item["begin"] = date_begin
|
||||
item["end"] = date_end
|
||||
item["prettydate"] = pretty_date
|
||||
item["flag"] = FLAGS.get(item.get("country"),"")
|
||||
|
||||
today = datetime.date.today()
|
||||
|
||||
@@ -1,3 +1,125 @@
|
||||
- date: [2020-10-05, 2020-10-06]
|
||||
country: www
|
||||
city: streaming
|
||||
event: ENIX SAS
|
||||
speaker: jpetazzo
|
||||
title: Docker intensif (en français)
|
||||
lang: fr
|
||||
attend: https://enix.io/fr/services/formation/online/
|
||||
|
||||
- date: [2020-10-07, 2020-10-09]
|
||||
country: www
|
||||
city: streaming
|
||||
event: ENIX SAS
|
||||
speaker: jpetazzo
|
||||
title: Fondamentaux Kubernetes (en français)
|
||||
lang: fr
|
||||
attend: https://enix.io/fr/services/formation/online/
|
||||
|
||||
- date: 2020-10-12
|
||||
country: www
|
||||
city: streaming
|
||||
event: ENIX SAS
|
||||
speaker: jpetazzo
|
||||
title: Packaging pour Kubernetes (en français)
|
||||
lang: fr
|
||||
attend: https://enix.io/fr/services/formation/online/
|
||||
|
||||
- date: [2020-10-13, 2020-10-14]
|
||||
country: www
|
||||
city: streaming
|
||||
event: ENIX SAS
|
||||
speaker: jpetazzo
|
||||
title: Kubernetes avancé (en français)
|
||||
lang: fr
|
||||
attend: https://enix.io/fr/services/formation/online/
|
||||
|
||||
- date: [2020-10-19, 2020-10-20]
|
||||
country: www
|
||||
city: streaming
|
||||
event: ENIX SAS
|
||||
speaker: jpetazzo
|
||||
title: Opérer Kubernetes (en français)
|
||||
lang: fr
|
||||
attend: https://enix.io/fr/services/formation/online/
|
||||
|
||||
- date: [2020-09-28, 2020-10-01]
|
||||
country: www
|
||||
city: streaming
|
||||
event: Skills Matter
|
||||
speaker: jpetazzo
|
||||
title: Advanced Kubernetes Concepts
|
||||
attend: https://skillsmatter.com/courses/700-advanced-kubernetes-concepts-workshop-jerome-petazzoni
|
||||
|
||||
- date: [2020-08-29, 2020-08-30]
|
||||
country: www
|
||||
city: streaming
|
||||
event: fwdays
|
||||
speaker: jpetazzo
|
||||
title: Intensive Docker Online Workshop
|
||||
attend: https://fwdays.com/en/event/intensive-docker-workshop
|
||||
|
||||
- date: [2020-09-12, 2020-09-13]
|
||||
country: www
|
||||
city: streaming
|
||||
event: fwdays
|
||||
speaker: jpetazzo
|
||||
title: Kubernetes Intensive Online Workshop
|
||||
attend: https://fwdays.com/en/event/kubernetes-intensive-workshop
|
||||
|
||||
- date: [2020-07-07, 2020-07-09]
|
||||
country: www
|
||||
city: streaming
|
||||
event: Ardan Live
|
||||
speaker: jpetazzo
|
||||
title: Intensive Docker Bootcamp
|
||||
attend: https://www.eventbrite.com/e/livestream-intensive-docker-bootcamp-tickets-103258886108
|
||||
|
||||
- date: [2020-06-15, 2020-06-16]
|
||||
country: www
|
||||
city: streaming
|
||||
event: ENIX SAS
|
||||
speaker: jpetazzo
|
||||
title: Docker intensif (en français)
|
||||
lang: fr
|
||||
attend: https://enix.io/fr/services/formation/online/
|
||||
|
||||
- date: [2020-06-17, 2020-06-19]
|
||||
country: www
|
||||
city: streaming
|
||||
event: ENIX SAS
|
||||
speaker: jpetazzo
|
||||
title: Fondamentaux Kubernetes (en français)
|
||||
lang: fr
|
||||
attend: https://enix.io/fr/services/formation/online/
|
||||
|
||||
- date: 2020-06-22
|
||||
country: www
|
||||
city: streaming
|
||||
event: ENIX SAS
|
||||
speaker: jpetazzo
|
||||
title: Packaging pour Kubernetes (en français)
|
||||
lang: fr
|
||||
attend: https://enix.io/fr/services/formation/online/
|
||||
|
||||
- date: [2020-06-23, 2020-06-24]
|
||||
country: www
|
||||
city: streaming
|
||||
event: ENIX SAS
|
||||
speaker: jpetazzo
|
||||
title: Kubernetes avancé (en français)
|
||||
lang: fr
|
||||
attend: https://enix.io/fr/services/formation/online/
|
||||
|
||||
- date: [2020-06-25, 2020-06-26]
|
||||
country: www
|
||||
city: streaming
|
||||
event: ENIX SAS
|
||||
speaker: jpetazzo
|
||||
title: Opérer Kubernetes (en français)
|
||||
lang: fr
|
||||
attend: https://enix.io/fr/services/formation/online/
|
||||
|
||||
- date: [2020-06-09, 2020-06-11]
|
||||
country: www
|
||||
city: streaming
|
||||
@@ -6,14 +128,6 @@
|
||||
title: Intensive Kubernetes Bootcamp
|
||||
attend: https://www.eventbrite.com/e/livestream-intensive-kubernetes-bootcamp-tickets-103262336428
|
||||
|
||||
- date: [2020-05-19, 2020-05-21]
|
||||
country: www
|
||||
city: streaming
|
||||
event: Ardan Live
|
||||
speaker: jpetazzo
|
||||
title: Intensive Docker Bootcamp
|
||||
attend: https://www.eventbrite.com/e/livestream-intensive-docker-bootcamp-tickets-103258886108
|
||||
|
||||
- date: [2020-05-04, 2020-05-08]
|
||||
country: www
|
||||
city: streaming
|
||||
@@ -29,7 +143,7 @@
|
||||
speaker: jpetazzo
|
||||
title: Intensive Docker and Kubernetes
|
||||
attend: https://www.eventbrite.com/e/ardan-labs-live-worldwide-march-30-april-2-2020-tickets-100331129108#
|
||||
slides: https://https://2020-03-ardan.container.training/
|
||||
slides: https://2020-03-ardan.container.training/
|
||||
|
||||
- date: 2020-03-06
|
||||
country: uk
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
title: |
|
||||
Introduction
|
||||
to Containers
|
||||
|
||||
chat: "[Slack](https://dockercommunity.slack.com/messages/C7GKACWDV)"
|
||||
#chat: "[Gitter](https://gitter.im/jpetazzo/workshop-yyyymmdd-city)"
|
||||
|
||||
gitrepo: github.com/jpetazzo/container.training
|
||||
|
||||
slides: http://container.training/
|
||||
|
||||
#slidenumberprefix: "#SomeHashTag — "
|
||||
|
||||
exclude:
|
||||
- self-paced
|
||||
|
||||
content:
|
||||
- shared/title.md
|
||||
- logistics.md
|
||||
- containers/intro.md
|
||||
- shared/about-slides.md
|
||||
- shared/chat-room-im.md
|
||||
#- shared/chat-room-zoom-meeting.md
|
||||
#- shared/chat-room-zoom-webinar.md
|
||||
- shared/toc.md
|
||||
-
|
||||
#- containers/Docker_Overview.md
|
||||
#- containers/Docker_History.md
|
||||
- containers/Training_Environment.md
|
||||
#- containers/Installing_Docker.md
|
||||
- containers/First_Containers.md
|
||||
- containers/Background_Containers.md
|
||||
#- containers/Start_And_Attach.md
|
||||
- containers/Naming_And_Inspecting.md
|
||||
#- containers/Labels.md
|
||||
- containers/Getting_Inside.md
|
||||
- containers/Initial_Images.md
|
||||
-
|
||||
- containers/Building_Images_Interactively.md
|
||||
- containers/Building_Images_With_Dockerfiles.md
|
||||
- containers/Cmd_And_Entrypoint.md
|
||||
- containers/Copying_Files_During_Build.md
|
||||
- containers/Exercise_Dockerfile_Basic.md
|
||||
-
|
||||
- containers/Container_Networking_Basics.md
|
||||
#- containers/Network_Drivers.md
|
||||
#- containers/Container_Network_Model.md
|
||||
- containers/Local_Development_Workflow.md
|
||||
- containers/Compose_For_Dev_Stacks.md
|
||||
- containers/Exercise_Composefile.md
|
||||
-
|
||||
- containers/Multi_Stage_Builds.md
|
||||
#- containers/Publishing_To_Docker_Hub.md
|
||||
- containers/Dockerfile_Tips.md
|
||||
- containers/Exercise_Dockerfile_Advanced.md
|
||||
#- containers/Docker_Machine.md
|
||||
#- containers/Advanced_Dockerfiles.md
|
||||
#- containers/Init_Systems.md
|
||||
#- containers/Application_Configuration.md
|
||||
#- containers/Logging.md
|
||||
#- containers/Namespaces_Cgroups.md
|
||||
#- containers/Copy_On_Write.md
|
||||
#- containers/Containers_From_Scratch.md
|
||||
#- containers/Container_Engines.md
|
||||
#- containers/Pods_Anatomy.md
|
||||
#- containers/Ecosystem.md
|
||||
#- containers/Orchestration_Overview.md
|
||||
-
|
||||
- shared/thankyou.md
|
||||
- containers/links.md
|
||||
@@ -1,70 +0,0 @@
|
||||
title: |
|
||||
Introduction
|
||||
to Containers
|
||||
|
||||
chat: "[Slack](https://dockercommunity.slack.com/messages/C7GKACWDV)"
|
||||
#chat: "[Gitter](https://gitter.im/jpetazzo/workshop-yyyymmdd-city)"
|
||||
|
||||
gitrepo: github.com/jpetazzo/container.training
|
||||
|
||||
slides: http://container.training/
|
||||
|
||||
#slidenumberprefix: "#SomeHashTag — "
|
||||
|
||||
exclude:
|
||||
- in-person
|
||||
|
||||
content:
|
||||
- shared/title.md
|
||||
# - shared/logistics.md
|
||||
- containers/intro.md
|
||||
- shared/about-slides.md
|
||||
#- shared/chat-room-im.md
|
||||
#- shared/chat-room-zoom-meeting.md
|
||||
#- shared/chat-room-zoom-webinar.md
|
||||
- shared/toc.md
|
||||
- - containers/Docker_Overview.md
|
||||
- containers/Docker_History.md
|
||||
- containers/Training_Environment.md
|
||||
- containers/Installing_Docker.md
|
||||
- containers/First_Containers.md
|
||||
- containers/Background_Containers.md
|
||||
- containers/Start_And_Attach.md
|
||||
- - containers/Initial_Images.md
|
||||
- containers/Building_Images_Interactively.md
|
||||
- containers/Building_Images_With_Dockerfiles.md
|
||||
- containers/Cmd_And_Entrypoint.md
|
||||
- containers/Copying_Files_During_Build.md
|
||||
- containers/Exercise_Dockerfile_Basic.md
|
||||
- - containers/Multi_Stage_Builds.md
|
||||
- containers/Publishing_To_Docker_Hub.md
|
||||
- containers/Dockerfile_Tips.md
|
||||
- containers/Exercise_Dockerfile_Advanced.md
|
||||
- - containers/Naming_And_Inspecting.md
|
||||
- containers/Labels.md
|
||||
- containers/Getting_Inside.md
|
||||
- - containers/Container_Networking_Basics.md
|
||||
- containers/Network_Drivers.md
|
||||
- containers/Container_Network_Model.md
|
||||
#- containers/Connecting_Containers_With_Links.md
|
||||
- containers/Ambassadors.md
|
||||
- - containers/Local_Development_Workflow.md
|
||||
- containers/Windows_Containers.md
|
||||
- containers/Working_With_Volumes.md
|
||||
- containers/Compose_For_Dev_Stacks.md
|
||||
- containers/Exercise_Composefile.md
|
||||
- containers/Docker_Machine.md
|
||||
- - containers/Advanced_Dockerfiles.md
|
||||
- containers/Init_Systems.md
|
||||
- containers/Application_Configuration.md
|
||||
- containers/Logging.md
|
||||
- containers/Resource_Limits.md
|
||||
- - containers/Namespaces_Cgroups.md
|
||||
- containers/Copy_On_Write.md
|
||||
#- containers/Containers_From_Scratch.md
|
||||
- - containers/Container_Engines.md
|
||||
- containers/Pods_Anatomy.md
|
||||
- containers/Ecosystem.md
|
||||
- containers/Orchestration_Overview.md
|
||||
- shared/thankyou.md
|
||||
- containers/links.md
|
||||
@@ -1,78 +0,0 @@
|
||||
title: |
|
||||
Introduction
|
||||
to Containers
|
||||
|
||||
chat: "[Slack](https://dockercommunity.slack.com/messages/C7GKACWDV)"
|
||||
#chat: "[Gitter](https://gitter.im/jpetazzo/workshop-yyyymmdd-city)"
|
||||
|
||||
gitrepo: github.com/jpetazzo/container.training
|
||||
|
||||
slides: http://container.training/
|
||||
|
||||
#slidenumberprefix: "#SomeHashTag — "
|
||||
|
||||
exclude:
|
||||
- self-paced
|
||||
|
||||
content:
|
||||
- shared/title.md
|
||||
- logistics.md
|
||||
- containers/intro.md
|
||||
- shared/about-slides.md
|
||||
- shared/chat-room-im.md
|
||||
#- shared/chat-room-zoom-meeting.md
|
||||
#- shared/chat-room-zoom-webinar.md
|
||||
- shared/toc.md
|
||||
- # DAY 1
|
||||
- containers/Docker_Overview.md
|
||||
#- containers/Docker_History.md
|
||||
- containers/Training_Environment.md
|
||||
- containers/First_Containers.md
|
||||
- containers/Background_Containers.md
|
||||
- containers/Initial_Images.md
|
||||
-
|
||||
- containers/Building_Images_Interactively.md
|
||||
- containers/Building_Images_With_Dockerfiles.md
|
||||
- containers/Cmd_And_Entrypoint.md
|
||||
- containers/Copying_Files_During_Build.md
|
||||
- containers/Exercise_Dockerfile_Basic.md
|
||||
-
|
||||
- containers/Dockerfile_Tips.md
|
||||
- containers/Multi_Stage_Builds.md
|
||||
- containers/Publishing_To_Docker_Hub.md
|
||||
- containers/Exercise_Dockerfile_Advanced.md
|
||||
-
|
||||
- containers/Naming_And_Inspecting.md
|
||||
- containers/Labels.md
|
||||
- containers/Start_And_Attach.md
|
||||
- containers/Getting_Inside.md
|
||||
- containers/Resource_Limits.md
|
||||
- # DAY 2
|
||||
- containers/Container_Networking_Basics.md
|
||||
- containers/Network_Drivers.md
|
||||
- containers/Container_Network_Model.md
|
||||
-
|
||||
- containers/Local_Development_Workflow.md
|
||||
- containers/Working_With_Volumes.md
|
||||
- containers/Compose_For_Dev_Stacks.md
|
||||
- containers/Exercise_Composefile.md
|
||||
-
|
||||
- containers/Installing_Docker.md
|
||||
- containers/Container_Engines.md
|
||||
- containers/Init_Systems.md
|
||||
- containers/Advanced_Dockerfiles.md
|
||||
-
|
||||
- containers/Application_Configuration.md
|
||||
- containers/Logging.md
|
||||
- containers/Orchestration_Overview.md
|
||||
-
|
||||
- shared/thankyou.md
|
||||
- containers/links.md
|
||||
#-
|
||||
#- containers/Docker_Machine.md
|
||||
#- containers/Ambassadors.md
|
||||
#- containers/Namespaces_Cgroups.md
|
||||
#- containers/Copy_On_Write.md
|
||||
#- containers/Containers_From_Scratch.md
|
||||
#- containers/Pods_Anatomy.md
|
||||
#- containers/Ecosystem.md
|
||||
@@ -1,6 +1,74 @@
|
||||
# Authentication and authorization
|
||||
|
||||
*And first, a little refresher!*
|
||||
- In this section, we will:
|
||||
|
||||
- define authentication and authorization
|
||||
|
||||
- explain how they are implemented in Kubernetes
|
||||
|
||||
- talk about tokens, certificates, service accounts, RBAC ...
|
||||
|
||||
- But first: why do we need all this?
|
||||
|
||||
---
|
||||
|
||||
## The need for fine-grained security
|
||||
|
||||
- The Kubernetes API should only be available for identified users
|
||||
|
||||
- we don't want "guest access" (except in very rare scenarios)
|
||||
|
||||
- we don't want strangers to use our compute resources, delete our apps ...
|
||||
|
||||
- our keys and passwords should not be exposed to the public
|
||||
|
||||
- Users will often have different access rights
|
||||
|
||||
- cluster admin (similar to UNIX "root") can do everything
|
||||
|
||||
- developer might access specific resources, or a specific namespace
|
||||
|
||||
- supervision might have read only access to *most* resources
|
||||
|
||||
---
|
||||
|
||||
## Example: custom HTTP load balancer
|
||||
|
||||
- Let's imagine that we have a custom HTTP load balancer for multiple apps
|
||||
|
||||
- Each app has its own *Deployment* resource
|
||||
|
||||
- By default, the apps are "sleeping" and scaled to zero
|
||||
|
||||
- When a request comes in, the corresponding app gets woken up
|
||||
|
||||
- After some inactivity, the app is scaled down again
|
||||
|
||||
- This HTTP load balancer needs API access (to scale up/down)
|
||||
|
||||
- What if *a wild vulnerability appears*?
|
||||
|
||||
---
|
||||
|
||||
## Consequences of vulnerability
|
||||
|
||||
- If the HTTP load balancer has the same API access as we do:
|
||||
|
||||
*full cluster compromise (easy data leak, cryptojacking...)*
|
||||
|
||||
- If the HTTP load balancer has `update` permissions on the Deployments:
|
||||
|
||||
*defacement (easy), MITM / impersonation (medium to hard)*
|
||||
|
||||
- If the HTTP load balancer only has permission to `scale` the Deployments:
|
||||
|
||||
*denial-of-service*
|
||||
|
||||
- All these outcomes are bad, but some are worse than others
|
||||
|
||||
---
|
||||
|
||||
## Definitions
|
||||
|
||||
- Authentication = verifying the identity of a person
|
||||
|
||||
@@ -50,7 +118,7 @@
|
||||
|
||||
- [HTTP basic auth](https://en.wikipedia.org/wiki/Basic_access_authentication)
|
||||
|
||||
(carrying user and password in an HTTP header)
|
||||
(carrying user and password in an HTTP header; [deprecated since Kubernetes 1.19](https://github.com/kubernetes/kubernetes/pull/89069))
|
||||
|
||||
- Authentication proxy
|
||||
|
||||
@@ -147,7 +215,7 @@ class: extra-details
|
||||
|
||||
(if their key is compromised, or they leave the organization)
|
||||
|
||||
- Option 1: re-create a new CA and re-issue everyone's certificates
|
||||
- Option 1: re-create a new CA and re-issue everyone's certificates
|
||||
<br/>
|
||||
→ Maybe OK if we only have a few users; no way otherwise
|
||||
|
||||
@@ -631,7 +699,7 @@ class: extra-details
|
||||
|
||||
- Let's look for these in existing ClusterRoleBindings:
|
||||
```bash
|
||||
kubectl get clusterrolebindings -o yaml |
|
||||
kubectl get clusterrolebindings -o yaml |
|
||||
grep -e kubernetes-admin -e system:masters
|
||||
```
|
||||
|
||||
@@ -681,7 +749,7 @@ class: extra-details
|
||||
|
||||
:EN:- Authentication and authorization in Kubernetes
|
||||
:EN:- Authentication with tokens and certificates
|
||||
:EN:- Aithorization with RBAC (Role-Based Access Control)
|
||||
:EN:- Authorization with RBAC (Role-Based Access Control)
|
||||
:EN:- Restricting permissions with Service Accounts
|
||||
:EN:- Working with Roles, Cluster Roles, Role Bindings, etc.
|
||||
|
||||
|
||||
@@ -176,12 +176,8 @@ class: extra-details
|
||||
|
||||
- can't express parallelism or completions of Jobs
|
||||
|
||||
- can't express Pods with multiple containers
|
||||
|
||||
- can't express healthchecks, resource limits
|
||||
|
||||
- etc.
|
||||
|
||||
- `kubectl create` and `kubectl run` are *helpers* that generate YAML manifests
|
||||
|
||||
- If we write these manifests ourselves, we can use all features and options
|
||||
|
||||
@@ -217,15 +217,16 @@ docker run --rm --net host -v $PWD:/vol \
|
||||
|
||||
## How can we remember all these flags?
|
||||
|
||||
- Look at the static pod manifest for etcd
|
||||
- Older versions of kubeadm did add a healthcheck probe with all these flags
|
||||
|
||||
(in `/etc/kubernetes/manifests`)
|
||||
- That healthcheck probe was calling `etcdctl` with all the right flags
|
||||
|
||||
- The healthcheck probe is calling `etcdctl` with all the right flags
|
||||
😉👍✌️
|
||||
- With recent versions of kubeadm, we're on our own!
|
||||
|
||||
- Exercise: write the YAML for a batch job to perform the backup
|
||||
|
||||
(how will you access the key and certificate required to connect?)
|
||||
|
||||
---
|
||||
|
||||
## Restoring an etcd snapshot
|
||||
|
||||
@@ -210,6 +210,8 @@
|
||||
|
||||
(through files that get created in the container filesystem)
|
||||
|
||||
- That second link also includes a list of all the fields that can be used with the downward API
|
||||
|
||||
---
|
||||
|
||||
## Environment variables, pros and cons
|
||||
@@ -534,6 +536,8 @@ spec:
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## Differences between configmaps and secrets
|
||||
|
||||
- Secrets are base64-encoded when shown with `kubectl get secrets -o yaml`
|
||||
@@ -548,6 +552,29 @@ spec:
|
||||
|
||||
(since they are two different kinds of resources)
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## Immutable ConfigMaps and Secrets
|
||||
|
||||
- Since Kubernetes 1.19, it is possible to mark a ConfigMap or Secret as *immutable*
|
||||
|
||||
```bash
|
||||
kubectl patch configmap xyz --patch='{"immutable": true}'
|
||||
```
|
||||
|
||||
- This brings performance improvements when using lots of ConfigMaps and Secrets
|
||||
|
||||
(lots = tens of thousands)
|
||||
|
||||
- Once a ConfigMap or Secret has been marked as immutable:
|
||||
|
||||
- its content cannot be changed anymore
|
||||
- the `immutable` field can't be changed back either
|
||||
- the only way to change it is to delete and re-create it
|
||||
- Pods using it will have to be re-created as well
|
||||
|
||||
???
|
||||
|
||||
:EN:- Managing application configuration
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
|
||||
<!-- ##VERSION## -->
|
||||
|
||||
- Unfortunately, as of Kubernetes 1.17, the CLI cannot create daemon sets
|
||||
- Unfortunately, as of Kubernetes 1.19, the CLI cannot create daemon sets
|
||||
|
||||
--
|
||||
|
||||
|
||||
@@ -485,6 +485,8 @@ spec:
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## Using multiple ingress controllers
|
||||
|
||||
- You can have multiple ingress controllers active simultaneously
|
||||
@@ -495,11 +497,13 @@ spec:
|
||||
|
||||
(e.g. one for internal, another for external traffic)
|
||||
|
||||
- The `kubernetes.io/ingress.class` annotation can be used to tell which one to use
|
||||
- To indicate which ingress controller should be used by a given Ingress resouce:
|
||||
|
||||
- It's OK if multiple ingress controllers configure the same resource
|
||||
- before Kubernetes 1.18, use the `kubernetes.io/ingress.class` annotation
|
||||
|
||||
(it just means that the service will be accessible through multiple paths)
|
||||
- since Kubernetes 1.18, use the `ingressClassName` field
|
||||
<br/>
|
||||
(which should refer to an existing `IngressClass` resource)
|
||||
|
||||
---
|
||||
|
||||
@@ -535,9 +539,9 @@ spec:
|
||||
|
||||
- [ingress.kubernetes.io/rewrite-target: /](https://github.com/kubernetes/contrib/tree/master/ingress/controllers/nginx/examples/rewrite)
|
||||
|
||||
- This should eventually stabilize
|
||||
- The Ingress spec stabilized in Kubernetes 1.19 ...
|
||||
|
||||
(remember that ingresses are currently `apiVersion: networking.k8s.io/v1beta1`)
|
||||
... without specifying these features! 😭
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -296,7 +296,7 @@ class: extra-details
|
||||
|
||||
- When using `kubectl create deployment`, we cannot indicate the command to execute
|
||||
|
||||
(at least, not in Kubernetes 1.18)
|
||||
(at least, not in Kubernetes 1.18; but that changed in Kubernetes 1.19)
|
||||
|
||||
- We can:
|
||||
|
||||
@@ -338,12 +338,25 @@ class: extra-details
|
||||
kubectl get all
|
||||
```
|
||||
|
||||
<!-- ```hide kubectl wait pod --selector=run=pingpong --for condition=ready ``` -->
|
||||
<!-- ```hide kubectl wait pod --selector=app=pingpong --for condition=ready ``` -->
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## In Kubernetes 1.19
|
||||
|
||||
- Since Kubernetes 1.19, we can specify the command to run
|
||||
|
||||
- The command must be passed after two dashes:
|
||||
```bash
|
||||
kubectl create deployment pingpong --image=alpine -- ping 127.1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Viewing container output
|
||||
|
||||
- Let's use the `kubectl logs` command
|
||||
@@ -494,9 +507,7 @@ We'll see later how to address that shortcoming.
|
||||
```key ^J```
|
||||
```check```
|
||||
```key ^D```
|
||||
```tmux select-pane -t 1```
|
||||
```key ^C```
|
||||
```key ^D```
|
||||
-->
|
||||
|
||||
]
|
||||
|
||||
@@ -149,6 +149,28 @@
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## Supporting other CPU architectures
|
||||
|
||||
- The `jpetazzo/httpenv` image is currently only available for `x86_64`
|
||||
|
||||
(the "classic" Intel 64 bits architecture found on most PCs and Macs)
|
||||
|
||||
- That image won't work on other architectures
|
||||
|
||||
(e.g. Raspberry Pi or other ARM-based machines)
|
||||
|
||||
- Note that Docker supports [multi-arch](https://www.docker.com/blog/multi-arch-build-and-images-the-simple-way/) images
|
||||
|
||||
(so *technically* we could make it work across multiple architectures)
|
||||
|
||||
- If you want to build `httpenv` for your own platform, here is the source:
|
||||
|
||||
https://github.com/jpetazzo/httpenv
|
||||
|
||||
---
|
||||
|
||||
## Creating a deployment for our HTTP server
|
||||
|
||||
- We will create a deployment with `kubectl create deployment`
|
||||
|
||||
@@ -143,6 +143,30 @@ So, what do we get?
|
||||
|
||||
---
|
||||
|
||||
## Other ways to view labels
|
||||
|
||||
- `kubectl get` gives us a couple of useful flags to check labels
|
||||
|
||||
- `kubectl get --show-labels` shows all labels
|
||||
|
||||
- `kubectl get -L xyz` shows the value of label `xyz`
|
||||
|
||||
.exercise[
|
||||
|
||||
- List all the labels that we have on pods:
|
||||
```bash
|
||||
kubectl get pods --show-labels
|
||||
```
|
||||
|
||||
- List the value of label `app` on these pods:
|
||||
```bash
|
||||
kubectl get pods -L app
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## More on selectors
|
||||
|
||||
@@ -191,6 +191,8 @@ are a few tools that can help us.*
|
||||
|
||||
## Developer experience
|
||||
|
||||
*These questions constitute a quick "smoke test" for our strategy:*
|
||||
|
||||
- How do we on-board a new developer?
|
||||
|
||||
- What do they need to install to get a dev stack?
|
||||
@@ -199,8 +201,6 @@ are a few tools that can help us.*
|
||||
|
||||
- How does someone add a component to a stack?
|
||||
|
||||
*These questions are good "sanity checks" to validate our strategy!*
|
||||
|
||||
---
|
||||
|
||||
## Some guidelines
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
|
||||
- Check that our Consul clusters has 3 members indeed:
|
||||
```bash
|
||||
kubectl exec persistentconsul-0 consul members
|
||||
kubectl exec persistentconsul-0 -- consul members
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
@@ -34,11 +34,11 @@
|
||||
|
||||
- Download the `kubectl` binary from one of these links:
|
||||
|
||||
[Linux](https://storage.googleapis.com/kubernetes-release/release/v1.15.3/bin/linux/amd64/kubectl)
|
||||
[Linux](https://storage.googleapis.com/kubernetes-release/release/v1.18.8/bin/linux/amd64/kubectl)
|
||||
|
|
||||
[macOS](https://storage.googleapis.com/kubernetes-release/release/v1.15.3/bin/darwin/amd64/kubectl)
|
||||
[macOS](https://storage.googleapis.com/kubernetes-release/release/v1.18.8/bin/darwin/amd64/kubectl)
|
||||
|
|
||||
[Windows](https://storage.googleapis.com/kubernetes-release/release/v1.15.3/bin/windows/amd64/kubectl.exe)
|
||||
[Windows](https://storage.googleapis.com/kubernetes-release/release/v1.18.8/bin/windows/amd64/kubectl.exe)
|
||||
|
||||
- On Linux and macOS, make the binary executable with `chmod +x kubectl`
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ Exactly what we need!
|
||||
sudo chmod +x /usr/local/bin/stern
|
||||
```
|
||||
|
||||
- On macOS, we can also `brew install stern` or `port install stern`
|
||||
- On macOS, we can also `brew install stern` or `sudo port install stern`
|
||||
|
||||
<!-- ##VERSION## -->
|
||||
|
||||
|
||||
@@ -1,3 +1,35 @@
|
||||
# Designing an operator
|
||||
|
||||
- Once we understand CRDs and operators, it's tempting to use them everywhere
|
||||
|
||||
- Yes, we can do (almost) everything with operators ...
|
||||
|
||||
- ... But *should we?*
|
||||
|
||||
- Very often, the answer is **“no!”**
|
||||
|
||||
- Operators are powerful, but significantly more complex than other solutions
|
||||
|
||||
---
|
||||
|
||||
## When should we (not) use operators?
|
||||
|
||||
- Operators are great if our app needs to react to cluster events
|
||||
|
||||
(nodes or pods going down, and requiring extensive reconfiguration)
|
||||
|
||||
- Operators *might* be helpful to encapsulate complexity
|
||||
|
||||
(manipulate one single custom resource for an entire stack)
|
||||
|
||||
- Operators are probably overkill if a Helm chart would suffice
|
||||
|
||||
- That being said, if we really want to write an operator ...
|
||||
|
||||
Read on!
|
||||
|
||||
---
|
||||
|
||||
## What does it take to write an operator?
|
||||
|
||||
- Writing a quick-and-dirty operator, or a POC/MVP, is easy
|
||||
|
||||
@@ -93,11 +93,11 @@ Examples:
|
||||
|
||||
- Representing and managing external resources
|
||||
|
||||
(Example: [AWS Service Operator](https://operatorhub.io/operator/alpha/aws-service-operator.v0.0.1))
|
||||
(Example: [AWS S3 Operator](https://operatorhub.io/operator/awss3-operator-registry))
|
||||
|
||||
- Managing complex cluster add-ons
|
||||
|
||||
(Example: [Istio operator](https://operatorhub.io/operator/beta/istio-operator.0.1.6))
|
||||
(Example: [Istio operator](https://operatorhub.io/operator/istio))
|
||||
|
||||
- Deploying and managing our applications' lifecycles
|
||||
|
||||
|
||||
@@ -74,29 +74,78 @@
|
||||
|
||||
---
|
||||
|
||||
## Portworx requirements
|
||||
## Installing Portworx
|
||||
|
||||
- Kubernetes cluster ✔️
|
||||
- Portworx installation is relatively simple
|
||||
|
||||
- Optional key/value store (etcd or Consul) ❌
|
||||
- ... But we made it *even simpler!*
|
||||
|
||||
- At least one available block device ❌
|
||||
- We are going to use a YAML manifest that will take care of everything
|
||||
|
||||
- Warning: this manifest is customized for a very specific setup
|
||||
|
||||
(like the VMs that we provide during workshops and training sessions)
|
||||
|
||||
- It will probably *not work* If you are using a different setup
|
||||
|
||||
(like Docker Desktop, k3s, MicroK8S, Minikube ...)
|
||||
|
||||
---
|
||||
|
||||
## The key-value store
|
||||
## The simplified Portworx installer
|
||||
|
||||
- In the current version of Portworx (1.4) it is recommended to use etcd or Consul
|
||||
- The Portworx installation will take a few minutes
|
||||
|
||||
- But Portworx also has beta support for an embedded key/value store
|
||||
- Let's start it, then we'll explain what happens behind the scenes
|
||||
|
||||
- For simplicity, we are going to use the latter option
|
||||
.exercise[
|
||||
|
||||
(but if we have deployed Consul or etcd, we can use that, too)
|
||||
- Install Portworx:
|
||||
```bash
|
||||
kubectl apply -f ~/container.training/k8s/portworx.yaml
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
<!-- ##VERSION ## -->
|
||||
|
||||
*Note: this was tested with Kubernetes 1.18. Newer versions may or may not work.*
|
||||
|
||||
---
|
||||
|
||||
## One available block device
|
||||
class: extra-details
|
||||
|
||||
## What's in this YAML manifest?
|
||||
|
||||
- Portworx installation itself, pre-configured for our setup
|
||||
|
||||
- A default *Storage Class* using Portworx
|
||||
|
||||
- A *Daemon Set* to create loop devices on each node of the cluster
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## Portworx installation
|
||||
|
||||
- The official way to install Portworx is to use [PX-Central](https://central.portworx.com/)
|
||||
|
||||
(this requires a free account)
|
||||
|
||||
- PX-Central will ask us a few questions about our cluster
|
||||
|
||||
(Kubernetes version, on-prem/cloud deployment, etc.)
|
||||
|
||||
- Using our answers, it will generate a YAML manifest that we can use
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## Portworx storage configuration
|
||||
|
||||
- Portworx needs at least one *block device*
|
||||
|
||||
- Block device = disk or partition on a disk
|
||||
|
||||
@@ -112,71 +161,41 @@
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## Setting up a loop device
|
||||
|
||||
- We are going to create a 10 GB (empty) file on each node
|
||||
- Our `portworx.yaml` manifest includes a *Daemon Set* that will:
|
||||
|
||||
- Then make a loop device from it, to be used by Portworx
|
||||
- create a 10 GB (empty) file on each node
|
||||
|
||||
.exercise[
|
||||
- load the `loop` module (if it's not already loaded)
|
||||
|
||||
- Create a 10 GB file on each node:
|
||||
```bash
|
||||
for N in $(seq 1 4); do ssh node$N sudo truncate --size 10G /portworx.blk; done
|
||||
```
|
||||
(If SSH asks to confirm host keys, enter `yes` each time.)
|
||||
- associate a loop device with the 10 GB file
|
||||
|
||||
- Associate the file to a loop device on each node:
|
||||
```bash
|
||||
for N in $(seq 1 4); do ssh node$N sudo losetup /dev/loop4 /portworx.blk; done
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Installing Portworx
|
||||
|
||||
- To install Portworx, we need to go to https://install.portworx.com/
|
||||
|
||||
- This website will ask us a bunch of questions about our cluster
|
||||
|
||||
- Then, it will generate a YAML file that we should apply to our cluster
|
||||
|
||||
--
|
||||
|
||||
- Or, we can just apply that YAML file directly (it's in `k8s/portworx.yaml`)
|
||||
|
||||
.exercise[
|
||||
|
||||
- Install Portworx:
|
||||
```bash
|
||||
kubectl apply -f ~/container.training/k8s/portworx.yaml
|
||||
```
|
||||
|
||||
]
|
||||
- After these steps, we have a block device that Portworx can use
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## Generating a custom YAML file
|
||||
## Implementation details
|
||||
|
||||
If you want to generate a YAML file tailored to your own needs, the easiest
|
||||
way is to use https://install.portworx.com/.
|
||||
- The file is `/portworx.blk`
|
||||
|
||||
FYI, this is how we obtained the YAML file used earlier:
|
||||
```
|
||||
KBVER=$(kubectl version -o json | jq -r .serverVersion.gitVersion)
|
||||
BLKDEV=/dev/loop4
|
||||
curl https://install.portworx.com/1.4/?kbver=$KBVER&b=true&s=$BLKDEV&c=px-workshop&stork=true&lh=true
|
||||
```
|
||||
If you want to use an external key/value store, add one of the following:
|
||||
```
|
||||
&k=etcd://`XXX`:2379
|
||||
&k=consul://`XXX`:8500
|
||||
```
|
||||
... where `XXX` is the name or address of your etcd or Consul server.
|
||||
(it is a [sparse file](https://en.wikipedia.org/wiki/Sparse_file) created with `truncate`)
|
||||
|
||||
- The loop device is `/dev/loop4`
|
||||
|
||||
- This can be verified by running `sudo losetup`
|
||||
|
||||
- The *Daemon Set* uses a privileged *Init Container*
|
||||
|
||||
- We can check the logs of that container with:
|
||||
```bash
|
||||
kubectl logs --selector=app=setup-loop4-for-portworx \
|
||||
-c setup-loop4-for-portworx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -276,11 +295,9 @@ parameters:
|
||||
priority_io: "high"
|
||||
```
|
||||
|
||||
- It says "use Portworx to create volumes"
|
||||
- It says "use Portworx to create volumes and keep 2 replicas of these volumes"
|
||||
|
||||
- It tells Portworx to "keep 2 replicas of these volumes"
|
||||
|
||||
- It marks the Storage Class as being the default one
|
||||
- The annotation makes this Storage Class the default one
|
||||
|
||||
---
|
||||
|
||||
@@ -323,7 +340,10 @@ spec:
|
||||
schedulerName: stork
|
||||
containers:
|
||||
- name: postgres
|
||||
image: postgres:11
|
||||
image: postgres:12
|
||||
env:
|
||||
- name: POSTGRES_HOST_AUTH_METHOD
|
||||
value: trust
|
||||
volumeMounts:
|
||||
- mountPath: /var/lib/postgresql/data
|
||||
name: postgres
|
||||
@@ -367,7 +387,7 @@ spec:
|
||||
|
||||
- Get a shell in the pod, as the `postgres` user:
|
||||
```bash
|
||||
kubectl exec -ti postgres-0 su postgres
|
||||
kubectl exec -ti postgres-0 -- su postgres
|
||||
```
|
||||
|
||||
<!--
|
||||
@@ -401,14 +421,14 @@ autopilot prompt detection expects $ or # at the beginning of the line.
|
||||
|
||||
- Populate it with `pgbench`:
|
||||
```bash
|
||||
pgbench -i -s 10 demo
|
||||
pgbench -i demo
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
- The `-i` flag means "create tables"
|
||||
|
||||
- The `-s 10` flag means "create 10 x 100,000 rows"
|
||||
- If you want more data in the test tables, add e.g. `-s 10` (to get 10x more rows)
|
||||
|
||||
---
|
||||
|
||||
@@ -428,11 +448,55 @@ autopilot prompt detection expects $ or # at the beginning of the line.
|
||||
psql demo -c "select count(*) from pgbench_accounts"
|
||||
```
|
||||
|
||||
<!-- ```key ^D``` -->
|
||||
- Check that `pgbench_history` is currently empty:
|
||||
```bash
|
||||
psql demo -c "select count(*) from pgbench_history"
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
(We should see a count of 1,000,000 rows.)
|
||||
---
|
||||
|
||||
## Testing the load generator
|
||||
|
||||
- Let's use `pgbench` to generate a few transactions
|
||||
|
||||
.exercise[
|
||||
|
||||
- Run `pgbench` for 10 seconds, reporting progress every second:
|
||||
```bash
|
||||
pgbench -P 1 -T 10 demo
|
||||
```
|
||||
|
||||
- Check the size of the history table now:
|
||||
```bash
|
||||
psql demo -c "select count(*) from pgbench_history"
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
Note: on small cloud instances, a typical speed is about 100 transactions/second.
|
||||
|
||||
---
|
||||
|
||||
## Generating transactions
|
||||
|
||||
- Now let's use `pgbench` to generate more transactions
|
||||
|
||||
- While it's running, we will disrupt the database server
|
||||
|
||||
.exercise[
|
||||
|
||||
- Run `pgbench` for 10 minutes, reporting progress every second:
|
||||
```bash
|
||||
pgbench -P 1 -T 600 demo
|
||||
```
|
||||
|
||||
- You can use a longer time period if you need more time to run the next steps
|
||||
|
||||
<!-- ```tmux split-pane -h``` -->
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
@@ -513,7 +577,7 @@ By "disrupt" we mean: "disconnect it from the network".
|
||||
|
||||
- Get a shell on the pod:
|
||||
```bash
|
||||
kubectl exec -ti postgres-0 su postgres
|
||||
kubectl exec -ti postgres-0 -- su postgres
|
||||
```
|
||||
|
||||
<!--
|
||||
@@ -522,15 +586,18 @@ By "disrupt" we mean: "disconnect it from the network".
|
||||
```key ^J```
|
||||
-->
|
||||
|
||||
- Check the number of rows in the `pgbench_accounts` table:
|
||||
- Check how many transactions are now in the `pgbench_history` table:
|
||||
```bash
|
||||
psql demo -c "select count(*) from pgbench_accounts"
|
||||
psql demo -c "select count(*) from pgbench_history"
|
||||
```
|
||||
|
||||
<!-- ```key ^D``` -->
|
||||
|
||||
]
|
||||
|
||||
If the 10-second test that we ran earlier gave e.g. 80 transactions per second,
|
||||
and we failed the node after 30 seconds, we should have about 2400 row in that table.
|
||||
|
||||
---
|
||||
|
||||
## Double-check that the pod has really moved
|
||||
@@ -598,7 +665,7 @@ class: extra-details
|
||||
|
||||
- If we need to see what's going on with Portworx:
|
||||
```
|
||||
PXPOD=$(kubectl -n kube-system get pod -l name=portworx -o json |
|
||||
PXPOD=$(kubectl -n kube-system get pod -l name=portworx -o json |
|
||||
jq -r .items[0].metadata.name)
|
||||
kubectl -n kube-system exec $PXPOD -- /opt/pwx/bin/pxctl status
|
||||
```
|
||||
|
||||
@@ -104,9 +104,9 @@ Each pod is assigned a QoS class (visible in `status.qosClass`).
|
||||
|
||||
- When a node is overloaded, BestEffort pods are killed first
|
||||
|
||||
- Then, Burstable pods that exceed their limits
|
||||
- Then, Burstable pods that exceed their requests
|
||||
|
||||
- Burstable and Guaranteed pods below their limits are never killed
|
||||
- Burstable and Guaranteed pods below their requests are never killed
|
||||
|
||||
(except if their node fails)
|
||||
|
||||
|
||||
145
slides/k8s/setup-devel.md
Normal file
145
slides/k8s/setup-devel.md
Normal file
@@ -0,0 +1,145 @@
|
||||
# Running a local development cluster
|
||||
|
||||
- Let's review some options to run Kubernetes locally
|
||||
|
||||
- There is no "best option", it depends what you value:
|
||||
|
||||
- ability to run on all platforms (Linux, Mac, Windows, other?)
|
||||
|
||||
- ability to run clusters with multiple nodes
|
||||
|
||||
- ability to run multiple clusters side by side
|
||||
|
||||
- ability to run recent (or even, unreleased) versions of Kubernetes
|
||||
|
||||
- availability of plugins
|
||||
|
||||
- etc.
|
||||
|
||||
---
|
||||
|
||||
## Docker Desktop
|
||||
|
||||
- Available on Mac and Windows
|
||||
|
||||
- Gives you one cluster with one node
|
||||
|
||||
- Rather old version of Kubernetes
|
||||
|
||||
- Very easy to use if you are already using Docker Desktop:
|
||||
|
||||
go to Docker Desktop preferences and enable Kubernetes
|
||||
|
||||
- Ideal for Docker users who need good integration between both platforms
|
||||
|
||||
---
|
||||
|
||||
## [k3d](https://k3d.io/)
|
||||
|
||||
- Based on [K3s](https://k3s.io/) by Rancher Labs
|
||||
|
||||
- Requires Docker
|
||||
|
||||
- Runs Kubernetes nodes in Docker containers
|
||||
|
||||
- Can deploy multiple clusters, with multiple nodes, and multiple master nodes
|
||||
|
||||
- As of June 2020, two versions co-exist: stable (1.7) and beta (3.0)
|
||||
|
||||
- They have different syntax and options, this can be confusing
|
||||
|
||||
(but don't let that stop you!)
|
||||
|
||||
---
|
||||
|
||||
## k3d in action
|
||||
|
||||
- Get `k3d` beta 3 binary on https://github.com/rancher/k3d/releases
|
||||
|
||||
- Create a simple cluster:
|
||||
```bash
|
||||
k3d create cluster petitcluster --update-kubeconfig
|
||||
```
|
||||
|
||||
- Use it:
|
||||
```bash
|
||||
kubectl config use-context k3d-petitcluster
|
||||
```
|
||||
|
||||
- Create a more complex cluster with a custom version:
|
||||
```bash
|
||||
k3d create cluster groscluster --update-kubeconfig \
|
||||
--image rancher/k3s:v1.18.3-k3s1 --masters 3 --workers 5 --api-port 6444
|
||||
```
|
||||
|
||||
(note: API port seems to be necessary when running multiple clusters)
|
||||
|
||||
---
|
||||
|
||||
## [KinD](https://kind.sigs.k8s.io/)
|
||||
|
||||
- Kubernetes-in-Docker
|
||||
|
||||
- Requires Docker (obviously!)
|
||||
|
||||
- Deploying a single node cluster using the latest version is simple:
|
||||
```bash
|
||||
kind create cluster
|
||||
```
|
||||
|
||||
- More advanced scenarios require writing a short [config file](https://kind.sigs.k8s.io/docs/user/quick-start#configuring-your-kind-cluster)
|
||||
|
||||
(to define multiple nodes, multiple master nodes, set Kubernetes versions ...)
|
||||
|
||||
- Can deploy multiple clusters
|
||||
|
||||
---
|
||||
|
||||
## [Minikube](https://minikube.sigs.k8s.io/docs/)
|
||||
|
||||
- The "legacy" option!
|
||||
|
||||
(note: this is not a bad thing, it means that it's very stable, has lots of plugins, etc.)
|
||||
|
||||
- Supports many [drivers](https://minikube.sigs.k8s.io/docs/drivers/)
|
||||
|
||||
(HyperKit, Hyper-V, KVM, VirtualBox, but also Docker and many others)
|
||||
|
||||
- Can deploy a single cluster; recent versions can deploy multiple nodes
|
||||
|
||||
- Great option if you want a "Kubernetes first" experience
|
||||
|
||||
(i.e. if you don't already have Docker and/or don't want/need it)
|
||||
|
||||
---
|
||||
|
||||
## [MicroK8s](https://microk8s.io/)
|
||||
|
||||
- Available on Linux, and since recently, on Mac and Windows as well
|
||||
|
||||
- The Linux version is installed through Snap
|
||||
|
||||
(which is pre-installed on all recent versions of Ubuntu)
|
||||
|
||||
- Also supports clustering (as in, multiple machines running MicroK8s)
|
||||
|
||||
- DNS is not enabled by default; enable it with `microk8s enable dns`
|
||||
|
||||
---
|
||||
|
||||
## VM with custom install
|
||||
|
||||
- Choose your own adventure!
|
||||
|
||||
- Pick any Linux distribution!
|
||||
|
||||
- Build your cluster from scratch or use a Kubernetes installer!
|
||||
|
||||
- Discover exotic CNI plugins and container runtimes!
|
||||
|
||||
- The only limit is yourself, and the time you are willing to sink in!
|
||||
|
||||
???
|
||||
|
||||
:EN:- Kubernetes options for local development
|
||||
:FR:- Installation de Kubernetes pour travailler en local
|
||||
@@ -1,106 +0,0 @@
|
||||
# Setting up Kubernetes
|
||||
|
||||
- How did we set up these Kubernetes clusters that we're using?
|
||||
|
||||
--
|
||||
|
||||
<!-- ##VERSION## -->
|
||||
|
||||
- We used `kubeadm` on freshly installed VM instances running Ubuntu LTS
|
||||
|
||||
1. Install Docker
|
||||
|
||||
2. Install Kubernetes packages
|
||||
|
||||
3. Run `kubeadm init` on the first node (it deploys the control plane on that node)
|
||||
|
||||
4. Set up Weave (the overlay network)
|
||||
<br/>
|
||||
(that step is just one `kubectl apply` command; discussed later)
|
||||
|
||||
5. Run `kubeadm join` on the other nodes (with the token produced by `kubeadm init`)
|
||||
|
||||
6. Copy the configuration file generated by `kubeadm init`
|
||||
|
||||
- Check the [prepare VMs README](https://@@GITREPO@@/blob/master/prepare-vms/README.md) for more details
|
||||
|
||||
---
|
||||
|
||||
## `kubeadm` drawbacks
|
||||
|
||||
- Doesn't set up Docker or any other container engine
|
||||
|
||||
- Doesn't set up the overlay network
|
||||
|
||||
- [Some extra steps](https://kubernetes.io/docs/setup/independent/high-availability/) to support HA control plane
|
||||
|
||||
--
|
||||
|
||||
- "It's still twice as many steps as setting up a Swarm cluster 😕" -- Jérôme
|
||||
|
||||
---
|
||||
|
||||
## Managed options
|
||||
|
||||
- On AWS: [EKS](https://aws.amazon.com/eks/),
|
||||
[eksctl](https://eksctl.io/)
|
||||
|
||||
- On Azure: [AKS](https://azure.microsoft.com/services/kubernetes-service/)
|
||||
|
||||
- On DigitalOcean: [DOK](https://www.digitalocean.com/products/kubernetes/)
|
||||
|
||||
- On Google Cloud: [GKE](https://cloud.google.com/kubernetes-engine/)
|
||||
|
||||
- On Linode: [LKE](https://www.linode.com/products/kubernetes/)
|
||||
|
||||
- On OVHcloud: [Managed Kubernetes Service](https://www.ovhcloud.com/en/public-cloud/kubernetes/)
|
||||
|
||||
- On Scaleway: [Kapsule](https://www.scaleway.com/en/kubernetes-kapsule/)
|
||||
|
||||
- and much more!
|
||||
|
||||
---
|
||||
|
||||
## Other deployment options
|
||||
|
||||
- [kops](https://github.com/kubernetes/kops):
|
||||
customizable deployments on AWS, Digital Ocean, GCE (beta), vSphere (alpha)
|
||||
|
||||
- [minikube](https://kubernetes.io/docs/setup/minikube/),
|
||||
[kubespawn](https://github.com/kinvolk/kube-spawn),
|
||||
[Docker Desktop](https://docs.docker.com/docker-for-mac/kubernetes/),
|
||||
[kind](https://kind.sigs.k8s.io):
|
||||
for local development
|
||||
|
||||
- [kubicorn](https://github.com/kubicorn/kubicorn),
|
||||
the [Cluster API](https://blogs.vmware.com/cloudnative/2019/03/14/what-and-why-of-cluster-api/):
|
||||
deploy your clusters declaratively, "the Kubernetes way"
|
||||
|
||||
---
|
||||
|
||||
## Even more deployment options
|
||||
|
||||
- If you like Ansible:
|
||||
[kubespray](https://github.com/kubernetes-incubator/kubespray)
|
||||
|
||||
- If you like Terraform:
|
||||
[typhoon](https://github.com/poseidon/typhoon)
|
||||
|
||||
- If you like Terraform and Puppet:
|
||||
[tarmak](https://github.com/jetstack/tarmak)
|
||||
|
||||
- You can also learn how to install every component manually, with
|
||||
the excellent tutorial [Kubernetes The Hard Way](https://github.com/kelseyhightower/kubernetes-the-hard-way)
|
||||
|
||||
*Kubernetes The Hard Way is optimized for learning, which means taking the long route to ensure you understand each task required to bootstrap a Kubernetes cluster.*
|
||||
|
||||
- There are also many commercial options available!
|
||||
|
||||
- For a longer list, check the Kubernetes documentation:
|
||||
<br/>
|
||||
it has a great guide to [pick the right solution](https://kubernetes.io/docs/setup/#production-environment) to set up Kubernetes.
|
||||
|
||||
???
|
||||
|
||||
:EN:- Overview of the kubeadm installer
|
||||
:FR:- Survol de kubeadm
|
||||
@@ -1,4 +1,4 @@
|
||||
# Installing a managed cluster
|
||||
# Deploying a managed cluster
|
||||
|
||||
*"The easiest way to install Kubernetes is to get someone
|
||||
else to do it for you."
|
||||
@@ -11,6 +11,8 @@ else to do it for you."
|
||||
|
||||
(the goal is to show the actual steps to get started)
|
||||
|
||||
- The list is sorted alphabetically
|
||||
|
||||
- All the options mentioned here require an account
|
||||
with a cloud provider
|
||||
|
||||
@@ -18,123 +20,6 @@ with a cloud provider
|
||||
|
||||
---
|
||||
|
||||
## EKS (the old way)
|
||||
|
||||
- [Read the doc](https://docs.aws.amazon.com/eks/latest/userguide/getting-started-console.html)
|
||||
|
||||
- Create service roles, VPCs, and a bunch of other oddities
|
||||
|
||||
- Try to figure out why it doesn't work
|
||||
|
||||
- Start over, following an [official AWS blog post](https://aws.amazon.com/blogs/aws/amazon-eks-now-generally-available/)
|
||||
|
||||
- Try to find the missing Cloud Formation template
|
||||
|
||||
--
|
||||
|
||||
.footnote[(╯°□°)╯︵ ┻━┻]
|
||||
|
||||
---
|
||||
|
||||
## EKS (the new way)
|
||||
|
||||
- Install `eksctl`
|
||||
|
||||
- Set the usual environment variables
|
||||
|
||||
([AWS_DEFAULT_REGION](https://docs.aws.amazon.com/general/latest/gr/rande.html#eks_region), AWS_ACCESS_KEY, AWS_SECRET_ACCESS_KEY)
|
||||
|
||||
- Create the cluster:
|
||||
```bash
|
||||
eksctl create cluster
|
||||
```
|
||||
|
||||
- Wait 15-20 minutes (yes, it's sloooooooooooooooooow)
|
||||
|
||||
- Add cluster add-ons
|
||||
|
||||
(by default, it doesn't come with metrics-server, logging, etc.)
|
||||
|
||||
---
|
||||
|
||||
## EKS (cleanup)
|
||||
|
||||
- Delete the cluster:
|
||||
```bash
|
||||
eksctl delete cluster <clustername>
|
||||
```
|
||||
|
||||
- If you need to find the name of the cluster:
|
||||
```bash
|
||||
eksctl get clusters
|
||||
```
|
||||
|
||||
.footnote[Note: the AWS documentation has been updated and now includes [eksctl instructions](https://docs.aws.amazon.com/eks/latest/userguide/getting-started-eksctl.html).]
|
||||
|
||||
---
|
||||
|
||||
## GKE (initial setup)
|
||||
|
||||
- Install `gcloud`
|
||||
|
||||
- Login:
|
||||
```bash
|
||||
gcloud auth init
|
||||
```
|
||||
|
||||
- Create a "project":
|
||||
```bash
|
||||
gcloud projects create my-gke-project
|
||||
gcloud config set project my-gke-project
|
||||
```
|
||||
|
||||
- Pick a [region](https://cloud.google.com/compute/docs/regions-zones/)
|
||||
|
||||
(example: `europe-west1`, `us-west1`, ...)
|
||||
|
||||
---
|
||||
|
||||
## GKE (create cluster)
|
||||
|
||||
- Create the cluster:
|
||||
```bash
|
||||
gcloud container clusters create my-gke-cluster --region us-west1 --num-nodes=2
|
||||
```
|
||||
|
||||
(without `--num-nodes` you might exhaust your IP address quota!)
|
||||
|
||||
- The first time you try to create a cluster in a given project, you get an error
|
||||
|
||||
- you need to enable the Kubernetes Engine API
|
||||
- the error message gives you a link
|
||||
- follow the link and enable the API (and billing)
|
||||
<br/>(it's just a couple of clicks and it's instantaneous)
|
||||
|
||||
- Wait a couple of minutes (yes, it's faaaaaaaaast)
|
||||
|
||||
- The cluster comes with many add-ons
|
||||
|
||||
---
|
||||
|
||||
## GKE (cleanup)
|
||||
|
||||
- List clusters (if you forgot its name):
|
||||
```bash
|
||||
gcloud container clusters list
|
||||
```
|
||||
|
||||
- Delete the cluster:
|
||||
```bash
|
||||
gcloud container clusters delete my-gke-cluster --region us-west1
|
||||
```
|
||||
|
||||
- Delete the project (optional):
|
||||
```bash
|
||||
gcloud projects delete my-gke-project
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## AKS (initial setup)
|
||||
|
||||
- Install the Azure CLI
|
||||
@@ -168,8 +53,6 @@ with a cloud provider
|
||||
az aks get-credentials --resource-group my-aks-group --name my-aks-cluster
|
||||
```
|
||||
|
||||
- The cluster has useful components pre-installed, such as the metrics server
|
||||
|
||||
---
|
||||
|
||||
## AKS (cleanup)
|
||||
@@ -190,6 +73,95 @@ with a cloud provider
|
||||
|
||||
---
|
||||
|
||||
## AKS (notes)
|
||||
|
||||
- The cluster has useful components pre-installed, such as the metrics server
|
||||
|
||||
- There is also a product called [AKS Engine](https://github.com/Azure/aks-engine):
|
||||
|
||||
- leverages ARM (Azure Resource Manager) templates to deploy Kubernetes
|
||||
|
||||
- it's "the library used by AKS"
|
||||
|
||||
- fully customizable
|
||||
|
||||
- think of it as "half-managed" Kubernetes option
|
||||
|
||||
---
|
||||
|
||||
## Amazon EKS (the old way)
|
||||
|
||||
- [Read the doc](https://docs.aws.amazon.com/eks/latest/userguide/getting-started-console.html)
|
||||
|
||||
- Create service roles, VPCs, and a bunch of other oddities
|
||||
|
||||
- Try to figure out why it doesn't work
|
||||
|
||||
- Start over, following an [official AWS blog post](https://aws.amazon.com/blogs/aws/amazon-eks-now-generally-available/)
|
||||
|
||||
- Try to find the missing Cloud Formation template
|
||||
|
||||
--
|
||||
|
||||
.footnote[(╯°□°)╯︵ ┻━┻]
|
||||
|
||||
---
|
||||
|
||||
## Amazon EKS (the new way)
|
||||
|
||||
- Install `eksctl`
|
||||
|
||||
- Set the usual environment variables
|
||||
|
||||
([AWS_DEFAULT_REGION](https://docs.aws.amazon.com/general/latest/gr/rande.html#eks_region), AWS_ACCESS_KEY, AWS_SECRET_ACCESS_KEY)
|
||||
|
||||
- Create the cluster:
|
||||
```bash
|
||||
eksctl create cluster
|
||||
```
|
||||
|
||||
- Cluster can take a long time to be ready (15-20 minutes is typical)
|
||||
|
||||
- Add cluster add-ons
|
||||
|
||||
(by default, it doesn't come with metrics-server, logging, etc.)
|
||||
|
||||
---
|
||||
|
||||
## Amazon EKS (cleanup)
|
||||
|
||||
- Delete the cluster:
|
||||
```bash
|
||||
eksctl delete cluster <clustername>
|
||||
```
|
||||
|
||||
- If you need to find the name of the cluster:
|
||||
```bash
|
||||
eksctl get clusters
|
||||
```
|
||||
|
||||
.footnote[Note: the AWS documentation has been updated and now includes [eksctl instructions](https://docs.aws.amazon.com/eks/latest/userguide/getting-started-eksctl.html).]
|
||||
|
||||
---
|
||||
|
||||
## Amazon EKS (notes)
|
||||
|
||||
- Convenient if you *have to* use AWS
|
||||
|
||||
- Needs extra steps to be truly production-ready
|
||||
|
||||
- [Versions tend to be outdated](https://twitter.com/jpetazzo/status/1252948707680686081)
|
||||
|
||||
- The only officially supported pod network is the [Amazon VPC CNI plugin](https://docs.aws.amazon.com/eks/latest/userguide/pod-networking.html)
|
||||
|
||||
- integrates tightly with security groups and VPC networking
|
||||
|
||||
- not suitable for high density clusters (with many small pods on big nodes)
|
||||
|
||||
- other plugins [should still work](https://docs.aws.amazon.com/eks/latest/userguide/alternate-cni-plugins.html) but will require extra work
|
||||
|
||||
---
|
||||
|
||||
## Digital Ocean (initial setup)
|
||||
|
||||
- Install `doctl`
|
||||
@@ -242,15 +214,181 @@ with a cloud provider
|
||||
|
||||
---
|
||||
|
||||
## GKE (initial setup)
|
||||
|
||||
- Install `gcloud`
|
||||
|
||||
- Login:
|
||||
```bash
|
||||
gcloud auth init
|
||||
```
|
||||
|
||||
- Create a "project":
|
||||
```bash
|
||||
gcloud projects create my-gke-project
|
||||
gcloud config set project my-gke-project
|
||||
```
|
||||
|
||||
- Pick a [region](https://cloud.google.com/compute/docs/regions-zones/)
|
||||
|
||||
(example: `europe-west1`, `us-west1`, ...)
|
||||
|
||||
---
|
||||
|
||||
## GKE (create cluster)
|
||||
|
||||
- Create the cluster:
|
||||
```bash
|
||||
gcloud container clusters create my-gke-cluster --region us-west1 --num-nodes=2
|
||||
```
|
||||
|
||||
(without `--num-nodes` you might exhaust your IP address quota!)
|
||||
|
||||
- The first time you try to create a cluster in a given project, you get an error
|
||||
|
||||
- you need to enable the Kubernetes Engine API
|
||||
- the error message gives you a link
|
||||
- follow the link and enable the API (and billing)
|
||||
<br/>(it's just a couple of clicks and it's instantaneous)
|
||||
|
||||
- Clutser should be ready in a couple of minutes
|
||||
|
||||
---
|
||||
|
||||
## GKE (cleanup)
|
||||
|
||||
- List clusters (if you forgot its name):
|
||||
```bash
|
||||
gcloud container clusters list
|
||||
```
|
||||
|
||||
- Delete the cluster:
|
||||
```bash
|
||||
gcloud container clusters delete my-gke-cluster --region us-west1
|
||||
```
|
||||
|
||||
- Delete the project (optional):
|
||||
```bash
|
||||
gcloud projects delete my-gke-project
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## GKE (notes)
|
||||
|
||||
- Well-rounded product overall
|
||||
|
||||
(it used to be one of the best managed Kubernetes offerings available;
|
||||
now that many other providers entered the game, that title is debatable)
|
||||
|
||||
- The cluster comes with many add-ons
|
||||
|
||||
- Versions lag a bit:
|
||||
|
||||
- latest minor version (e.g. 1.18) tends to be unsupported
|
||||
|
||||
- previous minor version (e.g. 1.17) supported through alpha channel
|
||||
|
||||
- previous versions (e.g. 1.14-1.16) supported
|
||||
|
||||
---
|
||||
|
||||
## Scaleway (initial setup)
|
||||
|
||||
- After creating your account, make sure you set a password or get an API key
|
||||
|
||||
(by default, it uses email "magic links" to sign in)
|
||||
|
||||
- Install `scw`
|
||||
|
||||
(you need [CLI v2](https://github.com/scaleway/scaleway-cli/tree/v2#Installation), which in beta as of May 2020)
|
||||
|
||||
- Generate the CLI configuration with `scw init`
|
||||
|
||||
(it will prompt for your API key, or email + password)
|
||||
|
||||
---
|
||||
|
||||
## Scaleway (create cluster)
|
||||
|
||||
- Create the cluster:
|
||||
```bash
|
||||
k8s cluster create name=my-kapsule-cluster version=1.18.3 cni=cilium \
|
||||
default-pool-config.node-type=DEV1-M default-pool-config.size=3
|
||||
```
|
||||
|
||||
- After less than 5 minutes, cluster state will be `ready`
|
||||
|
||||
(check cluster status with e.g. `scw k8s cluster list` on a wide terminal
|
||||
)
|
||||
|
||||
- Add connection information to your `.kube/config` file:
|
||||
```bash
|
||||
scw k8s kubeconfig install `CLUSTERID`
|
||||
```
|
||||
|
||||
(the cluster ID is shown by `scw k8s cluster list`)
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## Scaleway (automation)
|
||||
|
||||
- If you want to obtain the cluster ID programmatically, this will do it:
|
||||
|
||||
```bash
|
||||
scw k8s cluster list
|
||||
# or
|
||||
CLUSTERID=$(scw k8s cluster list -o json | \
|
||||
jq -r '.[] | select(.name="my-kapsule-cluster") | .id')
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Scaleway (cleanup)
|
||||
|
||||
- Get cluster ID (e.g. with `scw k8s cluster list`)
|
||||
|
||||
- Delete the cluster:
|
||||
```bash
|
||||
scw cluster delete cluster-id=$CLUSTERID
|
||||
```
|
||||
|
||||
- Warning: as of May 2020, load balancers have to be deleted separately!
|
||||
|
||||
---
|
||||
|
||||
## Scaleway (notes)
|
||||
|
||||
- The `create` command is a bit more complex than with other providers
|
||||
|
||||
(you must specify the Kubernetes version, CNI plugin, and node type)
|
||||
|
||||
- To see available versions and CNI plugins, run `scw k8s version list`
|
||||
|
||||
- As of May 2020, Kapsule supports:
|
||||
|
||||
- multiple CNI plugins, including: cilium, calico, weave, flannel
|
||||
|
||||
- Kubernetes versions 1.15 to 1.18
|
||||
|
||||
- multiple container runtimes, including: Docker, containerd, CRI-O
|
||||
|
||||
- To see available node types and their price, check their [pricing page](
|
||||
https://www.scaleway.com/en/pricing/)
|
||||
|
||||
---
|
||||
|
||||
## More options
|
||||
|
||||
- Alibaba Cloud
|
||||
|
||||
- [IBM Cloud](https://console.bluemix.net/docs/containers/cs_cli_install.html#cs_cli_install)
|
||||
|
||||
- OVH
|
||||
- [Linode Kubernetes Engine (LKE)](https://www.linode.com/products/kubernetes/)
|
||||
|
||||
- Scaleway
|
||||
- OVHcloud [Managed Kubernetes Service](https://www.ovhcloud.com/en/public-cloud/kubernetes/)
|
||||
|
||||
- ...
|
||||
|
||||
|
||||
192
slides/k8s/setup-overview.md
Normal file
192
slides/k8s/setup-overview.md
Normal file
@@ -0,0 +1,192 @@
|
||||
# Setting up Kubernetes
|
||||
|
||||
- Kubernetes is made of many components that require careful configuration
|
||||
|
||||
- Secure operation typically requires TLS certificates and a local CA
|
||||
|
||||
(certificate authority)
|
||||
|
||||
- Setting up everything manually is possible, but rarely done
|
||||
|
||||
(except for learning purposes)
|
||||
|
||||
- Let's do a quick overview of available options!
|
||||
|
||||
---
|
||||
|
||||
## Local development
|
||||
|
||||
- Are you writing code that will eventually run on Kubernetes?
|
||||
|
||||
- Then it's a good idea to have a development cluster!
|
||||
|
||||
- Development clusters only need one node
|
||||
|
||||
- This simplifies their setup a lot:
|
||||
|
||||
- pod networking doesn't even need CNI plugins, overlay networks, etc.
|
||||
|
||||
- they can be fully contained (no pun intended) in an easy-to-ship VM image
|
||||
|
||||
- some of the security aspects may be simplified (different threat model)
|
||||
|
||||
- Examples: Docker Desktop, k3d, KinD, MicroK8s, Minikube
|
||||
|
||||
(some of these also support clusters with multiple nodes)
|
||||
|
||||
---
|
||||
|
||||
## Managed clusters
|
||||
|
||||
- Many cloud providers and hosting providers offer "managed Kubernetes"
|
||||
|
||||
- The deployment and maintenance of the cluster is entirely managed by the provider
|
||||
|
||||
(ideally, clusters can be spun up automatically through an API, CLI, or web interface)
|
||||
|
||||
- Given the complexity of Kubernetes, this approach is *strongly recommended*
|
||||
|
||||
(at least for your first production clusters)
|
||||
|
||||
- After working for a while with Kubernetes, you will be better equipped to decide:
|
||||
|
||||
- whether to operate it yourself or use a managed offering
|
||||
|
||||
- which offering or which distribution works best for you and your needs
|
||||
|
||||
---
|
||||
|
||||
## Managed clusters details
|
||||
|
||||
- Pricing models differ from one provider to another
|
||||
|
||||
- nodes are generally charged at their usual price
|
||||
|
||||
- control plane may be free or incur a small nominal fee
|
||||
|
||||
- Beyond pricing, there are *huge* differences in features between providers
|
||||
|
||||
- The "major" providers are not always the best ones!
|
||||
|
||||
---
|
||||
|
||||
## Managed clusters differences
|
||||
|
||||
- Most providers let you pick which Kubernetes version you want
|
||||
|
||||
- some providers offer up-to-date versions
|
||||
|
||||
- others lag significantly (sometimes by 2 or 3 minor versions)
|
||||
|
||||
- Some providers offer multiple networking or storage options
|
||||
|
||||
- Others will only support one, tied to their infrastructure
|
||||
|
||||
(changing that is in theory possible, but might be complex or unsupported)
|
||||
|
||||
- Some providers let you configure or customize the control plane
|
||||
|
||||
(generally through Kubernetes "feature gates")
|
||||
|
||||
---
|
||||
|
||||
## Kubernetes distributions and installers
|
||||
|
||||
- If you want to run Kubernetes yourselves, there are many options
|
||||
|
||||
(free, commercial, proprietary, open source ...)
|
||||
|
||||
- Some of them are installers, while some are complete platforms
|
||||
|
||||
- Some of them leverage other well-known deployment tools
|
||||
|
||||
(like Puppet, Terraform ...)
|
||||
|
||||
- A good starting point to explore these options is this [guide](https://v1-16.docs.kubernetes.io/docs/setup/#production-environment)
|
||||
|
||||
(it defines categories like "managed", "turnkey" ...)
|
||||
|
||||
---
|
||||
|
||||
## kubeadm
|
||||
|
||||
- kubeadm is a tool part of Kubernetes to facilitate cluster setup
|
||||
|
||||
- Many other installers and distributions use it (but not all of them)
|
||||
|
||||
- It can also be used by itself
|
||||
|
||||
- Excellent starting point to install Kubernetes on your own machines
|
||||
|
||||
(virtual, physical, it doesn't matter)
|
||||
|
||||
- It even supports highly available control planes, or "multi-master"
|
||||
|
||||
(this is more complex, though, because it introduces the need for an API load balancer)
|
||||
|
||||
---
|
||||
|
||||
## Manual setup
|
||||
|
||||
- The resources below are mainly for educational purposes!
|
||||
|
||||
- [Kubernetes The Hard Way](https://github.com/kelseyhightower/kubernetes-the-hard-way) by Kelsey Hightower
|
||||
|
||||
- step by step guide to install Kubernetes on Google Cloud
|
||||
|
||||
- covers certificates, high availability ...
|
||||
|
||||
- *“Kubernetes The Hard Way is optimized for learning, which means taking the long route to ensure you understand each task required to bootstrap a Kubernetes cluster.”*
|
||||
|
||||
- [Deep Dive into Kubernetes Internals for Builders and Operators](https://www.youtube.com/watch?v=3KtEAa7_duA)
|
||||
|
||||
- conference presentation showing step-by-step control plane setup
|
||||
|
||||
- emphasis on simplicity, not on security and availability
|
||||
|
||||
---
|
||||
|
||||
## About our training clusters
|
||||
|
||||
- How did we set up these Kubernetes clusters that we're using?
|
||||
|
||||
--
|
||||
|
||||
- We used `kubeadm` on freshly installed VM instances running Ubuntu LTS
|
||||
|
||||
1. Install Docker
|
||||
|
||||
2. Install Kubernetes packages
|
||||
|
||||
3. Run `kubeadm init` on the first node (it deploys the control plane on that node)
|
||||
|
||||
4. Set up Weave (the overlay network) with a single `kubectl apply` command
|
||||
|
||||
5. Run `kubeadm join` on the other nodes (with the token produced by `kubeadm init`)
|
||||
|
||||
6. Copy the configuration file generated by `kubeadm init`
|
||||
|
||||
- Check the [prepare VMs README](https://@@GITREPO@@/blob/master/prepare-vms/README.md) for more details
|
||||
|
||||
---
|
||||
|
||||
## `kubeadm` "drawbacks"
|
||||
|
||||
- Doesn't set up Docker or any other container engine
|
||||
|
||||
(this is by design, to give us choice)
|
||||
|
||||
- Doesn't set up the overlay network
|
||||
|
||||
(this is also by design, for the same reasons)
|
||||
|
||||
- HA control plane requires [some extra steps](https://kubernetes.io/docs/setup/independent/high-availability/)
|
||||
|
||||
- Note that HA control plane also requires setting up a specific API load balancer
|
||||
|
||||
(which is beyond the scope of kubeadm)
|
||||
|
||||
???
|
||||
|
||||
:EN:- Various ways to install Kubernetes
|
||||
:FR:- Survol des techniques d'installation de Kubernetes
|
||||
@@ -1,5 +1,15 @@
|
||||
# Kubernetes distributions and installers
|
||||
|
||||
- Sometimes, we need to run Kubernetes ourselves
|
||||
|
||||
(as opposed to "use a managed offering")
|
||||
|
||||
- Beware: it takes *a lot of work* to set up and maintain Kubernetes
|
||||
|
||||
- It might be necessary if you have specific security or compliance requirements
|
||||
|
||||
(e.g. national security for states that don't have a suitable domestic cloud)
|
||||
|
||||
- There are [countless](https://kubernetes.io/docs/setup/pick-right-solution/) distributions available
|
||||
|
||||
- We can't review them all
|
||||
@@ -8,7 +18,7 @@
|
||||
|
||||
---
|
||||
|
||||
## kops
|
||||
## [kops](https://github.com/kubernetes/kops)
|
||||
|
||||
- Deploys Kubernetes using cloud infrastructure
|
||||
|
||||
@@ -32,7 +42,7 @@
|
||||
|
||||
---
|
||||
|
||||
## Kubespray
|
||||
## [kubespray](https://github.com/kubernetes-incubator/kubespray)
|
||||
|
||||
- Based on Ansible
|
||||
|
||||
@@ -78,15 +88,21 @@
|
||||
|
||||
## And many more ...
|
||||
|
||||
- [AKS Engine](https://github.com/Azure/aks-engine)
|
||||
|
||||
- Docker Enterprise Edition
|
||||
|
||||
- [AKS Engine](https://github.com/Azure/aks-engine)
|
||||
- [Lokomotive](https://github.com/kinvolk/lokomotive), leveraging Terraform and [Flatcar Linux](https://www.flatcar-linux.org/)
|
||||
|
||||
- Pivotal Container Service (PKS)
|
||||
|
||||
- Tectonic by CoreOS
|
||||
- [Tarmak](https://github.com/jetstack/tarmak), leveraging Puppet and Terraform
|
||||
|
||||
- etc.
|
||||
- Tectonic by CoreOS (now being integrated into Red Hat OpenShift)
|
||||
|
||||
- [Typhoon](https://typhoon.psdn.io/), leveraging Terraform
|
||||
|
||||
- VMware Tanzu Kubernetes Grid (TKG)
|
||||
|
||||
---
|
||||
|
||||
@@ -111,5 +127,5 @@
|
||||
|
||||
???
|
||||
|
||||
:EN:- Various ways to set up Kubernetes
|
||||
:FR:- Différentes méthodes pour installer Kubernetes
|
||||
:EN:- Kubernetes distributions and installers
|
||||
:FR:- L'offre Kubernetes "on premises"
|
||||
|
||||
@@ -117,9 +117,9 @@ spec:
|
||||
name: my-nfs-volume
|
||||
volumes:
|
||||
- name: my-nfs-volume
|
||||
nfs:
|
||||
server: 192.168.0.55
|
||||
path: "/exports/assets"
|
||||
nfs:
|
||||
server: 192.168.0.55
|
||||
path: "/exports/assets"
|
||||
```
|
||||
|
||||
---
|
||||
@@ -297,7 +297,7 @@ nodes and encryption of gossip traffic) were removed for simplicity.
|
||||
|
||||
- Check the health of the cluster:
|
||||
```bash
|
||||
kubectl exec consul-0 consul members
|
||||
kubectl exec consul-0 -- consul members
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
title: |
|
||||
Kubernetes
|
||||
for Admins and Ops
|
||||
|
||||
#chat: "[Slack](https://dockercommunity.slack.com/messages/C7GKACWDV)"
|
||||
#chat: "[Gitter](https://gitter.im/jpetazzo/workshop-yyyymmdd-city)"
|
||||
chat: "In person!"
|
||||
|
||||
gitrepo: github.com/jpetazzo/container.training
|
||||
|
||||
slides: http://container.training/
|
||||
|
||||
#slidenumberprefix: "#SomeHashTag — "
|
||||
|
||||
exclude:
|
||||
- self-paced
|
||||
- static-pods-exercise
|
||||
|
||||
content:
|
||||
- shared/title.md
|
||||
- logistics.md
|
||||
- k8s/intro.md
|
||||
- shared/about-slides.md
|
||||
- shared/chat-room-im.md
|
||||
#- shared/chat-room-zoom-meeting.md
|
||||
#- shared/chat-room-zoom-webinar.md
|
||||
- shared/toc.md
|
||||
-
|
||||
- k8s/prereqs-admin.md
|
||||
- k8s/architecture.md
|
||||
- k8s/deploymentslideshow.md
|
||||
- k8s/dmuc.md
|
||||
-
|
||||
- k8s/multinode.md
|
||||
- k8s/cni.md
|
||||
- k8s/interco.md
|
||||
-
|
||||
- k8s/apilb.md
|
||||
#- k8s/setup-managed.md
|
||||
#- k8s/setup-selfhosted.md
|
||||
- k8s/cluster-upgrade.md
|
||||
- k8s/cluster-backup.md
|
||||
- k8s/staticpods.md
|
||||
-
|
||||
#- k8s/cloud-controller-manager.md
|
||||
#- k8s/bootstrap.md
|
||||
- k8s/control-plane-auth.md
|
||||
- k8s/podsecuritypolicy.md
|
||||
- k8s/csr-api.md
|
||||
- k8s/openid-connect.md
|
||||
-
|
||||
#- k8s/lastwords-admin.md
|
||||
- k8s/links.md
|
||||
- shared/thankyou.md
|
||||
@@ -1,75 +0,0 @@
|
||||
title: |
|
||||
Kubernetes
|
||||
for administrators
|
||||
and operators
|
||||
|
||||
#chat: "[Slack](https://dockercommunity.slack.com/messages/C7GKACWDV)"
|
||||
#chat: "[Gitter](https://gitter.im/jpetazzo/workshop-yyyymmdd-city)"
|
||||
chat: "In person!"
|
||||
|
||||
gitrepo: github.com/jpetazzo/container.training
|
||||
|
||||
slides: http://container.training/
|
||||
|
||||
#slidenumberprefix: "#SomeHashTag — "
|
||||
|
||||
exclude:
|
||||
- self-paced
|
||||
|
||||
content:
|
||||
- shared/title.md
|
||||
- logistics.md
|
||||
- k8s/intro.md
|
||||
- shared/about-slides.md
|
||||
- shared/chat-room-im.md
|
||||
#- shared/chat-room-zoom-meeting.md
|
||||
#- shared/chat-room-zoom-webinar.md
|
||||
- shared/toc.md
|
||||
# DAY 1
|
||||
- - k8s/prereqs-admin.md
|
||||
- k8s/architecture.md
|
||||
- k8s/deploymentslideshow.md
|
||||
- k8s/dmuc.md
|
||||
- - k8s/multinode.md
|
||||
- k8s/cni.md
|
||||
- k8s/interco.md
|
||||
- - k8s/apilb.md
|
||||
- k8s/setup-managed.md
|
||||
- k8s/setup-selfhosted.md
|
||||
- k8s/cluster-upgrade.md
|
||||
- k8s/staticpods.md
|
||||
- - k8s/cluster-backup.md
|
||||
- k8s/cloud-controller-manager.md
|
||||
- k8s/healthchecks.md
|
||||
- k8s/healthchecks-more.md
|
||||
# DAY 2
|
||||
- - k8s/kubercoins.md
|
||||
- k8s/logs-cli.md
|
||||
- k8s/logs-centralized.md
|
||||
- k8s/authn-authz.md
|
||||
- k8s/csr-api.md
|
||||
- - k8s/openid-connect.md
|
||||
- k8s/control-plane-auth.md
|
||||
###- k8s/bootstrap.md
|
||||
- k8s/netpol.md
|
||||
- k8s/podsecuritypolicy.md
|
||||
- - k8s/resource-limits.md
|
||||
- k8s/metrics-server.md
|
||||
- k8s/cluster-sizing.md
|
||||
- k8s/horizontal-pod-autoscaler.md
|
||||
- - k8s/prometheus.md
|
||||
- k8s/extending-api.md
|
||||
- k8s/operators.md
|
||||
###- k8s/operators-design.md
|
||||
# CONCLUSION
|
||||
- - k8s/lastwords.md
|
||||
- k8s/links.md
|
||||
- shared/thankyou.md
|
||||
- |
|
||||
# (All content after this slide is bonus material)
|
||||
# EXTRA
|
||||
- - k8s/volumes.md
|
||||
- k8s/configuration.md
|
||||
- k8s/statefulsets.md
|
||||
- k8s/local-persistent-volumes.md
|
||||
- k8s/portworx.md
|
||||
@@ -1,16 +1,22 @@
|
||||
title: |
|
||||
Deploying and Scaling Microservices
|
||||
with Kubernetes
|
||||
Kubernetes
|
||||
Intensive
|
||||
Workshop
|
||||
|
||||
#chat: "[Slack](https://dockercommunity.slack.com/messages/C7GKACWDV)"
|
||||
#chat: "[Gitter](https://gitter.im/jpetazzo/workshop-yyyymmdd-city)"
|
||||
chat: "In person!"
|
||||
chat: "[Gitter](https://gitter.im/jpetazzo/workshop-20200912-online)"
|
||||
|
||||
gitrepo: github.com/jpetazzo/container.training
|
||||
|
||||
slides: http://container.training/
|
||||
slides: https://2020-09-fwdays.container.training/
|
||||
|
||||
#slidenumberprefix: "#SomeHashTag — "
|
||||
slidenumberprefix:
|
||||
<a href="https://fwdays.com/">fwdays</a>
|
||||
—
|
||||
<a href="https://container.training/">container.training</a>
|
||||
—
|
||||
<a href="https://twitter.com/jpetazzo">@jpetazzo</a>
|
||||
—
|
||||
|
||||
|
||||
exclude:
|
||||
- self-paced
|
||||
@@ -35,9 +41,8 @@ content:
|
||||
- shared/composedown.md
|
||||
- k8s/concepts-k8s.md
|
||||
- k8s/kubectlget.md
|
||||
-
|
||||
- k8s/kubectl-run.md
|
||||
- k8s/batch-jobs.md
|
||||
-
|
||||
- k8s/labels-annotations.md
|
||||
- k8s/kubectl-logs.md
|
||||
- k8s/logs-cli.md
|
||||
@@ -53,7 +58,8 @@ content:
|
||||
#- k8s/exercise-wordsmith.md
|
||||
-
|
||||
- k8s/yamldeploy.md
|
||||
- k8s/setup-k8s.md
|
||||
#- k8s/setup-managed.md
|
||||
#- k8s/setup-selfhosted.md
|
||||
#- k8s/dashboard.md
|
||||
#- k8s/kubectlscale.md
|
||||
- k8s/scalingdockercoins.md
|
||||
@@ -65,7 +71,6 @@ content:
|
||||
#- k8s/accessinternal.md
|
||||
#- k8s/kubectlproxy.md
|
||||
- k8s/rollout.md
|
||||
#- k8s/healthchecks.md
|
||||
#- k8s/healthchecks-more.md
|
||||
#- k8s/record.md
|
||||
-
|
||||
@@ -80,8 +85,6 @@ content:
|
||||
#- k8s/exercise-helm.md
|
||||
#- k8s/create-chart.md
|
||||
#- k8s/create-more-charts.md
|
||||
#- k8s/netpol.md
|
||||
#- k8s/authn-authz.md
|
||||
#- k8s/csr-api.md
|
||||
#- k8s/openid-connect.md
|
||||
#- k8s/podsecuritypolicy.md
|
||||
@@ -92,17 +95,28 @@ content:
|
||||
- k8s/configuration.md
|
||||
#- k8s/logs-centralized.md
|
||||
#- k8s/prometheus.md
|
||||
#- k8s/statefulsets.md
|
||||
#- k8s/local-persistent-volumes.md
|
||||
#- k8s/portworx.md
|
||||
#- k8s/extending-api.md
|
||||
#- k8s/operators.md
|
||||
#- k8s/operators-design.md
|
||||
#- k8s/staticpods.md
|
||||
#- k8s/owners-and-dependents.md
|
||||
#- k8s/gitworkflows.md
|
||||
-
|
||||
- k8s/whatsnext.md
|
||||
- k8s/lastwords.md
|
||||
- k8s/setup-overview.md
|
||||
- k8s/setup-devel.md
|
||||
#- k8s/whatsnext.md
|
||||
#- k8s/lastwords.md
|
||||
- k8s/links.md
|
||||
- shared/thankyou.md
|
||||
-
|
||||
- |
|
||||
# (Extra content)
|
||||
- k8s/healthchecks.md
|
||||
- k8s/batch-jobs.md
|
||||
- k8s/netpol.md
|
||||
- k8s/authn-authz.md
|
||||
-
|
||||
- |
|
||||
# (More extra content)
|
||||
- k8s/statefulsets.md
|
||||
- k8s/local-persistent-volumes.md
|
||||
- k8s/portworx.md
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
title: |
|
||||
Kubernetes 101
|
||||
|
||||
|
||||
#chat: "[Slack](https://dockercommunity.slack.com/messages/C7GKACWDV)"
|
||||
#chat: "[Gitter](https://gitter.im/jpetazzo/training-20180413-paris)"
|
||||
chat: "In person!"
|
||||
|
||||
gitrepo: github.com/jpetazzo/container.training
|
||||
|
||||
slides: http://container.training/
|
||||
|
||||
#slidenumberprefix: "#SomeHashTag — "
|
||||
|
||||
exclude:
|
||||
- self-paced
|
||||
|
||||
content:
|
||||
- shared/title.md
|
||||
#- logistics.md
|
||||
# Bridget-specific; others use logistics.md
|
||||
- logistics-bridget.md
|
||||
- k8s/intro.md
|
||||
- shared/about-slides.md
|
||||
- shared/chat-room-im.md
|
||||
#- shared/chat-room-zoom-meeting.md
|
||||
#- shared/chat-room-zoom-webinar.md
|
||||
- shared/toc.md
|
||||
- - shared/prereqs.md
|
||||
#- shared/webssh.md
|
||||
- shared/connecting.md
|
||||
- k8s/versions-k8s.md
|
||||
- shared/sampleapp.md
|
||||
# Bridget doesn't go into as much depth with compose
|
||||
#- shared/composescale.md
|
||||
#- shared/hastyconclusions.md
|
||||
- shared/composedown.md
|
||||
- k8s/concepts-k8s.md
|
||||
- shared/declarative.md
|
||||
- k8s/declarative.md
|
||||
- k8s/kubenet.md
|
||||
- k8s/kubectlget.md
|
||||
- k8s/setup-k8s.md
|
||||
- - k8s/kubectl-run.md
|
||||
#- k8s/batch-jobs.md
|
||||
#- k8s/labels-annotations.md
|
||||
- k8s/kubectl-logs.md
|
||||
- k8s/deploymentslideshow.md
|
||||
- k8s/kubectlexpose.md
|
||||
- k8s/shippingimages.md
|
||||
#- k8s/buildshiprun-selfhosted.md
|
||||
- k8s/buildshiprun-dockerhub.md
|
||||
- k8s/ourapponkube.md
|
||||
#- k8s/localkubeconfig.md
|
||||
#- k8s/accessinternal.md
|
||||
#- k8s/kubectlproxy.md
|
||||
- - k8s/dashboard.md
|
||||
#- k8s/kubectlscale.md
|
||||
- k8s/scalingdockercoins.md
|
||||
- shared/hastyconclusions.md
|
||||
- k8s/daemonset.md
|
||||
- k8s/rollout.md
|
||||
#- k8s/record.md
|
||||
- - k8s/logs-cli.md
|
||||
# Bridget hasn't added EFK yet
|
||||
#- k8s/logs-centralized.md
|
||||
- k8s/namespaces.md
|
||||
- k8s/helm-intro.md
|
||||
#- k8s/helm-chart-format.md
|
||||
- k8s/helm-create-basic-chart.md
|
||||
#- k8s/helm-create-better-chart.md
|
||||
#- k8s/helm-secrets.md
|
||||
#- k8s/kustomize.md
|
||||
#- k8s/netpol.md
|
||||
- k8s/whatsnext.md
|
||||
# - k8s/links.md
|
||||
# Bridget-specific
|
||||
- k8s/links-bridget.md
|
||||
- shared/thankyou.md
|
||||
@@ -1,127 +0,0 @@
|
||||
title: |
|
||||
Deploying and Scaling Microservices
|
||||
with Docker and Kubernetes
|
||||
|
||||
chat: "[Slack](https://dockercommunity.slack.com/messages/C7GKACWDV)"
|
||||
#chat: "[Gitter](https://gitter.im/jpetazzo/workshop-yyyymmdd-city)"
|
||||
|
||||
|
||||
gitrepo: github.com/jpetazzo/container.training
|
||||
|
||||
slides: http://container.training/
|
||||
|
||||
#slidenumberprefix: "#SomeHashTag — "
|
||||
|
||||
exclude:
|
||||
- in-person
|
||||
|
||||
content:
|
||||
- shared/title.md
|
||||
#- logistics.md
|
||||
- k8s/intro.md
|
||||
- shared/about-slides.md
|
||||
#- shared/chat-room-im.md
|
||||
#- shared/chat-room-zoom-meeting.md
|
||||
#- shared/chat-room-zoom-webinar.md
|
||||
- shared/toc.md
|
||||
-
|
||||
- shared/prereqs.md
|
||||
#- shared/webssh.md
|
||||
- shared/connecting.md
|
||||
- k8s/versions-k8s.md
|
||||
- shared/sampleapp.md
|
||||
#- shared/composescale.md
|
||||
#- shared/hastyconclusions.md
|
||||
- shared/composedown.md
|
||||
- k8s/concepts-k8s.md
|
||||
-
|
||||
- k8s/kubectlget.md
|
||||
- k8s/kubectl-run.md
|
||||
- k8s/batch-jobs.md
|
||||
- k8s/labels-annotations.md
|
||||
- k8s/kubectl-logs.md
|
||||
- k8s/logs-cli.md
|
||||
- shared/declarative.md
|
||||
- k8s/declarative.md
|
||||
- k8s/deploymentslideshow.md
|
||||
-
|
||||
- k8s/kubenet.md
|
||||
- k8s/kubectlexpose.md
|
||||
- k8s/shippingimages.md
|
||||
- k8s/buildshiprun-selfhosted.md
|
||||
- k8s/buildshiprun-dockerhub.md
|
||||
- k8s/ourapponkube.md
|
||||
#- k8s/exercise-wordsmith.md
|
||||
- k8s/yamldeploy.md
|
||||
-
|
||||
- k8s/setup-k8s.md
|
||||
- k8s/dashboard.md
|
||||
#- k8s/kubectlscale.md
|
||||
- k8s/scalingdockercoins.md
|
||||
- shared/hastyconclusions.md
|
||||
- k8s/daemonset.md
|
||||
- k8s/dryrun.md
|
||||
#- k8s/exercise-yaml.md
|
||||
-
|
||||
- k8s/rollout.md
|
||||
- k8s/healthchecks.md
|
||||
- k8s/healthchecks-more.md
|
||||
- k8s/record.md
|
||||
-
|
||||
- k8s/namespaces.md
|
||||
- k8s/localkubeconfig.md
|
||||
- k8s/accessinternal.md
|
||||
- k8s/kubectlproxy.md
|
||||
-
|
||||
- k8s/ingress.md
|
||||
- k8s/kustomize.md
|
||||
- k8s/helm-intro.md
|
||||
- k8s/helm-chart-format.md
|
||||
- k8s/helm-create-basic-chart.md
|
||||
- k8s/helm-create-better-chart.md
|
||||
- k8s/helm-secrets.md
|
||||
#- k8s/exercise-helm.md
|
||||
-
|
||||
- k8s/netpol.md
|
||||
- k8s/authn-authz.md
|
||||
- k8s/podsecuritypolicy.md
|
||||
- k8s/csr-api.md
|
||||
- k8s/openid-connect.md
|
||||
- k8s/control-plane-auth.md
|
||||
-
|
||||
- k8s/volumes.md
|
||||
#- k8s/exercise-configmap.md
|
||||
- k8s/build-with-docker.md
|
||||
- k8s/build-with-kaniko.md
|
||||
-
|
||||
- k8s/configuration.md
|
||||
- k8s/statefulsets.md
|
||||
- k8s/local-persistent-volumes.md
|
||||
- k8s/portworx.md
|
||||
-
|
||||
- k8s/logs-centralized.md
|
||||
- k8s/prometheus.md
|
||||
- k8s/resource-limits.md
|
||||
- k8s/metrics-server.md
|
||||
- k8s/cluster-sizing.md
|
||||
- k8s/horizontal-pod-autoscaler.md
|
||||
-
|
||||
- k8s/extending-api.md
|
||||
- k8s/operators.md
|
||||
- k8s/operators-design.md
|
||||
- k8s/owners-and-dependents.md
|
||||
-
|
||||
- k8s/dmuc.md
|
||||
- k8s/multinode.md
|
||||
- k8s/cni.md
|
||||
- k8s/apilb.md
|
||||
- k8s/staticpods.md
|
||||
-
|
||||
- k8s/cluster-upgrade.md
|
||||
- k8s/cluster-backup.md
|
||||
- k8s/cloud-controller-manager.md
|
||||
- k8s/gitworkflows.md
|
||||
-
|
||||
- k8s/lastwords.md
|
||||
- k8s/links.md
|
||||
- shared/thankyou.md
|
||||
@@ -1,110 +0,0 @@
|
||||
title: |
|
||||
Deploying and Scaling Microservices
|
||||
with Kubernetes
|
||||
|
||||
#chat: "[Slack](https://dockercommunity.slack.com/messages/C7GKACWDV)"
|
||||
#chat: "[Gitter](https://gitter.im/jpetazzo/workshop-yyyymmdd-city)"
|
||||
chat: "In person!"
|
||||
|
||||
gitrepo: github.com/jpetazzo/container.training
|
||||
|
||||
slides: http://container.training/
|
||||
|
||||
#slidenumberprefix: "#SomeHashTag — "
|
||||
|
||||
exclude:
|
||||
- self-paced
|
||||
|
||||
content:
|
||||
- shared/title.md
|
||||
- logistics.md
|
||||
- k8s/intro.md
|
||||
- shared/about-slides.md
|
||||
- shared/chat-room-im.md
|
||||
#- shared/chat-room-zoom-meeting.md
|
||||
#- shared/chat-room-zoom-webinar.md
|
||||
- shared/toc.md
|
||||
-
|
||||
- shared/prereqs.md
|
||||
#- shared/webssh.md
|
||||
- shared/connecting.md
|
||||
#- k8s/versions-k8s.md
|
||||
- shared/sampleapp.md
|
||||
#- shared/composescale.md
|
||||
#- shared/hastyconclusions.md
|
||||
- shared/composedown.md
|
||||
- k8s/concepts-k8s.md
|
||||
- k8s/kubectlget.md
|
||||
-
|
||||
- k8s/kubectl-run.md
|
||||
- k8s/batch-jobs.md
|
||||
- k8s/labels-annotations.md
|
||||
- k8s/kubectl-logs.md
|
||||
- k8s/logs-cli.md
|
||||
- shared/declarative.md
|
||||
- k8s/declarative.md
|
||||
- k8s/deploymentslideshow.md
|
||||
- k8s/kubenet.md
|
||||
- k8s/kubectlexpose.md
|
||||
- k8s/shippingimages.md
|
||||
#- k8s/buildshiprun-selfhosted.md
|
||||
- k8s/buildshiprun-dockerhub.md
|
||||
- k8s/ourapponkube.md
|
||||
#- k8s/exercise-wordsmith.md
|
||||
-
|
||||
- k8s/yamldeploy.md
|
||||
#- k8s/setup-k8s.md
|
||||
- k8s/dashboard.md
|
||||
#- k8s/kubectlscale.md
|
||||
- k8s/scalingdockercoins.md
|
||||
- shared/hastyconclusions.md
|
||||
- k8s/daemonset.md
|
||||
- k8s/dryrun.md
|
||||
#- k8s/exercise-yaml.md
|
||||
-
|
||||
- k8s/localkubeconfig.md
|
||||
- k8s/accessinternal.md
|
||||
#- k8s/kubectlproxy.md
|
||||
- k8s/rollout.md
|
||||
- k8s/healthchecks.md
|
||||
#- k8s/healthchecks-more.md
|
||||
- k8s/record.md
|
||||
-
|
||||
- k8s/namespaces.md
|
||||
- k8s/ingress.md
|
||||
- k8s/kustomize.md
|
||||
- k8s/helm-intro.md
|
||||
- k8s/helm-chart-format.md
|
||||
- k8s/helm-create-basic-chart.md
|
||||
- k8s/helm-create-better-chart.md
|
||||
- k8s/helm-secrets.md
|
||||
#- k8s/exercise-helm.md
|
||||
-
|
||||
- k8s/netpol.md
|
||||
- k8s/authn-authz.md
|
||||
#- k8s/csr-api.md
|
||||
#- k8s/openid-connect.md
|
||||
#- k8s/podsecuritypolicy.md
|
||||
-
|
||||
- k8s/volumes.md
|
||||
#- k8s/exercise-configmap.md
|
||||
#- k8s/build-with-docker.md
|
||||
#- k8s/build-with-kaniko.md
|
||||
- k8s/configuration.md
|
||||
- k8s/logs-centralized.md
|
||||
- k8s/prometheus.md
|
||||
-
|
||||
- k8s/statefulsets.md
|
||||
- k8s/local-persistent-volumes.md
|
||||
- k8s/portworx.md
|
||||
#- k8s/extending-api.md
|
||||
#- k8s/operators.md
|
||||
#- k8s/operators-design.md
|
||||
#- k8s/staticpods.md
|
||||
#- k8s/owners-and-dependents.md
|
||||
#- k8s/gitworkflows.md
|
||||
-
|
||||
- k8s/whatsnext.md
|
||||
- k8s/lastwords.md
|
||||
- k8s/links.md
|
||||
- shared/thankyou.md
|
||||
@@ -1,32 +1,16 @@
|
||||
## Intros
|
||||
|
||||
- This slide should be customized by the tutorial instructor(s).
|
||||
|
||||
- Hello! We are:
|
||||
|
||||
- .emoji[👩🏻🏫] Ann O'Nymous ([@...](https://twitter.com/...), Megacorp Inc)
|
||||
|
||||
- .emoji[👨🏾🎓] Stu Dent ([@...](https://twitter.com/...), University of Wakanda)
|
||||
|
||||
<!-- .dummy[
|
||||
|
||||
- .emoji[👷🏻♀️] AJ ([@s0ulshake](https://twitter.com/s0ulshake), Travis CI)
|
||||
|
||||
- .emoji[🚁] Alexandre ([@alexbuisine](https://twitter.com/alexbuisine), Enix SAS)
|
||||
- .emoji[👷🏻♀️] AJ ([@s0ulshake](https://twitter.com/s0ulshake), [EphemeraSearch](https://ephemerasearch.com/))
|
||||
|
||||
- .emoji[🐳] Jérôme ([@jpetazzo](https://twitter.com/jpetazzo), Enix SAS)
|
||||
|
||||
- .emoji[⛵] Jérémy ([@jeremygarrouste](twitter.com/jeremygarrouste), Inpiwee)
|
||||
- The workshop will run from 10:00 to 15:00 (EEST timezone, GMT+3)
|
||||
|
||||
- .emoji[🎧] Romain ([@rdegez](https://twitter.com/rdegez), Enix SAS)
|
||||
- We will have short breaks at 11:10 and 13:50 (approximately!)
|
||||
|
||||
] -->
|
||||
|
||||
- The workshop will run from ...
|
||||
|
||||
- There will be a lunch break at ...
|
||||
|
||||
(And coffee breaks!)
|
||||
- And a longer lunch break at 12:20 (about 30 minutes)
|
||||
|
||||
- Feel free to interrupt for questions at any time
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
(then open the file `@@HTML@@`)
|
||||
|
||||
- You will to find new versions of these slides on:
|
||||
- You will find new versions of these slides on:
|
||||
|
||||
https://container.training/
|
||||
|
||||
|
||||
37
slides/shared/chat-room-twitch.md
Normal file
37
slides/shared/chat-room-twitch.md
Normal file
@@ -0,0 +1,37 @@
|
||||
## Use the chat!
|
||||
|
||||
- We have set up a chat room on @@CHAT@@
|
||||
|
||||
(clicking the link above will take you to the chat room)
|
||||
|
||||
- Don't hesitate to use it to ask questions, or get help, or share feedback
|
||||
|
||||
- We will *not* use the Twitch chat room for Q&A
|
||||
|
||||
(nothing wrong with it, but Gitter is more convenient for code snippets etc.)
|
||||
|
||||
- Feel free to ask questions at any time
|
||||
|
||||
- Sometimes we will wait a bit to answer ...
|
||||
|
||||
... but don't worry, we'll make sure to address all your questions!
|
||||
|
||||
---
|
||||
|
||||
## Use non-verbal communication cues
|
||||
|
||||
- ... wait, what?!?
|
||||
|
||||
--
|
||||
|
||||
- In the chat room, you are welcome (even encouraged!) to use emojis!
|
||||
|
||||
- Some of our favorites:
|
||||
|
||||
.emoji[🤔✔️👍🏻👍🏼👍🏽👍🏾👍🏿⚠️🛑]
|
||||
|
||||
- During the session, we'll often ask audience participation questions
|
||||
|
||||
- Feel free to answer in the chat room, any way you like!
|
||||
|
||||
(short message, emoji reaction ...)
|
||||
@@ -1,70 +0,0 @@
|
||||
title: |
|
||||
Container Orchestration
|
||||
with Docker and Swarm
|
||||
|
||||
chat: "[Slack](https://dockercommunity.slack.com/messages/C7GKACWDV)"
|
||||
#chat: "[Gitter](https://gitter.im/jpetazzo/workshop-yyyymmdd-city)"
|
||||
|
||||
gitrepo: github.com/jpetazzo/container.training
|
||||
|
||||
slides: http://container.training/
|
||||
|
||||
#slidenumberprefix: "#SomeHashTag — "
|
||||
|
||||
exclude:
|
||||
- self-paced
|
||||
- snap
|
||||
- btp-auto
|
||||
- benchmarking
|
||||
- elk-manual
|
||||
- prom-manual
|
||||
|
||||
content:
|
||||
- shared/title.md
|
||||
- logistics.md
|
||||
- swarm/intro.md
|
||||
- shared/about-slides.md
|
||||
- shared/chat-room-im.md
|
||||
#- shared/chat-room-zoom-meeting.md
|
||||
#- shared/chat-room-zoom-webinar.md
|
||||
- shared/toc.md
|
||||
- - shared/prereqs.md
|
||||
- shared/connecting.md
|
||||
- swarm/versions.md
|
||||
- shared/sampleapp.md
|
||||
- shared/composescale.md
|
||||
- shared/hastyconclusions.md
|
||||
- shared/composedown.md
|
||||
- swarm/swarmkit.md
|
||||
- shared/declarative.md
|
||||
- swarm/swarmmode.md
|
||||
- swarm/creatingswarm.md
|
||||
#- swarm/machine.md
|
||||
- swarm/morenodes.md
|
||||
- - swarm/firstservice.md
|
||||
- swarm/ourapponswarm.md
|
||||
- swarm/hostingregistry.md
|
||||
- swarm/testingregistry.md
|
||||
- swarm/btp-manual.md
|
||||
- swarm/swarmready.md
|
||||
- swarm/stacks.md
|
||||
- swarm/cicd.md
|
||||
- swarm/updatingservices.md
|
||||
- swarm/rollingupdates.md
|
||||
- swarm/healthchecks.md
|
||||
- - swarm/operatingswarm.md
|
||||
- swarm/netshoot.md
|
||||
- swarm/ipsec.md
|
||||
- swarm/swarmtools.md
|
||||
- swarm/security.md
|
||||
- swarm/secrets.md
|
||||
- swarm/encryptionatrest.md
|
||||
- swarm/leastprivilege.md
|
||||
- swarm/apiscope.md
|
||||
- - swarm/logging.md
|
||||
- swarm/metrics.md
|
||||
- swarm/gui.md
|
||||
- swarm/stateful.md
|
||||
- swarm/extratips.md
|
||||
- shared/thankyou.md
|
||||
- swarm/links.md
|
||||
@@ -1,69 +0,0 @@
|
||||
title: |
|
||||
Container Orchestration
|
||||
with Docker and Swarm
|
||||
|
||||
chat: "[Slack](https://dockercommunity.slack.com/messages/C7GKACWDV)"
|
||||
#chat: "[Gitter](https://gitter.im/jpetazzo/workshop-yyyymmdd-city)"
|
||||
|
||||
gitrepo: github.com/jpetazzo/container.training
|
||||
|
||||
slides: http://container.training/
|
||||
|
||||
#slidenumberprefix: "#SomeHashTag — "
|
||||
|
||||
exclude:
|
||||
- self-paced
|
||||
- snap
|
||||
- btp-manual
|
||||
- benchmarking
|
||||
- elk-manual
|
||||
- prom-manual
|
||||
|
||||
content:
|
||||
- shared/title.md
|
||||
- logistics.md
|
||||
- swarm/intro.md
|
||||
- shared/about-slides.md
|
||||
- shared/chat-room-im.md
|
||||
#- shared/chat-room-zoom-meeting.md
|
||||
#- shared/chat-room-zoom-webinar.md
|
||||
- shared/toc.md
|
||||
- - shared/prereqs.md
|
||||
- shared/connecting.md
|
||||
- swarm/versions.md
|
||||
- shared/sampleapp.md
|
||||
- shared/composescale.md
|
||||
- shared/hastyconclusions.md
|
||||
- shared/composedown.md
|
||||
- swarm/swarmkit.md
|
||||
- shared/declarative.md
|
||||
- swarm/swarmmode.md
|
||||
- swarm/creatingswarm.md
|
||||
#- swarm/machine.md
|
||||
- swarm/morenodes.md
|
||||
- - swarm/firstservice.md
|
||||
- swarm/ourapponswarm.md
|
||||
#- swarm/hostingregistry.md
|
||||
#- swarm/testingregistry.md
|
||||
#- swarm/btp-manual.md
|
||||
#- swarm/swarmready.md
|
||||
- swarm/stacks.md
|
||||
- swarm/cicd.md
|
||||
- swarm/updatingservices.md
|
||||
#- swarm/rollingupdates.md
|
||||
#- swarm/healthchecks.md
|
||||
- - swarm/operatingswarm.md
|
||||
#- swarm/netshoot.md
|
||||
#- swarm/ipsec.md
|
||||
#- swarm/swarmtools.md
|
||||
- swarm/security.md
|
||||
#- swarm/secrets.md
|
||||
#- swarm/encryptionatrest.md
|
||||
- swarm/leastprivilege.md
|
||||
- swarm/apiscope.md
|
||||
- swarm/logging.md
|
||||
- swarm/metrics.md
|
||||
#- swarm/stateful.md
|
||||
#- swarm/extratips.md
|
||||
- shared/thankyou.md
|
||||
- swarm/links.md
|
||||
@@ -1,78 +0,0 @@
|
||||
title: |
|
||||
Container Orchestration
|
||||
with Docker and Swarm
|
||||
|
||||
chat: "[Slack](https://dockercommunity.slack.com/messages/C7GKACWDV)"
|
||||
|
||||
gitrepo: github.com/jpetazzo/container.training
|
||||
|
||||
slides: http://container.training/
|
||||
|
||||
#slidenumberprefix: "#SomeHashTag — "
|
||||
|
||||
exclude:
|
||||
- in-person
|
||||
- btp-auto
|
||||
|
||||
content:
|
||||
- shared/title.md
|
||||
#- shared/logistics.md
|
||||
- swarm/intro.md
|
||||
- shared/about-slides.md
|
||||
#- shared/chat-room-im.md
|
||||
#- shared/chat-room-zoom-meeting.md
|
||||
#- shared/chat-room-zoom-webinar.md
|
||||
- shared/toc.md
|
||||
- - shared/prereqs.md
|
||||
- shared/connecting.md
|
||||
- swarm/versions.md
|
||||
- |
|
||||
name: part-1
|
||||
|
||||
class: title, self-paced
|
||||
|
||||
Part 1
|
||||
- shared/sampleapp.md
|
||||
- shared/composescale.md
|
||||
- shared/hastyconclusions.md
|
||||
- shared/composedown.md
|
||||
- swarm/swarmkit.md
|
||||
- shared/declarative.md
|
||||
- swarm/swarmmode.md
|
||||
- swarm/creatingswarm.md
|
||||
#- swarm/machine.md
|
||||
- swarm/morenodes.md
|
||||
- - swarm/firstservice.md
|
||||
- swarm/ourapponswarm.md
|
||||
- swarm/hostingregistry.md
|
||||
- swarm/testingregistry.md
|
||||
- swarm/btp-manual.md
|
||||
- swarm/swarmready.md
|
||||
- swarm/stacks.md
|
||||
- swarm/cicd.md
|
||||
- |
|
||||
name: part-2
|
||||
|
||||
class: title, self-paced
|
||||
|
||||
Part 2
|
||||
- - swarm/operatingswarm.md
|
||||
- swarm/netshoot.md
|
||||
- swarm/swarmnbt.md
|
||||
- swarm/ipsec.md
|
||||
- swarm/updatingservices.md
|
||||
- swarm/rollingupdates.md
|
||||
- swarm/healthchecks.md
|
||||
- swarm/nodeinfo.md
|
||||
- swarm/swarmtools.md
|
||||
- - swarm/security.md
|
||||
- swarm/secrets.md
|
||||
- swarm/encryptionatrest.md
|
||||
- swarm/leastprivilege.md
|
||||
- swarm/apiscope.md
|
||||
- swarm/logging.md
|
||||
- swarm/metrics.md
|
||||
- swarm/stateful.md
|
||||
- swarm/extratips.md
|
||||
- shared/thankyou.md
|
||||
- swarm/links.md
|
||||
@@ -1,74 +0,0 @@
|
||||
title: |
|
||||
Container Orchestration
|
||||
with Docker and Swarm
|
||||
|
||||
chat: "[Slack](https://dockercommunity.slack.com/messages/C7GKACWDV)"
|
||||
|
||||
gitrepo: github.com/jpetazzo/container.training
|
||||
|
||||
slides: http://container.training/
|
||||
|
||||
#slidenumberprefix: "#SomeHashTag — "
|
||||
|
||||
exclude:
|
||||
- in-person
|
||||
- btp-auto
|
||||
|
||||
content:
|
||||
- shared/title.md
|
||||
#- shared/logistics.md
|
||||
- swarm/intro.md
|
||||
- shared/about-slides.md
|
||||
- shared/toc.md
|
||||
- - shared/prereqs.md
|
||||
- shared/connecting.md
|
||||
- swarm/versions.md
|
||||
- |
|
||||
name: part-1
|
||||
|
||||
class: title, self-paced
|
||||
|
||||
Part 1
|
||||
- shared/sampleapp.md
|
||||
- shared/composescale.md
|
||||
- shared/hastyconclusions.md
|
||||
- shared/composedown.md
|
||||
- swarm/swarmkit.md
|
||||
- shared/declarative.md
|
||||
- swarm/swarmmode.md
|
||||
- swarm/creatingswarm.md
|
||||
#- swarm/machine.md
|
||||
- swarm/morenodes.md
|
||||
- - swarm/firstservice.md
|
||||
- swarm/ourapponswarm.md
|
||||
- swarm/hostingregistry.md
|
||||
- swarm/testingregistry.md
|
||||
- swarm/btp-manual.md
|
||||
- swarm/swarmready.md
|
||||
- swarm/stacks.md
|
||||
- |
|
||||
name: part-2
|
||||
|
||||
class: title, self-paced
|
||||
|
||||
Part 2
|
||||
- - swarm/operatingswarm.md
|
||||
#- swarm/netshoot.md
|
||||
#- swarm/swarmnbt.md
|
||||
- swarm/ipsec.md
|
||||
- swarm/updatingservices.md
|
||||
- swarm/rollingupdates.md
|
||||
#- swarm/healthchecks.md
|
||||
- swarm/nodeinfo.md
|
||||
- swarm/swarmtools.md
|
||||
- - swarm/security.md
|
||||
- swarm/secrets.md
|
||||
- swarm/encryptionatrest.md
|
||||
- swarm/leastprivilege.md
|
||||
- swarm/apiscope.md
|
||||
#- swarm/logging.md
|
||||
#- swarm/metrics.md
|
||||
- swarm/stateful.md
|
||||
- swarm/extratips.md
|
||||
- shared/thankyou.md
|
||||
- swarm/links.md
|
||||
Reference in New Issue
Block a user