Kubernetes基于Helm安装部署高可用的Redis

Stella981
• 阅读 1127

Kubernetes基于Helm安装部署高可用的Redis

1、Redis简介

Redis是一个开放源代码(BSD许可证)的代理,其在内存中存储数据,可以代理数据库、缓存和消息。它支持字符串、散列、列表、集合和位图等数据结构。Redis 是一个高性能的key-value数据库, 它在很大程度改进了memcached这类key/value存储的不足。Redis提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby和Erlang等语言的客户端。

Redis支持master/slave结构,数据可以从master向任意数量的slave上进行同步。Redis 与其它 key – value 缓存产品相比,具有以下三个方面特点:

  • 支持内存的持久化:可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用;

  • 支持多种数据结构:Redis不仅仅只是支持key-value类型的数据,还能够支持字符串、散列和列表等数据结构;

  • 支持主从结构:Redis支持主从结构,保证系统的高可用。

2、基于Sentinel模式的高可用方案

本文中的Redis高可用方案采用Sentinel(哨兵)模式,在集群出现故障的时候自动进行故障转移,保证集群的可用性。Redis Sentinel 为Redis提供了高可用性,这意味着通过使用Sentinel 可以创建一个Redis部署,在没有人为干预的情况下能够抵抗某些类型的失败。Sentiel的完整功能列表如下所示:

  • 监控:不间断的检查master/slave实例否是安装预期正常工作;

  • 通知:当 Redis 实例出现错误的时候,会使用程序(通过 API 接口)通知管理员;

  • 自动故障转移:在master发生故障时,哨兵会开启故障转移处理,将一台slave提升为master,其它的slave被重新配置使用新的master,当应用程序连接时使用新的地址配置;

  • 配置信息:Sentinel作为服务发现的权威来源,客户端连接到Sentinel去获取当前Redis master的地址,如果发生故障转移,Sentinel将会汇报新的服务器地址。

Sentinel本身是一套分布式系统,它被设计成能够进行多个进程间协同工作的模式,这样的好处如下:

  • 多个Sentinel一致明确给定的主机不再可用时,才会执行故障检测,这能够有效错报的概率。

  • 即使只有一个Sentinel在正常运行,Redis也是可用的,从而保证系统具有较高的健壮性。

Sentinel,Redis实例(master和slave)和连接到Sentinel和Redis的客户端的数量,也是一个具有特定属性的更大的分布式系统。在本文中,定制的Redis服务器镜像会确定执行它的Pod是redis的Sentinel、master还是slave,并启动适当的服务。这个Helm chart指示Sentinel状态与环境变量。如果没有设置,新启动的Pod将查询Kunbernetes的活动master。如果不存在,则它使用一种确定的方法来检测它是否应该作为master启动,然后将“master”或“slave”写入到称为redis-role的标签中。

redis-role=master Pod是集群启动的关键。在它们完成启动,sentinel将处于等待整体。所有其他的Pod等待sentinel识别主节点。运行Pod并设置标签podIP和runID。runID是每个redis服务器生成的唯一run_ID值的前几个字符。

在正常操作中,应该只有一个redis=master Pod。如果失败,Sentinel将提名一个新的master,并适当地改变所有的redis-role的值。

通过执行如下命令可以查看Pod所承担的角色:

  1. $ kubectl get pods -L redis-role -namespace=kube-public

Kubernetes基于Helm安装部署高可用的Redis

3、安装部署

3.1 环境要求

已有Kubernetes 1.6+环境;

