Appearance
Redis on Kubernetes 部署與維運
在 Kubernetes 與 AKS 上部署 Redis Master-Replica 架構,涵蓋 Bitnami Helm Chart 安裝、官方 Image StatefulSet 部署、LoadBalancer 暴露、備份還原與 Standalone 快速啟動。
概述
Redis 在 Kubernetes 上最常見的做法是透過 Bitnami Helm Chart 部署 Master-Replica 架構,Master 負責讀寫,Replicas 提供唯讀分流。Helm Chart 會自動建立 PVC,但在升級或重建時需要注意:PVC 不會被自動刪除,需要手動管理,這個特性在需要保留資料的升級場景中反而是一個優勢(可利用既有 PVC 進行資料繼承)。
對外暴露 Redis 服務的方式隨著部署環境演進:本地 K8s 使用 NodePort,AKS 環境則建立獨立的 Azure Internal LoadBalancer Service,讓 Master 與 Replicas 各自擁有固定的內部 IP 端點。
核心內容
Bitnami Helm Chart 關鍵參數
| 參數 | 說明 |
|---|---|
auth.password | Redis 密碼 |
master.disableCommands | 停用危險指令(如 FLUSHALL),留空 '' 表示不停用任何指令 |
replica.disableCommands | Replicas 同步停用的危險指令 |
global.storageClass | StorageClass(本地 K8s 用 nfs-client,AKS 用 managed-csi-premium) |
master.persistence.size | Master PVC 大小 |
replica.persistence.size | Replicas PVC 大小 |
replica.replicaCount | Replica 數量(建議至少 1) |
commonConfiguration | Redis 設定(如 databases 128) |
master.persistence.existingClaim | 指定既有 PVC(用於資料繼承升級) |
重要:
master.disableCommands與replica.disableCommands必須保持一致,否則會導致資料不同步。
備份與還原策略
Method 1:匯出 dump.rdb 再還原
適用於跨版本升級(版本差異太大無法 upgrade 時):
- 在 redis-cli 中執行
save產生/data/dump.rdb kubectl cp將檔案複製到本地(加--retries=5提高成功率)- 用
md5sum確認複製完整性 - 建立臨時 Pod 掛載目標 PVC,將 dump.rdb 複製進去
- 重新安裝 Redis 並掛載該 PVC
Method 2:砍掉重裝,直接利用原有 PVC
更簡潔的做法,透過 master.persistence.existingClaim 參數直接繼承既有 PVC 的資料,不需要手動搬移檔案。注意:Replica PVC 若不繼承,需先手動刪除,讓 Helm 重新建立空的 Replica PVC。
叢集內部連線
| 用途 | DNS | Port |
|---|---|---|
| 讀寫(Master) | redis-master.redis-system.svc.cluster.local | 6379 |
| 唯讀(Replicas) | redis-replicas.redis-system.svc.cluster.local | 6379 |
官方 Image StatefulSet 部署(AKS,2026/02)
當需要從 Bitnami Image 遷移至官方 Redis Image,或需要更精細控制 StatefulSet 配置時,可改用官方 redis Image 直接撰寫 StatefulSet YAML,不依賴 Helm Chart。
架構重點:
- Master 使用預先建立的 PVC(
redis-master-0),保留既有資料 - Replica 使用 VolumeClaimTemplate 自動建立新 PVC
- Master 與 Replica 的 Internal LoadBalancer 共用同一個 IP(
10.30.196.79),透過不同 port 區分(Master: 6379,Replica: 6380) - initContainer 負責修正 UID:從 Bitnami 的
1001→ 官方 Image 的999 - Redis 設定(密碼、
databases、appendonly、禁用FLUSHALL)透過 ConfigMap 注入
Standalone 輕量部署
對於不需要 Master-Replica 架構的場景(如單一應用的快取需求),可直接以 redis:latest 映像搭配簡單的 Deployment + Service 快速建立。資料持久化透過 PVC 實現,密碼以啟動參數 --requirepass 傳入。
關鍵要點
- PVC 在
helm uninstall後不會自動刪除,需手動清理或利用此特性繼承資料 - AKS 環境最新作法(2023/08):Master 與 Replicas 各自建立獨立的 Internal LoadBalancer
- 新版 Helm Chart 無法透過
--set直接設定 NodePort,需自行建立 Service YAML - 指定
resources.requests.memory避免 OOM Kill(預設值可能過低) commonConfiguration='databases 128'(或 256)可擴充資料庫數量上限- 從 Bitnami 遷移至官方 Image 時,需 initContainer 修正資料目錄 UID(1001 → 999)
FLUSHALL可在 ConfigMap 的rename-command設為空字串予以禁用(等同關閉)
實際應用
Redis 在 AKS 上透過 Internal LoadBalancer 提供固定 IP 端點(Master: 10.30.196.79,Replicas: 10.30.196.80),應用程式依據讀寫需求連接不同端點實現讀寫分離。Redis Exporter 部署後,Prometheus 透過叢集內部 DNS 抓取指標,詳見 Redis Exporter 部署。
部署設定參考
以下為實際部署時使用的完整設定,供日後查詢與複製使用。
環境參數
| 項目 | 值 |
|---|---|
| Namespace | redis-system |
| 密碼 | Bed200@2022 |
| databases | 128(K8s)/ 256(AKS 升級後) |
| Master PVC | 12Gi(AKS) |
| Replica PVC | 12Gi(AKS) |
| StorageClass | nfs-client(K8s)/ managed-csi-premium(AKS) |
| Chart 版本 | 17.10.3(2023-05 安裝) |
| App 版本 | Redis 7.0.11 |
安裝指令
K8s(NodePort,2023/05)
bash
helm install --namespace redis-system redis \
--set auth.password=Bed200@2022,\
master.disableCommands='',\
replica.disableCommands='',\
global.storageClass="nfs-client",\
master.service.type=NodePort,\
master.service.nodePorts.redis=30100,\
replica.service.type=NodePort,\
replica.service.nodePorts.redis=30101,\
commonConfiguration='databases 128' \
bitnami/redisAKS(2023/09)
bash
helm install redis bitnami/redis --namespace redis-system \
--set auth.password=Bed200@2022,\
master.disableCommands='',\
replica.disableCommands='',\
global.storageClass="managed-csi-premium",\
master.persistence.size=12Gi,\
replica.persistence.size=12Gi,\
replica.replicaCount=1,\
replica.resources.requests.memory=2Gi,\
master.resources.requests.memory=2Gi,\
commonConfiguration='databases 128'AKS Upgrade(2024/04)
bash
helm upgrade redis bitnami/redis \
--namespace redis-system \
--reuse-values \
--set master.resources.requests.memory=16Gi \
--set replica.resources.requests.memory=8Gi利用既有 PVC 重裝(AKS 2025/02)
bash
helm install redis bitnami/redis --namespace redis-system \
--set auth.password=Bed200@2022,\
master.disableCommands={'FLUSHALL'},\
replica.disableCommands={'FLUSHALL'},\
master.persistence.existingClaim="redis-data-redis-master-0",\
replica.persistence.existingClaim="redis-data-redis-replicas-0",\
replica.replicaCount=1,\
replica.resources.requests.memory=8Gi,\
master.resources.requests.memory=16Gi,\
commonConfiguration='databases 256'利用既有 PVC 重裝(K8s 2025/09)
bash
helm install --namespace redis-system redis \
--set auth.password=Bed200@2022,\
master.disableCommands={'FLUSHALL'},\
replica.disableCommands={'FLUSHALL'},\
global.storageClass="nfs-client",\
master.persistence.existingClaim="redis-data-redis-k8s-master-0",\
replica.replicaCount=1,\
replica.resources.requests.memory=8Gi,\
master.resources.requests.memory=16Gi,\
commonConfiguration='databases 256' \
bitnami/redis自訂 LoadBalancer Service(AKS)
yaml
apiVersion: v1
kind: Service
metadata:
name: redis-master-loadbalancer
namespace: redis-system
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "true"
service.beta.kubernetes.io/azure-load-balancer-ipv4: 10.30.196.79
spec:
type: LoadBalancer
selector:
app.kubernetes.io/component: master
app.kubernetes.io/instance: redis
app.kubernetes.io/name: redis
ports:
- protocol: TCP
port: 6379
targetPort: 6379
---
apiVersion: v1
kind: Service
metadata:
name: redis-replicas-loadbalancer
namespace: redis-system
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "true"
service.beta.kubernetes.io/azure-load-balancer-ipv4: 10.30.196.80
spec:
type: LoadBalancer
selector:
app.kubernetes.io/component: replica
app.kubernetes.io/instance: redis
app.kubernetes.io/name: redis
ports:
- protocol: TCP
port: 6379
targetPort: 6379| 角色 | Internal LB IP | Port |
|---|---|---|
| Master | 10.30.196.79 | 6379 |
| Replicas | 10.30.196.80 | 6379 |
操作指令
bash
# 取得密碼
export REDIS_PASSWORD=$(kubectl get secret --namespace redis-system redis \
-o jsonpath="{.data.redis-password}" | base64 -d)
# 啟動 Redis client Pod
kubectl run --namespace redis-system redis-client \
--restart='Always' \
--env REDIS_PASSWORD=$REDIS_PASSWORD \
--image docker.io/bitnami/redis:7.0.12-debian-11-r2 \
--command -- sleep infinity
# 進入 Pod
kubectl exec --tty -i redis-client --namespace redis-system -- bash
# 連線 Master
REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli -h redis-master
# 連線 Replicas
REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli -h redis-replicas官方 Image StatefulSet 部署(AKS 2026/02)
環境參數
| 項目 | 值 |
|---|---|
| Namespace | redis-system |
| Image | redis:8.6.0-trixie |
| 密碼 | Bed200@2022 |
| Master PVC | redis-master-0(預先建立) |
| Replica PVC | 50Gi(VolumeClaimTemplate,managed-csi-premium) |
| Master Memory Request | 16Gi |
| Replica Memory Request | 8Gi |
| Master LB IP:Port | 10.30.196.79:6379 |
| Replica LB IP:Port | 10.30.196.79:6380 |
完整 YAML 清單
yaml
# 1. ConfigMap — 共用 Redis 設定
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-config
namespace: redis-system
data:
redis-common.conf: |
databases 256
appendonly yes
protected-mode no
rename-command FLUSHALL ""
requirepass Bed200@2022
masterauth Bed200@2022
---
# 2. Headless Service — Master 識別用
apiVersion: v1
kind: Service
metadata:
name: redis-master-svc
namespace: redis-system
spec:
clusterIP: None
ports:
- port: 6379
targetPort: 6379
selector:
app: redis
role: master
---
# 3. ClusterIP Service — Replica 讀取
apiVersion: v1
kind: Service
metadata:
name: redis-replica-svc
namespace: redis-system
spec:
ports:
- port: 6379
targetPort: 6379
selector:
app: redis
role: replica
---
# 4. StatefulSet — Redis Master
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: aks-redis-master
namespace: redis-system
spec:
serviceName: "redis-master-svc"
replicas: 1
selector:
matchLabels:
app: redis
role: master
template:
metadata:
labels:
app: redis
role: master
spec:
initContainers:
- name: fix-bitnami-migration
image: busybox
command:
- sh
- -c
- |
chown -R 999:999 /data
volumeMounts:
- name: redis-data
mountPath: /data
containers:
- name: redis
image: redis:8.6.0-trixie
command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
env:
- name: REDIS_PASSWORD
value: "Bed200@2022"
resources:
requests:
memory: 16Gi
cpu: 500m
ports:
- containerPort: 6379
volumeMounts:
- name: redis-data
mountPath: /data
- name: config
mountPath: /usr/local/etc/redis/redis.conf
subPath: redis-common.conf
volumes:
- name: config
configMap:
name: redis-config
- name: redis-data
persistentVolumeClaim:
claimName: redis-master-0
---
# 5. StatefulSet — Redis Replica
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: aks-redis-replica
namespace: redis-system
spec:
serviceName: "redis-replica-svc"
replicas: 1
selector:
matchLabels:
app: redis
role: replica
template:
metadata:
labels:
app: redis
role: replica
spec:
containers:
- name: redis
image: redis:8.6.0-trixie
command: ["redis-server", "/usr/local/etc/redis/redis.conf", "--replicaof", "redis-master-svc", "6379"]
resources:
requests:
memory: 8Gi
cpu: 500m
ports:
- containerPort: 6379
volumeMounts:
- name: redis-data
mountPath: /data
- name: config
mountPath: /usr/local/etc/redis/redis.conf
subPath: redis-common.conf
volumes:
- name: config
configMap:
name: redis-config
volumeClaimTemplates:
- metadata:
name: redis-data
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "managed-csi-premium"
resources:
requests:
storage: 50Gi
---
# 6. Internal LoadBalancer — Master(Port 6379)
apiVersion: v1
kind: Service
metadata:
name: aks-redis-master-loadbalancer
namespace: redis-system
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "true"
service.beta.kubernetes.io/azure-load-balancer-ipv4: 10.30.196.79
spec:
type: LoadBalancer
selector:
app: redis
role: master
ports:
- protocol: TCP
port: 6379
targetPort: 6379
---
# 7. Internal LoadBalancer — Replica(Port 6380)
apiVersion: v1
kind: Service
metadata:
name: aks-redis-replica-loadbalancer
namespace: redis-system
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "true"
service.beta.kubernetes.io/azure-load-balancer-ipv4: 10.30.196.79
spec:
type: LoadBalancer
selector:
app: redis
role: replica
ports:
- protocol: TCP
port: 6380
targetPort: 6379Standalone 快速啟動(Server 版本,2025/06)
yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wes-redis-pvc
namespace: ingress-basic
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: managed-csi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: wes-redis
namespace: ingress-basic
spec:
replicas: 1
selector:
matchLabels:
app: wes-redis
template:
metadata:
labels:
app: wes-redis
spec:
securityContext:
fsGroup: 999
containers:
- name: redis
image: redis
ports:
- containerPort: 6379
args:
- "--requirepass"
- "wes@CuIce"
volumeMounts:
- name: redis-data
mountPath: /data
volumes:
- name: redis-data
persistentVolumeClaim:
claimName: wes-redis-pvc
---
apiVersion: v1
kind: Service
metadata:
name: wes-redis
namespace: ingress-basic
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "true"
service.beta.kubernetes.io/azure-load-balancer-ipv4: 10.30.196.79
spec:
ports:
- port: 3379
targetPort: 6379
selector:
app: wes-redis
type: LoadBalancer| 項目 | 值 |
|---|---|
| Namespace | ingress-basic |
| Password | wes@CuIce |
| Internal LB IP | 10.30.196.79 |
| 外部 Port | 3379 |
| 容器 Port | 6379 |
相關概念
- Redis Exporter 部署 — 將 Redis 指標匯出至 Prometheus
- Prometheus on Kubernetes 部署 — 收集 Redis 指標的 Prometheus 伺服器
- RabbitMQ on Kubernetes 部署 — 類似的 Message Broker 在 K8s 上的部署模式
- MariaDB Helm 部署(Kubernetes) — Bitnami Helm Chart 部署另一個有狀態服務的參考