クラウドネイティブのCaaSプラットフォーム

高セキュリティのもとで、

圧倒的なユーザビリティで

マルチクラウドの開発・運用をサポート

  • スピーディーにデプロイ
  • コスト削減
  • 高可用性
  • 優れたスケーラビリティ

5.《一目で分かる K8s 永続的なストレージプロセス》

はじめに:ご存じのとおり、K8sの永続ストレージ(永続ストレージ)は、アプリケーションのデータがアプリケーションのライフサイクルとは独立して存在することを保証しますが、その内部実装についてはほとんど言及されていません。K8sの内部ストレージプロセスとは何でしょうか? PV、PVC、StorageClass、Kubelet、CSIプラグインなどの間の呼び出し関係は何でしょうか。これらの疑問は、この記事でひとつずつ明らかにされます。

K8s 永続的ストレージの基本

K8sストレージプロセスを説明する前に、まずK8sの永続ストレージの基本概念を確認します。

1. 用語集

2. コンポーネント紹介

3. 永続的なボリュームの使用
KubernetesはPVとPVCを導入して、アプリケーションとその開発者が通常ストレージリソースをリクエストし、ストレージファシリティの詳細の処理を回避できるようにしました。PVを作成するには2つの方法があります。

手順1:クラスター管理者がNFS PVを作成します。NFSは、K8sでネイティブにサポートされるツリー内ストレージタイプに属しています。
yaml ファイルは次のとおりです。

apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv
spec:
capacity:
storage: 10Gi
accessModes:
– ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
nfs:
server: 192.168.4.1
path: /nfs_storage

手順2:ユーザーがPVCを作成すると、yamlファイルは次のようになります。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc
spec:
accessModes:
– ReadWriteOnce
resources:
requests:
storage: 10Gi

kubectl get pvコマンドは、PVとPVCがBoundされていることを示しています。

[root@huizhi ~]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
nfs-pvc Bound nfs-pv-no-affinity 10Gi RWO 4s

手順3:ユーザーはアプリケーションを作成し、2番目のステップで作成したPVCを使用します。

apiVersion: v1
kind: Pod
metadata:
name: test-nfs
spec:
containers:
– image: nginx:alpine
imagePullPolicy: IfNotPresent
name: nginx
volumeMounts:
– mountPath: /data
name: nfs-volume
volumes:
– name: nfs-volume
persistentVolumeClaim:
claimName: nfs-pvc

このとき、NFSのリモートストレージはPodのnginxコンテナの/ dataディレクトリにマウントされます。

ストレージボリュームを動的に作成する

ストレージボリュームを動的に作成するには、nfs-client-provisionerと対応するストレージクラスをクラスターにデプロイする必要があります。 静的なストレージボリュームの作成と比較して、ストレージボリュームを動的に作成すると、クラスター管理者の介入が軽減されます。このプロセスを次の図に示します。

クラスター管理者は、環境にNFS関連のストレージクラスがあることを確認するだけで済みます。

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: nfs-sc
provisioner: example.com/nfs
mountOptions:
– vers=4.1

手順1:ユーザーはPVCを作成します。PVCのstorageClassNameは、上記のNFSのstorageclass名として指定されています。

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nfs
annotations:
volume.beta.kubernetes.io/storage-class: “example-nfs”
spec:
accessModes:
– ReadWriteMany
resources:
requests:
storage: 10Mi
storageClassName: nfs-sc

手順2:クラスター内のnfs-client-provisionerは、対応するPVを動的に作成します。この時点で、環境内のPVが作成され、PVCにBoundされていることがわかります。

[root@huizhi ~]# kubectl get pv
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM REASON AGE
pvc-dce84888-7a9d-11e6-b1ee-5254001e0c1b 10Mi RWX Delete Bound default/nfs 4s

手順3:ユーザーはアプリケーションを作成し、ストレージボリュームを静的に作成する3番目のステップと同じように、2番目のステップで作成されたPVCを使用します。

K8s 永続的なストレージプロセス

1. プロセスの概要
ここから学ぶ@郡宝 クラウドネイティブストレージコースの中のフローチャート です。

