Skip to content

Commit

Permalink
Merge pull request #1862 from hashicorp/f-rkt-portmap
Browse files Browse the repository at this point in the history
driver.rkt: support network configuration [waiting]
  • Loading branch information
schmichael committed Oct 27, 2016
2 parents 0d9e54b + edac5e3 commit 6821210
Show file tree
Hide file tree
Showing 3 changed files with 188 additions and 8 deletions.
81 changes: 73 additions & 8 deletions client/driver/rkt.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"syscall"
"time"
Expand Down Expand Up @@ -60,14 +61,18 @@ type RktDriver struct {
}

type RktDriverConfig struct {
ImageName string `mapstructure:"image"`
Command string `mapstructure:"command"`
Args []string `mapstructure:"args"`
TrustPrefix string `mapstructure:"trust_prefix"`
DNSServers []string `mapstructure:"dns_servers"` // DNS Server for containers
DNSSearchDomains []string `mapstructure:"dns_search_domains"` // DNS Search domains for containers
Debug bool `mapstructure:"debug"` // Enable debug option for rkt command
Volumes []string `mapstructure:"volumes"` // Host-Volumes to mount in, syntax: /path/to/host/directory:/destination/path/in/container
ImageName string `mapstructure:"image"`
Command string `mapstructure:"command"`
Args []string `mapstructure:"args"`
TrustPrefix string `mapstructure:"trust_prefix"`
DNSServers []string `mapstructure:"dns_servers"` // DNS Server for containers
DNSSearchDomains []string `mapstructure:"dns_search_domains"` // DNS Search domains for containers
Net []string `mapstructure:"net"` // Networks for the containers
PortMapRaw []map[string]string `mapstructure:"port_map"` //
PortMap map[string]string `mapstructure:"-"` // A map of host port and the port name defined in the image manifest file
Volumes []string `mapstructure:"volumes"` // Host-Volumes to mount in, syntax: /path/to/host/directory:/destination/path/in/container

Debug bool `mapstructure:"debug"` // Enable debug option for rkt command
}

