k8s下搭建redis集群

记录一下近期实现的在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 因此拥有稳定的网络标识

java 复制代码
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个

java 复制代码
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来验证

java 复制代码
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

进入到其中一个容器中

使用命令创建集群

java 复制代码
redis-cli --cluster create 192.168.5.127:6379 192.168.135.199:6379 192.168.5.112:6379 -a foobared

得到的信息类似于

这些master节点的id用来添加slave节点

java 复制代码
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还在持久卷里存储着,它的网络标识就没有变化

相关推荐
张先shen2 小时前
亿级流量下的缓存架构设计:Redis+Caffeine多级缓存实战
数据库·redis·缓存
Andy杨2 小时前
20250712-1-Kubernetes 监控与日志管理-K8s日志管理与维护_笔记
笔记·容器·kubernetes
sniper_fandc5 小时前
Redis数据类型之list
数据库·redis·list
KKKingWei5 小时前
Kubernetes Dashboard UI 部署安装
云原生·容器·kubernetes
笑衬人心。7 小时前
Redis 基本操作笔记
数据库·redis·笔记
埃泽漫笔7 小时前
Redis事件机制
redis·event
埃泽漫笔8 小时前
Redis概念和基础
redis
vortex59 小时前
Redis渗透思路总结
数据库·redis·缓存
都叫我大帅哥12 小时前
Redis Set数据类型:从青铜到王者的全方位指南
redis
都叫我大帅哥13 小时前
Redis生产环境完全指南:Java最佳实践与经典问题破解
redis