フローは以下の通りです。

  1. ユーザーは、動的ストレージボリュームを必要とするPVCを含むPodを作成します。
  2. Schedulerは、Pod構成、ノードのステータス、PV構成、およびその他の情報に基づいて、Podを適切なWorkerノードにスケジュールします。
  3. PVコントローラーは、Podが使用するPVCがPending状態であることを監視するため、ボリュームプラグイン(ツリー内)を呼び出してストレージボリュームを作成し、PVオブジェクトを作成します(ツリー外は外部プロビジョナーによって処理されます)。
  4. ADコントローラーは、PodとPVCが保留状態であることを検出するため、ボリュームプラグインを呼び出して、ストレージデバイスをターゲットWorkerノードにマウントします。
  5. Workerノードで、Kubeletのボリュームマネージャーはストレージデバイスがマウントされるのを待ち、ボリュームプラグインを介してデバイスをグローバルディレクトリにマウントします:/ var / lib / kubelet / pods / [pod uid] /volumes/kubernetes.io 〜iscsi / [PV名](例としてiscsiを使用)。
  6. KubeletはDockerを介してPodのコンテナを起動し、bind mountを使用して、ローカルグローバルディレクトリにマウントされているボリュームをコンテナにマップします。
    さらに詳細なフローは以下の通りです。

2. プロセス詳細
K8sのバージョンにより、永続的なストレージプロセスが少し異なります。この記事は、Kubernetesバージョン1.14.8に基づいています。

上記のフローチャートからわかるように、ストレージボリュームは作成からアプリケーション使用までの3つの段階に分かれています。
Provision/Delete、Attach/Detach、Mount/Unmount。
provisioning volumes

PVコントローラーには2つのWorkerがあります。

KubeletコンポーネントとADコントローラーの両方がアタッチ/デタッチ操作を実行できます。Kubeletの起動パラメーターで–enable-controller-attach-detachが指定されている場合、Kubeletはそれを実行します。それ以外の場合、ADはデフォルトでそれを実行します。 アタッチ/デタッチ操作を説明するために、例としてADコントローラーを取り上げます。

ADコントローラーには2つのコア変数があります

Volume Managerには2つのコア変数もあります。

  1. Remove all bind-mounts:UnmounterのTearDownインターフェースを呼び出します(ツリー外の場合は、CSIプラグインのNodeUnpublishVolumeインターフェースを呼び出します)。
  2. Unmount volume:DeviceUnmounterのUnmountDevice関数を呼び出します(ツリー外の場合は、CSIプラグインのNodeUnstageVolumeインターフェースを呼び出します)。
  3. ASWを更新します。
    mountAttachVolumes:Podで使用されるボリュームが正常にマウントされていることを確認します。 DSW内のすべてのPodを反復処理し、それがASW内にない場合(ディレクトリがマウントされ、Podにマップされることを示す)、ここでは例としてVolumeMode = FileSystemを使用し、次の操作を実行します。
  4. ボリュームがノードに接続されるのを待ちます(External AttacherまたはKubelet本体によって接続されます)。
  5. ボリュームをグローバルディレクトリにマウントします。DeviceMounterのMountDevice関数を呼び出します(ツリー外の場合は、CSIプラグインのNodeStageVolumeインターフェースを呼び出します)。
  6. ASWを更新します。ボリュームはグローバルディレクトリにマウントされています。
  7. volume を Pod にbind-mountします。 MounterのSetUpインターフェースを呼び出します(それがツリー外の場合は、CSIプラグインのNodePublishVolumeインターフェースを呼び出します)。
  8. ASWを更新します。
    unmountDetachDevices:アンマウントする必要があるボリュームがアンマウントされていることを確認してください。すべてのASWでUnmountedVolumeを反復処理し、DSWにない場合(ボリュームが不要になったことを示す)、次の操作を実行します。
  9. Unmount volume:DeviceUnmounterのUnmountDevice関数を呼び出します(ツリー外の場合は、CSIプラグインのNodeUnstageVolumeインターフェースを呼び出します)。
  10. ASWを更新します。

まとめ

この記事では、まずK8s永続ストレージの基本的な概念と使用方法を紹介し、K8sの内部ストレージプロセスを深く分析しました。K8sでは、あらゆる種類のストレージの使用は上記プロセスと切り離せません(一部のシナリオではアタッチ/デタッチを使用しません)。また、同環境のストレージに問題がある場合は、リンクの1つに障害があるはずです。
特にプロプラエタリーな独自のクラウド環境では、コンテナストレージに多くの落とし穴があります。しかし、課題が増えるほど、チャンスも増えます!現在、中国国内のプロプライエタリクラウド市場もストレージ分野のリーダーであり、私達PaaSコンテナチームは、皆さんが一緒に未来を創造するために私達に加わることを歓迎しています!