一、K8s部署Redis集群
K8s可以帮助我们快速部署Redis集群。首先,我们需要创建一个redis-master Deployment,同时为redis-master指定1个Pod。
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-master
labels:
app: redis
spec:
replicas: 1
selector:
matchLabels:
app: redis
role: master
template:
metadata:
labels:
app: redis
role: master
spec:
containers:
- name: redis-master
image: redis
command: ["redis-server"]
args: ["--requirepass", "password"]
ports:
- containerPort: 6379
接着,我们为redis-master创建一个NodePort类型的Service,以便在K8s集群外部通过IP:NodePort的方式访问redis-master。
apiVersion: v1
kind: Service
metadata:
name: redis-master
labels:
app: redis
role: master
spec:
type: NodePort
ports:
- port: 6379
targetPort: 6379
nodePort: 30001
selector:
app: redis
role: master
然后,我们创建一个redis-slave Deployment,并指定它有2个Pods,它们的Pod Template和redis-master是一致的,只是少了一个role: master的Label。
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-slave
labels:
app: redis
spec:
replicas: 2
selector:
matchLabels:
app: redis
role: slave
template:
metadata:
labels:
app: redis
role: slave
spec:
containers:
- name: redis-slave
image: redis
command: ["redis-server"]
args: ["--requirepass", "password", "--slaveof", "redis-master", "6379"]
ports:
- containerPort: 6379
同样地,为redis-slave创建一个NodePort类型的Service。
apiVersion: v1
kind: Service
metadata:
name: redis-slave
labels:
app: redis
role: slave
spec:
type: NodePort
ports:
- port: 6379
targetPort: 6379
nodePort: 30002
selector:
app: redis
role: slave
二、K8s部署Redis集群外部访问不上
当我们在K8s集群外部访问redis时,可能会遇到Connection refused的错误。这时,我们需要检查以下几个方面:
- 确保redis-master和redis-slave的Service的type是NodePort。
- 确保redis-master和redis-slave的Pod都启动并且没有CrashLoopBackOff的错误。
- 检查防火墙和网络配置是否允许访问K8s集群的IP:NodePort。
三、K8s部署Redis哨兵
为了保证Redis的高可用性,我们可以使用Redis哨兵来做主从切换。和部署Redis集群类似,我们首先需要创建哨兵的Deployment。
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-sentinel
labels:
app: redis
spec:
replicas: 3
selector:
matchLabels:
app: redis
role: sentinel
template:
metadata:
labels:
app: redis
role: sentinel
spec:
containers:
- name: redis-sentinel
image: redis
command:
- "/bin/sh"
- "-ec"
- |
redis-sentinel /usr/local/etc/redis/sentinel.conf
env:
- name: SENTINEL_QUORUM
value: "2"
- name: REDIS_MASTER_SERVICE_NAME
value: "redis-master"
ports:
- containerPort: 26379
volumeMounts:
- name: config
mountPath: /usr/local/etc/redis
volumes:
- name: config
configMap:
name: redis-sentinel-config
然后,为redis-sentinel创建一个NodePort类型的Service,以便在K8s集群外部通过IP:NodePort的方式访问redis-sentinel。
apiVersion: v1
kind: Service
metadata:
name: redis-sentinel
labels:
app: redis
role: sentinel
spec:
type: NodePort
ports:
- port: 26379
targetPort: 26379
nodePort: 30179
selector:
app: redis
role: sentinel
最后,我们需要为redis-master创建一个ConfigMap,用于配置哨兵。
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-sentinel-config
data:
sentinel.conf: |
port 26379
daemonize no
logfile ""
dir "/tmp"
sentinel monitor mymaster redis-master 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
四、K8s部署Redis缺点
和其他基于容器的应用一样,K8s部署Redis也存在一些缺点:
- 网络延迟:和普通的虚拟机相比,由于K8s要额外的处理网络数据包的转发等操作,所以可能会带来一定的网络延迟。
- 性能损失:由于K8s需要运行一些辅助容器,如Proxy,所以可能会带来一定的性能损失。
- 复杂度:K8s的使用和配置相对复杂,可能需要学习额外的知识,如K8s的API和yaml文件的编写。
五、K8s部署Redis Cluster
除了部署Redis主从模式和哨兵模式,我们还可以使用Redis Cluster来实现高可用性。Redis Cluster是通过对多个Redis实例进行分片来实现高可用性和可扩展性的方案。在K8s中,我们可以使用StatefulSet来部署Redis Cluster。 在StatefulSet中,每个Pod的名字都会按照指定的规则进行命名,例如:redis-cluster-0、redis-cluster-1、redis-cluster-2。为了实现Redis Cluster的分片,我们还需要为StatefulSet创建一个Headless Service。 完整的Redis Cluster在K8s中的部署示例如下:
apiVersion: v1
kind: Service
metadata:
name: redis-cluster
labels:
app: redis
spec:
clusterIP: None
ports:
- name: redis
port: 6379
selector:
app: redis
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis-cluster
spec:
serviceName: "redis-cluster"
replicas: 6
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis
command:
- redis-server
- /usr/local/etc/redis/redis.conf
ports:
- containerPort: 6379
volumeMounts:
- name: config
mountPath: /usr/local/etc/redis/
volumeClaimTemplates:
- metadata:
name: redis-data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-cluster-config
data:
redis.conf: |
cluster-enabled yes
cluster-config-file /data/nodes.conf
cluster-node-timeout 5000
appendonly yes
nodes.conf: |
# This file will be automatically generated by Redis
六、K8s部署Redis集群外部访问
同样地,为了让Redis Cluster能够被外部访问,我们仍然需要为Headless Service创建一个NodePort类型的Service,例如:
apiVersion: v1
kind: Service
metadata:
name: redis-cluster-nodeport
labels:
app: redis
spec:
type: NodePort
ports:
- name: redis
port: 6379
targetPort: 6379
nodePort: 30003
selector:
app: redis
七、K8s部署Redis集群的原理
Redis集群是通过一致性哈希的算法来实现分片的。具体来说,集群将所有的key分成16384个槽位,每个Redis实例负责一部分槽位。 在Redis集群中,客户端需要根据key的哈希值,选择相应的Redis实例进行操作。当Redis集群中的一个节点宕机时,集群会将其负责的槽位重新分配给其它节点。同时,Redis集群还支持主从复制和哨兵机制,来确保集群的高可用性。
八、Redis部署安装
除了使用K8s部署Redis外,我们还可以从官方网站下载Redis的源码,然后进行编译和安装。完整的Redis部署安装过程如下:
- 下载Redis的源码:
$ wget https://download.redis.io/releases/redis-6.2.5.tar.gz
$ tar xzf redis-6.2.5.tar.gz
$ cd redis-6.2.5
- 编译Redis:
$ make
- 安装Redis:
$ make install
- 启动Redis Server:
$ redis-server
九、K8s部署方式
K8s提供了多种方式来部署应用程序:
- Deployment:用于快速创建Pod、ReplicaSet和Service。
- StatefulSet:用于有状态应用程序的部署,例如数据库。
- DaemonSet:用于在K8s集群中的每个节点上启动一个Pod。
- Job:用于运行短暂或一次性的任务。
- CronJob:类似于Linux的crontab,用于定时执行任务。
十、K8s部署流程
在K8s中部署一个应用程序的流程通常如下:
- 准备Docker镜像:将应用程序及其依赖打包成Docker镜像,并上传到镜像仓库。
- 编写K8s的yaml文件:按照需要,编写应用程序的Deployment、Service、ConfigMap、Secret等K8s资源的yaml文件。
- 创建K8s资源:使用
kubectl create
或kubectl apply
命令,创建K8s资源。 - 验证部署:使用
kubectl get
命令,查看各个K8s资源的状态,验证部署是否成功。