Containers are everywhere these days. Many of us are containerizing our applications to take advantage of the ease of a single artifact, but what can we do to make deploying these containers to a fleet of servers easier? Kubernetes is arguably the most popular container orchestration system to date. Kubernetes was born out of a decade of research at Google and has seen success; by itself as a fantastic way to orchestrate containers across multiple machines and as a component in other platforms.
This talk will begin with the anatomy and setup of a Kubernetes cluster. We'll demonstrate (live) taking a container containing a simple web service and launch our application into a small Kubernetes cluster. Next we'll perform a rolling update to deploy a new container version with zero downtime. Also, we'll check out some cool debugging features Kubernetes provides over the course of our demo.
2. What is Kubernetes?What is Kubernetes?
Container Orchestration Toolset
Originated at Google (Borg)
Now a Cloud Native Computing Foundation project
Used in commercial and open source projects
Tectonic (CoreOS)
Meteor Galaxy (MeteorJS)
OpenShift 3 (Red Hat)
Kubernetes Scheduler for Deis (Engine Yard)
3. Why Kubernetes?Why Kubernetes?
Deploying one single container app is easy
Deploying a complex app is more difficult
One or more containers
Replicas of containers
Data volumes for persistent storage
Deploying lots of complex apps can be a challenge
24. Node
kubelet
Ensures that pod specifications are met on a
node
Performs garbage collection on containers
Ensures that containers are healthy
25. Node
kube-proxy
Network proxy that forwards traffic to proper
container
Configured using Kubernetes service
Can forward TCP and UDP steams or round-
robin TCP and UDP forwarding
29. If you see this and following slides during the
talk, then my demo was a bust. These slides
are plan B. Sorry about that.
If you're browsing my slides after the talk,
then this is what I demonstrated live.
https://github.com/pires/kubernetes-vagrant-coreos-cluster
Follow along with this simple Kubernetes vagrant setup.
30. apiVersion: v1
kind: ReplicationController
# Metadata about the controller
metadata:
name: blog-controller
labels:
name: blog-controller
spec:
replicas: 2
# The labels of pods to be monitored
selector:
name: blog-pod
# Template newly created pods follow
template:
metadata:
# Match the controller selector at minimum
labels:
name: blog-pod
spec:
containers:
- name: blog-container
image: quay.io/kelcecil/kelcecil-com:latest
# containerPort is port in use inside container
ports:
- containerPort: 80
Create a new replication controller
blog.yaml
31. Create a new replication controller (2/2)
# Set your KUBERNETES_MASTER to your API Server
# Alternatively, use the -s flag with kubectl
export KUBERNETES_MASTER="http://127.0.0.1:8080"
kubectl create -f blog.yaml
In your terminal...
32. Get a list of replication controllers and pods
kelcecil@Kels-MBP ~/c/kube-talk> kubectl get rc
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLIC
blog-controller blog-container quay.io/kelcecil/kelcecil-com:latest name=blog-pod 2
kelcecil@Kels-MBP ~/c/kube-talk> kubectl get pods
NAME READY STATUS RESTARTS AGE
blog-controller-0g7ng 1/1 Running 0 1m
blog-controller-a6729 1/1 Running 0 1m
# You can use kubectl get with any Kubernetes resource
# kubectl get <resource>
# kubectl get nodes
# kubectl get services
33. kelcecil@Kels-MBP ~/c/kube-talk> kubectl describe pod blog-controller-0g7ng
Name: blog-controller-0g7ng
Namespace: default
Image(s): quay.io/kelcecil/kelcecil-com:latest
Node: 172.17.8.102/172.17.8.102
Labels: name=blog-pod
Status: Running
Reason:
Message:
IP: 10.244.35.4
Replication Controllers: blog-controller (2/2 replicas created)
Containers:
blog-container:
Image: quay.io/kelcecil/kelcecil-com:latest
State: Running
Started: Tue, 29 Sep 2015 20:44:37 -0400
Ready: True
Restart Count: 0
......
......
......
Get information about a particular pod
kubectl describe also works for any Kubernetes resource
34. kelcecil@Kels-MBP ~/c/kube-talk> kubectl describe node 172.17.8.102
Name: 172.17.8.102
Labels: kubernetes.io/hostname=172.17.8.102
CreationTimestamp: Sun, 13 Sep 2015 15:53:52 -0400
Conditions:
Type Status LastHeartbeatTime LastTransitionTime
Ready True Sun, 13 Sep 2015 16:55:16 -0400 Sun, 13 Sep 2015 15:53:52 -0400
Addresses: 172.17.8.102
Capacity:
memory: 2053532Ki
pods: 40
cpu: 1
Version:
Kernel Version: 4.1.6-coreos-r2
OS Image: CoreOS 801.0.0
Container Runtime Version: docker://1.8.1
Kubelet Version: v1.0.3
Kube-Proxy Version: v1.0.3
ExternalID: 172.17.8.102
Pods: (1 in total)
Namespace Name
default blog-lmj3c
No events.
Get system information about a node
kelcecil@Kels-MBP ~/c/kube-talk> kubectl get nodes
NAME LABELS STATUS
172.17.8.102 kubernetes.io/hostname=172.17.8.102 Ready
172.17.8.103 kubernetes.io/hostname=172.17.8.103 Ready
35. Create a label
kelcecil@Kels-MBP ~/c/kube-talk> kubectl label node 172.17.8.102 region=us-east-1
NAME LABELS STATUS
172.17.8.102 kubernetes.io/hostname=172.17.8.102,region=us-east-1 Ready
kelcecil@Kels-MBP ~/c/kube-talk> kubectl get nodes
NAME LABELS STATUS
172.17.8.102 kubernetes.io/hostname=172.17.8.102,region=us-east-1 Ready
172.17.8.103 kubernetes.io/hostname=172.17.8.103 Ready
kelcecil@Kels-MBP ~/c/kube-talk> kubectl get -l region=us-east-1 nodes
NAME LABELS STATUS
172.17.8.102 kubernetes.io/hostname=172.17.8.102,region=us-east-1 Ready
Filter resources by label
Remove a label
kelcecil@Kels-MBP ~/c/kube-talk> kubectl label node 172.17.8.102 region-
NAME LABELS STATUS
172.17.8.102 kubernetes.io/hostname=172.17.8.102 Ready
36. Scale a Replication Controller to 3 Replicas
kelcecil@Kels-MBP ~/c/kube-talk> kubectl get pods
NAME READY STATUS RESTARTS AGE
blog-controller-0g7ng 1/1 Running 0 3m
blog-controller-a6729 1/1 Running 0 3m
kelcecil@Kels-MBP ~/c/kube-talk> kubectl scale --replicas=3 rc blog-controller
scaled
kelcecil@Kels-MBP ~/c/kube-talk> kubectl get pods
NAME READY STATUS RESTARTS AGE
blog-controller-0g7ng 1/1 Running 0 3m
blog-controller-a6729 1/1 Running 0 3m
blog-controller-sems7 1/1 Running 0 18s
37. Get logs from a pod
> kubectl logs blog-controller-0g7ng
2015/09/14 03:07:32 [notice] 12#0: using the "epoll" event method
2015/09/14 03:07:32 [notice] 12#0: nginx/1.8.0
2015/09/14 03:07:32 [notice] 12#0: OS: Linux 4.1.6-coreos-r2
2015/09/14 03:07:32 [notice] 12#0: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2015/09/14 03:07:32 [notice] 12#0: start worker processes
2015/09/14 03:07:32 [notice] 12#0: start worker process 13
38. Executing a command inside a pod/container
> kubectl exec blog-controller-0g7ng "ps"
PID USER TIME COMMAND
1 root 0:00 /bin/sh -c nginx
12 root 0:00 nginx: master process nginx
13 nginx 0:00 nginx: worker process
82 root 0:00 ps
Interact with a shell inside a container
> kubectl exec -it blog-controller-0g7ng "sh"
/ # ps ax
PID USER TIME COMMAND
1 root 0:00 /bin/sh -c nginx
12 root 0:00 nginx: master process nginx
13 nginx 0:00 nginx: worker process
98 root 0:00 sh
103 root 0:00 ps ax
/ # exit
39. apiVersion: v1
kind: Service
# Metadata about the service
metadata:
name: blog-service
labels:
name: blog-service
spec:
# Open a port on nodes using kube-proxy
type: NodePort
ports:
# the port the container serves on
- port: 80
# Match the labels for pods to be served
selector:
name: blog-pod
Create a new service
blog-service.yaml
# Set your KUBERNETES_MASTER to your API Server
export KUBERNETES_MASTER="http://127.0.0.1:8080"
kubectl create -f blog-service.yaml
In your terminal...
40. Perform a rolling update on a container
> kubectl rolling-update --image=quay.io/kelcecil/kelcecil-com:talks blog-controller
Creating blog-controller-676be42f24a573bf0ee7733377bd5ea8
At beginning of loop: blog-controller replicas: 1, blog-controller-676be42f24a573bf0ee7733377bd5ea
Updating blog-controller replicas: 1, blog-controller-676be42f24a573bf0ee7733377bd5ea8 replicas: 1
At end of loop: blog-controller replicas: 1, blog-controller-676be42f24a573bf0ee7733377bd5ea8 repl
At beginning of loop: blog-controller replicas: 0, blog-controller-676be42f24a573bf0ee7733377bd5ea
Updating blog-controller replicas: 0, blog-controller-676be42f24a573bf0ee7733377bd5ea8 replicas: 2
At end of loop: blog-controller replicas: 0, blog-controller-676be42f24a573bf0ee7733377bd5ea8 repl
Update succeeded. Deleting old controller: blog-controller
Renaming blog-controller-676be42f24a573bf0ee7733377bd5ea8 to blog-controller
blog-controller