Kubernetes
Table of Contents
:ID: 31929B00-829E-41F3-BEBF-2F5B77B53E35
See also https://kubernetes.io/
# Fundamental k8 objects
# Pods
- k8s is all about managing pods.
- A Pod can encapsulate multiple running containers and volumes
# Replica Set
Contains Pod replicas for redundancy.
# Deployment
This is the application. They contain the replica sets. Replica sets contain the pods. Deployments contain the scalability and availability configurations.
# Services
- Used to expose container ports to other containers and host machine.
- Can make containers reachable by other containers by name. DNS resolution happens automatically.
- One type is like a load balancer – it distributes traffic to different pods in a deployment.
# Ingress
For http/https only. It provides URL access to services.
# YAML files
These are used to declare k8 cluster configuration as opposed to using the web interface or cli.
# Dashboard
A web interface for managing the k8 cluster. You get this with minikube.
minikube dashboard
Otherwise, use kubectl
cli tool to manage the cluster.
# K9s GUI tool
Useful tool that provides a TUI (with vim key bindings) for doing comment commands to the cluster that you’d otherwise do using a GUI or CLI. https://k9scli.io/topics/commands/
# Kubectl cli tool
See also my notes/command reference on Kubectl
This is also for managing the k8 cluster.
# Some common commands for getting info
kubectl api-resources
to see all the different types of resources that can be managed.kubectl explain <object>
to see the resource properties. You can drill into properties likekubectl explain pods.specs
. This is useful when figuring out what you need when defining YAML files.kubectl describe <resourceType> <resourceName>
kubectl get <resourceType> <resourceName> -o yaml
This is super useful with--dry-run
option and> my_resource.yml
to quickly create yamls.
See also https://kubernetes.io/docs/reference/kubectl/cheatsheet/
# Create deployment
One way is to:
kubectl create deployment apache image=httpd
More often you’ll create from a yaml file (more on this below)
kubectl apply -f deployment.ym
# Updates and Rollbacks
Lets say you apply -f deployment.yaml
with a newer version of a container
image. This will by default be deployed as a rolling update. Then you can see
the numbered revision history with:
kubectl rollout history deployment <deploymentName>
It can be rolled back with:
kubectl rollout undo deployment <deploymentName> --to-revision=n
# YAMLs
See https://github.com/sandervanvugt/kubernetes for examples
# Getting started
One easy way to build these yamls is to use the dashboard or cli to build deployments, then “export” the configuration to a yaml file.
kubectl get deployments foo-nginx -o yaml > foo-nginx.yml
There’s a bunch of things that are extraneous and can be deleted from this export:
creationTimestamp
resourceVersion
selfLink
uid
status
and all the stuff nested in it
You can make further changes, delete the previous deployment and re-created it from the yaml file (see below)
# –dry-run
Or use the --dry-run
if nothing has been build yet. Dry runs can be
exported just the same.
kubectl create deployment mynginx --image=ngnix:1.8 --dry-run=server -o yaml > mynginx_deployment.yml
# Creating stuff from YAML
kubectl apply -f foo-nginx.yml
# Update stuff
Same as creating, use apply -f
# Labels
API objects use labels to connect to other objects
# Namespaces
- Isolated environments, whereas a Context is a cluster (ie, you have have access to multiple clusters each with multiple namespaces).
- You can have the same named resource in different namespaces
- See https://github.com/ahmetb/kubectx for a handy cool
kubens
for switching between namespaces.
# Secrets
Secret values are Base64 encoded in the yamls/config but plain text in the containers.
# imagePullSecrets
Most likely I’ll be working with private container registries. To specify a private registry and auth details:
create a
docker-registry
secret. See the docs. Example:kubectl create secret docker-registry dockerhub-regcred \ --docker-server=https://index.docker.io/v1/ \ --docker-username=USERNAME \ --docker-password='PASSWORD' \ --docker-email=EMAIL
add the secret to a deployment or a pod
apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - image: username/someimage:latest imagePullSecrets: - name: dockerhub-regcred
# Environment variables
There are many ways to supply env vars to containers. Here is one:
Create a secret from a file, like a .env file with key value pairs:
kubectl create secret generic env-secrets --from-env-file=.env
Then just reference the secret using the
envFrom
propertycontainers: - name: nginx image: nginx:latest envFrom: - secretRef: name: env-secrets
# Networking
Pods and Services are the things that have IP addresses. All the containers within the Pod will share the Pod’s IP address.
- How do running containers within a pod communicate with each other?
# Service object
There’s a bunch of different service types.
- Connects to Pods with labels
targetPort
is the exposed port of the containers (thecontainerPort
property)
# LoadBalancer example
Exposing an app.
Create one using --dry-run
. In this example export host 3000 to container
port 3000
kubectl expose deployment kubetest-web --port=3000 --target-port=3000 --dry-run=client -o yaml > service.yml
When using minikube
. You’ll need to start a tunnel and leave it open:
minikube tunnel
Then, find the EXTERNAL-IP
and ports with kubectl get svc
. See
also this example.
# Database example
How to connect an app deployment to a database deployment?
Assuming there is a deployment with an app that needs to make a connection to a Postgres database. Also, assumes the Kubernetes DNS cluster addon is running in the cluster.
Create the postgres database deployment. See Secrets above for how to use the
fromEnv
property. It will be needed to set the postgres user and password.apiVersion: apps/v1 kind: Deployment metadata: labels: app: postgres name: postgres spec: replicas: 1 selector: matchLabels: app: postgres template: metadata: labels: app: postgres spec: containers: - image: postgres:12 name: postgres ports: - containerPort: 5432 envFrom: - secretRef: name: env-secrets
Create the service with the desired port
kubectl expose deployment postgres --port=5432 --target-port=5432 --dry-run=client -o yaml > service-database.yml
Test it out with
nslookup
. If the K8s DNS cluster is running, you should now be able to use the service name to reach the database.kubectl run curl --image=radial/busyboxplus:curl -i --tty nslookup postgres
- So, now
postgres
will resolve to the postgres database. Just provide that as aDATABASE_HOST
env var to your app.
# hostNetwork
spec.template.spec.hostNetwork
# Volumes
# Persistent Volume Claim
When using minikube
, it is the host. So, the directory to which the volume
is mounted should exist there. So do minikube ssh
and sudo mkdir /mydata
.
- Create the persistent volume. This could use the host’s storage, NFS, cloud storage, etc.
- Create the persistent volume claim (eg, it claims some amount of the PV volume’s storage).
- Add the volume to the container spec that references the PVC created in step 2.
See examples in https://github.com/apmiller108/kubernetes_rails
# ConfigMap
ConfigMaps can be mounted as a volume and used to provide configuration files.
See https://kubernetes.io/docs/concepts/configuration/configmap/#using-configmaps
# Tilt
Tilt is cool for doing local development against a local or remote K8s cluster. It handles exposing rebuilding the image with code changes and deploying to the cluster automatically. It will also expose resources (ie, a web app reachable from your host machines browser).
A simple Tiltfile
can get up an running with tilt up
k8s_yaml(['deployment-web.yml', 'deployment-sidekiq.yml']) docker_build('apmiller/imagename, '.') k8s_resource('web', port_forwards='3000')
# Helm Charts
https://helm.sh/docs/intro/install/
- A package manager for bundled Kubernetes manifests
- A tar archive in a repo
- requires the use of a Helm client
# The files
chart.yml
: metadata about the chartvalues.yml
: key/value pairs- templates: yaml manifests that define the application
# Resources
- kubectl is a cmd line tool for k8 cluster management
- minikube used to run a single node k8 cluster locally
- tilt something for kubernetes development environment
- https://kubernetes-rails.com/
- https://github.com/apmiller108/kubernetes_rails