已部署helm客户端和tiller服务端(请参考:https://docs.helm.sh/using\_helm/#installing-helm):

在Kubernetes中创建了具备足够权限访问权限的service account;

并通过此service account在Kubernetes部署了tiller服务端(请参考:https://docs.helm.sh/using\_helm/#role-based-access-control)。

在Kubernetes中提供了容量大于10g的持久化存储卷。

3.2 Helm char配置

下表列示了Redis chart的配置参数和默认值:

Kubernetes基于Helm安装部署高可用的Redis

在helm install中使用–set key=value 格式设置上述的参数值,例如:

  1. $ helm install \

  2. --set redis_image=quay.io/smile/redis:4.0.6r2 \

  3. stable/redis-ha

3.3 持久化

redis将持久化数据保存在容器的/redis-master-datal路径下,安装时会创建一个PersistentVolumeClaim ,并将其挂接到容器内的目录。因此,需要在Kubernetes中提前提供一个PersistentVolume。

3.4 通过Chart安装Redis

通过执行如下的命令,在Kubernetes中部署Redis:

  1. $ helm install stable/redis-ha --name=redis-ha --namespace=kube-public

通过上述命令,将以默认的配置在Kubernetes中部署Redis。默认情况下,chart会安装部署3个Sentinel Pod,1个master Pod和2个slave Pod。

Kubernetes基于Helm安装部署高可用的Redis

4、Helm Chart分析

MySQL Chart的目录如下,其中,values为默认的配置文件,用于为部署提供默认值。templates目录下的YAML文件是在Kubernetes进行部署的配置文件。

  1. redis-ha

  2. --templates # 模板目录,当与values.yaml组合时,将生成有效的Kubernetes清单文件。

  3. ----NOTES.txt

  4. ----_helpers.tpl

  5. ----redis-auth-secret.yaml

  6. ----redis-master-service.yalm

  7. ----redis-role.yaml

  8. ----redis-rolebinding.yaml

  9. ----redis-sentinel-deployment.yaml

  10. ----redis-sentinel-service.yaml

  11. ----redis-server-deployment.yaml

  12. ----redis-serviceaccount.yaml

  13. ----redis-slave-service.yaml

  14. --Chart.yaml # 描述chart的信息

  15. --README.md # 可读的chart介绍文件

  16. --values.yaml # 默认配置文件

4.1 values.yaml 在values.yaml配置文件中设置了通过helm进行部署时的默认值。在values.yaml中,首先,定义了主Pod和哨兵Pod的请求和限制资源的要求;接着,通过nodeSelector和容忍度为Pod定义调度到哪个Node上;以及,指定容器所使用的镜像和其它的相关信息。

  1. ## Configure resource requests and limits

  2. ## ref: http://kubernetes.io/docs/user-guide/compute-resources/

  3. ##

  4. resources:

  5. server:

  6. requests:

  7. memory: 200Mi

  8. cpu: 100m

  9. limits:

  10. memory: 700Mi

  11. sentinel:

  12. requests:

  13. memory: 200Mi

  14. cpu: 100m

  15. limits:

  16. memory: 200Mi

  17. ## Node labels and tolerations for pod assignment

  18. ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector

  19. ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#taints-and-tolerations-beta-feature

  20. nodeSelector: {}

  21. tolerations: []

  22. ## Redis image version

  23. redis_image: quay.io/smile/redis:4.0.8r0

  24. ## replicas number for each component

  25. replicas:

  26. servers: 3

  27. sentinels: 3

  28. servers:

  29. serviceType: ClusterIP # [ClusterIP|LoadBalancer]

  30. annotations: {}

  31. rbac:

  32. # Specifies whether RBAC resources should be created

  33. create: true

  34. serviceAccount:

  35. # Specifies whether a ServiceAccount should be created

  36. create: true

  37. # The name of the ServiceAccount to use.

  38. # If not set and create is true, a name is generated using the fullname template

  39. name:

  40. ## Configures redis with AUTH (requirepass & masterauth conf params)

  41. auth: false

  42. ## Redis password

  43. ## Defaults to a random 10-character alphanumeric string if not set and auth is true

  44. ## ref: https://github.com/kubernetes/charts/blob/master/stable/redis-ha/templates/redis-auth-secret.yaml

  45. ##

  46. ## redisPassword:

4.2 redis-server-deployment.yaml

此YAML配置文件用于定义Redis master/slave的部署。

  1. apiVersion: extensions/v1beta1

  2. kind: Deployment

  3. metadata:

  4. # Pay attention to the redis-role label at runtime. The self-determination logic in the image sets

  5. # this value accordingly.

  6. name: {{ template "redis-ha.fullname" . }}-server

  7. labels:

  8. name: {{ template "redis-ha.fullname" . }}-server

  9. redis-node: "true"

  10. {{ include "labels.standard" . | indent 4 }}

  11. spec:

  12. replicas: {{ .Values.replicas.servers }}

  13. template:

  14. metadata:

  15. labels:

  16. app: {{ template "redis-ha.name" . }}

  17. release: {{ .Release.Name }}

  18. component: server

  19. name: {{ template "redis-ha.fullname" . }}-server

  20. redis-node: "true"

  21. spec:

  22. serviceAccountName: {{ template "redis-ha.serviceAccountName" . }}

  23. {{- if .Values.nodeSelector }}

  24. nodeSelector:

  25. {{ toYaml .Values.nodeSelector | indent 8 }}

  26. {{- end }}

  27. {{- if .Values.tolerations }}

  28. tolerations:

  29. {{ toYaml .Values.tolerations | indent 8 }}

  30. {{- end }}

  31. containers:

  32. - name: redis

  33. image: {{ .Values.redis_image }}

  34. resources:

  35. {{ toYaml .Values.resources.server | indent 10 }}

  36. env:

  37. - name: REDIS_SENTINEL_SERVICE_HOST

  38. value: "redis-sentinel"

  39. - name: REDIS_CHART_PREFIX

  40. value: {{ template "redis-ha.fullname" . }}-

  41. {{- if .Values.auth }}

  42. - name: REDIS_PASS

  43. valueFrom:

  44. secretKeyRef:

  45. name: {{ template "redis-ha.fullname" . }}

  46. key: auth

  47. {{- end }}

  48. ports:

  49. - containerPort: 6379

  50. volumeMounts:

  51. - mountPath: /redis-master-data

  52. name: data

  53. volumes:

  54. - name: data

4.3 redis-master-service.yaml

此YAML配置文件为定义了redis master的服务,此服务暴露6379端口,以供在集群中使用。

  1. apiVersion: v1

  2. kind: Service

  3. metadata:

  4. name: {{ template "redis-ha.fullname" . }}-master-svc

  5. labels:

  6. {{ include "labels.standard" . | indent 4 }}

  7. annotations:

  8. {{ toYaml .Values.servers.annotations | indent 4 }}

  9. spec:

  10. ports:

  11. - port: 6379

  12. protocol: TCP

  13. targetPort: 6379

  14. selector:

  15. app: {{ template "redis-ha.name" . }}

  16. release: "{{ .Release.Name }}"

  17. redis-node: "true"

  18. redis-role: "master"

  19. type: "{{ .Values.servers.serviceType }}"

4.4 redis-slave-service.yaml

此YAML配置文件为定义了redis slave的服务,此服务暴露6379端口,以供在集群中使用。

  1. apiVersion: v1

  2. kind: Service

  3. metadata:

  4. name: {{ template "redis-ha.fullname" . }}-slave-svc

  5. labels:

  6. role: service

  7. {{ include "labels.standard" . | indent 4 }}

  8. annotations:

  9. {{ toYaml .Values.servers.annotations | indent 4 }}

  10. spec:

  11. ports:

  12. - port: 6379

  13. protocol: TCP

  14. targetPort: 6379

  15. selector:

  16. app: {{ template "redis-ha.name" . }}

  17. release: "{{ .Release.Name }}"

  18. redis-node: "true"

  19. redis-role: "slave"

  20. type: "{{ .Values.servers.serviceType }}"

4.5 redis-sentinel-deployment.yaml

此YAML文件定义Sentinel部署,Sentinel用于监控和管理对于Redis的访问。

  1. apiVersion: extensions/v1beta1

  2. kind: Deployment

  3. metadata:

  4. name: {{ template "redis-ha.fullname" . }}-sentinel

  5. labels:

  6. {{ include "labels.standard" . | indent 4 }}

  7. spec:

  8. replicas: {{ .Values.replicas.sentinels }}

  9. template:

  10. metadata:

  11. labels:

  12. app: {{ template "redis-ha.name" . }}

  13. release: {{ .Release.Name }}

  14. component: sentinel

  15. name: {{ template "redis-ha.fullname" . }}-sentinel

  16. spec:

  17. serviceAccountName: {{ template "redis-ha.serviceAccountName" . }}

  18. {{- if .Values.nodeSelector }}

  19. nodeSelector:

  20. {{ toYaml .Values.nodeSelector | indent 8 }}

  21. {{- end }}

  22. {{- if .Values.tolerations }}

  23. tolerations:

  24. {{ toYaml .Values.tolerations | indent 8 }}

  25. {{- end }}

  26. containers:

  27. - name: sentinel

  28. image: {{ .Values.redis_image }}

  29. resources:

  30. {{ toYaml .Values.resources.sentinel | indent 10 }}

  31. env:

  32. - name: SENTINEL

  33. value: "true"

  34. - name: REDIS_CHART_PREFIX

  35. value: {{ template "redis-ha.fullname" . }}-

  36. {{- if .Values.auth }}

  37. - name: REDIS_PASS

  38. valueFrom:

  39. secretKeyRef:

  40. name: {{ template "redis-ha.fullname" . }}

  41. key: auth

  42. {{- end }}

  43. ports:

  44. - containerPort: 26379

4.6 redis-sentinel-service.yaml

此YAML文件用于在集群内容暴露Sentinel部署,以供其它应用访问和调用。

  1. apiVersion: v1

  2. kind: Service

  3. metadata:

  4. name: {{ template "redis-ha.fullname" . }}-sentinel

  5. labels:

  6. name: {{ template "redis-ha.name" . }}-sentinel-svc

  7. role: service

  8. {{ include "labels.standard" . | indent 4 }}

  9. spec:

  10. ports:

  11. - port: 26379

  12. targetPort: 26379

  13. selector:

  14. app: {{ template "redis-ha.name" . }}

  15. release: "{{ .Release.Name }}"

  16. redis-role: "sentinel"

4.7 redis-serviceaccount.yaml

如果rbac.create的值为true,此YAML文件将创建一个名为{{template “redis-ha.serviceAccountName”.}}的service account。

  1. {{- if .Values.serviceAccount.create -}}

  2. apiVersion: v1

  3. kind: ServiceAccount

  4. metadata:

  5. name: {{ template "redis-ha.serviceAccountName" . }}

  6. labels:

  7. app: "redis-ha"

  8. chart: {{ .Chart.Name }}-{{ .Chart.Version }}

  9. heritage: {{ .Release.Service }}

  10. release: {{ .Release.Name }}

  11. {{- end -}}

4.8 redis-role.yaml

如果rbac.create的值为true,则此YAML文件将会定义名为{{template “redis-ha.fullname” .}}一个角色,此角色拥有获取、列示和修改pods的权限。

  1. {{- if .Values.rbac.create -}}

  2. apiVersion: rbac.authorization.k8s.io/v1beta1

  3. kind: Role

  4. metadata:

  5. name: {{ template "redis-ha.fullname" . }}

  6. labels:

  7. {{ include "labels.standard" . | indent 4 }}

  8. rules:

  9. - apiGroups:

  10. - ""

  11. resources:

  12. - pods

  13. verbs:

  14. - get

  15. - list

  16. - patch

  17. {{- end -}}

4.9 redis-rolebinding.yaml

如果rbac.create的值为true,将上述创建的service account和角色进行绑定。

  1. {{- if .Values.rbac.create -}}

  2. apiVersion: rbac.authorization.k8s.io/v1beta1

  3. kind: RoleBinding

  4. metadata:

  5. name: {{ template "redis-ha.fullname" . }}

  6. labels:

  7. {{ include "labels.standard" . | indent 4 }}

  8. roleRef:

  9. apiGroup: rbac.authorization.k8s.io

  10. kind: Role

  11. name: {{ template "redis-ha.fullname" . }}

  12. subjects:

  13. - kind: ServiceAccount

  14. name: {{ template "redis-ha.serviceAccountName" . }}

  15. {{- end -}}

4.10 redis-auth-secret.yaml

如果auth的值为true,则会创建一个保密字典。

5、Redis部署环境验证

在Kubernetes集群中,可以通过DNS名称{{ template “redis-ha.fullname” . }}.{{ .Release.Namespace }}.svc.cluster.local和端口6379访问redis集群。 如果设置了认证的话,通过下面的步骤连接Redis:

1)获取随机创建的redis密码:

  1. echo $(kubectl get secret {{ template “redis-ha.fullname” . }} -o “jsonpath={.data[‘auth’]}” | base64 -D)

2)使用客户端连接Redis master Pod:

  1. kubectl exec -it $(kubectl get pod -o jsonpath='{range .items[*]}{.metadata.name} {.status.containerStatuses[0].state}{“\n”}{end}’ -l redis-role=master | grep running | awk ‘{print $1}’) bash

3)在容器内使用Redis CLI连接:

  1. redis-cli -a <REDIS-PASS-FROM-SECRET>

