From abcc47b56395ee2ce765a10b83d3beba1c0f8d89 Mon Sep 17 00:00:00 2001 From: Jerome Petazzoni Date: Wed, 28 Nov 2018 01:29:40 +0100 Subject: [PATCH] Add a section about static pods This was a request by @abuisine, so I'm flagging him for review :-) This section explains the challenges associated with self-hosting the control plane; and segues into static pods. It also mentions bootkube and the Pod Checkpointer. There is an exercise showing how to run a static pod. --- k8s/just-a-pod.yaml | 10 ++ slides/k8s/staticpods.md | 218 ++++++++++++++++++++++++++++++++++++++ slides/kube-selfpaced.yml | 1 + 3 files changed, 229 insertions(+) create mode 100644 k8s/just-a-pod.yaml create mode 100644 slides/k8s/staticpods.md diff --git a/k8s/just-a-pod.yaml b/k8s/just-a-pod.yaml new file mode 100644 index 00000000..346525de --- /dev/null +++ b/k8s/just-a-pod.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +Kind: Pod +metadata: + name: hello + namespace: default +spec: + containers: + - name: hello + image: nginx + diff --git a/slides/k8s/staticpods.md b/slides/k8s/staticpods.md new file mode 100644 index 00000000..a65f2f34 --- /dev/null +++ b/slides/k8s/staticpods.md @@ -0,0 +1,218 @@ +# Static pods + +- Pods are usually created indirectly, through another resource: + + Deployment, Daemon Set, Job, Stateful Set ... + +- They can also be created directly + +- This can be done by writing YAML and using `kubectl apply` or `kubectl create` + +- Some resources (not all of them) can be created with `kubectl run` + +- Creating a resource with `kubectl` requires the API to be up + +- If we want to run the API server (and its dependencies) on Kubernetes itself ... + + ... how can we create API pods (and other resources) when the API is not up yet? + +--- + +## In theory + +- Each component of the control plane can be replicated + +- We could set up the control plane outside of the cluster + +- Then, once the cluster is up, create replicas running on the cluster + +- Finally, remove the replicas that are running outside of the cluster + +*What could possibly go wrong?* + +--- + +## Sawing off the branch you're sitting on + +- What if anything goes wrong? + + (During the setup or at a later point) + +- Worst case scenario, we might need to: + + - set up a new control plane (outside of the cluster) + + - restore a backup from the old control plane + + - move the new control plane to the cluster (again) + +- This doesn't sound like a great experience + +--- + +## Static pods to the rescue + +- Pods are started by kubelet (an agent running on every node) + +- To know which pods it should run, the kubelet queries the API server + +- The kubelet can also get a list of *static pods* from: + + - a directory containing one (or multiple) *manifests*, and/or + + - a URL (serving a *manifest*) + +- These "manifests" are basically YAML definitions + + (As produced by `kubectl get pod my-little-pod -o yaml --export`) + +--- + +## Static pods are dynamic + +- Kubelet will periodically reload the manifests + +- It will start/stop pods accordingly + + (i.e. it is not necessary to restart the kubelet after updating the manifests) + +- When connected to the Kubernetes API, the kubelet will create *mirror pods* + +- Mirror pods are copies of the static pods + + (so they can be seen with e.g. `kubectl get pods`) + +--- + +## Bootstrapping a cluster with static pods + +- We can run control plane components with these static pods + +- They don't need the API to be up (just the kubelet) + +- Once they are up, the API becomes available + +- These pods are then visible through the API + + (We cannot upgrade them from the API, though) + +*This is how kubeadm has initialized our clusters.* + +--- + +## Static pods vs normal pods + +- The API only gives us a read-only access to static pods + +- We can `kubectl delete` a static pod ... + + ... But the kubelet will restart it immediately + +- Static pods can be selected just like other pods + + (So they can receive service traffic) + +- A service can select a mixture of static and other pods + +--- + +## From static pods to normal pods + +- Once the control plane is up and running, it can be used to create normal pods + +- We can then set up a copy of the control plane in normal pods + +- Then the static pods can be removed + +- The scheduler and the controller manager use leader election + + (Only one is active at a time; removing an instance is seamless) + +- Each instance of the API server adds itself to the `kubernetes` service + +- Etcd will typically require more work! + +--- + +## From normal pods back to static pods + +- Alright, but what if the control plane is down and we need to fix it? + +- We restart it using static pods! + +- This can be done automatically with the [Pod Checkpointer] + +- The Pod Checkpointer automatically generates manifests of running pods + +- The manifests are used to restart these pods if API contact is lost + + (More details in the [Pod Checkpointer] documentation page) + +- This technique is used by [bootkube] + +[Pod Checkpointer]: https://github.com/kubernetes-incubator/bootkube/blob/master/cmd/checkpoint/README.md +[bootkube]: https://github.com/kubernetes-incubator/bootkube + +--- + +## Static pods in action + +- On our clusters, the `staticPodPath` is `/etc/kubernetes/manifests` + +.exercise[ + +- Have a look at this directory: + ```bash + ls -l /etc/kubernetes/manifests + ``` + +] + +We should see YAML files corresponding to the pods of the control plane. + +--- + +## Running a static pod + +- We are going to add a pod manifest to the directory, and kubelet will run it + +.exercise[ + +- Copy a manifest to the directory: + ```bash + sudo cp ~/container.training/k8s/just-a-pod.yaml /etc/kubernetes/manifests + ``` + +- Check that it's running: + ```bash + kubectl get pods + ``` + +] + +The output should include a pod named `hello-node1`. + +--- + +## Remarks + +In the manifest, the pod was named `hello`. + +```yaml +apiVersion: v1 +Kind: Pod +metadata: + name: hello + namespace: default +spec: + containers: + - name: hello + image: nginx +``` + +The `-node1` suffix was added automatically by kubelet. + +If we delete the pod (with `kubectl delete`), it will be recreated immediately. + +To delete the pod, we need to delete (or move) the manifest file. + diff --git a/slides/kube-selfpaced.yml b/slides/kube-selfpaced.yml index 84da8835..5a162d5f 100644 --- a/slides/kube-selfpaced.yml +++ b/slides/kube-selfpaced.yml @@ -57,6 +57,7 @@ chapters: - - k8s/owners-and-dependents.md - k8s/statefulsets.md - k8s/portworx.md + - k8s/staticpods.md - - k8s/whatsnext.md - k8s/links.md - shared/thankyou.md