
#EBS CSI Driver 설치 여부 확인
$ kubectl get pods -n kube-system | grep ebs
--- 아무것도 뜨지 않음 --- -> EBS CSI Driver 설치 되어있지 않음
$ kubectl get storageclass -o wide
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
gp2 kubernetes.io/aws-ebs Delete WaitForFirstConsumer false
19h
EKS 클러스터에 EBS CSI Driver가 아직 설치되지 않았다는 뜻
Kubernetes가 EBS 볼륨을 동적으로 생성할 수 없기 때문에 PVC가 계속 Pending 상태로 남아있어 문제가 발생하고 있다.
eksctl create addon \
--name aws-ebs-csi-driver \
--cluster <클러스터명> \
--region ap-northeast-2 \
--force

EBS CSI 드라이버 확인
kubectl get pods -n kube-system | grep ebs

eksctl create addon \
--name aws-ebs-csi-driver \
--cluster <클러스터명> \
--region ap-northeast-2 \
--service-account-role-arn <IAM_ROLE_ARN> \
--force
kubectl apply -f gp3-storageclass.yaml
kubectl get pods -n kube-system | grep ebs
kubectl get pvc -n redis-cluster
kubectl get pods -n redis-cluster
하지만 여전히 pending인 상태가 지속 되었다
StorageClass gp2가 CSI 드라이버랑 연결되어 있지 않기 때문
위의 helm 방식은 잘 안되어서 yaml로 수동으로 해줘야 한다.
kubectl create namespace redis-cluster
sudo vi redis-headless-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: redis-cluster
spec:
ports:
- port: 6379
clusterIP: None # Headless
selector:
app: redis
kubectl apply -f redis-headless-svc.yaml
# redis-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
namespace: redis-cluster
spec:
serviceName: "redis"
replicas: 6
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7.2
command:
- redis-server
- "--cluster-enabled"
- "yes"
- "--cluster-config-file"
- "nodes.conf"
- "--cluster-node-timeout"
- "5000"
- "--appendonly"
- "yes"
ports:
- containerPort: 6379
volumeMounts:
- name: data
mountPath: /data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: gp3 <= redis의 pvc
resources:
requests:
storage: 1Gi
kubectl apply -f redis-statefulset.yaml
이제 모든 redis 파드가 bound 되었으니 클러스터를 구성해주자.
아래 명령어는 자동으로 마스터-슬레이브 쌍으로 클러스터를 구성해주는 명령어이다.
multi-az에 내가 원하는 구성으로 고정해서 구성하는 방식은 조금 더 아래에서 하도록 한다.
kubectl exec -n redis-cluster -it redis-0 -- redis-cli --cluster create \
redis-0.redis:6379 redis-1.redis:6379 redis-2.redis:6379 \
redis-3.redis:6379 redis-4.redis:6379 redis-5.redis:6379 \
--cluster-replicas 1

kubectl exec -it redis-0 -n redis-cluster -- redis-cli -c
127.0.0.1:6379> cluster nodes

cluster info

cluster slots

kubectl get pod -n redis-cluster -o wide

kubectl get nodes -L topology.kubernetes.io/zone

kubectl get pod -n redis-cluster -o=custom-columns=NAME:.metadata.name,NODE:.spec.nodeName --no-headers | while read pod node; do
zone=$(kubectl get node "$node" -o=jsonpath='{.metadata.labels.topology\.kubernetes\.io/zone}')
echo "$pod -> $node -> $zone"
done

