この記事では Azure Kubernetes Services (AKS) を使用して Kubernetes に SQL Server コンテナーを配置する を深堀します。既に AKS チュートリアルの深堀 で紹介した内容についての理解がある前提とします。
今回はまずストレージの作成についてみていきます。次回シークレットの作成や SQL Server 2017 の配置を行います。
データの保存場所について
ポッドが作成される場合、コンテナは毎回イメージからインスタンスを作成するため、ローカルに保存していたデータはすべて消えます。そのためストレージは別途用意します。
ポッドと同じライフサイクルのボリューム
ライフサイクルがポッドと同じ場合、ポッドがスケールダウンや再起動などで再作成された際、データが失われます。早速動作を確認しましょう。
1. Redis のイメージに対して、emptyDir と呼ばれる一時領域をマウントするマニフェストを作成。ここではファイル名を volume-test.yaml とした。
- volumes にて emptyDir を指定
- containers.volumeMount にてボリュームを /cache にマウント
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: volume-test
spec:
replicas: 1
template:
metadata:
labels:
app: volume-test
spec:
nodeSelector:
"beta.kubernetes.io/os": linux
containers:
- name: volume-test
image: redis
ports:
- containerPort: 6379
name: redis
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
2. マニフェストを適用してポッドを展開
> kubectl apply -f .\volume-test.yaml
3. ポッドにアタッチして、フォルダとファイルを作成。
> kubectl get pods -l app=volume-test
NAME READY STATUS RESTARTS AGE
volume-test-6d9595775d-kwqxx 1/1 Running 0 31s
> kubectl exec -it volume-test-6d9595775d-kwqxx /bin/bash
root@volume-test-6d9595775d-kwqxx:/data# mkdir mydata
root@volume-test-6d9595775d-kwqxx:/data# echo hello > mydata/test.txt
root@volume-test-6d9595775d-kwqxx:/data# cat mydata/test.txt
hello
root@volume-test-6d9595775d-kwqxx:/data# exit
4. ポッドを削除。
> kubectl delete pods volume-test-6d9595775d-kwqxx
pod "volume-test-6d9595775d-kwqxx" deleted
5. レプリカセットによって自動で再作成されるので、確認して再度アタッチ。先ほどのフォルダもファイルも存在しないことを確認。
> kubectl get pods -l app=volume-test
NAME READY STATUS RESTARTS AGE
volume-test-6d9595775d-rtqrq 1/1 Running 0 17s
> kubectl exec -it volume-test-6d9595775d-rtqrq /bin/bash
root@volume-test-6d9595775d-rtqrq:/data# cat mydata/test.txt
cat: mydata/test.txt: No such file or directory
6. デプロイメントを削除。
kubectl delete deployments -l app=volume-test
これでポッドを再作成するとデータが消えることがわかりました。
永続ボリューム
データベースのように書き出したデータはポッドの再起動に関係なく維持したい場合、永続ボリュームを使います。これによりポッドとストレージを分離し、ポッド起動時に同じ永続ボリュームにアタッチすることでデータの維持ができます。
AKS では永続ボリュームとして以下のサービスが利用できます。
- Azure ディスク : 1 つのポッドのみがアクセスする場合
- Azure Files : 複数のポッドからアクセスする場合
ストレージクラスと永続ボリューム要求
永続ボリュームは、ストレージクラスと永続ボリューム要求の組み合わせて設定します。
- ストレージの種類を決めるストレージクラスを作成
- 永続ボリュームの容量など要求を決める、永続ボリューム要求を作成、ポッドに関連付け
- ポッド要求時、永続ボリュームを作成して割り当て
永続ボリューム要求と永続ボリューム
上記で説明した通り永続ボリューム要求と永続ボリュームは 1 対 1 の関係ですが、ポッドに紐づく永続ボリューム要求を削除した場合、永続ボリュームも削除するかは、ReclaimPolicy で決めることができます。ReclaimPolicy を含めたストレージに関するパラメーターはストレーククラスから引き継ぎます。
このチュートリアルでは Azure ディスクを使います。
ボリュームとは
k8s におけるボリュームは、ポッド内のコンテナがデータを読み書きできるディスク領域で、ポッドに紐づきます。ボリュームには様々な種類や用途があります。
- ポッド内のコンテナが利用するデータの一時領域
- ポッド内の複数コンテナでのデータ共有
- ボリュームを通したアプリケーション設定やシークレットの割り当て
- ポッドが削除されると同時に削除される領域
- ポッドの削除時でもデータを永続化する領域
高可用性
SQL 本体にも Always On などの HA 機能がありますが、このチュートリアルでは k8s のレプリカセットによるポッドの自動復旧機能を使っています。障害発生時のイメージは以下の通りです。
1. あるノードに展開された SQL ポッドが永続ボリュームに接続している。
2. ポッドが落ちた場合は、レプリカセットによって新規ポッドが展開されるが、同じ永続ボリュームにアタッチするため継続してサービスできる。
3. ノードが落ちた場合も、レプリカセットによって他のノードにポッドが展開されるが、同じ永続ボリュームにアタッチするため継続してサービスできる。
チュートリアルの深堀
今回はチュートリアルのうち、ストレージに関わる部分の作業を見ていきます。
またチュートリアルでは Standard ディスクを使っていますが、SQL は高速はディスクが通常必要なため、ここでは Premium を使っています。
ストレージを作成する
この手順では永続ボリュームと永続ボリューム要求を構成しています。またストレージクラスを使った動的作成を利用しているため、事前に Azure 側で Azure ディスクを用意する必要はありません。
1. ストレージクラスおよび永続ボリューム要求を展開する yaml を mssql-storage.yaml として作成。
- 前半はストレージクラス (StorageClass) 用。名前は azure-disk
- provisioner: ストレージ作成の実行サービス。ここでは Azure Disk を指定
- parameter: provisioner に渡すパラメータを指定。ストレージの種類をして Premium_LRS を指定
- ReclaimPolicy の設定がないため、既定の Delete が適用
- 後半は永続ボリューム要求 (PersistentVolumeClaim) 用。名前は mssql-data
- annotations: ストレージクラスとして azure-disk を指定
- spec: ボリュームに対するアクセス。ここでは ReadWriteOnce のため 1 ポッドからのみ読み書き。また容量として 8GB を指定
kind: StorageClass
apiVersion: storage.k8s.io/v1beta1
metadata:
name: azure-disk
provisioner: kubernetes.io/azure-disk
parameters:
storageaccounttype: Premium_LRS
kind: Managed
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: mssql-data
annotations:
volume.beta.kubernetes.io/storage-class: azure-disk
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 8Gi
2. apply
で yaml を適用。
kubectl apply -f mssql-storage.yaml
3. 作成された永続ボリューム要求を確認。
- pvc: persistentvolumeclaims の省略形
> kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mssql-data Bound pvc-49cbb6c9-e0f8-11e9-869b-d2cecd57d4bb 8Gi RWO azure-disk 118s
4. describe
で詳細確認。
- Volume として pvc-9021c795-e0dd-11e9-869b-d2cecd57d4bb が割り当てらている
> kubectl describe pvc mssql-data Name: mssql-data
Namespace: default
StorageClass: azure-disk
Status: Bound
Volume: pvc-49cbb6c9-e0f8-11e9-869b-d2cecd57d4bb
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"PersistentVolumeClaim","metadata":{"annotations":{"volume.beta.kubernetes.io/storage-class":"azure-disk"},"name...
pv.kubernetes.io/bind-completed: yes
pv.kubernetes.io/bound-by-controller: yes
volume.beta.kubernetes.io/storage-class: azure-disk
volume.beta.kubernetes.io/storage-provisioner: kubernetes.io/azure-disk
Finalizers: [kubernetes.io/pvc-protection]
Capacity: 8Gi
Access Modes: RWO
VolumeMode: Filesystem
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ProvisioningSucceeded 2m27s persistentvolume-controller Successfully provisioned volume pvc-49cbb6c9-e0f8-11e9-869b-d2cecd57d4bb using kubernetes.io/azure-disk
Mounted By: mssql-deployment-5b74bdb6f7-tqz8q
5. 上記結果より割り当てられている Volume が「pvc-49cbb6c9-e0f8-11e9-869b-d2cecd57d4bb」となっているが、Azure 側に同名の Azure ディスクが作成されている。
6. ストレージクラスを確認。今回作成したもの以外に、既定のもの存在。
- sc: storageclass の省略形
> kubectl get sc -o wide
NAME PROVISIONER AGE
azure-disk kubernetes.io/azure-disk 17m
default (default) kubernetes.io/azure-disk 31h
managed-premium kubernetes.io/azure-disk 31h
7. describe
で詳細確認。
- ReclaimPolicy が Delete
> kubectl describe sc azure-disk
Name: azure-disk
IsDefaultClass: No
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"storage.k8s.io/v1beta1","kind":"StorageClass","metadata":{"annotations":{},"name":"azure-disk"},"parameters":{"kind":"Managed","storageaccounttype":"Premium_LRS"},"provisioner":"kubernetes.io/azure-disk"}
Provisioner: kubernetes.io/azure-disk
Parameters: kind=Managed,storageaccounttype=Premium_LRS
AllowVolumeExpansion: <unset>
MountOptions: <none>
ReclaimPolicy: Delete
VolumeBindingMode: Immediate
Events: <none>
8. 永続ボリューム要求とセットで作成される永続ボリュームを確認。
- pv: persistentvolume の省略形
- Reclaim Policy: ストレージクラスから継承。永続ボリューム要求が削除された場合の永続ボリュームの挙動。ここでは Delete のため一緒に削除される
> kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-49cbb6c9-e0f8-11e9-869b-d2cecd57d4bb 8Gi RWO Delete Bound default/mssql-data azure-disk 5m
これでディスクの準備は完了です。
動作の深堀
では実際に永続ボリューム要求を消したらどうなるか試してみましょう。
1. 以下コマンドで永続ボリューム要求を削除。
kubectl delete pvc mssql-data
2. 永続ボリュームが削除されていることを確認。
> kubectl get pv
No resources found.
要求が消えると関連するボリュームも消えることが確認できました。次のステップのために再度要求を作成します。
4. yaml を適用。
kubectl apply -f .\mssql-storage.yaml
まとめ
基本的なポッドの性質として、ファイルの作成や変更は永続ボリュームがないと維持できない事と、動的にストレージを作成できることがわかりました。
ボリュームは動的以外にも静的に割り当てることもでますし、複数ポッドから同じボリュームにアクセスしたい場合は Azure Files を使うなど、まだまだ他のオプションもありますが、これらはまたの機会に紹介します。
参照
Azure で利用できるディスクの種類
[Azure Kubernetes Service (AKS) でのアプリケーションのストレージ オプション]
(https://docs.microsoft.com/ja-jp/azure/aks/concepts-storage)
Persistent Volumes