日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

在Kubernetes中使用Sateful Set部署Redis

發(fā)布時(shí)間:2023/12/20 数据库 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在Kubernetes中使用Sateful Set部署Redis 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

面寫過(guò)過(guò)幾篇關(guān)于在Kubernetes上運(yùn)行有狀態(tài)服務(wù)相關(guān)的博文:


  • Kubernetes資源對(duì)象之Persistent Volumes
  • 在Kubernetes Pod中使用Ceph RBD Volume
  • 在Kubernetes上部署有狀態(tài)服務(wù)

最近需要在我們的一個(gè)Kubernetes集群上部署Redis,因此重新整理,寫一下如何在Kubernetes上使用Sateful Set部署Redis。

1.需求和環(huán)境

我們的需求是需要部署三節(jié)點(diǎn)的Redis主從復(fù)制,并部署三個(gè)節(jié)點(diǎn)的Redis Sentinel實(shí)現(xiàn)Redis的高可用。

環(huán)境信息如下:

  • Kubernetes 1.6.7集群
  • Ceph 11.2.0集群

Kubernetes的官方examples中已經(jīng)給出了一個(gè)在k8s集群上部署Redis的例子Reliable, Scalable Redis on Kubernetes, 就是基于Redis主從復(fù)制+Sentinel實(shí)現(xiàn)的,但是這個(gè)例子是以無(wú)狀態(tài)服務(wù)形式部署的,如果整個(gè)k8s集群重啟了,Redis的狀態(tài)就會(huì)丟失,因此不能用于生產(chǎn)環(huán)境。 但我們可以參考這個(gè)例子,以Satefult Set的形式部署。

我們的線上環(huán)境主要使用Ceph的塊存儲(chǔ)RBD作為Kubernetes的存儲(chǔ)卷,這里可以將Redis服務(wù)的狀態(tài)保存在Ceph RBD中。

關(guān)于Kubernetes和Ceph的部署可以參考我之前寫過(guò)的幾篇博文,這里不再展開(kāi):

  • 使用kubeadm安裝Kubernetes 1.6
  • Kubernetes 1.6 高可用集群部署
  • 使用kubeadm安裝Kubernetes 1.7
  • Ceph Kraken 11.2.0部署記錄

2.Storage Classes和Dynamic Storage Provision

Kubernetes 1.6開(kāi)始Storage Classes和Dynamic Storage Provision已經(jīng)是穩(wěn)定可用的了。 StorageClass是Dynamic Storage Provision的基礎(chǔ),k8s的管理員可以定義底層存儲(chǔ)平臺(tái)抽象。 用戶通過(guò)在PVC(Persistent Volume Claim)中通過(guò)名字引用StorageClass,PV(Persistent Volume)將使用StorageClass來(lái)動(dòng)態(tài)創(chuàng)建,這樣就節(jié)省了集群管理員手動(dòng)創(chuàng)建PV的時(shí)間。

2.1 在Ceph中創(chuàng)建存儲(chǔ)池Pool

我們需要先在Ceph中創(chuàng)建一個(gè)k8s集群專用的Ceph Pool,在創(chuàng)建之前我們先看一下當(dāng)前Ceph集群中的存儲(chǔ)池:

ceph osd lspools 0 rbd,1 .rgw.root,2 default.rgw.control,3 default.rgw.data.root,4 default.rgw.gc,5 default.rgw.lc,6 default.rgw.log,7 default.rgw.users.uid,8 default.rgw.users.email,9 default.rgw.users.keys,10 default.rgw.buckets.index,11 default.rgw.buckets.data,

一個(gè)Ceph集群可以有多個(gè)pool,pool是邏輯上的存儲(chǔ)池。不同的pool可以有不一樣的數(shù)據(jù)處理方式,例如replica size, placement groups, crush rules,snapshot等等。 可以看到因?yàn)槲覀冞@個(gè)環(huán)境還是用Ceph的RGW作為我們的對(duì)象存儲(chǔ),因此除了默認(rèn)的名稱為rbd的pool外,還有很多rgw的pool。

下面創(chuàng)建一個(gè)專門給k8s集群專用的pool kube:

