DOCKER, KUBERNETES, AND GCP
How do you use these complementary tools to deploy containers in the Cloud?
THE BASICS
CONTAINER TECH
Nothing new… Existed for years
Linux has LXC and Libcontainer, BSD has Jails, Solaris has
Zones
Docker (the company) just figured a clever way to packaging it
and adding a rich toolset around it.
DOCKER BASICS
•  Docker runs on Linux x64 (only)
•  Dependent on libcontainer, a Linux container platform
•  Container isolation (sandbox): filesystem, process, network
•  Layered filesystem
•  Benefits
•  Versioning
•  Portability
•  Lightweight
•  Faster to launch
DOCKER WORKFLOW
Dockerfile
Docker Client
docker build
Image
Docker Client
docker run
Container
Docker Client
docker pull
docker push
Docker Registry
Infrastructure
Client
swarm
kubernetes
meso
DOCKER ON MAC
•  Let’s focus on running Docker on the Mac
•  Remember Docker only runs on Linux x64
•  How do I run it on the Mac?
•  Need Virtual Machine to emulate a Linux host
•  Virtual machine (VM) running Linux x64
•  Docker engine running on VM
•  Mac client to communicate with Docker engine on Linux VM
DOCKER FOR MAC VS DOCKER TOOLBOX
Docker for Mac Docker Toolbox
# VMs 1 Multiple
Underlying VM
Hypervisor.framework
(xhyve)
VirtualBox
Base OS Alpine Boot2Docker
(VM) Management Tool Docker.app docker-machine
(VM) Management UI GUI CLI
MAC DOCKER ARCHITECTURE
Mac OS X
Virtual Machine (VirtualBox)Docker client
docker (CLI)
Kinematic (GUI)
Docker Machine
Linux (Boot2Docker)
Container
1
Container
2
Kernel
Docker Engine
Docker
Daemon
API
docker
(CLI)
KUBERNETES ARCHITECTURE
Master
API Server
Replication Scheduler
Config
(etcd)
Client
kubectl
Node
Kubelet
Kube-proxy
Pod 1
Container
Container
Container Engine
Pod 2
Container
KUBERNETES BASICS
•  Tool to orchestrate containers at scale and managing the application/service stack
•  Master
•  API Server and kubectl (client) – communicate and define the desired state
•  Scheduler – schedule workload on nodes
•  Replication – correct number of pod replicas
•  Config – distributed config store
•  Node (Slave)
•  Kubelet – communicate with master and start workloads
•  Kube-proxy – load balancer and direct traffic
•  Pod – group of 1..n containers tied together for admin and networking
•  Cluster = masters + nodes
DEMO
Tying together what we have learned so far and deploy Docker containers to Google
Cloud
HELLO WORLD ON GOOGLE CLOUD
(KUBERNETES)
http://kubernetes.io/docs/hellonode/
PRE-REQUISITES – SERVER SIDE
1.  Go to https://console.cloud.google.com/
2.  Create a GCP Project
3.  Copy the GCP Project ID
PRE-REQUISITES – CLIENT (MAC) SIDE
# Install node and nvm (node version manager)
$ brew update
$ brew install nvm
$ # Add the following to ~/.bash_profile
$ # export NVM_DIR=~/.nvm
$ # source $(brew --prefix nvm)/nvm.sh
$ nvm install 7.0.0
PRE-REQUISITES – CLIENT (MAC) SIDE II
$ # Install docker
$ brew install docker-compose # should also install docker and
docker-machine
$ # Install google cloud sdk
$ brew cask install google-cloud-sdk
$ gcloud components install kubectl
$ # You may want to add the following:
$ EXPORT PATH=$PATH:/opt/homebrew-cask/Caskroom/google-cloud-
sdk/latest/google-cloud-sdk/bin/
$ # Set up Google Cloud environment
$ export PROJECT_ID="my-google-cloud-project-id"
AUTHENTICATION
# Set up your account with google cloud sdk
$ gcloud auth login my-registered-email
$ gcloud config set project my-google-cloud-project-
id
$ gcloud auth list
# Optional: env var set for convenience
$ export PROJECT_ID="my-google-cloud-project-id"
$ # Note: your project-id != project name
NODE.JS CODE
// Filename: server.js
var http = require('http');
var handleRequest = function(request, response) {
console.log('Received request for URL: ' + request.url);
response.writeHead(200);
response.end('Hello World!');
};
var www = http.createServer(handleRequest);
www.listen(8080);
RUN DOCKER-MACHINE ON LOCAL VM
$ # Before running any docker commands, run docker-machine
to create a VirtualBox instance
$ docker-machine create --driver virtualbox default
$ docker-machine env
$ eval "$(docker-machine env default)"
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
default * virtualbox Running tcp://192.168.99.100:2376 v1.12.0
DOCKERFILE
FROM node:7.0.0
ADD server.js .
EXPOSE 8080
CMD node server.js
DOCKER BUILD
$ # Build docker image
$ docker images
$ docker build -t gcr.io/$PROJECT_ID/helloworld:v1 .
$ # Please get your project id right.
$ # project name != project id. For example
$ # project name = helloworld-kubernetes
$ # project id = helloworld-kubernetes-148321
RUN LOCALLY
$ # Run docker locally
$ docker run -d -p 8080:8080 --name helloworld gcr.io/helloworld-kubernetes/
helloworld:v1
$ # Docker machine
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
default * virtualbox Running tcp://192.168.99.100:2376 v1.12.3
$ # Docker containers running
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
PORTS NAMES
3047947245fa gcr.io/helloworld-kubernetes/helloworld:v1 "/bin/sh -c 'node ser" 4 minutes ago Up 3
minutes 0.0.0.0:8080->8080/tcp helloworld
$ curl http://192.168.99.100:8080
Hello World!
# Or just do curl $(docker-machine ip default):8080
PRIVATE DOCKER REGISTRY (EMPTY)
PUSH IMAGE TO PRIVATE GOOGLE REGISTRY
$ docker images
$ gcloud docker -- push gcr.io/$PROJECT_ID/helloworld:v1
$ # If gcloud docker -- push doesn’t work, you probably
didn’t set your project id properly.
$ # project name != project id. For example
$ # project name = helloworld-kubernetes
$ # project id = helloworld-kubernetes-148321
PRIVATE DOCKER REGISTRY
PUSH IMAGE TO PRIVATE GOOGLE REGISTRY
$ docker images
$ gcloud docker -- push gcr.io/$PROJECT_ID/helloworld:v1
$ # If gcloud docker -- push doesn’t work, you probably
didn’t set your project id properly.
$ # project name != project id. For example
$ # project name = helloworld-kubernetes
$ # project id = helloworld-kubernetes-148321
CREATE A CONTAINER CLUSTER
CONFIGURE A CONTAINER CLUSTER
CREATED CONTAINER CLUSTER
GET CREDENTIALS FOR KUBECTL
•  API Manager > Create
Credentials > Service
Account Key
•  JSON Key type
•  Download the json file
AUTH FOR KUBECTL
$ # If you run kubectl, you see an error message
$ kubectl version
error: google: could not find default credentials. See https://
developers.google.com/accounts/docs/application-default-credentials
for more information.
$ You need to authenticate with the crentials
$ export GOOGLE_APPLICATION_CREDENTIALS=~/helloworld-
kubernetes-abcde00000.json
$ gcloud auth application-default login
$ kubectl version # Should work now
RUN KUBERNETES NODE
$ # Create and run a Kubernetes pod
$ kubectl run helloworld --image=gcr.io/$PROJECT_ID/helloworld:v1 --
port=8080
deployment "helloworld" created
$ # Print deployments
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
helloworld 1 1 1 1 1m
$ # Print pods
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
helloworld-2696007752-golst 1/1 Running 0 5m
TEST WEBSITE
$ # Expose pod. By default a Kubernetes node is only
accessible by its internal IP address
$ kubectl expose deployment helloworld --
type="LoadBalancer"
$ kubectl get services helloworld
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
helloworld 10.3.247.187 104.198.6.146 8080/TCP 2m
$ curl 104.198.6.146:8080
Hello World!
SCALE WEBSITE
$ # Scale the pod to 4 replicas
$ kubectl scale deployment helloworld --replicas=4
$ # Get status
$ kubectl get deployment
$ kubectl get pods
CHANGE CODE AND UPDATE GCP
$ # Edit server.js
$ vi server.js
$ # Build and push changes
$ docker build -t gcr.io/$PROJECT_ID/helloworld:v2 .
$ gcloud docker -- push gcr.io/$PROJECT_ID/helloworld:v2
$ # Deploy changes
$ kubectl set image deployment/helloworld helloworld=gcr.io/$PROJECT_ID/helloworld:v2
$ deployment "helloworld" image updated
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
helloworld-2696007752-bergs 1/1 Terminating 0 15m
helloworld-2696007752-c87rs 1/1 Terminating 0 15m
helloworld-2696007752-golst 1/1 Terminating 0 14h
helloworld-2696007752-zwpi4 1/1 Terminating 0 15m
helloworld-2777403465-e802v 1/1 Running 0 11s
helloworld-2777403465-ksyxe 0/1 ContainerCreating 0 5s
helloworld-2777403465-rgq7f 1/1 Running 0 11s
helloworld-2777403465-six3e 1/1 Running 0 4s
$ kubectl get services helloworld
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
helloworld 10.3.247.187 104.198.6.146 8080/TCP 14h
$ curl 104.198.6.146:8080
Hello World 2!
CLEAN UP
$ # Delete pod
$ kubectl delete service,deployment helloworld
$ # Delete container cluster
$ gcloud container clusters delete helloworld
Q + A
Any questions?
You can find me at @cybersam

