Kubernetes Learning Note (ii)

E.Y.
5 min readAug 9, 2020

--

Photo by Cameron Venti on Unsplash

There are two ways to set up your k8s cluster up and running, declarative and imperative. In this blog, we are focusing on how to using YAML file to set up k8s containers declaratively. And for imperatively we do it through kubectl in next blog.

YAML is a human-readable text-based format for specifying configuration-type information. YAML is a superset of JSON, which means that any valid JSON file is also a valid YAML file. In the context of k8s, we mainly use two data structures of YAML: list and map.

YAML lists are literally a sequence of objects. For example:

YAML list
ports:
- containerPort: 5432
//in json
{
"ports": ["containerPort":"5432"]
}
YAML map (map the key-value pairs)apiVersion: apps/v1
kind: Deployment

Kubernetes objects

Kubernetes objects are persistent entities in the Kubernetes system. Specifically, they can describe:

  • What containerized applications are running (and on which nodes)
  • The resources available to those applications
  • The policies around how those applications behave, such as restart policies, upgrades, and fault-tolerance

Object Spec and Status

Almost every Kubernetes object includes two nested object fields that govern the object’s configuration: the object spec and the object status. For objects that have a spec, you have to set this when you create the object. The status describes the current state of the object, supplied and updated by the Kubernetes and its components. The Kubernetes control plane continually and actively manages every object’s actual state to match the desired state you supplied.

Required Fields

In the .yaml file for the Kubernetes object you want to create, you’ll need to set values for the following fields:

  • apiVersion - Which version of the Kubernetes API you’re using to create this object
  • kind - What kind of object you want to create
  • metadata - Data that helps uniquely identify the object, including a name string, UID, and optional namespace
  • spec - What state you desire for the object.

Pod, Deployment and Service

  • A Pod is the most basic unit that Kubernetes deals with. It wraps containers inside it. Containers inside a pod containers share a life cycle, and their environment, volumes, and IP space. Usually, pods consist of a primary container and optionally some support containers.
  • A Deployment is an object that lets you manage a set of identical pods using Replication sets. It eases the life cycle management of replicated pods. Deployments can be modified easily by changing the configuration and Kubernetes will adjust accordingly.
  • a Service defines a logical set of Pods and a policy by which to access them. A service’s IP address remains stable regardless of changes to the pods it routes to. Any time you need to provide access to one or more pods to another application or to external consumers, you should configure a service. Although services, by default, are only available using an internally routable IP address, they can be made available outside of the cluster by choosing one of several strategies.

A Pod is the smallest unit of work which can be scheduled in Kubernetes. A Pod encapsulates an application containers, storage resources, unique network IP. Normally, higher level abstractions are used to deploy pods such as Deployments, Replica Sets, Daemon Sets, Stateful Sets, or Jobs.

Now let’s use some examples to look into how these objects work.

//client-pod.yml
apiVersion: v1
kind: Pod
metadata:
name: client-pod
labels:
component: web
spec:
containers:
- name: client
image: elfiy/multi-worker
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: 3000
//client-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: client-deployment
spec:
replicas: 1
selector:
matchLabels:
component: web
template:
metadata:
labels:
component: web
spec:
containers:
- name: client
image: stephengrider/multi-client
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: 3000
//client-node-port.yml
apiVersion: v1
kind: Service
metadata:
name: client-node-port
spec:
selector:
component: web
type: NodePort
ports:
- port: 3050
targetPort: 3000
nodePort: 31515

There are some keys worth mentioning from above:

  • apiVersion:Which version of the Kubernetes API you’re using to create this object.
  • Metadata: The metadata contains information of the object. The information in the metadata usually contains the name you want to give the object , the labels, and the annotation.
  • Spec: is about the desired status of our object.
  • Container: Here you specify:the name of the container that you’ll run in your pod (client in our first example); the image of the application you want to run in your pods (elfiy/multi-worker); the containerPort is the port your application in your container is listening to (3000).

You may notice there are some differences in each object, for example in Deployment yml, we have something extra:

  • Replicas sets the number of instances of the pod that the deployment should run.
  • Label selector is to match the pods to the deployment. This is equivalent of “all the pods matching these labels are included in the deployment.” (in our case it’s the pod with name “web”)
  • Template is added by the deployment controller to every ReplicaSet that a Deployment creates or adopts. It is just a pod spec. When the deployment creates pods, it will create them using this template.

Lastly on the Service object, notice the 3 different ports:

  • ClusterIP (default) — Exposes the Service on an internal IP in the cluster. This type makes the Service only reachable from within the cluster. There may be other pods that need access to this pod.(3050)
  • NodePort — Exposes the Service on the same port of each selected Node in the cluster using NAT. Makes a Service accessible from outside the cluster using <NodeIP>:<NodePort>.(31515) Note that if we go to localhost:31515 we won’t get anything. Since k8s has a VM and we need the IP assigns to this VM instead using
$minikube ip 
192.168.64.2
So visit to go to http://192.168.64.2/31515
  • TargetPort — This is the port on the pod that the request gets sent to. (3000)
  • Additionally, note that there are some use cases with Services that involve not defining selector in the spec. A Service created without selector will also not create the corresponding Endpoints object. This allows users to manually map a Service to specific endpoints. Apart from these ports, there’s also Loadbalancer port and Ingress which we will touch later.
architecture illustrated

Cool. That’s so much of it! Happy Reading!

🛥 🚤 ⛴ 🛳 ⛵ ⚓️ 🌊🛥 🚤 ⛴ 🛳 ⛵ ⚓️ 🌊🛥 🚤 ⛴ 🛳 ⛵ ⚓️ 🌊🛥 🚤 ⛴ 🛳 ⛵ ⚓️ 🌊🛥 🚤 ⛴ 🛳 ⛵ ⚓️ 🌊🛥 🚤 ⛴ 🛳 ⛵ ⚓️ 🌊🛥 🚤 ⛴ 🛳 ⛵ ⚓️ 🌊🚤

--

--

No responses yet