ceph osd pool create kube 128 pool 'kube' createdceph osd lspools 0 rbd,1 .rgw.root,2 default.rgw.control,3 default.rgw.data.root,4 default.rgw.gc,5 default.rgw.lc,6 default.rgw.log,7 default.rgw.users.uid,8 default.rgw.users.email,9 default.rgw.users.keys,10 default.rgw.buckets.index,11 default.rgw.buckets.data,12 kube,
  • 當(dāng)前這個(gè)ceph集群只有3個(gè)osd,所以設(shè)置pg_num為128,可參考PLACEMENT GROUPS

2.2 配置k8s Node節(jié)點(diǎn)訪問(wèn)Ceph

為了讓Kubernetes的Node可以調(diào)用rbd,如果Ceph集群和Kubernetes集群不是在相同的機(jī)器上,還需要在Kubernetes的Node上安裝ceph-common:

yum install -y ceph-common

接下來(lái)在Kubernetes上創(chuàng)建ceph-secret,這個(gè)Secret將用于Kubernetes集群的StorageClass上。

我們先查看一下ceph集群上的所有用戶列表:

ceph auth list

這個(gè)命令會(huì)列出針對(duì)Ceph的每種類型的進(jìn)程已經(jīng)創(chuàng)建的不同權(quán)限的用戶,同時(shí)也會(huì)列出client.admin用戶,這個(gè)是Ceph集群的管理員用戶。

接下來(lái)我們創(chuàng)建一個(gè)client.kube用戶:

ceph auth get-or-create client.kube [client.kube]key = AQAzcYVZ6sbJLhAA7qCBywM+iPRgAG97FtoXIw==

創(chuàng)建好的client.kube用戶用戶還沒(méi)有任何權(quán)限,下面給其授權(quán):

ceph auth caps client.kube mon 'allow r' osd 'allow rwx pool=kube' updated caps for client.kube

查看用戶和權(quán)限信息:

ceph auth get client.kube exported keyring for client.kube [client.kube]key = AQAzcYVZ6sbJLhAA7qCBywM+iPRgAG97FtoXIw==caps mon = "allow r"caps osd = "allow rwx pool=kube"

因?yàn)镵ubernetes的Secret需要Base64編碼,下面將這個(gè)keyring轉(zhuǎn)換成Base64編碼:

ceph auth get-key client.kube | base64 QVFBemNZVlo2c2JKTGhBQTdxQ0J5d00raVBSZ0FHOTdGdG9YSXc9PQ==

接下來(lái)創(chuàng)建Secret,ceph-secret.yaml:

apiVersion: v1 kind: Secret metadata:name: ceph-secretnamespace: kube-system type: kubernetes.io/rbd data:key: QVFBemNZVlo2c2JKTGhBQTdxQ0J5d00raVBSZ0FHOTdGdG9YSXc9PQ== kubectl create -f ceph-secret.yaml secret "ceph-secret" created

2.3 在k8s集群創(chuàng)建StorageClass

首先檢查我們的集群中是否有默認(rèn)的StorageClass:

kubectl get storageclass No resources found.

我們這里使用的k8s集群是使用ansible部署的Kubernetes 1.6 高可用集群,可以看出我們部署的這個(gè)集群并沒(méi)有創(chuàng)建默認(rèn)的StorageClass。

我們現(xiàn)在集群中創(chuàng)建默認(rèn)的Storage Class, storege.yaml文件如下:

--- apiVersion: storage.k8s.io/v1 kind: StorageClass metadata:name: defaultannotations:storageclass.kubernetes.io/is-default-class: "true"labels:kubernetes.io/cluster-service: "true" provisioner: kubernetes.io/rbd parameters:monitors: 192.168.61.3:6789,192.168.61.4:6789,192.168.61.5:6789adminId: kubeadminSecretName: ceph-secretadminSecretNamespace: kube-systempool: kubeuserId: kubeuserSecretName: ceph-secret-user
  • annotations中storageclass.kubernetes.io/is-default-class: “true”表示這個(gè)StorageClass是集群默認(rèn)的StorageClass
  • provisioner: kubernetes.io/rbd表示這個(gè)StorageClass的類型時(shí)Ceph RBD
  • parameters配置了這個(gè)StorageClass使用的Ceph集群以及RBD的相關(guān)參數(shù)
  • monitors是逗號(hào)分隔的Ceph Mon節(jié)點(diǎn)地址
  • adminId指定Ceph client 的ID需要具有能在配置的Ceph RBD Pool中創(chuàng)建鏡像的權(quán)限。默認(rèn)值為admin
  • adminSecret:adminId的Secret Name,該Secret的type必須是”kubernetes.io/rbd”,該參數(shù)是必須的
  • adminSecretNamespace: adminSecret的namespace,默認(rèn)為”default”
  • pool: Ceph RBD Pool,默認(rèn)為”rbd”
  • userId: Ceph client Id,用來(lái)映射RBD鏡像。
  • userSecretName: userId在映射RBD鏡像時(shí)所需要的Secret的名稱。該Secret要求必須出現(xiàn)在和PVC相同的namespace內(nèi),并且type必須是”kubernetes.io/rbd”。該參數(shù)是必須的

