Skip to content

Commit

Permalink
Add configuration options to support different driver modes (#372)
Browse files Browse the repository at this point in the history
This enables to run the driver on a non-droplet VM.
  • Loading branch information
r0kas authored Feb 17, 2021
1 parent 9ee15e2 commit 745391f
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 16 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
cmd/do-csi-plugin/do-csi-plugin
.idea/
*.sedbak
.DS_Store
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,30 @@ Kubernetes Release | DigitalOcean CSI Driver Version

The [DigitalOcean Kubernetes](https://www.digitalocean.com/products/kubernetes/) product comes with the CSI driver pre-installed and no further steps are required.

---
**Driver modes:**

By default, the driver supports both the [controller and node mode.](https://kubernetes-csi.github.io/docs/deploying.html)
It can manage DigitalOcean Volumes via the cloud API and mount them on the required node.
The actually used mode is determined by how the driver is deployed and configured.
The suggested release manifests provide separate deployments for controller and node modes, respectively.

When running outside of DigitalOcean droplets, the driver can only function in **controller mode**.
This requires to set the `--region` flag to a valid DigitalOcean region slug in addition to the other flags.

The `--region` flag **must not** be set when running the driver on DigitalOcean droplets.

Alternatively driver can be run in **node only mode** on DigitalOcean droplets.
Driver would only handle node related requests like mount volume. Driver runs in **node only mode** when `--token` flag is not provided.

Skip secret creation (section 1. in following deployment instructions) when using **node only mode** as API token is not required.

| Modes | `--token` flag | `--region` flag |
|-------------------------------------------|:----------------:|:----------------:|
| Controller and Node mode in DigitalOcean |:white_check_mark:| :x: |
| Controller only mode not in DigitalOcean |:white_check_mark:|:white_check_mark:|
| Node only mode in DigitalOcean | :x: | :x: |

---

**Requirements:**
Expand Down
19 changes: 12 additions & 7 deletions cmd/do-csi-plugin/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,13 @@ import (

func main() {
var (
endpoint = flag.String("endpoint", "unix:///var/lib/kubelet/plugins/"+driver.DefaultDriverName+"/csi.sock", "CSI endpoint")
token = flag.String("token", "", "DigitalOcean access token")
url = flag.String("url", "https://api.digitalocean.com/", "DigitalOcean API URL")
doTag = flag.String("do-tag", "", "Tag DigitalOcean volumes on Create/Attach")
driverName = flag.String("driver-name", driver.DefaultDriverName, "Name for the driver")
debugAddr = flag.String("debug-addr", "", "Address to serve the HTTP debug server on")
endpoint = flag.String("endpoint", "unix:///var/lib/kubelet/plugins/"+driver.DefaultDriverName+"/csi.sock", "CSI endpoint.")
token = flag.String("token", "", "DigitalOcean access token.")
url = flag.String("url", "https://api.digitalocean.com/", "DigitalOcean API URL.")
region = flag.String("region", "", "DigitalOcean region slug. Specify only when running in controller mode outside of a DigitalOcean droplet.")
doTag = flag.String("do-tag", "", "Tag DigitalOcean volumes on Create/Attach.")
driverName = flag.String("driver-name", driver.DefaultDriverName, "Name for the driver.")
debugAddr = flag.String("debug-addr", "", "Address to serve the HTTP debug server on.")
version = flag.Bool("version", false, "Print the version and exit.")
)
flag.Parse()
Expand All @@ -45,7 +46,11 @@ func main() {
os.Exit(0)
}

drv, err := driver.NewDriver(*endpoint, *token, *url, *doTag, *driverName, *debugAddr)
if *token == "" && *region != "" {
log.Fatalln("region flag must not be set when driver is running in node mode (i.e., token flag is unset)")
}

drv, err := driver.NewDriver(*endpoint, *token, *url, *region, *doTag, *driverName, *debugAddr)
if err != nil {
log.Fatalln(err)
}
Expand Down
20 changes: 11 additions & 9 deletions driver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ type Driver struct {
// NewDriver returns a CSI plugin that contains the necessary gRPC
// interfaces to interact with Kubernetes over unix domain sockets for
// managing DigitalOcean Block Storage
func NewDriver(ep, token, url, doTag, driverName, debugAddr string) (*Driver, error) {
func NewDriver(ep, token, url, region, doTag, driverName, debugAddr string) (*Driver, error) {
if driverName == "" {
driverName = DefaultDriverName
}
Expand All @@ -104,13 +104,16 @@ func NewDriver(ep, token, url, doTag, driverName, debugAddr string) (*Driver, er
})
oauthClient := oauth2.NewClient(context.Background(), tokenSource)

all, err := metadata.NewClient().Metadata()
if err != nil {
return nil, fmt.Errorf("couldn't get metadata: %s (are you running on DigitalOcean droplets?)", err)
}
var hostID string
if region == "" {
all, err := metadata.NewClient().Metadata()
if err != nil {
return nil, fmt.Errorf("couldn't get metadata: %s (are you running outside of a DigitalOcean droplet and possibly forgot to specify the 'region' flag?)", err)
}

region := all.Region
hostID := strconv.Itoa(all.DropletID)
region = all.Region
hostID = strconv.Itoa(all.DropletID)
}

opts := []godo.ClientOpt{}
opts = append(opts, godo.SetBaseURL(url))
Expand Down Expand Up @@ -144,8 +147,7 @@ func NewDriver(ep, token, url, doTag, driverName, debugAddr string) (*Driver, er
region: region,
mounter: newMounter(log),
log: log,
// for now we're assuming only the controller has a non-empty token. In
// the future we should pass an explicit flag to the driver.
// we're assuming only the controller has a non-empty token.
isController: token != "",
waitActionTimeout: defaultWaitActionTimeout,

Expand Down

0 comments on commit 745391f

Please sign in to comment.