I found it overwhelming when start working with K8s. Event
when I have used Docker for years. K8s has bunch of object types
and many many configuration to know and remember but you just
can’t learn them by heart. Therefore I decided to organize
my understanding of K8s into something, anything. Only
by trying to visualize it, my brain can start linking all
the documents I have read so far into a bigger picture.
And here’s the result.
---
config:
class:
hideEmptyMembersBox: true
layout: elk
---
classDiagram
direction LR
class Cluster {
}
class ControlPlane {
}
class ControlPlaneNode {
}
Node <|-- ControlPlaneNode
class WorkerNode {
}
Node <|-- WorkerNode
class APIServer {
}
class Scheduler {
}
class ControllerManager {
}
class KeyValueStore {
}
class NodeComponent {
}
class ContainerRuntime {
}
class Kubelet {
}
class KubeProxy {
}
class AddOn {
}
class Logging {
}
class Monitoring {
}
class NodeAgent {
}
class Namespace {
}
class Pod {
template
}
class Container {
name: str
image: str
port: number
}
class Label {
key
value?
}
class ReplicaSet {
replicas: number
template: pod
}
class Deployment {
replicas: number
template: pod
}
class Port {
port: number
targetPort: number
protocol: str = TCP
}
class AutoScaler {
}
class RollingUpdate {
}
class DaemonSet {
}
class Service {
name: str
selector: Label[]
ports: Port[]
type: ServiceType = ClusterIP
}
class ServiceType {
}
class ClusterIP {
}
class NodePort {
}
class LoadBalancer {
}
class ExternalIP {
}
class ExternalName {
}
class Object {
}
class Node {
}
<<interface>> NodeComponent
<<interface>> ServiceType
<<interface>> Object
note for ContainerRuntime "eg: Dockerengine, containerd"
note for KeyValueStore "etcd, can run on node or external etcd cluster"
note for Service "ports referred to as service endpoints"
note for ClusterIP "A Service receives a Virtual IP address<br/> accessible only from within the cluster."
note for NodePort "A Service includes a ClusterIP and a high-port, <br/> dynamically picked from the default range 30000-32767,<br/> is mapped to the respective Service, from all the worker nodes."
note for LoadBalancer "NodePort and ClusterIP are automatically created,<br/> and the external load balancer will route to them<br>The Service is exposed at a static port on each worker node.<br>The Service is exposed externally using the underlying cloud<br>provider's load balancer feature."
note for ExternalIP "A Service can be mapped to an external IP address not managed by K8s"
note for ExternalName "When accessed within the cluster, <br>it returns a CNAME record of <br>an externally configured Service."
AddOn <|-- Logging
AddOn <|-- Monitoring
Service "1" --> "1" ServiceType : is
ServiceType <|-- ClusterIP
ServiceType <|-- NodePort
ServiceType <|-- LoadBalancer
ServiceType <|-- ExternalIP
ServiceType <|-- ExternalName
Cluster "1" --> "1..*" ControlPlane : has
Cluster "1" --> "1..*" Node : has
Cluster "1" --> "1..*" Namespace : patitions
Namespace "1" --> "0..*" Object : contains
Object <|-- Node
Object <|-- Pod
Object <|-- ReplicaSet
Object <|-- DaemonSet
Object <|-- Deployment
Object <|-- Service
ControlPlaneNode "1" --> "*" NodeComponent: runs
NodeComponent <|-- APIServer
NodeComponent <|-- Scheduler
NodeComponent <|-- ControllerManager
NodeComponent <|-- KeyValueStore
NodeComponent <|-- ContainerRuntime
NodeComponent <|-- AddOn
ControlPlaneNode --> "0..*" NodeAgent: runs
NodeAgent <|-- Kubelet
NodeAgent <|-- KubeProxy
WorkerNode --> "0..*" NodeAgent: runs
WorkerNode --> "0..1" NodeComponent: runs
Pod "1" --> "1..*" Container : has
ContainerRuntime "1" --> "0..*" Container : handles_and_runs
Kubelet "1" --> "0..*" Pod : monitors
Pod "1" --> "0..*" Label : has
ReplicaSet "0..1" --> "1..*" Pod : controls
ReplicaSet "0..1" --> "0..1" AutoScaler : has
AutoScaler "0..1" --> "1..*" Pod : scales
Deployment "0..1" --> "1" ReplicaSet : manages
Deployment "1" --> "1..*" RollingUpdate : rollouts
Deployment "1" --> "0..*" RollingUpdate : rollbacks
DaemonSet "0..1" --> "0..*" NodeAgent : manages
Service "0..1" --> "1" Pod : exposes
Service "0..1" --> "1" ReplicaSet : exposes
Service "0..1" --> "1" Deployment : exposes
class Cluster:::Pine
class Cluster:::Aqua
class Namespace:::Rose
class Pod:::Rose
class Container:::Rose
class ReplicaSet:::Rose
class Deployment:::Rose
class Port:::Rose
class Service:::Rose
classDef Rose :, stroke-width:1px, stroke-dasharray:none, stroke:#FF5978, fill:#FFDFE5, color:#8E2236
classDef Pine :, stroke-width:1px, stroke-dasharray:none, stroke:#254336, fill:#27654A, color:#FFFFFF
classDef Aqua :,stroke-width:1px, stroke-dasharray:none, stroke:#46EDC8, fill:#DEFFF8, color:#378E7A
First, we start looking at the green box named Cluster. It contains every
other objects in K8s. It can be bare metal servers or some cloud VMs.
Some classes are highlighted as red. Those are objects/components that I
believe are very important to know well when working with K8s. As developer, we
create, update and delete them frequently. Those are Namespace, Service,
Deployment, ReplicaSet, Pod, Container. Knowing each one of them and
their differences can help avoiding mistakes.
Other objects are good to know but as a developer, we might not need to work with or configure them regularly.
Diagram source code Link to heading
---
config:
class:
hideEmptyMembersBox: true
layout: elk
---
classDiagram
direction LR
class Cluster {
}
class ControlPlane {
}
class ControlPlaneNode {
}
Node <|-- ControlPlaneNode
class WorkerNode {
}
Node <|-- WorkerNode
class APIServer {
}
class Scheduler {
}
class ControllerManager {
}
class KeyValueStore {
}
class NodeComponent {
}
class ContainerRuntime {
}
class Kubelet {
}
class KubeProxy {
}
class AddOn {
}
class Logging {
}
class Monitoring {
}
class NodeAgent {
}
class Namespace {
}
class Pod {
template
}
class Container {
name: str
image: str
port: number
}
class Label {
key
value?
}
class ReplicaSet {
replicas: number
template: pod
}
class Deployment {
replicas: number
template: pod
}
class Port {
port: number
targetPort: number
protocol: str = TCP
}
class AutoScaler {
}
class RollingUpdate {
}
class DaemonSet {
}
class Service {
name: str
selector: Label[]
ports: Port[]
type: ServiceType = ClusterIP
}
class ServiceType {
}
class ClusterIP {
}
class NodePort {
}
class LoadBalancer {
}
class ExternalIP {
}
class ExternalName {
}
class Object {
}
class Node {
}
<<interface>> NodeComponent
<<interface>> ServiceType
<<interface>> Object
note for ContainerRuntime "eg: Dockerengine, containerd"
note for KeyValueStore "etcd, can run on node or external etcd cluster"
note for Service "ports referred to as service endpoints"
note for ClusterIP "A Service receives a Virtual IP address<br/> accessible only from within the cluster."
note for NodePort "A Service includes a ClusterIP and a high-port, <br/> dynamically picked from the default range 30000-32767,<br/> is mapped to the respective Service, from all the worker nodes."
note for LoadBalancer "NodePort and ClusterIP are automatically created,<br/> and the external load balancer will route to them<br>The Service is exposed at a static port on each worker node.<br>The Service is exposed externally using the underlying cloud<br>provider's load balancer feature."
note for ExternalIP "A Service can be mapped to an external IP address not managed by K8s"
note for ExternalName "When accessed within the cluster, <br>it returns a CNAME record of <br>an externally configured Service."
AddOn <|-- Logging
AddOn <|-- Monitoring
Service "1" --> "1" ServiceType : is
ServiceType <|-- ClusterIP
ServiceType <|-- NodePort
ServiceType <|-- LoadBalancer
ServiceType <|-- ExternalIP
ServiceType <|-- ExternalName
Cluster "1" --> "1..*" ControlPlane : has
Cluster "1" --> "1..*" Node : has
Cluster "1" --> "1..*" Namespace : patitions
Namespace "1" --> "0..*" Object : contains
Object <|-- Node
Object <|-- Pod
Object <|-- ReplicaSet
Object <|-- DaemonSet
Object <|-- Deployment
Object <|-- Service
ControlPlaneNode "1" --> "*" NodeComponent: runs
NodeComponent <|-- APIServer
NodeComponent <|-- Scheduler
NodeComponent <|-- ControllerManager
NodeComponent <|-- KeyValueStore
NodeComponent <|-- ContainerRuntime
NodeComponent <|-- AddOn
ControlPlaneNode --> "0..*" NodeAgent: runs
NodeAgent <|-- Kubelet
NodeAgent <|-- KubeProxy
WorkerNode --> "0..*" NodeAgent: runs
WorkerNode --> "0..1" NodeComponent: runs
Pod "1" --> "1..*" Container : has
ContainerRuntime "1" --> "0..*" Container : handles_and_runs
Kubelet "1" --> "0..*" Pod : monitors
Pod "1" --> "0..*" Label : has
ReplicaSet "0..1" --> "1..*" Pod : controls
ReplicaSet "0..1" --> "0..1" AutoScaler : has
AutoScaler "0..1" --> "1..*" Pod : scales
Deployment "0..1" --> "1" ReplicaSet : manages
Deployment "1" --> "1..*" RollingUpdate : rollouts
Deployment "1" --> "0..*" RollingUpdate : rollbacks
DaemonSet "0..1" --> "0..*" NodeAgent : manages
Service "0..1" --> "1" Pod : exposes
Service "0..1" --> "1" ReplicaSet : exposes
Service "0..1" --> "1" Deployment : exposes
class Cluster:::Pine
class Cluster:::Aqua
class Namespace:::Rose
class Pod:::Rose
class Container:::Rose
class ReplicaSet:::Rose
class Deployment:::Rose
class Port:::Rose
class Service:::Rose
classDef Rose :, stroke-width:1px, stroke-dasharray:none, stroke:#FF5978, fill:#FFDFE5, color:#8E2236
classDef Pine :, stroke-width:1px, stroke-dasharray:none, stroke:#254336, fill:#27654A, color:#FFFFFF
classDef Aqua :,stroke-width:1px, stroke-dasharray:none, stroke:#46EDC8, fill:#DEFFF8, color:#378E7A