// rktHandle is returned from Start/Open as a handle to the PID
Expand Down Expand Up @@ -122,6 +127,12 @@ func (d *RktDriver) Validate(config map[string]interface{}) error {
"dns_search_domains": &fields.FieldSchema{
Type: fields.TypeArray,
},
"net": &fields.FieldSchema{
Type: fields.TypeArray,
},
"port_map": &fields.FieldSchema{
Type: fields.TypeArray,
},
"debug": &fields.FieldSchema{
Type: fields.TypeBool,
},
Expand Down Expand Up @@ -199,6 +210,8 @@ func (d *RktDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, e
return nil, err
}

driverConfig.PortMap = mapMergeStrStr(driverConfig.PortMapRaw...)

// ACI image
img := driverConfig.ImageName

Expand Down Expand Up @@ -308,6 +321,58 @@ func (d *RktDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, e
cmdArgs = append(cmdArgs, fmt.Sprintf("--dns-search=%s", domain))
}

// set network
network := strings.Join(driverConfig.Net, ",")
if network != "" {
cmdArgs = append(cmdArgs, fmt.Sprintf("--net=%s", network))
}

// Setup port mapping and exposed ports
if len(task.Resources.Networks) == 0 {
d.logger.Println("[DEBUG] driver.rkt: No network interfaces are available")
if len(driverConfig.PortMap) > 0 {
return nil, fmt.Errorf("Trying to map ports but no network interface is available")
}
} else {
// TODO add support for more than one network
network := task.Resources.Networks[0]
for _, port := range network.ReservedPorts {
var containerPort string

mapped, ok := driverConfig.PortMap[port.Label]
if !ok {
// If the user doesn't have a mapped port using port_map, driver stops running container.
return nil, fmt.Errorf("port_map is not set. When you defined port in the resources, you need to configure port_map.")
}
containerPort = mapped

hostPortStr := strconv.Itoa(port.Value)

d.logger.Printf("[DEBUG] driver.rkt: exposed port %s", containerPort)
// Add port option to rkt run arguments. rkt allows multiple port args
cmdArgs = append(cmdArgs, fmt.Sprintf("--port=%s:%s", containerPort, hostPortStr))
}

for _, port := range network.DynamicPorts {
// By default we will map the allocated port 1:1 to the container
var containerPort string

if mapped, ok := driverConfig.PortMap[port.Label]; ok {
containerPort = mapped
} else {
// If the user doesn't have mapped a port using port_map, driver stops running container.
return nil, fmt.Errorf("port_map is not set. When you defined port in the resources, you need to configure port_map.")
}

hostPortStr := strconv.Itoa(port.Value)

d.logger.Printf("[DEBUG] driver.rkt: exposed port %s", containerPort)
// Add port option to rkt run arguments. rkt allows multiple port args
cmdArgs = append(cmdArgs, fmt.Sprintf("--port=%s:%s", containerPort, hostPortStr))
}

}

// Add user passed arguments.
if len(driverConfig.Args) != 0 {
parsed := d.taskEnv.ParseAndReplace(driverConfig.Args)
Expand Down
59 changes: 59 additions & 0 deletions client/driver/rkt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,3 +397,62 @@ func TestRktTaskValidate(t *testing.T) {
t.Fatalf("Validation error in TaskConfig : '%v'", err)
}
}

// TODO: Port Mapping test should be ran with proper ACI image and test the port access.
func TestRktDriver_PortsMapping(t *testing.T) {
if os.Getenv("NOMAD_TEST_RKT") == "" {
t.Skip("skipping rkt tests")
}

ctestutils.RktCompatible(t)
task := &structs.Task{
Name: "etcd",
Config: map[string]interface{}{
"image": "docker://redis:latest",
"args": []string{"--version"},
"port_map": []map[string]string{
map[string]string{
"main": "6379-tcp",
},
},
"debug": "true",
},
LogConfig: &structs.LogConfig{
MaxFiles: 10,
MaxFileSizeMB: 10,
},
Resources: &structs.Resources{
MemoryMB: 256,
CPU: 512,
Networks: []*structs.NetworkResource{
&structs.NetworkResource{
IP: "127.0.0.1",
ReservedPorts: []structs.Port{{"main", 8080}},
},
},
},
}

driverCtx, execCtx := testDriverContexts(task)
defer execCtx.AllocDir.Destroy()

d := NewRktDriver(driverCtx)

handle, err := d.Start(execCtx, task)
if err != nil {
t.Fatalf("err: %v", err)
}
if handle == nil {
t.Fatalf("missing handle")
}
defer handle.Kill()

select {
case res := <-handle.WaitCh():
if !res.Successful() {
t.Fatalf("err: %v", res)
}
case <-time.After(time.Duration(testutil.TestMultiplier()*15) * time.Second):
t.Fatalf("timeout")
}
}
56 changes: 56 additions & 0 deletions website/source/docs/drivers/rkt.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,19 @@ The `rkt` driver supports the following configuration in the job spec:
* `dns_search_domains` - (Optional) A list of DNS search domains to be used in
the containers.

* `net` - (Optional) A list of networks to be used by the containers

* `port_map` - (Optional) A key/value map of port to be used by the container.
port name in the image manifest file needs to be specified for the value. For example:

```
port_map {
app = "8080-tcp"
}
```

See below for more details.

* `debug` - (Optional) Enable rkt command debug option.

* `volumes` - (Optional) A list of `host_path:container_path` strings to bind
Expand All @@ -84,6 +97,49 @@ The `rkt` driver supports the following configuration in the job spec:
}
```

## Networking

The `rkt` can specify `--net` and `--port` for the rkt client. Hence, there are two ways to use host ports by
using `--net=host` or `--port=PORT` with your network.

Example:

```
task "redis" {
# Use rkt to run the task.
driver = "rkt"
config {
# Use docker image with port defined
image = "docker://redis:latest"
port_map {
app = "6379-tcp"
}
}
service {
port = "app"
}
resources {
network {
mbits = 10
port "app" {
static = 12345
}
}
}
}
```

### Allocating Ports

You can allocate ports to your task using the port syntax described on the
[networking page](/docs/jobspec/networking.html).

When you use port allocation, the image manifest needs to declare public ports and host has configured network.
For more information, please refer to [rkt Networking](https://coreos.com/rkt/docs/latest/networking/overview.html).

## Client Requirements

The `rkt` driver requires rkt to be installed and in your system's `$PATH`.
Expand Down

0 comments on commit 6821210

Please sign in to comment.