Deploying and Running Containers
Pod
A pod is a collection of containers (usually just single container) sharing a network and mount namespace and is the basic unit of deployment in Kubernetes. All containers in a pod are scheduled on the same node. Most of the time deployment
should be used instead. Often, init-containers
are part of the pod
.
Here is an example pod with 2 containers.
apiVersion: v1
kind: Pod
metadata:
name: twocontainers
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
- name: shell
image: centos:7
command:
- "bin/bash"
- "-c"
- "sleep 10000"
Replication Controller
A replication controller
(RC) is a supervisor for long-running pods. An RC will launch a specified number of pods
called replicas
and makes sure that they keep running, for example when a node fails or something inside of a pod, that is, in one of its containers goes wrong.
Note that, going forward, the RCs are called replica sets
(RS), supporting set-based selectors. The RS are already in use in the context of deployments
.
apiVersion: v1
kind: ReplicationController
metadata:
name: some-namespace
spec:
replicas: 1
selector:
app: sise
template:
metadata:
name: somename
labels:
app: sise
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
Deployment
A deployment is a supervisor for pods and replica sets, giving you fine-grained control over how and when a new pod version is rolled out as well as rolled back to a previous state.
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: myapp-deploy # Name of the deployment
spec:
replicas: 2 # Number of replicas (pods)
template:
metadata:
labels:
app: MyApp # Label all pods with "app: MyApp"
spec:
containers:
- name: myapp
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
env:
- name: SIMPLE_SERVICE_VERSION
value: "0.9"
Updating a Deployment
Rollout is triggered if and only if the Deployment’s pod template is changed:
- labels
- container image
# Edit deployment
kubectl edit deployment.v1.apps/nginx-deployment
# Get rollout status
kubectl rollout status deployment.v1.apps/nginx-deployment
# Describe the deployment
kubectl describe deployment nginx-deployment
Rolling Back a Deployment
Update
deployment. Append the --record
flag to save the kubectl
command that is making changes to the resource.
$ kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.91 --record=true
deployment.apps/nginx-deployment image updated
Check update/rollout
deployment (Can get stuck)
$ kubectl rollout status deployment.v1.apps/nginx-deployment
Waiting for rollout to finish: 1 out of 3 new replicas have been updated...
Get rollout history
. Use --revision=2
for more details.
kubectl rollout history deployment.v1.apps/nginx-deployment
Roll-back
to previous version
$ kubectl rollout undo deployment.v1.apps/nginx-deployment
deployment.apps/nginx-deployment
Alternatively, you can rollback
to a specific revision by specify that in --to-revision
$ kubectl rollout undo deployment.v1.apps/nginx-deployment --to-revision=2
deployment.apps/nginx-deployment
Pausing and Resuming a Deployment
Pause
by running the following command:
$ kubectl rollout pause deployment.v1.apps/nginx-deployment
deployment.apps/nginx-deployment paused
The initial state of the Deployment prior to pausing it will continue its function, but new updates to the Deployment will not have any effect as long as the Deployment is paused.
Eventually, resume
the Deployment and observe a new ReplicaSet coming up with all the new updates:
$ kubectl rollout resume deployment.v1.apps/nginx-deployment
deployment.apps/nginx-deployment resumed
Scaling a Deployment
You can scale
a Deployment by using the following command:
$ kubectl scale deployment.v1.apps/nginx-deployment --replicas=10
deployment.apps/nginx-deployment scaled
Assuming horizontal pod autoscaling
is enabled in your cluster, you can setup an autoscaler for your Deployment and choose the minimum
and maximum
number of Pods you want to run based on the CPU utilization of your existing Pods.
$ kubectl autoscale deployment.v1.apps/nginx-deployment --min=10 --max=15 --cpu-percent=80
deployment.apps/nginx-deployment scaled
DaemonSet
A DaemonSet
ensures that all (or some) Nodes
run a copy of a Pod
. As nodes are added to the cluster, Pods
are added to them. As nodes are removed from the cluster, those Pods
are garbage collected. Deleting a DaemonSet
will clean up the Pods
it created.
Some typical uses of a DaemonSet are:
- running a cluster storage daemon, such as
glusterd
,ceph
, on each node. - running a logs collection daemon on every node, such as
fluentd
orlogstash
.
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: frontend
spec:
updateStrategy: RollingUpdate # Update strategy
maxUnavailable: 1 # Max unavailable pods when updating
minReadySeconds: 0
template:
metadata:
labels:
app: frontend-webserver # All pods in DS will have label: "app: frontend-webserver"
spec:
nodeSelector:
app: frontend-node # Selects which nodes will run this DS
containers:
- name: webserver
image: nginx
ports:
- containerPort: 80
Starting in Kubernetes 1.6, you will be able to do rolling updates with Kubernetes DaemonSets. You’ll have to set the updateStrategy
.
Service
A Kubernetes Service is an abstraction which defines a logical set of Pods and a policy by which to access them - sometimes called a micro-service. The set of Pods targeted by a Service is (usually) determined by a Label Selector
This specification will create a new Service object named “my-service
” which targets TCP port 9376 on any Pod
with the "app=MyApp
" label. This Service will also be assigned an IP address (Cluster IP
).
kind: Service
apiVersion: v1
metadata:
name: my-service # Name of the service
spec:
selector:
app: MyApp # Service targets pods with "app: MyApp"
ports:
- protocol: TCP
port: 80
targetPort: 9376
Note that a Service
can map an incoming port to any targetPort
. By default the targetPort
will be set to the same value as the port
field. Perhaps more interesting is that targetPort
can be a string, referring to the name of a port in the backend Pods
. The actual port number assigned to that name can be different in each backend Pod
. This offers a lot of flexibility for deploying and evolving your Services. For example, you can change the port number that pods expose in the next version of your backend software, without breaking clients.
More about services in "Services & Ingress" section.
StatefulSet
Deployment - You specify a PersistentVolumeClaim that is shared by all pod replicas. In other words, shared volume.
The backing storage obviously must have ReadWriteMany or ReadOnlyMany accessMode if you have more than one replica pod.
StatefulSet - You specify a volumeClaimTemplates so that each replica pod gets a unique PersistentVolumeClaim associated with it. In other words, no shared volume.
Here, the backing storage can have ReadWriteOnce accessMode.
StatefulSet is useful for running things in cluster e.g Hadoop cluster, MySQL cluster, where each node has its own storage.
Metadata
Namespace
Namespaces
provide a scope of Kubernetes objects. You can think of it as a workspace you’re sharing with other users. Many objects such as pods and services are namespaced, while some (like nodes) are not. Can have access control or resource quotas.
apiVersion: v1
kind: Namespace
metadata:
name: test # Create namespace called "test"
Later K8s resources can be deployed to that namespace using metadata
. It will be hard coded so this pod will always deploy to that namespace.
apiVersion: v1
kind: Pod
metadata:
name: podintest
namespace: test # This pod will be deployed in "test" namespace
Labels
Labels
are the mechanism you use to organize Kubernetes objects. A label is a key-value pair with certain restrictions concerning length and allowed values but without any pre-defined meaning. So you’re free to choose labels as you see fit, for example, to express environments such as ‘this pod is running in production’ or ownership, like ‘department X owns that pod’.
apiVersion: v1
kind: Pod
metadata:
name: labelexother
labels:
env: production
owner: michael
app: MyApp
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
Annotations
Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not "queryable" and should be preserved when modifying objects.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ghost-ingress
annotations:
kubernetes.io/ingress.class: traefik # Use annotation to define, which ingress controller to use (Traefik)
spec:
rules:
- host: "ghost.tadone.pw"
http:
paths:
- path: /
backend:
serviceName: ghost-svc
servicePort: 80