
k8s는 기본적으로 위와 같은 클러스터 형태로 구성된다. k8s 클러스터를 전반적으로 매니징하는 역할을 하는 Master node와 실질적인 자원 제공을 하는 Node로 구성되어 있다.
이렇게 k8s는 클러스터 형태로 구성되어 있고, 이를 '쿠버네티스 클러스터'라고 부르기도 한다.

하나의 k8s 클러스터는 N개의 Namespace로 구성될 수 있다.
하나의 Namespace는 클러스터 내에서 독립적으로 구성된 환경을 의미한다. 즉, 같은 Namespace에 존재하는 자원들은 서로 통신 및 접근할 수 있지만, 서로 다른 Namespace에 있는 자원들은 서로 통신 및 접근할 수 없다.
k8s의 최소 배포 단위에 해당하는 Pod는 정확히 동일하다고 볼 순 없지만 실질적인 물리 서버 역할을 한다.
하나의 애플리케이션이 돌게 되는 컴포넌트이다. Docker 컨테이너라고 볼 수 있다.
Pod는 다운되게 되면, Pod내에서 들고 있던 데이터들은 모두 날아가게 된다. Pod가 다운되도 날라가면 안되는 데이터가 있다면, Volume을 마운팅해서 보존할 수 있다.
k8s에는 위에서 언급한 것 외에도 아래와 같이 다양한 컴포넌트들이 있다.
일단 언급만하고 넘어가도록 하겠다.
k8s에서 가장 기본적이면서 중요한 컴포넌트 중에 하나인 Pod에 대해서 먼저 알아보자.

하나의 Pod에서는 여러 애플리케이션을 구동할 수 있고, 각가의 애플리케이션은 Container로 구동되게 된다.
이 때, 각 컨테이너에는 포트를 지정할수 있고, 컨테이너끼리는 localhost로 서로에게 접근할 수 있다.
또, Pod는 생성될 때마다 동적으로 IP가 할당되게 되는데, 이 IP는 외부에서 접근 가능한 IP는 아니고, 클러스터 안에서 Pod에 접근하고자할 때 사용될 수 있는 IP이다.
Pod를 생성할 때는 아래와 같은 형태로 yml파일을 작성해서 생성하게 된다.
apiVersion: v1
kind: Pod
metadata:
name: pod-1
labels:
type: web
env: dev
spec:
containers:
- name: container-1
image: kai1114/hello
ports:
- containerPort: 8000
Pod를 생성하면, 생성된 Pod는 특정 Node에 소속되게 되는데,yml 에 nodeSelector를 작성해서 직접 Node를 선택할 수도 있고, 스케줄러가 판단한 후, 여유 자원(특히, CPU, RAM)이 있는 Node에 생성된 Pod를 할당할 수도 있다.
라벨은 말 그래도 '라벨'의 역할을 한다.
하나의 라벨은 Key:Value로 구성된다.
클러스터 내에 존재하는 다양한 컴포넌트들을 분류 및 구분하기 위해서 사용하고, Pod, Container등등 모든 컴포넌트들에 Label을 부여할 수 있다.
아래와 같은 식으로 컴포넌트의 종류, 목적, 환경 등을 명시한다.
type:application-servertype:dbenv:devenv:prod동일한 이름을 갖고 있는 Label을 묶어서 하나의 Service로 만들 수 있고, 이를 통해서 다양한 기능들을 수행할 수 있으므로, Label은 적절히 잘 지어주는 게 좋다.
Service를 생성할 때, 특정 Label을 지정해서 생성하고 싶다면, selector에 해당 Label을 작성해주면 된다.
apiVersion: v1
kind: Service
metadata:
name: service-1
spec:
selector:
type: db
ports:
- port: 8080
Pod는 장애로 인해서 죽거나 삭제될 수도 있고, 새롭게 뜰 때마다 클러스터에서 접근할 수 있는 IP가 동적으로 할당된다는 특징을 갖고 있다.
반면에 Service는 사용자가 직접 삭제 또는 수정을 하지 않는 이상 삭제되거나 IP가 동적으로 재할당되는 경우가 없다.
그래서 어떠한 목적 또는 관심사를 기준으로 N개의 Pod를 Service로 구성하고 Pod에 접근하고 싶을 때는 Service를 통해서 접근할 수 있다.
이러한 이유로 Service를 사용한다.
Service에는 다양한 종류가 있는데, 하나씩 알아보도록 한다.

ClusterIp 방식은 클러스터에서 접근 가능한 고정적인 IP를 Service에 부여해서, 접근할 수 있게 하고, 들어오는 트래픽은 Service에 연결된 Pod에 분산해준다.
apiVersion: v1
kind: Service
metadata:
name: cluster-ip-service-1
spec:
selector:
app: pod-1
ports:
- port: 9000
targetPort: 8000
type: ClusterIP
ClusterIp 서비스는 위와 같이 yml을 작성하여 만들 수 있다.

NodePort는 ClusterIp의 모든 기능을 갖고 있으며, Node를 활용할 수 있도록 확장된 기능이다.
NodePort 방식으로 Service를 만들면, 특정 Node의 IP와 포트로 접근했을 때, 트래픽을 Service로 전달하고, 해당 트래픽은 Service에 물려있는 Pod들에 분산되어 전달되게 된다.
다만, externalTrafficPolicy: local로 옵션을 줄 경우, 특정 Node로 들어온 트래픽은 Service를 거쳐서 해당 Node에 물려 있는 Pod에 전달되게 된다.
NodePort는 ClusterIp를 확장하여, 외부에서 접근 가능한 Node의 IP를 사용하여, 외부에서 애플리케이션에 접근할 수 있도록 했다고 볼 수 있겠다.
apiVersion: v1
kind: Service
metadata:
name: node-port-service-1
spec:
selector:
app: pod-2
ports:
- port: 9001
targetPort: 8000
nodePort: 30000
type: NodePort
externalTrafficPolicy: Local # Node에 존재하는 Pod로 트래픽 전달
NodePort 서비스는 위와 같이 yml을 작성하여 만들 수 있다.

Load balancer (이하, LB)는 NodePort의 동작 방식에서 LB 추가된 것이다.
외부에서 접근 가능한 LB 컴포넌트가 존재하게 되고, Public IP를 할당하는 플러그인 통해서 LB에 IP를 할당하면 외부에서 LB에 접근할 수 있게 된다.
LB는 다양한 정책을 통해서 트래픽을 분산할 수 있게 된다.
apiVersion: v1
kind: Service
metadata:
name: load-balancer-service-1
spec:
selector:
app: pod-3
ports:
- port: 9000
targetPort: 8000
type: LoadBalancer
LB 서비스는 위와 같이 yml을 작성하여 만들 수 있다.