創(chuàng)建這個(gè)默認(rèn)的StorageClass:

kubectl create -f storage.yaml storageclass "default" createdkubectl get storageclass NAME TYPE default (default) kubernetes.io/rbd
  • (default)表示這個(gè)名稱為default的StorageClass是k8s集群默認(rèn)的StorageClass

3.構(gòu)建Redis的Docker鏡像

參考Reliable, Scalable Redis on Kubernetes中的Redis鏡像,我們的Redis的Dockerfile定制如下:

FROM harbor.frognew.com/rg/alpine-glibc:0.1RUN apk add --no-cache redis sed bashCOPY redis-master.conf /redis-master/redis.conf COPY redis-slave.conf /redis-slave/redis.conf COPY run.sh /run.sh RUN chmod u+x /run.sh CMD [ "/run.sh" ]ENTRYPOINT [ "bash", "-c" ]
  • alpine-glibc:0.1是我們的基礎(chǔ)鏡像,在alpine:3.6的基礎(chǔ)上增加了glibc,并將時(shí)區(qū)設(shè)置為Asia/Shanghai

參考Reliable, Scalable Redis on Kubernetes中的run.sh做如下定制,原來(lái)的run.sh不支持對(duì)redis設(shè)置密碼,加上從環(huán)境變量$REDIS_PASS讀取redis密碼:

#!/bin/bash # Copyright 2014 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. function launchmaster() { if [[ ! -e /redis-master-data ]]; thenecho "Redis master data doesn't exist, data won't be persistent!"mkdir /redis-master-datafised -i "s/%redis-pass%/${REDIS_PASS}/" /redis-master/redis.confredis-server /redis-master/redis.conf --protected-mode no } function launchsentinel() { while true; domaster=$(redis-cli -a $REDIS_PASS -h ${REDIS_SENTINEL_SERVICE_HOST} -p ${REDIS_SENTINEL_SERVICE_PORT} --csv SENTINEL get-master-addr-by-name mymaster | tr ',' ' ' | cut -d' ' -f1) if [[ -n ${master} ]]; thenmaster="${master//\"}" elsemaster=${REDIS_MASTER_SERVICE_HOST} firedis-cli -a $REDIS_PASS -h ${master} INFOif [[ "$?" == "0" ]]; then break fiecho "Connecting to master failed. Waiting..."sleep 10 donesentinel_conf=sentinel.confecho "sentinel monitor mymaster ${master} 6379 2" > ${sentinel_conf}echo "sentinel auth-pass mymaster ${REDIS_PASS}" >> ${sentinel_conf}echo "sentinel down-after-milliseconds mymaster 60000" >> ${sentinel_conf}echo "sentinel failover-timeout mymaster 180000" >> ${sentinel_conf}echo "sentinel parallel-syncs mymaster 1" >> ${sentinel_conf}echo "bind 0.0.0.0" >> ${sentinel_conf}redis-sentinel ${sentinel_conf} --protected-mode no } function launchslave() { while true; domaster=$(redis-cli -a $REDIS_PASS -h ${REDIS_SENTINEL_SERVICE_HOST} -p ${REDIS_SENTINEL_SERVICE_PORT} --csv SENTINEL get-master-addr-by-name mymaster | tr ',' ' ' | cut -d' ' -f1) if [[ -n ${master} ]]; thenmaster="${master//\"}" elseecho "Failed to find master."sleep 60 exit 1 fi redis-cli -a $REDIS_PASS -h ${master} INFOif [[ "$?" == "0" ]]; then break fiecho "Connecting to master failed. Waiting..."sleep 10 donesed -i "s/%master-ip%/${master}/" /redis-slave/redis.confsed -i "s/%master-port%/6379/" /redis-slave/redis.confsed -i "s/%redis-pass%/${REDIS_PASS}/" /redis-slave/redis.confredis-server /redis-slave/redis.conf --protected-mode no } if [[ "${MASTER}" == "true" ]]; thenlaunchmasterexit 0 fi if [[ "${SENTINEL}" == "true" ]]; thenlaunchsentinelexit 0 filaunchslave
  • 這個(gè)腳本根據(jù)環(huán)境變量MASTER, SENTINEL來(lái)判斷是啟動(dòng)不同類型的redis進(jìn)程,如果MASTER為true,則啟動(dòng)redis master,否則如果SENTINEL為true則啟動(dòng)redis sentinel,否則啟動(dòng)redis salve
  • 從環(huán)境變量REDIS_PASS中讀取并設(shè)置redis的密碼

