Skip to content

Commit cbcc1b3

Browse files
Merge pull request #36 from Roblox/networking
Add support for networking
2 parents 0550b1a + 22011a2 commit cbcc1b3

File tree

3 files changed

+50
-10
lines changed

3 files changed

+50
-10
lines changed

README.md

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,29 @@ mounts = [
113113
]
114114
```
115115

116+
## Networking
117+
118+
`nomad-driver-containerd` supports **host** and **bridge** networks.<br/>
119+
120+
**NOTE:** `host` and `bridge` are mutually exclusive options, and only one of them should be used at a time.
121+
122+
1. **Host** network can be enabled by setting `host_network` to `true` in task config
123+
of the job spec [Check under [`Supported options`](https://github.com/Roblox/nomad-driver-containerd#supported-options)].
124+
125+
2. **Bridge** network can be enabled by setting the `network` stanza in the task group section of the job spec.
126+
127+
```
128+
network {
129+
mode = "bridge"
130+
}
131+
```
132+
You need to install CNI plugins on nomad client nodes under `/opt/cni/bin` before you can use `bridge` networks.
133+
134+
**Instructions for installing CNI plugins.**<br/>
135+
- $ curl -L -o cni-plugins.tgz https://github.com/containernetworking/plugins/releases/download/v0.8.1/cni-plugins-linux-amd64-v0.8.1.tgz<br/>
136+
- sudo mkdir -p /opt/cni/bin<br/>
137+
- sudo tar -C /opt/cni/bin -xzf cni-plugins.tgz
138+
116139
## Tests
117140
```
118141
$ make test
@@ -140,11 +163,9 @@ Ubuntu (>= 16.04)
140163
`nomad-driver-containerd` [`v0.1`](https://github.com/Roblox/nomad-driver-containerd/releases/tag/v0.1) is **not** production ready.
141164
There are some open items which are currently being worked on.
142165

143-
1) **Networking**: Networking is **not in scope** of containerd as described [`here`](https://kubernetes.io/blog/2017/11/containerd-container-runtime-options-kubernetes/). However an external CNI plugin can be used to add networking to the container. We are researching on how to enable networking for our internal use-cases, and would publish (open-source) that work at some point.
144-
145-
2) **Port forwarding**: The ability to map a host port to a container port. This is currently not supported, but could be supported in future.
166+
1) **Port forwarding**: The ability to map a host port to a container port. This is currently not supported, but could be supported in future.
146167

147-
3) **Consul connect**: When a user launches a job in `nomad`, s/he can add a [`service stanza`](https://www.nomadproject.io/docs/job-specification/service) which will instruct `nomad` to register the service with `consul` for service discovery. This is currently not supported.
168+
2) **Consul connect**: When a user launches a job in `nomad`, s/he can add a [`service stanza`](https://www.nomadproject.io/docs/job-specification/service) which will instruct `nomad` to register the service with `consul` for service discovery. This is currently not supported.
148169

149170
## License
150171

containerd/containerd.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func (d *Driver) pullImage(imageName string) (containerd.Image, error) {
4141
return d.client.Pull(d.ctxContainerd, imageName, containerd.WithPullUnpack)
4242
}
4343

44-
func (d *Driver) createContainer(image containerd.Image, containerName, containerSnapshotName, containerdRuntime string, env []string, config *TaskConfig) (containerd.Container, error) {
44+
func (d *Driver) createContainer(image containerd.Image, containerName, containerSnapshotName, containerdRuntime, netnsPath string, env []string, config *TaskConfig) (containerd.Container, error) {
4545
if config.Command == "" && len(config.Args) > 0 {
4646
return nil, fmt.Errorf("Command is empty. Cannot set --args without --command.")
4747
}
@@ -123,6 +123,16 @@ func (d *Driver) createContainer(image containerd.Image, containerName, containe
123123
opts = append(opts, oci.WithMounts(mounts))
124124
}
125125

126+
// nomad use CNI plugins e.g bridge to setup a network (and network namespace) for the container.
127+
// CNI plugins need to be installed under /opt/cni/bin.
128+
// network namespace is created at /var/run/netns/<id>.
129+
// netnsPath is the path to the network namespace, which containerd joins to provide network
130+
// for the container.
131+
// NOTE: Only bridge networking mode is supported at this point.
132+
if netnsPath != "" {
133+
opts = append(opts, oci.WithLinuxNamespace(specs.LinuxNamespace{Type: specs.NetworkNamespace, Path: netnsPath}))
134+
}
135+
126136
return d.client.NewContainer(
127137
d.ctxContainerd,
128138
containerName,

containerd/driver.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,10 @@ var (
110110
// this should be set according to the target run time.
111111
// https://godoc.org/github.com/hashicorp/nomad/plugins/drivers#Capabilities
112112
capabilities = &drivers.Capabilities{
113-
SendSignals: true,
114-
Exec: true,
115-
FSIsolation: drivers.FSIsolationNone,
113+
SendSignals: true,
114+
Exec: true,
115+
FSIsolation: drivers.FSIsolationNone,
116+
NetIsolationModes: []drivers.NetIsolationMode{drivers.NetIsolationModeGroup, drivers.NetIsolationModeTask},
116117
}
117118
)
118119

@@ -333,6 +334,10 @@ func (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drive
333334
return nil, nil, fmt.Errorf("failed to decode driver config: %v", err)
334335
}
335336

337+
if driverConfig.HostNetwork && cfg.NetworkIsolation != nil {
338+
return nil, nil, fmt.Errorf("host_network and bridge network mode are mutually exclusive, and only one of them should be set")
339+
}
340+
336341
d.logger.Info("starting task", "driver_cfg", hclog.Fmt("%+v", driverConfig))
337342
handle := drivers.NewTaskHandle(taskHandleVersion)
338343
handle.Config = cfg
@@ -355,13 +360,17 @@ func (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drive
355360
}
356361

357362
containerSnapshotName := fmt.Sprintf("%s-snapshot", containerName)
358-
container, err := d.createContainer(image, containerName, containerSnapshotName, d.config.ContainerdRuntime, env, &driverConfig)
363+
var netnsPath string
364+
if cfg.NetworkIsolation != nil && cfg.NetworkIsolation.Path != "" {
365+
netnsPath = cfg.NetworkIsolation.Path
366+
}
367+
368+
container, err := d.createContainer(image, containerName, containerSnapshotName, d.config.ContainerdRuntime, netnsPath, env, &driverConfig)
359369
if err != nil {
360370
return nil, nil, fmt.Errorf("Error in creating container: %v", err)
361371
}
362372

363373
d.logger.Info(fmt.Sprintf("Successfully created container with name: %s", containerName))
364-
365374
task, err := d.createTask(container, cfg.StdoutPath, cfg.StderrPath)
366375
if err != nil {
367376
return nil, nil, fmt.Errorf("Error in creating task: %v", err)

0 commit comments

Comments
 (0)