This supersedes #399. There was a bug in Kubernetes 1.12. It was fixed in 1.13. Let's just mention the issue in one brief slide but not add too much extra fluff about it.
7.7 KiB
Running our first containers on Kubernetes
- First things first: we cannot run a container
--
- We are going to run a pod, and in that pod there will be a single container
--
-
In that container in the pod, we are going to run a simple
pingcommand -
Then we are going to start additional copies of the pod
Starting a simple pod with kubectl run
- We need to specify at least a name and the image we want to use
.exercise[
- Let's ping
1.1.1.1, Cloudflare's public DNS resolver:kubectl run pingpong --image alpine ping 1.1.1.1
]
--
(Starting with Kubernetes 1.12, we get a message telling us that
kubectl run is deprecated. Let's ignore it for now.)
Behind the scenes of kubectl run
- Let's look at the resources that were created by
kubectl run
.exercise[
- List most resource types:
kubectl get all
]
--
We should see the following things:
deployment.apps/pingpong(the deployment that we just created)replicaset.apps/pingpong-xxxxxxxxxx(a replica set created by the deployment)pod/pingpong-xxxxxxxxxx-yyyyy(a pod created by the replica set)
Note: as of 1.10.1, resource types are displayed in more detail.
What are these different things?
-
A deployment is a high-level construct
-
allows scaling, rolling updates, rollbacks
-
multiple deployments can be used together to implement a canary deployment
-
delegates pods management to replica sets
-
-
A replica set is a low-level construct
-
makes sure that a given number of identical pods are running
-
allows scaling
-
rarely used directly
-
-
A replication controller is the (deprecated) predecessor of a replica set
Our pingpong deployment
kubectl runcreated a deployment,deployment.apps/pingpong
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deployment.apps/pingpong 1 1 1 1 10m
- That deployment created a replica set,
replicaset.apps/pingpong-xxxxxxxxxx
NAME DESIRED CURRENT READY AGE
replicaset.apps/pingpong-7c8bbcd9bc 1 1 1 10m
- That replica set created a pod,
pod/pingpong-xxxxxxxxxx-yyyyy
NAME READY STATUS RESTARTS AGE
pod/pingpong-7c8bbcd9bc-6c9qz 1/1 Running 0 10m
-
We'll see later how these folks play together for:
- scaling, high availability, rolling updates
Viewing container output
-
Let's use the
kubectl logscommand -
We will pass either a pod name, or a type/name
(E.g. if we specify a deployment or replica set, it will get the first pod in it)
-
Unless specified otherwise, it will only show logs of the first container in the pod
(Good thing there's only one in ours!)
.exercise[
- View the result of our
pingcommand:kubectl logs deploy/pingpong
]
Streaming logs in real time
-
Just like
docker logs,kubectl logssupports convenient options:-
-f/--followto stream logs in real time (à latail -f) -
--tailto indicate how many lines you want to see (from the end) -
--sinceto get logs only after a given timestamp
-
.exercise[
- View the latest logs of our
pingcommand:kubectl logs deploy/pingpong --tail 1 --follow
]
Scaling our application
- We can create additional copies of our container (I mean, our pod) with
kubectl scale
.exercise[
-
Scale our
pingpongdeployment:kubectl scale deploy/pingpong --replicas 8 -
Note that this command does exactly the same thing:
kubectl scale deployment pingpong --replicas 8
]
Note: what if we tried to scale replicaset.apps/pingpong-xxxxxxxxxx?
We could! But the deployment would notice it right away, and scale back to the initial level.
Resilience
-
The deployment
pingpongwatches its replica set -
The replica set ensures that the right number of pods are running
-
What happens if pods disappear?
.exercise[
- In a separate window, list pods, and keep watching them:
kubectl get pods -w
- Destroy a pod:
kubectl delete pod pingpong-xxxxxxxxxx-yyyyy
]
What if we wanted something different?
-
What if we wanted to start a "one-shot" container that doesn't get restarted?
-
We could use
kubectl run --restart=OnFailureorkubectl run --restart=Never -
These commands would create jobs or pods instead of deployments
-
Under the hood,
kubectl runinvokes "generators" to create resource descriptions -
We could also write these resource descriptions ourselves (typically in YAML),
and create them on the cluster withkubectl apply -f(discussed later) -
With
kubectl run --schedule=..., we can also create cronjobs
What about that deprecation warning?
-
As we can see from the previous slide,
kubectl runcan do many things -
The exact type of resource created is not obvious
-
To make things more explicit, it is better to use
kubectl create:-
kubectl create deploymentto create a deployment -
kubectl create jobto create a job
-
-
Eventually,
kubectl runwill be used only to start one-shot pods
Various ways of creating resources
-
kubectl run- easy way to get started
- versatile
-
kubectl create <resource>- explicit, but lacks some features
- can't create a CronJob
- can't pass command-line arguments to deployments
-
kubectl create -f foo.yamlorkubectl apply -f foo.yaml- all features are available
- requires writing YAML
Viewing logs of multiple pods
-
When we specify a deployment name, only one single pod's logs are shown
-
We can view the logs of multiple pods by specifying a selector
-
A selector is a logic expression using labels
-
Conveniently, when you
kubectl run somename, the associated objects have arun=somenamelabel
.exercise[
- View the last line of log from all pods with the
run=pingponglabel:kubectl logs -l run=pingpong --tail 1
]
Unfortunately, --follow cannot (yet) be used to stream the logs from multiple containers.
class: extra-details
kubectl logs -l ... --tail N
-
If we run this with Kubernetes 1.12, the last command shows multiple lines
-
This is a regression when
--tailis used together with-l/--selector -
It always shows the last 10 lines of output for each container
(instead of the number of lines specified on the command line)
-
The problem was fixed in Kubernetes 1.13
See #70554 for details.
Aren't we flooding 1.1.1.1?
-
If you're wondering this, good question!
-
Don't worry, though:
APNIC's research group held the IP addresses 1.1.1.1 and 1.0.0.1. While the addresses were valid, so many people had entered them into various random systems that they were continuously overwhelmed by a flood of garbage traffic. APNIC wanted to study this garbage traffic but any time they'd tried to announce the IPs, the flood would overwhelm any conventional network.
-
It's very unlikely that our concerted pings manage to produce even a modest blip at Cloudflare's NOC!