Pod : 쿠버네티스의 가장 작은 배포 단위
쿠버네티스는 컨테이너를 직접 관리하지 않고 pod이라는 걸로 감싸서 관리한다.
Pod이 쿠버네티스에서 가장 작은 배포 단위이고, 컨테이너를 배포하는 것이 아니라 'Pod를 배포한다'고 한다.
Pod의 특징
- 전체 클러스터에서 고유한 IP를 부여받는다.
여러 개의 컨테이너가 하나의 Pod에 속할 수 있다.
- 첫번째의 경우 Container와 log를 수집하는 컨테이너, 이렇게 2개가 떠있을 수 있고, 호스트에 있는 폴더를 공유할 수 있다.
- 두번째의 경우 캐시를 같이 띄워서 포트를 공유할 수 있다.
ReplicaSet
- 여러 개의 Pod을 관리
- 새로운 Pod는 template을 참고하여 생성
- 신규 Pod를 생성하거나 기존 Pod를 제거하여 원하는 수의 Replicas를 유지
Deployment
- 배포 버전을 관리
- ReplicaSet을 무중단 배포하기 위해서 사용할 수 있다.
- ReplicaSet을 둘러쌈
쿠버네티스는 다양한 방식을 제공한다.
- Demonset : 모든 노드에 꼭 하나씩만 떠 있기를 원하는 Pod을 만들고 싶을 때 사용
- 로그를 수집하거나 모니터링을 하는 것에 적합
- StatefulSet
- 순서대로 Pod을 실행하고 싶거나 같은 볼륨을 계속 재활용하고 싶을 때
- Job
- 한번 실행하고 죽는 종류의 Pod을 만들 수 있다.
쿠버네티스 네트워크
쿠버네티스는 네트워크도 별도의 오브젝트로 관리한다.
Cluster IP
서비스 중에서도 ClusterIP 라는 것은 Pod들(여기서는 3개)를 로드밸런서 하는 별도의 서비스이다.
ClusterIP로 요청을 보내면 자동으로 저 3개 Pod 중에 하나로 요청이 가게 되는 것이다.
이렇게 하는 이유는 Deployment나 ReplicaSet을 보면 Pod이 업데이트 될 때, 그 IP를 유지한 상태로 업데이트 되는 것이 아니라 그냥 Pod이 죽고 새로운 Pod이 뜨는 개념이기 때문에 IP가 언제든지 사라졌다가 바뀌거나 하는 것이 자연스럽다.
그래서 요청을 보낼 때, Pod으로 바로 보내는 것이 아니라 Service라는 것을 먼저 만들고 Service의 IP는 고정이니까 거기에 요청을 보내면 뒤에 Pod은 늘던 줄던 Ip가 바뀌든 상관없이 정상적으로 원하는 Pod에 요청을 보낼 수 있기 때문에 ClusterIP 서비스를 붙이게 된다.
내부적으로는 이렇게 통신을 하게 된다.
만약 웹 서버에서 Redis로 통신을 하고 싶다면 내부 DNS에서 Redis라는 도메인이 생긴다.
그러면 Redis로 요청을 보내면 ClusterIP로 요청을 보내고, 그 요청이 다시 안쪽에 있는 Pod으로 요청이 가게 된다.
웹에서 mysql로 요청을 보내면 1차적으로 ClusterIP로 요청이 간 다음에 그 요청이 다시 mysql의 pod으로 요청이 간다.
그런데 ClusterIP는 내부에서만 통신할 수 있다. (외부 브라우저로는 접근할 수 없다.)
그래서 외부에서 접근하기 위해서 NodePort라는 개념이 생긴다.
Node에 Port가 생기고, 거기로 접속을 하면 그 요청이 다시 ClusterIP로 가고 그 요청이 다시 또 Pod로 가는 그런 구조로 되어 있다.
모든 노드에 동일한 포트로 되어있다.
웹브라우저에서 요청 → NodePort → ClusterIP → 내부에 있는 Pod들
만약에 Node가 2개가 있고, NodePort를 생성하게 되면 1번 Node에도 생기고 2번 Node에도 생기게 된다. 그래서 1번 Node로 요청을 보내도 원했던 ClusterIP로 요청이 가고, 2번 Node에도 요청을 보내도 원했던 ClusterIP로 요청이 가게 된다.
예를 들어 Node가 10개면 10개 중에 아무데나 보내도 내부에 있는 네트워크를 잘 찾아가는 그런 기능을 가지고 있다.
문제는 만약 내가 1번 노드를 도메인으로 연결을 해놓았는데 그런데 갑자기 1번 노드가 죽을 수가 있다. (서버 자체가 사라질 수가 있다. )
그럼 2번 노드로 붙어야 되는데 설정을 1번 노드로 해놓았기 때문에 순간적으로 접속이 안되게 된다.
그래서 이것을 방지하기 위해서 앞에 로드 밸런서를 별도로 둔다.
[흐름]
사용자는 LoadBalancer로 요청을 보내고, 그 요청이 다시 NodePort로 가고, NodePort가 다시 ClusterIP로 가고, ClusterIP가 다시 Pod로 가는 구조로 되어 있다.
Ingress
위의 그림처럼 전부 다 NodePort를 만들거나 전부 다 LoadBalancer를 만들면 자원이 낭비된다.
Ingress 하나를 만들고, Ingress 내부에서 Service를 분기할 수 있다.
이전에 설명한 네트워크는 IP Port로만 접속을 하는 것이라면 Ingress는 도메인 이름, 그리고 도메인 뒤에 붙는 path에 따라서 내부에 있는 ClusterIP 연결을 할 수 있다.
예를 들어서, example.com, kluster.com/blog, kluster.com/news 이런 3개의 요청이 들어왔을 때 이 세개를 전부 다 NodePort를 만들거나 전부 다 LoadBalancer를 만들면 그 자원이 낭비가 된다.
그 대신에 Ingress 하나만 만들고 그 Ingress가 내부적으로 서비스를 분기할 수 있다.
Ingress는 뭔가 새로 만든다기보다는 기존에 있었던 Nginx, HAProxy, ALB 이런 것들을 재활용해서 쿠버네티스에 맞게 포장을 해서 사용을 한다.
일반적으로 Pod만 띄우는 경우는 잘 없다. Deployment를 생성을 하고, Deployment가 ReplicaSet을 자동으로 생성하고, ReplicaSet이 자동으로 Pod를 생성하는 이런 구조를 갖는다.
그리고 이것을 외부로 노출시키기 위해서 Service(ClusterIP)를 하나 붙인다.
그리고 서비스를 붙인 다음에 Ingress를 붙인다.
Ingress를 붙이면 NodePort랑 LoadBalancer가 자동으로 따라온다.
그래서 저걸 붙인 다음에 실제 클라이언트는 이제 저 도메인으로 접속을 하게 되면은 저 LoadBalancer를 거쳐서 NodePort를 거쳐서 ClusterIP를 거쳐서 Pod로 연결되는 것이 일반적인 방법이다.
그 외 기본 오브젝트
Volume - Storage(EBS, NFS, …)
Namespace - 논리적인 리소스 구분
- 내부적으로 리소스를 네임스페이스로 구분할 수 있다.
ConfigMap / Secret - 설정
ServiceAccount - 권한 계정
Role / ClusterRole - 권한 설정 (get, list, watch, create …)
API 호출
그럼 쿠버네티스는 실제로 어떻게 API를 호출할까?
Pod이라는 오브젝트를 띄우고 싶다, 생성하고 싶다면 yaml로 사용해서 생성한다.
apiVersion: v1
kind: Pod
metadata:
name: example
spec:
containers:
- name: busybox
image: busybox:1.25
명세서 작성을 하면 컨테이너가 동작을 하게 된다.
명세서를 API Server가 보고 etcd에 저장을 하고, 각 Controller들이 동작하게 된다.
API 호출한다 == 원하는 상태(desired state)를 다양한 오브젝트(object)로 정의(spec)하고 API 서버에 yaml형식으로 전달하는 것
'클라우드 네이티브 > Kubernetes' 카테고리의 다른 글
Worker Node를 내려야 할 필요가 있을 경우 안전한 이동 (0) | 2024.05.20 |
---|---|
쿠버네티스 등장 배경과 용어 (4) | 2024.03.08 |
[DevOps] 쿠버네티스에 스프링 프로젝트 배포하기(macOS m1) (1) | 2023.12.07 |
[DevOps] ArgoCD와 사용 이유 (0) | 2023.12.07 |
도커, 도커 엔진, 컨테이너, 가상 서버, 도커 데몬 (0) | 2023.03.27 |