天天看點

【kubernetes/k8s概念】k8s csi一.  Identity 身份服務二. Controller 控制器服務三. Node 節點服務1. DefaultIdentityServer儲存driver對象2.  DefaultNodeServer實作了NodeServer接口四. CSIDriver Object五. CSINode ObjectKubernetes Changelog

WHY

In-Tree: 需要将後端存儲的代碼邏輯放到K8S的代碼中運作。邏輯代碼可能會引起與K8S其他部件之間的互相影響。

Flexvolume: 調用一個主機的可執行程式包的方式執行存儲卷的挂載使用。解決了In-Tree方式的強耦合,不過指令行調用的方式,在主機安全性、部署依賴的容器化、與K8S服務之間的互相擴充性等方面存在不足

Flexvolume運作在host 空間,不能使用rbac授權機制通路Kubernetes API,導緻其功能極大的受限。

CSI: CSI标準使K8S和存儲提供者之間将徹底解耦,将存儲的所有的部件作為容器形式運作在K8S上。

目前版本資訊:

Kubernetes CSI Version CSI Status
v1.9 v0.1 Alpha
v1.10 v0.2 Beta
v1.11 v0.3 Beta
v1.12 v0.3 Beta
v1.13 v1.0.0 GA

       CSI是Container Storage Interface的縮寫。CSI是由來自Kubernetes、Mesos、 Docker等社群的member聯合制定的一個行業标準接口規範,旨在将任意存儲系統暴露給容器化應用程式。CSI規範定義了存儲提供商(SP)實作CSI相容插件的最小操作集和部署建議。CSI規範的主要焦點是聲明插件必須實作的接口

架構圖

【kubernetes/k8s概念】k8s csi一.  Identity 身份服務二. Controller 控制器服務三. Node 節點服務1. DefaultIdentityServer儲存driver對象2.  DefaultNodeServer實作了NodeServer接口四. CSIDriver Object五. CSINode ObjectKubernetes Changelog

       三個獨立的外部元件(External Components),即:Driver Registrar、External Provisioner 和 External Attacher,對應的正是從 Kubernetes 項目裡面剝離出來的那部分存儲管理功能。

       External Components 雖然是外部元件,但依然由 Kubernetes 社群來開發和維護。

       參考:http://bamboox.online/k8s-15-%E5%AD%98%E5%82%A8-02.html

Driver Registrar

     将插件注冊到 kubelet ,需要請求 CSI 插件的 Identity 服務來擷取插件資訊

External Provisioner

     Watch  APIServer 的 PVC 對象,PVC 被建立時,就會調用 CSI Controller 的 CreateVolume 方法,建立對應 PV

External Attacher

     Watch APIServer 的 VolumeAttachment 對象,就會調用 CSI Controller 服務的 ControllerPublish 方法,完成它所對應的 Volume 的 Attach 階段

開發步驟

  1. Create a containerized application implementing the Identity, Node, and optionally the Controller services described in the CSI specification (the CSI driver container). See Developing CSI Driver for more information.
  2. Unit test it using csi-sanity. See Driver - Unit Testing for more information.
  3. Define Kubernetes API YAML files that deploy the CSI driver container along with appropriate sidecar containers. See Deploying in Kubernetes for more information.
  4. Deploy the driver on a Kubernetes cluster and run end-to-end functional tests on it. See Driver - Functional Testing

    At a minimum, CSI drivers must implement the following CSI services:

  • CSI 

    Identity

     service
    • Enables callers (Kubernetes components and CSI sidecar containers) to identify the driver and what optional functionality it supports.
  • CSI 

    Node

     service
    • Only 

      NodePublishVolume

      NodeUnpublishVolume

      , and 

      NodeGetCapabilities

       are required.
    • Required methods enable callers to make a volume available at a specified path and discover what optional functionality the driver supports.

一.  Identity 身份服務

      Node Plugin和Controller Plugin都必須實作這些RPC集。協調kubernetes與csi的版本資訊,

      負責對外暴露這個插件的資訊

service Identity {
  rpc GetPluginInfo(GetPluginInfoRequest)
    returns (GetPluginInfoResponse) {}

  rpc GetPluginCapabilities(GetPluginCapabilitiesRequest)
    returns (GetPluginCapabilitiesResponse) {}

  rpc Probe (ProbeRequest)
    returns (ProbeResponse) {}
}           
  • PluginCapability_Service_CONTROLLER_SERVICE:代表對 ControllerService 插件提供 RPC 服務,這個是可選的,如果實作了就開啟
  • PluginCapability_Service_VOLUME_ACCESSIBILITY_CONSTRAINTS:代表 volume 在叢集中通路限制

