Kuzunoha-NEのブログ

pythonの勉強中。

【kubernetes】SecretとRedisのパスワード設定

こんばんは、葛の葉です。

さて、今回はkubernetesでRedisをデプロイする際のパスワードの設定とSecretの設定方法を記載します。

環境

minikube ver 0.31.0

Redis(image) tag 5.0.3

簡単なRedisのパスワード設定のおさらい

Redisがインストールされている環境であれば、以下のコマンドでパスワードを設定できます。

redis-server --requirepass [password]

コマンドを打つとRedisが起動して、以下のような感じでメッセージが出力されると思います。今回のパスワードは1212です。

root@657cb0734634:/data# redis-server --requirepass 1212
15:C 20 Feb 2019 04:05:48.917 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
15:C 20 Feb 2019 04:05:48.918 # Redis version=5.0.3, bits=64, commit=00000000, modified=0, pid=15, just started
15:C 20 Feb 2019 04:05:48.918 # Configuration loaded
                _._
           _.-``__ ''-._
      _.-``    `.  `_.  ''-._           Redis 5.0.3 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 15
  `-._    `-._  `-./  _.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |           http://redis.io
  `-._    `-._`-.__.-'_.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |
  `-._    `-._`-.__.-'_.-'    _.-'
      `-._    `-.__.-'    _.-'
          `-._        _.-'
              `-.__.-'

15:M 20 Feb 2019 04:05:48.919 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
15:M 20 Feb 2019 04:05:48.920 # Server initialized
15:M 20 Feb 2019 04:05:48.920 * DB loaded from disk: 0.000 seconds
15:M 20 Feb 2019 04:05:48.920 * Ready to accept connections

パスワードが設定されれば、そのRedisに接続したあと、操作を行うにはパスワードが必要になります。例えばredis-cliで接続した際は、auth [password]といった形で認証を得ないといけません。

root@657cb0734634:/data# redis-cli -h 192.168.99.100 -p 6379 
192.168.99.100:6379 > auth 1111
ERR invalid password
192.168.99.100:6379 > auth 1212
OK

ERR invalid passwordと出るとパスワードが間違っています。OKが出てれば接続できます。ここまでがRedisでパスワードを設定する方法とそのRedisに繋げる方法です。

redis.io

KubernetesのSecret

さて、KubernetesのSecretですが、詳細は以下のリンクを見てもらえればと思います。

kubernetes.io

KubernetesではこのSecretというオブジェクトを使ってパスワードを管理したほうが良いようです。先ほどの1212というパスワードを管理するSecretを作成します。

ファイル名test-secret.yaml

apiVersion: v1
kind: Secret
metadata:
    name: redis-password # secretの名称となり、k8s上で使用する名前
type: Opaque
data:
    RedisPassword: MTIxMg== #base64でないと受け付けません。

metadatanameを使って、このSecretをredis-password命名し、Kubernetes内ではこの名前でこのSecretを呼び出します。また、data内にあるRedisPasswordMTIxMg==はKeyとValueになっています。MTIxMg==base641212になります。Keyは複数作ることが出来ますので、一つのSecretに複数のパスワード等を含めることが出来ます。例えばusernamekeyとpasswordkeyを入れるなんてことも出来ます。

kubectl apply -f test-secret.yamlとすれば設定が反映されます。

kubectl get secretとすればSecretが表示されます。

NAME                       TYPE                                  DATA      AGE
default-token-57h4x        kubernetes.io/service-account-token   3         5d
redis-password             Opaque                                1         28m

default-token-57h4xはminikubeのものかなぁと。

Podの設定はこんな感じ

次にKubernetes上でRedisの入ったPodを作成します。今回はSecretの設定はPodで行いますが、DeployMentやStatefulSetでも設定可能です。

ファイル名test-pod.yaml

apiVersion: v1  
kind: Pod
metadata:
  name: test-redis
  labels:
    app: test-redis #ここの値を用いてServiceと連携する
spec:
  containers:
  - name: test-redis-ctr
    image: redis:5.0.3
    env:
    - name: REDIS_PASSWORD # Pod内に挿入する環境変数の名前
      valueFrom:
        secretKeyRef: 
          name: redis-password # 先ほど作成したSecret名
          key: RedisPassword #  先ほど作成したKey名。Valueが環境変数内に代入される。
    command: ["redis-server"]
    args: ["--requirepass $(REDIS_PASSWORD)"]
    ports:
    - containerPort: 6379

yaml内のspec以下にcontainers項目があって、これらが生成するコンテナの詳細に設定する部分になります。-nameはコンテナの名前です。imageはそのPodを作成するに使用するDockerimageを記します。

また、envがあって、これがPod内の環境変数を作成する項目になります。env-name環境変数名です。 valueFromはその環境変数の値を引っ張ってくる設定ファイルがどの形式であるかというもので、Secretを使用する場合はsecretKeyRefとします。configMapKeyRefだとConfigMapというオブジェクトを使用するようになります。nameはSecretの名前を、keyはSecret内dataで記入したkeyであるRedisPasswordにします。

commandはPod生成時に実行されるコマンドで、redis-serverというコマンドを、argsで引数を渡しています。--requirepassは先に説明したとおりで、$(REDIS_PASSWORD)環境変数部分になります。ブランケットの括弧${}ではなくパレンティスの括弧$()なので注意してください。

kubectl apply -f test-pod.yamlで作成しましょう。

kubectl get podsで出来たPodを見られます。

NAME                              READY     STATUS      RESTARTS   AGE
test-redis                        1/1       Running     0          34m

なお、STATUSがErrImagePullといったものであった場合は、Redis:5.0.3のイメージが存在していないので作成できていないというエラーになります。minikubeでしたらdocker pull redis:5.0.3とかやってみてください。

Serviceを使ってみる(minikube)

次にServiceを使って先のPodを確認出来るようにします。

ファイル名test-svc.yaml

apiVersion: v1 # ここも固定。kubernetes側が対応したらVの値を増やす形に
kind: Service metadata:
  name: test-service # Serviceそのものの名前。アンスコが使えない等ルールあり
spec:
  type: NodePort  
  selector:
    app: test-redis 
  ports:
  - port: 6379 
    targetPort: 6379 

Serviceの説明は省きます。kubectl apply -f test-svc.yamlで作成し、kubectl get service (又は"svc")と打って確認しましょう。

NAME                    TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
test-service            NodePort       10.111.68.208   <none>        6379:30271/TCP   38m

CLUSTER-IPPORT(S)のコロン右側の値はそれぞれ異なると思います。

IPアドレスとポート番号を確認する

GKEと違って、minikubeではNodePortタイプ(LoadBalancerタイプも同様)のServiceにEXTERNAL-IPは振られないようです。代わりに、minikubeの下記のコマンドでIPアドレスを確認する必要があります。

minikube service [Service名] --url

kubernetes.io

今回はminikube service test-service --urlです。そうしますと、http://192.168.99.100:30271といった表示が出てくると思います。IPアドレス部分、Port番号部分はそれぞれ異なると思います。

C:\>minikube service test-service --url
http://192.168.99.100:30271

これが今回生成したServiceにアクセスするためのIPアドレスとPort番号になります。

redis-cliでアクセス

下記コマンドを打ちます。

redis-cli -h [IPアドレス] -p [Port番号]

root@kuzunohasan:# redis-cli -h 192.168.99.100 -p 30271
192.168.99.100:30271> get 1
(error) NOAUTH Authentication required.
192.168.99.100:30271> auth 1212
OK
192.168.99.100:30271> get 1
(nil)

最初のget 1(error) NOAUTH Authentication required.と弾かれていますが、auth 1212とした後、get 1とした場合は(nil)とされています。無事成功しています。

綺麗にする

kubectl apply -f ***.yamlで設定したものはkubectl delete -f ***.yamlで削除可能です。

また、applyでもそうですが、ディレクトリを選択すれば、ディレクトリ内のyamlファイル全てを読みに行き、全てを削除してくれます。

C:\>kubectl delete -f test-secret.yaml
secret "redis-password" deleted

C:\>kubectl delete -f test-pod.yaml
pod "test-redis" deleted

C:\>kubectl delete -f test-svc.yaml
service "test-service" deleted

なんでRedisConfでパスワードの設定しないの?

今回のRedisのパスワードの設定はサーバー実行コマンドのオプションを使っていて、confを使った設定は行っていません。なぜならconf内で環境変数を呼び出して取得する方法がなかったからです…シェルスクリプトを使ったらよいかもしれませんね。

github.com