※このブログではサーバー運用、技術の検証等の費用のため広告をいれています。
記事が見づらいなどの問題がありましたらContactからお知らせください。

<前のページ
Kubernetesダッシュボードのインストールからログインまで解説
次のページ>
【Kubernetes】Serviceの各タイプについて解説

【Kubernetes】redisのレプリケーションを実装する方法

kubernetes kubectl k8s サーバー開発 レプリケーション 冗長性 redis

投稿日:2020年10月10日

このエントリーをはてなブックマークに追加
この記事ではKubernetesのDeployment、Serviceについてredisのレプリケーションを実装する実例を交えつつ解説しています。

はじめに

この記事について

この記事ではKubernetesのDeployment、Serviceについてredisのレプリケーションを実装する実例を交えつつ解説しています。

環境

この記事は以下の環境で実践・確認されました。

  • minikube version:v1.13.1
  • kubernetes client:v1.19.0
  • kubernetes server:v1.19.2
  • ホストOS:Ubuntu18.04LTS

レプリケーション(Replication)の実装について

レプリケーション(Replication)とは

レプリケーションとは、データベースなどに対して同じデータを保持するものを複数用意することで、高可用性を実現することを言います。このときメインで利用されるサーバーを稼働系(マスター)、稼働系に障害があった際に利用されるサーバーを待機系という。
稼働系と待機系は物理的な障害に強くするために離れた距離に置くことが多い(例えばクラウドならそれぞれのリージョンを違うものに設定)。

Kubernetesで

ReplicationController

ReplicationControllerは複数のPodのレプリカを一度に実行・管理することのできるKubernetesのリソースです。このリソースを利用すると常に指定した数のPodを起動させておくことができます。
これにより、障害やホストのカーネルのアップデートなどの際にもPodの存在を維持できます。

以前はこちらが利用されていましたが、Version1.12以降は後述のDeploymentを利用したReplicaSetによる管理が推奨されています。

Deployment

Deploymentは状態を指定すると、その状態を実現するPodとReplicaSetを維持します。

今回この記事でレプリケーション実装のために作成するのはこちらのDeploymentです。

DeploymentによるPodの作成・管理は自動的におこなわれるため、以下のような問題があります。

  • それぞれのPodのIPアドレスが不定であるため、レプリケーションを行うためのマスターへの参照でIPアドレスを使用できない
  • レプリケーションを複数作った際にどのPodにつなぐべきかわからない

これらの問題を解決するのがServiceです。

Service

ServiceはPodへの接続を解決してくれる抽象的なオブジェクトです。これを使用することでPodが再作成などされても、そのPodへの接続を実際のIPアドレスではなく常に同じDNS名でアクセスできます。

Serviceには以下のタイプがあります。

  • ClusterIP
  • NodePort
  • LoadBalancer
  • ExternalName

この内今回使用するのはLoadBalancerです。

これを使用することで複数のPodへのアクセスを上手くバランシングすることができます。


実践

この記事で使用するKubernetes環境はMinikubeのシングルノードクラスタです。
すでにMinikubeは起動しているものとします。もし、これの前にそのクラスタで作業していた場合には一度削除して再度起動したほうが良いかも知れません。

まずDeploymentを作成する前に確認しなければいけないことがあります。

ターミナル
$ kubectl cluster-info
Kubernetes master is running at https://192.168.39.7:8443
KubeDNS is running at https://192.168.39.7:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

上のようにKubeDNSが起動していることが確認できればOKです。今回作成するyamlファイルでは待機系から稼働系への参照でこのKubeDNSを使用します。

まずはRedisのマスターを起動させます。

deployment-redis-master.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-redis-master
  labels:
    name: deployment-redis-master
spec:
  replicas: 1
  selector:
    matchLabels:
      name: redis-master
  template:
    metadata:
      labels:
        name: redis-master
    spec:
      subdomain: master
      containers:
        - name: redis
          image: redis:3.2.0-alpine
          command:
            - "redis-server"
          args:
            - "--protected-mode"
            - "no"
          ports:
            - containerPort: 6379

yamlからリソースを作成します。

ターミナル
$ kubectl apply -f deployment-redis-master.yml
deployment.apps/deployment-redis-master created

リソースが正しく作成されたかをkubectl getコマンドで確認します。ちなみに通常渡す引数はreplicasetなのですが、rsと省略することができます。

ターミナル
$ kubectl get deployment
NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment-redis-master   1/1     1            1           32m
(base) ogihara@ubuntu:~/kubernetes_sample/redis_replication$ kubectl get deployments
NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment-redis-master   1/1     1            1           32m
$ kubectl get rs
NAME                                DESIRED   CURRENT   READY   AGE
deployment-redis-master-5b97f7fd5   1         1         1       32m
$ kubectl get pods
NAME                                      READY   STATUS    RESTARTS   AGE
deployment-redis-master-5b97f7fd5-n8m2b   1/1     Running   0          33m

つぎにこのRedisのマスタへの参照を管理するServiceを作成します。

service-redis-master.yml
apiVersion: v1
kind: Service
metadata:
  name: service-redis-master
