在kubernetes集群中创建redis主从多实例


       继续使用上次实验环境 《centos7 使用二进制包搭建kubernetes 1.9.0集群》 ,因为环境中已经配置好flannel网络了,接下要就是慢慢在此环境中创建一些实例。因为只是搭建简单的环境是比较容易上手,随便网上一搜可能就出来了。但是要自己去从头一步一步跑起项目,还是基于真实的项目来跑的话还是需要自己多研究,当然目前还是止于使用阶段,要深入还得多看资料。

 

 

本次要记录的是自己从创建镜像到实现redis主从示例,为什么要自己制作镜像呢?其实就是为了自己可以学多点,毕竟网上的都人别人做好的,你自己没做过根本不知道制作过程中会遇到什么。为什么有些镜像大,有些镜像比较小。这都是在哪里做的优化?

本次直接使用alpine基础镜像,因为它小,加上个redis也就11M左右的镜像,如果使用centos可能就大点了,这里先不做存储的方便,只是简单的实现redis-master和redis-slave之间的自动发现。

为了自己好区分我直接制作两个镜像,一个为redis-master专门用来跑master服务的,一个为redis-slave专门跑slave实例的。其实可以只用一个,只需分两个配置文件或者是两个不同的启动方法,这里不做这个介绍。

 

redis-slave镜像制作

 

需要二个文件:Dockerfile、run.sh

Dockerfile内容如下: 

  1. FROM alpine:3.4  
  2. RUN apk add --no-cache redis sed bash  
  3. COPY run.sh /run.sh  
  4. CMD [ "/run.sh" ]  
  5. ENTRYPOINT [ "bash" ]  

 

其实默认可以不使用redis.conf文件的,如果需要就在上面的Dockerfile文件也加入,这里目前也处于测试,先不加配置。

 

run.sh启动脚本,也就是一行文件。

 

  1. [root@k8s-node1 slave]# cat run.sh 
  2. #/bin/sh 
  3. redis-server --slaveof ${REDIS_MASTER_SERVICE_HOST} ${REDIS_MASTER_SERVICE_PORT} 

 

打包成镜像传到内网仓库:

 

  1. docker build -t redis-slave . 
  2. docker tag redis-slave reg.docker.tb/harbor/redis-slave 
  3. docker push reg.docker.tb/harbor/redis-slave 

 

redis-master镜像制作

跟上面的配置差不多一样,只是启动时的命令有点不而已。

Dockerfile内容如下: 

  1. FROM alpine:3.4  
  2. RUN apk add --no-cache redis sed bash  
  3. COPY run.sh /run.sh  
  4. CMD [ "/run.sh" ]  
  5. ENTRYPOINT [ "bash" ]  

 

其实默认可以不使用redis.conf文件的,如果需要就在上面的Dockerfile文件也加入,这里目前也处于测试,先不加配置。

 

run.sh启动脚本,也就是一行文件。

 

  1. [root@k8s-node1 master]# cat run.sh 
  2. #/bin/sh 
  3. redis-server

 

打包成镜像传到内网仓库:

 

  1. docker build -t redis-master . 
  2. docker tag redis-master reg.docker.tb/harbor/redis-master 
  3. docker push reg.docker.tb/harbor/redis-master 
  4.  

 

创建kube的配置文件yaml

创建一个master-service.yaml 来统一Master的入口,同时会自动关联到labels为redis-master的所有Pod,这里要注意Service要优于pod启动,不然无法通过环境变量把配置信息写入到pod中。

 

  1. apiVersion: v1 
  2. kind: Service 
  3. metadata: 
  4.   name: redis-master 
  5.   labels: 
  6.     name: redis-master 
  7. spec: 
  8.   ports: 
  9.   - port: 6379 
  10.     targetPort: 6379 
  11.   selector: 
  12.     name: redis-master 

 

 

