Understanding the Basics of Kubernetes
On this page
Overview
History
An open-source project that began at Google and was developed by the community
Various commercial Kubernetes offerings have emerged (OpenShift, EKS, GKE, etc.)

Need
A platform for container-based microservices
Adopting a DevOps culture

Cluster
Configuring a virtual layer on top of server infrastructure
User apps are managed on top of it
Developers do not need to interact directly with the infrastructure

Namespace
A concept for logically isolating and managing Kubernetes resources

What does it provide?
Given an app state definition, it operates according to that definition
Application state definition: Kubernetes resource definition in YAML or JSON format

K8s resources?
apiVersion: apps/v1 kind: Deployment metadata: name: broken-pods spec: replicas: 3 selector: matchLabels: app: broken-pod template: metadata: labels: app: broken-pod spec: containers: - name: broken-container image: busybox command: ["sh", "-c", "exit 1"]
What happens when the application state definition changes?
Kubernetes automatically updates everything to match the new definition
Conclusion: All you need to do is define the app state correctly!

Kubernetes is Kubernetes, no matter where you use it

Configuring a k8s cluster
Control Plane Nodes
Components required for k8s to run are executed
API Server
etcd
Controller Manager
Scheduler
...
Workload nodes
User applications run

Internal configuration of each node
Contains a container runtime
Controlled by the k8s node agent

Relationship between k8s and Docker
Docker was the only runtime
Emergence of other runtimes (rkt, Hypernetes)
Kubernetes CRI
Docker Engine is not CRI-compatible
Dockershim
Dockershim support was discontinued starting with Kubernetes version 1.24
containerd, cri-o,

How to Communicate with Kubernetes
kubectl
Helm
argocd
Kubernetes dashboard tools such as Lens
All of these use the kube-api

Workloads
Container
Containers are implemented using the following Linux kernel features
namespace - a feature for logical isolation
cgroup – Resource limiting
Containers vs. Virtual Machines
No additional OS or kernel required
No performance degradation since there is no virtualization

Pod
Definition:
A Pod is the smallest and most basic deployment unit in Kubernetes.
It consists of one or more containers that share storage and network resources.
It represents a single logical application unit.

Key Features:
Co-location and Co-scheduling: All containers within a Pod run on the same node and are scheduled together.
Shared Network Namespace: Containers share the same IP address and networking configuration.
Shared storage: A Pod can access a shared volume for persistent data storage.
Ephemeral: Pods are generally designed to be recreated after termination.
Components:
Container: The actual application execution unit within a Pod
Volume: Persistent storage attached to a Pod. Accessible to all containers.
Secrets and ConfigMaps: Securely store sensitive information or configuration data.
Lifecycle Hooks: Scripts executed during Pod creation, startup, or termination
Liveness and Readiness Probes: Monitor container status and verify Pod availability.
Network Communication:
Containers within a Pod can communicate freely using a loopback interface.
Pods communicate with each other using internal IP addresses on the cluster network.
Pods access external services through services.
simple.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
ReplicaSet
Definition:
A ReplicaSet creates and manages Pods based on a container image and automatically restarts them when they terminate.
A ReplicaSet is a controller in Kubernetes used to maintain the desired number of Pods for a specific application.
Key Features:
Maintaining the Number of Pods: It ensures that the desired number of Pods is always running.
Pod Management: Automatically manages Pod creation, deletion, and restarting.
Pod Template: Defines the Pod’s spec (container image, resource requests/limits, etc.).

Selector and Label
A ReplicaSet uses labels to identify the Pods it manages.

apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: guestbook
tier: frontend
spec:
replicas: 3
selector:
matchLabels:
tier: frontend
template:
metadata:
labels:
tier: frontend
spec:
containers:
- name: php-redis
image: gcr.io/google_samples/gb-frontend:v3
Deployment
Definition
A Deployment is a resource used in Kubernetes to automate deployment via ReplicaSets.
It is implemented based on a ReplicaSet and manages not only the number of Pods but also changes to the Pod specification.
Key Features
Pod State Management: Declaratively defines the desired number of Pods and their specifications.
Pod Template: The specification used when creating new Pods.
Selector: A label used to select the Pods that the Deployment will manage.
Rolling Updates: You can gradually update the application by modifying the Pod template.
Rollback: If a problem occurs during an update, you can roll back to the previous version.
Various Update Strategies: You can control the deployment process using customizable update strategies.



Deployment Methods
Recreate
Rolling Update

ReplicaSet Replacement
When deploying a new version, Deployment internally creates a new ReplicaSet.

