狠狠撸
Submit Search
Container Storage Interface のすべて
?
1 like
?
9,267 views
祐司 伊藤
Follow
KubeFest Tokyo 2020 発表資料
Read less
Read more
1 of 41
Download now
Downloaded 28 times
More Related Content
Container Storage Interface のすべて
1.
Container Storage Interface のすべて KubeFest
Tokyo 2020 2020/06/13 サイボウズ株式会社 Yuji Ito
2.
自己紹介 ▌伊藤祐司 ? 分散システムにかかわる仕事がしたく、2019年10月 からNecoチームでデータセンタの開発に参画している。 ▌サイボウズ株式会社 Necoチーム ?
自社データセンタに1000ノード規模のKubernetes クラスタを構築する。 ? ストレージ専従ではなく、約1ヵ月ごとに班を変えながら 満遍なく知識を蓄える。 2
3.
本発表の目的 ▌Container Storage Interface
(CSI) について知ってもらう。 ? 概要 ? どのような機能が実装可能なのか ▌CSIドライバの開発を行うための情報を提供する。 ? CSIドライバの開発方法 ? CSIドライバのテスト方法 3
4.
発表の流れ ▌PV, PVC, SC
のおさらい ▌CSIの概要 ▌CSI?CSIドライバの構造 ▌最小限のCSIドライバの実装 ▌CSIドライバのテスト ▌オプション機能の拡張方法 ▌ドキュメント?参考情報 ▌まとめ 4
5.
metadata: name: pv01 spec: capacity: ... storageClassName:
sc01 PV: Persistent Volume metadata: name: sc01 provisioner: ... parameters: ... SC: Storage Class metadata: name: pvc01 spec: resources: ... storageClassName: sc01 PVC: Persistent Volume Claim PV, PVC, SC のおさらい 5 metadata: name: pod01 spec: containers: volumes: - name: volume01 persistentVolumeClaim: claimName: pvc01 1. PodおよびPodが利用する volumeをPVCとして定義 0. (前準備) SCでPVをグループ分け することが可能 ストレージ システム 2. Podから利用可能なvolume (ファイルシステムまたはRawブロックデバイス) ごとにPVを定義し、関連付ける 4. PVCに関連付けられた PVのvolumeを用い、 Podが起動 3. PVCで定義した条件に マッチするPVがPVCに 関連付けられる
6.
CSIの概要 6
7.
CSIの定義に 従った拡張 CSIとはなんなのか ▌各種Container Orchestrators (CO)において、 ストレージ機能を拡張するための 統一されたインタフェース。 ▌PVCの変更に対し、PV?スト レージを自動で作成?拡張?削 除するなどの仕組みを追加可能。 7 ストレージ システム CSIドライバ K8s CSI
sidecar container 開発対象となるCSIドライバはKubernetesから 独立しており (out of tree) 誰でも開発可能 監視 作成?変更 操作 Kubernetes プロジェクトから 提供されている CSIで定義されたgRPC Kubernetesに絞って説明
8.
CSI関連の用語 ▌Volume CSIを通して利用可能になるストレージの単位。ファイルシステムまたはブロックデバイ スのこと。 KubernetesのPVから指示される実際に利用可能な領域に対応。 ▌CSIドライバ /
CSIDriver オブジェクト CSIドライバ: CSIを利用するドライバ全体。 CSIDriver: KubernetesにCSIの情報を渡すためのオブジェクト。 ▌Node Plugin 各KubernetesのNode上で動く、CSIドライバのプログラム及びコンテナ。 8
9.
CSIを利用して実現できる機能 ▌ファイルシステム, Rawブロックデバイスを扱う。 ▌PVCの作成?削除に対応し、PV?ストレージを自動で割当て、削除する。 - Dynamic
Provisioning ▌PVCで定義される容量の変更に対応し、ストレージを拡張する。 - Volume Expansion ▌Podの終了とともに開放される短期的な領域の割り当て。 9
10.
CSIを利用して実現できる機能 (続き) ▌既存のPVをコピーしたPVを作成する。 ▌PVのSnapshotを作成し、それをコピーしたPVを作成する。 ▌ストレージシステムが利用できるRackやRegionが制限される場合に、 その状態に応じてPodを作る場所を制御する。 10 CSIドライバを開発することで、前述のような機能を Kubernetesクラスタのサービスとして提供可能
11.
CSI?CSIドライバの構造 11
12.
CSIドライバに関連する主な要素 12 CSIDriver (Object) 当該CSIドライバの存在と機能をKubernetes に伝える Controller
Plugin の Pod (Deployment/StatefulSet) Node Plugin の Pod (DaemonSet) Controller Plugin コンテナ ? Controller サービス ? Identity サービス K8s CSI の sidecar コンテナ Node Plugin コンテナ ? Node サービス ? Identity サービス Kubernetes プロジェクトから 提供されている K8s CSI の sidecar コンテナ Kubernetes プロジェクトから 提供されている Kubernetes プロジェクトから 提供されている 開発対象
13.
apiVersion: v1 kind: Pod metadata: name:
pod-name spec: containers: - image: container1:latest name: container-1 volumeMounts: - mountPath: /mnt/share name: shared-volume - image: container2:latest name: container-2 volumeMounts: - mountPath: /mnt/share name: shared-volume volumes: - name: shared-volume emptyDir: {} sidecarのおさらい ▌複数のコンテナを内包するPod ▌コンテナ間で、Volumeの共有や Volume内の Unix Domain Socket (USD) を利用した通信 が可能 13 Pod Container#2Container#1 Container#1 Container#2 Volume
14.
Kubernetesプロジェクトから提供される主要な CSI sidecar ▌external-provisioner Dynamic
Provisioning 機能を提供する場合に利用する。 ▌livenessprobe CSIドライバの状態を Kubernetes に伝えるため、 Readiness Probe 機能と連 携する。 ▌node-driver-registrar Kubernetes がNodeを認識するための CSINode オブジェクトを作成する。 14
15.
Kubernetes の Node CSIに関するコンポーネントの連携 15 Controller
Plugin の Pod (Deployment/StatefulSet) Controller Plugin コンテナ ? Controller サービス ? Identity サービス K8s CSI の sidecar コンテナ Node Plugin の Pod (DaemonSet) Node Plugin コンテナ ? Node サービス ? Identity サービス K8s CSI の sidecar コンテナ API Server gRPC Unix Domain Socket gRPC Unix Domain Socket Kubelet Volume Volume詳しくは、CSI Volume Plugins in Kubernetes Design Doc を参照 作成 利用
16.
最小限のCSIドライバの実装 16
17.
CSIのspecについて ▌CSIドライバが実装するプロシージャの 細かい仕様が記載されている。 ? 引数の内容 ? 期待する戻り値 ?
エラー時の戻り値 ▌https://github.com/ container-storage-interface/ spec/blob/master/spec.md 17
18.
最小限のCSIドライバの状態遷移 ▌host pathを用意するだけの最小限のCSIドライバを例示する。 ▌構成要素はNodeサービスとIdentityサービスだけ。 18 Podの起動準備 完了 PUBLISHED NodePublishVolume プロシージャの呼び出し NodeUnpublishVolumeプロシージャの呼び出し この時点でPodが動作する Podの削除処理がトリガになる
19.
サービスのスケルトンを生成 ▌各gRPCサービス用のコードを生成。 ? gRPCの定義は以下のリポジトリで公開されている。 https://github.com/container-storage- interface/spec/blob/master/csi.proto ? 言語について制限は無いが、Kubernetesの機能を利用する場合、ライブラリが 充実しているgo言語が無難。 19 ##
protocコマンドをダウンロード?展開しておく ## csi.protoフィルをダウンロードしておく GO111MODULE=on go get github.com/golang/protobuf/protoc-gen-go protoc -I=. --go_out=plugins=grpc:. csi.proto
20.
生成されたスケルトンについて ▌csi.pb.goが生成される ▌Identity, Controller, Node
の各サービスで実装するべきプロシー ジャが定義されている。 20 type IdentityServer interface { GetPluginInfo(context.Context, *GetPluginInfoRequest) (*GetPluginInfoResponse, error) ... type ControllerServer interface { CreateVolume(context.Context, *CreateVolumeRequest) (*CreateVolumeResponse, error) ... type NodeServer interface { NodeStageVolume(context.Context, *NodeStageVolumeRequest) (*NodeStageVolumeResponse, ... ...
21.
ドライバが提供する機能とcapability ▌CSIドライバで提供したい機能に応じて実装するgRPCメソッドは異なる。 ▌gRPCのAPIを通じて、ドライバ?コンポーネントが提供する機能を Kubernetes や CSI
sidecar に伝える。 ? GetPluginCapabilities (Identityサービス) ? ControllerGetCapabilities (Controllerサービス) ? NodeGetCapabilities (Nodeサービス) 21
22.
func (ns *nodeServer)
NodeGetCapabilities(ctx context.Context, req *csi.NodeGetCapabilitiesRequest) (*csi.NodeGetCapabilitiesResponse, error) { return &csi.NodeGetCapabilitiesResponse{ Capabilities: []*csi.NodeServiceCapability{ { Type: &csi.NodeServiceCapability_Rpc{ Rpc: &csi.NodeServiceCapability_RPC{ Type: csi.NodeServiceCapability_RPC_STAGE_UNSTAGE_VOLUME, }, }, }, ... }, }, nil } Capabilityの設定例 22https://github.com/kubernetes-csi/csi-driver-host-path/blob/v1.3.0/pkg/hostpath/nodeserver.go#L279-L299 CSIドライバで提供する機能に応じ、 capabilityを列挙する
23.
NodePublishVolumeの例 ▌領域をPodが利用可能な状態にする。 ? ファイルシステムの場合、指定されたpathにファイルシステムをマウントする。 ? Rawブロックデバイスの場合、指定されたpathにデバイスファイルを用意する。 23 targetPath
:= req.GetTargetPath() ... if req.GetVolumeCapability().GetBlock() != nil { ... loopDevice, err := volPathHandler.GetLoopDevice(vol.VolPath) ... mount.New("").Mount(loopDevice, targetPath, "", options) ... } ... return &csi.NodePublishVolumeResponse{}, nil https://github.com/kubernetes-csi/csi-driver-host-path/blob/v1.3.0/pkg/hostpath/nodeserver.go#L50-L189 loop deviceを作成している 引数で渡された場所に loop device をマウントしている
24.
プロシージャ実装時の注意点 ▌CSIプロシージャは冪等性を満たすように実装する必要がある。 ? Kubernetes 側でプロシージャの成否を取得できなかった場合などに、再度プロ シージャを呼び出すことを許容するため。 ?
capacityやparameterが許容可能であれば、正常終了のレスポンスを返す。 24
25.
CSIDriverの例 ▌CSIドライバの存在と機能を Kubernetes に伝える 25 apiVersion:
storage.k8s.io/v1beta1 kind: CSIDriver metadata: name: topolvm.cybozu.com spec: attachRequired: true podInfoOnMount: true volumeLifecycleModes: - Persistent - Ephemeral 該当CSIドライバが提供している機能についての定義 https://github.com/cybozu-go/topolvm/blob/v0.4.8/deploy/manifests/controller.yaml#L2-L11 該当CSIドライバが Kubernetes に要求する 挙動についての定義
26.
CSIドライバのテスト 26
27.
CSI Driver Sanity
Tester ▌Kubernetes プロジェクトから提供されるCSIドライバのテストツール。 ? https://github.com/kubernetes-csi/csi- test/tree/master/pkg/sanity ▌CSIドライバを起動した状態で、gRPC の応答が正しく実装されているか をテストしてくれる。 ▌コマンドラインから起動 / Ginkgo (Go言語のTesting Framework) から利用。 27 Tip: 手戻りをなくすため、最初からテストを実行できるようにする。
28.
Sanity Testerの利用例 28 var _
= Describe("TopoLVM", func() { Context("CSI sanity", func() { ... テスト対象のCSIドライバを起動しておく sanity.GinkgoTest(&sanity.Config{ Address: "/tmp/topolvm/worker1/plugins/topolvm.cybozu.com/node/csi-topolvm.sock", ControllerAddress: "/tmp/topolvm/worker1/plugins/topolvm.cybozu.com/controller/csi-topolvm.sock", TargetPath: "/tmp/topolvm/worker1/plugins/topolvm.cybozu.com/node/mountdir", StagingPath: "/tmp/topolvm/worker1/plugins/topolvm.cybozu.com/node/stagingdir", TestVolumeSize: 1073741824, IDGen: &sanity.DefaultIDGenerator{}, }) }) }) https://github.com/cybozu-go/topolvm/blob/v0.4.8/e2e/suite_test.go#L99-L137 Controller と Node の両方のエンドポイントに アクセス可能な環境で実行
29.
Sanity Tester 以外のテスト ▌Sanity
Testerだけでは全てのテストをカバーしているわけではない。 ▌実際にストレージが使えるかのE2Eテストを行っていない。 ? Cybozuで開発しているCSIドライバ (TopoLVM) では、 kindを利用したE2E テストを別途実施している。 ▌個々のCSIドライバの実装に関する単体テストも必要に応じて追加する。 29
30.
オプション機能の拡張方法 30
31.
Volume Expansion 機能を提供する ▌定義するCapabilities ?
EXPAND_VOLUME (ControllerCapabilities) ? EXPAND_VOLUME (NodeCapabilities) ▌実装するメソッド ? ControllerExpandVolume (Controllerサービス) ? NodeExpandVolume (Nodeサービス) ▌Sidecarとして external-resizer を追加 ▌StorageClass に allowVolumeExpansion を定義 31
32.
ControllerExpandVolumeの例 ▌サイズの変更が可能かどうかを判定する。 requestGb, err :=
convertRequestCapacity(req.GetCapacityRange().GetRequiredBytes(), req.GetCapacityRange().GetLimitBytes()) ... if requestGb <= currentGb { return &csi.ControllerExpandVolumeResponse{ CapacityBytes: currentGb << 30, NodeExpansionRequired: true, }, nil } ... if capacity < (requestGb<<30 - currentGb<<30) { return nil, status.Error(codes.Internal, "not enough space") } ... return &csi.ControllerExpandVolumeResponse{ CapacityBytes: requestGb << 30, NodeExpansionRequired: true, }, nil 領域の縮小が要求される場合もある 領域の拡張を許容する場合 NodeExpansionRequired が true の場合、 Node の NodeExpandVolume (次スライド) が呼ばれる https://github.com/cybozu-go/topolvm/blob/v0.4.8/driver/controller.go#L310-L376 32
33.
NodeExpandVolumeの例 ▌各ノード上で、サイズ変更後のVolumeを利用可能にする。 ? TopoLVMではlvmd (Kubernetes
node 上の daemon) でlvを拡張してい るため、NodeExpandVolume ではファイルシステムの拡張のみを行う。 33 vpath := req.GetVolumePath() ... err = fs.Resize(vpath) ... return &csi.NodeExpandVolumeResponse{}, nil https://github.com/cybozu-go/topolvm/blob/v0.4.8/driver/node.go#L414-L498
34.
Dynamic Provisioning 機能を提供する ▌定義するCapabilities ?
CREATE_DELETE_VOLUME (ControllerCapabilities) ▌実装するメソッド ? CreateVolume (Controllerサービス) ? DeleteVolume (Controllerサービス) ▌Sidecarとして external-provisioner を追加 ▌StorageClass の provisioner と、GetPluginInfo で戻すnameの 値を同じにしておく。 34 詳しい実装はTopoLVMを参照
35.
ドキュメント?参考情報 35
36.
CSIのバージョンについて ▌CSIのバージョンはKubernetesと 独立している。 ▌Kubernetes v1.13 のタイミン グで
CSIはGAとなりバージョンが 1.0になった。 36https://github.com/container-storage-interface/spec/releases
37.
CSI sidecarのバージョンについて ▌各sidecarのバージョンはspecか ら独立して管理される ? CSIがGAになった後に追加された機 能もあり、機能ごとにalpha,
beta, GAの状況は異なる ▌Kubernetes, spec, sidecar のバージョンの対応については、各 sidecarのReleasesに記載があ る。 37https://github.com/kubernetes-csi/external-provisioner/releases
38.
参考となるCSIドライバ ▌sig-storage でCSIドライバのサンプルを公開している。 ▌https://github.com/kubernetes-csi/ ? csi-driver-host-path ?
csi-driver-nfs ? csi-driver-smb 38
39.
既存のCSIドライバ ▌以下のページより既存のCSIドライバ一覧が探すことが可能。 ? https://kubernetes-csi.github.io/docs/drivers.html ▌サイボウズでもTopoLVMというCSIドライバを開発?公開している。 ? 各NodeのLVM領域を動的に提供する。 ?
Topologyを考慮し、ストレージ容量の空きが多いNodeにPodが優先配置され る。 ? https://blog.cybozu.io/entry/2019/11/08/090000 39
40.
ドキュメント ▌Container Storage Interface
(CSI) のspec https://github.com/container-storage-interface/spec/ ▌CSI Volume Plugins in Kubernetes Design Doc https://github.com/kubernetes/community/blob/master/contribut ors/design-proposals/storage/container-storage-interface.md ▌Kubernetes CSI Developer Documentation https://kubernetes-csi.github.io/docs/introduction.html ▌各sidecarのREADME.mdにオプションなどが記載されている 40
41.
まとめ ▌シンプルなCSIドライバを例に、実装方法ついて説明した。 ? まだたくさんのドキュメントを読む必要がある。 ? 特にCSIのspecは、詳細まで記述してある。 ▌実装時の注意点?Tipについて説明した。 ?
CSIドライバで提供したい機能に合わせて利用するsidecarや実装するプロシー ジャが変わる。 ? CSIドライバのプロシージャは冪等性を満たす必要がある。 ? 開発初期からSanity Testerを利用し、手戻りを防ぐ。 41
Download