클러스터 구성이 성공한 것은 확인했다. 하지만 우리가 원하는 것은 Multi-AZ로 고가용성 클러스터!!!
위에는 마스터-슬레이브가 랜덤 AZ에 구성된다.
레디스 파드를 특정 노드에 고정해서 생성하고 마스터-슬레이브를 구성하도록 하자
kubectl delete statefulset redis -n redis-cluster
kubectl delete service redis -n redis-cluster
kubectl delete pvc --all -n redis-cluster
# pv 검색해서 redis-cluster 네임스페이스의 pv만 삭제
kubectl get pv
kubectl create namespace redis-cluster
redis-headless-svc.yaml)apiVersion: v1
kind: Service
metadata:
name: redis
namespace: redis-cluster
spec:
clusterIP: None # Headless!
selector:
app: redis
ports:
- port: 6379
kubectl apply -f redis-headless-svc.yaml
redis-statefulset.yaml)apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
namespace: redis-cluster
spec:
serviceName: "redis"
replicas: 6
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- ap-northeast-2a
- weight: 1
preference:
matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- ap-northeast-2b
- weight: 1
preference:
matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- ap-northeast-2c
containers:
- name: redis
image: redis:7.2
command:
- redis-server
- "--cluster-enabled"
- "yes"
- "--cluster-config-file"
- "nodes.conf"
- "--cluster-node-timeout"
- "5000"
- "--appendonly"
- "yes"
ports:
- containerPort: 6379
volumeMounts:
- name: data
mountPath: /data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: gp3
resources:
requests:
storage: 1Gi
kubectl apply -f redis-statefulset.yaml
kubectl get pod -o wide -n redis-cluster
kubectl get pvc -n redis-cluster
→ 각 Pod가 서로 다른 AZ의 노드에 분산되었는지 NODE 열로 확인하세요.
kubectl run redis-cluster-client --rm -it --restart=Never \
-n redis-cluster \
--image=bitnami/redis-cluster:7.0 \
-- bash
redis-server)에서는 실행할 수 없고,redis-cli의 특별한 기능이기 때문에 다음 조건이 필요합니다:
| 조건 | 이유 |
|---|---|
✅ redis-cli 명령어 존재 | Redis 서버 이미지에는 CLI가 없을 수 있음 |
✅ --cluster 옵션 사용 가능 | 일반 redis-cli는 단순 키 조회용, 클러스터 명령은 별도 옵션 필요 |
| ✅ 클러스터 외부에서 전체 노드에 접근 가능 | 노드 간 연결을 한 번에 조립해주는 역할 필요 |
Redis 서버에 직접 접속해서 시도해 보면:
kubectl exec -it redis-0 -n redis-cluster -- redis-cli --cluster create ...
→ 에러 발생 가능:
redis-cli: unknown option --cluster
이는 서버용 이미지에 redis-cli가 포함되지 않았거나, 알파인/경량화 버전으로 빌드됐기 때문입니다.
redis-cli --cluster create는 단순히 클러스터 명령을 던지는 게 아니라:
CLUSTER MEET 수행CLUSTER ADDSLOTS)CLUSTER REPLICATE)💡 즉, 모든 노드에 일괄적으로 작업을 수행해야 하기 때문에
→ 이를 실행할 수 있는 독립된 redis-cli가 필요한 것입니다.
| 질문 | 답변 |
|---|---|
| 왜 클러스터 생성용 클라이언트 Pod이 필요한가요? | redis-cli --cluster create는 일반 redis-server에 없고, 모든 노드를 연결하고 구성하기 위해 별도의 클러스터 전용 클라이언트가 필요하기 때문입니다. |
| 꼭 bitnami 이미지 써야 하나요? | 아니요, redis-cli만 있으면 다른 이미지도 가능하지만, bitnami/redis-cluster는 검증된 도구이므로 추천됩니다. |
redis-cli --cluster create \
redis-0.redis:6379 redis-1.redis:6379 redis-2.redis:6379 \
redis-3.redis:6379 redis-4.redis:6379 redis-5.redis:6379 \
--cluster-replicas 1
→ 중간에 yes 입력 요구 시 반드시 입력
redis-cli -c -h redis-0.redis
> cluster nodes
> cluster info

kubectl get nodes -o wide -L topology.kubernetes.io/zone

kubectl get pod -o wide -n redis-cluster

redis-0 (ap-northeast-2b) ↳ Slave: redis-4 (ap-northeast-2c)redis-1 (ap-northeast-2c) ↳ Slave: redis-5 (ap-northeast-2a)redis-2 (ap-northeast-2a) ↳ Slave: redis-3 (ap-northeast-2b)모든 파드가 분산 되어 있는 것을 확인할 수 있다.