如果未设置认证的话,通过下面的步骤连接Redis:

1)可以通过下面的命令运行Redis Pod,作为客户端:

获取当前系统中的Pods:

  1. $ kubectl get pods -L redis-role --namespace=kube-public

Kubernetes基于Helm安装部署高可用的Redis

以名称为redis-ha-redis-ha-server-79659c558f-lgrtg的Pod作为客户端:

  1. $ kubectl exec -it redis-ha-redis-ha-server-79659c558f-lgrtg --namespace=kube-public bash

Kubernetes基于Helm安装部署高可用的Redis

2)使用Redis CLI:

获取Redis的master服务名称:

  1. $ kubectl get svc --namespace=kube-public

Kubernetes基于Helm安装部署高可用的Redis

  1. $ redis-cli -h redis-ha-redis-ha-master-svc.kube-public -p 6379

5、参考资料

1. 《redis-ha》地址:

https://github.com/kubernetes/charts/blob/master/stable/redis-ha

2. 《Redis Sentinel Documentation》地址:

https://redis.io/topics/sentinel

作者简介:
季向远,北京神舟航天软件技术有限公司产品经理。本文版权归原作者所有。

Kubernetes基于Helm安装部署高可用的Redis

Kubernetes基于Helm安装部署高可用的Redis

推荐阅读

本文分享自微信公众号 - K8S中文社区(k8schina)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这