AWS EKS 폐쇄망에 Valkey 배포하기
인터넷이 차단된 완전 폐쇄망(Air-gapped) 환경의 AWS EKS 위에 Valkey를 Helm Chart로 배포하는 전 과정을 정리했습니다.
인터넷이 차단된 완전 폐쇄망(Air-gapped) 환경의 AWS EKS 위에 Valkey를 Helm Chart로 배포하는 전 과정을 정리했습니다. Valkey가 무엇인지, 왜 Redis 대신 선택했는지부터 이미지 준비, ECR 업로드, Helm 배포, 영구 스토리지 구성까지 단계별로 설명합니다.
Valkey란?
Valkey는 2024년 3월, Redis의 BSD 오픈소스 포크(fork)로 탄생한 인메모리 데이터 스토어입니다.
탄생 배경: Redis Inc.는 2024년 3월 Redis 7.4부터 기존 BSD-3-Clause 라이선스를 RSALv2와 SSPLv1이라는 더 제한적인 소스어베일러블 라이선스로 전환했습니다. 이는 AWS, GCP 같은 대형 클라우드 벤더가 Redis를 상업적으로 서비스하는 것을 제한하기 위한 조치였습니다.
이에 AWS, Google Cloud, Oracle, Ericsson 등 주요 기업들이 Linux Foundation 산하에서 Redis 7.2.4를 포크하여 Valkey 프로젝트를 시작했습니다. Valkey는 BSD-3-Clause 라이선스를 유지하며, 단일 벤더가 라이선스를 변경할 수 없는 구조로 운영됩니다.
Redis와의 호환성: Valkey는 Redis 7.2 API와 완전히 호환됩니다. 기존 Redis 클라이언트(Lettuce, Jedis, redis-py 등)를 그대로 사용할 수 있고, RESP2/RESP3 프로토콜도 지원합니다.
성능 개선: Valkey 8.0부터 멀티스레드 I/O가 크게 강화되어 멀티코어 CPU 활용도가 높아졌습니다. Redis 7.2 대비 더 높은 처리량과 낮은 레이턴시를 보이는 벤치마크 결과들이 보고되고 있습니다.
배포 환경 및 전제 조건
이 가이드는 다음 환경을 기준으로 합니다.
- EKS 클러스터: NAT Gateway 없는 완전 폐쇄망 (VPC Endpoint만으로 AWS 서비스 접근)
- Bastion 구성: Public Bastion (인터넷 접근 가능) → Private Bastion (인터넷 접근 불가)
- 이미지 레지스트리: AWS ECR (Private)
아래 항목들이 사전에 구성되어 있어야 합니다.
| 전제 조건 | 설명 |
|---|---|
| EKS 클러스터 | kubectl 접근 가능 상태 |
| EBS CSI Driver | kubectl get pods -n kube-system | grep ebs-csi 로 확인 |
| ECR Repository | 이미지를 저장할 Private ECR |
| Helm 3 | Public/Private Bastion 모두 설치 |
| Docker | Public/Private Bastion 모두 설치 |
EBS CSI Driver 필수: Valkey의 영구 스토리지로 EBS 볼륨을 사용하려면 EKS 클러스터에 EBS CSI Driver가 설치되어 있어야 합니다. EBS CSI Driver가 EKS Node의 IAM Role을 통해 AWS API를 호출하여 EBS 볼륨을 자동으로 프로비저닝합니다.
전체 배포 흐름
[Public Bastion]
│
│ 1. helm pull (Chart .tgz)
│ 2. docker pull → docker save (Image .tar)
│
↓ scp
[Private Bastion]
│
│ 3. docker load
│ 4. docker tag → docker push → ECR
│ 5. helm install (values.yaml)
│
↓ kubectl apply
[EKS Cluster]
└── Valkey Pod (EBS PVC 마운트)
EBS CSI Driver 설치
Valkey의 영구 스토리지(EBS PVC)를 자동으로 프로비저닝하려면 EKS 클러스터에 EBS CSI Driver가 설치되어 있어야 합니다. EBS CSI Driver는 **IAM IRSA(IAM Roles for Service Accounts)**를 통해 AWS API를 호출하므로, Add-on 설치 전에 IRSA 설정이 선행되어야 합니다.
1단계: OIDC Provider 확인 및 생성
IRSA는 EKS 클러스터의 OIDC(OpenID Connect) Provider를 기반으로 동작합니다. 먼저 클러스터에 OIDC Provider가 연결되어 있는지 확인합니다.
aws eks describe-cluster \
--name <CLUSTER_NAME> \
--query "cluster.identity.oidc.issuer" \
--output text
# 출력 예: https://oidc.eks.ap-northeast-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E
OIDC Provider가 IAM에 등록되어 있는지 확인합니다.
# URL에서 ID 부분만 추출
OIDC_ID=$(aws eks describe-cluster --name <CLUSTER_NAME> \
--query "cluster.identity.oidc.issuer" --output text | cut -d '/' -f 5)
aws iam list-open-id-connect-providers | grep $OIDC_ID
# 아무것도 출력되지 않으면 아직 미등록 상태
등록되어 있지 않다면 eksctl로 생성합니다.
eksctl utils associate-iam-oidc-provider \
--cluster <CLUSTER_NAME> \
--approve
2단계: IAM Role 생성 (IRSA)
EBS CSI Driver가 AWS API를 호출할 수 있도록 IAM Role을 생성하고, AWS 관리형 정책 AmazonEBSCSIDriverPolicy를 연결합니다.
eksctl 사용 (권장):
eksctl create iamserviceaccount \
--name ebs-csi-controller-sa \
--namespace kube-system \
--cluster <CLUSTER_NAME> \
--attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \
--approve \
--role-only \
--role-name AmazonEKS_EBS_CSI_DriverRole
--role-only옵션을 사용하면 IAM Role만 생성합니다. ServiceAccount는 EKS Add-on 설치 시 자동으로 생성됩니다.
AWS CLI 사용 (수동):
신뢰 정책(Trust Policy) 파일을 먼저 생성합니다.
OIDC_ID=$(aws eks describe-cluster --name <CLUSTER_NAME> \
--query "cluster.identity.oidc.issuer" --output text | cut -d '/' -f 5)
cat > trust-policy.json << EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/oidc.eks.ap-northeast-2.amazonaws.com/id/${OIDC_ID}"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.ap-northeast-2.amazonaws.com/id/${OIDC_ID}:aud": "sts.amazonaws.com",
"oidc.eks.ap-northeast-2.amazonaws.com/id/${OIDC_ID}:sub": "system:serviceaccount:kube-system:ebs-csi-controller-sa"
}
}
}
]
}
EOF
IAM Role을 생성하고 정책을 연결합니다.
aws iam create-role \
--role-name AmazonEKS_EBS_CSI_DriverRole \
--assume-role-policy-document file://trust-policy.json
aws iam attach-role-policy \
--role-name AmazonEKS_EBS_CSI_DriverRole \
--policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy
3단계: EKS Add-on 설치
생성한 IAM Role ARN을 지정하여 EBS CSI Driver Add-on을 설치합니다.
aws eks create-addon \
--cluster-name <CLUSTER_NAME> \
--addon-name aws-ebs-csi-driver \
--service-account-role-arn arn:aws:iam::<AWS_ACCOUNT_ID>:role/AmazonEKS_EBS_CSI_DriverRole
AWS 콘솔에서는 EKS → 클러스터 → Add-ons → 추가 Add-ons 받기 → Amazon EBS CSI Driver 에서 설치할 수 있습니다. IAM Role ARN 입력 필드에 위에서 생성한 Role ARN을 넣어주세요.
4단계: 설치 확인
kubectl get pods -n kube-system | grep ebs-csi
# 정상 출력 예:
# ebs-csi-controller-xxxxxxxxxx-xxxxx 6/6 Running 0 2m
# ebs-csi-node-xxxxx 3/3 Running 0 2m
1. Public Bastion에서 준비
인터넷이 되는 Public Bastion에서 Chart와 이미지를 받아 Private Bastion으로 전송합니다.
Helm Repository 등록 및 Chart 다운로드
# Valkey 공식 Helm 레포지터리 추가
helm repo add valkey https://valkey.io/valkey-helm/
# 레포지터리 업데이트
helm repo update valkey
# Chart 다운로드 (.tgz 파일로 저장)
helm pull valkey/valkey
다운로드된 .tgz 파일을 압축 해제하면 Chart.yaml에서 정확한 Valkey 버전을 확인할 수 있습니다.
tar -xzf valkey-*.tgz
cat valkey/Chart.yaml | grep appVersion
# appVersion: 8.0.2 (버전은 다를 수 있음)
이미지 Pull 및 저장
Chart.yaml에서 확인한 appVersion을 태그로 사용합니다.
# 이미지 Pull
docker pull valkey/valkey:8.0.2
# .tar 파일로 저장
docker save -o ~/valkey.tar valkey/valkey:8.0.2
docker images명령어로 pull된 이미지 이름과 태그를 정확히 확인한 후 사용하세요.
Private Bastion으로 파일 전송
# Chart 전송
scp -i <.pem 키> ~/valkey-*.tgz <User>@<Private Bastion IP>:~
# Image 전송
scp -i <.pem 키> ~/valkey.tar <User>@<Private Bastion IP>:~
2. Private Bastion에서 ECR 업로드
이미지 Load 및 ECR Push
# 이미지 로드
docker load -i ~/valkey.tar
# 로드된 이미지 확인
docker images | grep valkey
# ECR 로그인
aws ecr get-login-password --region ap-northeast-2 | \
docker login --username AWS --password-stdin \
<AWS_ACCOUNT_ID>.dkr.ecr.ap-northeast-2.amazonaws.com
# ECR 태그 생성
docker tag valkey/valkey:8.0.2 \
<AWS_ACCOUNT_ID>.dkr.ecr.ap-northeast-2.amazonaws.com/<ECR_REPO>:valkey-8.0.2
# ECR Push
docker push <AWS_ACCOUNT_ID>.dkr.ecr.ap-northeast-2.amazonaws.com/<ECR_REPO>:valkey-8.0.2
Push 완료 후 로컬 tar 파일을 정리합니다.
rm -rf ~/valkey.tar
3. gp3 StorageClass 생성
Valkey에 영구 스토리지를 붙이려면 먼저 StorageClass를 생성해야 합니다. EKS 기본 gp2 대신 비용 효율이 좋고 성능도 높은 gp3를 사용합니다.
vi ~/sc.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: gp3
annotations:
storageclass.kubernetes.io/is-default-class: "false"
provisioner: ebs.csi.aws.com
parameters:
type: gp3
fsType: ext4
encrypted: "true"
volumeBindingMode: WaitForFirstConsumer # Pod가 스케줄되는 AZ에 EBS 생성
allowVolumeExpansion: true
reclaimPolicy: Delete
kubectl apply -f ~/sc.yaml
# 확인
kubectl get storageclass
volumeBindingMode: WaitForFirstConsumer가 중요합니다. Pod가 특정 AZ에 스케줄된 이후에 해당 AZ에 EBS를 생성하므로, Multi-AZ 클러스터에서 AZ 불일치 문제를 방지합니다.
4. values.yaml 작성
Chart를 배포할 설정 파일을 작성합니다.
vi ~/valkey.yaml
# 이미지: ECR Private Registry 사용
image:
registry: "<AWS_ACCOUNT_ID>.dkr.ecr.ap-northeast-2.amazonaws.com"
repository: "<ECR_REPO>"
tag: "valkey-8.0.2"
pullPolicy: IfNotPresent
# 복제본 수 (standalone: 1, HA: 3 이상 권장)
replicaCount: 3
# 영구 스토리지 설정
dataStorage:
enabled: true
keepPvc: true # Pod 재시작/업그레이드 시 PVC 유지
size: 10Gi
storageClass: "gp3"
accessModes:
- ReadWriteOnce
# Valkey 설정
config: |
appendonly yes
appendfsync everysec
maxmemory-policy allkeys-lru
주요 옵션 설명:
keepPvc: true: Pod 삭제 시에도 PVC를 보존하여 데이터 유실을 방지합니다. 반드시true로 설정하세요.appendonly yes: AOF(Append Only File) 방식으로 모든 쓰기를 디스크에 기록해 내구성을 높입니다.maxmemory-policy allkeys-lru: 메모리 한계 도달 시 LRU 알고리즘으로 키를 제거합니다. 캐시 용도로 사용할 경우 권장 설정입니다.
5. Helm 배포
Chart .tgz 파일을 이용해 배포합니다.
# 네임스페이스 생성
kubectl create namespace valkey
# 배포
helm install valkey ~/valkey-*.tgz \
-n valkey \
-f ~/valkey.yaml
배포 상태를 확인합니다.
# Pod 상태 확인
kubectl get pods -n valkey -w
# PVC 확인 (EBS 볼륨 자동 프로비저닝 여부)
kubectl get pvc -n valkey
# PV 확인
kubectl get pv
정상 배포 시 아래와 같이 출력됩니다.
NAME READY STATUS RESTARTS AGE
valkey-0 1/1 Running 0 2m
valkey-1 1/1 Running 0 90s
valkey-2 1/1 Running 0 60s
6. 배포 확인 및 동작 테스트
Valkey Pod에 직접 접속하여 동작을 확인합니다.
kubectl exec -it valkey-0 -n valkey -- valkey-cli ping
# PONG
kubectl exec -it valkey-0 -n valkey -- valkey-cli set testkey "hello valkey"
# OK
kubectl exec -it valkey-0 -n valkey -- valkey-cli get testkey
# "hello valkey"
# 서버 정보 확인
kubectl exec -it valkey-0 -n valkey -- valkey-cli info server | grep valkey_version
# valkey_version:8.0.2
7. EBS 자동 프로비저닝 흐름
dataStorage.enabled: true로 설정하면 다음 과정이 자동으로 일어납니다.
1. Helm이 PVC 생성 요청 (10Gi, gp3 StorageClass)
↓
2. Kubernetes가 PVC 요청 감지
↓
3. EBS CSI Driver가 EKS Node의 IAM Role로 AWS API 호출
↓
4. AWS에 EBS gp3 볼륨 생성 (10GiB)
↓
5. PersistentVolume(PV) 자동 생성 및 PVC 바인딩
↓
6. Valkey Pod에 볼륨 마운트
EBS CSI Driver가 없으면 PVC가
Pending상태에서 멈춥니다.kubectl describe pvc -n valkey로 원인을 확인할 수 있습니다.
8. 업그레이드 및 삭제
버전 업그레이드
새 Chart와 이미지를 동일한 방식으로 ECR에 올린 후 helm upgrade로 교체합니다.
helm upgrade valkey ~/valkey-<new-version>.tgz \
-n valkey \
-f ~/valkey.yaml
삭제
keepPvc: true로 설정했기 때문에 helm uninstall로 제거해도 PVC(EBS 볼륨)는 유지됩니다.
# Helm Release 삭제
helm uninstall valkey -n valkey
# PVC는 유지됨 (수동으로 삭제해야 EBS 볼륨도 삭제됨)
kubectl get pvc -n valkey
# PVC 수동 삭제 (EBS 볼륨도 함께 삭제됨)
kubectl delete pvc -n valkey --all
마치며
폐쇄망 EKS 환경에서 Valkey를 배포할 때의 핵심은 세 가지입니다.
- 이미지 경로: 모든 이미지는 반드시 ECR에 미리 올려놓아야 합니다.
- EBS CSI Driver: 영구 스토리지를 사용하려면 필수입니다.
- keepPvc: true: 운영 환경에서는 반드시 설정해 데이터 유실을 방지하세요.
Valkey는 Redis API와 완전히 호환되기 때문에 기존 Redis를 사용하던 애플리케이션을 변경 없이 마이그레이션할 수 있습니다. 라이선스 이슈 없이 자유롭게 사용할 수 있는 Redis 대안을 찾고 있다면 Valkey를 강력하게 추천합니다.