Kubernetes — Container as a Service
Quick Reference
Overview
Kubernetes aka K8s …manage containerized workloads and services
- …supports declarative configuration …automates deployment
- …runs on virtual and physical environments …on-premise & public clouds
- …reference infrastructure for cloud-native1˒2 applications
- Benefits of the Kubernetes architecture…
- …service discovery …networks, devices, service, metadata, etc
- …storage orchestration …decouple storage allocation from back-ends
- …container run-time agnostic …use any OCI compliant container engine
- …provider agnostic …no vendor lock-in to a specific IaaS
- …productivity …enables fast deployment CI/CD & DevOps
What can be difficult with Kubernetes?
- Hard multi-tenancy…
- …options for cluster-level sharing are available
- …however difficult where the tenants do not trust each other
- …typically each tenant is hosted a dedicated cluster instance
- Most deployments are virtual …and run on a cloud infrastructure
- …many use-cases & examples specific to cloud providers
- …bare-metal deployment not widely used …hence more challenging to build
Architecture
# display cluster information
kubectl cluster-info
# list cluster nodes
kubectl get nodes
# additional details about a node
kubectl describe node $node_name
Control plane — Manages worker nodes & pods in the cluster
- …usually runs distributed over multiple nodes (fault-tolerance, highly-available)
- Control plane components …global decisions about the cluster:
- API server
- …core component server …exposes the Kubernetes API
- …runs several instances of
kube-apiserver
to scale horizontally
- Cluster Storage
- …consistent and highly-available key value store
- …
etcd
3 …uses Raft consensus algorithm - …data is consistently replicated across multiple nodes
- …supports built-in snapshots for backup
- Scheduler
- …
kube-scheduler
…basically assigns pods to nodes - …monitors cluster resources …uses various policies for placement
- …
- Controllers …manage the cluster state
- …
kube-controller-manager
…runs individual controller processes - …different controllers for nodes, jobs, services, etc.
- …
- API server
Worker nodes — Host pods that house containerized applications
- …provide the Kubernetes run-time environment
- Components that run on every node:
kubelet
4 …primary “node agent”- …works in terms of a PodSpec …YAML/JSON object describing a pod
- …ensures that pods are running and healthy
kube-proxy
(optional) …connects pods with a network- …uses the OS packet filter …otherwise forwards the traffic itself
- …other network plugins implement CNI (Container Network Interface)
- Container run-time …Kubernetes CRI (Container Runtime Interface)
Objects
Objects — Specific configurations that define the desired state
- “Configuration that describes what you want to run”
- After an object is created…
- …it represents a specific entity with its own configuration and purpose
- …system will constantly work to ensure that the object exists
- An object includes two nested object fields:
- …object spec describes the desired state for the object
- …object status describes the actual state of the object
# list supported resources
kubectl api-resources
Resources — Components that can be managed within the cluster
- Generally refers to quantifiable units of compute, storage, and networking
- Resources include the object themselves and underlying hardware used
- “Not all resources are necessarily objects in the same sense”
Manifests
Manifests — Files that describe what to deploy
- Deployments created by posting a manifest to the Kubernetes API
- Why use Kubernetes manifest files?
- Declarative configuration …predictable correct state
- Prevents configuration drift by re-applying manifest
- Configuration as code …maintained with version control system
- Allows structured collaboration with co-workers
- Format described in the Kubernetes API5
# discover possible API object fields
kubectl explain $object # describe associated fields
kubectl explain $object --recursive # list all possible fields and subfields
kubectl explain $object.metadata # get details on fields
Main parts of a manifest:
kind
— Object typemetadata
— Name, namespace & labelsspec
— Containers, volumes, etc.
# example for a pod object
apiVersion: apps/v1 # Kubernetes API version
kind: Pod # Type of resource
metadata:
name: nginx # Name of the resource
spec:
containers:
- name: nginx # Name of the container
image: nginx:latest # Image to create the container from
Usage
Install the kubectl
binary to $HOME/bin
:
ver=$(curl -L -s https://dl.k8s.io/release/stable.txt)
url=https://dl.k8s.io/release/$ver/bin/linux/amd64/kubectl
curl -Lo ~/bin/kubectl $url && chmod +x ~/bin/kubectl
# load tab-completion
source <(kubectl completion bash)
Custom configuration file:
export KUBECONFIG=$(realpath kubeconfig.yml)
# check your current context
kubectl config view
# check resource access
kubectl auth can-i get pods
kubectl run
# start an interactive container…
kubectl run $pod_name --image=$image --restart=Never --stdin --tty
kubectl delete pods $pod_name
# specific shell
kubectl run $pod_name --image=$image --restart=Never -it --rm -- /bin/bash
# specific application (Perl in this example)
kubectl run $pod_name --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'
kubectl run
6 common options:
--image=
— which container image to use-it
aka--stdin
&--tty
— spawn an interactive shell- …allocate a terminal for each container
- …keep
stdin
open (even if empty)
- Clean up…
--restart=Never
— pod should never be restarted--rm
— automatically remove pod after exit
kubectl exec
# execute a command in a specified pod
kubectl exec $pod_name -- curl -s https://10.20.30.40
# specify a container
kubectl exec $pod_name -c $container_name #...
# start an interactive shell
kubectl exec -it my-pod -- /bin/bash
Use cases…
- …debugging & diagnostics …for example check logs, inspect files
- …modify configuration files & environment variables
- …run test scripts …validate application behavior
# copy file to & from containers
kubectl cp /local/path $pod_name:/path/in/container
kubectl cp $pod_name:/path/in/container /local/path
kubectl logs
# show logs entires from the last rotation
kubectl logs $pod_name
# show logs for a specific container
kubectl logs $pod_name -c $container_name
Containerized application log to stdout/stderr…
- …automatically rotated daily …every time the logs reaches 10MB
- …logs deleted when the pod is deleted
kubectl apply
Imperative commands — Fail if a resource exists already
# run an instance of the nginx container by creating a deployment object
kubectl create deployment nginx --image nginx
# create the objects defined in a configuration file
kubectl create -f deployment.yaml
# update the objects defined in a configuration file
# note: dropping all changes to the object missing from the configuration file
kubectl replace -f deployment.yaml
Declarative commands — Create new or modify existing objects
- …create, update, and delete operations are automatically detected per-object
- …retains changes, even if the changes are not in the object configuration file
# apply changes
kubectl apply -f nginx/
# see what changes are going to be made
kubectl diff -f nginx/
# use option -R for recursive directory decent
Pods
# list pods
kubectl get pods -o wide
# detailed information
kubectl describe pod $pod_name
Pod — Smallest deployable compute object in Kubernetes…
- Group of one or more tightly related container
- Container in a pod will always run together…
- …on the same worker node …same Linux namespace
- …“running on the same logical machine”
Pod life-cycle
Pending
— ready for scheduling …not started yetRunning
— Pod bound to a node …containers createdSucceeded
— Pod containers terminated in success (no restart)Failed
— Container terminated in failure (non-zero status)Unknown
— Pod state could not be obtained- Container states inside a pod…
Waiting
— Running operations to complete startupRunning
— Container is executing without issuesTerminated
— Container ran to completion or failed for some reason
Command & Arguments
spec:
containers:
- name: #…
command: ["/bin/sh", "-c"]
args: ["echo 'Hello, World!' && sleep 3600"]
spec:
containers:
- name: #…
command: ["/bin/sh", "-c"]
args:
- |
echo "Hello World!" sleep 3600
Define commands & arguments for a container in a pod:
- …override default from the container image
- …if only arguments are defined the default command is used
command
— Command to run when the container starts- …corresponds to an entrypoint in a Dockerfile
args
— Arguments to pass to the command
# define an argument by environment variable
spec:
containers:
- name: #…
env:
- name: MESSAGE
value: "hello world"
command: ["/bin/echo"]
args: ["$(MESSAGE)"] # variable expansion
Namespaces
Mechanism for isolating groups of resources within a single cluster
- …scoping is applicable only for namespaced objects
- …divide cluster resources between multiple users (via resource quota)
- Namespaces
default
for new clusters without first creating a namespace
# list current namespaces
kubectl get namespace
# set the namespace for a current request
kubectl <...> --namespace=$name
# set namespace preference
kubectl config set-context --current --namespace=$name
# ...to unset
kubectl config set-context --current --namespace=''
Labels & Annotations
Labels are key/value pairs to specify identifying attributes of objects…
- …used to organize and to select subsets of objects
- …each key must be unique for a given object
- …common set of labels allows tools to work interoperable
- …labels without a prefix are private to users
Labels are defined in the metadata.labels
object:
apiVersion: v1
kind: Pod
metadata:
# ...
labels:
environment: prod
name: mariadb
component: database
part-of: slurm
#...
# list objects with a given label
kubectl get <...> -l 'component=database,part-of=slurm'
kubectl get <...> -l 'environment in (prod,dev)'
Po# list all labels of an object
kubectl get <...> -o json | jq .metadata.labels
Shared labels/annotations have a common prefix <prefix>/<name>
<prefix>
(optional) needs to be a valid DNS subdomain<name>
arbitrary property name of the label
Annotations attach arbitrary non-identifying metadata to objects
Secrets
# create a secret
kubectl create secret generic project-secret \
--from-literal=username=alice --from-literal=password=abc123
spec:
containers:
env:
- name: USERNAME
valueFrom:
secretKeyRef:
name: project-secret
key: username
- name: PASSWORD
valueFrom:
secretKeyRef:
name: project-secret
key: password
Store & manage sensitive information like passwords, SSH keys, OAuth tokens
- Ensure secret information is not exposed in configuration files
- Enables processes to regularity rotate secrets
Secrets are stored in the etcd database…
- …in a Base64-encoded format …basically exposed on access to the database
- Encryption at Rest — Encryption data before storing to the database
TODO…
Services
# list all services in a cluster
kubectl get service
# create a load-balancer service object
kubectl expose $object $name --type=LoadBalancer --name=$name
# remove a service object
kubectl delete service $name
Services — Constant point of entry to a group of pods
- Pods get dedicated internal IP addresses…
- …Pods are not accessible from outside by default
- Why using a service?
- Route external connections to pods backing a service
- Clients do not need to know individual pods
- Single constant IP-address for a service
Pods need to be exposed through a service object:
ClusterIP
— Reserve a static virtual IP address- Accessible only within the cluster
- Internal communication between services
- Load-balanced within the cluster
NodePort
— Forward traffic to specific port- Accessible from outside the cluster via node IP address
- Each node forwards traffic to a specific port
LoadBalancer
— External load balancer with public IP- Accessible from outside via load balancer IP address
- For production …distributes traffic over nodes
# forward a local network port to a port in the pod
kubectl port-forward $pod_name $local_port:$pod_port
Connect to a specific pod without going through a service…
- …typically for debugging & testing individual pods
- …notation is local port, colon followed by port in the pod
ClusterIP
Service object to assign an IP address to an application (the cluster IP):
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app.kubernetes.io/name: MyApp
ports:
- protocol: TCP
port: 80 # service endpoint port
targetPort: 9376 # target port on the application pods
Load Balancer
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: LoadBalancer
selector:
app: my-app # identify pods for this service
ports:
- port: 8080 # service port
targetPort: 8080 # foward to container port
Configure session affinity for a service…
- …clients are redirected to the same port every time
- …defaults to
None
if not specified
spec:
sessionsAffinity: ClientIP
Pods backing a service can not see the actual client IP-address…
- …packets source IP changed for cluster internal routing
- …SNAT (Source Network Access Translation) performed on each package
Ingress
Ingress — Access for HTTP/S traffic to the cluster
- Operates on the application layer of the network stack (HTTP)
- Why use ingress?
- Path- & Host-based routing …typically an URL path
- Multiple services can share a single IP-address
- Manage SSL certificates and terminate SSL connections
- Manage authentication and authorization
- Ingress controllers
- NGINX Ingress Controller
- Traefik …HTTP reverse proxy and load balance
- HAProxy Ingress
Containers
Kubernetes supports various container patterns
Container Pattern | Description |
---|---|
Main | Core functionality of a pod |
InitContainer | Run before the main application container |
SideCar | Run alongside the main application container |
Job | One-off tasks …runs until completion |
CronJob | One-time Jobs …repeating schedule |
ReplicaSet | Maintain a stable set of pods |
Deployment | Stateless application workload |
StatefulSet | Persistent storage & unique network identity |
DaemonSet | Local to specific nodes |
Ambassador | Communication proxy for external services |
Adapter | Transform formats/protocols to ensure compatibility |
Jobs
job_name=hello
cat > $job_name.yml <<EOF
apiVersion: batch/v1
kind: Job
metadata:
name: $job_name
spec:
template:
spec:
containers:
- name: hello
image: busybox
command: ["echo", "Hello, World!"]
restartPolicy: OnFailure
EOF
# create job (if not existing)
kubectl create -f $job_name.yml
# inspect job state
kubectl get jobs $job_name
kubectl describe jobs $job_name
# print the logs
kubectl logs job/$job_name
# clean up
kubectl delete job $job_name
Run the parallel job example:
job_name=sleep-parallel
cat > $job_name.yml <<EOF
apiVersion: batch/v1
kind: Job
metadata:
name: $job_name
spec:
completions: 6
parallelism: 2
template:
spec:
containers:
- name: sleep
image: busybox
command: ["sleep", "60"]
restartPolicy: Never
EOF
kubectl create -f $job_name.yml
# watch the status of pods created
kubectl get -w pods -l job-name=$job_name
# clean up
kubectl delete -f $job_name.yml
completions
number of pods to completeparallelism
number of pods to run in parallel
Cronjob
Run jobs on a scheduled interval
apiVersion: batch/v1
kind: CronJob
metadata:
name: project-crontjob
spec:
schedule: "*/1 * * * *" # Cron format for the schedule
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
command: ["echo", "Hello, World!"]
restartPolicy: OnFailure
Each CronJob creates a Job …each Job runs a single Pod
# list cronjobs
kubectl get cronjobs $name
# list the jobs
kubectl get jobs --watch
# remove a cronjob
kubectl delete cronjob $name
The job name is different from the pod name
# list pods for a given job
kubectl get pods --selector=job-name=$name --output=jsonpath={.items[*].metadata.name}
Manually start a cron job… --from=crontjob/
to specify the CronJob to use as template:
kubectl create job --from=cronjob/$cronjob_name $job_name
ReplicaSet
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: my-replicaset
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: my-image:latest
Manage a number of Pod replicas and their life-cycle
- Monitor health & automatically re-create pods on failure
- Features: scaling, self-healing, label selector, rolling updates
- Important fields:
replicas
— Number of podsselector
— How to identify pods belonging to the ReplicaSettemplate
— Describe the pods
Add additional expressions to the selector:
# more expressive label selector
selector:
matchExpression:
- key: app
operator: In
values:
- my-app
- Valid operators…
In
…labels value must matchNotIn
…labels value must not matchExists
…pod must include label with keyDoesNotExist
…pod must not include label with key
- Multiple expressions must all evaluate to true
- Possible to combine
matchLabels
withmatchExpressions
Deployment
Deployments7 provide rollback functionality and update control
Download nginx-deployment.yaml
Kubernetes example:
kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
# inspect the deployment
kubectl get deployments
# see the ReplicaSet created by the Deployment
kubectl get kubectl get replicaset
# list the pods (using a label)
kubectl get pods -l app=nginx
Rolling update incremental replacement of multiple pods
- …no downtime …network traffic load-balanced to available pods
- …facilitates CI/CD deployments …support rollback to previous version
# update pods to a new container version
kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1
# check the revisions of this Deployment
kubectl rollout history deployment/nginx-deployment
# undo the current rollout and rollback to the previous revision
kubectl rollout undo deployment/nginx-deployment
Scaling an application on demand…
- …increase the number of pods to a desired state
- …supports (horizontal) autoscaling depending to load
# scale a deployment
kubectl scale deployment/nginx-deployment --replicas=5
# remove a deployment
kubectl delete deployment nginx-deployment
Init Container
Example: Use an initContainer
to clone a Git repository:
spec:
volumes:
- name: repo
emptyDir: {}
initContainers:
- name: git-clone
image: alpine/git
env:
- name: GITLAB_TOKEN
valueFrom:
secretKeyRef:
key: gitlab-token
name: project-secrets
args:
- 'clone'
- 'https://none:$(GITLAB_TOKEN)@example.org/path/to/repo.git'
- '/srv/repo'
volumeMounts:
- name: repo
mountPath: /srv
Run before the main application container
- Why — Perform initialization tasks
- Sequential execution…
- …multiple init containers run in sequence
- …containers must run successful before the next starts
- …failing init containers restarted until success
- Main application container starts after success of all init containers
Sidecar
Run alongside the main application container
- Why use a sidecar container?
- Collect monitoring metrics & health information
- Proxy and network communication
- Log forwarding …update of service components
- Co-location — Share resources with the main container
- Stop/start alongside the main container
Storage
Commands to overview storage:
# list persistent volumes (pv)
kubectl get pv
# list persistent volume claims (pvc)
kubectl get pvc
# list storage classes (sc)
kubectl get sc
Long-term & temporary storage for pods…
- Container storage is ephemeral (aka temporary)…
- …data created/modified during lifetime is lost
- …restart boots a container with clean state
Volumes8 (directory accessible to the container)
- …many types of volumes …pods can use multiple types simultaneously
- …mount at the specified paths within the container
- Ephemeral volumes …have the lifetime of a pod
- Persistent volumes …exist beyond the lifetime of a pod
Volume Types
Commonly used…
emptyDir
— Simple empty directory …for transient datahostPath
— Directory from the work nodenfs
— Mount of an NFS shareconfigMap
— Non-confidential configuration …key-value pairssecret
— Passwords, Oath tokens, SSH keys, etc.downwardAPI
— Access pod metadata & cluster contextpersistantVolumeClaim
— Use pre- & dynamic provisioned persistent storage
Mount other network storage for example cephfs
, rbd
, etc.
Common Fields
Common fields for persistent volumes:
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 10Gi
persistentVolumeReclaimPolicy: Retain
accessModes
supports the following access modesReadWriteOnce
— read-write by a single podReadOnlyMany
— read-only by multiple podsReadWriteMany
— read-write by multiple pods
capacity.storage
— Valid suffixMi
,Gi
,Ti
persistentVolumeReclaimPolicy
what happens if claim is releasedRetain
— PV will not be deleted …remain in theReleased
stateDelete
— Storage resource will be deleted automatically
EmptyDir
An emptyDir
volume is created when a pod is assigned to a node…
- …on storage local to the worker node
- …deleted when the pod is removed …safe across container crashes
- Why use an
emptydir
?- User for temporary scratch space
- Share files between container running in the same pod
apiVersion: v1
kind: Pod
metadata:
name: test-emptydir
spec:
volumes:
- name: opt
emptyDir: {}
containers:
- name: container-one
volumeMounts:
- name: opt
mountPath: /opt
image: alpine
command: ["/bin/sh"]
args: ["-c", "sleep 10000"]
- name: container-two
volumeMounts:
- name: opt
mountPath: /opt
image: alpine
command: ["/bin/sh"]
args: ["-c", "sleep 10000"]
# write a file into the mounted volume from the first container
kubectl exec test-emptydir -c container-one -- cp /etc/hostname /opt
# read the file from the second container
kubectl exec test-emptydir -c container-two -- cat /opt/hostname
Use an tmpfs file-system in memory instead of local storage:
volumes:
- name: html
emptyDir:
medium: Memory
Host Path
kind: PersistentVolume
metadata:
name: project-storage
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 10Gi
hostPath:
path: /data/project/ # absolute path on the host node
Mount the host node’s file-system into a pod
- Capacity is determined by the available space on the host node
- No Quotas or limits imposed …responsibility outside Kubernetes
- Data persistent as long as host node is operational
- Typical use-cases:
- Testing & development
- Access logs & configuration files on the host
- Share data between pods on the same host
Storage Classes
Storage Classes are an abstraction layer over the underlying storage infrastructure
- Define properties/behavior of PVs, quality-of-service levels, (backup) policies
- Enable automatic provisioning of storage characteristics…
- …type of the storage (for example SSD, HDD)
- …access modes (read-only, read-write, etc.)
kubectl get sc
CSI (Container Storage Interface) volume plugins…
- …enable storage vendors to create custom storage plugins
- …uses the
csi
volume type to attach or mount the volumes
Persistent Volumes
Persistent Volumes9 (PV) are a way to abstract and represent physical or networked storage resources
Why use persistent volumes?
- Data persistence vital to stateful applications and databases
- Abstraction of the back-end storage
- …allows to manage storage resources independently
- …enables admins control utilization and optimization of storage hardware
- Access control to ensure data integrity and security
Persistent Volume Claims (PVC) request storage resources for pods
- Used to specific requirements to the storage resource
- …independent of the internals of the storage provider
- Ensures a volume ‘claim’ to be portable across numerous back-ends
- Isolates storage-related concerns from the workload
example.yml
apiVersion: v1
kind: PersistentVolume
metadata:
name: example-storage
spec:
capacity:
storage: 500Mi
# Indicating that this PV is intended for file-based storage
volumeMode: Filesystem
# Can be mounted as read-write by a single node at a time
accessModes:
- ReadWriteOnce
# Data is retained even if the associated PVC is deleted
# …requires to be removed manual for cleanup
persistentVolumeReclaimPolicy: Retain
# Associates to a particular StorageClass
storageClassName: local-storage
# Specify the actual location on the host machine
hostPath:
path: /srv
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: example-claim
spec:
# can be mounted as read-write by a single node at a time
accessModes:
- ReadWriteOnce
resources:
requests:
# request minimum storage capacity
storage: 200Mi
# associates with a StorageClass
storageClassName: local-storage
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
# mount volumes to the container
volumeMounts:
# which volume to mount
- name: example-nginx-storage
# where to mount the volume inside the container
mountPath: /usr/share/nginx/html
# define volumes available to the pod
volumes:
- name: example-nginx-storage
persistentVolumeClaim:
claimName: example-claim
kubectl apply -f example.yml
# check ...clean up
kubectl get -f example.yml
kubectl delete -f example.yml
ConfigMap
# create a ConfigMap directly from literal values
kubectl create configmap project-config \
--from-literal=key1=value1 --from-literal=key2=value2
# create a ConfigMap from a file
kubectl create configmap project-config \
--from-file=project-config.properties
kubectl create configmap project-config \
--from-file=/path/to/project-config/
Manage configuration settings for applications
- For non-confidential configuration only (cf. Kubernetes secrets)
- Values can be strings, numbers, JSON, YAML
- Version control configuration separate form application code & container images
Example of a configuration file nginx.conf
used by a pod:
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-conf
data:
nginx.conf: |
user nginx;
worker_processes 1;
events {
worker_connections 10240;
}
http {
server {
listen 80;
server_name localhost;
location / {
root /srv/htdocs;
index index.html index.htm;
}
}
}
---
apiVersion: v1
kind: Pod
metadata:
name: website
spec:
containers:
- name: web-server
image: nginx:alpine
ports:
- containerPort: 80
volumeMounts:
- name: html
mountPath: /srv
readOnly: true
- name: nginx-conf
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
readOnly: true
Footnotes
CNCF (Cloud Native Computing Foundation)
https://landscape.cncf.io/↩︎Open Service Broker API Specification
https://www.openservicebrokerapi.org
https://github.com/openservicebrokerapi/servicebroker↩︎etcd
Documentation
https://etcd.io/docs
https://raft.github.io↩︎kubelet
, Documentation
https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/↩︎Kuberneter API Documentation
https://kubernetes.io/docs/reference/using-api
https://kubernetes.io/docs/reference/#api-reference↩︎kubectl run
, Documentation
https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#run↩︎Kubernetes Deployments https://kubernetes.io/docs/concepts/workloads/controllers/deployment↩︎
Kubernetes Volumes
https://kubernetes.io/docs/concepts/storage/volumes/↩︎Persistent Volumes, Kubernetes Documentation
https://kubernetes.io/docs/concepts/storage/persistent-volumes/↩︎