Compare commits

..

13 Commits

Author SHA1 Message Date
Jerome Petazzoni
08fa37dace fix-redirects.sh: adding forced redirect 2020-04-07 16:57:19 -05:00
Jerome Petazzoni
807028cbf3 Remove WiFi warning 2019-06-13 10:51:44 -05:00
Jerome Petazzoni
dfde597cb9 Merge branch 'master' into sfsf-2019-06 2019-06-13 10:51:22 -05:00
Jerome Petazzoni
96419c6baf test→node 2019-06-12 21:35:12 -05:00
Jerome Petazzoni
12da011f21 Customize logistics etc 2019-06-12 21:13:00 -05:00
Jerome Petazzoni
fa1637fb7e Add Helm charts and reorg content 2019-06-12 21:07:55 -05:00
Jerome Petazzoni
fbe2251e21 Merge remote-tracking branch 'origin/make-chart' into sfsf-2019-06 2019-06-12 21:07:12 -05:00
Jerome Petazzoni
b4faf10581 merge 2019-06-12 16:43:24 -05:00
Jerome Petazzoni
0ef9c87f97 Merge branch 'master' into sfsf-2019-06 2019-06-12 16:04:36 -05:00
Jerome Petazzoni
addd14582a merge 2019-06-09 18:41:04 -05:00
Jerome Petazzoni
5299fbaab5 merge 2019-06-02 19:32:20 -05:00
Jerome Petazzoni
398ff5ee4f merge 2019-06-02 16:48:30 -05:00
Jerome Petazzoni
b883e6d557 Prepare SFSF training 2019-06-02 16:47:53 -05:00
65 changed files with 463 additions and 1627 deletions

1
.gitignore vendored
View File