Deployment History
Deployment history is stored in the form of ReplicaSets.
Managing Deployment History
Rollback

Other Workloads…
DaemonSet
StatefulSet
Job
CronJob
App Config
ConfigMap
Secret
ConfigMap
ConfigMap is used to manage the configuration and environment files of containerized applications separately from the containers.
By separating the application container from its configuration, the same container can be deployed to multiple environments with different configurations.
Same Image, Different Environments

Key Concepts
Key-value pair: A ConfigMap consists of key-value pairs, where each key identifies a configuration item. The value represents the data for that configuration item.
Data: The data stored in a ConfigMap is typically in text format. This data can be used as environment variables, configuration files, command-line arguments, and more.
Volume Mount: A ConfigMap can be mounted as a volume so that the application container can access the configuration data from within it.
ConfigMap Usage
ENV
FILE

configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: my-config
data:
db_host: db.example.com
db_port: "3306"
pod.yaml
spec:
containers:
- name: my-app
image: my-app-image
envFrom:
- configMapRef:
name: my-config
Mounting a ConfigMap as a file
key: file name
value: file content

configmap.yaml
kind: ConfigMap
metadata:
name: my-configmap
data:
my-config-file.txt: |
key1=value1
key2=value2
pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: my-image
volumeMounts:
- name: config-volume
mountPath: /path/to/config
volumes:
- name: config-volume
configMap:
name: my-configmap
items:
- key: my-config-file.txt
path: my-config-file.txt
Secret
The basic usage is the same as ConfigMap, but since it is a resource designed to manage sensitive data, there are a few differences. It is generally used to store passwords, API tokens, TLS certificates, SSH keys, and so on.
Differences from ConfigMap:
Base64 encoding
Data is stored only in memory and not on disk.
Provides data type definitions.
Built-in TypeUsageOpaquearbitrary user-defined datakubernetes.io/dockercfgserialized ~/.dockercfg filekubernetes.io/dockerconfigjsonserialized ~/.docker/config.json filekubernetes.io/basic-auth: credentials for basic authenticationkubernetes.io/ssh-auth: credentials for SSH authentication; kubernetes.io/tls: data for a TLS client or server; kubernetes.io/service-account-token: ServiceAccount token; bootstrap.kubernetes.io/token: bootstrap token data

Docker config Secret
A special type of Secret for Container Registry account information
apiVersion: v1
kind: Secret
metadata:
name: secret-dockercfg
type: kubernetes.io/dockercfg
data:
.dockercfg: |
eyJhdXRocyI6eyJodHRwczovL2V4YW1wbGUvdjEvIjp7ImF1dGgiOiJvcGVuc2VzYW1lIn19fQo=
General environment variables
containers:
- name: my-app
image: my-app-image
env:
- name: DB_HOST
value: db.example.com
- name: DB_PORT
value: "3306"
Network
Service
Definition:
Pods are ephemeral!!!
Fixed Endpoint: A K8S service provides a single access point to a set of Pods within the cluster.
Traffic Distribution: Services distribute traffic across multiple Pods and balance the load.
Key Features:
Load Balancing: Distributes traffic using various load-balancing algorithms.
Session Persistence: Maintains client connections to specific Pods through session persistence policies.
Like a ReplicaSet, it locates target Pods using labels.

Service Types:
ClusterIP: The service can only be accessed by Pods within the cluster.
NodePort: The service can be accessed through a specific port on any node.
LoadBalancer: The service can be accessed using a cloud load balancer.
ExternalName: You can manage information about external endpoints.
ClusterIP
Virtual IP Address: A ClusterIP service assigns a virtual IP address that is accessible only within the cluster. This allows other Pods or services to access the service using that virtual IP address.
Internal Communication: The ClusterIP service is primarily used for communication between services within the cluster. It is used when other Pods or services within the cluster call that service.
Load Balancing: For services with multiple Pods, the ClusterIP service performs load balancing to distribute requests across those Pods.
Session Persistence: The ClusterIP service does not provide functionality to maintain connections or manage sessions between clients and the service. Therefore, you may need to use other resources, such as a StatefulSet, to maintain state between the service and clients.
Kubernetes DNS: A ClusterIP service is automatically assigned a DNS name within the cluster. This allows other Pods or services to access the service using that DNS name.

apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app.kubernetes.io/name: MyApp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 9376
- name: https
protocol: TCP
port: 443
targetPort: 9377
NodePort
External Access: A NodePort service exposes an application within the cluster to external access through a specified port.
NodePort: Defines a port on each node in the cluster through which the service can be accessed. All nodes in the cluster can access the service through this port.
Target Port: Defines the port of the backend application to which the service connects. A NodePort service connects to the application within the cluster through this port.
Service Port: Defines the port through which the service can be accessed from within the cluster. It is typically used within the cluster for the service.
External Cluster Access: You can access the application from outside the cluster via a NodePort service. Access is achieved using each node’s external IP address or hostname and the specified node port.
Load Balancing: Load balancing is performed to distribute access to the service across multiple nodes. Kubernetes performs load balancing through NodePort services.


Load Balancer
Scalable NodePort-type
Available only from providers that offer this type of service

ExternalName
External Service Access: Used when access to an external service is required. For example, there may be cases where an application inside the cluster needs to access an external service. In such cases, an ExternalName service can be used to expose the DNS name of the external service to the cluster.
Service Abstraction: This abstracts the service so that it can be accessed via a DNS name without directly exposing the external service’s IP address or port. This hides the specific implementation details of the external service.
Environment Isolation: By defining a separate service for accessing external services, you can isolate the internal and external parts of the cluster and enhance security. Access permissions to external services can be managed separately.
Ease of Service Renaming: If the location or name of an external service changes, applications within the cluster only need to update the DNS name, allowing for flexible adaptation to such changes.
Testing Environment: When conducting tests in a specific environment, you can define a test service to stand in for the actual service. This allows you to perform tests safely without affecting the actual service.
Ingress

Kubernetes Ingress is an API and resource for routing traffic to and from the cluster. An Ingress resource defines HTTP and HTTPS routing rules for applications both inside and outside the cluster.
Roles
Host-based routing: An Ingress resource can route traffic to different services based on hostnames. For example, it can route www.example.com과 and api.example.com to different services.
Path-based routing: An Ingress resource can route traffic to different services based on URL paths. For example, it can route requests with the /app1 path to Service A and requests with the /app2 path to Service B.
Backend Service Integration: An Ingress resource connects to backend services to forward traffic. You can specify different backend services for each route.
TLS Encryption: Ingress resources support HTTPS traffic and can provide SSL/TLS encryption, enabling secure communication.
Ingress Controller: This is the controller that manages Ingress resources and performs the actual traffic routing. The Ingress Controller must be deployed in the cluster; you can use controllers such as the Nginx Ingress Controller, Traefik, or HAProxy.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
spec:
rules:
- host: app1.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app1-service
port:
number: 80
- host: app2.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app2-service
port:
number: 80
Example of Applying a TLS Certificate to an Ingress
The certificate file must be stored as a secret.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-example-ingress
spec:
tls:
- hosts:
- https-example.foo.com
secretName: testsecret-tls
rules:
- host: https-example.foo.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service1
port:
number: 80
Ingress Annotation
This is how you can configure detailed settings for the Ingress Controller.
nginx.ingress.kubernetes.io/proxy-body-size: 50m
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$1
nginx.ingress.kubernetes.io/ssl-redirect: "true"Storage
In Kubernetes, a Volume is an abstract concept that provides disk space for sharing data within and between containers, or for storing data.
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mycontainer
image: nginx
volumeMounts: # Volume Mounts 정의
- name: myvolume # 사용할 볼륨의 이름
mountPath: /data # 볼륨을 마운트할 경로
volumes: # Volumes 정의
- name: myvolume # 볼륨의 이름
emptyDir: {} # 빈 디렉터리를 사용한 예시
Types of Storage
emptyDir
hostPath
nfs
rbd
ConfigMap
secret
PVC
etc.
Ephemeral Storage
Stored in the container's internal filesystem
An EmptyDir volume that can be shared by multiple containers within a Pod
Deleted when the Pod terminates

Persistent Storage
A volume type managed separately, independent of the Pod’s lifecycle
Can be read from and written to by multiple Pods
Can be reused by the next Pod even after the previous Pod terminates

Persistent Volume (PV)
A Persistent Volume (PV) is an abstract concept in Kubernetes for storing persistent data. A PV represents storage within the cluster; it can be dynamically allocated when a Pod requests it, or a predefined PV can be used.

apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs-storage
nfs:
server: <NFS_Server_IP>
path: /path/to/nfs/share
Persistent Volume Claim (PVC)
In Kubernetes, a Persistent Volume Claim (PVC) defines how an application or user requests and uses a Persistent Volume (PV) within the cluster. A PVC provides abstraction for storage requests, and cluster administrators can use PVCs to provide users with appropriate storage.

