23.06.15
DEVOTEE를 활성화 시키면
지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.
버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.
| 컨텐츠 유형 | 제목 | 저장일 | 삭제 |
|---|
본인인증 로그인에 실패하였습니다.
회원이 아니시거나 본인인증 등록이
완료되지 않은 사용자입니다.
많은 회사에서 캐시 용도로 널리 사용하는 Redis! 빠른 데이터 처리 속도 덕분에 세션 관리, 메시지 브로커 시스템, 실시간 분석 등 다양한 분야에서 활약하고 있습니다.
하지만 Redis를 직접 사용하려면 서버 구축부터 설치, 운영까지 꽤 복잡한 과정을 거쳐야 합니다. 이는 서비스 출시를 지연시키는 요인이 될 수 있습니다.
저희 팀 역시 대용량 데이터를 실시간으로 처리하기 위해 다양한 프로젝트에서 Redis를 활용하고 있습니다.
기존 방식대로 서버를 구축하고 운영하는 데에는 시간과 비용이 많이 들었고, 데이터 증가에 따른 확장성 문제도 발생했습니다.
이러한 문제를 해결하기 위해 필요할 때 바로 사용할 수 있는 SaaS형 Redis 서비스를 고민하게 되었고, Kubernetes Operator를 활용한 Redis Cluster 구축 방안을 모색하게 되었습니다.
출처: http://www.chlux.co.kr/bbs/board.php?bo_table=board02&wr_id=262
SaaS(Software as a Service)는 인터넷을 통해 소프트웨어를 사용할 수 있는 서비스를 의미합니다.
대표적으로 Gmail이나 네이버 메일 같은 이메일 서비스를 들 수 있습니다.
과거에는 이메일 서비스를 사용하려면 직접 서버를 구축하고 소프트웨어를 설치해야 했지만, SaaS형 서비스 덕분에 복잡한 과정 없이 편리하게 이메일을 사용할 수 있게 되었습니다.
SaaS형 Redis Cluster 서비스 역시 사용자들에게 다음과 같은 장점을 제공합니다.
시간 및 비용 절감: 서버 구축과 유지보수에 드는 시간과 비용을 크게 절약할 수 있습니다.
빠른 서비스 개발: 인프라 걱정 없이 바로 Redis를 사용하여 서비스 개발 속도를 높일 수 있습니다.
안정성 및 성능 향상: SaaS 제공자가 Redis Cluster를 관리하고 최적화하여 안정성과 성능을 보장합니다.
장애 대응: 장애 발생 시 신속한 대응이 가능하여 서비스 중단을 최소화합니다.
출처: https://www.cloudflare.com/ko-kr/learning/cloud/what-is-saas/
Redis는 단일 인스턴스 모드, Sentinel 모드, Cluster 모드를 지원합니다.
각 모드마다 특징이 있지만, 저희 팀은 대용량 메모리 지원과 고가용성이 필요했기 때문에 Redis Cluster를 선택했습니다.
Redis Cluster는 데이터를 여러 노드에 분산 저장하여 더 큰 데이터 용량을 지원하고, 고가용성과 성능을 동시에 보장합니다.
출처: https://redis.io/redis-enterprise/technology/redis-enterprise-cluster-architecture/
Redis Cluster를 직접 설치하고 운영하려면 다음과 같은 어려움이 따릅니다.
복잡한 설치 및 설정: 수동으로 설치하고 설정하는 과정이 복잡하고, 여러 노드 간의 정확한 구성이 필요합니다.
스케일링의 어려움: 데이터 증가에 따라 Redis Cluster를 확장해야 하는데, 새로운 노드 추가와 데이터 재분배 과정이 복잡합니다.
장애 대응 및 복구: 노드 장애 발생 시 신속한 대응과 복구가 필요한데, 이는 운영팀에 큰 부담이 됩니다.
Redis Cluster 설치 방법은 https://devocean.sk.com/blog/techBoardDetail.do?ID=165603&boardType=techBlog&searchData=Redis&page=&subIndex=최신+기술+블로그 글에 자세히 설명되어있습니다.
Kubernetes Operator는 Redis Cluster의 생성, 운영, 관리를 자동화하여 위에서 언급한 어려움을 해결해 줍니다.
자동화된 설치 및 설정: 복잡한 과정을 자동화하여 시간을 절약하고 오류 가능성을 줄입니다.
간편한 스케일링: 자동으로 노드를 추가하고 데이터를 재분배하여 확장성 문제를 해결합니다.
자동화된 장애 대응: 장애를 자동으로 감지하고 복구 절차를 수행하여 시스템 안정성을 높입니다.
출처: https://www.cncf.io/blog/2022/06/15/kubernetes-operators-what-are-they-some-examples/
Kubernetes Operator는 특정 애플리케이션의 관리를 자동화하는 소프트웨어입니다.
단순히 애플리케이션을 배포하고 실행하는 것을 넘어서, 원하는 상태를 지속적으로 유지하고 문제 발생 시 자동으로 복구하는 등 고급 기능을 수행합니다.
이러한 기능을 이해하기 위해서는 Kubernetes 시스템의 핵심 개념인 Desired state를 먼저 알아야 합니다.
Desired state는 말 그대로 "원하는 상태"를 의미합니다.
Kubernetes에게 우리가 원하는 시스템의 상태를 선언하는 것이죠. 예를 들어, 특정 서비스가 항상 3개의 Pod로 실행되기를 원한다면, 이것이 Desired state가 됩니다.
Kubernetes는 Desired state를 달성하고 유지하기 위해 Kubernetes Resource와 Controller라는 두 가지 중요한 요소를 사용합니다.
출처: https://iximiuz.com/en/series/writing-kubernetes-controllers-operators/
Kubernetes Resource: Kubernetes API를 통해 관리되는 엔티티로, Pod, Deployment, Service, Volume 등 다양한 종류가 있습니다.
각 Resource는 고유한 이름을 가지고 있으며, 클러스터의 현재 상태를 나타냅니다. 또한, Desired state를 정의하는데 사용합니다.
예를 들어, Deployment Resource는 원하는 Pod의 개수, 이미지, 환경 변수 등을 정의하여 Desired state를 표현합니다.
Controller: Kubernetes의 핵심 컨트롤 루프로, 현재 클러스터 상태를 Desired state에 가깝게 만드는 역할을 합니다.
Controller는 특정 Resource 유형을 감시하고, 현재 상태와 Desired state를 비교합니다.
만약 차이가 있다면, Pod 생성/삭제, 설정 변경 등 필요한 조치를 취하여 Desired state를 달성합니다.
이 과정은 지속적으로 반복되어 시스템 상태가 항상 Desired state를 유지하도록 합니다.
Operator는 이러한 Kubernetes Resource와 Controller 개념을 확장하여 특정 애플리케이션의 Desired state를 보다 효과적으로 관리합니다.
Operator는 Custom Resource와 Custom Controller를 통해 작동합니다.
Custom Resource: 사용자가 정의한 새로운 Resource 유형입니다.
예를 들어, RC Operator는 RC(RedisCluster)라는 Custom Resource를 정의하여 Redis Cluster의 Desired state를 표현합니다.
Custom Controller: Custom Resource를 감시하고 관리하는 Controller입니다.
RC Operator의 Custom Controller는 RC Resource의 Desired state를 감시하고, 필요한 경우 Pod 생성, 설정 변경, 장애 복구 등의 작업을 수행하여 Desired state를 유지합니다.
Operator를 사용하면 다음과 같은 장점을 얻을 수 있습니다.
복잡한 관리 작업 자동화: 애플리케이션의 배포, 설정, 확장, 업그레이드, 백업, 복구 등 복잡한 작업을 자동화하여 운영 부담을 줄입니다.
전문 지식 내장: Operator는 해당 애플리케이션에 대한 전문 지식을 내장하고 있어, 최적의 상태로 운영되도록 관리합니다.
선언적 구성: Desired state를 선언적으로 정의하여, 시스템의 의도를 명확하게 표현하고 일관성을 유지합니다.
Operator는 다양한 애플리케이션 관리에 활용할 수 있습니다.
특히, 기본 Resource 와 Controller로 처리하기 어려운 복잡한 작업이나 애플리케이션 특화 기능을 자동화하는 데 유용합니다.
데이터베이스(MySQL,PostgreSQL, MongoDB):
자동화된 백업 및 복구: 데이터베이스의 정기적인 백업과 장애 발생 시 자동 복구를 수행합니다.
데이터 베이스의 자동 복구는 각 데이터 베이스 별 특화된 전문 지식이 필요하고, 특별한 수행 과정이 필요한데, 기본 Controller 로는 구현하기 어려운 부분입니다.
장애 조치 (Failover): 마스터 노드 장애 시 자동으로 슬레이브 노드를 마스터로 승격시키는 등 복잡한 장애 조치 과정이 필요한데,
장애 감지, 상황에 맞는 분기, 특화된 처리등은 해당 데이터 베이스 전용의 Operator 로 수행 가능합니다.
메시징 시스템(Kafka):
파티션 리밸런싱: 메시지 처리량에 따라 파티션을 자동으로 재조정합니다. 통계 정보를 수집 명령을 수행하고,
확인한 통계량을 바탕으로 파티션을 재조정 명령을 수행하는등 복잡한 처리작업은 Operator 로 수행할수 있습니다
Operator 개발에는 다양한 도구와 언어를 사용할 수 있습니다. 대표적으로 Kubebuilder, Go Operator SDK, Ansible Operator SDK가 있습니다.
Kubebuilder: Kubernetes SIG API Machinery에서 관리하며, Kubernetes API Machinery에 대한 깊은 이해를 바탕으로 Operator를 개발할 수 있는 프레임워크입니다.
사용자 정의 리소스 정의, 웹훅, admission controller 등 Kubernetes API의 다양한 기능을 활용하여 복잡한 Operator를 구현할 수 있습니다.
Go Operator SDK: Red Hat에서 주도하는 Operator Framework 프로젝트의 일부이며, Go 언어 기반의 Operator 개발을 위한 프레임워크입니다.
CLI 명령어와 Scaffolding 기능을 통해 개발 과정을 간소화하고, 빠른 Operator 개발을 지원합니다.
Ansible Operator SDK: Ansible을 사용하여 쉽고 빠르게 Operator를 개발할 수 있지만, Go에 비해 성능이 떨어질 수 있습니다.
저희 팀은 Redis Cluster 생성 및 관리에 세밀한 제어와 Kubernetes API의 다양한 기능 활용이 필요했기 때문에 Kubebuilder를 선택했습니다.
앞서, RC 개발의 배경, SaaS형 Redis 서비스의 장점, 그리고 Kubernetes Operator에 대해 설명하였습니다.
이제 저희 팀이 RC 서비스를 개발한 과정을 각 단계별로 간략하게 소개하겠습니다.
Kubebuilder CLI 설치:
Kubebuilder 설치는 **공식 가이드**를 참고하여 Go 언어 버전, Kubernetes(Kubectl) 버전에 맞는 버전을 설치합니다.
아래는 RC 프로젝트에서 사용한 환경 설정입니다.
어플리케이션 | 버전 |
|---|---|
Go | v1.20.5 |
kubebuilder | v3.3.0 |
controller-runtime | v0.15.0 |
Kubebuilder 자세한 사용법은 https://devocean.sk.com/blog/techBoardDetail.do?ID=164257 에서 확인할 수 있습니다.
RC로 생성할 Redis Cluster Docker 이미지, Helm 차트 준비:
RC는 Redis Cluster의 생성, 변경, 삭제, 장애 감지 및 복구 과정 중 상태를 체크하고, Desired State에 따라 Reconcile 로직을 수행하는 Custom Controller 역할에 초점을 맞춥니다.
기본적인 Controller, Resource로 처리할 수 있는 부분은(생성, 변경, 삭제) Helm 차트를 사용합니다.
RC는 널리 사용되는 오픈소스인 Bitnami Redis-Cluster 차트를 사용하고 있습니다.
이 Helm 차트에는 Redis Cluster의 생성, 변경, 삭제에 필요한 Docker 이미지, 설정, 스크립트 등이 포함되어 있습니다.
RC는 장애 복구를 위해 수정한 스크립트를 추가하여 자체 빌드한 Docker 이미지와 이를 반영하여 수정한 Helm 차트를 사용합니다.
추가/변경 사항:
RC가 Redis Cluster의 마스터/슬레이브 노드를 정확하게 파악하고, 장애 발생 시 각 노드의 타입에 따른 조치를 취할 수 있게,
Helm 설치 시 RC가 Redis Client를 사용하여 마스터/슬레이브 구성을 직접 설정하도록 설치 스크립트를 변경하였습니다.
노드 종료 시(예를 들어, Drain 등의 이유로) 해당 노드가 마스터 노드인 경우, Kubernetes PreStop Hook를 사용하여 마스터를 슬레이브로 전환하는 스크립트를 추가하였습니다.
이를 통해 마스터 노드가 자연스럽게 슬레이브로 전환되며, Redis Client는 타임아웃 없이 전환된 마스터(기존 슬레이브)와 통신할 수 있게 변경하였습니다.
Docker 이미지:
Helm 차트:
Redis Cluster Proxy(Predixy) Docker 이미지, Helm 차트 준비:
아래에서 더 자세히 설명할 예정이지만, RC는 SaaS 형태의 서비스로써, Kubernetes Cluster 외부 사용자가 RC가 생성한 Redis Cluster에 접근하여 사용할 수 있도록 Proxy 서버를 제공합니다.
(관련 링크) RC는 Redis Cluster를 설치할 때 함께 준비한 Predixy 차트도 같이 설치합니다.
Git:
Docker 이미지:
먼저, Kubebuilder CLI create 명령을 사용하여 RC Custom Resource를 생성합니다.
이후, 자동 생성된 스켈레톤 코드에 RC의 원하는 Desired State를 정의하는 spec과 status 필드를 추가합니다.
이 단계에서는 Operator가 제공하는 기능과 역할을 고려해야 합니다.
RC가 제공하는 기능은 Redis Cluster의 생성, 변경, 삭제 기능과 장애 발생 시 장애 인지 및 자동 복구였으며,
이를 수행하는 데 필요한 설정, 상태 등을 포함했습니다.
RcSpec 필드에는 Redis Cluster 설정에 사용될 필드를 추가합니다.
필드 | 설명 |
|---|---|
Shard | 구성할 마스터 노드의 노드 수 설정(최소 3) |
Replica | 설정할 복제본(슬레이브)의 세트 수(기본 1) |
Memory | 클러스터에서 사용할 메모리 총량. 예) 300mb → Shard가 3인 경우, 각 노드별 100mb 할당. Replica가 1이면, 마스터 300 + 슬레이브 300 = 총 600mb 할당 |
AdditionalConf | 기본 설정 외에 redis.conf 파일에 추가 설정이 필요할 때 사용 |
NodeSelector | Kubernetes 배포 시 특정 노드 선택 배포가 필요한 경우 설정 |
RedisPort | Redis Cluster 구성 시 클라이언트 접속 포트. 기본 6379 |
HostNetwork | Redis Cluster 배포 시 Host Network 사용 여부 |
NodePort | 외부 사용자가 할당받은 Redis Cluster에 접근 시 사용할 포트 |
RcStatus 필드에는 Redis Cluster 상태 정보와 관련된 필드를 추가합니다.
필드 | 설명 |
|---|---|
Phase | 현재 Redis Cluster가 어떤 단계에 있는지 표시합니다. 예를 들어 Running, Pending, Panic 등 |
RedisClusterStatus | Redis Cluster 내 각 파드(노드)의 상태를 표시합니다. 파드의 역할(마스터/슬레이브), 어떤 노드와 연결되어 있는지, 파드의 상태 등 |
Message | 최종 상태를 메시지 형태로 제공합니다. |
EventTimelines | 과거 Redis Cluster에서 발생한 주요 이벤트(상태 변경)를 리스트로 제공합니다. |
Kubebuilder CLI를 사용하여 프로젝트를 초기화하고, 이 과정에서 생성된 스켈레톤 코드에 RC Custom Controller를 구현합니다.
RC Controller의 가장 중요한 요소는 스켈레톤 코드에서 생성된 Reconcile 함수의 구현입니다.
이 함수는 원하는 상태(Desired state)와 현재 상태를 비교하며, 두 상태가 일치하지 않을 경우 필요한 로직을 실행하여 원하는 상태로 조정합니다.
Reconcile 함수는 다음의 작업을 수행합니다.
RcSpec 정보를 기반으로 Redis Cluster를 생성, 삭제, 업데이트, 스케일링합니다.
Helm 라이브러리를 사용하여 RcSpec에 따라 Helm 차트 값을 수정하고 설치, 업데이트합니다.
Redis Cluster의 현재 상태 정보를 RcStatus의 Phase 필드에 업데이트합니다.
Kubernetes API를 사용하여 Redis Cluster의 Pod, Service, PV/PVC 상태를 확인하고 정보를 추출합니다.
이 정보를 통해 현재 Phase를 결정하고, 다음 Phase로 전환할 수 있게 합니다.
Phase | 설명 |
|---|---|
Running | 모든 Pod가 정상 상태이며, 마스터/슬레이브가 고르게 배치되어 실행되고 있음 |
WithPending | Pending Pod 또는 PodReady가 False인 Abnormal Pod가 하나 이상 존재하는 상태 |
WithUnstable | 복구가 완료된 Abnormal Pod가 다시 살아나는 상태 |
WithRecovering | Abnormal Pod가 다시 살아나는 경우, 복구를 진행하는 상태 |
Panic | 단일 샤드의 마스터, 슬레이브가 모두 죽은 경우, 사람의 운영 개입이 필요한 상태 |
Redis Client를 사용하여 Cluster를 구성합니다.
Go Redis 클라이언트 라이브러리를 사용하여 Redis Cluster와 연결하고, 다음의 작업을 수행합니다.
Redis Cluster 구성: Helm 차트를 사용하여 Redis Cluster를 생성했지만, Cluster가 구성된 상태는 아닙니다.
RC는 Redis Client를 사용하여 각 Pod(노드) 정보를 확인 후 Cluster를 구성하고 연결 설정합니다.
Redis Cluster 상태 정보 확인 및 재구성: Redis Client를 사용하여 지속적으로 Redis Cluster의 Pod 상태를 확인하고,
Desired State가 아닌 경우 Cluster를 재구성합니다.
장애가 발생한 경우 상황을 파악하고, 다음의 장애 처리 절차를 수행합니다.
Redis Cluster의 현재 상태가 Abnormal(즉, Running 상태가 아닌 경우)인 경우 장애가 발생했다고 판단하고, 복구 작업을 수행합니다.
예를 들어, 마스터 노드에서 장애가 발생한 것을 확인하면 WithPending Phase로 전환합니다.
해당 노드가 복구될 수 있도록 Pod를 재시작하는 등의 작업을 수행합니다.
노드가 정상적으로 실행되면 Redis Cluster에 해당 Pod를 등록하고, 마스터/슬레이브 역할을 부여하는 등의 복구 작업을 수행합니다.
최종적으로 정상 상태가 되면 Phase를 Running으로 업데이트합니다.
Prometheus, Grafana 를 사용하여 Redis Cluster와 RC Operator의 상태를 모니터링하고, 시각화합니다.
RC는 상태 정보 수집을 위해 Bitnami Redis Cluster로 제공되는 Redis Exporter를 사용합니다.
주요 모니터링 항목은 다음과 같습니다.
Redis Cluster 노드 상태
Redis Cluster 메모리 사용량
Redis Cluster 트래픽
클러스터 생성, 삭제, 변경 API 구현:
사용자가 Redis Cluster를 생성, 삭제, 변경할 수 있는 API를 구현합니다.
만약 Redis Cluster를 생성, 삭제, 변경하는 API가 없다면, 사용자가 직접 Custom Resource(RC) ymal 파일을 작성해
Kubernetes에 적용하거나, 삭제, 변경 명령을 수행해야합니다.(kubectl 이용)
Kubernetes에 RC Operator 배포시 RC CRUD API(RESTful API 형태)를 같이 배포하고,
사용자는 API를 통해 Redis Cluster의 spec을 정의하고, Operator가 해당 spec에 따라 Redis Cluster를 생성하고 관리하게 합니다.
Kubernetes 외부에 서비스 제공(proxy):
사용자가 Kubernetes 외부에서 Redis Cluster에 접근할 수 있도록 proxy를 구성합니다.
Kubernetes 내부에서 Redis Cluster를 접근하는 일반적인 상황에서는 고려할 사항이 아니지만,
SaaS형 서비스로 외부 사용자에게 제공시에는 반드시 확인이 필요한 부분입니다.
Redis Cluster Proxy: Redis Cluster 모드에서 클라이언트는 Redis Cluster의 모든 노드와 연결하고 통신해야 합니다.
Kubernetes 외부에서 내부에 설치된 Redis Cluster에 직접 연결하려면, Redis 노드 수만큼(최소 6개)의 Service NodePort를 설정해야 합니다.
NodePort는 한정된 자원(30000-32767)이므로 낭비를 최소화해야 합니다.
이 문제를 해결하기 위해, RC 서비스는 Redis Cluster 설치 시 함께 Redis Cluster Proxy(Predixy)를 배포하고,
외부 사용자에게는 이 Proxy 주소(1개 NodePort)를 제공합니다. 외부 사용자는 이 Proxy 주소를 통해 Redis 단일 인스턴스 Client Library로 접속해 사용합니다.
Predixy는 Redis Cluster Proxy 를 목적으로 개발된 오픈 소스 프로젝트 입니다. 오픈소스 공개후 추가 개발이 되지 않아,
Kubernetes 환경에 바로 사용할 경우 Cluster Node 간 통신중 한 노드가 재시작되는 경우 ip 주소가 업데이트 되지 않는 문제를 겪게 됩니다.
저희팀에서는 해당 오픈소스 ip 갱신 관련 코드를 수정해 문제를 해결했습니다.
Redis RESTful API: 사용자가 Redis Client를 사용하지 않고 RESTful API를 통해 Redis Cluster를 사용할 수 있도록 API Gateway를 구축합니다.
이를 통해 Redis 사용 경험을 개선하고, 다양한 애플리케이션과의 통합을 쉽게 할 수 있습니다.
Redis 는 string 기반의 단순한 get/set 명령외에, list, set, zset, hash 자료구조와 pub/sub 을 이용한 메세지 전송 기능을 제공합니다.
Redis의 자료구조/기능을 HTTP 프로토콜만 이용해 RESTful API로 구현하는 것은 어렵습니다.
pub/sub의 경우 HTTP 프로토콜을 확장한 WebSocket을 활용해 제공하고 있고, string get/set 명령부터 사용자가 원하는 API를 순차적으로 추가하고 있습니다.
인증 및 보안: RC는 사내에서 제공하는 서비스이지만, 다양한 목적을 가진 사용자에게 SaaS 형 서비스를 제공하기 때문에 보안에 대한 고려가 필요합니다.
인증, 권한 관리, 트래픽 제한등이 필요한데, Redis는 자체적으로 AUTH 명령을 이용 password 입력방식의 인증을 지원하지만, 부족한 점이 있습니다.
더 나은 인증 및 보안을 위해 OAuth 2.0을 이용 사용자 인증을 처리하고, RBAC (Role-Based Access Control)을 사용하여 사용자 권한을 관리하고,
API Gateway를 이용 트래픽 제한 기능을 제공할 예정입니다.
개발한 RC를 사내 서비스로 제공하여, Redis Cluster를 필요로 하는 팀들이 쉽고 빠르게 Redis Cluster를 생성하고 관리할 수 있도록 Web UI를 지원합니다.
서비스 사용량 모니터링을 Web UI로 제공합니다.
Kubernetes Operator를 활용한 SaaS형 Redis 서비스인 RC 개발을 통해, 저희 팀은 Redis 사용의 복잡성을 줄이고, 사용자 경험을 향상시켰습니다.
RC는 설치와 운영을 자동화하고, 사용자 친화적인 인터페이스를 제공하여 개발 팀의 시간과 비용을 절약할 뿐만 아니라, 안정적이고 확장 가능한 Redis 서비스를 사내 프로젝트에 제공합니다.
앞으로도 보안 강화와 기능 확장을 통해 사용자에게 더 나은 서비스를 제공할 계획입니다. RC는 지속적인 개선을 통해 더욱 강력하고 편리한 Redis 서비스로 자리매김할 것입니다.
DEVOTEE를 활성화 시키면
지금 작성한 댓글에 AI가 댓글을 달아줍니다.