ECK란?
ECK는 Elastic Cloud on Kubernetes 약자로 ELK 스택을 쿠버네티스 환경에서 쉽게 배포하고, 관리할 수 있도록 해주는 솔루션입니다. Elasticsearch에서 공식적으로 제공하는 쿠버네티스 오퍼레이터이며, 기본적으로 엘라스틱서치 클러스터 배포, 관리, 스케줄링 등을 자동화할 수 있게 해줍니다.
CRD 정의 및 등록
kubectl create -f https://download.elastic.co/downloads/eck/2.16.1/crds.yaml
CRD는 쿠버네티스에서 자신만의 리소스를 정의할 수 있도록 해주는 기능입니다. 공식적으로 엘라스틱서치는 ECK 배포를 위해 CRD를 배포했습니다. 기본적으로 쿠버네티스는 Pod, Service, Deployment 와 같은 리소스 객체를 제공하지만, 사용자만의 특별한 리소스가 필요할 때 CRD를 사용합니다. 만약에 PostgreSQLCluster가 필요하다면 관련된 리소스를 쿠버네티스에서 제공해주지 않으니 따로 CRD로 정의해서 사용할 수 있을 것입니다.
실행하면 crd가 만들어지는 것을 확인할 수 있습니다.
오퍼레이터 배포
kubectl apply -f https://download.elastic.co/downloads/eck/2.16.1/operator.yaml
오퍼레이터란? 무엇일까요? 오퍼레이터는 CRD를 사용하여 자동으로 엘라스틱 서치 관련 리소스를 생성하고 관리하는 역할을 합니다. CRD를 조작하는 컨트롤러라고 생각하면 쉽습니다. ECK를 사용하기 위해서는 CRD + Operator를 꼭 등록해야 ELK 스택을 사용할 수 있습니다.
오퍼레이터를 잘 설치했으면 로그를 확인해 볼 수 있습니다.
kubectl -n elastic-system logs -f statefulset.apps/elastic-operator
이후 CRD + Oprator를 배포했으면 구성된 요소를 확인할 수 있습니다. Elasticsearch, Logstash, Kibana 이외에 다른 beat나 모니터링 기능을하는 다른 리소스들도 정의 된 것을 확인할 수 있습니다.
kubectl get customresourcedefinitions.apiextensions.k8s.io | grep elastic
Elasticsearch 매니페스트 배포
CRD + Operator까지 배포했다면 마지막으로 Elasticsearch 클러스터를 어떻게 구성할 것인가에 대한 매니페스트 파일을 정의해주고 쿠버네티스에 배포하면 됩니다.
elasticsearch.yaml
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
name: quickstart
spec:
version: 8.11.1 # 원하는 Elasticsearch 버전 지정 가능
nodeSets:
- name: default
count: 1 # 노드 개수 설정 가능
config:
node.store.allow_mmap: false
kubectl apply -f elasticsearch.yaml
이렇게 배포를하면 끝인데, 나처럼 에러를 겪는 경우가 많다 보니까 트러블슈팅도 함께 기록하고자 한다.
StorageClass 정의를 안 해뒀을 경우
위 에러는 영구 저장소를 찾을 수 없다는 뜻의 에러다. 엘라스틱서치도 NoSQL 데이터베이스에 속할 수 있기 때문에 데이터를 저장하고, 기억해야 한다. 파드의 특성상 죽었다가 살아나면 휘발되는 stateless 성격을 가졌지만, 이러한 파드도 stateful하게 데이터를 저장할 수 있도록할 수 있다. 그것이 statefulset인데 엘라스틱서치도 CRD로 정의하긴 했지만 엄밀히 말하자면 statefulset의 성격을 지닌다. 때문에 StorageClass가 필요하다.
PV, PVC, StorageClass는 무엇인가?
PV는 쿠버네티스 클러스터 전반에서 공유 가능한 영구 스토리지다.
PVC는 Persistent Volume Claims 라고해서 PV를 요청하는 신청서와 같다고 생각하면 쉽다.
StorageClass를 사용하지 않는다면, PV를 미리 정의하고 PVC를 생성해야 PV를 사용할 수 있다.
PVC가 기존에 정의된 PV를 찾아서 연결하는 방식을 정적 프로비저닝이라고 한다. PV를 정의할 필요없이 PVC만 정의해주면 알아서 할당 PV를 사용할 수 있게하는 것이 StorageClass다. 이를 동적 프로비저닝이라고 한다.
나는 Elasticsearch를 배포하기 전에 StorageClass를 정의해두지 않았기 때문에] default StorageClass가 없어서 PV가 생성되지 않아. 위와 같은 에러가 발생한 것이었다. ECK에는 이미 PVC를 정의해두었기에 기본 스토리지 클래스만 만들어주면 알아서 PV가 생기며 배포가 될 것이다.
NFS StorgaeClass 설치
나의 작업환경은 온프레미스에서 쿠버네티스를 사용하고 있다. EKS, GKE라면 다른 스토리지를 사용하면 되지만 로컬에서 간단히 테스트 해보는 용도로 NFS가 적합하다. 물론 프로덕션 환경에서는 그렇게 좋진 않다.
NFS 서버 설치(Linux)
# NFS 서버 패키지 설치
sudo apt-get update
sudo apt-get install nfs-kernel-server -y
# NFS 공유 디렉토리 생성
sudo mkdir -p /nfs/data
sudo chown nobody:nogroup /nfs/data
sudo chmod 777 /nfs/data
# NFS 설정 파일 수정
sudo vi /etc/exports
/nfs/data *(rw,sync,no_subtree_check,no_root_squash)
# NFS 서버 재시작
sudo exportfs -a
sudo systemctl restart nfs-kernel-server
각 쿠버네티스 Worker 노드에 NFS 클라이언트 설치
# 모든 worker 노드에서 실행
sudo apt-get update
sudo apt-get install nfs-common -y
NFS StorageClass 설정을 위한 Helm 차트 설치
# NFS Subdir External Provisioner 저장소 추가
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
# 저장소 업데이트
helm repo update
혹여나 헬름이 설치되어 있지 않으면 아래의 것을 실행하면 된다.
Helm 설치(Optional)
curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 > get_helm.sh
chmod 700 get_helm.sh
./get_helm.sh
nfs-values.yaml 파일 생성
# nfs-values.yaml
nfs:
server: <NFS_SERVER_IP> # NFS 서버 IP 주소
path: /nfs/data # NFS 공유 경로
storageClass:
name: nfs-client # StorageClass 이름
defaultClass: false # 기본 StorageClass로 설정할지 여부
Helm으로 NFS Provisional 설치
# nfs-provisioner namespace 생성
kubectl create namespace nfs-provisioner
# Helm으로 설치
helm install nfs-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \\
--namespace nfs-provisioner \\
-f nfs-values.yaml
설치확인
# StorageClass 확인
kubectl get sc
# Provisioner Pod 확인
kubectl get pods -n nfs-provisioner
시스템 볼륨 이슈
nfs StorageClass를 정상적으로 배포했지만 위와 같은 에러가 발생했다. PV를 자동으로 할당하려는데 이를 할당 할 수 없다는 것이다. 왜냐면 나는 컨트롤 플레인1, 워커노드1 이렇게 구성된 쿠버네티스 클러스터다. 워커노드1에는 현재 디스크 용량이 부족한 상태였고, 컨트롤 플레인은 기본적으로 쿠버네티스 api를 관리하는 곳이기 때문에 엘라스틱 서치 같은 pod는 실행할 수 없도록 Taint가 걸려있다.
Taint란?
테넌트는 특정 노드에서 파드를 제한하거나 차단하는 메커니즘인데, 컨트롤 플레인에서는 쿠버네티스를 가동시키는 중요한 etcd, 스케줄러, api 등이 실행되고 있다. 때문에 쿠버네티스 운영에만 자원사용을 집중하려고 디스크 용량이 충분한 컨트롤 플레인에 엘라스틱서치가 올라오려고 하자 이를 차단한 것입니다.
그래서 해결방법은 워커노드의 디스크 용량을 확보하면 되는 것이었습니다.
VM웨어 워크스테이션에서 VM이 돌아가고 있는데 피지컬 스토리지는 20GB를 할당했지만 실제로 10G만 사용중 이를 우분투 명령어로 확장해주었습니다.
sudo lvextend -L +5G /dev/mapper/ubuntu--vg-ubuntu--lv
sudo resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv
그리고 다시 kubectl apply -f elasticsearch.yaml 을 배포하니 정상적으로 pod가 실행 되었습니다.
Elasticsearch 접근 및 인증 정보 확인
kubectl get service quickstart-es-http
ECK에서 시스템 접근을 위한 사용자 계정은 기본적으로 Elastic 이며, 비밀번호는 명령어로 확인 가능합니다.
kubectl get secret quickstart-es-elastic-user -o go-template='{{.data.elastic | base64decode}}'
이렇게 비밀번호를 확인하고, 포트포워딩으로 9200번을 열어준 후 curl 명령어로 접근 테스트를 할 수 있습니다.
kubectl port-forward service/quickstart-es-http 9200
curl -u "elastic:<비밀번호>" -k "https://localhost:9200"
포트포워딩을 해두면 로컬 pc에서도 접속할 수 있습니다.
**참고자료**
https://www.elastic.co/guide/en/cloud-on-k8s/current/k8s-deploy-elasticsearch.html
https://esbook.kimjmin.net/ https://discuss.elastic.co/t/pod-has-unbound-immediate-persistentvolumeclaims/274057 https://kubernetes.io/docs/concepts/storage/storage-classes/ https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/
https://www.elastic.co/kr/blog/elastic-stack-monitoring-with-elastic-cloud-on-kubernetes
'ELK' 카테고리의 다른 글
[Elasticsearch] 엘라스틱서치란? 핵심 개념 잡기 (0) | 2025.03.17 |
---|