├── container-revolution-2016 └── demo │ ├── cleanup │ ├── jobs │ ├── lobsters-db-schema-load.yaml │ └── lobsters-db-seed.yaml │ ├── rc │ ├── lobsters.yaml │ └── mysql.yaml │ ├── rolling-update │ └── services │ ├── lobsters.yaml │ └── mysql.yaml ├── devops-networking-forum-2016 └── demo │ ├── README.md │ ├── cleanup │ └── config.json ├── distributed-matters-2015 ├── demo │ ├── cleanup │ └── lobsters │ │ ├── jobs │ │ ├── lobsters-db-schema-load.yaml │ │ └── lobsters-db-seed.yaml │ │ ├── rc │ │ ├── lobsters.yaml │ │ └── mysql.yaml │ │ └── services │ │ ├── lobsters.yaml │ │ └── mysql.yaml └── slides │ └── talk.slide ├── dutch-docker-day-2015 ├── demo │ ├── cleanup │ ├── kubernetes │ │ └── lobsters │ │ │ ├── jobs │ │ │ ├── lobsters-db-schema-load.yaml │ │ │ └── lobsters-db-seed.yaml │ │ │ ├── rc │ │ │ ├── lobsters.yaml │ │ │ └── mysql.yaml │ │ │ ├── rolling-update │ │ │ └── services │ │ │ ├── lobsters.yaml │ │ │ └── mysql.yaml │ └── swarm │ │ ├── docker-compose.yml │ │ ├── scsm-docker-compose.yml │ │ └── state │ │ └── nginx.json └── slides │ └── talk.slide ├── gwo-2016 └── README.md └── kubecon-eu-2016 └── demo ├── .gitignore ├── README.md ├── cleanup ├── configs ├── README.md ├── config.example.js └── ghost.conf ├── deployments ├── ghost-canary.yaml └── ghost.yaml ├── docker ├── ghost-0-7-7 │ ├── Dockerfile │ └── docker-entrypoint.sh └── ghost-0-7-8 │ ├── Dockerfile │ └── docker-entrypoint.sh ├── ghost-screen-shot.png ├── ingress └── ghost.yaml ├── pods ├── config.js └── ghost.yaml ├── services └── ghost.yaml └── tls ├── ca.crt ├── database-ca.crt ├── tls.crt └── tls.key /container-revolution-2016/demo/cleanup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | kubectl delete rc mysql lobsters 4 | kubectl delete svc mysql lobsters 5 | kubectl delete jobs lobsters-db-schema-load lobsters-db-seed 6 | 7 | sleep 15 8 | 9 | gcloud compute disks delete mysql-data 10 | -------------------------------------------------------------------------------- /container-revolution-2016/demo/jobs/lobsters-db-schema-load.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Job 3 | metadata: 4 | name: lobsters-db-schema-load 5 | spec: 6 | selector: 7 | matchLabels: 8 | task: db-schema-load 9 | template: 10 | metadata: 11 | name: lobsters-db-schema-load 12 | labels: 13 | task: db-schema-load 14 | spec: 15 | containers: 16 | - name: lobsters 17 | image: kelseyhightower/lobsters:1.0.0 18 | env: 19 | - name: DATABASE_URL 20 | value: "mysql2://lobster:linux@mysql.default.svc.cluster.local:3306/lobster" 21 | command: 22 | - "/usr/local/bundle/bin/rake" 23 | - "db:schema:load" 24 | restartPolicy: Never 25 | -------------------------------------------------------------------------------- /container-revolution-2016/demo/jobs/lobsters-db-seed.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Job 3 | metadata: 4 | name: lobsters-db-seed 5 | spec: 6 | selector: 7 | matchLabels: 8 | task: db-seed 9 | template: 10 | metadata: 11 | name: lobsters-db-seed 12 | labels: 13 | task: db-seed 14 | spec: 15 | containers: 16 | - name: lobsters 17 | image: kelseyhightower/lobsters:1.0.0 18 | env: 19 | - name: DATABASE_URL 20 | value: "mysql2://lobster:linux@mysql.default.svc.cluster.local:3306/lobster" 21 | command: 22 | - "/usr/local/bundle/bin/rake" 23 | - "db:seed" 24 | restartPolicy: Never 25 | -------------------------------------------------------------------------------- /container-revolution-2016/demo/rc/lobsters.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | labels: 5 | app: lobsters 6 | name: lobsters 7 | spec: 8 | replicas: 1 9 | selector: 10 | app: lobsters 11 | template: 12 | metadata: 13 | labels: 14 | app: lobsters 15 | spec: 16 | containers: 17 | - name: lobsters 18 | image: kelseyhightower/lobsters:1.0.0 19 | env: 20 | - name: DATABASE_URL 21 | value: "mysql2://lobster:linux@mysql.default.svc.cluster.local:3306/lobster" 22 | ports: 23 | - containerPort: 3000 24 | protocol: TCP 25 | -------------------------------------------------------------------------------- /container-revolution-2016/demo/rc/mysql.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | labels: 5 | app: mysql 6 | name: mysql 7 | spec: 8 | replicas: 1 9 | selector: 10 | app: mysql 11 | template: 12 | metadata: 13 | labels: 14 | app: mysql 15 | name: mysql 16 | spec: 17 | containers: 18 | - name: mysql 19 | image: mysql/mysql-server:5.6 20 | env: 21 | - name: MYSQL_ROOT_PASSWORD 22 | value: lobster 23 | - name: MYSQL_PASSWORD 24 | value: linux 25 | - name: MYSQL_USER 26 | value: lobster 27 | - name: MYSQL_DATABASE 28 | value: lobster 29 | ports: 30 | - name: mysql 31 | containerPort: 3306 32 | volumeMounts: 33 | - mountPath: /var/lib/mysql 34 | name: mysql-data 35 | volumes: 36 | - name: "mysql-data" 37 | gcePersistentDisk: 38 | pdName: mysql-data 39 | fsType: ext4 40 | -------------------------------------------------------------------------------- /container-revolution-2016/demo/rolling-update: -------------------------------------------------------------------------------- 1 | kubectl rolling-update --update-period=1s --image=kelseyhightower/lobsters:1.0.1 lobsters 2 | -------------------------------------------------------------------------------- /container-revolution-2016/demo/services/lobsters.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app: lobsters 6 | name: lobsters 7 | spec: 8 | ports: 9 | - port: 3000 10 | protocol: TCP 11 | targetPort: 3000 12 | selector: 13 | app: lobsters 14 | type: LoadBalancer 15 | -------------------------------------------------------------------------------- /container-revolution-2016/demo/services/mysql.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app: mysql 6 | name: mysql 7 | spec: 8 | ports: 9 | - port: 3306 10 | targetPort: 3306 11 | selector: 12 | app: mysql 13 | -------------------------------------------------------------------------------- /devops-networking-forum-2016/demo/README.md: -------------------------------------------------------------------------------- 1 | # Devops Network Forum Demo 2 | 3 | ## Prerequisites 4 | 5 | ### Create Machines 6 | 7 | ``` 8 | gcloud compute instances create machine0 \ 9 | --machine-type "n1-standard-2" \ 10 | --can-ip-forward \ 11 | --image coreos-alpha-983-0-0-v20160311 \ 12 | --image-project coreos-cloud \ 13 | --boot-disk-size "80" \ 14 | --boot-disk-type "pd-ssd" 15 | ``` 16 | 17 | ``` 18 | gcloud compute instances create machine1 \ 19 | --machine-type "n1-standard-2" \ 20 | --can-ip-forward \ 21 | --image coreos-alpha-983-0-0-v20160311 \ 22 | --image-project coreos-cloud \ 23 | --boot-disk-size "80" \ 24 | --boot-disk-type "pd-ssd" 25 | ``` 26 | 27 | ``` 28 | gcloud compute instances create lb0 \ 29 | --machine-type "n1-standard-2" \ 30 | --can-ip-forward \ 31 | --image coreos-alpha-983-0-0-v20160311 \ 32 | --image-project coreos-cloud \ 33 | --boot-disk-size "80" \ 34 | --boot-disk-type "pd-ssd" 35 | ``` 36 | 37 | ### Install runc 38 | 39 | ``` 40 | gcloud compute ssh core@machine0 41 | ``` 42 | 43 | ``` 44 | sudo mkdir -p /opt/bin 45 | sudo curl -o /opt/bin/runc https://storage.googleapis.com/hightowerlabs/runc 46 | sudo chmod +x /opt/bin/runc 47 | ``` 48 | 49 | > Repeat for machine1 50 | 51 | 52 | ## Inspector Demo 53 | 54 | ### Inspector Binary 55 | 56 | ``` 57 | gcloud compute ssh core@machine0 58 | ``` 59 | 60 | ``` 61 | sudo curl -o /opt/bin/inspector https://storage.googleapis.com/hightowerlabs/inspector 62 | sudo chmod +x /opt/bin/inspector 63 | ``` 64 | 65 | ``` 66 | sudo inspector 67 | ``` 68 | 69 | > Visit http://machine0 70 | 71 | ### Inspector Container - Host Networking 72 | 73 | ``` 74 | gcloud compute ssh core@machine0 75 | ``` 76 | 77 | Download OCI config 78 | 79 | ``` 80 | curl -O https://storage.googleapis.com/hightowerlabs/config.json 81 | ``` 82 | 83 | Create inspector container root directory: 84 | 85 | ``` 86 | mkdir -p inspector/rootfs/etc 87 | ``` 88 | 89 | Populate the inspector container root directory: 90 | 91 | ``` 92 | cp /etc/resolv.conf inspector/rootfs/etc/ 93 | cp /etc/hosts inspector/rootfs/etc/ 94 | cp /opt/bin/inspector inspector/rootfs/ 95 | cp config.json inspector/ 96 | ``` 97 | 98 | Start the inspector container: 99 | 100 | ``` 101 | sudo runc start -b inspector inspector 102 | ``` 103 | 104 | > Repeat these steps for machine1 105 | 106 | 107 | ### Network Namespaces in Action 108 | 109 | ``` 110 | gcloud compute ssh core@machine0 111 | ``` 112 | 113 | Create the `containers` bridge: 114 | 115 | ``` 116 | sudo brctl addbr containers 117 | sudo brctl stp containers off 118 | sudo ip link set dev containers up 119 | sudo ip addr add 10.10.0.1/24 dev containers 120 | ``` 121 | 122 | Create the inspector namespace: 123 | 124 | ``` 125 | sudo ip netns add inspector 126 | ``` 127 | 128 | Create a veth0 pair: 129 | 130 | ``` 131 | sudo ip link add veth0 type veth peer name br-veth0 132 | ``` 133 | 134 | Connect one end of the veth pair to the containers bridge: 135 | 136 | ``` 137 | sudo brctl addif containers br-veth0 138 | ``` 139 | 140 | Move one end of the veth0 pair into the inspector network namespace: 141 | 142 | ``` 143 | sudo ip link set veth0 netns inspector 144 | ``` 145 | 146 | Configure the inspector network namespace: 147 | 148 | ``` 149 | sudo ip netns exec inspector bash 150 | ``` 151 | 152 | ``` 153 | ifconfig -a 154 | ip addr add 10.10.0.2/24 dev veth0 155 | ip addr add 127.0.0.1 dev lo 156 | ip link set veth0 up 157 | ip link set lo up 158 | ip route add default via 10.10.0.1 dev veth0 159 | ``` 160 | 161 | ``` 162 | exit 163 | ``` 164 | 165 | 166 | Repeat these steps on machine1 167 | 168 | > Use 10.10.1.1/24 for the container bridge and 10.10.1.2/24 for veth0 169 | 170 | 171 | ### Cross host networking 172 | 173 | #### Terminal 1 174 | 175 | ``` 176 | gcloud compute ssh core@machine0 177 | ``` 178 | 179 | ``` 180 | sudo ip netns exec inspector bash 181 | ``` 182 | 183 | ``` 184 | ping 10.10.1.2 185 | ``` 186 | 187 | #### Terminal 2 188 | 189 | ``` 190 | gcloud compute ssh core@machine1 191 | ``` 192 | 193 | ``` 194 | sudo ip netns exec inspector bash 195 | ``` 196 | 197 | ``` 198 | ping 10.10.0.2 199 | ``` 200 | 201 | #### Create Routes 202 | 203 | ``` 204 | gcloud compute routes create default-route-10-10-0-0-24 \ 205 | --destination-range 10.10.0.0/24 \ 206 | --next-hop-instance machine0 207 | ``` 208 | 209 | ``` 210 | gcloud compute routes create default-route-10-10-1-0-24 \ 211 | --destination-range 10.10.1.0/24 \ 212 | --next-hop-instance machine1 213 | ``` 214 | 215 | 216 | ### Inspector Container - Network Namespace 217 | 218 | ``` 219 | gcloud compute ssh core@machine0 220 | ``` 221 | 222 | Edit `container/config.json` 223 | 224 | ``` 225 | "linux":{ 226 | "namespaces":[ 227 | ... 228 | { 229 | "type":"network", 230 | "path": "/var/run/netns/inspector" 231 | } 232 | ], 233 | ... 234 | }, 235 | ``` 236 | 237 | ``` 238 | sudo runc start -b inspector inspector 239 | ``` 240 | 241 | > Repeat for machine1 242 | 243 | 244 | ## Load Balance with nginx 245 | 246 | ``` 247 | gcloud compute ssh core@lb0 248 | ``` 249 | 250 | ``` 251 | cat < inspector.conf 252 | upstream inspector { 253 | least_conn; 254 | server 10.10.0.2; 255 | server 10.10.1.2; 256 | } 257 | 258 | server { 259 | listen 80; 260 | location / { 261 | proxy_pass http://inspector; 262 | } 263 | } 264 | EOF 265 | ``` 266 | 267 | ``` 268 | sudo mkdir -p /etc/nginx/conf.d 269 | ``` 270 | 271 | ``` 272 | sudo mv inspector.conf /etc/nginx/conf.d/ 273 | ``` 274 | 275 | ``` 276 | sudo docker run -d --net=host \ 277 | -v /etc/nginx/conf.d:/etc/nginx/conf.d \ 278 | nginx 279 | ``` 280 | 281 | 282 | ## Automate it all with Kubernetes 283 | 284 | ``` 285 | kubectl run inspector --image=gcr.io/kuar/inspector:2.0.0 --port=80 286 | ``` 287 | 288 | ``` 289 | kubectl expose rc inspector --type=LoadBalancer 290 | ``` 291 | 292 | ``` 293 | kubectl scale rc inspector --replicas=10 294 | ``` 295 | -------------------------------------------------------------------------------- /devops-networking-forum-2016/demo/cleanup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | gcloud compute routes delete default-route-10-10-0-0-24 4 | gcloud compute routes delete default-route-10-10-1-0-24 5 | 6 | -------------------------------------------------------------------------------- /devops-networking-forum-2016/demo/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "ociVersion":"0.4.0", 3 | "root":{ 4 | "path":"rootfs", 5 | "readonly":true 6 | }, 7 | "platform":{ 8 | "os":"linux", 9 | "arch":"amd64" 10 | }, 11 | "linux":{ 12 | "namespaces":[ 13 | { 14 | "type":"pid" 15 | }, 16 | { 17 | "type":"ipc" 18 | }, 19 | { 20 | "type":"mount" 21 | } 22 | ], 23 | "resources":{} 24 | }, 25 | "mounts":[ 26 | { 27 | "destination":"/proc", 28 | "type":"proc", 29 | "source":"proc" 30 | }, 31 | { 32 | "destination":"/dev", 33 | "type":"tmpfs", 34 | "source":"tmpfs", 35 | "options":[ 36 | "nosuid", 37 | "strictatime", 38 | "mode=755", 39 | "size=65536k" 40 | ] 41 | }, 42 | { 43 | "destination":"/dev/pts", 44 | "type":"devpts", 45 | "source":"devpts", 46 | "options":[ 47 | "nosuid", 48 | "noexec", 49 | "newinstance", 50 | "ptmxmode=0666", 51 | "mode=0620", 52 | "gid=5" 53 | ] 54 | }, 55 | { 56 | "destination":"/dev/shm", 57 | "type":"tmpfs", 58 | "source":"shm", 59 | "options":[ 60 | "nosuid", 61 | "noexec", 62 | "nodev", 63 | "mode=1777", 64 | "size=65536k" 65 | ] 66 | }, 67 | { 68 | "destination":"/dev/mqueue", 69 | "type":"mqueue", 70 | "source":"mqueue", 71 | "options":[ 72 | "nosuid", 73 | "noexec", 74 | "nodev" 75 | ] 76 | }, 77 | { 78 | "destination":"/sys", 79 | "type":"sysfs", 80 | "source":"sysfs", 81 | "options":[ 82 | "nosuid", 83 | "noexec", 84 | "nodev" 85 | ] 86 | }, 87 | { 88 | "destination":"/sys/fs/cgroup", 89 | "type":"cgroup", 90 | "source":"cgroup", 91 | "options":[ 92 | "nosuid", 93 | "noexec", 94 | "nodev", 95 | "relatime", 96 | "ro" 97 | ] 98 | } 99 | ], 100 | "process":{ 101 | "user":{ 102 | "uid":0, 103 | "gid":0 104 | }, 105 | "cwd":"/", 106 | "capabilities":[ 107 | "CAP_AUDIT_WRITE", 108 | "CAP_KILL", 109 | "CAP_NET_BIND_SERVICE" 110 | ], 111 | "args":[ 112 | "/inspector" 113 | ] 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /distributed-matters-2015/demo/cleanup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | kubectl delete rc mysql lobsters 4 | kubectl delete svc mysql lobsters 5 | kubectl delete jobs lobsters-db-schema-load lobsters-db-seed 6 | gcloud compute disks delete mysql-data 7 | -------------------------------------------------------------------------------- /distributed-matters-2015/demo/lobsters/jobs/lobsters-db-schema-load.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Job 3 | metadata: 4 | name: lobsters-db-schema-load 5 | spec: 6 | selector: 7 | matchLabels: 8 | task: db-schema-load 9 | template: 10 | metadata: 11 | name: lobsters-db-schema-load 12 | labels: 13 | task: db-schema-load 14 | spec: 15 | containers: 16 | - name: lobsters 17 | image: kelseyhightower/lobsters:1.0.0 18 | env: 19 | - name: DATABASE_URL 20 | value: "mysql2://lobster:linux@10.31.240.125:3306/lobster" 21 | command: 22 | - "/usr/local/bundle/bin/rake" 23 | - "db:schema:load" 24 | restartPolicy: Never 25 | -------------------------------------------------------------------------------- /distributed-matters-2015/demo/lobsters/jobs/lobsters-db-seed.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Job 3 | metadata: 4 | name: lobsters-db-seed 5 | spec: 6 | selector: 7 | matchLabels: 8 | task: db-seed 9 | template: 10 | metadata: 11 | name: lobsters-db-seed 12 | labels: 13 | task: db-seed 14 | spec: 15 | containers: 16 | - name: lobsters 17 | image: kelseyhightower/lobsters:1.0.0 18 | env: 19 | - name: DATABASE_URL 20 | value: "mysql2://lobster:linux@10.31.240.125:3306/lobster" 21 | command: 22 | - "/usr/local/bundle/bin/rake" 23 | - "db:seed" 24 | restartPolicy: Never 25 | -------------------------------------------------------------------------------- /distributed-matters-2015/demo/lobsters/rc/lobsters.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | labels: 5 | app: lobsters 6 | name: lobsters 7 | spec: 8 | replicas: 1 9 | selector: 10 | app: lobsters 11 | template: 12 | metadata: 13 | labels: 14 | app: lobsters 15 | spec: 16 | containers: 17 | - name: lobsters 18 | image: kelseyhightower/lobsters:1.0.0 19 | env: 20 | - name: DATABASE_URL 21 | value: "mysql2://lobster:linux@10.31.240.125:3306/lobster" 22 | ports: 23 | - containerPort: 3000 24 | protocol: TCP 25 | -------------------------------------------------------------------------------- /distributed-matters-2015/demo/lobsters/rc/mysql.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | labels: 5 | app: mysql 6 | name: mysql 7 | spec: 8 | replicas: 1 9 | selector: 10 | app: mysql 11 | template: 12 | metadata: 13 | labels: 14 | app: mysql 15 | name: mysql 16 | spec: 17 | containers: 18 | - name: mysql 19 | image: mysql/mysql-server:5.6 20 | env: 21 | - name: MYSQL_ROOT_PASSWORD 22 | value: lobster 23 | - name: MYSQL_PASSWORD 24 | value: linux 25 | - name: MYSQL_USER 26 | value: lobster 27 | - name: MYSQL_DATABASE 28 | value: lobster 29 | ports: 30 | - name: mysql 31 | containerPort: 3306 32 | volumeMounts: 33 | - mountPath: /var/lib/mysql 34 | name: mysql-data 35 | volumes: 36 | - name: "mysql-data" 37 | gcePersistentDisk: 38 | pdName: mysql-data 39 | fsType: ext4 40 | -------------------------------------------------------------------------------- /distributed-matters-2015/demo/lobsters/services/lobsters.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app: lobsters 6 | name: lobsters 7 | spec: 8 | ports: 9 | - port: 3000 10 | protocol: TCP 11 | targetPort: 3000 12 | selector: 13 | app: lobsters 14 | type: LoadBalancer 15 | -------------------------------------------------------------------------------- /distributed-matters-2015/demo/lobsters/services/mysql.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app: mysql 6 | name: mysql 7 | spec: 8 | clusterIP: 10.31.240.125 9 | ports: 10 | - port: 3306 11 | targetPort: 3306 12 | selector: 13 | app: mysql 14 | -------------------------------------------------------------------------------- /distributed-matters-2015/slides/talk.slide: -------------------------------------------------------------------------------- 1 | Redefining the cloud one container at a time 2 | Distributed Matters 3 | 4 | Kelsey Hightower 5 | Google Cloud Platform 6 | kelsey.hightower@gmail.com 7 | @kelseyhightower 8 | 9 | * Distributed computing has gone mainstream. 10 | 11 | * Containers abstract away the gory details of application packaging and runtime semantics. 12 | 13 | * Resource utilization is the key to utility computing. Not containers. 14 | 15 | * The datacenter is the computer but rather useless without an API. 16 | 17 | * Network attached storage can decouple applications from machines. 18 | 19 | * Consistent data stores enable reliable communication and coordination. 20 | 21 | * Schedulers enable intelligent deployments and self-healing. 22 | 23 | * What kind of system can we build if we utilize all those things? 24 | -------------------------------------------------------------------------------- /dutch-docker-day-2015/demo/cleanup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | kubectl delete rc mysql lobsters 4 | kubectl delete svc mysql lobsters 5 | kubectl delete jobs lobsters-db-schema-load lobsters-db-seed 6 | 7 | curl https://$(docker-machine ip swarm-master):3476/remove?name=nginx \ 8 | --cacert ~/.docker/machine/certs/ca.pem \ 9 | --cert ~/.docker/machine/certs/cert.pfx \ 10 | --pass swarm 11 | 12 | eval $(docker-machine env swarm-master --swarm) 13 | docker rm -f $(docker ps -f label=swarm.cluster.state=nginx -q) 14 | -------------------------------------------------------------------------------- /dutch-docker-day-2015/demo/kubernetes/lobsters/jobs/lobsters-db-schema-load.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Job 3 | metadata: 4 | name: lobsters-db-schema-load 5 | spec: 6 | selector: 7 | matchLabels: 8 | task: db-schema-load 9 | template: 10 | metadata: 11 | name: lobsters-db-schema-load 12 | labels: 13 | task: db-schema-load 14 | spec: 15 | containers: 16 | - name: lobsters 17 | image: kelseyhightower/lobsters:1.0.0 18 | env: 19 | - name: DATABASE_URL 20 | value: "mysql2://lobster:linux@10.31.240.125:3306/lobster" 21 | command: 22 | - "/usr/local/bundle/bin/rake" 23 | - "db:schema:load" 24 | restartPolicy: Never 25 | -------------------------------------------------------------------------------- /dutch-docker-day-2015/demo/kubernetes/lobsters/jobs/lobsters-db-seed.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Job 3 | metadata: 4 | name: lobsters-db-seed 5 | spec: 6 | selector: 7 | matchLabels: 8 | task: db-seed 9 | template: 10 | metadata: 11 | name: lobsters-db-seed 12 | labels: 13 | task: db-seed 14 | spec: 15 | containers: 16 | - name: lobsters 17 | image: kelseyhightower/lobsters:1.0.0 18 | env: 19 | - name: DATABASE_URL 20 | value: "mysql2://lobster:linux@10.31.240.125:3306/lobster" 21 | command: 22 | - "/usr/local/bundle/bin/rake" 23 | - "db:seed" 24 | restartPolicy: Never 25 | -------------------------------------------------------------------------------- /dutch-docker-day-2015/demo/kubernetes/lobsters/rc/lobsters.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | labels: 5 | app: lobsters 6 | name: lobsters 7 | spec: 8 | replicas: 1 9 | selector: 10 | app: lobsters 11 | template: 12 | metadata: 13 | labels: 14 | app: lobsters 15 | spec: 16 | containers: 17 | - name: lobsters 18 | image: kelseyhightower/lobsters:1.0.0 19 | env: 20 | - name: DATABASE_URL 21 | value: "mysql2://lobster:linux@10.31.240.125:3306/lobster" 22 | ports: 23 | - containerPort: 3000 24 | protocol: TCP 25 | -------------------------------------------------------------------------------- /dutch-docker-day-2015/demo/kubernetes/lobsters/rc/mysql.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | labels: 5 | app: mysql 6 | name: mysql 7 | spec: 8 | replicas: 1 9 | selector: 10 | app: mysql 11 | template: 12 | metadata: 13 | labels: 14 | app: mysql 15 | name: mysql 16 | spec: 17 | containers: 18 | - name: mysql 19 | image: mysql/mysql-server:5.6 20 | env: 21 | - name: MYSQL_ROOT_PASSWORD 22 | value: lobster 23 | - name: MYSQL_PASSWORD 24 | value: linux 25 | - name: MYSQL_USER 26 | value: lobster 27 | - name: MYSQL_DATABASE 28 | value: lobster 29 | ports: 30 | - name: mysql 31 | containerPort: 3306 32 | volumeMounts: 33 | - mountPath: /var/lib/mysql 34 | name: mysql-data 35 | volumes: 36 | - name: "mysql-data" 37 | gcePersistentDisk: 38 | pdName: mysql-data 39 | fsType: ext4 40 | -------------------------------------------------------------------------------- /dutch-docker-day-2015/demo/kubernetes/lobsters/rolling-update: -------------------------------------------------------------------------------- 1 | kubectl rolling-update --update-period=1s --image=kelseyhightower/lobsters:1.0.1 lobsters 2 | -------------------------------------------------------------------------------- /dutch-docker-day-2015/demo/kubernetes/lobsters/services/lobsters.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app: lobsters 6 | name: lobsters 7 | spec: 8 | ports: 9 | - port: 3000 10 | protocol: TCP 11 | targetPort: 3000 12 | selector: 13 | app: lobsters 14 | type: NodePort 15 | -------------------------------------------------------------------------------- /dutch-docker-day-2015/demo/kubernetes/lobsters/services/mysql.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app: mysql 6 | name: mysql 7 | spec: 8 | clusterIP: 10.31.240.125 9 | ports: 10 | - port: 3306 11 | targetPort: 3306 12 | selector: 13 | app: mysql 14 | -------------------------------------------------------------------------------- /dutch-docker-day-2015/demo/swarm/docker-compose.yml: -------------------------------------------------------------------------------- 1 | nginx: 2 | image: nginx:1.9.6 3 | -------------------------------------------------------------------------------- /dutch-docker-day-2015/demo/swarm/scsm-docker-compose.yml: -------------------------------------------------------------------------------- 1 | swarm-cluster-state-manager: 2 | container_name: swarm-cluster-state-manager 3 | image: kelseyhightower/swarm-cluster-state-manager 4 | volumes: 5 | - /etc/docker:/etc/docker 6 | command: | 7 | --addr=0.0.0.0:3476 8 | --swarm-manager="tcp://104.197.39.197:3376" 9 | --tlscacert="/etc/docker/ca.pem" 10 | --tlscert="/etc/docker/server.pem" 11 | --tlskey="/etc/docker/server-key.pem" 12 | ports: 13 | - "3476:3476" 14 | -------------------------------------------------------------------------------- /dutch-docker-day-2015/demo/swarm/state/nginx.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "nginx", 3 | "Image": "nginx:1.9.6", 4 | "Count": 5 5 | } 6 | -------------------------------------------------------------------------------- /dutch-docker-day-2015/slides/talk.slide: -------------------------------------------------------------------------------- 1 | Containers, Swarm, and Kubernetes 2 | 3 | Kelsey Hightower 4 | Google Cloud Platform 5 | kelsey.hightower@gmail.com 6 | @kelseyhightower 7 | 8 | * Containers are fancy application packages and a way to describe runtime details. 9 | 10 | * Compute resource utilization is the key to utility computing. Not containers. 11 | 12 | * Automation (task) and orchestration (process) are not the same things. 13 | 14 | * Docker Swarm allows you to treat a pool of Docker hosts like a single machine. 15 | 16 | * Kubernetes handles scheduling onto a compute cluster and actively manages workloads to match desired state. 17 | -------------------------------------------------------------------------------- /gwo-2016/README.md: -------------------------------------------------------------------------------- 1 | # GWO Demo 2 | 3 | ## Single System Demo 4 | 5 | ``` 6 | gcloud compute ssh core@machine0 7 | ``` 8 | 9 | ``` 10 | top 11 | ``` 12 | 13 | ``` 14 | ps -ax -o pid,psr,cmd 15 | ``` 16 | 17 | ``` 18 | docker run -d -P nginx:1.7.9 19 | ``` 20 | 21 | ``` 22 | gcloud compute ssh machine1 23 | ``` 24 | 25 | ``` 26 | docker run -d -P nginx:1.7.9 27 | ``` 28 | 29 | ### Manging Resources 30 | 31 | ``` 32 | gcloud compute ssh machine1 33 | ``` 34 | 35 | ``` 36 | docker run -d -P nginx:1.7.9 37 | ``` 38 | 39 | ### Upgrading Applications 40 | 41 | ``` 42 | docker stop 43 | docker rm 44 | docker run -d -P nginx:1.9.12 45 | ``` 46 | 47 | ## Distribute Operating System Demo 48 | 49 | ``` 50 | kubectl get nodes 51 | ``` 52 | 53 | ``` 54 | kubectl run nginx --image=nginx:1.7.9 55 | ``` 56 | 57 | ``` 58 | kubectl expose rc nginx --type=LoadBalancer --port=80 59 | ``` 60 | 61 | ### Managing Resources 62 | 63 | ``` 64 | kubectl scale rc nginx --replicas=3 65 | ``` 66 | 67 | ### Upgrading Applications 68 | 69 | ``` 70 | kubectl rollingupdate nginx --image=nginx:1.9.12 --update-period=5s 71 | ``` 72 | -------------------------------------------------------------------------------- /kubecon-eu-2016/demo/.gitignore: -------------------------------------------------------------------------------- 1 | configs/config.js 2 | -------------------------------------------------------------------------------- /kubecon-eu-2016/demo/README.md: -------------------------------------------------------------------------------- 1 | # Kubernetes 1.2 Demo (Ghost) 2 | 3 | This tutorial will walk you through deploying [Ghost](https://ghost.org), 4 | A publishing platform for professional bloggers, using Kubernetes 1.2 features. 5 | This is the live demo that was given at KubeCon EU 2016. 6 | 7 | ![Ghost](ghost-screen-shot.png) 8 | 9 | ## Prerequisites 10 | 11 | ### Database 12 | 13 | Create a [Cloud SQL database instance](https://cloud.google.com/sql/docs/create-instance). 14 | 15 | #### Create the Ghost user and database 16 | 17 | Login to the mysql instance: 18 | 19 | ``` 20 | mysql -u root -p -h --ssl -p 21 | ``` 22 | 23 | Create the ghost user: 24 | 25 | ``` 26 | CREATE USER 'ghost'@'%' IDENTIFIED BY ''; 27 | ``` 28 | 29 | Create the ghost database and grant access to the ghost user: 30 | 31 | ``` 32 | CREATE DATABASE ghost; 33 | GRANT ALL ON ghost.* TO 'ghost'@'%'; 34 | FLUSH PRIVILEGES; 35 | ``` 36 | 37 | ### TLS Certificates 38 | 39 | The tls directory includes a set of self-signed TLS certificates for testing Ghost with 40 | TLS support. The certs are valid for the `*.example.com` wildcard domain. 41 | 42 | ``` 43 | ls -1 tls/ 44 | ``` 45 | ``` 46 | ca.crt 47 | tls.crt 48 | database-ca.crt 49 | tls.key 50 | ``` 51 | 52 | > The database-ca.crt was downloaded from the Cloud SQL control panel. 53 | 54 | ## Secrets Demo 55 | 56 | ``` 57 | kubectl create secret generic ghost-test --from-file pods/config.js 58 | ``` 59 | 60 | ``` 61 | kubectl create -f pods/ghost.yaml 62 | ``` 63 | 64 | ``` 65 | kubectl exec ghost /bin/cat /etc/ghost/config.js 66 | ``` 67 | 68 | ``` 69 | kubectl exec ghost /bin/mount 70 | ``` 71 | 72 | ``` 73 | ... 74 | tmpfs on /etc/ghost type tmpfs (rw,relatime) 75 | ``` 76 | 77 | ## Deployment Demo 78 | 79 | ### Store Server Certificates 80 | 81 | In order to share our TLS certificates with pods, and loadbalancers created by Kubernetes 82 | we first need to store them in a Secret. 83 | 84 | ``` 85 | kubectl create secret generic ghost-tls --from-file=tls/ 86 | ``` 87 | 88 | > The `--from-file` flag will create a secrets entry under the `ghost-tls` secret 89 | > for each file under the tls directory. 90 | 91 | ``` 92 | kubectl describe secrets ghost-tls 93 | ``` 94 | 95 | ``` 96 | Name: ghost-tls 97 | Namespace: default 98 | Labels: 99 | Annotations: 100 | 101 | Type: Opaque 102 | 103 | Data 104 | ==== 105 | tls.key: 1679 bytes 106 | ca.crt: 1363 bytes 107 | database-ca.crt: 1146 bytes 108 | tls.crt: 1440 bytes 109 | ``` 110 | 111 | ### Store the Ghost configuration file in a Secret 112 | 113 | The Ghost configuration file holds database connection info, mail and general application 114 | settings. Since the configuration file includes sensitive data we will store it in a secret. 115 | 116 | ``` 117 | kubectl create secret generic ghost --from-file=configs/config.js 118 | ``` 119 | 120 | > Once a configuration file is stored in a secret you can reference it from other 121 | > Kubernetes objects such as deployments and pods. 122 | 123 | 124 | ``` 125 | kubectl describe secret ghost 126 | ``` 127 | 128 | ### Store the Ghost Nginx config in configmap 129 | 130 | Nginx will be used to proxy traffic to the Ghost server over localhost in the same Pod. 131 | The configuration required to do this is fairly simple and does not contain sensitive data 132 | so it can be stored in a ConfigMap: 133 | 134 | ``` 135 | kubectl create configmap nginx-ghost --from-file=configs/ghost.conf 136 | ``` 137 | 138 | ``` 139 | kubectl describe configmap nginx-ghost 140 | ``` 141 | 142 | ### Expose the Ghost deployment 143 | 144 | ``` 145 | kubectl create -f services/ghost.yaml 146 | ``` 147 | 148 | ``` 149 | gcloud compute firewall-rules create allow-130-211-0-0-22 \ 150 | --source-ranges 130.211.0.0/22 --allow tcp:32000 151 | ``` 152 | 153 | ### Create the Ghost ingress controller 154 | 155 | ``` 156 | kubectl create -f ingress/ghost.yaml 157 | ``` 158 | 159 | ``` 160 | kubectl describe ingress ghost 161 | ``` 162 | 163 | ### Create the Ghost deployment 164 | 165 | ``` 166 | kubectl create -f deployments/ghost.yaml 167 | ``` 168 | 169 | ``` 170 | kubectl describe deployment ghost 171 | ``` 172 | 173 | ## Scale Demo 174 | 175 | ### Scale the ghost deployment 176 | 177 | Edit `deployments/ghost.yaml` and update the number of replicas: 178 | 179 | ``` 180 | spec: 181 | replicas: 3 182 | ``` 183 | 184 | Update the ghost deployment: 185 | 186 | ``` 187 | kubectl apply -f deployments/ghost.yaml 188 | ``` 189 | 190 | ``` 191 | kubectl describe deployment ghost 192 | ``` 193 | 194 | ``` 195 | kubectl get replicaset 196 | ``` 197 | 198 | ## Rolling Update Demo 199 | 200 | Deploy new versions of Ghost using the canary pattern. 201 | 202 | ### Deploy a canary 203 | 204 | ``` 205 | kubectl apply -f deployments/ghost-canary.yaml 206 | ``` 207 | 208 | ### Roll out a new version 209 | 210 | Edit `deployments/ghost.yaml` and update the image: 211 | 212 | ``` 213 | - name: "ghost" 214 | image: "kelseyhightower/ghost:0.7.8" 215 | ``` 216 | 217 | Update the ghost deployment: 218 | 219 | ``` 220 | kubectl apply -f deployments/ghost.yaml 221 | ``` 222 | 223 | 224 | 225 | -------------------------------------------------------------------------------- /kubecon-eu-2016/demo/cleanup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | kubectl delete deployments nginx 4 | kubectl delete deployments ghost 5 | kubectl delete deployments ghost-canary 6 | kubectl delete secret ghost-tls 7 | kubectl delete secret ghost 8 | kubectl delete secret 'ghost-test' 9 | kubectl delete configmap nginx-ghost 10 | kubectl delete pods ghost 11 | kubectl delete service ghost 12 | kubectl delete service nginx 13 | kubectl delete ingress ghost 14 | -------------------------------------------------------------------------------- /kubecon-eu-2016/demo/configs/README.md: -------------------------------------------------------------------------------- 1 | # Ghost Configuration Guide 2 | 3 | This guide will walk you through creating a `config.js` 4 | configuration file. 5 | 6 | ## Prerequisites 7 | 8 | * [Mailgun account](https://www.mailgun.com) 9 | * [mySQL instance]() 10 | 11 | ## Configuring Ghost 12 | 13 | 14 | Copy the `config.example.js` config to `config.js`, then edit 15 | `config.js` using the [Ghost configuration guide](http://support.ghost.org/config) 16 | as a reference to substitute the following items: 17 | 18 | ``` 19 | GhostURL 20 | DatabaseHost 21 | DatabasePassword 22 | MailgunDomain 23 | MailgunUsername 24 | MailgunPassword 25 | ``` 26 | 27 | 28 | ### Example Config 29 | 30 | ``` 31 | const fs = require('fs'); 32 | 33 | var config; 34 | 35 | config = { 36 | production: { 37 | url: 'http://ghost.example.com', 38 | forceAdminSSL: true, 39 | database: { 40 | client: 'mysql', 41 | connection: { 42 | host: '203.0.113.100', 43 | user: 'ghost', 44 | password: 'XXXXXXXX', 45 | database: 'ghost', 46 | charset: 'utf8', 47 | ssl: { 48 | ca: fs.readFileSync('/etc/ghost/ssl/database-ca.crt'), 49 | } 50 | } 51 | }, 52 | server: { 53 | host: '127.0.0.1', 54 | port: '2368' 55 | }, 56 | paths: { 57 | contentPath: '/var/lib/ghost' 58 | }, 59 | mail: { 60 | transport: 'SMTP', 61 | options: { 62 | from: 'ghost@example.com', 63 | host: 'smtp.mailgun.org', 64 | port: 2525, 65 | secure: true, 66 | auth: { 67 | user: 'postmaster@mg.example.com', 68 | pass: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' 69 | } 70 | } 71 | } 72 | } 73 | } 74 | 75 | module.exports = config; 76 | ``` 77 | -------------------------------------------------------------------------------- /kubecon-eu-2016/demo/configs/config.example.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | var config; 4 | 5 | config = { 6 | production: { 7 | url: '{{.GhostURL}}', 8 | urlSSL: '{{.GhostSSLURL}}', 9 | forceAdminSSL: true, 10 | database: { 11 | client: 'mysql', 12 | connection: { 13 | host: '{{.DatabaseHost}}', 14 | user: 'ghost', 15 | password: '{{.DatabasePassword}}', 16 | database: 'ghost', 17 | charset: 'utf8', 18 | ssl: { 19 | ca: fs.readFileSync('/etc/ghost/ssl/database-ca.crt'), 20 | } 21 | } 22 | }, 23 | server: { 24 | host: '127.0.0.1', 25 | port: '2368' 26 | }, 27 | paths: { 28 | contentPath: '/var/lib/ghost' 29 | }, 30 | mail: { 31 | transport: 'SMTP', 32 | options: { 33 | from: 'ghost@{{.MailgunDomain}}', 34 | host: 'smtp.mailgun.org', 35 | port: 2525, 36 | secure: true, 37 | auth: { 38 | user: '{{.MailgunUsername}}', 39 | pass: '{{.MailgunPassword}}' 40 | } 41 | } 42 | } 43 | } 44 | } 45 | 46 | module.exports = config; 47 | -------------------------------------------------------------------------------- /kubecon-eu-2016/demo/configs/ghost.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | 4 | location / { 5 | proxy_pass http://127.0.0.1:2368; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /kubecon-eu-2016/demo/deployments/ghost-canary.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | name: ghost-canary 5 | spec: 6 | replicas: 1 7 | template: 8 | metadata: 9 | labels: 10 | app: "ghost" 11 | track: "canary" 12 | spec: 13 | containers: 14 | - name: "nginx" 15 | image: "nginx:1.9.12" 16 | ports: 17 | - containerPort: 80 18 | lifecycle: 19 | preStop: 20 | exec: 21 | command: ["/usr/sbin/nginx","-s","quit"] 22 | livenessProbe: 23 | httpGet: 24 | path: / 25 | port: 80 26 | scheme: HTTP 27 | initialDelaySeconds: 10 28 | periodSeconds: 30 29 | timeoutSeconds: 5 30 | readinessProbe: 31 | httpGet: 32 | path: / 33 | port: 80 34 | scheme: HTTP 35 | initialDelaySeconds: 5 36 | timeoutSeconds: 1 37 | volumeMounts: 38 | - name: "nginx-conf" 39 | mountPath: "/etc/nginx/conf.d" 40 | - name: "ghost" 41 | image: "kelseyhightower/ghost:0.7.8" 42 | env: 43 | - name: "NODE_ENV" 44 | value: "production" 45 | - name: "GHOST_CONFIG" 46 | value: "/etc/ghost/config.js" 47 | livenessProbe: 48 | httpGet: 49 | path: / 50 | port: 2368 51 | scheme: HTTP 52 | initialDelaySeconds: 10 53 | periodSeconds: 30 54 | timeoutSeconds: 1 55 | volumeMounts: 56 | - name: "ghost" 57 | mountPath: "/etc/ghost" 58 | - name: "ghost-tls" 59 | mountPath: "/etc/ghost/ssl" 60 | volumes: 61 | - name: "ghost-tls" 62 | secret: 63 | secretName: "ghost-tls" 64 | - name: "nginx-conf" 65 | configMap: 66 | name: "nginx-ghost" 67 | items: 68 | - key: "ghost.conf" 69 | path: "ghost.conf" 70 | - name: "ghost" 71 | secret: 72 | secretName: "ghost" 73 | -------------------------------------------------------------------------------- /kubecon-eu-2016/demo/deployments/ghost.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | name: ghost 5 | spec: 6 | replicas: 1 7 | template: 8 | metadata: 9 | labels: 10 | app: "ghost" 11 | track: "stable" 12 | spec: 13 | containers: 14 | - name: "nginx" 15 | image: "nginx:1.9.12" 16 | ports: 17 | - containerPort: 80 18 | lifecycle: 19 | preStop: 20 | exec: 21 | command: ["/usr/sbin/nginx","-s","quit"] 22 | livenessProbe: 23 | httpGet: 24 | path: / 25 | port: 80 26 | scheme: HTTP 27 | initialDelaySeconds: 10 28 | periodSeconds: 30 29 | timeoutSeconds: 5 30 | readinessProbe: 31 | httpGet: 32 | path: / 33 | port: 80 34 | scheme: HTTP 35 | initialDelaySeconds: 5 36 | timeoutSeconds: 1 37 | volumeMounts: 38 | - name: "nginx-conf" 39 | mountPath: "/etc/nginx/conf.d" 40 | - name: "ghost" 41 | image: "kelseyhightower/ghost:0.7.7" 42 | env: 43 | - name: "NODE_ENV" 44 | value: "production" 45 | - name: "GHOST_CONFIG" 46 | value: "/etc/ghost/config.js" 47 | livenessProbe: 48 | httpGet: 49 | path: / 50 | port: 2368 51 | scheme: HTTP 52 | initialDelaySeconds: 10 53 | periodSeconds: 30 54 | timeoutSeconds: 1 55 | volumeMounts: 56 | - name: "ghost" 57 | mountPath: "/etc/ghost" 58 | - name: "ghost-tls" 59 | mountPath: "/etc/ghost/ssl" 60 | volumes: 61 | - name: "ghost-tls" 62 | secret: 63 | secretName: "ghost-tls" 64 | - name: "nginx-conf" 65 | configMap: 66 | name: "nginx-ghost" 67 | items: 68 | - key: "ghost.conf" 69 | path: "ghost.conf" 70 | - name: "ghost" 71 | secret: 72 | secretName: "ghost" 73 | -------------------------------------------------------------------------------- /kubecon-eu-2016/demo/docker/ghost-0-7-7/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:4.2-slim 2 | 3 | RUN apt-get update && apt-get install -y \ 4 | ca-certificates \ 5 | wget \ 6 | --no-install-recommends && rm -rf /var/lib/apt/lists/* 7 | 8 | ENV GHOST_SOURCE /usr/src/ghost 9 | WORKDIR $GHOST_SOURCE 10 | 11 | ENV GHOST_VERSION 0.7.7 12 | 13 | RUN buildDeps=' \ 14 | gcc \ 15 | make \ 16 | python \ 17 | unzip \ 18 | ' \ 19 | && set -x \ 20 | && apt-get update && apt-get install -y $buildDeps --no-install-recommends && rm -rf /var/lib/apt/lists/* \ 21 | && wget -O ghost.zip "https://ghost.org/archives/ghost-${GHOST_VERSION}.zip" \ 22 | && unzip ghost.zip \ 23 | && npm install --production \ 24 | && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false -o APT::AutoRemove::SuggestsImportant=false $buildDeps \ 25 | && rm ghost.zip \ 26 | && npm cache clean \ 27 | && rm -rf /tmp/npm* 28 | 29 | ENV GHOST_CONTENT /var/lib/ghost 30 | RUN mkdir -p "$GHOST_CONTENT" 31 | VOLUME $GHOST_CONTENT 32 | 33 | COPY docker-entrypoint.sh /entrypoint.sh 34 | ENTRYPOINT ["/entrypoint.sh"] 35 | 36 | EXPOSE 2368 37 | CMD ["npm", "start"] 38 | -------------------------------------------------------------------------------- /kubecon-eu-2016/demo/docker/ghost-0-7-7/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if [[ "$*" == npm*start* ]]; then 5 | baseDir="$GHOST_SOURCE/content" 6 | for dir in "$baseDir"/*/ "$baseDir"/themes/*/; do 7 | targetDir="$GHOST_CONTENT/${dir#$baseDir/}" 8 | mkdir -p "$targetDir" 9 | if [ -z "$(ls -A "$targetDir")" ]; then 10 | tar -c --one-file-system -C "$dir" . | tar xC "$targetDir" 11 | fi 12 | done 13 | 14 | if [ ! -e "$GHOST_CONTENT/config.js" ]; then 15 | sed -r ' 16 | s/127\.0\.0\.1/0.0.0.0/g; 17 | s!path.join\(__dirname, (.)/content!path.join(process.env.GHOST_CONTENT, \1!g; 18 | ' "$GHOST_SOURCE/config.example.js" > "$GHOST_CONTENT/config.js" 19 | fi 20 | 21 | ln -sf "$GHOST_CONTENT/config.js" "$GHOST_SOURCE/config.js" 22 | fi 23 | 24 | exec "$@" 25 | -------------------------------------------------------------------------------- /kubecon-eu-2016/demo/docker/ghost-0-7-8/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:4.2-slim 2 | 3 | RUN apt-get update && apt-get install -y \ 4 | ca-certificates \ 5 | wget \ 6 | --no-install-recommends && rm -rf /var/lib/apt/lists/* 7 | 8 | ENV GHOST_SOURCE /usr/src/ghost 9 | WORKDIR $GHOST_SOURCE 10 | 11 | ENV GHOST_VERSION 0.7.8 12 | 13 | RUN buildDeps=' \ 14 | gcc \ 15 | make \ 16 | python \ 17 | unzip \ 18 | ' \ 19 | && set -x \ 20 | && apt-get update && apt-get install -y $buildDeps --no-install-recommends && rm -rf /var/lib/apt/lists/* \ 21 | && wget -O ghost.zip "https://ghost.org/archives/ghost-${GHOST_VERSION}.zip" \ 22 | && unzip ghost.zip \ 23 | && npm install --production \ 24 | && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false -o APT::AutoRemove::SuggestsImportant=false $buildDeps \ 25 | && rm ghost.zip \ 26 | && npm cache clean \ 27 | && rm -rf /tmp/npm* 28 | 29 | ENV GHOST_CONTENT /var/lib/ghost 30 | RUN mkdir -p "$GHOST_CONTENT" 31 | VOLUME $GHOST_CONTENT 32 | 33 | COPY docker-entrypoint.sh /entrypoint.sh 34 | ENTRYPOINT ["/entrypoint.sh"] 35 | 36 | EXPOSE 2368 37 | CMD ["npm", "start"] 38 | -------------------------------------------------------------------------------- /kubecon-eu-2016/demo/docker/ghost-0-7-8/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if [[ "$*" == npm*start* ]]; then 5 | baseDir="$GHOST_SOURCE/content" 6 | for dir in "$baseDir"/*/ "$baseDir"/themes/*/; do 7 | targetDir="$GHOST_CONTENT/${dir#$baseDir/}" 8 | mkdir -p "$targetDir" 9 | if [ -z "$(ls -A "$targetDir")" ]; then 10 | tar -c --one-file-system -C "$dir" . | tar xC "$targetDir" 11 | fi 12 | done 13 | 14 | if [ ! -e "$GHOST_CONTENT/config.js" ]; then 15 | sed -r ' 16 | s/127\.0\.0\.1/0.0.0.0/g; 17 | s!path.join\(__dirname, (.)/content!path.join(process.env.GHOST_CONTENT, \1!g; 18 | ' "$GHOST_SOURCE/config.example.js" > "$GHOST_CONTENT/config.js" 19 | fi 20 | 21 | ln -sf "$GHOST_CONTENT/config.js" "$GHOST_SOURCE/config.js" 22 | fi 23 | 24 | exec "$@" 25 | -------------------------------------------------------------------------------- /kubecon-eu-2016/demo/ghost-screen-shot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelseyhightower/talks/a2a78c1a845654868aa75775fc00df9598bec361/kubecon-eu-2016/demo/ghost-screen-shot.png -------------------------------------------------------------------------------- /kubecon-eu-2016/demo/ingress/ghost.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Ingress 3 | metadata: 4 | name: ghost 5 | spec: 6 | backend: 7 | serviceName: ghost 8 | servicePort: 80 9 | tls: 10 | - secretName: "ghost-tls" 11 | hosts: 12 | - "*.example.com" 13 | -------------------------------------------------------------------------------- /kubecon-eu-2016/demo/pods/config.js: -------------------------------------------------------------------------------- 1 | var config; 2 | 3 | config = { 4 | test: { 5 | url: 'http://localhost:2368', 6 | database: { 7 | client: 'sqlite3', 8 | connection: { 9 | filename: '/var/lib/ghost/data/ghost.db' 10 | } 11 | }, 12 | server: { 13 | host: '127.0.0.1', 14 | port: '2368' 15 | }, 16 | paths: { 17 | contentPath: '/var/lib/ghost' 18 | }, 19 | } 20 | } 21 | 22 | module.exports = config; 23 | -------------------------------------------------------------------------------- /kubecon-eu-2016/demo/pods/ghost.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: ghost 5 | spec: 6 | containers: 7 | - name: "ghost" 8 | image: "kelseyhightower/ghost:0.7.8" 9 | env: 10 | - name: "NODE_ENV" 11 | value: "test" 12 | - name: "GHOST_CONFIG" 13 | value: "/etc/ghost/config.js" 14 | volumeMounts: 15 | - name: "ghost" 16 | mountPath: "/etc/ghost" 17 | volumes: 18 | - name: "ghost" 19 | secret: 20 | secretName: "ghost-test" 21 | -------------------------------------------------------------------------------- /kubecon-eu-2016/demo/services/ghost.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app: ghost 6 | name: ghost 7 | namespace: default 8 | spec: 9 | ports: 10 | - nodePort: 32000 11 | port: 80 12 | protocol: TCP 13 | targetPort: 80 14 | selector: 15 | app: ghost 16 | type: NodePort 17 | -------------------------------------------------------------------------------- /kubecon-eu-2016/demo/tls/ca.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIID2jCCAsKgAwIBAgIUM/sHjbCs24029HM5h21usngW25owDQYJKoZIhvcNAQEL 3 | BQAwczELMAkGA1UEBhMCVVMxDzANBgNVBAgTBk9yZWdvbjERMA8GA1UEBxMIUG9y 4 | dGxhbmQxEzARBgNVBAoTCkt1YmVybmV0ZXMxEzARBgNVBAsTCkt1YmVybmV0ZXMx 5 | FjAUBgNVBAMTDUt1YmVybmV0ZXMgQ0EwHhcNMTYwMzEwMDEzODAwWhcNMjEwMzA5 6 | MDEzODAwWjBzMQswCQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQH 7 | EwhQb3J0bGFuZDETMBEGA1UEChMKS3ViZXJuZXRlczETMBEGA1UECxMKS3ViZXJu 8 | ZXRlczEWMBQGA1UEAxMNS3ViZXJuZXRlcyBDQTCCASIwDQYJKoZIhvcNAQEBBQAD 9 | ggEPADCCAQoCggEBAN+nQ1dmkXnRnFVFtGU0uZOSNT66UqqeU+oBMTY2np0D13fW 10 | npFbFia48E836h5CQonRWmUVxYDBbW69UbiqotFE4E6m2Zu+X42XzA0hl2aV8ctJ 11 | C/FGFRBHUKuqW4SSUVdxOGk2F4cNr6LQlkFeira/h+GdwoMYGV5UbrlNsXMsVVCX 12 | 9+m9gW4mSffU675DqKs1li0e0BqoWt49pnBFyEWc+w7cbLY4+8IxnYeNmkQjcCys 13 | y056RrybVsecK2ckUJutseYTAK8JuruuoC87ZkC5y5fjF3M4ePg+f6nIyXNOb2SS 14 | qG15VXGC85Ixc8cL0M4iA4lTKTkjTrStnOrIKtsCAwEAAaNmMGQwDgYDVR0PAQH/ 15 | BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQIwHQYDVR0OBBYEFEaj2uZ1p0ef8dbT 16 | glQJ+kqc8Ju5MB8GA1UdIwQYMBaAFEaj2uZ1p0ef8dbTglQJ+kqc8Ju5MA0GCSqG 17 | SIb3DQEBCwUAA4IBAQDQWneM4sH2g9oUJ1I3CZ4nKCB8QO5sAPT7kSABSnqWdtW1 18 | 8JgHVhpItubNLYBPnFTK+2DdsR/YN221OyTpHfv/alNtSBtsIYQBpCaLBDYFcrxC 19 | Paq32z+9Es3sW5OnS+PaU3IEazSTexH+4OrNFWX6GqNm+11XKcXeDFyicd4WGxQt 20 | zJjingMMJfoTt0h3gjQHHJ9GjokZvGeG+YNEQV6dugLc5TxPqwI7oUNus+OxXO3i 21 | cSYYiU880Qs75ZCzkGSfYpFBy5ibp0WBpnZZSuuix1rgMAYYDPQHqYqc/GLjtKuA 22 | KW6epBJHuj6pSVZTg7jb20NIs/8rnnh1GwqiKVZr 23 | -----END CERTIFICATE----- 24 | -------------------------------------------------------------------------------- /kubecon-eu-2016/demo/tls/database-ca.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDITCCAgmgAwIBAgIBADANBgkqhkiG9w0BAQUFADBIMSMwIQYDVQQDExpHb29n 3 | bGUgQ2xvdWQgU1FMIFNlcnZlciBDQTEUMBIGA1UEChMLR29vZ2xlLCBJbmMxCzAJ 4 | BgNVBAYTAlVTMB4XDTE2MDMwOTIyNDA1MVoXDTE4MDMwOTIyNDE1MVowSDEjMCEG 5 | A1UEAxMaR29vZ2xlIENsb3VkIFNRTCBTZXJ2ZXIgQ0ExFDASBgNVBAoTC0dvb2ds 6 | ZSwgSW5jMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC 7 | ggEBAITRx5IUAvz2bx7CEVaAu0AUitLRJqzGtmYdmo3pI3Mn1gbpYlFL205xdHBd 8 | xYbQG3Pcxwypj+86VEzNNa9u5AYk7TGDQufY/ezPAlaraPF/zTEdrFbIf9Yf/5ly 9 | YNLT1hg+4yBIDjCke1njYBQSQTdIZZF5FDaC2qblAtQwSg6+jmjVKkxb0VUFzf2j 10 | rAMNI7+M1Q+Tnh0noYeFGCDczzkX7b/L6I6oDOYMLqabT//WFCed+AcbRnZ0PRqj 11 | 8JsRwdwgtl49QJ4CMeVeco1ugdF1jAwzKw9ATxjQ8rnCb2itNmUK5UReDs1e9b+D 12 | 6KnEvQLYybT24vLzT4u6Xh64ZE8CAwEAAaMWMBQwEgYDVR0TAQH/BAgwBgEB/wIB 13 | ADANBgkqhkiG9w0BAQUFAAOCAQEAGelH5UxamvTsfPLo5rBpvc8hP0xLmKgt44uF 14 | YRA5ZPAoT7KpZ2YaH3juY3NnRlsIenSu+O5JbtrCj2+EgI+fs3nGFWnxkQVXJjul 15 | okcw+r12mx+qcI0j5jzTjMqc0FC69j2bke4WJii338N8ZpgVfzmmekUXLYti0M9G 16 | MYD3TZ3BBRCz7ISvJSpwO10sAO1CuDsAdZK8NCut6bEftQh7jlix7QGNNnCU9wc2 17 | tSC6r1xIlBmRWJNCIXT2zlCsci+NLI/E17xgm7sWZJgLL+nfzlIc/le0jlGAOLzN 18 | GmXFnF6T728FtTizXeHbfsWOlbf/iITaYRTDVtoPuFwQVVElGA== 19 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /kubecon-eu-2016/demo/tls/tls.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEBjCCAu6gAwIBAgIUIeX2WalSMT3k13+BwNh55fui/XEwDQYJKoZIhvcNAQEL 3 | BQAwczELMAkGA1UEBhMCVVMxDzANBgNVBAgTBk9yZWdvbjERMA8GA1UEBxMIUG9y 4 | dGxhbmQxEzARBgNVBAoTCkt1YmVybmV0ZXMxEzARBgNVBAsTCkt1YmVybmV0ZXMx 5 | FjAUBgNVBAMTDUt1YmVybmV0ZXMgQ0EwHhcNMTYwMzEwMDEzODAwWhcNMTcwMzEw 6 | MDEzODAwWjBuMQswCQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQH 7 | EwhQb3J0bGFuZDETMBEGA1UEChMKS3ViZXJuZXRlczEOMAwGA1UECxMFR2hvc3Qx 8 | FjAUBgNVBAMTDSouZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw 9 | ggEKAoIBAQC8MAogAsbTj/JG3i/G/NncseaDGN4IsLj77ho6CMkVMSyWE1nJsSpP 10 | GhIFQpbuxkukY3iuxXmo92WlEIOEUrxHULS7gU3Yptl9/u72hHTV+X9IqfR+OVzz 11 | ITXbqge2MyJKi2ZynDKRg5l13KCgJ1eoe/qX5kLUbSLJ+3FOyWDtVGlQ6TY0dCgo 12 | sSpSyCyDWDFwHkNb7OWPX5CXNc4TZtmTQvb7kFX8be+bIxTlMMW8TmhDTwOxT6Ym 13 | 7sObLmIWMR7tYrBm5SM3OewGVBXY11FAFgJMPK+L1UYDz3pyq2xcpYRTIYCasjon 14 | SsRZIHRGo2cWpLOUfGcy85Ai0fBDy3nZAgMBAAGjgZYwgZMwDgYDVR0PAQH/BAQD 15 | AgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYE 16 | FFKDCG1Xo16PDsXHdRtu1OxBZKjDMB8GA1UdIwQYMBaAFEaj2uZ1p0ef8dbTglQJ 17 | +kqc8Ju5MB4GA1UdEQQXMBWCDSouZXhhbXBsZS5jb22HBH8AAAEwDQYJKoZIhvcN 18 | AQELBQADggEBAJIN2b/3f4HOF2UyPiISfN477BkSCOlTc6D5CEuLWYt6H8dg79yB 19 | tPtzzYnxd1gmR2Gy8yPFoJIWSjiyhDIWTOIlweQahIR6//9i+EpY74xdBbakHJbe 20 | P6pt1QfWAgJaAAQrK+BYMAoIke9HoRIKS6DtlOBxEOUiLqLQVDZEuU5OQS3Bt40f 21 | 2/Z1ADY9f6REfWf4EXYI8clLyQs+rlhsa/qqYZguJ+s1HbkLtgXZHo4NERL9V6T6 22 | BTi2NVlqQ/HirUptxgJfDFlaep66tYknjjhcmqYvSvuQ5bd8WRgCw423c4k9QRW/ 23 | ayFC9CMCSRLDgmDQeYX/tyc7leS63efpWK4= 24 | -----END CERTIFICATE----- 25 | -------------------------------------------------------------------------------- /kubecon-eu-2016/demo/tls/tls.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpQIBAAKCAQEAvDAKIALG04/yRt4vxvzZ3LHmgxjeCLC4++4aOgjJFTEslhNZ 3 | ybEqTxoSBUKW7sZLpGN4rsV5qPdlpRCDhFK8R1C0u4FN2KbZff7u9oR01fl/SKn0 4 | fjlc8yE126oHtjMiSotmcpwykYOZddygoCdXqHv6l+ZC1G0iyftxTslg7VRpUOk2 5 | NHQoKLEqUsgsg1gxcB5DW+zlj1+QlzXOE2bZk0L2+5BV/G3vmyMU5TDFvE5oQ08D 6 | sU+mJu7Dmy5iFjEe7WKwZuUjNznsBlQV2NdRQBYCTDyvi9VGA896cqtsXKWEUyGA 7 | mrI6J0rEWSB0RqNnFqSzlHxnMvOQItHwQ8t52QIDAQABAoIBAQCH1zmHz9lL3+1o 8 | IHxmbCCrQTN+0FV9+msdV8tQtwTHql5f2ooGoD9FKDF34JBovXTerfrwVZWzVRnn 9 | I9t7ielkpSpA616RFCeM3pgKFKTtzBKIFj5pWujwi7l/3eWBLLoFC0khVATgqxj8 10 | Tg0Ybi3FbfD+8vSsuDbTjBBHae/wf7Aw8+5D1SLJdBxFg8nFg+am3lu9Wgm3TcQM 11 | 3J5f6IWuJOiCWBlidml3AJ/b71yw7iYabu6Wf0d0S6HoykK+QHi2VWzPw11gH0JY 12 | x0nQLugLVu2YVTHsLrCDMGGcU2dPs/yb+QmrK1SEn4v4dHFJC4ULc6mSpS10QHmZ 13 | 2N4a4IoNAoGBAN/02MlRsgwnWJ1DDmuMdpVwC30VwzjEHRMz+hnhjosNv1y5bes1 14 | e2zWeA5D0v+we0KfLt/FVxnCPeTOjmnD03Kq1u8VD181wft7m6l9UaZxdQXXp+22 15 | 6+nNFEhQQA1lLznEFkogp51i7x0z4X0hxu/18UkJv/aGMXtbGirJvLH7AoGBANcd 16 | CqfRX9xoFULQE18V7Fbi589DmrhUUZBwIAdEw5PgawPHzLY7RIyInzwt24LNQiLM 17 | BMZCA4t1nhNAFTkAjeUFlcbB1cf4PnN8+5DDZYsmFWifqbFV4/NNbW8pPN9LIIdZ 18 | 8WsV+QQX/ebLixhiSwxOPsssOIpnbUdp17tThk87AoGBANbqFRtkjZMCMxR/JBhr 19 | K+UOJ8g6mSQhdrFV4LzzaiHg6HGn9GaR5Ua1rXIq/hGmnzJ4pbfRnVs3vsOSwLGY 20 | XZKdhTLbp+u7H9MgdGm6vB8Yo68em6UQM+YiikM217DDGAW8OZObMJ5lMYd5oPq+ 21 | 7jSadJidhZyifFufOkYzYCP/AoGAT1LnRgEgb192T5/5NLwZ3eRohPayDD0Tosam 22 | GOgTkulTrR41cBGk8onC5mcmpjJYrAo9zHo1Ymzp8MFV0iJRMN4BYDzEP6xcIyw4 23 | fCaBwHE3vc/6vGkm2OZ5b19ukgzbHu5c5xdAL3FFcKEoVsKQWCZWY4eYBfmjw4zV 24 | P7/KLFcCgYEA3qI0TCTM2WgRdRFKOhjojP57MW4y4ELnccrjfNAA0A4NKTvyMtrx 25 | isG6uMAJB3JYSiGqNNfyy/04VEPAHiQEPwDUxFBkyOhggBB0YF5o7FD7xF6vW0Qi 26 | YSsIkmBJyomshIwnSdPmn9UF7vUFpsFhTrbJOXuUqj1UupG4aGtbwvI= 27 | -----END RSA PRIVATE KEY----- 28 | --------------------------------------------------------------------------------