redis-master.conf的配置文件內(nèi)容如下:

daemonize no pidfile /var/run/redis.pid port 6379 tcp-backlog 511 bind 0.0.0.0 timeout 0 tcp-keepalive 60 loglevel notice logfile "" databases 16 save 900 1 save 300 10 save 60 10000 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump.rdb dir /redis-master-data slave-serve-stale-data yes rename-command FLUSHALL "" rename-command FLUSHDB "" slave-read-only yes repl-diskless-sync no repl-diskless-sync-delay 5 repl-disable-tcp-nodelay no slave-priority 100 requirepass %redis-pass% appendonly yes appendfilename "appendonly.aof" appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-load-truncated yes lua-time-limit 5000 slowlog-log-slower-than 10000 slowlog-max-len 128 latency-monitor-threshold 0 notify-keyspace-events "" hash-max-ziplist-entries 512 hash-max-ziplist-value 64 list-max-ziplist-entries 512 list-max-ziplist-value 64 set-max-intset-entries 512 zset-max-ziplist-entries 128 zset-max-ziplist-value 64 hll-sparse-max-bytes 3000 activerehashing yes client-output-buffer-limit normal 0 0 0 client-output-buffer-limit slave 256mb 64mb 60 client-output-buffer-limit pubsub 32mb 8mb 60 hz 10 aof-rewrite-incremental-fsync yes

redis-slave.conf配置文件內(nèi)容如下:

daemonize no pidfile /var/run/redis.pid port 6379 tcp-backlog 511 bind 0.0.0.0 timeout 0 tcp-keepalive 60 loglevel notice logfile "" databases 16 save 900 1 save 300 10 save 60 10000 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump.rdb dir "/data" slaveof %master-ip% %master-port% masterauth %redis-pass% slave-serve-stale-data yes rename-command FLUSHALL "" rename-command FLUSHDB "" slave-read-only yes repl-diskless-sync no repl-diskless-sync-delay 5 repl-disable-tcp-nodelay no slave-priority 100 requirepass %redis-pass% appendonly yes appendfilename "appendonly.aof" appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-load-truncated yes lua-time-limit 5000 slowlog-log-slower-than 10000 slowlog-max-len 128 latency-monitor-threshold 0 notify-keyspace-events "" hash-max-ziplist-entries 512 hash-max-ziplist-value 64 list-max-ziplist-entries 512 list-max-ziplist-value 64 set-max-intset-entries 512 zset-max-ziplist-entries 128 zset-max-ziplist-value 64 hll-sparse-max-bytes 3000 activerehashing yes client-output-buffer-limit normal 0 0 0 client-output-buffer-limit slave 256mb 64mb 60 client-output-buffer-limit pubsub 32mb 8mb 60 hz 10 aof-rewrite-incremental-fsync yes

構(gòu)建redis鏡像并推送到我們的私有倉(cāng)庫(kù):

docker build -t harbor.frognew.com/rg/redis:1.0 . docker push harbor.frognew.com/rg/rg/redis

4.在Kubernetes集群上部署Redis

假設(shè)我們的redis要部署在devops這個(gè)namespace下,先在這個(gè)namespace下創(chuàng)建ceph-secret-user這個(gè)Secret:

