Skip to content

Instantly share code, notes, and snippets.

@akutz
Last active June 5, 2017 21:01
Show Gist options
  • Save akutz/e0775d3cea6195ed20bd4fe8a00d1b47 to your computer and use it in GitHub Desktop.
Save akutz/e0775d3cea6195ed20bd4fe8a00d1b47 to your computer and use it in GitHub Desktop.
REX-Ray+CSI

REX-Ray+CSI

The introduction of the Container Storage Interface (CSI) provides an exciting opportunity to the world of Container Orchestrator (CO) and storage. This document reviews how CSI adds value to REX-Ray, strengthening its position as the leading CO storage management solution.

Note: Before reading this document please take time to review the several REX-Ray/CSI architecture and component types.

The Proposal

This section illustrates the proposed solution for introducing CSI to REX-Ray and libStorage:

  1. Create a new libStorage interface, EndpointProvider:
type EndpointProvider interface {
	// Close immediately closes all active net.Listeners and any
	// connections in state StateNew, StateActive, or StateIdle. For a
	// graceful shutdown, use Shutdown.
	Close() error

	// Serve accepts incoming connections on the Listener l, creating a
	// new service goroutine for each.
	Serve(l net.Listener) error

	// Shutdown gracefully shuts down the server without interrupting any
	// active connections. Shutdown works by first closing all open
	// listeners, then closing all idle connections, and then waiting
	// indefinitely for connections to return to idle and then shut down.
	// If the provided context expires before the shutdown is complete,
	// then the context's error is returned.
	Shutdown(ctx context.Context) error
}
  1. Refactor the libStorage API (HTTP/REST) components into an implementation of the EndpointProvider interface.
  2. Relocate the Docker Volume Driver endpoint from REX-Ray to libStorage and then refactor the endpoint provider as an implementation of the EndpointProvider interface.
  3. Create CSI implementations of the EndpointProvider interface:
    • csi.node
    • csi.controller
    • csi.node+controller
  4. Introduce the following configuration enhancements:
    • Use libstorage.server.endpoints.NAME.type to specify the endpoint's provider type
    • Use libstorage.server.endpoints.NAME.services to define which configured storage service(s) an endpoint will expose. Please note that if an endpoint provider is not capable of consuming more than one service the property can be defined as a string, otherwise it would be []string.

Diagrams

This section visualizes the proposed changes as two diagrams that represent a centralized architecture with Docker as the CO, without and with CSI support.

Centralized Architecture w Docker

The first diagram illustrates the centralized architecture as it is today using Docker as the CO:

Centralized Architecture w Docker & CSI

The second diagram also outlines the centralized architecture, but this time includes the model as it would appear with the changes required to support CSI described above:

Endpoint Providers

This section lists the supported endpoint provider types:

Type Multi-Service Support Description
libstorage The libStorage API (HTTP/REST) endpoint provider
docker The Docker Volume Driver (HTTP/REST) endpoint provider
csi The CSI node+controller (gRPC) endpoint provider
csi.node The CSI node (gRPC) endpoint provider
csi.controller The CSI controller (gRPC) endpoint provider

Estimates

This section estimates the story points for the issues above:

Issue Summary Story Points
#1 EndpointProvider interface 8
#2 Refactor libStorage w EndpointProvider interface 21
#3 Relocate/Refactor Docker Vol Driver 13
#4 Create CSI endpoint providers 21
#4 Enhance libStorage configuration 13
76
@startuml
frame "Master Host" as masterHost {
frame "REX-Ray\nController" as masterControllerProc {
rectangle "libStorage\nPackage" as masterLibstoragePkg {
rectangle "libStorage\nController" as masterControllerLibStorageEndpoint
}
rectangle masterController [
**libStorage Package**
==
libStorage Controller
]
}
}
frame "Node Host(s)" as nodeHost {
rectangle "Docker" as nodeClient
frame "REX-Ray\nAgent" as nodeAgentProc {
rectangle nodeAgentEndpoint [
**REX-Ray Package**
==
Docker Volume
Driver Endpoint
]
rectangle masterControllerClient [
**libStorage Package**
==
libStorage API
Client
]
}
nodeClient -> nodeAgentEndpoint: "Docker Volume\nDriver API (HTTP/REST)"
nodeAgentEndpoint -> masterControllerClient
masterHost -[hidden]d-> nodeHost
}
masterControllerClient -u-> masterControllerLibStorageEndpoint: "libStorage API\n(HTTP/REST)"
@enduml
Display the source blob
Display the rendered blob
Raw
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="594px" preserveAspectRatio="none" style="width:634px;height:594px;" version="1.1" viewBox="0 0 634 594" width="634px" zoomAndPan="magnify"><defs><filter height="300%" id="f1ox8tuba9gch9" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><!--cluster masterHost--><rect fill="#FFFFFF" filter="url(#f1ox8tuba9gch9)" height="190" style="stroke: #000000; stroke-width: 2.0;" width="368" x="221" y="16"/><path d="M319,17 L319,25.4883 L309,35.4883 L221,35.4883 " fill="none" style="stroke: #000000; stroke-width: 2.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="88" x="224" y="30.5352">Master Host</text><!--cluster masterControllerProc--><rect fill="#FFFFFF" filter="url(#f1ox8tuba9gch9)" height="155" style="stroke: #000000; stroke-width: 2.0;" width="325" x="256" y="43"/><path d="M339,44 L339,68.9766 L329,78.9766 L256,78.9766 " fill="none" style="stroke: #000000; stroke-width: 2.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="62" x="264.5" y="57.5352">REX-Ray</text><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="73" x="259" y="74.0234">Controller</text><!--cluster masterLibstoragePkg--><rect fill="#FFFFFF" filter="url(#f1ox8tuba9gch9)" height="104" style="stroke: #000000; stroke-width: 2.0;" width="106" x="467" y="86"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="73" x="483.5" y="101.5352">libStorage</text><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="58" x="491" y="118.0234">Package</text><!--cluster nodeHost--><rect fill="#FFFFFF" filter="url(#f1ox8tuba9gch9)" height="362" style="stroke: #000000; stroke-width: 2.0;" width="613" x="14" y="225"/><path d="M118,226 L118,234.4883 L108,244.4883 L14,244.4883 " fill="none" style="stroke: #000000; stroke-width: 2.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="94" x="17" y="239.5352">Node Host(s)</text><!--cluster nodeAgentProc--><rect fill="#FFFFFF" filter="url(#f1ox8tuba9gch9)" height="128" style="stroke: #000000; stroke-width: 2.0;" width="597" x="22" y="451"/><path d="M94,452 L94,476.9766 L84,486.9766 L22,486.9766 " fill="none" style="stroke: #000000; stroke-width: 2.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="62" x="25" y="465.5352">REX-Ray</text><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="42" x="35" y="482.0234">Agent</text><!--entity masterController--><rect fill="#FEFECE" filter="url(#f1ox8tuba9gch9)" height="60.9766" style="stroke: #000000; stroke-width: 1.5;" width="176" x="264" y="125"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="136" x="274" y="148.5352">libStorage Package</text><line style="stroke: #000000; stroke-width: 1.0;" x1="265" x2="439" y1="151.4883" y2="151.4883"/><line style="stroke: #000000; stroke-width: 1.0;" x1="265" x2="439" y1="153.4883" y2="153.4883"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="144" x="280" y="169.0234">libStorage Controller</text><!--entity masterControllerLibStorageEndpoint--><rect fill="#FEFECE" filter="url(#f1ox8tuba9gch9)" height="52.9766" style="stroke: #000000; stroke-width: 1.5;" width="90" x="475" y="129"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="70" x="485" y="152.5352">libStorage</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="70" x="485" y="169.0234">Controller</text><!--entity nodeClient--><rect fill="#FEFECE" filter="url(#f1ox8tuba9gch9)" height="36.4883" style="stroke: #000000; stroke-width: 1.5;" width="68" x="134" y="252"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="48" x="144" y="275.5352">Docker</text><!--entity nodeAgentEndpoint--><rect fill="#FEFECE" filter="url(#f1ox8tuba9gch9)" height="77.4648" style="stroke: #000000; stroke-width: 1.5;" width="145" x="30.5" y="494"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="125" x="40.5" y="517.5352">REX-Ray Package</text><line style="stroke: #000000; stroke-width: 1.0;" x1="31.5" x2="174.5" y1="520.4883" y2="520.4883"/><line style="stroke: #000000; stroke-width: 1.0;" x1="31.5" x2="174.5" y1="522.4883" y2="522.4883"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="104" x="46.5" y="538.0234">Docker Volume</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="107" x="46.5" y="554.5117">Driver Endpoint</text><!--entity masterControllerClient--><rect fill="#FEFECE" filter="url(#f1ox8tuba9gch9)" height="77.4648" style="stroke: #000000; stroke-width: 1.5;" width="156" x="455" y="494"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="136" x="465" y="517.5352">libStorage Package</text><line style="stroke: #000000; stroke-width: 1.0;" x1="456" x2="610" y1="520.4883" y2="520.4883"/><line style="stroke: #000000; stroke-width: 1.0;" x1="456" x2="610" y1="522.4883" y2="522.4883"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="96" x="471" y="538.0234">libStorage API</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="40" x="471" y="554.5117">Client</text><!--link nodeClient to nodeAgentEndpoint--><path d="M163.5323,288.0427 C153.3978,328.9705 128.4226,429.8319 113.9166,488.4136 " fill="none" id="nodeClient-nodeAgentEndpoint" style="stroke: #A80036; stroke-width: 1.0;"/><polygon fill="#A80036" points="112.6325,493.5995,118.6786,485.8248,113.8344,488.7461,110.9131,483.9019,112.6325,493.5995" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="96" x="165" y="393.5684">Docker Volume</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="144" x="141" y="408.8789">Driver API (HTTP/REST)</text><!--link nodeAgentEndpoint to masterControllerClient--><path d="M175.6465,532.5 C266.9806,532.5 358.3147,532.5 449.6488,532.5 " fill="none" id="nodeAgentEndpoint-masterControllerClient" style="stroke: #A80036; stroke-width: 1.0;"/><polygon fill="#A80036" points="454.8289,532.5,445.8289,528.5,449.8289,532.5,445.8289,536.5,454.8289,532.5" style="stroke: #A80036; stroke-width: 1.0;"/><!--link masterHost to nodeHost--><!--link masterControllerLibStorageEndpoint to masterControllerClient--><path d="M521.0929,187.1933 C523.4657,256.0066 529.0829,418.9033 531.6625,493.7126 " fill="none" id="masterControllerLibStorageEndpoint-masterControllerClient" style="stroke: #A80036; stroke-width: 1.0;"/><polygon fill="#A80036" points="520.9141,182.0099,517.2269,191.1425,521.0865,187.0069,525.2221,190.8666,520.9141,182.0099" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="87" x="527" y="331.5684">libStorage API</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="78" x="531.5" y="346.8789">(HTTP/REST)</text><!--
@startuml
frame "Master Host" as masterHost {
frame "REX-Ray\nController" as masterControllerProc {
rectangle "libStorage\nPackage" as masterLibstoragePkg {
rectangle "libStorage\nController" as masterControllerLibStorageEndpoint
}
rectangle masterController [
**libStorage Package**
==
libStorage Controller
]
}
}
frame "Node Host(s)" as nodeHost {
rectangle "Docker" as nodeClient
frame "REX-Ray\nAgent" as nodeAgentProc {
rectangle nodeAgentEndpoint [
**REX-Ray Package**
==
Docker Volume
Driver Endpoint
]
rectangle masterControllerClient [
**libStorage Package**
==
libStorage API
Client
]
}
nodeClient -> nodeAgentEndpoint: "Docker Volume\nDriver API (HTTP/REST)"
nodeAgentEndpoint -> masterControllerClient
masterHost -[hidden]d-> nodeHost
}
masterControllerClient -u-> masterControllerLibStorageEndpoint: "libStorage API\n(HTTP/REST)"
@enduml
PlantUML version 1.2017.13(Wed May 10 11:52:33 CDT 2017)
(GPL source distribution)
Java Runtime: Java(TM) SE Runtime Environment
JVM: Java HotSpot(TM) 64-Bit Server VM
Java Version: 1.8.0_20-b26
Operating System: Mac OS X
OS Version: 10.12.5
Default Encoding: UTF-8
Language: en
Country: US
--></g></svg>
@startuml
frame "Master Host" as masterHost {
rectangle "Docker" as masterClient
frame "REX-Ray\nController" as masterControllerProc {
rectangle "libStorage\nPackage" as masterLibstoragePkg {
rectangle "CSI\nController\nService" as masterControllerCSIEndpoint
rectangle "libStorage\nController" as masterControllerLibStorageEndpoint
}
}
masterClient -> masterControllerCSIEndpoint: "CSI\n(gRPC)"
}
frame "Node Host(s)" as nodeHost {
rectangle "Docker" as nodeClient
frame "REX-Ray\nAgent" as nodeAgentProc {
rectangle "libStorage\nPackage" as nodeLibstoragePkg {
rectangle "CSI\nNode\nService" as nodeAgentEndpoint
rectangle "libStorage\nAPI\nClient" as masterControllerClient
}
}
nodeClient -> nodeAgentEndpoint: "CSI\n(gRPC)"
nodeAgentEndpoint -> masterControllerClient
}
masterControllerClient -u-> masterControllerLibStorageEndpoint: "libStorage API\n(HTTP/REST)"
@enduml
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment