1.redis主從高可用集群結構
2.k8s部署有狀態的服務選擇
對於K8S集群有狀態的服務,我們可以選擇deployment和statefulset
- statefulset
- service&deployment
對於有狀態的服務例如:redis和mysql,我們使用statefulset為首選
3.設計原理
statefulset 的設計原理:
-
拓撲狀態
應用的多個實例之間不是完全對等的關系,這個應用實例的啟動必須按照某些順序啟動,比如應用的主節點 A 要先於從節點 B 啟動。而如果你把 A 和 B 兩個Pod刪除掉,他們再次被創建出來是也必須嚴格按照這個順序才行,並且,新創建出來的Pod,必須和原來的Pod的網絡標識一樣,這樣原先的訪問者才能使用同樣的方法,訪問到這個新的Pod
-
存儲狀態
應用的多個實例分別綁定了不同的存儲數據.對於這些應用實例來說,Pod A第一次讀取到的數據,和隔了十分鍾之后再次讀取到的數據,應該是同一份,哪怕在此期間Pod A被重新創建過.一個數據庫應用的多個存儲實例
無論是Master 還是 slave都作為statefulset的一個副本,通過pv/pvc進行持久化,對外暴露一個service 接受客戶端請求
4.部署步驟
4.1 創建configmap用於存放redis的配置文件
- 創建一個redis.conf文件
appendonly yes #開啟Redis的AOF持久化
cluster-enabled yes #集群模式打開
cluster-config-file /var/lib/redis/nodes.conf #下面說明
cluster-node-timeout 5000 #節點超時時間
dir /var/lib/redis #AOF持久化文件存在的位置
port 6379 #開啟的端口
- 創建名稱為redis.conf的ConfigMap
kubectl create configmap redis-conf --from-file=redis.conf
#查看configmap
kubectl get cm
4.2 創建headless service
Headless service是StatefulSet實現穩定網絡標識的基礎,我們需要提前創建。准備文件headless-service.yml如下
apiVersion: v1
kind: Service
metadata:
name: redis-service
labels:
app: redis
spec:
ports:
- name: redis-port
port: 6379
clusterIP: None
selector:
app: redis
appCluster: redis-cluster
創建和查看:
kubectl create -f headless-service.yml
kubectl get svc redis-service
4.3 創建redis集群節點
# cat redis.yaml
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: redis-app
spec:
serviceName: "redis-service"
replicas: 6
template:
metadata:
labels:
app: redis
appCluster: redis-cluster
spec:
terminationGracePeriodSeconds: 20
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- redis
topologyKey: kubernetes.io/hostname
containers:
- name: redis
image: "redis"
command:
- "redis-server" #redis啟動命令
args:
- "/etc/redis/redis.conf" #redis-server后面跟的參數,換行代表空格
- "--protected-mode" #允許外網訪問
- "no"
# command: redis-server /etc/redis/redis.conf --protected-mode no
resources: #資源
requests: #請求的資源
cpu: "100m" #m代表千分之,相當於0.1 個cpu資源
memory: "100Mi" #內存100m大小
ports:
- name: redis
containerPort: 6379
protocol: "TCP"
- name: cluster
containerPort: 16379
protocol: "TCP"
volumeMounts:
- name: "redis-conf" #掛載configmap生成的文件
mountPath: "/etc/redis" #掛載到哪個路徑下
- name: "redis-data" #掛載持久卷的路徑
mountPath: "/var/lib/redis"
volumes:
- name: "redis-conf" #引用configMap卷
configMap:
name: "redis-conf"
items:
- key: "redis.conf" #創建configMap指定的名稱
path: "redis.conf" #里面的那個文件--from-file參數后面的文件
volumeClaimTemplates: #進行pvc持久卷聲明,
- metadata:
name: redis-data
spec:
accessModes: ["ReadWriteMany"]
storageClassName: "cephfs"
resources:
requests:
storage: 10G