Storage Class: A PVC can specify the requested storage class. A Storage Class defines the policies and provisioning parameters that cluster administrators use to manage provisioned PVs.
Capacity: A PVC can specify the capacity of the requested storage. This represents the amount of storage available to the PVC.
Access Mode: A PVC can specify the access mode for the requested storage. This determines access permissions for that storage. Generally, there are three modes: ReadWriteOnce (RWO), ReadOnlyMany (ROX), and ReadWriteMany (RWX).
Volume Property Configuration: A PVC can configure the properties of the requested storage. These may vary depending on the storage class settings and can include, for example, the volume’s replication policy or storage type.
Request Status and Verification: A PVC tracks the request status for a storage class and verifies which PVs are available for that class. This allows the PVC to determine the provisioning and allocation status of the requested storage.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc
spec:
accessModes:
- ReadWriteMany
volumeName: example-pv # Specify the name of the PV here
resources:
requests:
storage: 5Gi
Storage Class
In Kubernetes, a StorageClass is a resource that dynamically provisions Persistent Volumes (PVs) for PVCs and defines provisioning parameters and policies for the storage class.

Provisioning: A StorageClass is used to dynamically provision PVs when a user creates a PVC. This allows users to define their storage requirements, and the storage is automatically provisioned when the PVC is created.
Provisioning Parameters: A StorageClass can define parameters for the PVs to be provisioned. For example, it can specify the storage type, storage capacity, replication policy, and more.
Volume Attribute Configuration: A StorageClass configures the attributes of the provisioned PV. These attributes are determined based on the specifications provided by the user when requesting a PVC.
Reuse Policy: A StorageClass defines a policy that determines how PVs are handled when they are reused. This is used to decide whether to delete a PV when it is no longer in use or to recycle it.
RBAC
Basic Concepts
ServiceAccount
Role
RoleBinding
ClusterRole
ClusterRoleBinding
serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
kubernetes.io/enforce-mountable-secrets: "true"
name: my-serviceaccount
namespace: my-namespace
Pod
Specify `spec.serviceAccountName` -> `/var/run/secrets/kubernetes.io/serviceaccount`
role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
# You can specify more than one "subject"
- kind: User
name: jane # "name" is case sensitive
apiGroup: rbac.authorization.k8s.io
roleRef:
# "roleRef" specifies the binding to a Role / ClusterRole
kind: Role #this must be Role or ClusterRole
name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
apiGroup: rbac.authorization.k8s.io
Grant permissions to the user
Generate PEM
openssl genrsa -out myuser.key 2048
Generate CSR
CN is the user's name
O is the group to which this user will belong
openssl req -new -key myuser.key -out myuser.csr -subj "/CN=myuser"Encode the CSR in Base64
cat myuser.csr | base64 | tr -d "\n"
Create csr.yaml
The `usages` field must be set to ‘client auth’
`expirationSeconds` can be set to a longer value ``` apiVersion: certificates.k8s.io/v1 kind: CertificateSigningRequest metadata: name: myuser spec: request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1ZqQ0NBVDRDQVFBd0VURVBNQTBHQTFVRUF3d0dZVzVuWld4aE1JSUJJakFOQmdrcWhraUc5dzBCQVFFRgpBQU9DQVE4QU1JSUJDZ0tDQVFFQTByczhJTHRHdTYxakx2dHhWTTJSVlRWMDNHWlJTWWw0dWluVWo4RElaWjBOCnR2MUZtRVFSd3VoaUZsOFEzcWl0Qm0wMUFSMkNJVXBGd2ZzSjZ4MXF3ckJzVkhZbGlBNVhwRVpZM3ExcGswSDQKM3Z3aGJlK1o2MVNrVHF5SVBYUUwrTWM5T1Nsbm0xb0R2N0NtSkZNMUlMRVI3QTVGZnZKOEdFRjJ6dHBoaUlFMwpub1dtdHNZb3JuT2wzc2lHQ2ZGZzR4Zmd4eW8ybmlneFNVekl1bXNnVm9PM2ttT0x1RVF6cXpkakJ3TFJXbWlECklmMXBMWnoyalVnald4UkhCM1gyWnVVV1d1T09PZnpXM01LaE8ybHEvZi9DdS8wYk83c0x0MCt3U2ZMSU91TFcKcW90blZtRmxMMytqTy82WDNDKzBERHk5aUtwbXJjVDBnWGZLemE1dHJRSURBUUFCb0FBd0RRWUpLb1pJaHZjTgpBUUVMQlFBRGdnRUJBR05WdmVIOGR4ZzNvK21VeVRkbmFjVmQ1N24zSkExdnZEU1JWREkyQTZ1eXN3ZFp1L1BVCkkwZXpZWFV0RVNnSk1IRmQycVVNMjNuNVJsSXJ3R0xuUXFISUh5VStWWHhsdnZsRnpNOVpEWllSTmU3QlJvYXgKQVlEdUI5STZXT3FYbkFvczFqRmxNUG5NbFpqdU5kSGxpT1BjTU1oNndLaTZzZFhpVStHYTJ2RUVLY01jSVUyRgpvU2djUWdMYTk0aEpacGk3ZnNMdm1OQUxoT045UHdNMGM1dVJVejV4T0dGMUtCbWRSeEgvbUNOS2JKYjFRQm1HCkkwYitEUEdaTktXTU0xMzhIQXdoV0tkNjVoVHdYOWl4V3ZHMkh4TG1WQzg0L1BHT0tWQW9FNkpsYWFHdTlQVmkKdjlOSjVaZlZrcXdCd0hKbzZXdk9xVlA3SVFjZmg3d0drWm89Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo= signerName: kubernetes.io/kube-apiserver-client expirationSeconds: 86400 # one day usages:
client auth ```
kubectl apply -f csr.yaml
kubectl get csr
kubectl certificate approve myuser
kubectl get csr/myuser -o yaml
kubectl get csr myuser -o jsonpath='{.status.certificate}'| base64 -d > myuser.crt
Add to kubeconfig
kubectl config set-credentials myuser --client-key=myuser.key --client-certificate=myuser.crt --embed-certs=true
Kubernetes Knowledge Every Developer Should Know
Readiness Probe
This checks whether a container is ready for use and is particularly useful for preventing user requests from reaching an app that takes a long time to start before it is fully ready.

