记录一下近期实现的在k8s上搭建redis集群的过程
1、新建存储类
主要是为了和其它服务的存储类区分一下
redis-beta-storage
2、编写configMap
redis启动时从configMap中读取配置
bind:默认的127.0.0.1可能会导致其它ip地址无法远程访问,因此修改为0.0.0.0
append only: 开启持久化存储模式,为存储提供更好的保护
protected-mode:设置为no 允许其它机器访问
requirepass: 设置密码
3、创建headless-service
headless-service用于有状态应用的场景
-
headless service和普通service的区别
headless不分配clusterIp
headless service通过解析service的DNS,返回所有pod的地址和dns
普通service只能通过解析service的dns,返回service的clusterIp -
statefulSet和Deployment的区别
statefulSet下的pod有DNS地址,通过解析pod的dns可以返回pod的ip
deployment的pod是没有dns的 -
为什么要使用headless + statefulSet的组合
第一种:client想要自己决定使用哪个real server,通过dns可以得到real server的信息
第二种:headless-service关联的每个pod都有自己的dns域名,因此pod可以相互访问,像redis这样集群间需要协作、选举的就需要这样的pod
由于statefulset中的pod保持有不变的podName dnsName 因此拥有稳定的网络标识
kind: Service
apiVersion: v1
metadata:
name: redis-cluster-service
namespace: tool-beta
labels:
app: redis-cluster
annotations:
kubesphere.io/creator: admin
spec:
ports:
- name: redis-port
protocol: TCP
port: 6379
targetPort: 6379
selector:
app: redis-cluster
clusterIP: None
clusterIPs:
- None
type: ClusterIP
sessionAffinity: None
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
internalTrafficPolicy: Cluster
4、部署redis statefulset 共6个
kind: StatefulSet
apiVersion: apps/v1
metadata:
name: redis-cluster
namespace: tool-beta
labels:
app: redis-cluster
annotations:
kubesphere.io/creator: admin
spec:
replicas: 6
selector:
matchLabels:
app: redis-cluster
template:
metadata:
creationTimestamp: null
labels:
app: redis-cluster
annotations:
kubesphere.io/creator: admin
kubesphere.io/restartedAt: '2024-03-26T06:49:20.735Z'
spec:
volumes:
- name: redis-conf
configMap:
name: redis-cluster-config-beta
defaultMode: 420
containers:
- name: redis
image: 'redis:5.0.7'
command:
- sh
- '-c'
- redis-server /usr/local/redis/redis.conf
args:
- '--protected-mode'
- 'no'
ports:
- name: redis
containerPort: 6379
protocol: TCP
- name: cluster
containerPort: 16379
protocol: TCP
resources:
limits:
cpu: '2'
memory: 4000Mi
requests:
cpu: 100m
memory: 500Mi
volumeMounts:
- name: redis-conf
mountPath: /usr/local/redis/redis.conf
subPath: redis.conf
- name: redis-data
mountPath: /var/lib/redis
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: IfNotPresent
restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
nodeSelector:
env_type: beta
group_name: tool
securityContext: {}
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
topologyKey: kubernetes.io/hostname
schedulerName: default-scheduler
volumeClaimTemplates:
- kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: redis-data
creationTimestamp: null
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
storageClassName: redis-beta-storage
volumeMode: Filesystem
status:
phase: Pending
serviceName: redis-cluster-service
podManagementPolicy: OrderedReady
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 0
revisionHistoryLimit: 10
全部启动完成后,查看pod的状态
命令 kubectl get pods -n 【namespace】
查看pvc的情况
kubectl get pvc -n 【namespace】
查看pod的dns域名
kubectl exec redis-cluster-0 -n tool-beta – hostname -f
每个pod都会得到集群内的一个dns域名,格式为
$(podname).$(service name).$(namespace).svc.cluster.local
也可以通过临时启动一个pod来验证
kubectl run --rm -i --tty busybox --image=busybox:1.28 /bin/sh
$ nslookup redis-app-0.redis-service
证明pod间可以解析该dns域名
若Redis Pod迁移或是重启(我们可以手动删除掉一个Redis Pod来测试),IP是会改变的,但是Pod的域名、SRV records、A record都不会改变。
5、初始化redis集群
使用redis-cli来进行集群的初始化
首先查看各pod的ip
进入到其中一个容器中
使用命令创建集群
redis-cli --cluster create 192.168.5.127:6379 192.168.135.199:6379 192.168.5.112:6379 -a foobared
得到的信息类似于
这些master节点的id用来添加slave节点
redis-cli --cluster add-node 10.168.235.225:6379 10.168.235.196:6379 --cluster-slave --cluster-master-id bcae187137a9b30d7dab8fe0d8ed4a46c6e39638 -a foobared
依次给所有master节点添加好子节点后,查看集群情况
进入redis-cli,输入命令cluster info
cluster nodes
写入数据、读取数据
注:集群模式需要redis-cli -c进入
可以看到存储和读取时切换至其它节点
最后重启某个pod,验证是否还能组成集群
可以看到,即使ip发生了变化,依然组成了集群
这是因为每个node的id是不变了,无论pod如何重启,只要nodeId还在持久卷里存储着,它的网络标识就没有变化