spec:
  type: LoadBalancer
  ports:
    - protocol: TCP
      port: 6379
      targetPort: 6379
      name: redis
  selector:
    name: redis-master

今回作成するServiceにはLoadBarancerタイプを指定します。

.spec.selecter.nameの値が先程作成したDeploymentで作成されるPodのlabelsのnameの値になるようにします。deployment-redis-master.yml.spec.template.metadata.labels.nameの値でredis-masterと設定したので、こちらも同じ値を設定しています。

ではyamlからServiceを起動させます。

ターミナル
$ kubectl apply -f service-redis-master.yml
service/service-redis-master created

リソースの作成を確認してみましょう。

ターミナル
$ kubectl get services
NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes             ClusterIP      10.96.0.1       <none>        443/TCP          46m
service-redis-master   LoadBalancer   10.104.249.53   <pending>     6379:31584/TCP   19s

問題なく作成できています。ちなみにkubernetesと名前のついたServiceはデフォルトのServiceで、Kubernetesのマスターへのアクセスを管理しています。我々がいつも使用しているkubectlコマンドはこのServiceを通ってKubernetesのマスターのAPIを叩いていたりします。

それでは次に、同様の方法でスレイブ用のDeploymentを作成しましょう。

redis-slave-
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-redis-replica
  labels:
    name: deployment-redis-replica
spec:
  replicas: 2
  selector:
    matchLabels:
      name: redis-replica
  template:
    metadata:
      labels:
        name: redis-replica
    spec:
      subdomain: replica
      containers:
        - name: redis
          image: redis:3.2.0-alpine
          command:
            - "redis-server"
          args:
            - "--slaveof"
            - "service-redis-master.default.svc.cluster.local"
            - "6379"
            - "--protected-mode"
            - "no"
          ports:
            - containerPort: 6379
service-redis-replica.yml
apiVersion: v1
kind: Service
metadata:
  name: service-redis-replica
spec:
  type: LoadBalancer
  ports:
    - protocol: TCP
      port: 6379
      targetPort: 6379
      name: redis
  selector:
    name: redis-replica

applyさせます。

ターミナル
$ kubectl apply -f deployment-redis-replica.yml
deployment.apps/deployment-redis-replica created
$ kubectl apply -f service-redis-replica.yml 
service/service-redis-replica created

Serviceの方はredisマスターで定義したときとほとんど同じなので説明する必要はないと思います。

注目するべきはDeployment側のymlファイルです。起動されるコンテナで以下のようなコマンドが実行されるような設定になっています。

$ redis-server \
--slaveof service-redis-master.default.svc.cluster.local \
6379 \
--protected-mode no \

--slaveof オプションでレプリケーションする対象のDNS名を指定します。

"通常の"(Headlessでない)Serviceは、my-svc.my-namespace.svc.cluster.localという形式のDNSのA(AAAA)レコードを、ServiceのIPバージョンに応じて割り当てられます。

  • my-svc:サービスの名前です。Serviceの.metadata.nameの値になります。
  • my-namespace:サービスの所属するnamespaceです。今回の様に特にnamespaceを指定しなかった場合はdefaultが割り当てられます。

現在作RedisマスターのPodが一つ、ReplicaSetのRedisレプリカのPodが2つ存在している状態です。

ターミナル
$ kubectl get pods
NAME                                       READY   STATUS    RESTARTS   AGE
deployment-redis-master-5b97f7fd5-n8m2b    1/1     Running   0          94m
deployment-redis-replica-89f5664db-vgtrg   1/1     Running   0          2m56s
deployment-redis-replica-89f5664db-zx5kl   1/1     Running   0          2m57s

レプリケーションを確認

最後に正しくレプリケーションを実装できているかどうか確認しましょう。

ちなみにServiceへの接続先の確認方法については【Kubernetes】ServiceのIPアドレスとポートについてにまとめてあるので、詳しく知りたい方は読んでみてください。

ターミナル
$ minikube service --url service-redis-master
http://192.168.39.220:31584
$ $ redis-cli -h 192.168.39.220 -p 31584 info replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.17.0.4,port=6379,state=online,offset=17585,lag=0
slave1:ip=172.17.0.5,port=6379,state=online,offset=17585,lag=1
master_repl_offset:17585
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:17584

connected_slaves:2となっているため、きちんとレプリケーションできていることが確認できました。

一応replicaの方も確認してみます。

ターミナル
$ minikube service --url service-redis-replica
http://192.168.39.220:30251
$ redis-cli -h 192.168.39.220 -p 30251 info replication
# Replication
role:slave
master_host:service-redis-master.default.svc.cluster.local
master_port:6379
master_link_status:up
master_last_io_seconds_ago:4
master_sync_in_progress:0
slave_repl_offset:17739
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

さいごに

今回はDeploymentとServiceについて勉強しました。

参考URL

このエントリーをはてなブックマークに追加

<前のページ
Kubernetesダッシュボードのインストールからログインまで解説
次のページ>
【Kubernetes】Serviceの各タイプについて解説

関連記事

記事へのコメント