本セクションで学習すること #
- PV とPVC によるデータの永続化
- データベースとの接続のための環境変数とSecret リソース
ストレージの基本 #
繰り返しになりますが、Pod は短命です。Pod は簡単に削除されるため、データを残したい場合は何かしらの形で外部に保存する仕組みが必要です。その1 つがPersistent Volume (PV)になります。
PV はその名の通り永続ストレージであり、PV の中にデータを保存することができます。PV をPod に割り当てるにはいくつか方法がありますが、代表的なものとしてPersistent Volume Claim (PVC) を使う方法があります。PVC はPV を要求するために使われるリソースであり、そのマニフェストの中には例えば要求するストレージのサイズなどが定義されます。Pod がデータを保存するためにPV を使いたい場合は、直接PV をアタッチするのではなく、PVC をアタッチします。
物理ストレージをKubernetes 用に抽象化したものがPVで、それをPod にアタッチするためにPVC が使われます。
PVC のマニフェストを見てみましょう。
cat ~/database/persistentvolumeclaim.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: blog-media
labels:
app: blog
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
ここでは、ストレージのサイズは少なくとも1Giで、アクセスモードはReadWriteOnce である必要があります。アクセスモードとは、払い出すPV がどのようにRead/Write されうるかを示しており、以下の4 つがあります。
- ReadWriteOnce(RWO) - 単一のノードからRead/Write 可能としてボリュームをマウントします。
- ReadOnlyMany (ROX) - 複数のノードによって読み取り専用としてボリュームをマウントします。
- ReadWriteMany (RWX) - 複数のノードによってRead/Write 可能としてボリュームをマウントします。
- ReadWriteOncePod (RWOP) - 単一のPod からRead/Write 可能としてボリュームをマウントします。
なお、使用するKubernetes クラスタによってはRWX が使えないなどの制約があります。
RWO, ROX, RWX のアクセス元はいずれも"ノード"であることに注意してください。すなわち、RWO を選択したとしても、複数のPod が同一ノード上で稼働していれば、そのPV にはアクセスが可能です。
既に作成したデータベースのマニフェストを見てみましょう。
cat ~/database/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: blog-db
labels:
app: blog-db
spec:
...
template:
...
spec:
containers:
...
volumeMounts:
- name: data
mountPath: "/var/lib/pgsql/data"
volumes:
- name: data
persistentVolumeClaim:
claimName: blog-database
spec.template.spec.volumes に使用するPVC のリソースオブジェクト名が記載され、その請求されるPV がdata と名付けられ、さらにそれがspec.template.spec.containers[*].volumeMounts にてコンテナのパス/var/lib/pgsql/data にマウントされていることが分かります。
フロントのWeb サーバーにもPV がマウントされていますが、これはブログの記事ではなく画像を保存するためのものです。
補足
データベースとの接続 #
フロントエンドのWebアプリケーションが動作しており、インターネットからアクセスできます。データの永続性を確保し、アプリケーションのすべてのインスタンスで同じデータベースを使用するために、フロントエンドのWebアプリケーションでは、すでに稼働しているPostgresql データベースを使用するように設定されています。
データベースのリソースを表示するには、以下を実行します。
kubectl get deployment,service,pvc,secret -l app=blog-db -o name
deployment.apps/blog-db
service/blog-db
persistentvolumeclaim/blog-database
secret/blog-credentials
Deployment とService、PVC の目的は先に説明した通りです。 Secret はデータベースの認証情報を保持するために使用されます。
データベースをフロントエンドのWeb アプリケーションにリンクさせるためには、Web アプリケーションにデータベースのホスト名とログイン認証情報を伝える必要があります。いくつか方法がありますが、まずは環境変数でパラメータを渡す方法を見てみます。
環境変数 #
フロントエンドWebアプリケーションにどのような環境変数がすでに設定されているかは、次のように実行すればわかります。
kubectl set env deployment/blog --list
以下のように表示されるはずです。
#Deployment blog, container blog
BLOG_SITE_NAME=EduK8S Blog
DATABASE_HOST=blog-db
#DATABASE_USER from secret blog-credentials, key database-user
#DATABASE_PASSWORD from secret blog-credentials, key database-password
#DATABASE_NAME from secret blog-credentials, key database-name
Pod 中のすべての環境変数を確認したい場合は以下のように実行することもできます。
DB=`kubectl get pod -l app=blog-db -o template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}'. | head -1`
kubectl exec $DB -- env
Web アプリケーションのDeployment のマニフェストを確認すると、環境変数が定義されていることが分かります。
cat ~/frontend/deployment.yaml
spec:
containers:
- env:
- name: BLOG_SITE_NAME
value: EduK8S Blog
- name: DATABASE_HOST
value: blog-db
この場合は、ブログ名や接続するService 名を記載しています。my-svc.my-namespace.svc.cluster-domain.example のように厳密に記載することもできますが、このように省略することもできます。
Secret #
データベースの認証情報も同様にマニフェストに直接環境変数を書き込んで追加することができますが、Deployment のマニフェストとは別に管理するために、Secret を使うことが一般的です。このWeb アプリケーションでは、blog-credentialsというシークレットを見ることができます。
kubectl get secret/blog-credentials -o yaml
出力の中では、data セクションに値が入っているのがわかります。
data:
database-name: YmxvZw==
database-password: dG9wLXNlY3JldA==
database-user: YmxvZw==
表示されているのは、base64 エンコーディングで難読化されているため、実際の値ではありません。なお、デコードすると以下のようになります。
echo dG9wLXNlY3JldA== | base64 -d
top-secret
このSecret をファイルとしてコンテナに渡すこともできますが、この例ではSecret の値をPod の環境変数として注入していることに注意してください。
やや込み入った内容ですが、どのデータベースにどのようにアクセスすべきか、環境変数やSecret といった方法を使って、フロントエンドのWeb アプリケーションに伝えることができたということを押さえれば十分です。