5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Kubernetes でデータ保存

Posted at

Kubernetes でデータを保存する仕組みが難しかったのでまとめました。Kubernetes では、ロードバランサーの背後にコンテナを複数立ち上げて、一つのコンテナが落ちても勝手に復旧する一人データセンターみたいな事が簡単に手元の開発機で実現出来ます。コンテナの入れ物である Pod は使い捨てなので、データをとっておく事が出来ません。データを保存するにはちょっと工夫が必要です。

また、ストレージの機構は本番サーバで利用するサービスによってもまちまちなので、アプリから見てストレージの詳細を隠蔽するような仕組みも必要です。とりあえずサンプルコードです。

# sticky.yaml

apiVersion: v1
kind: Service
metadata:
  name: sticky
  labels:
    app: sticky
spec:
  type: LoadBalancer
  ports:
  - name: web
    port: 3333
    targetPort: 80
  selector:
    app: sticky

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: sticky
spec:
  serviceName: sticky
  replicas: 3
  selector:
    matchLabels:
      app: sticky
  template:
    metadata:
      labels:
        app: sticky
    spec:
      containers:
      - name: nginx
        image: k8s.gcr.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: sticky-data # マウントしたいボリュームの名前
          mountPath: /usr/share/nginx/html # コンテナからみたストレージの位置
  volumeClaimTemplates:
  - metadata:
      name: sticky-data # ボリュームの名前
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

実行方法は以下です。

kubectl apply -f https://gist.github.com/propella/ba888509001a1e12ffe91227350fff1a/raw/b6c0fd530f7852cd4b4863ceebe85b9d8c06a833/sticky.yaml

--- の前半は LoadBalancer の定義なので気にしなくていいです。ブラウザから http://localhost:3333 で見るために使います。

後半の StatefulSet で複数の Pod を作りそれぞれ nginx を起動させます。nginx から見た /usr/share/nginx/html がストレージです。現在まだ何もストレージに置かれていないので、ブラウザでアクセスすると 403 Forbidden が表示されるはずです。

ランダムな名前の Pod を生成する Deployment や ReplicaSet とは違って、StatefulSet は順番に安定した名前を付けます。

$ kubectl get pods
NAME       READY     STATUS    RESTARTS   AGE
sticky-0   1/1       Running   0          4m
sticky-1   1/1       Running   0          4m
sticky-2   1/1       Running   0          3m

sticky-2 の /usr/share/nginx/html/index.html に何か書き込んでみます。

kubectl exec sticky-2 -- sh -c 'echo hello > /usr/share/nginx/html/index.html'

Pod が全部で三個あるので、三回に一度程度 hello が表示されるはずです。

$ curl http://localhost:3333/
hello

ここで、おもむろに Pod を全部消してしまいます!

$ kubectl delete pod -l app=sticky

当然 http://localhost:3333/ は反応しなくなりますが

$ curl http://localhost:3333/
curl: (52) Empty reply from server

Service のおかげで勝手に復旧します。また、通常コンテナが再起動すると古い内容は消えてしまうのですが、sticky-2 の /usr/share/nginx/html/ だけはホストに保存されているので、そのうち hello も返ってくるようになります。

$ curl http://localhost:3333/
hello

ちなみに、このファイルの実体はどこにあるかと言うと、まず kubectl get persistentvolumeclaim で sticky-data-sticky-2 に対応するボリュームを探して

$ kubectl get persistentvolumeclaim 
NAME                   STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
sticky-data-sticky-0   Bound     pvc-30ca019d-b1ab-11e8-9055-025000000001   1Gi        RWO            hostpath       16m
sticky-data-sticky-1   Bound     pvc-3aa2bc34-b1ab-11e8-9055-025000000001   1Gi        RWO            hostpath       16m
sticky-data-sticky-2   Bound     pvc-44f72ce0-b1ab-11e8-9055-025000000001   1Gi        RWO            hostpath       16m

kubectl describe persistentvolume で詳細を表示させると出てきます。

$ kubectl describe persistentvolume pvc-44f72ce0-b1ab-11e8-9055-025000000001 
Name:            pvc-44f72ce0-b1ab-11e8-9055-025000000001
...
    Path:          /Users/tyamamiya/.docker/Volumes/sticky-data-sticky-2/pvc-44f72ce0-b1ab-11e8-9055-025000000001

ためしにホスト側からファイルを変えてみます。

$ echo byebye > /Users/tyamamiya/.docker/Volumes/sticky-data-sticky-2/pvc-44f72ce0-b1ab-11e8-9055-025000000001/index.html 
$ curl http://localhost:3333/
byebye

仕組み

ここまで全く仕組みについて触れずに動作を紹介しましたが、使われている概念について書きます。

  • PersistentVolumeClaims
    • このサンプルでは volumeClaimTemplates: の中で作成しました。
    • Pod から見て、ここにこういうストレージがほしいと要求する物です。
  • Persistent Volumes
    • ストレージの実体です。
    • このサンプルでは自動的に生成されます。
    • node のようにクラスタ側であらかじめ作っておく事も出来ます。
  • Storage Classes
    • GCP や AWS などのプロバイダによって異なるストレージの種類を示します。
    • この例ではデフォルトの hostpath (ホストの適当な場所に置かれる) が選択されます。hotpath はデバッグ目的なので実用には向かないです。

ようするに、ストレージの定義を PersistentVolumeClaims と PersistentVolume に分割する事によってストレージの違いを吸収出来るというのが味噌です。開発時には hostpath で作っておいて本番は AWS EBS を使うというような事が出来ます。

参考

5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?