apiVersion: v1 kind: Secret metadata:name: ceph-secret-usernamespace: devops type: kubernetes.io/rbd data:key: QVFBemNZVlo2c2JKTGhBQTdxQ0J5d00raVBSZ0FHOTdGdG9YSXc9PQ== kubectl crate -f ceph-secret-user.yaml

4.1 redis-master.statefulset.yaml

redis-master.statefulset.yaml是redis master的Service和StatefulSet。

apiVersion: v1 kind: Service metadata:name: redis-masternamespace: devopslabels:name: redis-master spec:ports: - port: 6379selector:redis-master: "true" --- apiVersion: apps/v1beta1 kind: StatefulSet metadata:name: redis-masternamespace: devopslabels:name: redis-master spec:serviceName: redis-masterreplicas: 1 template:metadata:labels:app: redis-masterredis-master: "true"spec:terminationGracePeriodSeconds: 10containers: - name: redisimage: harbor.frognew.com/rg/redis:1.0imagePullPolicy: IfNotPresentports: - containerPort: 6379env: - name: MASTERvalue: "true" - name: REDIS_PASSvalueFrom:secretKeyRef:name: devopssecretkey: redisAuthPassresources:requests:memory: "256Mi"cpu: "250m"limits:memory: "512Mi"cpu: "500m"volumeMounts: - name: redis-master-volumemountPath: /dataimagePullSecrets: - name: regsecretvolumeClaimTemplates: - metadata:name: redis-master-volumespec:accessModes: [ "ReadWriteOnce" ]resources:requests:storage: 5Gi
  • 通過(guò)設(shè)置環(huán)境變量MASTER為true,表明以master形式啟動(dòng)redis,而環(huán)境變量REDIS_PASS從devopssecret這個(gè)Secret中獲取的值,這里略過(guò)devopssecret這個(gè)Secret的內(nèi)容
  • volumeClaimTemplates中定義了PVC,因?yàn)闆](méi)有給定storageClassName,所以將使用我們前面創(chuàng)建的默認(rèn)的StorageClass,會(huì)根據(jù)PVC動(dòng)態(tài)創(chuàng)建StatefulSet中Pod所需的PV

4.2 redis-sentinel.statefulset.yaml

redis-sentinel.statefulset.yaml定義了redis-sentinel的Service和StatefulSet:

apiVersion: v1 kind: Service metadata:name: redis-sentinelnamespace: devopslabels:name: redis-sentinel spec:ports: - port: 26379targetPort: 26379selector:redis-sentinel: "true" --- apiVersion: apps/v1beta1 kind: StatefulSet metadata:name: redis-sentinelnamespace: devops spec:serviceName: redis-sentinelreplicas: 3 template:metadata:labels:redis-sentinel: "true"spec:terminationGracePeriodSeconds: 10containers: - name: redis-sentinelimage: harbor.frognew.com/rg/redis:1.0imagePullPolicy: IfNotPresentports: - containerPort: 26379name: redis-sentinelenv: - name: SENTINELvalue: "true" - name: REDIS_PASSvalueFrom:secretKeyRef:name: devopssecretkey: redisAuthPassimagePullSecrets: - name: regsecret
  • sentinel的啟動(dòng)邏輯可以查看Docker鏡像中的run.sh中l(wèi)aunchsentinel()的邏輯

4.5 redis.statefulset.yaml

redis.statefulset.yaml定義了redis slave的Service和SatefulSet:

apiVersion: v1 kind: Service metadata:name: redisnamespace: devopslabels:app: redis spec:ports: - port: 6379clusterIP: Noneselector:app: redis --- apiVersion: apps/v1beta1 kind: StatefulSet metadata:name: redisnamespace: devopslabels:name: redis spec:serviceName: redisreplicas: 2 template:metadata:labels:app: redisspec:terminationGracePeriodSeconds: 10containers: - name: redisimage: harbor.frognew.com/rg/redis:1.0imagePullPolicy: IfNotPresentports: - containerPort: 6379env: - name: REDIS_PASSvalueFrom:secretKeyRef:name: devopssecretkey: redisAuthPassresources:requests:memory: "256Mi"cpu: "250m"limits:memory: "512Mi"cpu: "500m"volumeMounts: - name: redis-volumemountPath: /dataimagePullSecrets: - name: regsecretvolumeClaimTemplates: - metadata:name: redis-volumespec:accessModes: [ "ReadWriteOnce" ]resources:requests:storage: 5Gi
  • volumeClaimTemplates中定義了PVC,因?yàn)闆](méi)有給定storageClassName,所以將使用我們前面創(chuàng)建的默認(rèn)的StorageClass,會(huì)根據(jù)PVC動(dòng)態(tài)創(chuàng)建StatefulSet中Pod所需的PV。