@@ -3,7 +3,6 @@
*~
prepare-vms/tags
prepare-vms/infra
prepare-vms/www
slides/*.yml.html
slides/autopilot/state.yaml
slides/index.html

View File

@@ -39,7 +39,7 @@ your own tutorials.
All these materials have been gathered in a single repository
because they have a few things in common:
- some [shared slides](slides/shared/) that are re-used
- some [common slides](slides/common/) that are re-used
(and updated) identically between different decks;
- a [build system](slides/) generating HTML slides from
Markdown source files;

View File

@@ -72,7 +72,7 @@ spec:
terminationGracePeriodSeconds: 10
containers:
- name: consul
image: "consul:1.5"
image: "consul:1.4.4"
args:
- "agent"
- "-bootstrap-expect=3"

View File

@@ -32,16 +32,13 @@ subjects:
name: fluentd
namespace: default
---
apiVersion: apps/v1
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: fluentd
labels:
app: fluentd
spec:
selector:
matchLabels:
app: fluentd
template:
metadata:
labels:
@@ -54,7 +51,7 @@ spec:
effect: NoSchedule
containers:
- name: fluentd
image: fluent/fluentd-kubernetes-daemonset:v1.4-debian-elasticsearch-1
image: fluent/fluentd-kubernetes-daemonset:v1.3-debian-elasticsearch-1
env:
- name: FLUENT_ELASTICSEARCH_HOST
value: "elasticsearch"
@@ -89,7 +86,7 @@ spec:
hostPath:
path: /var/lib/docker/containers
---
apiVersion: apps/v1
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
@@ -131,7 +128,7 @@ spec:
app: elasticsearch
type: ClusterIP
---
apiVersion: apps/v1
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:

View File

@@ -1,13 +1,14 @@
apiVersion: networking.k8s.io/v1beta1
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: kibana
name: cheddar
spec:
rules:
- host: kibana.185.145.251.54.nip.io
- host: cheddar.A.B.C.D.nip.io
http:
paths:
- path: /
backend:
serviceName: kibana
servicePort: 5601
serviceName: cheddar
servicePort: 80

View File

@@ -12,6 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# Configuration to deploy release version of the Dashboard UI compatible with
# Kubernetes 1.8.
#
# Example usage: kubectl create -f <this_file>
# ------------------- Dashboard Secret ------------------- #
apiVersion: v1
@@ -90,7 +95,7 @@ subjects:
# ------------------- Dashboard Deployment ------------------- #
kind: Deployment
apiVersion: apps/v1
apiVersion: apps/v1beta2
metadata:
labels:
k8s-app: kubernetes-dashboard
@@ -109,13 +114,12 @@ spec:
spec:
containers:
- name: kubernetes-dashboard
image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1
image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.8.3
ports:
- containerPort: 8443
protocol: TCP
args:
- --auto-generate-certificates
- --enable-skip-login
# Uncomment the following line to manually specify Kubernetes API server Host
# If not specified, Dashboard will attempt to auto discover the API server and connect
# to it. Uncomment only if the default does not work.
@@ -162,7 +166,7 @@ spec:
selector:
k8s-app: kubernetes-dashboard
---
apiVersion: apps/v1
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:

View File

@@ -1,5 +1,5 @@
apiVersion: v1
kind: Pod
Kind: Pod
metadata:
name: hello
namespace: default

View File

@@ -12,6 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# Configuration to deploy release version of the Dashboard UI compatible with
# Kubernetes 1.8.
#
# Example usage: kubectl create -f <this_file>
# ------------------- Dashboard Secret ------------------- #
apiVersion: v1
@@ -90,7 +95,7 @@ subjects:
# ------------------- Dashboard Deployment ------------------- #
kind: Deployment
apiVersion: apps/v1
apiVersion: apps/v1beta2
metadata:
labels:
k8s-app: kubernetes-dashboard
@@ -109,7 +114,7 @@ spec:
spec:
containers:
- name: kubernetes-dashboard
image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1
image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.8.3
ports:
- containerPort: 8443
protocol: TCP

View File

@@ -45,7 +45,7 @@ subjects:
name: local-path-provisioner-service-account
namespace: local-path-storage
---
apiVersion: apps/v1
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: local-path-provisioner

View File

@@ -58,7 +58,7 @@ metadata:
name: metrics-server
namespace: kube-system
---
apiVersion: apps/v1
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: metrics-server
@@ -82,7 +82,7 @@ spec:
emptyDir: {}
containers:
- name: metrics-server
image: k8s.gcr.io/metrics-server-amd64:v0.3.3
image: k8s.gcr.io/metrics-server-amd64:v0.3.1
imagePullPolicy: Always
volumeMounts:
- name: tmp-dir

View File

@@ -74,7 +74,7 @@ spec:
terminationGracePeriodSeconds: 10
containers:
- name: consul
image: "consul:1.5"
image: "consul:1.4.4"
volumeMounts:
- name: data
mountPath: /consul/data

View File

@@ -1,340 +1,4 @@
# SOURCE: https://install.portworx.com/?kbver=1.15.2&b=true&s=/dev/loop4&c=px-workshop&stork=true&lh=true&st=k8s&mc=false
# SOURCE: https://install.portworx.com/?kbver=1.15.2&b=true&s=/dev/loop4&c=px-workshop&stork=true&lh=true&st=k8s&mc=false
---
kind: Service
apiVersion: v1
metadata:
name: portworx-service
namespace: kube-system
labels:
name: portworx
spec:
selector:
name: portworx
type: NodePort
ports:
- name: px-api
protocol: TCP
port: 9001
targetPort: 9001
- name: px-kvdb
protocol: TCP
port: 9019
targetPort: 9019
- name: px-sdk
protocol: TCP
port: 9020
targetPort: 9020
- name: px-rest-gateway
protocol: TCP
port: 9021
targetPort: 9021
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: volumeplacementstrategies.portworx.io
spec:
group: portworx.io
versions:
- name: v1beta2
served: true
storage: true
- name: v1beta1
served: false
storage: false
scope: Cluster
names:
plural: volumeplacementstrategies
singular: volumeplacementstrategy
kind: VolumePlacementStrategy
shortNames:
- vps
- vp
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: px-account
namespace: kube-system
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: node-get-put-list-role
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["watch", "get", "update", "list"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["delete", "get", "list", "watch", "update"]
- apiGroups: [""]
resources: ["persistentvolumeclaims", "persistentvolumes"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list", "update", "create"]
- apiGroups: ["extensions"]
resources: ["podsecuritypolicies"]
resourceNames: ["privileged"]
verbs: ["use"]
- apiGroups: ["portworx.io"]
resources: ["volumeplacementstrategies"]
verbs: ["get", "list"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: node-role-binding
subjects:
- kind: ServiceAccount
name: px-account
namespace: kube-system
roleRef:
kind: ClusterRole
name: node-get-put-list-role
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: Namespace
metadata:
name: portworx
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: px-role
namespace: portworx
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: px-role-binding
namespace: portworx
subjects:
- kind: ServiceAccount
name: px-account
namespace: kube-system
roleRef:
kind: Role
name: px-role
apiGroup: rbac.authorization.k8s.io
---
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: portworx
namespace: kube-system
annotations:
portworx.com/install-source: "https://install.portworx.com/?kbver=1.15.2&b=true&s=/dev/loop4&c=px-workshop&stork=true&lh=true&st=k8s&mc=false"
spec:
minReadySeconds: 0
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
template:
metadata:
labels:
name: portworx
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: px/enabled
operator: NotIn
values:
- "false"
- key: node-role.kubernetes.io/master
operator: DoesNotExist
hostNetwork: true
hostPID: false
initContainers:
- name: checkloop
image: alpine
command: [ "sh", "-c" ]
args:
- |
if ! grep -q loop4 /proc/partitions; then
echo 'Could not find "loop4" in /proc/partitions. Please create it first.'
exit 1
fi
containers:
- name: portworx
image: portworx/oci-monitor:2.1.3
imagePullPolicy: Always
args:
["-c", "px-workshop", "-s", "/dev/loop4", "-secret_type", "k8s", "-b",
"-x", "kubernetes"]
env:
- name: "AUTO_NODE_RECOVERY_TIMEOUT_IN_SECS"
value: "1500"
- name: "PX_TEMPLATE_VERSION"
value: "v4"
livenessProbe:
periodSeconds: 30
initialDelaySeconds: 840 # allow image pull in slow networks
httpGet:
host: 127.0.0.1
path: /status
port: 9001
readinessProbe:
periodSeconds: 10
httpGet:
host: 127.0.0.1
path: /health
port: 9015
terminationMessagePath: "/tmp/px-termination-log"
securityContext:
privileged: true
volumeMounts:
- name: diagsdump
mountPath: /var/cores
- name: dockersock
mountPath: /var/run/docker.sock
- name: containerdsock
mountPath: /run/containerd
- name: criosock
mountPath: /var/run/crio
- name: crioconf
mountPath: /etc/crictl.yaml
- name: etcpwx
mountPath: /etc/pwx
- name: optpwx
mountPath: /opt/pwx
- name: procmount
mountPath: /host_proc
- name: sysdmount
mountPath: /etc/systemd/system
- name: journalmount1
mountPath: /var/run/log
readOnly: true
- name: journalmount2
mountPath: /var/log
readOnly: true
- name: dbusmount
mountPath: /var/run/dbus
restartPolicy: Always
serviceAccountName: px-account
volumes:
- name: diagsdump
hostPath:
path: /var/cores
- name: dockersock
hostPath:
path: /var/run/docker.sock
- name: containerdsock
hostPath:
path: /run/containerd
- name: criosock
hostPath:
path: /var/run/crio
- name: crioconf
hostPath:
path: /etc/crictl.yaml
type: FileOrCreate
- name: etcpwx
hostPath:
path: /etc/pwx
- name: optpwx
hostPath:
path: /opt/pwx
- name: procmount
hostPath:
path: /proc
- name: sysdmount
hostPath:
path: /etc/systemd/system
- name: journalmount1
hostPath:
path: /var/run/log
- name: journalmount2
hostPath:
path: /var/log
- name: dbusmount
hostPath:
path: /var/run/dbus
---
kind: Service
apiVersion: v1
metadata:
name: portworx-api
namespace: kube-system
labels:
name: portworx-api
spec:
selector:
name: portworx-api
type: NodePort
ports:
- name: px-api
protocol: TCP
port: 9001
targetPort: 9001
- name: px-sdk
protocol: TCP
port: 9020
targetPort: 9020
- name: px-rest-gateway
protocol: TCP
port: 9021
targetPort: 9021
---
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: portworx-api
namespace: kube-system
spec:
minReadySeconds: 0
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 100%
template:
metadata:
labels:
name: portworx-api
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: px/enabled
operator: NotIn
values:
- "false"
- key: node-role.kubernetes.io/master
operator: DoesNotExist
hostNetwork: true
hostPID: false
containers:
- name: portworx-api
image: k8s.gcr.io/pause:3.1
imagePullPolicy: Always
readinessProbe:
periodSeconds: 10
httpGet:
host: 127.0.0.1
path: /status
port: 9001
restartPolicy: Always
serviceAccountName: px-account
---
# SOURCE: https://install.portworx.com/?kbver=1.11.2&b=true&s=/dev/loop4&c=px-workshop&stork=true&lh=true
apiVersion: v1
kind: ConfigMap
metadata:
@@ -347,7 +11,7 @@ data:
"apiVersion": "v1",
"extenders": [
{
"urlPrefix": "http://stork-service.kube-system:8099",
"urlPrefix": "http://stork-service.kube-system.svc:8099",
"apiVersion": "v1beta1",
"filterVerb": "filter",
"prioritizeVerb": "prioritize",
@@ -370,8 +34,8 @@ metadata:
name: stork-role
rules:
- apiGroups: [""]
resources: ["pods", "pods/exec"]
verbs: ["get", "list", "delete", "create", "watch"]
resources: ["pods"]
verbs: ["get", "list", "delete"]
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
@@ -384,14 +48,14 @@ rules:
- apiGroups: [""]
resources: ["events"]
verbs: ["list", "watch", "create", "update", "patch"]
- apiGroups: ["stork.libopenstorage.org"]
resources: ["*"]
verbs: ["get", "list", "watch", "update", "patch", "create", "delete"]
- apiGroups: ["apiextensions.k8s.io"]
resources: ["customresourcedefinitions"]
verbs: ["create", "get"]
verbs: ["create", "list", "watch", "delete"]
- apiGroups: ["volumesnapshot.external-storage.k8s.io"]
resources: ["volumesnapshots", "volumesnapshotdatas"]
resources: ["volumesnapshots"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["volumesnapshot.external-storage.k8s.io"]
resources: ["volumesnapshotdatas"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["configmaps"]
@@ -408,9 +72,6 @@ rules:
- apiGroups: ["*"]
resources: ["statefulsets", "statefulsets/extensions"]
verbs: ["list", "get", "watch", "patch", "update", "initialize"]
- apiGroups: ["*"]
resources: ["*"]
verbs: ["list", "get"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
@@ -470,10 +131,7 @@ spec:
- --leader-elect=true
- --health-monitor-interval=120
imagePullPolicy: Always
image: openstorage/stork:2.2.4
env:
- name: "PX_SERVICE_NAME"
value: "portworx-api"
image: openstorage/stork:1.1.3
resources:
requests:
cpu: '0.1'
@@ -510,13 +168,16 @@ metadata:
rules:
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "create", "update"]
verbs: ["get", "update"]
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "patch", "update"]
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["create"]
- apiGroups: [""]
resourceNames: ["kube-scheduler"]
resources: ["endpoints"]
@@ -536,7 +197,7 @@ rules:
- apiGroups: [""]
resources: ["replicationcontrollers", "services"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps", "extensions"]
- apiGroups: ["app", "extensions"]
resources: ["replicasets"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
@@ -592,7 +253,7 @@ spec:
- --policy-configmap=stork-config
- --policy-configmap-namespace=kube-system
- --lock-object-name=stork-scheduler
image: gcr.io/google_containers/kube-scheduler-amd64:v1.15.2
image: gcr.io/google_containers/kube-scheduler-amd64:v1.11.2
livenessProbe:
httpGet:
path: /healthz
@@ -619,61 +280,229 @@ spec:
hostPID: false
serviceAccountName: stork-scheduler-account
---
kind: Service
apiVersion: v1
metadata:
name: portworx-service
namespace: kube-system
labels:
name: portworx
spec:
selector:
name: portworx
ports:
- name: px-api
protocol: TCP
port: 9001
targetPort: 9001
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: px-account
namespace: kube-system
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: node-get-put-list-role
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["watch", "get", "update", "list"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["delete", "get", "list"]
- apiGroups: [""]
resources: ["persistentvolumeclaims", "persistentvolumes"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list", "update", "create"]
- apiGroups: ["extensions"]
resources: ["podsecuritypolicies"]
resourceNames: ["privileged"]
verbs: ["use"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: node-role-binding
subjects:
- kind: ServiceAccount
name: px-account
namespace: kube-system
roleRef:
kind: ClusterRole
name: node-get-put-list-role
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: Namespace
metadata:
name: portworx
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: px-role
namespace: portworx
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: px-role-binding
namespace: portworx
subjects:
- kind: ServiceAccount
name: px-account
namespace: kube-system
roleRef:
kind: Role
name: px-role
apiGroup: rbac.authorization.k8s.io
---
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: portworx
namespace: kube-system
annotations:
portworx.com/install-source: "https://install.portworx.com/?kbver=1.11.2&b=true&s=/dev/loop4&c=px-workshop&stork=true&lh=true"
spec:
minReadySeconds: 0
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
template:
metadata:
labels:
name: portworx
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: px/enabled
operator: NotIn
values:
- "false"
- key: node-role.kubernetes.io/master
operator: DoesNotExist
hostNetwork: true
hostPID: false
containers:
- name: portworx
image: portworx/oci-monitor:1.4.2.2
imagePullPolicy: Always
args:
["-c", "px-workshop", "-s", "/dev/loop4", "-b",
"-x", "kubernetes"]
env:
- name: "PX_TEMPLATE_VERSION"
value: "v4"
livenessProbe:
periodSeconds: 30
initialDelaySeconds: 840 # allow image pull in slow networks
httpGet:
host: 127.0.0.1
path: /status
port: 9001
readinessProbe:
periodSeconds: 10
httpGet:
host: 127.0.0.1
path: /health
port: 9015
terminationMessagePath: "/tmp/px-termination-log"
securityContext:
privileged: true
volumeMounts:
- name: dockersock
mountPath: /var/run/docker.sock
- name: etcpwx
mountPath: /etc/pwx
- name: optpwx
mountPath: /opt/pwx
- name: proc1nsmount
mountPath: /host_proc/1/ns
- name: sysdmount
mountPath: /etc/systemd/system
- name: diagsdump
mountPath: /var/cores
- name: journalmount1
mountPath: /var/run/log
readOnly: true
- name: journalmount2
mountPath: /var/log
readOnly: true
- name: dbusmount
mountPath: /var/run/dbus
restartPolicy: Always
serviceAccountName: px-account
volumes:
- name: dockersock
hostPath:
path: /var/run/docker.sock
- name: etcpwx
hostPath:
path: /etc/pwx
- name: optpwx
hostPath:
path: /opt/pwx
- name: proc1nsmount
hostPath:
path: /proc/1/ns
- name: sysdmount
hostPath:
path: /etc/systemd/system
- name: diagsdump
hostPath:
path: /var/cores
- name: journalmount1
hostPath:
path: /var/run/log
- name: journalmount2
hostPath:
path: /var/log
- name: dbusmount
hostPath:
path: /var/run/dbus
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: px-lh-account
namespace: kube-system
---
kind: ClusterRole
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: px-lh-role
namespace: kube-system
name: px-lh-role
namespace: kube-system
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["list", "get"]
- apiGroups:
- extensions
- apps
resources:
- deployments
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "create", "update"]
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "create", "update"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["services"]
verbs: ["create", "get", "list", "watch"]
- apiGroups: ["stork.libopenstorage.org"]
resources: ["clusterpairs","migrations","groupvolumesnapshots"]
verbs: ["get", "list", "create", "update", "delete"]
- apiGroups: ["monitoring.coreos.com"]
resources:
- alertmanagers
- prometheuses
- prometheuses/finalizers
- servicemonitors
verbs: ["*"]
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "create", "update"]
---
kind: ClusterRoleBinding
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: px-lh-role-binding
namespace: kube-system
subjects:
- kind: ServiceAccount
name: px-lh-account
namespace: kube-system
- kind: ServiceAccount
name: px-lh-account
namespace: kube-system
roleRef:
kind: ClusterRole
kind: Role
name: px-lh-role
apiGroup: rbac.authorization.k8s.io
---
@@ -689,12 +518,14 @@ spec:
ports:
- name: http
port: 80
nodePort: 32678
- name: https
port: 443
nodePort: 32679
selector:
tier: px-web-console
---
apiVersion: apps/v1beta1
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: px-lighthouse
@@ -718,7 +549,7 @@ spec:
spec:
initContainers:
- name: config-init
image: portworx/lh-config-sync:0.4
image: portworx/lh-config-sync:0.2
imagePullPolicy: Always
args:
- "init"
@@ -727,9 +558,8 @@ spec:
mountPath: /config/lh
containers:
- name: px-lighthouse
image: portworx/px-lighthouse:2.0.4
image: portworx/px-lighthouse:1.5.0
imagePullPolicy: Always
args: [ "-kubernetes", "true" ]
ports:
- containerPort: 80
- containerPort: 443
@@ -737,16 +567,13 @@ spec:
- name: config
mountPath: /config/lh
- name: config-sync
image: portworx/lh-config-sync:0.4
image: portworx/lh-config-sync:0.2
imagePullPolicy: Always
args:
- "sync"
volumeMounts:
- name: config
mountPath: /config/lh
- name: stork-connector
image: portworx/lh-stork-connector:0.2
imagePullPolicy: Always
serviceAccountName: px-lh-account
volumes:
- name: config

View File

@@ -15,7 +15,7 @@ spec:
schedulerName: stork
containers:
- name: postgres
image: postgres:11
image: postgres:10.5
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: postgres

View File

@@ -6,16 +6,13 @@ metadata:
namespace: kube-system
---
kind: DaemonSet
apiVersion: apps/v1
apiVersion: extensions/v1beta1
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:
@@ -29,7 +26,7 @@ spec:
serviceAccountName: traefik-ingress-controller
terminationGracePeriodSeconds: 60
containers:
- image: traefik:1.7
- image: traefik
name: traefik-ingress-lb
ports:
- name: http

View File

@@ -87,37 +87,26 @@ You're all set!
```
workshopctl - the orchestration workshop swiss army knife
Commands:
build Build the Docker image to run this program in a container
cards Generate ready-to-print cards for a group of VMs
deploy Install Docker on a bunch of running VMs
disableaddrchecks Disable source/destination IP address checks
disabledocker Stop Docker Engine and don't restart it automatically
helmprom Install Helm and Prometheus
help Show available commands
ids (FIXME) List the instance IDs belonging to a given tag or token
kubebins Install Kubernetes and CNI binaries but don't start anything
kubereset Wipe out Kubernetes configuration on all nodes
kube Setup kubernetes clusters with kubeadm (must be run AFTER deploy)
kubetest Check that all nodes are reporting as Ready
listall List VMs running on all configured infrastructures
list List available groups for a given infrastructure
netfix Disable GRO and run a pinger job on the VMs
opensg Open the default security group to ALL ingress traffic
ping Ping VMs in a given tag, to check that they have network access
pssh Run an arbitrary command on all nodes
pull_images Pre-pull a bunch of Docker images
quotas Check our infrastructure quotas (max instances)
remap_nodeports Remap NodePort range to 10000-10999
retag (FIXME) Apply a new tag to a group of VMs
ssh Open an SSH session to the first node of a tag
start Start a group of VMs
stop Stop (terminate, shutdown, kill, remove, destroy...) instances
tags List groups of VMs known locally
test Run tests (pre-flight checks) on a group of VMs
weavetest Check that weave seems properly setup
webssh Install a WEB SSH server on the machines (port 1080)
wrap Run this program in a container
www Run a web server to access card HTML and PDF
ami Show the AMI that will be used for deployment
amis List Ubuntu AMIs in the current region
build Build the Docker image to run this program in a container
cards Generate ready-to-print cards for a group of VMs
deploy Install Docker on a bunch of running VMs
ec2quotas Check our EC2 quotas (max instances)
help Show available commands
ids List the instance IDs belonging to a given tag or token
ips List the IP addresses of the VMs for a given tag or token
kube Setup kubernetes clusters with kubeadm (must be run AFTER deploy)
kubetest Check that all notes are reporting as Ready
list List available groups in the current region
opensg Open the default security group to ALL ingress traffic
pull_images Pre-pull a bunch of Docker images
retag Apply a new tag to a group of VMs
start Start a group of VMs
status List instance status for a given group
stop Stop (terminate, shutdown, kill, remove, destroy...) instances
test Run tests (pre-flight checks) on a group of VMs
wrap Run this program in a container
```
### Summary of What `./workshopctl` Does For You

View File

@@ -33,14 +33,9 @@ _cmd_cards() {
../../lib/ips-txt-to-html.py settings.yaml
)
ln -sf ../tags/$TAG/ips.html www/$TAG.html
ln -sf ../tags/$TAG/ips.pdf www/$TAG.pdf
info "Cards created. You can view them with:"
info "xdg-open tags/$TAG/ips.html tags/$TAG/ips.pdf (on Linux)"
info "open tags/$TAG/ips.html (on macOS)"
info "Or you can start a web server with:"
info "$0 www"
}
_cmd deploy "Install Docker on a bunch of running VMs"
@@ -157,10 +152,10 @@ _cmd_kube() {
# Optional version, e.g. 1.13.5
KUBEVERSION=$2
if [ "$KUBEVERSION" ]; then
EXTRA_APTGET="=$KUBEVERSION-00"
EXTRA_KUBELET="=$KUBEVERSION-00"
EXTRA_KUBEADM="--kubernetes-version=v$KUBEVERSION"
else
EXTRA_APTGET=""
EXTRA_KUBELET=""
EXTRA_KUBEADM=""
fi
@@ -172,7 +167,7 @@ _cmd_kube() {
sudo tee /etc/apt/sources.list.d/kubernetes.list"
pssh --timeout 200 "
sudo apt-get update -q &&
sudo apt-get install -qy kubelet$EXTRA_APTGET kubeadm$EXTRA_APTGET kubectl$EXTRA_APTGET &&
sudo apt-get install -qy kubelet$EXTRA_KUBELET kubeadm kubectl &&
kubectl completion bash | sudo tee /etc/bash_completion.d/kubectl"
# Initialize kube master
@@ -234,7 +229,7 @@ EOF"
pssh "
if [ ! -x /usr/local/bin/stern ]; then
##VERSION##
sudo curl -L -o /usr/local/bin/stern https://github.com/wercker/stern/releases/download/1.11.0/stern_linux_amd64 &&
sudo curl -L -o /usr/local/bin/stern https://github.com/wercker/stern/releases/download/1.10.0/stern_linux_amd64 &&
sudo chmod +x /usr/local/bin/stern &&
stern --completion bash | sudo tee /etc/bash_completion.d/stern
fi"
@@ -323,14 +318,6 @@ _cmd_listall() {
done
}
_cmd ping "Ping VMs in a given tag, to check that they have network access"
_cmd_ping() {
TAG=$1
need_tag
fping < tags/$TAG/ips.txt
}
_cmd netfix "Disable GRO and run a pinger job on the VMs"
_cmd_netfix () {
TAG=$1
@@ -386,20 +373,6 @@ _cmd_pull_images() {
pull_tag
}
_cmd remap_nodeports "Remap NodePort range to 10000-10999"
_cmd_remap_nodeports() {
TAG=$1
need_tag
FIND_LINE=" - --service-cluster-ip-range=10.96.0.0\/12"
ADD_LINE=" - --service-node-port-range=10000-10999"
MANIFEST_FILE=/etc/kubernetes/manifests/kube-apiserver.yaml
pssh "
if i_am_first_node && ! grep -q '$ADD_LINE' $MANIFEST_FILE; then
sudo sed -i 's/\($FIND_LINE\)\$/\1\n$ADD_LINE/' $MANIFEST_FILE
fi"
}
_cmd quotas "Check our infrastructure quotas (max instances)"
_cmd_quotas() {
need_infra $1
@@ -555,50 +528,6 @@ _cmd_weavetest() {
sh -c \"./weave --local status | grep Connections | grep -q ' 1 failed' || ! echo POD \""
}
_cmd webssh "Install a WEB SSH server on the machines (port 1080)"
_cmd_webssh() {
TAG=$1
need_tag
pssh "
sudo apt-get update &&
sudo apt-get install python-tornado python-paramiko -y"
pssh "
[ -d webssh ] || 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"
pssh "cat >webssh.service <<EOF
[Unit]
Description=webssh
[Install]
WantedBy=multi-user.target
[Service]
WorkingDirectory=/home/ubuntu/webssh
ExecStart=/usr/bin/env python run.py --fbidhttp=false --port=1080 --policy=reject
User=nobody
Group=nogroup
Restart=always
EOF"
pssh "
sudo systemctl enable \$PWD/webssh.service &&
sudo systemctl start webssh.service"
}
_cmd www "Run a web server to access card HTML and PDF"
_cmd_www() {
cd www
IPADDR=$(curl -sL canihazip.com/s)
info "The following files are available:"
for F in *; do
echo "http://$IPADDR:8000/$F"
done
info "Press Ctrl-C to stop server."
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."

View File

@@ -31,7 +31,6 @@ infra_start() {
die "I could not find which AMI to use in this region. Try another region?"
fi
AWS_KEY_NAME=$(make_key_name)
AWS_INSTANCE_TYPE=${AWS_INSTANCE_TYPE-t3a.medium}
sep "Starting instances"
info " Count: $COUNT"
@@ -39,11 +38,10 @@ infra_start() {
info " Token/tag: $TAG"
info " AMI: $AMI"
info " Key name: $AWS_KEY_NAME"
info " Instance type: $AWS_INSTANCE_TYPE"
result=$(aws ec2 run-instances \
--key-name $AWS_KEY_NAME \
--count $COUNT \
--instance-type $AWS_INSTANCE_TYPE \
--instance-type ${AWS_INSTANCE_TYPE-t2.medium} \
--client-token $TAG \
--block-device-mapping 'DeviceName=/dev/sda1,Ebs={VolumeSize=20}' \
--image-id $AMI)
@@ -99,7 +97,7 @@ infra_disableaddrchecks() {
}
wait_until_tag_is_running() {
max_retry=100
max_retry=50
i=0
done_count=0
while [[ $done_count -lt $COUNT ]]; do

View File

@@ -4,12 +4,17 @@ import sys
import yaml
import jinja2
def prettify(l):
l = [ip.strip() for ip in l]
ret = [ "node{}: <code>{}</code>".format(i+1, s) for (i, s) in zip(range(len(l)), l) ]
return ret
# Read settings from user-provided settings file
context = yaml.safe_load(open(sys.argv[1]))
SETTINGS = yaml.load(open(sys.argv[1]))
clustersize = SETTINGS["clustersize"]
ips = list(open("ips.txt"))
clustersize = context["clustersize"]
print("---------------------------------------------")
print(" Number of IPs: {}".format(len(ips)))
@@ -25,9 +30,7 @@ while ips:
ips = ips[clustersize:]
clusters.append(cluster)
context["clusters"] = clusters
template_file_name = context["cards_template"]
template_file_name = SETTINGS["cards_template"]
template_file_path = os.path.join(
os.path.dirname(__file__),
"..",
@@ -36,19 +39,18 @@ template_file_path = os.path.join(
)
template = jinja2.Template(open(template_file_path).read())
with open("ips.html", "w") as f:
f.write(template.render(**context))
f.write(template.render(clusters=clusters, **SETTINGS))
print("Generated ips.html")
try:
import pdfkit
with open("ips.html") as f:
pdfkit.from_file(f, "ips.pdf", options={
"page-size": context["paper_size"],
"margin-top": context["paper_margin"],
"margin-bottom": context["paper_margin"],
"margin-left": context["paper_margin"],
"margin-right": context["paper_margin"],
"page-size": SETTINGS["paper_size"],
"margin-top": SETTINGS["paper_margin"],
"margin-bottom": SETTINGS["paper_margin"],
"margin-left": SETTINGS["paper_margin"],
"margin-right": SETTINGS["paper_margin"],
})
print("Generated ips.pdf")
except ImportError:

View File

@@ -73,29 +73,8 @@ set expandtab
set number
set shiftwidth=2
set softtabstop=2
set nowrap
SQRL""")
# Custom .tmux.conf
system(
"""sudo -u docker tee /home/docker/.tmux.conf <<SQRL
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R
# Allow using mouse to switch panes
set -g mouse on
# Make scrolling with wheels work
bind -n WheelUpPane if-shell -F -t = "#{mouse_any_flag}" "send-keys -M" "if -Ft= '#{pane_in_mode}' 'send-keys -M' 'select-pane -t=; copy-mode -e; send-keys -M'"
bind -n WheelDownPane select-pane -t= \; send-keys -M
SQRL"""
)
# add docker user to sudoers and allow password authentication
system("""sudo tee /etc/sudoers.d/docker <<SQRL
docker ALL=(ALL) NOPASSWD:ALL

View File

@@ -21,10 +21,8 @@ paper_margin: 0.2in
engine_version: stable
# These correspond to the version numbers visible on their respective GitHub release pages
compose_version: 1.24.1
compose_version: 1.21.1
machine_version: 0.14.0
# Password used to connect with the "docker user"
docker_user_password: training
image:

View File

@@ -21,11 +21,8 @@ paper_margin: 0.2in
engine_version: stable
# These correspond to the version numbers visible on their respective GitHub release pages
compose_version: 1.24.1
compose_version: 1.21.1
machine_version: 0.14.0
# Password used to connect with the "docker user"
docker_user_password: training
clusternumber: 100
image:

View File

@@ -21,11 +21,8 @@ paper_margin: 0.2in
engine_version: stable
# These correspond to the version numbers visible on their respective GitHub release pages
compose_version: 1.24.1
compose_version: 1.21.1
machine_version: 0.14.0
# Password used to connect with the "docker user"
docker_user_password: training
clusternumber: 200
image:

View File

@@ -21,10 +21,8 @@ paper_margin: 0.2in
engine_version: stable
# These correspond to the version numbers visible on their respective GitHub release pages
compose_version: 1.24.1
compose_version: 1.21.1
machine_version: 0.14.0
# Password used to connect with the "docker user"
docker_user_password: training
image:

View File

@@ -23,7 +23,7 @@ paper_margin: 0.2in
engine_version: test
# These correspond to the version numbers visible on their respective GitHub release pages
compose_version: 1.24.1
compose_version: 1.18.0
machine_version: 0.13.0
# Password used to connect with the "docker user"

View File

@@ -23,7 +23,7 @@ paper_margin: 0.2in
engine_version: stable
# These correspond to the version numbers visible on their respective GitHub release pages
compose_version: 1.24.1
compose_version: 1.22.0
machine_version: 0.15.0
# Password used to connect with the "docker user"

View File

@@ -21,8 +21,9 @@ paper_margin: 0.2in
engine_version: stable
# These correspond to the version numbers visible on their respective GitHub release pages
compose_version: 1.24.1
compose_version: 1.21.1
machine_version: 0.14.0
# Password used to connect with the "docker user"
docker_user_password: training

View File

@@ -23,7 +23,7 @@ paper_margin: 0.2in
engine_version: stable
# These correspond to the version numbers visible on their respective GitHub release pages
compose_version: 1.24.1
compose_version: 1.21.1
machine_version: 0.14.0
# Password used to connect with the "docker user"

View File

@@ -23,7 +23,7 @@ paper_margin: 0.2in
engine_version: stable
# These correspond to the version numbers visible on their respective GitHub release pages
compose_version: 1.24.1
compose_version: 1.22.0
machine_version: 0.15.0
# Password used to connect with the "docker user"

View File

@@ -30,9 +30,9 @@ TAG=$PREFIX-$SETTINGS
--settings settings/$SETTINGS.yaml \
--count $((3*$STUDENTS))
./workshopctl disableaddrchecks $TAG
./workshopctl deploy $TAG
./workshopctl kubebins $TAG
./workshopctl disableaddrchecks $TAG
./workshopctl cards $TAG
SETTINGS=admin-kuberouter
@@ -43,15 +43,11 @@ TAG=$PREFIX-$SETTINGS
--settings settings/$SETTINGS.yaml \
--count $((3*$STUDENTS))
./workshopctl disableaddrchecks $TAG
./workshopctl deploy $TAG
./workshopctl kubebins $TAG
./workshopctl disableaddrchecks $TAG
./workshopctl cards $TAG
#INFRA=infra/aws-us-west-1
export AWS_INSTANCE_TYPE=t3a.medium
SETTINGS=admin-test
TAG=$PREFIX-$SETTINGS
./workshopctl start \
@@ -61,6 +57,5 @@ TAG=$PREFIX-$SETTINGS
--count $((3*$STUDENTS))
./workshopctl deploy $TAG
./workshopctl kube $TAG 1.14.6
./workshopctl kube $TAG 1.13.5
./workshopctl cards $TAG

View File

@@ -1,23 +1,12 @@
{#
The variables below can be customized here directly, or in your
settings.yaml file. Any variable in settings.yaml will be exposed
in here as well.
#}
{# Feel free to customize or override anything in there! #}
{%- set url = url
| default("http://FIXME.container.training/") -%}
{%- set pagesize = pagesize
| default(9) -%}
{%- set lang = lang
| default("en") -%}
{%- set event = event
| default("training session") -%}
{%- set backside = backside
| default(False) -%}
{%- set image = image
| default("kube") -%}
{%- set clusternumber = clusternumber
| default(None) -%}
{%- set url = "http://FIXME.container.training/" -%}
{%- set pagesize = 9 -%}
{%- set lang = "en" -%}
{%- set event = "training session" -%}
{%- set backside = False -%}
{%- set image = "kube" -%}
{%- set clusternumber = 100 -%}
{%- set image_src = {
"docker": "https://s3-us-west-2.amazonaws.com/www.breadware.com/integrations/docker.png",
@@ -172,9 +161,7 @@ img.kube {
<div>
<p>{{ intro }}</p>
<p>
{% if image_src %}
<img src="{{ image_src }}" />
{% endif %}
<table>
{% if clusternumber != None %}
<tr><td>cluster:</td></tr>
@@ -200,10 +187,8 @@ img.kube {
</p>
<p>
{% if url %}
{{ slides_are_at }}
<center>{{ url }}</center>
{% endif %}
</p>
</div>
{% if loop.index%pagesize==0 or loop.last %}

View File

@@ -1,4 +0,0 @@
This directory will contain symlinks to HTML and PDF files for the cards
with the IP address, login, and password for the training environments.
The file "index.html" is empty on purpose: it prevents listing the files.

View File

@@ -1,7 +1,5 @@
# 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!
# 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
#/ /kube-twodays.yml.html 200
/ /sfsf.yml.html 200!

View File

@@ -76,78 +76,6 @@ CMD ["python", "app.py"]
---
## Be careful with `chown`, `chmod`, `mv`
* Layers cannot store efficiently changes in permissions or ownership.
* Layers cannot represent efficiently when a file is moved either.
* As a result, operations like `chown`, `chown`, `mv` can be expensive.
* For instance, in the Dockerfile snippet below, each `RUN` line
creates a layer with an entire copy of `some-file`.
```dockerfile
COPY some-file .
RUN chown www-data:www-data some-file
RUN chmod 644 some-file
RUN mv some-file /var/www
```
* How can we avoid that?
---
## Put files on the right place
* Instead of using `mv`, directly put files at the right place.
* When extracting archives (tar, zip...), merge operations in a single layer.
Example:
```dockerfile
...
RUN wget http://.../foo.tar.gz \
&& tar -zxf foo.tar.gz \
&& mv foo/fooctl /usr/local/bin \
&& rm -rf foo
...
```
---
## Use `COPY --chown`
* The Dockerfile instruction `COPY` can take a `--chown` parameter.
Examples:
```dockerfile
...
COPY --chown=1000 some-file .
COPY --chown=1000:1000 some-file .
COPY --chown=www-data:www-data some-file .
```
* The `--chown` flag can specify a user, or a user:group pair.
* The user and group can be specified as names or numbers.
* When using names, the names must exist in `/etc/passwd` or `/etc/group`.
*(In the container, not on the host!)*
---
## Set correct permissions locally
* Instead of using `chmod`, set the right file permissions locally.
* When files are copied with `COPY`, permissions are preserved.
---
## Embedding unit tests in the build process
```dockerfile

View File

@@ -1,11 +1,3 @@
- date: [2019-11-04, 2019-11-05]
country: de
city: Berlin
event: Velocity
speaker: jpetazzo
title: Deploying and scaling applications with Kubernetes
attend: https://conferences.oreilly.com/velocity/vl-eu/public/schedule/detail/79109
- date: 2019-11-13
country: fr
city: Marseille
@@ -15,38 +7,6 @@
lang: fr
attend: http://2019.devops-dday.com/Workshop.html
- date: 2019-10-30
country: us
city: Portland, OR
event: LISA
speaker: jpetazzo
title: Deep Dive into Kubernetes Internals for Builders and Operators
attend: https://www.usenix.org/conference/lisa19/presentation/petazzoni-tutorial
- date: [2019-10-22, 2019-10-24]
country: us
city: Charlotte, NC
event: Ardan Labs
speaker: jpetazzo
title: Kubernetes Training
attend: https://www.eventbrite.com/e/containers-docker-and-kubernetes-training-for-devs-and-ops-charlotte-nc-november-2019-tickets-73296659281
- date: 2019-10-22
country: us
city: Charlotte, NC
event: Ardan Labs
speaker: jpetazzo
title: Docker & Containers Training
attend: https://www.eventbrite.com/e/containers-docker-and-kubernetes-training-for-devs-and-ops-charlotte-nc-november-2019-tickets-73296659281
- date: 2019-10-22
country: de
city: Berlin
event: GOTO
speaker: bretfisher
title: Kubernetes or Swarm? Build Both, Deploy Apps, Learn The Differences
attend: https://gotober.com/2019/workshops/194
- date: [2019-09-24, 2019-09-25]
country: fr
city: Paris
@@ -55,43 +15,6 @@
title: Déployer ses applications avec Kubernetes (in French)
lang: fr
attend: https://enix.io/fr/services/formation/deployer-ses-applications-avec-kubernetes/
slides: https://kube-2019-09.container.training/
- date: 2019-08-27
country: tr
city: Izmir
event: HacknBreak
speaker: gurayyildirim
title: Deploying and scaling applications with Kubernetes (in Turkish)
lang: tr
attend: https://hacknbreak.com
- date: 2019-08-26
country: tr
city: Izmir
event: HacknBreak
speaker: gurayyildirim
title: Container Orchestration with Docker and Swarm (in Turkish)
lang: tr
attend: https://hacknbreak.com
- date: 2019-08-25
country: tr
city: Izmir
event: HackBreak
speaker: gurayyildirim
title: Introduction to Docker and Containers (in Turkish)
lang: tr
attend: https://hacknbreak.com
- date: 2019-07-16
country: us
city: Portland, OR
event: OSCON
speaker: bridgetkromhout
title: "Kubernetes 201: Production tooling"
attend: https://conferences.oreilly.com/oscon/oscon-or/public/schedule/detail/76390
slides: https://oscon2019.container.training
- date: 2019-06-17
country: ca

View File

@@ -167,11 +167,13 @@ What does that mean?
## Let's experiment a bit!
- For the exercises in this section, connect to the first node of the `test` cluster
- For this section, we will use a cluster with 4 nodes
(named node1, node2, node3, node4)
.exercise[
- SSH to the first node of the test cluster
- SSH to the first node of the cluster
- Check that the cluster is operational:
```bash

View File

@@ -18,7 +18,7 @@
(it gives us replication primitives)
- Kubernetes helps us clone / replicate environments
- Kubernetes helps us to clone/replicate environments
(all resources can be described with manifests)

View File

@@ -10,8 +10,6 @@
- Components can be upgraded one at a time without problems
<!-- ##VERSION## -->
---
## Checking what we're running
@@ -168,7 +166,7 @@
- Upgrade kubelet:
```bash
sudo apt install kubelet=1.15.3-00
apt install kubelet=1.14.2-00
```
]
@@ -228,7 +226,7 @@
sudo vim /etc/kubernetes/manifests/kube-apiserver.yaml
```
- Look for the `image:` line, and update it to e.g. `v1.15.0`
- Look for the `image:` line, and update it to e.g. `v1.14.0`
]
@@ -262,52 +260,14 @@
sudo kubeadm upgrade plan
```
]
(Note: kubeadm is confused by our manual upgrade of the API server.
<br/>It thinks the cluster is running 1.14.0!)
Note 1: kubeadm thinks that our cluster is running 1.15.0.
<br/>It is confused by our manual upgrade of the API server!
Note 2: kubeadm itself is still version 1.14.6.
<br/>It doesn't know how to upgrade do 1.15.X.
---
## Upgrading kubeadm
- First things first: we need to upgrade kubeadm
.exercise[
- Upgrade kubeadm:
```
sudo apt install kubeadm
```
- Check what kubeadm tells us:
```
sudo kubeadm upgrade plan
```
]
Note: kubeadm still thinks that our cluster is running 1.15.0.
<br/>But at least it knows about version 1.15.X now.
---
## Upgrading the cluster with kubeadm
- Ideally, we should revert our `image:` change
(so that kubeadm executes the right migration steps)
- Or we can try the upgrade anyway
.exercise[
<!-- ##VERSION## -->
- Perform the upgrade:
```bash
sudo kubeadm upgrade apply v1.15.3
sudo kubeadm upgrade apply v1.14.2
```
]
@@ -327,8 +287,8 @@ Note: kubeadm still thinks that our cluster is running 1.15.0.
- Download the configuration on each node, and upgrade kubelet:
```bash
for N in 1 2 3; do
ssh test$N sudo kubeadm upgrade node config --kubelet-version v1.15.3
ssh test$N sudo apt install kubelet=1.15.3-00
ssh test$N sudo kubeadm upgrade node config --kubelet-version v1.14.2
ssh test$N sudo apt install kubelet=1.14.2-00
done
```
]
@@ -337,7 +297,7 @@ Note: kubeadm still thinks that our cluster is running 1.15.0.
## Checking what we've done
- All our nodes should now be updated to version 1.15.3
- All our nodes should now be updated to version 1.14.2
.exercise[
@@ -347,19 +307,3 @@ Note: kubeadm still thinks that our cluster is running 1.15.0.
```
]
---
class: extra-details
## Skipping versions
- This example worked because we went from 1.14 to 1.15
- If you are upgrading from e.g. 1.13, you will generally have to go through 1.14 first
- This means upgrading kubeadm to 1.14.X, then using it to upgrade the cluster
- Then upgrading kubeadm to 1.15.X, etc.
- **Make sure to read the release notes before upgrading!**

View File

@@ -66,8 +66,6 @@ Look in each plugin's directory for its documentation.
---
class: extra-details
## Conf vs conflist
- There are two slightly different configuration formats

View File

@@ -4,29 +4,15 @@
- We want one (and exactly one) instance of `rng` per node
- We *do not want* two instances of `rng` on the same node
- What if we just scale up `deploy/rng` to the number of nodes?
- We will do that with a *daemon set*
- nothing guarantees that the `rng` containers will be distributed evenly
---
- if we add nodes later, they will not automatically run a copy of `rng`
## Why not a deployment?
- if we remove (or reboot) a node, one `rng` container will restart elsewhere
- Can't we just do `kubectl scale deployment rng --replicas=...`?
--
- Nothing guarantees that the `rng` containers will be distributed evenly
- If we add nodes later, they will not automatically run a copy of `rng`
- If we remove (or reboot) a node, one `rng` container will restart elsewhere
(and we will end up with two instances `rng` on the same node)
- By contrast, a daemon set will start one pod per node and keep it that way
(as nodes are added or removed)
- Instead of a `deployment`, we will use a `daemonset`
---
@@ -52,7 +38,7 @@
<!-- ##VERSION## -->
- Unfortunately, as of Kubernetes 1.15, the CLI cannot create daemon sets
- Unfortunately, as of Kubernetes 1.14, the CLI cannot create daemon sets
--

View File

@@ -175,7 +175,7 @@ Success!
]
We should get `No resources found.` and the `kubernetes` service, respectively.
So far, so good.
Note: the API server automatically created the `kubernetes` service entry.
@@ -225,7 +225,7 @@ Success?
]
Our Deployment is in bad shape:
Our Deployment is in a bad shape:
```
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/web 0/1 0 0 2m26s

View File

@@ -87,7 +87,7 @@
- Clone the Flux repository:
```
git clone https://github.com/fluxcd/flux
git clone https://github.com/weaveworks/flux
```
- Edit `deploy/flux-deployment.yaml`

View File

@@ -304,15 +304,15 @@ It will use the default success threshold (1 successful attempt = alive).
- We need to make sure that the healthcheck doesn't trip when
performance degrades due to external pressure
- Using a readiness check would have fewer effects
- Using a readiness check would have lesser effects
(but it would still be an imperfect solution)
(but it still would be an imperfect solution)
- A possible combination:
- readiness check with a short timeout / low failure threshold
- liveness check with a longer timeout / higher failure threshold
- liveness check with a longer timeout / higher failure treshold
---
@@ -344,7 +344,7 @@ class: extra-details
- When a process is killed, its children are *orphaned* and attached to PID 1
- PID 1 has the responsibility of *reaping* these processes when they terminate
- PID 1 has the responsibility if *reaping* these processes when they terminate
- OK, but how does that affect us?
@@ -378,11 +378,11 @@ class: extra-details
(because worker isn't a backend for a service)
- Liveness may help us restart a broken worker, but how can we check it?
- Liveness may help us to restart a broken worker, but how can we check it?
- Embedding an HTTP server is an option
(but it has a high potential for unwanted side effects and false positives)
(but it has a high potential for unwanted side-effects and false positives)
- Using a "lease" file can be relatively easy:

View File

@@ -415,7 +415,7 @@ This is normal: we haven't provided any ingress rule yet.
Here is a minimal host-based ingress resource:
```yaml
apiVersion: networking.k8s.io/v1beta1
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: cheddar
@@ -523,4 +523,4 @@ spec:
- This should eventually stabilize
(remember that ingresses are currently `apiVersion: networking.k8s.io/v1beta1`)
(remember that ingresses are currently `apiVersion: extensions/v1beta1`)

View File

@@ -1,8 +1,8 @@
# Controlling a Kubernetes cluster remotely
# Controlling the cluster remotely
- `kubectl` can be used either on cluster instances or outside the cluster
- All the operations that we do with `kubectl` can be done remotely
- Here, we are going to use `kubectl` from our local machine
- In this section, we are going to use `kubectl` from our local machine
---
@@ -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.14.2/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.14.2/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.14.2/bin/windows/amd64/kubectl.exe)
- On Linux and macOS, make the binary executable with `chmod +x kubectl`
@@ -67,10 +67,10 @@ Note: if you are following along with a different platform (e.g. Linux on an arc
The output should look like this:
```
Client Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.0",
GitCommit:"e8462b5b5dc2584fdcd18e6bcfe9f1e4d970a529", GitTreeState:"clean",
BuildDate:"2019-06-19T16:40:16Z", GoVersion:"go1.12.5", Compiler:"gc",
Platform:"darwin/amd64"}
Client Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.0",
GitCommit:"641856db18352033a0d96dbc99153fa3b27298e5", GitTreeState:"clean",
BuildDate:"2019-03-25T15:53:57Z", GoVersion:"go1.12.1", Compiler:"gc",
Platform:"linux/amd64"}
```
---
@@ -192,4 +192,4 @@ class: extra-details
]
We can now utilize the cluster exactly as if we're logged into a node, except that it's remote.
We can now utilize the cluster exactly as we did before, except that it's remote.

View File

@@ -62,7 +62,7 @@ Exactly what we need!
- The following commands will install Stern on a Linux Intel 64 bit machine:
```bash
sudo curl -L -o /usr/local/bin/stern \
https://github.com/wercker/stern/releases/download/1.11.0/stern_linux_amd64
https://github.com/wercker/stern/releases/download/1.10.0/stern_linux_amd64
sudo chmod +x /usr/local/bin/stern
```

View File

@@ -1,8 +1,8 @@
# Checking pod and node resource usage
- Since Kubernetes 1.8, metrics are collected by the [resource metrics pipeline](https://kubernetes.io/docs/tasks/debug-application-cluster/resource-metrics-pipeline/)
- Since Kubernetes 1.8, metrics are collected by the [core metrics pipeline](https://v1-13.docs.kubernetes.io/docs/tasks/debug-application-cluster/core-metrics-pipeline/)
- The resource metrics pipeline is:
- The core metrics pipeline is:
- optional (Kubernetes can function without it)
@@ -37,7 +37,7 @@ If it shows our nodes and their CPU and memory load, we're good!
(it doesn't need persistence, as it doesn't *store* metrics)
- It has its own repository, [kubernetes-incubator/metrics-server](https://github.com/kubernetes-incubator/metrics-server)
- It has its own repository, [kubernetes-incubator/metrics-server](https://github.com/kubernetes-incubator/metrics-server])
- The repository comes with [YAML files for deployment](https://github.com/kubernetes-incubator/metrics-server/tree/master/deploy/1.8%2B)
@@ -59,7 +59,7 @@ If it shows our nodes and their CPU and memory load, we're good!
- Show resource usage across all containers:
```bash
kubectl top pods --containers --all-namespaces
kuebectl top pods --containers --all-namespaces
```
]

View File

@@ -195,7 +195,7 @@ class: extra-details
## Check our pods
- The pods will be scheduled on the nodes
- The pods will be scheduled to the nodes
- The nodes will pull the `nginx` image, and start the pods
@@ -325,7 +325,7 @@ class: extra-details
- We will add the `--network-plugin` and `--pod-cidr` flags
- We all have a "cluster number" (let's call that `C`) printed on your VM info card
- We all have a "cluster number" (let's call that `C`)
- We will use pod CIDR `10.C.N.0/24` (where `N` is the node number: 1, 2, 3)
@@ -480,23 +480,6 @@ Sometimes it works, sometimes it doesn't. Why?
```bash
kubectl get nodes -o wide
```
---
## Firewalling
- By default, Docker prevents containers from using arbitrary IP addresses
(by setting up iptables rules)
- We need to allow our containers to use our pod CIDR
- For simplicity, we will insert a blanket iptables rule allowing all traffic:
`iptables -I FORWARD -j ACCEPT`
- This has to be done on every node
---
## Setting up routing
@@ -505,8 +488,6 @@ Sometimes it works, sometimes it doesn't. Why?
- Create all the routes on all the nodes
- Insert the iptables rule allowing traffic
- Check that you can ping all the pods from one of the nodes
- Check that you can `curl` the ClusterIP of the Service successfully

View File

@@ -1,379 +0,0 @@
# OpenID Connect
- The Kubernetes API server can perform authentication with OpenID connect
- This requires an *OpenID provider*
(external authorization server using the OAuth 2.0 protocol)
- We can use a third-party provider (e.g. Google) or run our own (e.g. Dex)
- We are going to give an overview of the protocol
- We will show it in action (in a simplified scenario)
---
## Workflow overview
- We want to access our resources (a Kubernetes cluster)
- We authenticate with the OpenID provider
- we can do this directly (e.g. by going to https://accounts.google.com)
- or maybe a kubectl plugin can open a browser page on our behalf
- After authenticating us, the OpenID provider gives us:
- an *id token* (a short-lived signed JSON Web Token, see next slide)
- a *refresh token* (to renew the *id token* when needed)
- We can now issue requests to the Kubernetes API with the *id token*
- The API server will verify that token's content to authenticate us
---
## JSON Web Tokens
- A JSON Web Token (JWT) has three parts:
- a header specifying algorithms and token type
- a payload (indicating who issued the token, for whom, which purposes...)
- a signature generated by the issuer (the issuer = the OpenID provider)
- Anyone can verify a JWT without contacting the issuer
(except to obtain the issuer's public key)
- Pro tip: we can inspect a JWT with https://jwt.io/
---
## How the Kubernetes API uses JWT
- Server side
- enable OIDC authentication
- indicate which issuer (provider) should be allowed
- indicate which audience (or "client id") should be allowed
- optionally, map or prefix user and group names
- Client side
- obtain JWT as described earlier
- pass JWT as authentication token
- renew JWT when needed (using the refresh token)
---
## Demo time!
- We will use [Google Accounts](https://accounts.google.com) as our OpenID provider
- We will use the [Google OAuth Playground](https://developers.google.com/oauthplayground) as the "audience" or "client id"
- We will obtain a JWT through Google Accounts and the OAuth Playground
- We will enable OIDC in the Kubernetes API server
- We will use the JWT to authenticate
.footnote[If you can't or won't use a Google account, you can try to adapt this to another provider.]
---
## Checking the API server logs
- The API server logs will be particularly useful in this section
(they will indicate e.g. why a specific token is rejected)
- Let's keep an eye on the API server output!
.exercise[
- Tail the logs of the API server:
```bash
kubectl logs kube-apiserver-node1 --follow --namespace=kube-system
```
]
---
## Authenticate with the OpenID provider
- We will use the Google OAuth Playground for convenience
- In a real scenario, we would need our own OAuth client instead of the playground
(even if we were still using Google as the OpenID provider)
.exercise[
- Open the Google OAuth Playground:
```
https://developers.google.com/oauthplayground/
```
- Enter our own custom scope in the text field:
```
https://www.googleapis.com/auth/userinfo.email
```
- Click on "Authorize APIs" and allow the playground to access our email address
]
---
## Obtain our JSON Web Token
- The previous step gave us an "authorization code"
- We will use it to obtain tokens
.exercise[
- Click on "Exchange authorization code for tokens"
]
- The JWT is the very long `id_token` that shows up on the right hand side
(it is a base64-encoded JSON object, and should therefore start with `eyJ`)
---
## Using our JSON Web Token
- We need to create a context (in kubeconfig) for our token
(if we just add the token or use `kubectl --token`, our certificate will still be used)
.exercise[
- Create a new authentication section in kubeconfig:
```bash
kubectl config set-credentials myjwt --token=eyJ...
```
- Try to use it:
```bash
kubectl --user=myjwt get nodes
```
]
We should get an `Unauthorized` response, since we haven't enabled OpenID Connect in the API server yet. We should also see `invalid bearer token` in the API server log output.
---
## Enabling OpenID Connect
- We need to add a few flags to the API server configuration
- These two are mandatory:
`--oidc-issuer-url` → URL of the OpenID provider
`--oidc-client-id` → app requesting the authentication
<br/>(in our case, that's the ID for the Google OAuth Playground)
- This one is optional:
`--oidc-username-claim` → which field should be used as user name
<br/>(we will use the user's email address instead of an opaque ID)
- See the [API server documentation](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#configuring-the-api-server
) for more details about all available flags
---
## Updating the API server configuration
- The instructions below will work for clusters deployed with kubeadm
(or where the control plane is deployed in static pods)
- If your cluster is deployed differently, you will need to adapt them
.exercise[
- Edit `/etc/kubernetes/manifests/kube-apiserver.yaml`
- Add the following lines to the list of command-line flags:
```yaml
- --oidc-issuer-url=https://accounts.google.com
- --oidc-client-id=407408718192.apps.googleusercontent.com
- --oidc-username-claim=email
```
]
---
## Restarting the API server
- The kubelet monitors the files in `/etc/kubernetes/manifests`
- When we save the pod manifest, kubelet will restart the corresponding pod
(using the updated command line flags)
.exercise[
- After making the changes described on the previous slide, save the file
- Issue a simple command (like `kubectl version`) until the API server is back up
(it might take between a few seconds and one minute for the API server to restart)
- Restart the `kubectl logs` command to view the logs of the API server
]
---
## Using our JSON Web Token
- Now that the API server is set up to recognize our token, try again!
.exercise[
- Try an API command with our token:
```bash
kubectl --user=myjwt get nodes
kubectl --user=myjwt get pods
```
]
We should see a message like:
```
Error from server (Forbidden): nodes is forbidden: User "jean.doe@gmail.com"
cannot list resource "nodes" in API group "" at the cluster scope
```
→ We were successfully *authenticated*, but not *authorized*.
---
## Authorizing our user
- As an extra step, let's grant read access to our user
- We will use the pre-defined ClusterRole `view`
.exercise[
- Create a ClusterRoleBinding allowing us to view resources:
```bash
kubectl create clusterrolebinding i-can-view \
--user=`jean.doe@gmail.com` --clusterrole=view
```
(make sure to put *your* Google email address there)
- Confirm that we can now list pods with our token:
```bash
kubectl --user=myjwt get pods
```
]
---
## From demo to production
.warning[This was a very simplified demo! In a real deployment...]
- We wouldn't use the Google OAuth Playground
- We *probably* wouldn't even use Google at all
(it doesn't seem to provide a way to include groups!)
- Some popular alternatives:
- [Dex](https://github.com/dexidp/dex),
[Keycloak](https://www.keycloak.org/)
(self-hosted)
- [Okta](https://developer.okta.com/docs/how-to/creating-token-with-groups-claim/#step-five-decode-the-jwt-to-verify)
(SaaS)
- We would use a helper (like the [kubelogin](https://github.com/int128/kubelogin) plugin) to automatically obtain tokens
---
class: extra-details
## Service Account tokens
- The tokens used by Service Accounts are JWT tokens as well
- They are signed and verified using a special service account key pair
.exercise[
- Extract the token of a service account in the current namespace:
```bash
kubectl get secrets -o jsonpath={..token} | base64 -d
```
- Copy-paste the token to a verification service like https://jwt.io
- Notice that it says "Invalid Signature"
]
---
class: extra-details
## Verifying Service Account tokens
- JSON Web Tokens embed the URL of the "issuer" (=OpenID provider)
- The issuer provides its public key through a well-known discovery endpoint
(similar to https://accounts.google.com/.well-known/openid-configuration)
- There is no such endpoint for the Service Account key pair
- But we can provide the public key ourselves for verification
---
class: extra-details
## Verifying a Service Account token
- On clusters provisioned with kubeadm, the Service Account key pair is:
`/etc/kubernetes/pki/sa.key` (used by the controller manager to generate tokens)
`/etc/kubernetes/pki/sa.pub` (used by the API server to validate the same tokens)
.exercise[
- Display the public key used to sign Service Account tokens:
```bash
sudo cat /etc/kubernetes/pki/sa.pub
```
- Copy-paste the key in the "verify signature" area on https://jwt.io
- It should now say "Signature Verified"
]

View File

@@ -32,7 +32,7 @@
- must be able to anticipate all the events that might happen
- design will be better only to the extent of what we anticipated
- design will be better only to the extend of what we anticipated
- hard to anticipate if we don't have production experience
@@ -86,7 +86,7 @@ class: extra-details
## What can we store via the Kubernetes API?
- The API server stores most Kubernetes resources in etcd
- The API server stores most Kubernetes resources into etcd
- Etcd is designed for reliability, not for performance
@@ -187,8 +187,6 @@ class: extra-details
[Intro talk](https://www.youtube.com/watch?v=8k_ayO1VRXE)
|
[Deep dive talk](https://www.youtube.com/watch?v=fu7ecA2rXmc)
|
[Simple example](https://medium.com/faun/writing-your-first-kubernetes-operator-8f3df4453234)
- Zalando Kubernetes Operator Pythonic Framework (KOPF)

View File

@@ -302,7 +302,7 @@ Now, the StorageClass should have `(default)` next to its name.
- Retrieve the NodePort that was allocated:
```bash
kubectl get svc cerebro-es
kubectl get svc cerebreo-es
```
- Connect to that port with a browser
@@ -386,6 +386,4 @@ We should see at least one index being created in cerebro.
- What if we want different images or parameters for the different nodes?
*Operators can be very powerful.
<br/>
But we need to know exactly the scenarios that they can handle.*
*Operators can be very powerful, iff we know exactly the scenarios that they can handle.*

View File

@@ -1,4 +1,4 @@
# Highly available Persistent Volumes
# Highly available Persistent Volumes (extra material)
- How can we achieve true durability?

View File

@@ -1,169 +0,0 @@
# Recording deployment actions
- Some commands that modify a Deployment accept an optional `--record` flag
(Example: `kubectl set image deployment worker worker=alpine --record`)
- That flag will store the command line in the Deployment
(Technically, using the annotation `kubernetes.io/change-cause`)
- It gets copied to the corresponding ReplicaSet
(Allowing to keep track of which command created or promoted this ReplicaSet)
- We can view this information with `kubectl rollout history`
---
## Using `--record`
- Let's make a couple of changes to a Deployment and record them
.exercise[
- Roll back `worker` to image version 0.1:
```bash
kubectl set image deployment worker worker=dockercoins/worker:v0.1 --record
```
- Promote it to version 0.2 again:
```bash
kubectl set image deployment worker worker=dockercoins/worker:v0.2 --record
```
- View the change history:
```bash
kubectl rollout history deployment worker
```
]
---
## Pitfall #1: forgetting `--record`
- What happens if we don't specify `--record`?
.exercise[
- Promote `worker` to image version 0.3:
```bash
kubectl set image deployment worker worker=dockercoins/worker:v0.3
```
- View the change history:
```bash
kubectl rollout history deployment worker
```
]
--
It recorded version 0.2 instead of 0.3! Why?
---
## How `--record` really works
- `kubectl` adds the annotation `kubernetes.io/change-cause` to the Deployment
- The Deployment controller copies that annotation to the ReplicaSet
- `kubectl rollout history` shows the ReplicaSets' annotations
- If we don't specify `--record`, the annotation is not updated
- The previous value of that annotation is copied to the new ReplicaSet
- In that case, the ReplicaSet annotation does not reflect reality!
---
## Pitfall #2: recording `scale` commands
- What happens if we use `kubectl scale --record`?
.exercise[
- Check the current history:
```bash
kubectl rollout history deployment worker
```
- Scale the deployment:
```bash
kubectl scale deployment worker --replicas=3 --record
```
- Check the change history again:
```bash
kubectl rollout history deployment worker
```
]
--
The last entry in the history was overwritten by the `scale` command! Why?
---
## Actions that don't create a new ReplicaSet
- The `scale` command updates the Deployment definition
- But it doesn't create a new ReplicaSet
- Using the `--record` flag sets the annotation like before
- The annotation gets copied to the existing ReplicaSet
- This overwrites the previous annotation that was there
- In that case, we lose the previous change cause!
---
## Updating the annotation directly
- Let's see what happens if we set the annotation manually
.exercise[
- Annotate the Deployment:
```bash
kubectl annotate deployment worker kubernetes.io/change-cause="Just for fun"
```
- Check that our annotation shows up in the change history:
```bash
kubectl rollout history deployment worker
```
]
--
Our annotation shows up (and overwrote whatever was there before).
---
## Using change cause
- It sounds like a good idea to use `--record`, but:
*"Incorrect documentation is often worse than no documentation."*
<br/>
(Bertrand Meyer)
- If we use `--record` once, we need to either:
- use it every single time after that
- or clear the Deployment annotation after using `--record`
<br/>
(subsequent changes will show up with a `<none>` change cause)
- A safer way is to set it through our tooling

View File

@@ -404,7 +404,7 @@ These quotas will apply to the namespace where the ResourceQuota is created.
- Example:
```bash
kubectl create quota my-resource-quota --hard=pods=300,limits.memory=300Gi
kubectl create quota sparta --hard=pods=300,limits.memory=300Gi
```
- With both YAML and CLI form, the values are always under the `hard` section

View File

@@ -265,8 +265,6 @@ Note the `3xxxx` port.
---
class: extra-details
## Changing rollout parameters
- We want to:
@@ -296,8 +294,6 @@ spec:
---
class: extra-details
## Applying changes through a YAML patch
- We could use `kubectl edit deployment worker`

View File

@@ -18,7 +18,7 @@ with a cloud provider
---
## EKS (the old way)
## EKS (the hard way)
- [Read the doc](https://docs.aws.amazon.com/eks/latest/userguide/getting-started-console.html)
@@ -36,7 +36,7 @@ with a cloud provider
---
## EKS (the new way)
## EKS (the easy way)
- Install `eksctl`
@@ -144,7 +144,7 @@ with a cloud provider
az login
```
- Select a [region](https://azure.microsoft.com/en-us/global-infrastructure/services/?products=kubernetes-service&regions=all
- Select a [region](https://azure.microsoft.com/en-us/global-infrastructure/services/?products=kubernetes-service\&regions=all
)
- Create a "resource group":
@@ -168,7 +168,7 @@ 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
- The cluster has a lot of goodies pre-installed
---
@@ -224,7 +224,7 @@ with a cloud provider
kubectl config use-context do-xxx1-my-do-cluster
```
- The cluster comes with some components (like Cilium) but no metrics server
- The cluster comes with some goodies (like Cilium) but no metrics server
---

View File

@@ -80,8 +80,6 @@
- Docker Enterprise Edition
- [AKS Engine](https://github.com/Azure/aks-engine)
- Pivotal Container Service (PKS)
- Tectonic by CoreOS

View File

@@ -345,7 +345,7 @@ spec:
we figure out the minimal command-line to run our Consul cluster.*
```
consul agent -data-dir=/consul/data -client=0.0.0.0 -server -ui \
consul agent -data=dir=/consul/data -client=0.0.0.0 -server -ui \
-bootstrap-expect=3 \
-retry-join=`X.X.X.X` \
-retry-join=`Y.Y.Y.Y`

View File

@@ -224,7 +224,7 @@ In the manifest, the pod was named `hello`.
```yaml
apiVersion: v1
kind: Pod
Kind: Pod
metadata:
name: hello
namespace: default

View File

@@ -1,8 +1,8 @@
## Versions installed
- Kubernetes 1.15.3
- Docker Engine 19.03.1
- Docker Compose 1.24.1
- Kubernetes 1.14.2
- Docker Engine 18.09.6
- Docker Compose 1.21.1
<!-- ##VERSION## -->
@@ -23,7 +23,7 @@ class: extra-details
## Kubernetes and Docker compatibility
- Kubernetes 1.15 validates Docker Engine versions [up to 18.09](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.15.md#dependencies)
- Kubernetes 1.14 validates Docker Engine versions [up to 18.09](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.14.md#external-dependencies)
<br/>
(the latest version when Kubernetes 1.14 was released)

View File

@@ -1,92 +0,0 @@
title: |
D&eacute;ployer ses applications
avec Kubernetes
#chat: "[Slack](https://dockercommunity.slack.com/messages/C7GKACWDV)"
chat: "[Gitter](https://gitter.im/enix/formation-kubernetes-20190924)"
#chat: "In person!"
gitrepo: github.com/jpetazzo/container.training
slides: http://kube-2019-09.container.training/
exclude:
- self-paced
chapters:
- shared/title.md
- logistics.md
- k8s/intro.md
- shared/about-slides.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/kubectlrun.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/kubectlproxy.md
- k8s/localkubeconfig.md
- k8s/accessinternal.md
- k8s/setup-k8s.md
- k8s/dashboard.md
#- k8s/kubectlscale.md
- k8s/scalingdockercoins.md
- shared/hastyconclusions.md
- k8s/daemonset.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.md
- k8s/create-chart.md
-
- k8s/netpol.md
- k8s/authn-authz.md
#- k8s/csr-api.md
#- k8s/openid-connect.md
#- k8s/podsecuritypolicy.md
-
- k8s/volumes.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/links.md
- shared/thankyou.md

View File

@@ -1,10 +1,16 @@
## Intros
- Hello! I'm .emoji[🐳] Jérôme ([@jpetazzo](https://twitter.com/jpetazzo), Enix SAS)
- Hello! We are:
- The training will run from 9:00 to 17:30
- .emoji[👷🏻‍♀️] AJ ([@s0ulshake](https://twitter.com/s0ulshake), Tiny Shell Script LLC)
- There will be a lunch break (and coffee breaks!)
- .emoji[🐳] Jérôme ([@jpetazzo](https://twitter.com/jpetazzo), Ardan Labs LLC)
- The training will run from 9am to 5pm
- There will be a lunch break
(And coffee breaks!)
- Feel free to interrupt for questions at any time

61
slides/sfsf.yml Normal file
View File

@@ -0,0 +1,61 @@
title: |
Kubernetes
Advanced
Training
#chat: "[Slack](https://dockercommunity.slack.com/messages/C7GKACWDV)"
chat: "[Gitter](https://gitter.im/jpetazzo/training-20190613-sanfrancisco)"
#chat: "In person!"
gitrepo: github.com/jpetazzo/container.training
slides: http://sfsf-2019-06.container.training/
exclude:
- self-paced
chapters:
- shared/title.md
- logistics.md
- k8s/intro.md
- shared/about-slides.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/apilb.md
- - k8s/kubercoins.md
- k8s/logs-cli.md
- k8s/logs-centralized.md
- k8s/healthchecks.md
- k8s/healthchecks-more.md
- - k8s/volumes.md
- k8s/configuration.md
- k8s/statefulsets.md
- k8s/local-persistent-volumes.md
- k8s/portworx.md
# DAY 2
- - k8s/namespaces.md
- k8s/kustomize.md
- k8s/helm.md
- k8s/create-chart.md
- k8s/create-more-charts.md
- - k8s/extending-api.md
- k8s/operators.md
- k8s/operators-design.md
- k8s/owners-and-dependents.md
- - k8s/authn-authz.md
- k8s/control-plane-auth.md
- k8s/prometheus.md
- - k8s/resource-limits.md
- k8s/metrics-server.md
- k8s/cluster-sizing.md
- k8s/horizontal-pod-autoscaler.md
# CONCLUSION
- - k8s/lastwords-admin.md
- k8s/links.md
- shared/thankyou.md

View File

@@ -11,11 +11,5 @@ class: title, in-person
@@TITLE@@<br/></br>
.footnote[
**WiFi sans DNS: CONFERENCE**<br/>
**Password: 123conference**<br/>
<br/>
**WiFi avec DNS (et portail captif): ASTOTEL_WIFI**<br/>
**Password: Astotel75**<br/>
<br/>
**Slides: @@SLIDES@@**
]

View File

@@ -1,29 +0,0 @@
## WebSSH
- The virtual machines are also accessible via WebSSH
- This can be useful if:
- you can't install an SSH client on your machine
- SSH connections are blocked (by firewall or local policy)
- To use WebSSH, connect to the IP address of the remote VM on port 1080
(each machine runs a WebSSH server)
- Then provide the login and password indicated on your card
---
## Good to know
- WebSSH uses WebSocket
- If you're having connections issues, try to disable your HTTP proxy
(many HTTP proxies can't handle WebSocket properly)
- Most keyboard shortcuts should work, except Ctrl-W
(as it is hardwired by the browser to "close this tab")