아래는 쉽게 시작하는 쿠버네티스 책과 kubernetes ko docs 를 읽고 공부하여 정리한 글입니다.
Docker에게 두들겨 맞고 서버에서 OOM 오류를 계속 만나면서 컨테이너에 대해 조금 이해하게 되었다.
이제 쿠버네티스를 학습할 때가 온 것 같아 기초적인 이론 부분만 학습을 진행하였다..
목차
1. 아키텍쳐
2. 서비스
3. DEPLOYMENT 관리
4. Configmap, Secret
5. 볼륨
1. 아키텍쳐
쿠버네티스는 쿠버네티스 클러스터, 마스터 노드, 워커 노드, 컨테이너 런타임, 영구 스토리지 등으로 이루어져 있으며 각 구성요소의 역할은 아래와 같다.
구성요소의 역할
- 쿠버네티스 클러스터 : k8s의 여러 리소스를 관리하기 위한 집합체로, 마스터 노드와 워커 노드를 이용해 하나의 k8s 클러스터가 만들어진다.
- 마스터 노드 : k8s 클러스터 전체를 관리하는 시스템, control plane이라고도 불린다.
- 워커 노드 : 마스터 노드의 명령을 받아 파드를 생성하고 서비스, computing machine이라고도 불린다.
- 컨테이너 런타임 : 파드를 실행하는 엔진이다. 대표적으로 도커, 컨테이너디, 크라이오 등 이 있음
- 영구 스토리지 : 파드는 기본적으로 휘발성이므로 파드 외부 영구 스토리지에 저장해두는 작업이 필요하다.
k8s 컴포넌트
마스터 노드 속 컴포넌트
- API 서버 : k8s 클러스터의 API를 사용할 수 있게 해주는 프로세스로, 클러스터로 들어온 요청이 유효한지 검증한다.
kubectl create -f deployment.yml 명령어가 들어오면 워커노드로 가기 전에 마스터 노드 속 API server에서 먼저 검증한다. - etcd : k8s 클러스터의 상태를 저장한다. key-value 값으로 저장된다.
API 서버는 파드를 만든다는 사실을 etcd에 알린 후 사용자에게 파드가 생성되었음을 알린다. 하지만 이 때 내부적으로는 아직 파드가 생기지 않았다! - 스케쥴러 : 스케줄링 아님 !! 노드에 파드를 할당하는 역할을 한다. 파드를 위치시킬 적당한 워커 노드를 확인하고(CPU나 메모리 사용량을 참조) API 서버에 이 사실을 알린다. API 서버는 이제 etcd에 해당 정보를 저장한다.
- kubelet : 클러스터의 각 노드에서 실행되는 에이전트로, 파드에서 컨테이너의 생성 및 운영을 담당한다. 드디어! kubelet을 이용해 해당 정보를 이용해 파드를 생성한다. 그리고 또 etcd에 상황을 공유한다.
- controller manager : kube-controller-manager은 다양한 컴포넌트 상태를 지속적으로 모니터링 및 상태 유지하고, cloud-controller-manager은 EKS, AKS 같은 퍼블릭 클라우드에서 제공하는 k8s 연동 서비스를 관리한다.
- 프록시 : 클러스터의 모든 노드에서 실행되는 네트워크 프록시이다. 노드에 대한 네트워크 규칙을 관리하고 내외부 통신을 담당한다.
쿠버네티스 컨트롤러
- 일단 위에서 얘기한 controller manager과 다른 개념이다! 이는 배치 프로세스로, 파드를 관리하는 역할을 한다.
- 데몬셋, 디플로이먼트, 레플리카셋, 스테이트풀셋, 잡, 크론잡, 레플리케이션 컨트롤러 등이 있다.
- 디플로이먼트 - stateless 애플리케이션을 배포할 때 사용하는 가장 기본적인 컨트롤러. 파드를 배포할 때 사용하며 갯수와 전략을 조작할 수 있다.
- 레플리카셋 - 몇 개의 파드를 유지할지 결정하는 컨트롤러
- 잡 - 하나 이상의 파드를 지정하고 지정된 수의 파드가 성공적으로 실행되도록 한다. 만약 한 파드가 재부팅 등으로 비정상적으로 작동하면 다른 노드에서 파드 시작
- 크론잡 - 특정 시간에 잡을 실시한다.
- 데몬셋 - 파드를 생성하고 관리한다. 디플로이먼트와의 차이가 있다면, 데몬셋은 모든/특정 노드에 파드를 배포하고 관리한다. 따라서 노드마다 배치되어야 하는 성능/로그 수집 등에 사용된다.
2. 서비스
Service 자체가 명칭이니 그냥 서비스~ 라고 생각하지 말자!
파드는 k8s 클러스터 안에서 둥둥 떠다닌다. 그러면서 워커 노드가 변경되기도 하고 파드 IP가 변경되기도 한다. 이 때 서비스를 이용해 파드가 클러스터 내의 어디에 있던지 고정된 주소를 이용해 접근할 수 있고 클러스터 외부에서 파드에 접근할 수도 있다.
in 서비스
- Cluster IP - 파드가 아닌 클러스터들은 IP를 할당받는다. 내부에서 파드들을 접근할 때 이 IP를 쓴다.
- 노드포트 - 서비스를 외부로 노출할 때 사용한다. 워커노드 IP:포트 로 외부에서 접근 가능하다.
- 로드밸런서 - 주로 퍼블릭 클라우드에 존재하는 로드밸런서에 연결하고자 할 때 사용한다. 사용자는 로드밸런서의 외부 IP를 통해 접근한다.
같은 노드(워커 노드)에 떠 있는 파드끼리만 통신 가능하다! 즉 같은 노드 안에서는 같은 IP를 사용한다. 노드 속 파드들은 포트번호로 구별한다. 이들은 브릿지를 통해 통신한다.
다른 노드에 떠 있는 파드들끼리는 그 안에 파드들의 IP들끼리 같을 수도 있다(아래에서도 왼쪽과 오른쪽 파드 속 container의 IP가 같다.). 따라서 오버레이 네트워크를 통해 이 문제를 해결한다. 이 오버레이 네트워크를 구성하기 위해 CNI 규약을 따르는 플러그인(주로 플라넬 많이 씀)도 함께 설치해야 한다.
그러면 파드들은 어떻게 서비스에 접근할까?
내부(파드-서비스)
서비스들도 파드처럼 IP를 갖지만, 파드와 서비스에서 사용하는 IP 대역은 서로 다르다(ex. 파드의 IP 대역은 10.244.1.x 이고 서비스의 IP 대역은 10.101.x.x). 또한 서비스에서 사용하는 가상 네트워크는 ipconfig나 라우팅 테이블에서 확인할 수 없다. 따라서 서비스 IP로 파드를 찾아갈 때에는 리눅스 커널에서 제공하는 netfilter와 iptable로 찾아갈 수 있다.
외부(서비스-외부)
노드포트, 로드밸런서, 인그레스(외부에서 내부로 오는 요청들을 어떻게 처리할지에 관한 규칙 모음) 라는 서비스 유형을 통해 통신할 수 있다.
3. DEPLOYMENT 관리
예제 ) nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
디플로이먼트는 k8s에서 상태가 없는 stateless 애플리케이션을 배포할 떄 사용한다. 레플리카셋의 상위 개념으로 위에서는 레플리카셋을 3개 두었다. 아래와 같은 모습이다.
k8s의 큰 장점 중 하나는 버전 관리와 무중단 배포, 리소스 자동 관리이다. 이 Deployment 배포 전략에도 여러 가지가 존재한다.
- rolling - 새 버전을 배포할 때 새 버전은 하나씩 늘려가고 기존 버전은 하나씩 줄여간다.
- recreate - 이전 버전을 모두 한 번에 존재하고 새 버전을 일괄적으로 교체. 파드에 문제가 발생하면 대처 늦어질 수 있음
- blue/green - 이전 버전과 새 버전이 동시에 운영됨. 하지만 새 버전은 서비스 목적으로 접속 가능하나 이전 버전은 테스트 목적으로만 접속 가능하다. 하지만 많은 파드가 필요해 리소스를 많이 잡아먹는다.
- canary(카나리..
까나리??) - blue/green처럼 두 버전 모두 배포하지만 새 버전에는 조금씩 트래픽을 증가시켜 흘러 보냄
파드에서는 단순히 관련성이 있는 컨테이너가 하나의 파드에 포함되어 있는지가 중요했다면, 디플로이먼트에서는 파드(컨테이너)의 버전 관리가 중요하다.
4. Configmap, Secret
Configmap은 환경 변수 같은 값을 도커 이미지에 포함시키지 않고 별도로 분리해서 관리하는 방법을 제공한다. 기밀이 아닌 데이터를 키-값 쌍으로 저장하는 데 사용한다. database 종류나 url, 또는 파드에 볼륨 마운트를 작성하는 용도로 쓰면 좋다.
secret은 비밀번호와 같은 민감한 정보를 저장하는 용도로 사용한다.
5. Stateful 을 위한 영구 볼륨
임시 볼륨 ( 파드 생성 시 같이 생성되고 삭제 시 같이 삭제 ) |
로컬 볼륨 (노드가 종료되는 즉시 삭제) |
외부 볼륨 (영구) |
emptyDir | hostPath | NFS cephFS glusterFS AWS EBS azureDisk |
PV는 영구적으로 데이터를 보관하는 볼륨이고, PVC는 영구 볼륨을 요청하는 볼륨 클레임이다. 개발자는 볼륨을 정의하지 않고 볼륨을 요청하는 볼륨 클레임을 지정한다. 영구 볼륨 생성 시 아래와 같이 pvc(persistent volume claim)를 위한 yaml 파일을 작성한다.
아래는 샘플이다.
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-sample
spec:
capacity:
storage: 2Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
storageClassName: manual
persistentVolumeReclaimPolicy: Delete
hostPath:
path: /tmp/k8s-pv
persistentVolumeReclaimPolicy는 영구 볼륨의 삭제 시 처리 방식에 따라 Retain, Delete, Recycle 정책으로 나뉜다.
'INFRA' 카테고리의 다른 글
[Docker] Docker image에 https 인증서 적용하기 (2) | 2023.11.09 |
---|---|
[API GATEWAY] KONG API Gateway -2 (0) | 2023.10.25 |
[API GATEWAY] KONG API Gateway -1 (0) | 2023.10.23 |
[Docker] 도커를 공부하며.. 🐳 (2) | 2023.10.23 |
[ELK] Elastic Search ILM 정책 (+추가 에러 핸들링) (2) | 2023.09.25 |