Kubespeak

I'd hereby like to elaborate on my previous post about what Kubernetes was - to be more precise, on the specific manner of talking to it in a language the cluster understands. In doing so I'll make statements and do my best to explain them.


Kubernetes consumes instructions from structured data serialized as JSON via its RESTful API. Such an instruction, however, is usually composed in the slightly more human-friendly notation of YAML. For the sake of completeness I'll note it could well be produced as JSON and work the same way, but it usually isn't - as YAML is easier on the eye as well as the mind, documentation will normally be presented as such and is best followed suit. (Clients shall abstract this nuance and talk JSON to the API nevertheless.)

Kubernetes thinks in resources and objects. Whatever you'd like to end up having, you'll need to conceive it as resources to create and manage, exposed by a set of APIs - an instance of your application will ultimately be represented by an object as well as the storage it consumes or the network policies that apply to it. There is a set of predefined resources in the box to be used as building blocks. (This collection is extensible - more on this later.)

Kubernetes usage follows a declarative pattern. As opposed to a traditional imperative approach with turn-by-turn instructions for a system to follow, here you need to define your desired state and let the system converge. (This paradigm shift is well represented by the difference in shell scripting and configuration management as an example.)

Consequently the way of defining an application in Kubernetes is providing a set of resource definitions. (Strictly speaking, resources are the actual API endpoints while objects are the results of having resource instances defined. That said, even official documentation appears to treat these terms with levity, somewhat interchangeably.) These definitions are bundled in manifests. A manifest may be split into multiple files, or a single manifest can hold all your resource templates. Hang on for a second - manifests contain templates and not actual objects.  Indeed, the latter shall be created by the cluster based on the templates supplied. (You may think of them as instantiated classes, if you like.) Objects have unique identifiers and references as well as a status in immutable fields managed by the cluster exclusively, whereas templates contain mere definitions.

Manifests may be produced programmatically i.e. generated, and in an ideal world you won't write them manually. They will either be compiled by your IDE or package manager (dare I say more on that later?) or generated via code authored in a domain-specific language. In addition, all the usual techniques of development like linting and static analysis apply. That said you'll still need to achieve reading fluency at the very least. I believe you will inevitably learn to actually write those you work the most with by heart. Please note: Kubernetes manifests - like all code - should be kept under version control.

Here we are, wound up with a set of files containing formatted text adhering to the specifications of a markup language. In order to see something really happen, these must be fed to the Kubernetes API. (Initially you will most likely employ the official CLI named "kubectl".) Regardless of the tooling of choice - be that an IDE, a custom client based on the SDK or cURL - the submitted request shall be subject to authentication, authorization and admission control (often referred to as "triple-A") unless you're allowed to bypass these and it's safe to assume that you're not as that's an administrative privilege.

Authentication and authorization mean that you need to be entitled to talk to Kubernetes - it needs to know who you are so you have to prove your identity - and you also need to be entitled to doing whatever you're asking it to do for you. Admission control is about digesting your request and optionally denying or altering it in spite of your entitlement, solely based on policies pertaining to requirements imposed on resources by the cluster.

A request actually admitted by the cluster shall produce a so-called "record of intent" in the form an API object. This does not mean that everything is as you wanted it to be, but is the first step towards that goal and the cluster will now perform the tasks required in order to converge its actual state to one that matches your description - circumstances may still prevent that from happening. (As tedious as that might sound by now: more on this later.)

Finally I need to say that not all operations require manifests - those relating to administration instead of development are generally imperative. Furthermore, quite some cases support both approaches and imperative operations might also have merit in certain situations. As a rule of thumb, though, development and deployment shall involve a measure of coding in addition to or instead of executing one-off commands.

Stay tuned, there's more where this came from - I intend to keep going in the same vein.