Type:
HTTP: Checks whether the container responds to HTTP requests on a specific endpoint. Success or failure is determined based on the response code.
TCP: Checks whether the container accepts TCP socket connections on a specific port.
Command: Executes a custom command inside the container to determine success or failure.

workload.yaml
spec:
containers:
- name: mycontainer
image: nginx
ports:
- containerPort: 80
readinessProbe: # 레디니스 프로브 정의
httpGet:
path: / # 체크할 경로
port: 80 # 포트
initialDelaySeconds: 5 # 시작 후 최초 체크 딜레이 (초)
periodSeconds: 10 # 주기적으로 체크할 간격 (초)
timeoutSeconds: 5 # 타임아웃 (초)
successThreshold: 1 # 성공을 인정하는 임계값
failureThreshold: 3 # 실패를 인정하는 임계값
HostPath
In Kubernetes, a HostPath volume is used to mount a file system path on the host machine into a Pod.
Tip:
This is useful when mounting a Trusted CA certificate file from the host OS into a Pod.

SubPath
Pod and Service DNS
All pods and services within the cluster have DNS addresses, and the rules are as shown in the following figure.

Scheduling
nodeName
nodeSelector
nodeAffinity
nodeName
``` apiVersion: v1 kind: Pod metadata: name: nginx spec: containers:
name: nginx image: nginx nodeName: kube-01
#### nodeSelectorapiVersion: v1 kind: Pod metadata: name: nginx labels: env: test spec: containers:
name: nginx image: nginx imagePullPolicy: IfNotPresent nodeSelector: disktype: ssd ```
nodeAffinity
In Kubernetes, NodeAffinity is a feature used to ensure that a Pod is scheduled on a specific node. NodeAffinity is used to define conditions that affect Pod scheduling. The key concepts are as follows:
requiredDuringSchedulingIgnoredDuringExecution: This indicates that the Pod must be scheduled on a specific node. If no node meets this condition, the Pod will not be scheduled. However, Pods already scheduled on that node are not affected even if this condition changes.
preferredDuringSchedulingIgnoredDuringExecution: This indicates that a Pod is preferred to be scheduled on a specific node, but it is not mandatory. If no nodes meet this condition, the Pod may be scheduled on other nodes.
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- antarctica-east1
- antarctica-west1
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: another-node-label-key
operator: In
values:
- another-node-label-value
containers:
- name: with-node-affinity
image: registry.k8s.io/pause:2.0
QOS
request
limit
---
apiVersion: v1
kind: Pod
metadata:
name: frontend
spec:
containers:
- name: app
image: images.my-company.example/app:v4
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"

Debugging in a K8S Environment
kubectl get pods - Check pod status
kubectl get events
kubectl describe
kubectl get -o yaml
kubectl logs
kubectl logs –previous
kubectl exec
kubectl debug
curl/telnet/wget