Kubernetes: Overview
This section summarizes several specific introductory concepts/topics.
- Kubernetes Main Entities Overview
- Kubectl Inspection Quick Reference
- Kubectl Create Quick Reference
- Kubectl Modify Quick Reference
- Kubectl Run Quick Reference
- How to Install Minikube
- Kubectl Docker Discussion
- Docker Compose Translation
https://kubernetes.io/docs/reference/kubectl/quick-reference/
Syntax
Full reference: https://kubernetes.io/docs/reference/kubectl/generated/
Some commonly encountered Command verbs of interest:
applydeletegetcreatedeletedescribe
Some commonly encountered Entity Kinds of interest:
| Kind | Name | Shortname |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Display all Kinds, Names, Shortnames, ApiVersions (for config yaml)
kubectl api-resources
Generally, kubectl COMMAND ENTITY defines a valid operation where:
COMMANDis one of the above Command verbs; andENTITYis one of the above Entity Kinds.
Note: A Shortname can be substituted for any associated Kind or Name.
Resources and Links
Kubernetes: Main Entities Overview
I divide Kubernetes entities into a few kinds:
- Meta-level, organizational, groupings.
- Kubernetes Kinds (think primitives).
- Kubernetes Workload Management that assist in deploying and managing Pods.
Groupings
Grouping entities. These group and help manage Kubernetes Pods and Kubernetes Nodes.
Namespace
- https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
- A Kubernetes Namespace is a handle for grouping one or more Kubernetes Clusters.
- This allows Kubernetes Clusters to be categorized, grouped, etc. by role.
- Kubernetes Kind:
Namespace
Cluster
- https://kubernetes.io/docs/concepts/architecture/
- Kubernetes Clusters are divided into Kubernetes Nodes. Kubernetes Clusters are groupings of Kubernetes Nodes.
- Kubernetes Clusters are not created like other entities.
- Instead, Kubernetes Clusters are managed by Kubernetes Namespaces.
Service
- https://kubernetes.io/docs/concepts/services-networking/service/
- An abstract way to expose one or more Kubernetes Pods as a networking service.
- Essentially, a Kubernetes Service assigns a group of Kubernetes Pods a shared IP Address and/or DNS name.
- Akin to a Docker Compose Network that links and allows communication to and between Docker Containers.
- Kubernetes Kind:
Service
Basic
Think the basic conceptual units, primitives, or entities.
Node
- https://kubernetes.io/docs/concepts/architecture/nodes/
- A Kubernetes Node may be a virtual or physical machine.
- Multiple Kubernetes Pods can run in a Kubernetes Node.
- Kubernetes Nodes contain additional Kubernetes Components to run Kubernetes Pods.
Pod
- https://kubernetes.io/docs/concepts/workloads/pods/
- A group of one or more Kubernetes Containers.
- The primary workhorse and smallest unit of deployment.
- Kubernetes Kind:
Pod
Container
- https://kubernetes.io/docs/concepts/containers/
- Kubernetes Containers are Images that may be built (compiled, or otherwise) and run.
- They represent an Image at runtime, its state, etc.
- Conceptually, this is akin to a Docker Container (and may in fact be identical in some cases since Kubernetes can operate using Docker).
- Note, existing Kubernetes Containers cannot be added to a Kubernetes Kubernetes Pod since they are immutable.
Image
- https://kubernetes.io/docs/concepts/containers/images/
- Container Images represent an encapsulated resource with all its dependencies.
- This is akin to a Docker Image (and may in fact be identical in some cases since Kubernetes can operate using Docker).
Workload Management
ReplicaSets
- https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/
- Define a desired number of similar Kubernetes Pods to be running at any given time.
- They therefore help manage Kubernetes Pods but are themselves typically wrapped by and deployed as part of a Deployment.
- Kubernetes Kind:
ReplicaSet
Deployment
- https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
- A Kubernetes Deployment manages a set of Kubernetes Pods to run an application workload.
- Typically wrap Kubernetes ReplicaSets and manage both them and their Kubernetes Pods.
- Kubernetes Kind:
Deployment
Kubernetes: Kubectl Inspection Quick Reference Sheet
Some common and useful
kubectlcommands to inspect running or deployed Resources.
- Key operation:
kubectl get,kubectl describe. - Display one or many Resources.
- https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#get
- https://kubernetes.io/docs/reference/kubectl/generated/kubectl_describe/
minikube will install the default namespace automatically.
Commands
# See all resources
kubectl get all
# Display all Pods in every Namespace
kubectl get po --all-namespaces
# Display all pods in the `default` Namespace (will be empty by default)
kubectl get po -n default
# Display all Pods
kubectl get pods
# Display all Pods with the Label "label: example"
kubectl get po --selector label=example
# Display all Pods with the Labels "label: example" and "x: y"
kubectl get po --selector label=example,x=y
# Display all Namespace
kubectl get namespaces
# Display all services in every Namespace
kubectl get services --all-namespaces
# Display detailed information about test - Containers, status, etc.
kubectl describe namespace test
# Display detailed information about pod newpods-4npfh
kubectl describe po newpods-4npfh
Syntax
Generally:
kubectl get KINDorkubectl get NAMEdefines a valid operation.kubectl describe KINDorkubectl describe NAMEdefines a valid operation.
Resources and Links
Kubernetes: Kubectl Create Quick Reference Sheet
Some common and useful
kubectlcommands supporting the creation of Resources.
- Key operations:
kubectl create,kubectl apply. - Creates one or many Resources.
- https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#create
- https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#apply
Commands
# Create Namespace test
kubectl create namespace test
# Then review the created resource
kubectl get namespaces
# Create a Pod from a file (see below)
kubectl create -f pod-definition.yaml
# Create or update Pod from a file (see below)
kubectl apply -f pod-definition.yaml
Create vs. Apply
| kubectl create | kubectl apply |
|---|---|
| Imperative - a specific operation. | Declarative - specifies a target state. |
| Creates a Resource from a file or directly from within the CLI. | Creates a Resource by way of a manifest or configuration file. |
| Will error if Resource already exists. | Won't error if Resource already exists. |
| Creates a new Resource if it doesn't exist. | Updates a Resource if it exists, creates one if it doesn't. |
https://theserverside.com/answer/Kubectl-apply-vs-create-Whats-the-difference
Note: both
kubectl createandkubectl applyrequire configuration files to create Pods with a specific Docker Image.--imageis supported for kubectl create deployment.
Syntax
Generally:
kubectl create KINDandkubectl create NAMEdefines a valid operation.
Resources and Links
Kubernetes: Kubectl Run Quick Reference Sheet
Some common and useful
kubectl runcommands.
- Key operation:
kubectl run. - Create and run a particular Image in a Pod (without supplying YAML configuration).
- https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#run
Commands
# Create and run a Pod named nginx using the Image nginx w/out a config file
kubectl run nginx --image=nginx
Syntax
Generally, kubectl run POD_NAME --image=DOCKER_IMAGE defines a valid operation.
Resources and Links
Kubernetes: Kubectl Delete and Update Quick Reference Sheet
Some common and useful
kubectlcommands supporting the deletion and updating of Resources.
- Key operations:
kubectl delete,kubectl replace,kubectl apply,kubectl edit. - Updates, modifies, or deletes one or many Resources.
- https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#delete
- https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#replace
- https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#apply
- https://kubernetes.io/docs/reference/kubectl/generated/kubectl_edit/
Commands
# Delete Pod webapp
kubectl delete pod webapp
# Delete and recreate a resource using a modified configuration file
kubectl replace --force -f mypodconfig.yaml
# Create or update Pod from a file (see below)
kubectl apply -f pod-definition.yaml
# See the YAML config for a resource and edit it
kubectl edit rs new-replica-set
Note: Kubernetes Pods aren't "moved" (say from one Kubernetes Node to another) they are deleted in the first and recreated in the second.
Apply vs Replace
| kubectl apply | kubectl replace |
|---|---|
| Updates a Resource if it exists, creates one if it doesn't. | Updates if a Resource exists. |
| Won't typically error. | Will error if the Resource doesn't exist. |
Consider the following scenario:
kubectl create deployment --image=nginx nginx --dry-run=client -o yaml > nginx-deployment.yamlwhich creates the following YAML output:apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: nginx name: nginx spec: replicas: 1 selector: matchLabels: app: nginx strategy: {} template: metadata: creationTimestamp: null labels: app: nginx spec: containers: - image: nginx name: nginx resources: {} status: {}kubectl apply -f nginx-deployment.yamlkubectl describe deployment nginxdisplays:Name: nginx Namespace: default CreationTimestamp: Thu, 19 Dec 2024 15:37:38 -0600 Labels: app=nginx Annotations: deployment.kubernetes.io/revision: 1 Selector: app=nginx Replicas: 1 desired | 1 updated | 1 total | 1 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=nginx Containers: nginx: Image: nginx Port: <none> Host Port: <none> Environment: <none> Mounts: <none> Volumes: <none> Node-Selectors: <none> Tolerations: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: nginx-676b6c5bbc (1/1 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 2m11s deployment-controller Scaled up replica set nginx-676b6c5bbc to 1- Modifying the YAML document like so:
apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null name: nginx spec: replicas: 1 selector: matchLabels: app: nginx strategy: {} template: metadata: creationTimestamp: null labels: app: nginx spec: containers: - image: nginx name: nginx resources: {} status: {} - Then reapplying:
kubectl apply -f nginx-deployment.yamland inspecting viakubectl describe deployment nginx:Name: nginx Namespace: default CreationTimestamp: Thu, 19 Dec 2024 15:37:38 -0600 Labels: <none> Annotations: deployment.kubernetes.io/revision: 1 Selector: app=nginx Replicas: 1 desired | 1 updated | 1 total | 1 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=nginx Containers: nginx: Image: nginx Port: <none> Host Port: <none> Environment: <none> Mounts: <none> Volumes: <none> Node-Selectors: <none> Tolerations: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: nginx-676b6c5bbc (1/1 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 104s deployment-controller Scaled up replica set nginx-676b6c5bbc to 1
Omitting a field and kubectl applying will remove the fields on running Resources. (It's not a Patch operation per se - fields that aren't supplied aren't ignored or automatically populated in most cases.)
Edit
kubectl edit allows for:
- The live editing of a Resource through its YAML configuration. This configuration needn't be saved (but most be done so explicitly if updated YAML is required).
- Automatic updating of the Resource post-YAML modification. One doesn't need to run a second command to apply the new changes or remove prior Resource versions.
For this reason,
kubectl editis likely to be the preferred way to quickly modify Resources.
Syntax
Generally:
kubectl delete KINDandkubectl delete NAMEdefines a valid operation.kubectl edit KINDandkubectl edit NAMEdefines a valid operation.
Resources and Links
- https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#delete
- https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#replace
- https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#apply
- https://kubernetes.io/docs/reference/kubectl/generated/kubectl_edit/
- https://medium.com/@grpeto/kubectl-edit-performing-magic-in-kubernetes-684669a8bccd
Kubernetes: Install Minikube
I've chosen minikube here since it's the Kubernetes distribution that's used during the CKA exam and probably the easiest to get set up locally. It's a bit underpowered for Enterprisey stuff but suffices for these purposes.
Gotcha's
- You must have
dockerinstalled for the typical (and default)minikubeinstallation. - To install
minikubein a cloud VM you'll need at least 2 CPU cores (Medium size on AWS).
Minikube Installation
Basically follow this: https://minikube.sigs.k8s.io/docs/start/
Download the correct version after installing docker.
# Verify install
minikube version
# Start minikube
minikube start
- Note that
minikubeoffers a simplekubectlwrapper:minikube kubectl. This is, for all intents and purposes, just an automated installer for the correct version ofkubectl. Otherwise, most people recommend just usingkubectldirectly (it saves time typing too). - Note further that
minikubeis both a tool and a local cluster with several namespaces.
Minikube Removal
Some relevant commands:
# Stop your local cluster
minikube stop
# Removes your local minikube cluster (and start over)
minikube delete
# Removes all local clusters
minikube delete --all
minikube delete --purge
Helpful Minikube Commands
Helpful commands when using minikube.
Display minikube resources with a UI:
minikube dashboard
Display addons and common tools that can be enabled and added:
minikube addons list
Kubectl
Installing kubectl directly is likely a test question: https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/
Kubernetes: Kubectl Docker Discussion
Discussion and example highlighting major differences between using Docker Images in Docker and using them in Kubernetes.
Docker
Terminal One:
# Download image
docker pull elixir
# Open an interactive terminal through Elixir in Docker
## Note that calling this without -it will not allow commands to be passed to iex
docker run -it elixir
Terminal Two (Admin Console - use as needed)
# Display the container and obtain the CONTAINER ID
docker stats
# Display the downloaded images and obtain the IMAGE ID
docker images --all
# Remove container
docker stop CONTAINER_ID
docker rm CONTAINER_ID
# Remove downloaded image
docker rmi -f IMAGE_ID
# Remove all containers and volumes
docker system prune
# Remove all containers and volumes
docker system prune --volumes
So, in the above, one is able to pull elixir and run bash terminal.
Local Docker With Kubernetes
Close the other terminals and check out this awesome blog: https://www.yeahshecodes.com/docker/run-docker-images-locally-with-minikube
I've also found that using docker pull directly through kubectl will often result in Backoff Errors (CrashLoopBackOff) when using minikube. For example (in minikube dashboard):
| Name | Reason | Message | Source | Sub-object | Count | First Seen | Last Seen |
|---|---|---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
One might think using kubectl run elixir --image=elixir --namespace=test without additional configs would spin up a viable Pod but this is not the case for nearly every official Docker Image I tested in minikube.
- Following the same steps below for
elixir:latest,postgres,alpine, andubuntualso resulted in such Backoff Errors.- In fact that was the case with or without a version or tag suffix
- Also the case whether the Image was pulled or already available on-disk, whether customized, or official.
After some further tinkering and research, additional careful configuration is indeed required (e.g. - creating a Deployment resource file in YAML) and is explained in further detail here: https://spacelift.io/blog/kubernetes-imagepullpolicy
- Images must conform to a specific Image name and version/tag nomenclature. This affects the
--image-pull-policyflag that controls how Kubernetes looks up, pulls from a Container Repository, and pulls a Docker Image into a Pod. - Furthermore, the main/encouraged way to interact with Images is through a Container Repository (rather than through pre-build Images on-disk which may or may not be exposed or visible to the local Kubernetes environment).
However, there is another work around. Per the blog post above and some personal tinkering, one can use a docker-compose.yaml file with supplied "alias" (really a customized and conforming Image name):
version: "3.9"
services:
nginx:
image: localtest:v0.0.1
build: .
ports:
- "80:80"
and, a dockerfile:
FROM nginx:latest
EXPOSE 80
I tinkered with the config supplied in the above blog post and narrowed it down to just the above. That appears to be the most minimal config to use regulard Dockerfiles and Docker builds with
minikube+ Kubernetes (sinceminikubeis the Kubernetes distribution for local development).
Now in an additional terminal:
# Ensure both minikube and docker are in the same env
eval $(minikube docker-env)
# Build from dockerfile
docker-compose up -d
# View Docker Images ages (from within minikube!)
docker images --all
# Create Namespace test
kubectl create namespace test
# Set namespace context
kubectl config set-context --current --namespace=test
# Review all resources in Namespace
kubectl --namespace test get all
# Deploy the Docker Image as a Pod to the Container
kubectl run localtest --image=localtest:v0.0.1 --image-pull-policy=Never --namespace test
# Review all resources in Namespace
kubectl --namespace test get all
Make sure that both
minikubeanddockerare in the same env and visible to each other otherwise one will also encounters Backoff Errors via the command:eval $(minikube docker-env).
Also, do make sure that you supply
--image-pull-policy=Neveror--image-pull-policy=IfNotPresentas needed along with the appropriate and supplied tag version on the image per: https://spacelift.io/blog/kubernetes-imagepullpolicy
Kubernetes: Docker Compose Translation
Translating Docker Compose to Kubernetes.
Configuration Files
Kubernetes deployment.yml's and service.yml's are typically configured and applied together (kubectl apply -f python-deployment.yaml,python-service.yaml):
deployment.yml- defines Volumes, Commands to be executed, Docker Images, and Containers.- Contains many of the configuration settings one would find in
docker-compose.yml.
- Contains many of the configuration settings one would find in
service.yml- specifies Ports, Port Mappings, and generally connects Pods in a Deployment to shared Network resources.configmap.yml- injects Secrets, Environment Variables, initialization scripts, and files into the Kubernetes context.- Associated with a Deployment within
deployment.yml.
- Associated with a Deployment within
Resources and Links
Linux Foundation CKA: Overview
Note: These notes will do "double duty" for both the KCNA and CKA exams.
The CKA is being rewritten
1/15/2025-ish.
I strongly recommend taking the excellent KodeKloud KNCA and CKA courses!
Cluster Architecture
- Control Plane - manage, plan, schedule, and monitor Nodes
- etcd - Key value persistence store used to back all Kubernetes Cluster data.
- Listens on Port
2379by default. - Typically, only
kube-apiserverwill directly interact withetcd.
- Listens on Port
- kube-apiserver - exposes the Kubernetes API to allow the following functionalities to be performed: reference.
- kube-scheduler - Control Plane component that listens for newly created Kubernetes Pods with no assigned Kubernetes Node and assignes them one.
- kube-controller-manager - runs and manages Kubernetes Control Plane Controllers.
- Example: Node Controller - responsible for noticing and responding when Nodes fail.
- Example: Job Controller - watches for Kubernetes Job objects that represent one-off tasks then creates Pods to run those tasks to completion.
- Cloud Controller Manager (Optional) - embeds Cloud Provider-specific control logic.
- For example: cloud-provider-aws
- etcd - Key value persistence store used to back all Kubernetes Cluster data.
- Nodes - used to group Resources, run one or more Kubernetes Pods, and managed by the Control Plane. Node components run on every Node.
- kubelet - an Agent that runs on every Node in the Cluster.
- Ensures that Containers are running in a Pod.
- kube-proxy (Optional) - maintains Network rules on Nodes allowing communication to and between Pods (inside or outside the Cluster).
- Container Runtime - manages the execution and lifecycle of Containers within the Kubernetes environment.
- Supports any Container Runtime implementing the Kubernetes Container Runtime Interface (CRI).
- Note: support for Docker through Dockershim is now deprecated. containerD has been targeted as the go to for Docker going forward.
- kubelet - an Agent that runs on every Node in the Cluster.
Nodes, Pods, and Containers
- Many Containers can run in a single Kubernetes Pod.
- Many Kubernetes Pods can run in a single Kubernetes Node.
kube-proxy vs. kubectl proxy
- kube-proxy (Optional) - maintains Network rules on Nodes allowing communication to and between Pods (inside or outside the Cluster).
- Exists on Nodes.
- kubectl proxy - proxy for
kube-apiserver.- Exists in the Control Plane.
Namespaces
Some Kubernetes Resources can be organized, isolated, and grouped into Kubernetes Namespaces. Examples:
- Kubernetes Deployments
- Kubernetes Service Accounts
- Kubernetes Nodes
Some Resources are Global (available regardless of the current Kubernetes Namespace or accessible within any of them). Examples:
- Kubernetes Volumes
- Kubernetes Services (not to be confused with Kubernetes Service Accounts)
- Kubernetes User Accounts
Default Namespaces
These are automatically created when a Kubernetes Cluster is created through normal means:
defaultkube-systemkube-node-lease- holds Kubernetes Leases (mapped to Kubernetes Nodes) used by the Control Plane to detect Kubernetes Node failures (through Heartbeats).kube-public
https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
Resources and Links
- https://kubernetes.io/docs/concepts/architecture/#etcd
- https://kubernetes.io/docs/concepts/architecture/#kube-apiserver
- https://kubernetes.io/docs/concepts/architecture/#kube-controller-manager
- https://kubernetes.io/docs/concepts/architecture/cloud-controller
- https://kubernetes.io/docs/concepts/architecture/#node-components
- https://kubernetes.io/docs/concepts/architecture/#container-runtime
- https://kubernetes.io/docs/reference/kubectl/generated/kubectl_proxy
- https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
Linux Foundation CKA: etcd
etcd is the backing store for Kubernetes Clusters. It's typically provisioned automatically (along with other Control Plane Resources) but can be manually added (say in a Kubernetes Cluster that's manually provisioned and/or with customized/custom coded Resources, Controllers, etc.).
Typically, only kube-apiserver will directly interact with etcd.
etcdlistens on Port2379by default (both within and outside of Kubernetes).
Useful Commands
etcdctl put mykey myvalue # add a key value pair
etcdctl get mykey # read key value
etcdctl del mykey # delete pair mykey, myvalue by key
etcdctl watch mykey # prints out changes to mykey's value
etcdctl lease grant 60 # create a Lease
## prints Lease ID
# > lease 32695410dcc0ca06 granted with TTL(60s)
# automatically add mykey with auto eviction
etcdctl put mykey myvalue --lease=1234abcd ## --lease is assigned to a the Lease ID, not the chronotype itself
Resources and Links
Linux Foundation CKA: Pods
YAML
# pod-definition.yaml
apiVersion: v1
kind: Pod
metatdata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: nginx-container
image: nginx
Required fields (for any Resource):
apiVersion- typicallyv1but there are some outliers.kind- specifies the kind of Resource (Pod,Service,Deployment, etc.)metatdata- name of the Resource and any user-specified labelsspec- configuration, attached Resources, etc.
Creating
# Create a Pod from a YAML configuration
## Note: there's no way to pass an Image in as a flag with create!
kubectl create -f pod-definition.yaml
kubectl apply -f pod-definitional.yaml
# Create and run a Pod named nginx using the Image nginx w/out a config file
kubectl run nginx --image=nginx
Inspection
# Get all Pods regardless of Namespace
kubectl get po --all-namespaces
# Detailed inspection of Pod
kubectl describe po myapp-pod
Updating
To update a Pod configuration file you can first destroy the running Pod then recreate the new Pod with new configuration:
# Using the above config
kubectl delete pod myapp-pod
kubectl create -f pod-definition.yaml
Or, use:
kubectl replace -f pod-definition.yaml- to replace with a Resource using a modified configuration file.kubectl edit rs new-replica-set- to both display the config for the Resource (in YAML format) and edit it. (Editing alone may not be sufficient to update the actually running Resources - in a Replica Set, you'd want to delete the running Pods so they deploy with the updated configuration.)
Deployments
- See Deployments.
- Can be deployed as Kubernetes Static Pods that can be tracked by the Control Plane but otherwise exist independently. When using Kubernetes Static Pods, one will be restricted to a single Kubernetes Node and its local
kubectl(and while the Control Plane can be made aware of the Kubernetes Static Pod, it has no other control over managing, modifying, or interacting with it).
Linux Foundation CKA: Deployments
Kubernetes Pods will typically be deployed with the following considerations:
- A certain number of Kubernetes Pods will need to be available at all times.
- Updates to Kubernetes Pods must be careful sequenced.
The above requirements are typically satisfied by:
- Kubernetes Replica Sets which allow a number of Kubernetes Pods to be specified through the
replicasfield. - Kubernetes Rollout Strategies
Kubernetes Deployments therefore wrap both Kubernetes Replica Sets and provide the additional management tooling required for carefully deploying new changes.
Kubernetes Deployments will be assigned to various available Kubernetes Nodes based on configured Affinities, Taints, Tolerations, etc.
Deployment YAML
apiVersion: apps/v1
kind: Deployment
metadata:
name: python-pyramid
labels:
app: python-pyramid-postgres
service: python-pyramid
spec:
replicas: 3
selector:
matchLabels:
app: python-pyramid-postgres
service: python-pyramid
template:
metadata:
labels:
app: python-pyramid-postgres
service: python-pyramid
spec:
containers:
- name: python-pyramid
image: python-pyramid:v0.1
imagePullPolicy: Never
ports:
- containerPort: 8000
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
Rollout Strategies
RollingUpdate- Default.
- Will gradually update Kubernetes Pods a few at a time (depending on the configured settings).
Recreate- Kills all Kubernetes Pods before new ones (with the applied updates) are created.
Two optional fields help to control this process:
maxUnavailable- specify the number of Kubernetes Pods that must be available while the others are being updated.maxSurge- specify the number of Kubernetes Pods that can temporarily be added to complete the rollout.
Stateful Sets and DaemonSets
- Kubernetes Stateful Sets
- Are distinct from Kubernetes Replica Sets but are akin in certain specific ways. (e.g. - can specify
replicasand used to manage a group of Kubernetes Pods). Is not a subkind ofrs. - Stateful information is retained about a Kubernetes Stateful Set as it recreated and destroyed.
- This guarantees certain settings remain invariant (Kubernetes Volume Claims, Kubernetes Network settings, etc.).
- Does not guarantee that only one Kubernetes Pod managed by the Kubernetes Stateful Set is deployed to each Kubernetes Node.
- https://docs.rafay.co/learn/quickstart/kubernetes/deployments-daemonsets-statefulsets/
- Are distinct from Kubernetes Replica Sets but are akin in certain specific ways. (e.g. - can specify
- Kubernetes Daemon Sets
- Are distinct from Kubernetes Replica Sets but are akin in certain specific ways. (e.g. - can specify
replicasand used to manage a group of Kubernetes Pods). Is not a subkind ofrs. - Specifies that one, a particular, Kubernetes Pod must be present in all (or some specified) Kubernetes Nodes.
- Ideal for observability tooling, logging, or Agent-based installations.
- https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/
- Are distinct from Kubernetes Replica Sets but are akin in certain specific ways. (e.g. - can specify
Commands
# Check the rollout status
kubectl rollout status deployment python-pyramid
# Rollback the update
## Note the /
kubectl rollout undo deployment/python-pyramid
https://kubernetes.io/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_undo/
Resources and Links
- https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
- https://kubernetes.io/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_undo/
- https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/
- https://docs.rafay.co/learn/quickstart/kubernetes/deployments-daemonsets-statefulsets/
- https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/
Code samples:
Linux Foundation CKA: Services
Maps Kubernetes Pod Ports to Node Ports by listening on specified Ports and forwarding them.
YAML
apiVersion: v1
kind: Service
metadata:
name: myServiceName
spec:
type: NodePort
ports:
- targetPort: 80
port: 80
nodePort: 31000 # 30000-32767
- port: 8080
# port is the only required field
## if solely provided, targetPort is assumed to be the same as port
## and an available port in range 30000-32767 is selected
select:
app: myPod # Match a pod
type: someMetadataType
Kubernetes Ports:
- Inbound
portis mapped to internaltargetPort. nodePortis exposed externally as a Static IP Address.
Kubernetes Service YAML config type values:
LoadBalancer- Load balances external traffic into the Kubernetes Cluster.
- Requires that an external Load Balancer exists (such as an AWS ALB).
ClusterIP- Default value.
- Facilitates communications within the Kubernetes Cluster.
NodePort- Enables a Kubernetes Node to be accessible from outside a Kubernetes Cluster.
ExternalName- An internal Alias for an external DNS Name.
None- A Headless Kubernetes Service.
- Unlike the others, this isn't configured in the
spec.typefield. - Instead it's configured like so:
spec.clusterIP: None.
Load Balancing
- A Kubernetes Service will Load Balance multiple Kubernetes Pods in the same Kubernetes Node (of the same Kubernetes Cluster).
- It will also do so for multiple Kubernetes Pods in different Kubernetes Node within the same Kubernetes Cluster.
DNS Names
- Internal to the same Kubernetes Namespace, Kubernetes Pods can access another Kubernetes Service by its
name. - Kubernetes Pods can access another Kubernetes Service in another Kubernetes Namespace by its fully qualified
name:<SERVICE_NAME>.<NAMESPACE_NAME>.svc.cluster.local.
Commands
# Create a Service named redis-service with Pod redis associated on Port 6379
kubectl expose pod redis --port=6379 --name redis-service
Resources and Links
Linux Foundation CKA: Scheduling
Kubernetes Scheduling assigns Kubernetes Pods to Kubernetes Nodes.
Schedule Matching and Constraints
There are several considerations and ways that Kubernetes Schedules Pods:
- The inbuilt
kube-schedulertypically and automatically manages assigning Kubernetes Pods to Kubernetes Nodes. - Manually setting the
nodeNamefield. nodeSelectormatching against Node Labels.affinity- Taints and Tolerations.
|
|
|
|
Taints and Tolerations |
|---|---|---|---|---|
| Default. No user control. Automatic. Managed Scheduling. | Manual. Set in YAML or through JSON API. | Associates a Node Label with a Pod nodeSelector. |
An affinity field is specified in Pod YAML. |
Taints are set on Nodes and Tolerations are set on Pods. |
| First available (given the other constraints). | Most precise but requires exact Node name. |
Assigns by single Label (think CSS Selector). | More precise than nodeSelector. Supports multiple Labels. |
Assigns a Taint to a Node that will be avoid by any Pod without a toleration. |
| Attracting association. | Attracting association. | Attracting association. | Attracting or repelling association. | Repelling association. |
| API-centric. | Field. Key Value pair. | Field. Key Value pair. | Fields. Supports predicates, Labels, and complex expressions. | Fields. Supports predicates and complex expressions. |
| Random. | Exact Node. | Restricted to range of Nodes. | Restricted to narrower range of (or avoids certain) Nodes. | Pods are restricted to range of Nodes. |
Selectors and Labels
Selectors are used to pair Resources with other Resources.
Below, a Kubernetes ReplicaSet is associated with Kubernetes Pods with Label App1.
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: simple-webapp
labels:
app: App1
function: Front-end
spec:
replicas: 3
selector:
matchLabels:
app: App1 # Selector looks for matches on one of more labels
template:
metadata:
labels:
app: App1 # template labels specify the labels on each deployed Pod
function: Front-end
spec:
containers:
- name: simple-webapp
image: simple-webapp
# Display all Pods with the Label "label: example"
kubectl get po --selector label=example
# Display all Pods with the Labels "label: example" and "x: y"
kubectl get po --selector label=example,x=y
Manually Assign a Pod to a Node
To manually Schedule a Kubernetes Pod (assigning it to a Kubernetes Node).
# find all nodes
kubectl get nodes
Displaying:
NAME STATUS ROLES AGE VERSION
controlplane Ready control-plane 25m v1.31.0
abcNode Ready <none> 24m v1.31.0
Edit the config:
nano mypodconfig.yaml
# mypodconfig.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginx
nodeName: abcNode # Add
## kube-scheduler schedules a Pod by assigning it the field nodeNode with a valid Node
## This can be done manually too!
Recreate the Pod:
# Delete and recreate in two commands
kubectl delete pod nginx
kubectl create -f mypodconfig.yaml
# Delete and recreate in one command
kubectl replace --force -f mypodconfig.yaml
nodeSelector
Labels are added to Kubernetes Nodes:
# Show all Labels
kubectl get nodes --show-labels
# Create a new Label on a Node
kubectl label nodes my-node-name x=y
nodeSelector is specified on Kubernetes Pods:
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
Any Kubernetes Pod with a valid
nodeSelectorwill be paired with an available Kubernetes Node with a matching Kubernetes Nodelabel.
Affinity
- Supports complex, multi, Label associations.
- Supports Labels (see
nodeSelector). - Can define repellent Anti-Affinities.
apiVersion: v1
kind: Pod
metadata:
name: with-pod-affinity
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: topology.kubernetes.io/zone
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S2
topologyKey: topology.kubernetes.io/zone
containers:
- name: with-pod-affinity
image: registry.k8s.io/pause:3.8
affinitygoes undertemplatein Kubernetes Deployment config YAML.
Taints and Tolerations
Kubernetes Taints restrict which Kubernetes Pods can be assigned to which Kubernetes Nodes (which Kubernetes Nodes can accept which Kubernetes Pods).
Kubernetes Taints and Tolerations do not guarantee that Kubernetes Pod will be assigned to a specific Kubernetes Node(s)!
- Kubernetes Taints are set on Kubernetes Nodes
kubectl taint nodes my-node-name key=value:taint-effect- If Kubernetes Pod isn't Tolerant (it's Intolerant), it's behavior is determined by a specified Taint Effect.
- Taint Effects:
NoSchedule,PreferNoSchedule,NoExecute. - A Taint is repelling - negatively associated.
- Kubernetes Tolerations are set on Kubernetes Pods
- Must be coded with
" "and viewed with|grep.apiVersion: v1 kind: Pod metadata: name: myapp-pod spec: containers: - name: nginx-container image: nginx tolerations: - key: "app" operator: "Equal" value: "blue" effect: "NoSchedule"
- Must be coded with
kubectl describe node myapp-node |grep Taint
# Taint
kubectl taint nodes controlplane x=y:NoSchedule
# View Taints
kubectl describe node controlplane |grep Taint
# Use the fully qualified name to remove (note the - at the end)
kubectl taint nodes controlplane x=y:NoSchedule-
kubectl taint nodes controlplane node-role.kubernetes.io/control-plane:NoSchedule-
Scheduling Algorithm
The default kube-scheduler uses the following two-step algorithm to assign Kubernetes Pods to Kubernetes Nodes:
- Filtering
- Uses the
affinity, Taints and Tolerations,nodeSelector, and so on to identify a range of Kubernetes Node to assign a Kubernetes Pod to.
- Uses the
- Scoring
- Bin Packing - optimization scenario to maximize the number of "packages" that fit into a "bin" (hence "bin packing").
- Determines available Resources and if the Kubernetes Pod can be added.
Resources and Links
Linux Foundation CKA: Resource Limits
Kubernetes supports setting Resource limits (primarily CPU, Memory).
Requests and Limits
- A
LimitRangeRequest specifies the maximum that a Resource can ask for and have allotted to it. - A
LimitRangeLimit is used to enforce minimum and maximum compute resource usages.
For example: you may want to specify a
500Mmemory Limit but a250Mmemory Request to allow some extra memory buffer (pun) for other dependencies and services (including the Operating System itself).
Values
Standardized Resource values apply and simplifying resourcing whether a Container or Pod is run on a single-core, multi-core, or 48-core machine.
cpu.1(100m) is equivalent to a 1/10 of a CPU Physical Core or Hyperthread..5(500m) is equivalent to half a CPU Physical Core or Hyperthread.1is equivalent to a single CPU Physical Core or Hyperthread.- https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#meaning-of-cpu
memory400Mis equivalent to 400 megabytes.- Note:
400mis NOT equivalent to400M! - Consult the official Quantity Suffixes.
- https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#meaning-of-cpu
YAML
Such constraints can be set as a standalone LimitRange Kind:
apiVersion: v1
kind: LimitRange
metadata:
name: testLimit
namespace: ns1
spec:
limits:
- default:
cpu: 200m
memory: 500m
defaultRequest:
cpu: 100m
memory: 250m
type: Container
The Kubernetes Limit Range is applied to a Kubernetes Namespace (and its Kubernetes Pods only indirectly) like so:
kubectl apply -f cpu-constraint.yaml --namespace=my-name-space
Spec Configuration
They can also be set within another Resource definition:
Since Kubernetes
1.32, Pods can set this underspec.resources. This sets the overall limits for the entire Kubernetes Pod (and not just a single Container):apiVersion: v1 kind: Pod metadata: name: pod-resources-demo namespace: pod-resources-example spec: resources: limits: cpu: "1" memory: "200M" requests: cpu: "1" memory: "100M" containers: - name: pod-resources-demo-ctr-1 image: nginx resources: limits: cpu: "0.5" memory: "100M" requests: cpu: "0.5" memory: "50M"Note: This feature is Disabled by default and is in Alpha as of
12/2024.Via
spec.containers[].resourceswhich specifies limits for each Container:apiVersion: v1 kind: Pod metadata: name: frontend spec: containers: - name: app image: images.my-company.example/app:v4 resources: requests: memory: "64M" cpu: "250m" limits: memory: "128M" cpu: "500m"
Resources and Links
- https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#meaning-of-cpu
- https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#meaning-of-memory
- https://kubernetes.io/docs/concepts/policy/limit-range/
- https://kubernetes.io/docs/tasks/configure-pod-container/assign-pod-level-resources/
- https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/
- https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-requests-and-limits-of-pod-and-container
Linux Foundation CKA: Security
An excellent read: https://kubernetes.io/blog/2018/07/18/11-ways-not-to-get-hacked/ for Kubernetes security best practices.
Some Kubernetes security best practices:
- Disable Root Access.
- To close and/or disable all unneeded Container Ports.
- To disable any default password-based authentication (and use some stronger alternative).
- To move all Credentials and Secrets out of plaintext, configuration, and/or files into something more secure (third-party vault, temporary and in-memory tokens, etc.) as described here.
- To restrict access by RBAC and SSH Key only (Jump Bastion style).
TLS
- Using
opensslone will typically generate an SSL Certificate in the following way:- A Key:
.key - A Certificate Signing Request (CSR):
.csr - Which in turn are used to sign and generate a Certificate:
.crt,.pem(Privacy Enhanced Mail data and file format)
- A Key:
- The above steps are performed to generate a Certicate Authority Root Certificate that's used to generate valid Client Certificates.
# simple openssl to generate root cert for Kubernetes Cluster CA openssl genrsa -out ca.key 2048 # subj CN is Certificate Name openssl req -new -key ca.key -subj "/CN=KUBERNETES-CA" -out ca.csr openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt - Generate Certifcates for each Client and Signed with the Root Certificate and Key created above:
openssl genrsa -out client.key 2048 openssl req -new -key client.key -subj "/CN=my-client" -out client.csr # using the above root CA cert and key openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -out client.crt - It's good practice to generate a Certifcates for each Resource in the Kubernetes Cluster (in similar fashion):
- So that all communication between Resources is encrypted.
- Each Certificate can be associated with a single Client or kind of access aiding with proper RBAC.
Multi-Cluster Config
Defines and controls access from one Kubernetes Cluster to others:
apiVersion: v1
kind: Config
preferences: {}
clusters:
- cluster:
name: development
# Here, the Authentication Strategy is through valid Certificates.
certificate-authority: dev-ca-file
server: https://5.6.7.8
- cluster:
name: production
# And here.
certificate-authority: prod-ca-file
server: https://1.2.3.4
contexts:
- context:
name: development
namespace: development
user: dev-env-user
- context:
name: production
namespace: production
user: prod-env-user
users:
- name: dev-env-user
user:
client-certificate: dev-cert-file
client-key: dev-key-file
- name: prod-env-user
user:
client-certificate: prod-cert-file
client-key: prod-key-file
kubectl config view
Kubernetes Users are not Kinds - they are not created. For example, there is no kubectl creater user username command.
- They are merely associated with some Credential or Authentication Mechanism (password, CA Certificate, etc.).
- So it's probably better to think of such Users as namespaces for specific authentication identities.
- Indeed, the official documentation says:
"...Kubernetes does not have objects which represent normal user accounts... Even though a normal user cannot be added via an API call, any user that presents a valid certificate signed by the cluster's certificate authority (CA) is considered authenticated."
https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/
Users and Service Accounts
Kubernetes Users, therefore, aren't represented by Kinds or standalone objects but only indirectly through the specified Authentication Strategy.
- The Authentication Strategy is configured via CLI:
kube-apiserver --authorization-mode=...,RBAC. - Or through:
AuthorizationConfiguration(apiserver.config.k8s.io/v1) in YAML. - Also,
kubectl api-resourcesdoesn't display anyuserKind.
Kubernetes Service Accounts are managed through the Kubernetes API and are bound to specific Kubernetes Namespaces.
- These are mostly used to allow Resources to have access to other Resources (rather than Users attempting to gain access through Authentication).
Role-Based Access Control
Unlike Kubernetes Users, Kubernetes Roles are bona fide objects, that are managed through Kubernetes API, and which have an associated Kind:
# dev-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: developer
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["list", "get", "create", "update", "delete"]
kubectl create -f dev-role.yaml
Kubernetes Roles are then bound (through a Kubernetes Role Binding) to a Kubernetes User:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dev-role-binding-for-dev-user
subjects:
# Not a Kubernetes Kind per se
- kind: User # field is kind but not object
name: dev-user
roleRef:
kind: Role
name: developer
Kubernetes Secrets
Kubernetes Secrets are akin to Kubernetes Config Maps but are specifically intended to store Secrets.
- Values stored as such are unencrypted by default and anyone can view, modify, or retrieve them.
- Additional security is strongly encouraged per: https://kubernetes.io/docs/concepts/security/secrets-good-practices/
Impersonation and Authorization
Authentication involves gaining, obtaining, or having access to some Resource.
Authorization involves what a Resource or User can do once they have authenticated.
Administrators can check whether other Users can perform certain actions like so:
kubectl auth can-i list pods --as=system:serviceaccount:dev:foo -n prod
Users can see if they can for themselves:
# Check to see if I can create pods in any namespace
kubectl auth can-i create pods --all-namespaces
https://kubernetes.io/docs/reference/kubectl/generated/kubectl_auth/kubectl_auth_can-i/
Resources and Links
- https://kubernetes.io/blog/2018/07/18/11-ways-not-to-get-hacked/
- https://kubernetes.io/docs/reference/access-authn-authz/authentication/#authentication-strategies
- https://docs.openssl.org/1.0.2/man1/x509/#signing-options
- https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/
- https://kubernetes.io/docs/reference/access-authn-authz/authentication/#users-in-kubernetes
- https://kubernetes.io/docs/reference/access-authn-authz/rbac/
- https://kubernetes.io/docs/concepts/security/secrets-good-practices/
- https://kubernetes.io/docs/concepts/configuration/secret/
- https://kubernetes.io/docs/reference/kubectl/generated/kubectl_auth/kubectl_auth_can-i/
Linux Foundation CKA: Networking
DNS
- Kubernetess will automatically provision a DNS Server for a new Kubernetes Cluster.
- Kubernetes DNS will be managed and created for Kubernetes Pods and Kubernetes Services.
- Kubernetes Services are automatically assigned a DNS Record.
- Kubernetes Pods can be exposed directly or through a Kubernetess Service (and the way they are exposed determines what the DNS Record is)
Kubernetes DNS will create DNS Records and map IP Addresses like so:
- Kubernetes Service:
my-svc.my-namespace.svc.cluster-domain.example - Kubernetes Pod:
pod-ipv4-address.my-namespace.pod.cluster-domain.example- By convention Kubernetes Pods replace dots with dashes in the IP Address.
- The above will be mapped to a Network IP Address.
cluster-domain.exampleis typically thought of as the top-level Domain (despite the dot betweencluster-domainandexample) for all Resources within the Kubernetes Cluster:- The last item
examplecan be thought of as the top-level Domain. cluster-domaincan be thought of as a Subdomain (created for the Kubernetes Cluster). Especially in a multi-Cluster deployment.
- The last item
svcorpodare properly part of the Domain and Subdomain Names and are dependent on the Kubernetes Kind the DNS Record is created for.
https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/
Container Network Interface
- Containers running in a Kubernetes Pod will communicate using a Container Network Interface (CNI).
- CNI Plugins are stored in the CNI bin directory as executables on the
kubeletservice in each Kubernetes Node of the Kubernetes Cluster. - Each Kubernetes Node must have at least one CNI to connect to a network.
- Configuration is handled through CNI-specific JSON configuration files.
https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/
Pod Networking
- Kubernetes Pod networking requires a third-party tool and isn't available out of the box.
- Flannel
- Cilium
- WeaveWorks
- The above tools install Agents on each Kubernetes Pod to facilitate direct Kubernetes Pod to Kubernetes Pod intercommunication.
- Kubernetes Pod networking requirements:
- Kubernetes Pods within the same Kubernetes Node should be able to communicate using their IP Addresses.
- Each Kubernetes Pods should have a unique IP Address.
- Kubernetes Pods should be able to communicate across different Kubernetes Nodes using their IP Addresses.
- Kubernetes Pods can only access a Kubernetes Service by its shorthand service name if they are in the same Kubernetess Namespace. (Otherwise, use the FQDN.)
Kubernetes Endpoints
Kubernetes Endpoints lack a glossary entry but are supported using kubectl syntax.
They appear to refer to an assigned IP Address and Port combination (e.g. - the traditional use of the term as opposed to say an AWS API Gateway Endpoint which associates a specific DNS, URL Context Path, and API REST Method). As such, Kubernetes Endpoints can be associated with Kubernetes Pods or external Resources.
Example Minikube:
kubectl get endpoints
# NAME ENDPOINTS AGE
# kubernetes 192.168.49.2:8443 5h12m
Network Policies
- Ingress Policies - specify rules for inbound traffic.
- Egress Policies - specify rules for outbound traffic.
Configured through the NetworkPolicy Kind that's associated with one or more Kubernetes Pods through podSelector matchLabels.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector:
matchLabels:
app: myapp
policyTypes:
- Ingress
- Egress
A variety of values can be supplied:
- Default Policies:
default-deny-ingressallow-all-ingressdefault-deny-egressallow-all-egressdefault-deny-all
- Kubernetes Namespaces through the
namespaceSelectorfield. - Port ranges.
https://kubernetes.io/docs/concepts/services-networking/network-policies/
Ports
Important Kubernetes Port numbers: https://kubernetes.io/docs/reference/networking/ports-and-protocols/
| Port(s) or Range | Resource | Required | Description |
|---|---|---|---|
2379, 2380
|
etcd, also kube-apiserver
|
Yes. (Inbound.) | etcd default listening and API. |
6443
|
kube-apiserver |
Yes. (Inbound.) | Used by everything. |
10250
|
kubelet/kubelet API
|
Yes. (Inbound.) | Used on Control Plane and kubelet on all worker Nodes. |
10256
|
kube-proxy
|
Yes. (Inbound.) | Load balancers on worker Nodes. |
10257
|
kube-controller-manager
|
Yes. (Inbound.) | HTTPS on Control Plane. |
10259
|
kube-scheduler
|
Yes. (Inbound.) | Default listening on Control Plane. |
30000-32767
|
Everything. | Yes. (Inbound.) | NodePort Services on all worker Nodes. |
Resources and Links
- https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/
- https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/
- https://kubernetes.io/docs/concepts/services-networking/network-policies/
- https://stackoverflow.com/questions/52857825/what-is-an-endpoint-in-kubernetes
- https://kubernetes.io/docs/reference/networking/ports-and-protocols/
Linux Foundation CKA: Storage
Volumes and Volume Claims
- Kubernetes Volume Claims are singly attached to a Kubernetes Volume:
- Only one Kubernetes Volume Claim can bind to a Kubernetes Volume.
- Kubernetes Volumes without a Kubernetes Volume Claim are Unbound.
- Kubernetes Volume Claims that have no available Kubernetes Volumes remaining in a Pending state until a new Kubernetes Volume becomes available.
PersistentVolumeClaim,pvcis the Kubernetes Volume Claim KindPersistentVolume,pvis the Kubernetes Volume Kind.
Kubernetes Volume example YAML:
apiVersion: v1
kind: PersistentVolume
metadata:
name: postgres-volume
labels:
type: local
app: python-pyramid-postgres
service: postgres
spec:
storageClassName: local-storage
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
hostPath:
path: /data/postgresql
Kubernetes Volume Claim example YAML:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-volume-claim
labels:
type: local
app: python-pyramid-postgres
service: postgres
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 4Gi
volumeName: postgres-volume
storageClassName: local-storage
Reclaimation Policies
https://kubernetes.io/docs/concepts/storage/persistent-volumes/#reclaiming
Kubernetes Volume Reclaimation Policies specify what action(s) should occur when an associated Kubernetes Claim is Deleted:
Retain- Keeps the Volume but doesn't make it available again.
- https://kubernetes.io/docs/concepts/storage/persistent-volumes/#retain
Recycle- Scrubs, remove all data, then Unbinds making the Volume available again.
- This is now deprecated.
- https://kubernetes.io/docs/concepts/storage/persistent-volumes/#reclaiming
Delete- Deletes the Volume.
- https://kubernetes.io/docs/concepts/storage/persistent-volumes/#delete
Access Modes
Kubernetes Volume access modes:
readonlymanyreadwriteoncereadwritemany
Resources and Links
- https://kubernetes.io/docs/concepts/storage/persistent-volumes/
- https://kubernetes.io/docs/concepts/storage/persistent-volumes/#reclaiming
Code samples:
Linux Foundation CKA: Auto-Scaling
- Kubernetes Auto-Scaling is managed by dedicated Kubernetes Pods equipped with Controllers that track specified Metrics.
- Recommendations are then made on the basis of those Metrics and other specified Resource Limits/configurations.
- Default Resource Limits and/or Kubernetes Pod counts are intercepted and overridden based on those recommendations.
- Kubernetes Auto-Scaling comes in three varieties:
- Vertical Pod Autoscaler (VPA) for scaling the number of Kubernetes Pods that exist in a Kubernetes Deployment.
- Horizontal Pod Autoscaler (HPA) for dynamically modifying CPU and Memory Requests based on actual use.
- Cluster Autoscaler manages and scales Kubernetes Nodes based on use and demand.
| VPA | HPA | Cluster Autoscaler |
|---|---|---|
| Resource Requests | Pods | Nodes |
| CPU, RAM | Number of Pods | Number of Nodes |
Vertical Pod Autoscaler
Specifies how CPU and Memory Requests are updated based on actual use.
- Must first be independently installed
- Download and run the install script:
./hack/vpa-up.sh
- Download and run the install script:
- Given an existing Kubernetes Deployment (say,
my-example-deployment),kubectl apply -f vpa-example.yamlusing a YAML configuration:# vpa-example.yaml apiVersion: autoscaling.k8s.io/v1 kind: VerticalPodAutoscaler metadata: name: my-example-deployment-vpa spec: targetRef: apiVersion: "apps/v1" kind: Deployment # Associate the HPA with the Deployment name: my-example-deployment updatePolicy: # Take care here... updateMode: "Auto" updateModecan be set in four modes:"Auto""Recreate""Initial""Off"
kubectl get vpato retrieve information aboutVerticalPodAutoscalerobjects.
https://kubernetes.io/docs/concepts/workloads/autoscaling/#scaling-workloads-vertically
Horizontal Pod Autoscaler
Specifies a minReplicas to maxReplicas ranged controlled by specified metrics along with automatic auto-scaling to and from those quantities.
Given an existing Kubernetes Deployment (say, my-example-deployment):
- Create an HPA imperatively:
kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10 - Here's the declarative way to do so
kubectl apply -f hpa-example.yamlusing YAML:apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: my-example-deployment-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment # Associate the HPA with the Deployment name: my-example-deployment minReplicas: 1 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 50 kubectl get hpato retrieve information aboutHorizontalPodAutoscalerobjects.
Note: Kubernetes Replica Set
replicasvalues are overridden by HPAminReplicasandmaxReplicas. The number specified byreplicasis provisioned first, and is then adjusted by HPA to the desired min and max amounts.
https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/
Cluster Autoscaler
Typically used with a specific Cloud Provider.
Manages the number of and scaling for Kubernetes Nodes.
https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler
Resources and Links
- https://github.com/kubernetes/autoscaler/blob/master/vertical-pod-autoscaler/docs/installation.md
- https://technologyconversations.com/2018/10/10/to-replicas-or-not-to-replicas-in-kubernetes-deployments-and-statefulsets/
- https://stackoverflow.com/questions/66431556/what-is-the-relationship-between-the-hpa-and-replicaset-in-kubernetes
- https://github.com/kubernetes/autoscaler/blob/master/vertical-pod-autoscaler/docs/quickstart.md
- https://kubernetes.io/docs/concepts/workloads/autoscaling/#scaling-workloads-vertically
- https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/
- https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler
- https://medium.com/tensult/cluster-autoscaler-ca-and-horizontal-pod-autoscaler-hpa-on-kubernetes-f25ba7fd00b9
Linux Foundation CKA: GitOps
GitOps: tracking, versioning, and handling configuration code for infrasture.
Versioning
Versioning (in the context of Kubernetes) typically involves:
- Versioning Docker Images - handled through one's Docker Repository and Dockerfile (including but not limited to Docker Hub).
- Versioning of Kubernetes configuration - typically handled indirectly (through Docker Image versions mentioned above) or through a dedicated Package Manager like Helm.
- Kubernetes Labels might also suffice but I haven't personally seen them used for that purpose.
Helm
Helm is the primary Package Manager for Kubernetes.
Packages are organized into Helm Charts that add to standard Kubernetes YAML configuration templating features, built-in functions, more flexible syntax, etc.:
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Greetings Celestial Sphere!"
Push vs. Pull Approachs
- Push
- Triggered by Git Commit.
- It's oft-said that Secrets and credentials are often supplied by developers (say through their Git Repository) using this approach but it's required.
- Many newer CI/CD Pipelines integrate with tools like AWS KMS to retrieve Secrets combining a mix of Push and Pull approaches.
- Changes require a system external to the Cluster to have access.
- Pull
- Typically only encountered in Kubernetes deployments.
- Agent-based approaches (an Agent is installed and/or running within a Cluster).
- The Agent continuous monitors, scans, and then attepts to reconcile the Kubernetes deployment with some configuration or Source Code.
- The Agent is given access and permission to deploy changes, not the developer.
- More secure but far more bandwidth and Resource consumptive.
- Updates and changes are made and initiated from within the Cluster (by the Agent through constant scanning/polling).
Both approaches:
- Typically remove direct access and permission for a developer to make changes directly to Production.
- Automate the actual deployment, removal, and/or updating of Resources and code.
A good read: https://thenewstack.io/push-vs-pull-in-gitops-is-there-really-a-difference/
Benefits of GitOps CI/CD
- Can use Git to track both Source Code and infrastructure configuration.
- Supports automated rollbacks (to specific Git Commits, Tags, or prior Releases).
- Git is already used in most CI/CD Pipelines.
CI/CD Tools
Continuous Improvement is typically implemented using either:
- Continuous Integration and Continuous Delivery (CI/CD):
- Continuous Delivery stops short of automating Production deployments by requiring manual approval to do so.
- Typically encountered in heavily-regulated industries like Finance.
- Continuous Integration and Continuous Deployment (also, CI/CD):
- Continuous Deployment deploys code all the way to Production automatically.
CI/CD tools specific to Kubernetes:
- Flux CD
- Agent and Pull -based approach to CI/CD.
- Uses Helm by default.
- CLI-only.
- Argo CD
- Agent and Pull -based approach to CI/CD.
- Can integrate multiple Git Repositories across many Kubernetes Namespaces.
- More advanced overall synchronization capabilities.
- Growing in popularity.
- Considered easier to use and get started with out of the box.
- CLI and User Interface supported.
Resources and Links
- https://thenewstack.io/push-vs-pull-in-gitops-is-there-really-a-difference/
- https://helm.sh/
- https://helm.sh/docs/chart_template_guide/getting_started/
- https://fluxcd.io/flux/
- https://argo-cd.readthedocs.io/
- https://earthly.dev/blog/flux-vs-argo-cd/
- https://blog.aenix.io/argo-cd-vs-flux-cd-7b1d67a246ca
- https://dev.to/ariefwara/jenkins-argo-cd-4ld5
Linux Foundation CKA: Useful Commands
Commands that are useful for the exam itself.
Core Commands
# Switch Namespace context
kubectl config set-context --current --namespace=test
# Get all Resources
kubectl get all
# Get all Pods regardless of Namespace
kubectl get po --all-namespaces
## Inspect specific Pod
kubectl get pod mypod
### Detailed info
kubectl describe pod mypod
# Dry run/don't actually create and output a YAML file with filename
kubectl create deployment --image=nginx nginx --dry-run=client -o yaml > nginx-deployment.yaml
# See the YAML config for a Resource, edit it live w/out saving, and automatically apply those changes
kubectl edit rs new-replica-set
# Create or update Pod from a file (see below)
kubectl apply -f pod-definition.yaml
## kubectl apply is often preferred over create and/or replace
# Create and run a Pod named nginx using the Image nginx w/out a config file
kubectl run nginx --image=nginx
# Print out config to YAML
kubectl get deploy nginx -o yaml > nginx.yaml
# Create a Service named redis-service with Pod redis associated on Port 6379
kubectl expose pod redis --port=6379 --name redis-service
kubectl expose pod httpd --port=80 --name=httpd --type=ClusterIP
# Check to see if I can create pods in any namespace
kubectl auth can-i create pods --all-namespaces
# Show all Labels
kubectl get nodes --show-labels
# Create a new Label on a Node
kubectl label nodes my-node-name x=y
# Add a taint
kubectl taint nodes controlplane x=y:NoSchedule
# Remove a taint
kubectl taint nodes controlplane x=y:NoSchedule-
# View taints
kubectl describe node controlplane |grep Taint
## These are present in `kubectl describe`
Techniques
If a YAML is needed as a baseline one can be generated like so:
# Print out config to YAML
kubectl get deploy nginx -o yaml > nginx.yaml
# Then override and update current Resources
kubectl replace -f nginx.yml --force
Sometimes a field is protected (containers[0].name). This can nevertheless be updated by recreating:
# Edit some Resource
kubectl edit pod my-pod
# Even if it errors out a copy is saved to /tmp/
## /tmp/kubectl-edit-12345667.yml
# Update through recreation
kubectl delete pod my-pod
kubectl apply -f /tmp/kubectl-edit-12345667.yml
touch my.yaml
vi my.yaml # Vim if nano not present in env
nano my.yaml # Nano text editor