Note: I’m based in Korea, so some context here is Korea-specific.
k get pod <podname> -oork describe pod <podname>: Check detailed status infok logs -f <podname> -c <container-name>: Check logsk get pod <podname> --show-lables: Check label info
1. Pod
A group of one or more Containers
The smallest unit of execution
Characteristics
- If composed of multiple Containers, they are always assigned to the same Node
- Each Pod gets a unique Pod IP (one per Pod)
- Containers inside a Pod share the network, so they can be reached via Localhost
- Volumes are shared
States a Pod can have
Pending: The creation command was sent to the Master Node but the Pod hasn’t been created yetContainerCreating: Assigned to a specific Node and currently being created (image download, etc.)Running: Running normallyCompleted: A Pod that runs once and terminates (batch jobs, etc.) after the work is doneError: Something went wrong with the PodCrashLoopBackOff: A state where errors keep happening and Crashes repeat continuously
spec.restartPolicy
Always: Always restart on termination (default)Never: Never restartOnFailure: Restart only on failure (no restart on normal termination)
Health Checks
livenessProbe: Checks whether the Pod is operating normallyreadinessProbe: Checks whether the Pod is ready to accept traffic after creation (visible as the READY 0/1 status)
2. Service
Easy to think of as a Reverse Proxy. Pods are unstable, so a Service stands in front and provides a stable Endpoint
Similar to DNS, you can connect by Service name. If you create a service called myservice, you can connect to it by the name myservice
Service DNS
<ServiceName>.<Namespace>.svc.cluster.local- Example: myservice in the default Namespace ->
myservice.default.svc.cluster.local - svc.cluster.local is the K8S default
How does a Service get a DNS?
- Run
k exec client -- cat /etc/resolv.confto check the Pod’s DNS settings -> you can find the Nameserver IP - Running
k get svc -n kube-systemshows CoreDNS, which has that IP - DNS is available through the CoreDNS service
- Run
Types of Services
ClusterIP: (default) Accessible only from within the K8S cluster.NodePort: Connects a specific port on Localhost to a specific port on the Service (think Docker)- However, NodePort connects a specific port on every Node to the Service
- For example, if there’s a NodePort 32000, then
master:32000,worker01:32000all connect to port 32000
LoadBalancer: Creates a Load Balancer (provided by the Cloud or Software) and distributes traffic to Pods- Convenient since external clients only need to know the LoadBalancer’s IP. (ClusterIP -> stable service Endpoint for Pods, LoadBalancer -> stable service Endpoint for Nodes)
- Accessible externally via External-IP
ExternalName: When you want to use an external service from within the K8S network- e.g., if you set google.com as an ExternalName called google-svc, you can fetch google.com’s data with
curl google-svc
- e.g., if you set google.com as an ExternalName called google-svc, you can fetch google.com’s data with
3. Controller
Compares Current State and Desired State and repeatedly performs tasks to make them match
ReplicaSet- Replicates Pods to maintain a certain count.
- You can declare the number of replicas with something like spec.replicas: 2
- You can select Pods whose labels match via selector.matchLables
Deployment- Uses ReplicaSet to create a certain number of Pods, with deployment features added on top (Deployment -> ReplicaSet -> Pod)
- Supports Rolling Update, with adjustable update ratios
- Set the update strategy with
spec.strategy.type: RollingUpdate spec.strategy.rollingUpdate.maxUnavailable: 25%: (rounded down) Specifies the max % of Pods that can be unavailable during deployment. With 10 Pods at 25%, that’s 2 Podsspec.strategy.rollingUpdate.maxSurge: 25%: (rounded up) Specifies the max % of Pods that can exceed the desired count during deployment. With 10 Pods at 25%, that’s 3 Pods
- Set the update strategy with
- Stores update history and supports Rollback
k rollout undo deployment <deployment-name>
StatefulSet
- Each Pod has a unique identifier
- Each Pod can store unique data in storage (example: Database)
- Pod creation order is guaranteed -> used for order-sensitive applications (first one is Master, the rest are Slaves, etc.)
- Pods are named like
name-<index>(starting from 0) - On deletion, Pods are deleted in reverse order (highest number first)
DaemonSet
- When you want to run the same Pod on every Node -> monitoring, log collection, etc.
4. Job
Job- One-shot programs that run and finish (ML training, batch jobs, etc.)
- You can set a retry policy on failure with something like
spec.backoffLimit: 2. (2 retries)
CronJob
- Provides Crontab-like functionality so you can run Jobs periodically
- Specified like
spec.schedule: "*/1 * * * *"
Namespace
Used to logically partition the cluster
default: The default Namespace
kube-system: Holds the Pods of K8S core components (DNS, networking, etc.)
kube-public: A Namespace that holds resources that can be exposed externally
kube-node-lease: A Namespace used (I think?) for Nodes to signal to the master that they’re alive
ConfigMap, Secret
ConfigMapStores Metadata (configuration values)
Stores values in Key-Value form
Can be declared in YAML like the following
yaml# game-volume.yaml apiVersion: v1 kind: Pod metadata: name: game-volume spec: restartPolicy: OnFailure containers: - name: game-volume image: k8s.gcr.io/busybox command: [ "/bin/sh", "-c", "cat /etc/config/game.properties" ] volumeMounts: - name: game-volume mountPath: /etc/config volumes: - name: game-volume configMap: name: game-config- Other Pods can then use it via Volume mount or environment variables
- Volume:
yaml..... volumeMounts: - name: game-volume mountPath: /etc/config volumes: - name: game-volume configMap: name: game-config- Env:
yaml..... envFrom: - configMapRef: name: monster-configSecrets
- Uses tmpfs (a system that lets you treat memory like a file) for security benefits
- When you look up the value, it comes back as Base64-encoded (not encrypted, just encoded once)
Appendix 1. Running Pods Only on Specific Nodes
Example: How to separate placement between SSD/HDD Nodes
Attach a label to each Node
kubectl label node master disktype=ssdkubectl label node worker disktype=hdd
Then select the label with nodeSelector
apiVersion: v1
kind: Pod
metadata:
name: node-selector
spec:
containers:
- name: nginx
image: nginx
# Select a specific node label
nodeSelector:
disktype: ssd
Comments