Terminology and concepts
In order to keep things well organized, Kubernetes created the concept of Namespace. A namespace is basically a virtual cluster inside the actual cluster.
- Divide the cluster by team or project, to avoid naming conflict and help repartition of resources.
- Divide the cluster by environment (i.e. dev, staging, prod), to keep a consistent architecture.
- Deploy with more granularity (e.g. blue/green deployment), to quickly fall back on an untouched working environment in case of issue.
Definition files
Metadata and labels
name
and a namespace
(defaults to default
), thanks to which the control plane will automatically be able to tell if the file is a new addition to the cluster or the revision of a previously loaded file.labels
section. It is composed of a set of key-value pairs to narrow down the context and content of your resource. Those labels can later be used in almost any CLI commands through Selectors. As those entries are not used in the core behavior of Kubernetes, you can use any name you want, even if Kubernetes defines some best practices recommendations.annotations
section, which is almost identical to labels
but not used by Kubernetes at all. Those can be used on the applicative side to trigger behaviors or simply add data to ease debugging.# <metadata> narrows down selection and identify the resource
metadata:
# The <name> entry is required and used to identify the resource
name: my-resource
namespace: my-namespace-or-default
# <labels> is optional but often needed for resource selection
labels:
app: application-name
category: back
# <annotations> is optional and not needed for the configuration of Kubernetes
annotations:
version: 4.2
apiVersion: v1
# <kind> defines the resource described in this file
kind: ConfigMap
metadata:
name: my-config
data:
# <data> configures data to load
configuration_key: "configuration_value"
properties_entry: |
# Any multiline content is accepted
multiline_config=true
apiVersion: v1
# <kind> defines the resource described in this file
kind: Pod
metadata:
name: my-web-server
spec:
# <spec> is a domain specific description of the resource.
# The specification entries will be very different from one kind to another
Resources definition
apiVersion: v1
kind: ConfigMap
metadata:
name: simple-web-config
namespace: default
data:
configuration_key: "Configuration value"
valueFrom:
configMapKeyRef:
name: simple-web-config
key: configuration_key
ConfigMap Documentation
type
key at its root, which can be used to add validation on the keys declared in the data
entry. By default, the type is set to Opaque
which does not validate the entries at all.apiVersion: v1
kind: Secret
metadata:
name: simple-web-secrets
# Opaque <type> can hold generic secrets, so no validation will be done.
type: Opaque
data:
# Secrets should be encoded in base64
secret_configuration_key: "c2VjcmV0IHZhbHVl"
valueFrom:
secretKeyRef:
name: simple-web-secrets
key: secret_configuration_key
name
and image
fields are the only mandatory ones, but you might commonly use:
to define the ports to open on both the container and pod.ports
to define the environment variables to load on the container.env
andargs
to customize the container startup sequence.entrypoint
as the best practice indicates to use pod as part of a higher-level definition
(e.g. Deployment). In those cases, the Pod file’s content will simply be embedded in the other resource’s file.
apiVersion: v1
kind: Pod
metadata:
name: my-web-server
spec:
# <containers> is a list of container definition to embed in the pod
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
protocol: TCP
env:
- name: SOME_CONFIG
# Create a line "value: <config_entry>" from the ConfigMap data
valueFrom:
configMapKeyRef:
name: simple-web-config
key: configuration_key
- name: SOME_SECRET
# Create a line "value: <config_entry>" from the Secret data
valueFrom:
secretKeyRef:
name: simple-web-secrets
key: secret_configuration_key
Pod Documentation
Advanced Pod Configuration
Fields available in Pod <spec> entry
Fields available in Pod <containers> entry
- Create a pod definition based on the
entry.template
- Create a ReplicaSet on pods selected by the
entry, with the value ofselector
as a count of pods that should be running.replicas
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-web-server-deployment
namespace: default
labels:
app: webserver
spec:
# <selector> should retrieve the Pod defined below, and possibly more
selector:
matchLabels:
app: webserver
instance: nginx-ws-deployment
# <replicas> asks for 3 pods running in parallel at all time
replicas: 3
# The content of <template> is a Pod definition file, without <apiVersion> nor <kind>
template:
metadata:
name: my-web-server
namespace: default
labels:
app: webserver
instance: nginx-ws-deployment
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
protocol: TCP
env:
- name: SOME_CONFIG
# Create a line "value: <config_entry>" from the ConfigMap data
valueFrom:
configMapKeyRef:
name: simple-web-config
key: configuration_key
- name: SOME_SECRET
# Create a line "value: <config_entry>" from the Secret data
valueFrom:
secretKeyRef:
name: simple-web-secrets
key: secret_configuration_key
Deployment Documentation
selector
entry, thus based on its labels
. A Pod is selected if and only if all the labels in the selector are worn by the pod.ClusterIp
service, as other services are made for specific use cases.apiVersion: v1
kind: Service
metadata:
name: simple-web-service-clusterip
spec:
# ClusterIP is the default service <type>
type: ClusterIP
# Select all pods declaring a <label> entry "app: webserver"
selector:
app: webserver
ports:
- name: http
protocol: TCP
# <port> is the port to bind on the service side
port: 80
# <targetPort> is the port to bind on the Pod side
targetPort: 80
rules
and backends
as you want. A backend will typically be an internally routed ClusterIP service.apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: simple-web-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
# Using <host> redirects all request matching the given DNS name to this rule
- host: "*.minikube.internal"
http:
paths:
- path: /welcome
pathType: Prefix
backend:
service:
name: simple-web-service-clusterip
port:
number: 80
# All other requests will be redirected through this rule
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: simple-web-service-clusterip
port:
number: 80
Ingress Documentation
Available Ingress Controllers
Enable Ingress on Minikube
Nginx Ingress Annotations
CLI Usage
# <kind> is the type of resource to create (e.g. deployment, secret, namespace, quota, ...)
$ kubectl create <kind> <name>
$ kubectl edit <kind> <name>
$ kubectl delete <kind> <name>
# All those commands can be used through a description file.
$ kubectl create -f <resource>.yaml
$ kubectl edit -f <resource>.yaml
$ kubectl delete -f <resource>.yaml
# Create and update any resource
$ kubectl apply -f <resource>.yaml
# Delete any resource
$ kubectl delete -f <resource>.yaml
Managing Resources
kubectl get <kind>
. This command is pretty powerful and lets you filter the kind of resources to display or select the resources you want to see.default
namespace. You can specify -n <namespace>
to work on a specific namespace or -A
to show every namespace.# Fetch everything
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/my-web-server-deployment-58c4fd887f-5vm2b 1/1 Running 0 128m
pod/my-web-server-deployment-58c4fd887f-gq6lr 1/1 Running 0 128m
pod/my-web-server-deployment-58c4fd887f-gs6qb 1/1 Running 0 128m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/simple-web-service-clusterip ClusterIP 10.96.96.241 <none> 80/TCP,443/TCP 60m
service/simple-web-service-lb LoadBalancer 10.108.182.232 <pending> 80:31095/TCP,443:31940/TCP 60m
service/simple-web-service-np NodePort 10.101.77.203 <none> 80:31899/TCP,443:31522/TCP 60m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/my-web-server-deployment 3/3 3 3 136m
NAME DESIRED CURRENT READY AGE
replicaset.apps/my-web-server-deployment-58c4fd887f 3 3 3 128m
# We can ask for more details
$ kubectl get deployment -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
my-web-server-deployment 3/3 3 3 121m web nginx app=webserver
# Some resources are not visible using "all" but available
$ kubectl get configmap
NAME DATA AGE
kube-root-ca.crt 1 38d
simple-web-config 3 3h17m
kubectl describe <kind>/<name>
.# Let's describe the ingress for the sake of example
$ kubectl describe ingress/simple-web-ingress
Name: simple-web-ingress
Namespace: default
Address: 192.168.64.2
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
Host Path Backends
---- ---- --------
*.minikube.internal
/welcome simple-web-service-clusterip:80 (172.17.0.4:80,172.17.0.5:80,172.17.0.6:80 + 1 more...)
*
/ simple-web-service-clusterip:80 (172.17.0.4:80,172.17.0.5:80,172.17.0.6:80 + 1 more...)
Annotations: nginx.ingress.kubernetes.io/rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal UPDATE 7m6s (x6 over 23h) nginx-ingress-controller Ingress default/simple-web-ingress
kubectl logs <kind>/<name>
, as you might expect it shows you the resources’ logs if applicable. As the logs are produced by Pods, running such a command on a resource above a Pod will dig through Kubernetes to display the logs of a randomly chosen Pod underneath it.$ kubectl logs deployments/my-web-server-deployment
Found 3 pods, using pod/my-web-server-deployment-755b499f77-4n5vn
# [logs]
kubectl exec -it <pod_name> -— /bin/bash
. This will open an interactive shell on the pod, enabling you to interact with its content.# As for logs, when called on any resource enclosing Pods,
# Kubernetes will randomly chose one to execute the action
$ kubectl exec -it deployment/my-web-server-deployment -- /bin/bash
root@my-web-server-deployment-56c4554cf9-qwtm6:/# ls
# [...]
Conclusion
- Read the Kubernetes reference documentation.
- Install a sandbox locally with Minikube, and play with it.
- Watch the video Kubernetes Tutorial for Beginners — TechWorld with Nana.
- Manually bootstrap a Kubernetes cluster: Kubernetes The Hard Way.
you may want to take a look at the following technologies:
- Openshift is wrapping Kubernetes with production-friendly features
- Helm is a charts manager for Kubernetes helping improve the re-usability of configuration files.
- ArgoCD is keeping your Kubernetes Cluster up to date with your configurations from Git.