4.4 以StatefulSet的形式部署Redis

下面實(shí)際操作一遍基于StatefulSet的Redis的部署。

先創(chuàng)建redis-master的Service和StatefulSet:

kubectl create -f redis-master.statefulset.yaml service "redis-master" created statefulset "redis-master" created

確保這redis master Pod處于running狀態(tài):

kubectl get pods -l redis-master="true" -n devops NAME READY STATUS RESTARTS AGE redis-master-0 1/1 Running 0 48skubectl get svc -l name="redis-master" -n devops NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE redis-master 10.104.132.220 <none> 6379/TCP 1m

下面創(chuàng)建redis-sentinel的Service和StatefulSet:

kubectl create -f redis-sentinel.statefulset.yaml service "redis-sentinel" created statefulset "redis-sentinel" createdkubectl get svc -l name="redis-sentinel" -n devops -o wide NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR redis-sentinel 10.97.4.9 <none> 26379/TCP 16s redis-sentinel=true

查看StatefulSet確保DESIRED和CURRENT的數(shù)量是相同的。

kubectl get statefulset -n devops NAME DESIRED CURRENT AGE redis-master 1 1 3m redis-sentinel 3 3 42s

查看sentinel Pod:

kubectl get pod -l redis-sentinel="true" -n devops NAME READY STATUS RESTARTS AGE redis-sentinel-0 1/1 Running 0 1m redis-sentinel-1 1/1 Running 0 1m redis-sentinel-2 1/1 Running 0 1m

下面創(chuàng)建redis slave的Service和StatefulSet:

kubectl create -f redis.statefulset.yaml service "redis" created statefulset "redis" created

注意上面的過(guò)程中,在創(chuàng)建redis master和slave的stateful set時(shí)可能需要一定的時(shí)間,因?yàn)樯婕暗絇VC, PV, rbd image的創(chuàng)建,耐心等待。

因?yàn)閞edis-master這個(gè)StatefulSet的副本數(shù)為1,redis slave這個(gè)SatefulSet中的副本數(shù)為2,所以我們可以看到集群中創(chuàng)建了3個(gè)PVC,并創(chuàng)建了3個(gè)PV:

kubectl get pvc -n devops NAME STATUS VOLUME CAPACITY ACCESSMODES STORAGECLASS AGE redis-master-volume-redis-master-0 Bound pvc-fd2c30e3-7b14-11e7-ad4a-1866da8c6175 5Gi RWO default 10m redis-volume-redis-0 Bound pvc-65a2ba2c-7b17-11e7-ad4a-1866da8c6175 5Gi RWO default 7m redis-volume-redis-1 Bound pvc-6a96951c-7b17-11e7-ad4a-1866da8c6175 5Gi RWO default 7mkubectl get pv -n devops NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-65a2ba2c-7b17-11e7-ad4a-1866da8c6175 5Gi RWO Delete Bound devops/redis-volume-redis-0 default 10m pvc-6a96951c-7b17-11e7-ad4a-1866da8c6175 5Gi RWO Delete Bound devops/redis-volume-redis-1 default 7m pvc-fd2c30e3-7b14-11e7-ad4a-1866da8c6175 5Gi RWO Delete Bound devops/redis-master-volume-redis-master-0 default 7m

一定要確認(rèn)STATUS的狀態(tài)為Bound,如果不是可以通過(guò)kubectl describe pvc <pvc-name> -n <namespace>查看具體的事件。實(shí)際上rbd image的創(chuàng)建是由controller-manager調(diào)用rbd命令完成的,所以如果有問(wèn)題也可以看一下controller-manager的日志。

下面的decribe pv命令詳細(xì)打印出了這個(gè)PV已經(jīng)使用Ceph RBD Image:

kubectl describe pv pvc-65a2ba2c-7b17-11e7-ad4a-1866da8c6175 -n devops Name: pvc-65a2ba2c-7b17-11e7-ad4a-1866da8c6175 Labels: <none> Annotations: pv.kubernetes.io/bound-by-controller=yespv.kubernetes.io/provisioned-by=kubernetes.io/rbd StorageClass: default Status: Bound Claim: devops/redis-volume-redis-0 Reclaim Policy: Delete Access Modes: RWO Capacity: 5Gi Message: Source: Type: RBD (a Rados Block Device mount on the host that shares a pod's lifetime)CephMonitors: [192.168.61.3:6789 192.168.61.4:6879 192.168.61.5:6789]RBDImage: kubernetes-dynamic-pvc-856cff45-7a7b-11e7-ac3c-1866da8c2fcdFSType:RBDPool: kubeRadosUser: kubeKeyring: /etc/ceph/keyringSecretRef: &{ceph-secret-user}ReadOnly: false Events: <none>

另外可以在Ceph集群中查看創(chuàng)建的rbd image:

rbd list kube kubernetes-dynamic-pvc-856cff45-7a7b-11e7-ac3c-1866da8c2fcd kubernetes-dynamic-pvc-8b1be6fc-7a7b-11e7-ac3c-1866da8c2fcd kubernetes-dynamic-pvc-cce6429c-7a7a-11e7-ac3c-1866da8c2fcdrbd info -p kube --image kubernetes-dynamic-pvc-856cff45-7a7b-11e7-ac3c-1866da8c2fcd rbd image 'kubernetes-dynamic-pvc-856cff45-7a7b-11e7-ac3c-1866da8c2fcd':size 5120 MB in 1280 objectsorder 22 (4096 kB objects)block_name_prefix: rb.0.3e17b.238e1f29format: 1 kubectl get statefulset -n devops NAME DESIRED CURRENT AGE redis 2 2 5m redis-master 1 1 10m redis-sentinel 3 3 7m

我們重點(diǎn)來(lái)看一下redis statefulset和redis service:

kubectl get svc -l app="redis" -n devops NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE redis None <none> 6379/TCP 7mkubectl get pod -l app="redis" -n devops NAME READY STATUS RESTARTS AGE redis-0 1/1 Running 0 7m redis-1 1/1 Running 0 7m

注意redis service的CLUSTER-IP為None,這是由有狀態(tài)服務(wù)的特征決定的。 有狀態(tài)服務(wù)具有以下特征:

  • 要求有穩(wěn)定的網(wǎng)絡(luò)身份,即唯一不變的hostname,并保存在DNS中。hostname是由statefulset的名字后邊跟隨”-序號(hào)”組成,這里是redis-1, redis-2。 同時(shí)每個(gè)Pod的網(wǎng)絡(luò)身份也是通過(guò)Service定義被創(chuàng)建出來(lái)了,根據(jù)Service的定義,通過(guò)ClusterIp:None指定,該Service將在DNS生成一條沒(méi)有ClusterIP的記錄。
  • 要求有持久穩(wěn)定的存儲(chǔ),通過(guò)PVC和PV提供。這里使用了Kubernetes的通過(guò)Dynamic Storage Provision特性,PV使用StorageClass來(lái)動(dòng)態(tài)創(chuàng)建。
  • redis-0,redis-1這兩個(gè)是reddis的slave節(jié)點(diǎn)。

最后我們來(lái)看一下k8s集群中redis節(jié)點(diǎn):

kubectl get statefulset -n devops NAME DESIRED CURRENT AGE redis 2 2 8m redis-master 1 1 12m redis-sentinel 3 3 10m

我們以StatefulSet的形式部署了1個(gè)master, 2個(gè)slave, 3個(gè)sentinel。當(dāng)其中master節(jié)點(diǎn)發(fā)生故障時(shí),sentinel會(huì)從剩余redis節(jié)點(diǎn)中選舉新的master并切換。 3個(gè)redis節(jié)點(diǎn)的數(shù)據(jù)都是保存在ceph rbd中。

本文轉(zhuǎn)自中文社區(qū)-在Kubernetes中使用Sateful Set部署Redis

總結(jié)

以上是生活随笔為你收集整理的在Kubernetes中使用Sateful Set部署Redis的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。