二. Controller 控制器服務

    Controller Plugin必須實作這些RPC集。建立以及管理volume管理卷

service Controller {
  rpc CreateVolume (CreateVolumeRequest)
    returns (CreateVolumeResponse) {}

  rpc DeleteVolume (DeleteVolumeRequest)
    returns (DeleteVolumeResponse) {}

  rpc ControllerPublishVolume (ControllerPublishVolumeRequest)
    returns (ControllerPublishVolumeResponse) {}

  rpc ControllerUnpublishVolume (ControllerUnpublishVolumeRequest)
    returns (ControllerUnpublishVolumeResponse) {}

  rpc ValidateVolumeCapabilities (ValidateVolumeCapabilitiesRequest)
    returns (ValidateVolumeCapabilitiesResponse) {}

  rpc ListVolumes (ListVolumesRequest)
    returns (ListVolumesResponse) {}

  rpc GetCapacity (GetCapacityRequest)
    returns (GetCapacityResponse) {}

  rpc ControllerGetCapabilities (ControllerGetCapabilitiesRequest)
    returns (ControllerGetCapabilitiesResponse) {}

  rpc CreateSnapshot (CreateSnapshotRequest)
    returns (CreateSnapshotResponse) {}

  rpc DeleteSnapshot (DeleteSnapshotRequest)
    returns (DeleteSnapshotResponse) {}

  rpc ListSnapshots (ListSnapshotsRequest)
    returns (ListSnapshotsResponse) {}

  rpc ControllerExpandVolume (ControllerExpandVolumeRequest)
    returns (ControllerExpandVolumeResponse) {}
}           
  • ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME:支援動态 volume 執行 provision delete 操作
  • ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME:代表實作了 ControllerPublishVolume 和 ControllerUnpublishVolume 方法,對應 kubernetes 中 attach detach volume 操作

三. Node 節點服務

    Node Plugin必須實作這些RPC集。 将volume存儲卷挂載到指定目錄中,/var/lib/kubelet/plugins/${plugin_name}/csi.sock

service Node {
  rpc NodeStageVolume (NodeStageVolumeRequest)
    returns (NodeStageVolumeResponse) {}

  rpc NodeUnstageVolume (NodeUnstageVolumeRequest)
    returns (NodeUnstageVolumeResponse) {}

  rpc NodePublishVolume (NodePublishVolumeRequest)
    returns (NodePublishVolumeResponse) {}

  rpc NodeUnpublishVolume (NodeUnpublishVolumeRequest)
    returns (NodeUnpublishVolumeResponse) {}

  rpc NodeGetVolumeStats (NodeGetVolumeStatsRequest)
    returns (NodeGetVolumeStatsResponse) {}


  rpc NodeExpandVolume(NodeExpandVolumeRequest)
    returns (NodeExpandVolumeResponse) {}


  rpc NodeGetCapabilities (NodeGetCapabilitiesRequest)
    returns (NodeGetCapabilitiesResponse) {}

  rpc NodeGetInfo (NodeGetInfoRequest)
    returns (NodeGetInfoResponse) {}
}           
  • NodeServiceCapability_RPC_STAGE_UNSTAGE_VOLUME:實作了 NodeStageVolume 和 NodeUnstageVolume 方法,對應了 kubernetes 中的 mount / unmount device 操作

1. DefaultIdentityServer儲存driver對象

     實作了三個接口 GetPluginInfo,GetPluginCapabilities,Probe

// DefaultIdentityServer stores driver object
type DefaultIdentityServer struct {
	Driver *CSIDriver
}
           

     1.1 GetPluginInfo

        獲得plugin 資訊,包括插件名字與版本

// GetPluginInfo returns plugin information
func (ids *DefaultIdentityServer) GetPluginInfo(ctx context.Context, req *csi.GetPluginInfoRequest) (*csi.GetPluginInfoResponse, error) {
	klog.V(5).Infof("Using default GetPluginInfo")

	if ids.Driver.name == "" {
		return nil, status.Error(codes.Unavailable, "Driver name not configured")
	}

	if ids.Driver.version == "" {
		return nil, status.Error(codes.Unavailable, "Driver is missing version")
	}

	return &csi.GetPluginInfoResponse{
		Name:          ids.Driver.name,
		VendorVersion: ids.Driver.version,
	}, nil
}           

    1.2 Probe 用于探測

