클러스터는 물리적인 노드들의 집합이다. 하나의 클러스터는 하나 이상의 노드로 구성된다.
보통 master node와 worker node로 구성된다.
master node는 API 를 받아 처리하는 kubernetes api, 파드를 노드에 할당하는 scheduler, 상태를 저장하는 etcd 로 구성된다.
worker node는 실제로 작업을 실행하는 노드로, kubelet 데몬을 통해 작업 요청을 받아 수행한다.
네임스페이스는 동일한 물리 클러스터를 기반으로 하는 가상적인 노드 집합이다. 하나의 클러스터에서 여러 네임스페이스가 존재할 수 있다.
네임스페이스를 기반으로 프로젝트 환경 또는 사용자를 구분하여 전혀 다른 환경으로 관리할 수 있다.
일반적으로 소규모 프로젝트에서는 고려 대상이 아니지만, 대규모 프로젝트에서는 편리하게 쓸 수 있다.
파드(Pod) 는 쿠버네티스에서 생성하고 관리할 수 있는 배포 가능한 가장 작은 컴퓨팅 단위이다.
파드 내에는 하나 이상의 컨테이너가 배포된다. 서로 밀접한 연관관계를 가진 컨테이너를 하나의 파드에 넣음으로써 작업을 논리적으로 강하게 결합할 수 있다.
같은 파드는 여러 노드에 배치될 수 있고, 한 노드에 여러개 배치될 수도 있다. 그러나 같은 파드 내에 있는 컨테이너는 모두 같은 노드에 있어야 한다. 즉 한 파드가 여러 노드에 걸쳐서 (span) 배포될 수는 없다.
파드는 다음과 같은 라이프사이클에 따라 움직인다. 시스템 실패로 인하여 'failed'상태로 빠질 경우 재생성이 필요하다.
워크로드는 쿠버네티스에서 구동되는 애플리케이션으로, 1개 혹은 다수 개의 Pod로 이루어져 있다. 그러나 각 Pod는 실패할 경우 직접 노드의 상태와 관계없이 수동으로 삭제/재생성을 해 주어야 한다.
따라서 각 Pod 를 직접 관리할 필요가 없이 더 쉽게 작업을 관리할 수 있도록 workload가 만들어졌다.
어느 정도 규모가 되는 시스템의 애플리케이션은 같은 파드를 여러 개 실행하여 가용성을 확보하여야 한다. 레플리카세트는 똑같은 정의를 갖는 파드를 여러 개 생성하고 관리하기 위한 리소스이다.
레플리카 세트로 배포하면 같은 기능을 하는 파드 여러개가 무작위 접미사를 달고 동시에 생성된다.
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는 일반적으로 다음과 같은 케이스에 사용된다.
일반적인 레플리카셋 여러개로 구성된 디플로이먼트는 주로 stateless 애플리케이션(웹 애플리케이션, 클라우드 네이티브 앱 등)을 배포할 때 사용된다.
그러나 Stateful한 애플리케이션의 배포가 필요할 경우 디플로이먼트 내에 stateful set을 구성할 수 있다.
스테이트풀셋은 다음 중 하나 또는 이상이 필요한 애플리케이션에 유용하다.
예를 들어 Relational DB, NoSQL DB, Redis cache 저장소 등 트랜잭션/상태 저장이 필요한 애플리케이션들이 이에 해당된다.
아래는 stateful set의 배포 구성 매니페스트 예시이다.
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx # .spec.template.metadata.labels 와 일치해야 한다
serviceName: "nginx"
replicas: 3 # 기본값은 1
minReadySeconds: 10 # 기본값은 0
template:
metadata:
labels:
app: nginx # .spec.selector.matchLabels 와 일치해야 한다
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: k8s.gcr.io/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "my-storage-class"
resources:
requests:
storage: 1Gi
데몬셋은 모든 노드 혹은 일부 노드에서 항상 실행되어야 하는 작업을 관리하는 데 사용되는 워크로드이다.
디플로이먼트와도 유사하나, 차이점은 다음과 같다.
데몬셋의 일부 대표적인 용도는 다음과 같다.
아래는 데몬셋 배포 매니페스트 예시이다.
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd-elasticsearch
namespace: kube-system
labels:
k8s-app: fluentd-logging
spec:
selector:
matchLabels:
name: fluentd-elasticsearch
template:
metadata:
labels:
name: fluentd-elasticsearch
spec:
tolerations:
# this toleration is to have the daemonset runnable on master nodes
# remove it if your masters can't run pods
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
containers:
- name: fluentd-elasticsearch
image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
서비스는 파드 집합에서 실행중인 애플리케이션을 네트워크 서비스로 노출하는 추상화된 방법이다.
서비스는 유동적으로 변경되는 파드 집합에 대한 게이트웨이 역할을 하며, 변경되는 파드의 IP정보를 알 필요 없이 단일 DNS 명을 부여하여 로드밸런싱을 수행한다.
서비스는 파드의 논리적 집합에 해당하며, 서비스에 지정된 Selector에 의해 파드를 노드에 배치한다.
또한, 파드를 외부 네트워크와 연결해주고 여러 개의 파드를 바라보는 내부 로드밸런서를 생성할 때도 사용한다. 내부 DNS에 서비스 이름을 도메인으로 등록하기 때문에 서비스 디스커버리 역할도 수행한다.
쿠버네티스에서 지원하는 서비스는 3가지 종류가 있다.
1. ClusterIP (default) - 파드들이 클러스터 내부의 다른 구성요소와 통신할 수 있도록 해 주는 서비스 형태이다. 클러스터 외부에선 접근할 수 없다.
2. NodePort - 외부에서 노드 IP의 특정 포트로 들어오는 요청을 감지하여 해당 포트와 연결된 파드로 전송해주는 형태의 서비스다.
3. LoadBalancer - 별도의 외부 로드 밸런서를 제공하는 클라우드(AWS, Azure, GCP 등) 환경을 고려하여, 해당 로드 밸런서를 클러스터의 서비스로 프로비저닝할 수 있는 서비스 형태다. 온프레미스 혹은 로드밸런서가 지원되지 않는 클라우드일 경우, 별도의 LB를 설치해 연결하지 않으면 NodePort와 똑같이 동작한다.
4. ExternalName - 서비스에 selector 대신 DNS name을 직접 명시하고자 할 때 사용하는 형태의 서비스다.
서비스는 다음과 같이 선언 가능하다. 이 예시는 clusterIP 타입의 서비스이다. (기본값)
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376