redis-master.yaml 以rc的方式来创建一个master容器,它会保证容器的副本数量。 

 

  1. apiVersion: v1 
  2. kind: ReplicationController 
  3. metadata: 
  4.   name: redis-master 
  5.   labels: 
  6.     name: redis-master 
  7. spec: 
  8.   replicas: 1 
  9.   selector: 
  10.     name: redis-master 
  11.   template: 
  12.     metadata: 
  13.       labels: 
  14.         name: redis-master 
  15.     spec: 
  16.       containers: 
  17.       - name: master 
  18.         image: reg.docker.tb/harbor/redis-master 
  19.         ports: 
  20.         - containerPort: 6379 

redis-slave-service.yaml跟上面的Service一样,都是管理redis-slave所有容器的,此服务创建后会把所有的slave实例的容器分配一个集群IP.

 

  1. apiVersion: v1 
  2. kind: Service 
  3. metadata: 
  4.   name: redis-slave 
  5.   labels: 
  6.     name: redis-slave 
  7. spec: 
  8.   ports: 
  9.   - port: 6379 
  10.   selector: 
  11.     name: redis-slave 

 

redis-slave.yaml  同样是以RC的方式来创建redis-slave实例,这里的数量为两个。需要注意的是Image这里指定是刚才打包的镜像名。

 

  1. apiVersion: v1 
  2. kind: ReplicationController 
  3. metadata: 
  4.   name: redis-slave 
  5.   labels: 
  6.     name: redis-slave 
  7. spec: 
  8.   replicas: 2 
  9.   selector: 
  10.     name: redis-slave 
  11.   template: 
  12.     metadata: 
  13.       labels: 
  14.         name: redis-slave 
  15.     spec: 
  16.       containers: 
  17.       - name: worker 
  18.         image: reg.docker.tb/harbor/redis-slave 
  19.         env: 
  20.         - name: GET_HOSTS_FROM 
  21.           value: env 
  22. #value: dns
  23.         ports: 
  24.         - containerPort: 6379 

 

 注意:要实现master和slave服务自动发现,需要配置它们之间的对应关系。Kubernetes有两种方法就是环境变量ENV和DNS记录解析,因为我的实验环境没有使用这个DNS来解析,所以只能使用ENV环境变量。

 

上面的redis-slave.yaml 就是使用了env环境变量。

 

 

接下来创建实例吧:

 

  1. master: 
  2. kubectl create -f redis-service.yaml 
  3. kubectl create -f redis-master.yaml 
  4.  
  5. slave: 
  6. kubectl create -f redis-slave-service.yaml 
  7. kubectl create -f redis-slave.yaml 

 

 查看启动的效果:

 

  1. [root@k8s-master redis-pod]# kubectl get all -o wide 
  2. NAME                    READY     STATUS    RESTARTS   AGE       IP           NODE 
  3. po/redis-master-qpzlh   1/1       Running   0          1h        172.21.2.2   k8s-node1 
  4. po/redis-slave-2rwk5    1/1       Running   0          1h        172.21.2.3   k8s-node1 
  5. po/redis-slave-6tf2f    1/1       Running   0          1h        172.21.8.3   k8s-node2 
  6.  
  7. NAME              DESIRED   CURRENT   READY     AGE       CONTAINERS   IMAGES                              SELECTOR 
  8. rc/redis-master   1         1         1         1h        master       reg.docker.tb/harbor/redis-master   name=redis-master 
  9. rc/redis-slave    2         2         2         1h        worker       reg.docker.tb/harbor/redis-slave    name=redis-slave 
  10.  
  11. NAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE       SELECTOR 
  12. svc/kubernetes     ClusterIP   10.254.0.1       <none>        443/TCP    3d        <none> 
  13. svc/redis-master   ClusterIP   10.254.152.116   <none>        6379/TCP   1h        name=redis-master 
  14. svc/redis-slave    ClusterIP   10.254.188.60    <none>        6379/TCP   1h        name=redis-slave 

 

简单的测试master和slave是否可以同步数据:

连接master容器,可以看到有两个Replication中有两个connected_slaves就是从实例,后面跟着的就是IP地址。

 

  1. [root@k8s-master redis-pod]# kubectl exec -it redis-master-qpzlh -- /bin/bash 
  2. bash-4.3# redis-cli                                                                                                                                          
  3. 127.0.0.1:6379> info 
  4. # Server 
  5. redis_version:3.2.11 
  6. redis_git_sha1:535782f7 
  7. redis_git_dirty:0 
  8. redis_build_id:80ce8a1f388ac530 
  9. redis_mode:standalone 
  10. os:Linux 4.4.113-1.el7.elrepo.x86_64 x86_64 
  11. arch_bits:64 
  12. multiplexing_api:epoll 
  13. gcc_version:5.3.0 
  14. process_id:5 
  15. run_id:6629f021c2e5bd972fff05c84566cc92c7e59be0 
  16. tcp_port:6379 
  17. uptime_in_seconds:7105 
  18. uptime_in_days:0 
  19.  
  20. ...... 
  21. # Clients 
  22. connected_clients:2 
  23. client_longest_output_list:0 
  24. client_biggest_input_buf:0 
  25. blocked_clients:0 
  26. ...... 
  27.  
  28. # Replication 
  29. role:master 
  30. connected_slaves:2 
  31. slave0:ip=172.21.2.3,port=6379,state=online,offset=5276,lag=1 
  32. slave1:ip=172.21.8.0,port=6379,state=online,offset=5276,lag=1 
  33. master_repl_offset:5276 
  34. repl_backlog_active:1 
  35. repl_backlog_size:1048576 
  36. repl_backlog_first_byte_offset:2 
  37. repl_backlog_histlen:5275 

 

连接一个slave容器查看信息,可以看到Replication中role:slave为从实例,master的IP和端口等信息。

 

  1. [root@k8s-master ~]# kubectl exec -it redis-slave-2rwk5 -- /bin/bash 
  2. bash-4.3# redis-cli                                                                                                                                          
  3. 127.0.0.1:6379> info 
  4. # Server 
  5. redis_version:3.2.11 
  6. redis_git_sha1:535782f7 
  7. redis_git_dirty:0 
  8. redis_build_id:80ce8a1f388ac530 
  9. redis_mode:standalone 
  10. os:Linux 4.4.113-1.el7.elrepo.x86_64 x86_64 
  11. arch_bits:64 
  12. multiplexing_api:epoll 
  13. gcc_version:5.3.0 
  14. process_id:5 
  15. run_id:d48c42ea0a83babda663837ed5a6f9ef5a3ff9bf 
  16. tcp_port:6379 
  17. uptime_in_seconds:3957 
  18. uptime_in_days:0 
  19.  
  20. ...... 
  21. # Replication 
  22. role:slave 
  23. master_host:10.254.152.116 
  24. master_port:6379 
  25. master_link_status:up 
  26. master_last_io_seconds_ago:7 
  27. master_sync_in_progress:0 
  28. slave_repl_offset:5542 
  29. slave_priority:100 
  30. slave_read_only:1 
  31. connected_slaves:0 
  32. master_repl_offset:0 
  33. repl_backlog_active:0 
  34. repl_backlog_size:1048576 
  35. repl_backlog_first_byte_offset:0 
  36. repl_backlog_histlen:0 

 

此时在Master上创建一个key, 在slave上立马就可以获取到了。

 

  1. master: 
  2. 127.0.0.1:6379> set name swper 
  3. OK 
  4.  
  5. slave: 
  6. 127.0.0.1:6379> get name 
  7. "swper" 
  8.  
  9. slave上只读: 
  10. 127.0.0.1:6379> set test 1 
  11. (error) READONLY You can't write against a read only slave. 

 

这样就实现了一主多从的效果了,集群的IP现在是外部无法访问的,kubernetes节点中可以相互连通。

其实原本是很简单的实验,我居然在传递参数的时候少了个$号导致一直获取不到。。。。

 

参考:https://github.com/kubernetes/kubernetes/tree/master/examples/guestbook