// Probe returns empty response
func (ids *DefaultIdentityServer) Probe(ctx context.Context, req *csi.ProbeRequest) (*csi.ProbeResponse, error) {
	return &csi.ProbeResponse{}, nil
}           

    1.3 GetPluginCapabilities用于獲得插件具有那些特權

// GetPluginCapabilities returns plugin capabilities
func (ids *DefaultIdentityServer) GetPluginCapabilities(ctx context.Context, req *csi.GetPluginCapabilitiesRequest) (*csi.GetPluginCapabilitiesResponse, error) {
	klog.V(5).Infof("Using default capabilities")
	return &csi.GetPluginCapabilitiesResponse{
		Capabilities: []*csi.PluginCapability{
			{
				Type: &csi.PluginCapability_Service_{
					Service: &csi.PluginCapability_Service{
						Type: csi.PluginCapability_Service_CONTROLLER_SERVICE,
					},
				},
			},
		},
	}, nil
}           

2.  DefaultNodeServer實作了NodeServer接口

  • NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRequest)
  • NodeUnstageVolume(ctx context.Context, req *csi.NodeUnstageVolumeRequest)
  • NodeGetInfo(ctx context.Context, req *csi.NodeGetInfoRequest)
  • NodeGetCapabilities(ctx context.Context, req *csi.NodeGetCapabilitiesRequest)
  • NodeGetVolumeStats(ctx context.Context, in *csi.NodeGetVolumeStatsRequest)
// DefaultNodeServer stores driver object
type DefaultNodeServer struct {
	Driver *CSIDriver
}           

四. CSIDriver Object

    主要有兩個目的:

  • 簡化了 driver 服務發現:可以通過 Kubectl get CSIDriver 
  • 定制 k8s driver 行為功能:比如預設 Attach / Detach 操作

    4.1 CSIDriver Object 定義格式

     attachRequired::需要 attach 操作,實作了 ControllerPublishVolume 方法

     podInfoOnMount:在 mount 操作中需要 pod 的資訊,比如 name UID 等,如果設定為 true,NodePublishVolume 方法中 volume_context 如下所示:

  • "csi.storage.k8s.io/pod.name": pod.Name

  • "csi.storage.k8s.io/pod.namespace": pod.Namespace

  • "csi.storage.k8s.io/pod.uid": string(pod.UID)

     volumeLifecycleModes:k8s v1.16 版本新增,

apiVersion: storage.k8s.io/v1beta1

kind: CSIDriver

metadata:

  name: hostpath.csi.k8s.io

spec:

  attachRequired: true

  podInfoOnMount: true

  volumeLifecycleModes:

  - Persistent

  - Ephemeral

五. CSINode Object

    主要有以下幾個目的:

  • 影射 k8s node 名字到 CSI node 名字:如果新的 CSI driver 注冊,存儲資訊
  • driver 可用性
  • volume topology

    5.1 CSINode Object 定義

  • drivers

     - list of CSI drivers running on the node and their properties.
  • name

     - the CSI driver that this object refers to.
  • nodeID

     - the assigned identifier for the node as determined by the driver.
  • topologyKeys

     - A list of topology keys assigned to the node as supported by the driver.

apiVersion: storage.k8s.io/v1beta1

kind: CSINode

metadata:

  name: master-node

spec:

  drivers:

  - name: hostpath.csi.k8s.io

    nodeID: master-node

    topologyKeys:

    - topology.hostpath.csi/node

      node-driver-registrar sidecar container 建立 CSINode 對象

Kubernetes Changelog

Kubernetes 1.14

Breaking Changes

  • csi.storage.k8s.io/v1alpha1

    CSINodeInfo

     and 

    CSIDriver

     CRDs are no longer supported.

Features

  • New beta features:
    • Topology
    • Raw block
    • Skip attach
    • Pod info on mount
  • New alpha features:
    • Volume expansion
  • New 

    storage.k8s.io/v1beta1

    CSINode

     and 

    CSIDriver

     objects were introduced.

Kubernetes 1.13

Deprecations

  • CSI spec 0.2 and 0.3 are deprecated and support will be removed in Kubernetes 1.18.

Features

  • GA support added for CSI spec 1.0.

參考:

    Kubernetes Container Storage Interface (CSI) Documentation

    How to write a Container Storage Interface (CSI) plugin

          https://arslan.io/2018/06/21/how-to-write-a-container-storage-interface-csi-plugin/