======================== Certified k8s Admin Prep ======================== Sections ======== - 25% cluster architecture, installation and configuration - 15% workloads and scheduling - 20% servicing and networking - 10% storage - 30% troubleshooting K8s in a Nutshell ================= K8s is a container orchestration tool. Today there are a lot of microservices architectures. We can have a container per service and managing all those containers can be hard. K8s takes care of teh scalability, security, persistence and load balancing. When k8s is triggered to create a container, it will delegate it to the container runtime engine via a CRI (container runtime interface) Features -------- - Declarative Model - the cool thing about k8s, is that you just tell it the status of the cluster you want, via yamls, and it will do its best to create it. - Autoscaling - k8s can also automatically (or manually) scale resources when needed. - Application management - When deploying new versions for your application, you can use k8s to manage the roll out technique. As well as come back to previous rollouts - Persistent Storage - Containers are ephemeral, meaning the filesystem in them will die with them. With k8s you can have persistent volumes, to manage storage across containers. - Networking - k8s has internal and external load balancing for network traffic. High-Level Architecture ----------------------- There are two types of nodes (these can be vm, baremetal machines, whatever you call a computer), two types of nodes: - control plane nodes - this node exposes k8s API thru a server. Whenever you do `kubectl something` you are talking to this API. - worker nodes - this are the nodes that execute the workload in containers manged by pods. - worth to say that every worker node needs a container runtime engine, to create the containers. Control Plane Nodes ------------------- These have different components to do their job: * API Server - Exposes the k8s api to clients (kubectl) - Here is where the authentication, authorization and admission control also happens. * Scheduler - Background process that watches for new k8s pods with no assigned and look for a node to execute them. * Control Manager - Watches the state of your clusters and implements changes where needed. - This is the guy that makes the cluster be to its desired state. * Etcd - key-value db that stores all k8s cluster related data. Components Shared by Nodes -------------------------- There are some components that are shared by the nodes, whether they are control or workers. * Kubelet - agent that makes sure the necessary containers are running in a pod. - this is the glue between k8s and the container runtime engine. * Kube Proxy - every node has this network proxy to enable network communication and implement their rules. * Container runtime - the container runtime that will manage the containers. Not really needed in control planes. Advantages on Using k8s ----------------------- * Portability - the container runtime engine can run stuff regardless of whether you run it on a vm, bm or even on a raspberry. So you have portability for your things regardless of where the cluster is located. * Resilience - controllers are always looking to be on the desired state. Meaning it will try to self-heal when something goes array. * Scalability - k8s can scale the number of pods on demand or automatically * Extensibility - When the core functionality is not enough you can introduce CRDs that extend the functionality of the cluster. Interacting with K8s ==================== API Primitives and Objects -------------------------- K8s has api resources which are the building blocks of the cluster. These are your pods, deployments, services, and so on. Every k8s primitive follows a general structure: - api version: - defines the structure of a primitive and uses it to validate the correctness of the data. - you can do `k api-versions` to see the versions compatible with your cluster - kind - the type of the primitive - metadata - name, namespace, high level info - here you see the UID, which is an id k8s generates for each object. - spec - the desired state of the resource - status - actual state of the resource kubectl ------- This is how we talk to the api. Usually you do: ``` k ``` Keep in mind we usually have different stuff in different namespaces, so we are always appending `-n ` to the command. The name of an object has to be unique across all objects of the same resource within a namespace. Managing Objects ---------------- There are two ways to manage objects the imperative or the declarative way. Imperative --- The imperative is where you use commands to make stuff happen in the cluster, say you want to create an nginx pod you would do: ``` k run --image=nginx:latest nginx --port=80 ``` This would create the pod in the cluster when you hit enter. In my professional experience, you hardly ever create stuff like that. The only time I use it is to create temporary pods to test something. There are other verbs which you might use a bit more, `edit` brings up the raw config of the resource and you can change it in the fly. Although I would recommend just do this for testing things. Hopefully your team has the manifests under a version control system, if you edit stuff like this it would mess it up. There is also `patch` which I have never used, but it... > Update fields of a resource using strategic merge patch, a JSON merge patch, > or a JSON patch. There is also `delete` which -- as you probably guess already -- deletes the resource. Usually the object gets a 30 sec grace period for it to die. But if it does not the kubelet will try to kill it forcefully. If you do ``` k delete pod nginx --now ``` It will ignore the grace period. Declarative --- This is where you have a bunch of `yaml`s which your definitions of resources, the cool thing about this is that you can version control them. Say you have a `nginx-deploy.yaml`. You can create it in the cluster with: ``` k apply -f nginx-deploy.yaml ``` This gives you more flexibility on what you are doing. Since you can just go to the file change stuff and apply it again. Hybrid --- Usually I use a hybrid approach, most of the imperative commands have this `--dry-run=client -o yaml` flag that you can append to to the command and it will render the yaml manifest. You can redirect that to a file and start working on that. You open the yaml with your favourite text editor, and then mount volumes and stuff like that. There are more ways to manage the resources for example you can use kustomize to render different values based on the same manifest, or with helm to bring up complete apps/releases to just cluster. Probably we will go over them later in the book. Cluster Installation and Upgrade ================================