Docker, Kubernetes, and Google Cloud

  • 1.
    DOCKER, KUBERNETES, ANDGCP How do you use these complementary tools to deploy containers in the Cloud?
  • 2.
  • 3.
    CONTAINER TECH Nothing new…Existed for years Linux has LXC and Libcontainer, BSD has Jails, Solaris has Zones
  • 4.
    Docker (the company)just figured a clever way to packaging it and adding a rich toolset around it.
  • 5.
    DOCKER BASICS •  Dockerruns on Linux x64 (only) •  Dependent on libcontainer, a Linux container platform •  Container isolation (sandbox): filesystem, process, network •  Layered filesystem •  Benefits •  Versioning •  Portability •  Lightweight •  Faster to launch
  • 6.
    DOCKER WORKFLOW Dockerfile Docker Client dockerbuild Image Docker Client docker run Container Docker Client docker pull docker push Docker Registry Infrastructure Client swarm kubernetes meso
  • 7.
    DOCKER ON MAC • Let’s focus on running Docker on the Mac •  Remember Docker only runs on Linux x64 •  How do I run it on the Mac? •  Need Virtual Machine to emulate a Linux host •  Virtual machine (VM) running Linux x64 •  Docker engine running on VM •  Mac client to communicate with Docker engine on Linux VM
  • 8.
    DOCKER FOR MACVS DOCKER TOOLBOX Docker for Mac Docker Toolbox # VMs 1 Multiple Underlying VM Hypervisor.framework (xhyve) VirtualBox Base OS Alpine Boot2Docker (VM) Management Tool Docker.app docker-machine (VM) Management UI GUI CLI
  • 9.
    MAC DOCKER ARCHITECTURE MacOS X Virtual Machine (VirtualBox)Docker client docker (CLI) Kinematic (GUI) Docker Machine Linux (Boot2Docker) Container 1 Container 2 Kernel Docker Engine Docker Daemon API docker (CLI)
  • 10.
    KUBERNETES ARCHITECTURE Master API Server ReplicationScheduler Config (etcd) Client kubectl Node Kubelet Kube-proxy Pod 1 Container Container Container Engine Pod 2 Container
  • 11.
    KUBERNETES BASICS •  Toolto orchestrate containers at scale and managing the application/service stack •  Master •  API Server and kubectl (client) – communicate and define the desired state •  Scheduler – schedule workload on nodes •  Replication – correct number of pod replicas •  Config – distributed config store •  Node (Slave) •  Kubelet – communicate with master and start workloads •  Kube-proxy – load balancer and direct traffic •  Pod – group of 1..n containers tied together for admin and networking •  Cluster = masters + nodes
  • 12.
    DEMO Tying together whatwe have learned so far and deploy Docker containers to Google Cloud
  • 13.
    HELLO WORLD ONGOOGLE CLOUD (KUBERNETES) http://kubernetes.io/docs/hellonode/
  • 14.
    PRE-REQUISITES – SERVERSIDE 1.  Go to https://console.cloud.google.com/ 2.  Create a GCP Project 3.  Copy the GCP Project ID
  • 15.
    PRE-REQUISITES – CLIENT(MAC) SIDE # Install node and nvm (node version manager) $ brew update $ brew install nvm $ # Add the following to ~/.bash_profile $ # export NVM_DIR=~/.nvm $ # source $(brew --prefix nvm)/nvm.sh $ nvm install 7.0.0
  • 16.
    PRE-REQUISITES – CLIENT(MAC) SIDE II $ # Install docker $ brew install docker-compose # should also install docker and docker-machine $ # Install google cloud sdk $ brew cask install google-cloud-sdk $ gcloud components install kubectl $ # You may want to add the following: $ EXPORT PATH=$PATH:/opt/homebrew-cask/Caskroom/google-cloud- sdk/latest/google-cloud-sdk/bin/ $ # Set up Google Cloud environment $ export PROJECT_ID="my-google-cloud-project-id"
  • 17.
    AUTHENTICATION # Set upyour account with google cloud sdk $ gcloud auth login my-registered-email $ gcloud config set project my-google-cloud-project- id $ gcloud auth list # Optional: env var set for convenience $ export PROJECT_ID="my-google-cloud-project-id" $ # Note: your project-id != project name
  • 18.
    NODE.JS CODE // Filename:server.js var http = require('http'); var handleRequest = function(request, response) { console.log('Received request for URL: ' + request.url); response.writeHead(200); response.end('Hello World!'); }; var www = http.createServer(handleRequest); www.listen(8080);
  • 19.
    RUN DOCKER-MACHINE ONLOCAL VM $ # Before running any docker commands, run docker-machine to create a VirtualBox instance $ docker-machine create --driver virtualbox default $ docker-machine env $ eval "$(docker-machine env default)" $ docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS default * virtualbox Running tcp://192.168.99.100:2376 v1.12.0
  • 20.
    DOCKERFILE FROM node:7.0.0 ADD server.js. EXPOSE 8080 CMD node server.js
  • 21.
    DOCKER BUILD $ #Build docker image $ docker images $ docker build -t gcr.io/$PROJECT_ID/helloworld:v1 . $ # Please get your project id right. $ # project name != project id. For example $ # project name = helloworld-kubernetes $ # project id = helloworld-kubernetes-148321
  • 22.
    RUN LOCALLY $ #Run docker locally $ docker run -d -p 8080:8080 --name helloworld gcr.io/helloworld-kubernetes/ helloworld:v1 $ # Docker machine $ docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS default * virtualbox Running tcp://192.168.99.100:2376 v1.12.3 $ # Docker containers running $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3047947245fa gcr.io/helloworld-kubernetes/helloworld:v1 "/bin/sh -c 'node ser" 4 minutes ago Up 3 minutes 0.0.0.0:8080->8080/tcp helloworld $ curl http://192.168.99.100:8080 Hello World! # Or just do curl $(docker-machine ip default):8080
  • 23.
  • 24.
    PUSH IMAGE TOPRIVATE GOOGLE REGISTRY $ docker images $ gcloud docker -- push gcr.io/$PROJECT_ID/helloworld:v1 $ # If gcloud docker -- push doesn’t work, you probably didn’t set your project id properly. $ # project name != project id. For example $ # project name = helloworld-kubernetes $ # project id = helloworld-kubernetes-148321
  • 25.
  • 26.
    PUSH IMAGE TOPRIVATE GOOGLE REGISTRY $ docker images $ gcloud docker -- push gcr.io/$PROJECT_ID/helloworld:v1 $ # If gcloud docker -- push doesn’t work, you probably didn’t set your project id properly. $ # project name != project id. For example $ # project name = helloworld-kubernetes $ # project id = helloworld-kubernetes-148321
  • 27.
  • 28.
  • 29.
  • 30.
    GET CREDENTIALS FORKUBECTL •  API Manager > Create Credentials > Service Account Key •  JSON Key type •  Download the json file
  • 31.
    AUTH FOR KUBECTL $# If you run kubectl, you see an error message $ kubectl version error: google: could not find default credentials. See https:// developers.google.com/accounts/docs/application-default-credentials for more information. $ You need to authenticate with the crentials $ export GOOGLE_APPLICATION_CREDENTIALS=~/helloworld- kubernetes-abcde00000.json $ gcloud auth application-default login $ kubectl version # Should work now
  • 32.
    RUN KUBERNETES NODE $# Create and run a Kubernetes pod $ kubectl run helloworld --image=gcr.io/$PROJECT_ID/helloworld:v1 -- port=8080 deployment "helloworld" created $ # Print deployments $ kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE helloworld 1 1 1 1 1m $ # Print pods $ kubectl get pods NAME READY STATUS RESTARTS AGE helloworld-2696007752-golst 1/1 Running 0 5m
  • 33.
    TEST WEBSITE $ #Expose pod. By default a Kubernetes node is only accessible by its internal IP address $ kubectl expose deployment helloworld -- type="LoadBalancer" $ kubectl get services helloworld NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE helloworld 10.3.247.187 104.198.6.146 8080/TCP 2m $ curl 104.198.6.146:8080 Hello World!
  • 34.
    SCALE WEBSITE $ #Scale the pod to 4 replicas $ kubectl scale deployment helloworld --replicas=4 $ # Get status $ kubectl get deployment $ kubectl get pods
  • 35.
    CHANGE CODE ANDUPDATE GCP $ # Edit server.js $ vi server.js $ # Build and push changes $ docker build -t gcr.io/$PROJECT_ID/helloworld:v2 . $ gcloud docker -- push gcr.io/$PROJECT_ID/helloworld:v2 $ # Deploy changes $ kubectl set image deployment/helloworld helloworld=gcr.io/$PROJECT_ID/helloworld:v2 $ deployment "helloworld" image updated $ kubectl get pods NAME READY STATUS RESTARTS AGE helloworld-2696007752-bergs 1/1 Terminating 0 15m helloworld-2696007752-c87rs 1/1 Terminating 0 15m helloworld-2696007752-golst 1/1 Terminating 0 14h helloworld-2696007752-zwpi4 1/1 Terminating 0 15m helloworld-2777403465-e802v 1/1 Running 0 11s helloworld-2777403465-ksyxe 0/1 ContainerCreating 0 5s helloworld-2777403465-rgq7f 1/1 Running 0 11s helloworld-2777403465-six3e 1/1 Running 0 4s $ kubectl get services helloworld NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE helloworld 10.3.247.187 104.198.6.146 8080/TCP 14h $ curl 104.198.6.146:8080 Hello World 2!
  • 36.
    CLEAN UP $ #Delete pod $ kubectl delete service,deployment helloworld $ # Delete container cluster $ gcloud container clusters delete helloworld
  • 37.
    Q + A Anyquestions? You can find me at @cybersam