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

相关推荐
恼书:-(空寄4 小时前
Redisson 原理与最佳实践
redis·分布式锁·redisson
gQ85v10Db7 小时前
Redis分布式锁进阶第十七篇:微服务分布式锁全局治理 + 跨团队统一规范落地 + 全链路稳定性提升方案
redis·分布式·微服务
Javatutouhouduan8 小时前
Java小白如何快速玩转Redis?
java·数据库·redis·分布式锁·java面试·后端开发·java程序员
胡小禾10 小时前
K8S常识-如何指定只更新一个deployment中的某一个实例
云原生·容器·kubernetes
倒霉蛋小马11 小时前
【Redis】什么是缓存击穿?
数据库·redis·缓存
傻瓜搬砖人14 小时前
SpringBoot整合Junit-Redis-打包
spring boot·redis·junit
014-code14 小时前
布隆过滤器:判断“可能存在“和“一定不存在“
java·redis
gQ85v10Db14 小时前
Redis分布式锁进阶第十八篇:本地缓存+分布式锁双锁架构 + 高并发削峰兜底 + 极致性能无损优化实战
redis·分布式·缓存
gQ85v10Db14 小时前
Redis分布式锁进阶第十四篇:全系列终局架构复盘 + 锁体系统一规范 + 线上全年零事故收官方案
redis·分布式·架构
KmSH8umpK15 小时前
Redis分布式锁进阶第十二篇
数据库·redis·分布式