Understand Kubernetes 2: Operation Model

In the last article, we focus on the components in the work nodes. In this one, we'll switch our focus to the user and the component in master node.

Operation Model

From user's perspective, the model is quite simple: User declare a State he wants the system to be in, and then it is k8s's job to achieve that.
User send the Resouces and Operation to the k8s using the REST API, which is served by the API server inside of the master node, the request will be put into a stateStore (implemented using etcd). According to the type of resource, different Controllers will be delegated to do the job.
The exact Operations available depend on the Resource type, but most the case, it means CRUD. For create operation, there is a Specification define the attribute of the resource wanted to be created.
Here are two examples:
  • create a Pod, according to a Pod spec.
  • create a Deployment called mypetstore, according to ta Deployment spec.
  • update the mypetstore deployment with a new container image.
Each Resource (also called Object) has three pieces of information: Spec, Status and Metadata, and those are saved in the stateStore.
  • Spec is specified by the user for resource creation and update; it is desired state of the resource.
  • Status is updated by the k8s system and queried by the user; it is the actual state of the resource.
  • Metadata is partly specified by the user and can be updated by the k8s system; it is the label of the resource.
The class diagram looks like this:
ResourceSpec : create by userStatus : updated by k8s systemMetadata : may be updated by bothControllerCreate() : ResourceUpdate(Resource)Delete(Resource)GetStatus(Resource)CustomizedOps(Resource)K8sUseruse1ncontrols(CRUD)defines Spec, provides Metadata

Sequence Diagram:

Let's see how what really happens when you typing kubectl create -f deployment/spec.yaml:
UserUserkubectlkubectlAPI ServerAPI ServerStateStoreStateStoreControllerControllerWorkNodesWorkNodescreate spec.yamlkubectl turn it to REST callPost xxx/deploymentssave the specunblocked by new stateok (async)ok (async)do stuff to achieve the new stateok (async)update some new information (e.g pod & nodes binding)unblock by new state and do stuffdo stuff to achive the state

API

k8s cluster is managed and accessed from predefined APIkubectl is a client of the API, it converts the shell command to the REST call, as shown in above sequence diagram.
You can build your own tools using those APIs to add functionality that are currently not available. Since API is versioned and stable, it makes sure your tool are portable.
Portability and extensibility are the most important benefits k8s brings. In another word, k8s is awesome not only because it does awesome things itself but enables you and others build awesome things on top of it.

Controllers

Controller is to make sure the actual state of the object matches the desired state.
The idea of matching the actual state to the desired state is the driving philosophy of k8s's design. It doesn't sound quite novel given most declarative tools follow the same idea. For example, both Terraform and Ansible are declarative. The things k8s is different is it keep monitoring the system status and make sure the desired status is always kept. And that means all the goodness of availability and scalability are built-in in k8s.
The desired state is defined using a Spec, and that is the stuff user will interact with. It is k8s's job to do whatever you requested.
The most common specs are:
  • Deployments for stateless persistent apps (e.g. http servers)
  • StatefulSets for stateful persistent apps (e.g. databases)
  • Jobs for run-to-completion apps (e.g. batch jobs).
Let's take a close look at the Deployments Spec.

Deployment Spec

Below is the deployment spec that can be used to create a deployment of nginx server with 3 replicas, each of which use nginx:1.7.9 as the container image and application will listen on 80 port.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
This should be simple to understand. Compared with a simple Pod/Container specification,it has an extra replica field. The kind is set as Deployment so that a right Controller will be able to pick it up.
Lots of specs will have a nested PodSpec, as shown below, since at the end of the day, k8s is a Pod/Container management system.
Deplyment Controller and Speck8s (master)cluster (work nodes)specDeploymentControllerspec : DeloymentSpecstatus: DeloymentStatusControllerPodKindMetadataSpec : PodSpecStatus : PodStatusSpecKindMetadataDeloymentSpecreplicas: intselector: LabelSelectorstrategy: DeloymentStrategytemplate: PodTemplateSpecPodTemplateSpecMetadataSpec: PodSpecPodSpecContainers: []ContainerVolumes : []Volumecreate/update/monitor$.specuseembed$.template$.spec
For a complete reference of the field available for deployment spec, you can check here.

Summary

In this article, we looked at the components of Master node and the overall operation Model of k8s: drive and maintainer the actual state of the system to be same as the desired state as specified by the user through various object specification. In particular, we took a close look at most used deployment spec.