headless, statefulset service를 만들어야함.
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-0~redis-5 파드가 Running 되는지 확인kubectl get pods -n redis-cluster
redis pod가 하나 밖에 없음.

원인을 보니 redis-0이 생성되고 Pending → Bound으로 되어야만 다음 redis-1이 생성된다.
pending인 파드의 상세를 확인해봤다.
kubectl describe pod redis-0 -n redis-cluster
로그를 내리다 보니 Event 부분에 에러를 확인할 수 있었다
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 3m59s default-scheduler 0/3 nodes are available: pod has unbound immediate PersistentVolumeClaims. preemption: 0/3 nodes are available: 3 Preemption is not helpful for scheduling.
pod has unbound immediate PersistentVolumeClaims 라는 로그를 확인할 수 있었다.
혹시 PV를 생성해주지 않아서 문제가 발생하는지 확인해봤다.
스토리지 클래스가 존재하지 않았고, 이로 인해 Bound를 못하는 문제였다.

문제요약
Pending 상태에서 계속 멈춤스토리지 클래스를 생성해주기 위해 yaml 작성
sudo vi local-storageclass.yaml
# local-storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: manual
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
하지만 여전히 문제가 해결되지 않았다.
로컬 스토리지가 계속 프로비저닝 되지 않고 있다고 생각해 다른 방법을 찾았다.
local-path-provisioner 설치kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml
local-path-storage 네임스페이스에 스토리지 프로비저너 Pod를 설치해줌
kubectl get pods -A | grep local-path
# local-path-provisioner-xxxxx 1/1 Running
local-path StorageClass를 기본값(default)으로 설정kubectl patch storageclass local-path -p \
'{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
이 설정이 있어야 StatefulSet이 자동으로 PVC를 만족시키고 PV를 생성할 수 있다.
kubectl delete statefulset redis -n redis-cluster
kubectl delete pvc --all -n redis-cluster
YAML 내부에서 아래와 같이 반드시 설정돼야 함:
storageClassName: local-path
그 후 적용:
kubectl apply -f redis-statefulset.yaml
kubectl get pods -n redis-cluster
# redis-0 ~ redis-5: 모두 Running
kubectl get pvc -n redis-cluster
# 모두 Bound
kubectl get pv
# PV도 자동 생성됨


이제 모든 redis 파드가 bound 되었으니 클러스터를 구성해주자.
아래 명령어는 자동으로 마스터-슬레이브 쌍으로 클러스터를 구성해주는 명령어이다.
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

하지만 지금 레디스 클러스터는 Multi-AZ 레벨로 고가용성이 구축되어 있는 것이 아니다. 추후 EKS에서 구축하도록 하자.