mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Add args and netns flag to runsc spec
Adds a netns flag to runsc spec that allows users to specify a network namespace path when creating a sample config.json file. Also, adds the ability to specify the command arguments used when running the container. This will make it easier for new users to create sample OCI bundles without having to edit the config.json by hand. PiperOrigin-RevId: 320486267
This commit is contained in:
@@ -15,8 +15,8 @@ mkdir bundle
|
||||
cd bundle
|
||||
```
|
||||
|
||||
Create a root file system for the container. We will use the Docker hello-world
|
||||
image as the basis for our container.
|
||||
Create a root file system for the container. We will use the Docker
|
||||
`hello-world` image as the basis for our container.
|
||||
|
||||
```bash
|
||||
mkdir rootfs
|
||||
@@ -24,12 +24,10 @@ docker export $(docker create hello-world) | tar -xf - -C rootfs
|
||||
```
|
||||
|
||||
Next, create an specification file called `config.json` that contains our
|
||||
container specification. We will update the default command it runs to `/hello`
|
||||
in the `hello-world` container.
|
||||
container specification. We tell the container to run the `/hello` program.
|
||||
|
||||
```bash
|
||||
runsc spec
|
||||
sed -i 's;"sh";"/hello";' config.json
|
||||
runsc spec -- /hello
|
||||
```
|
||||
|
||||
Finally run the container.
|
||||
|
||||
@@ -128,12 +128,14 @@ sudo mkdir -p rootfs/var/www/html
|
||||
sudo sh -c 'echo "Hello World!" > rootfs/var/www/html/index.html'
|
||||
```
|
||||
|
||||
Next create the `config.json` specifying the network namespace. `sudo
|
||||
/usr/local/bin/runsc spec sudo sed -i 's;"sh";"python", "-m", "http.server";'
|
||||
config.json sudo sed -i "s;\"cwd\": \"/\";\"cwd\": \"/var/www/html\";"
|
||||
config.json sudo sed -i "s;\"type\": \"network\";\"type\":
|
||||
\"network\",\n\t\t\t\t\"path\": \"/var/run/netns/${CNI_CONTAINERID}\";"
|
||||
config.json`
|
||||
Next create the `config.json` specifying the network namespace.
|
||||
|
||||
```
|
||||
sudo /usr/local/bin/runsc spec \
|
||||
--cwd /var/www/html \
|
||||
--netns /var/run/netns/${CNI_CONTAINERID} \
|
||||
-- python -m http.server
|
||||
```
|
||||
|
||||
## Run the Container
|
||||
|
||||
|
||||
+117
-103
@@ -16,124 +16,122 @@ package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/google/subcommands"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"gvisor.dev/gvisor/runsc/flag"
|
||||
)
|
||||
|
||||
func genSpec(cwd string) []byte {
|
||||
var template = fmt.Sprintf(`{
|
||||
"ociVersion": "1.0.0",
|
||||
"process": {
|
||||
"terminal": true,
|
||||
"user": {
|
||||
"uid": 0,
|
||||
"gid": 0
|
||||
func writeSpec(w io.Writer, cwd string, netns string, args []string) error {
|
||||
spec := &specs.Spec{
|
||||
Version: "1.0.0",
|
||||
Process: &specs.Process{
|
||||
Terminal: true,
|
||||
User: specs.User{
|
||||
UID: 0,
|
||||
GID: 0,
|
||||
},
|
||||
Args: args,
|
||||
Env: []string{
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"TERM=xterm",
|
||||
},
|
||||
Cwd: cwd,
|
||||
Capabilities: &specs.LinuxCapabilities{
|
||||
Bounding: []string{
|
||||
"CAP_AUDIT_WRITE",
|
||||
"CAP_KILL",
|
||||
"CAP_NET_BIND_SERVICE",
|
||||
},
|
||||
Effective: []string{
|
||||
"CAP_AUDIT_WRITE",
|
||||
"CAP_KILL",
|
||||
"CAP_NET_BIND_SERVICE",
|
||||
},
|
||||
Inheritable: []string{
|
||||
"CAP_AUDIT_WRITE",
|
||||
"CAP_KILL",
|
||||
"CAP_NET_BIND_SERVICE",
|
||||
},
|
||||
Permitted: []string{
|
||||
"CAP_AUDIT_WRITE",
|
||||
"CAP_KILL",
|
||||
"CAP_NET_BIND_SERVICE",
|
||||
},
|
||||
// TODO(gvisor.dev/issue/3166): support ambient capabilities
|
||||
},
|
||||
Rlimits: []specs.POSIXRlimit{
|
||||
{
|
||||
Type: "RLIMIT_NOFILE",
|
||||
Hard: 1024,
|
||||
Soft: 1024,
|
||||
},
|
||||
},
|
||||
},
|
||||
"args": [
|
||||
"sh"
|
||||
],
|
||||
"env": [
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"TERM=xterm"
|
||||
],
|
||||
"cwd": "%s",
|
||||
"capabilities": {
|
||||
"bounding": [
|
||||
"CAP_AUDIT_WRITE",
|
||||
"CAP_KILL",
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
],
|
||||
"effective": [
|
||||
"CAP_AUDIT_WRITE",
|
||||
"CAP_KILL",
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
],
|
||||
"inheritable": [
|
||||
"CAP_AUDIT_WRITE",
|
||||
"CAP_KILL",
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
],
|
||||
"permitted": [
|
||||
"CAP_AUDIT_WRITE",
|
||||
"CAP_KILL",
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
],
|
||||
"ambient": [
|
||||
"CAP_AUDIT_WRITE",
|
||||
"CAP_KILL",
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
]
|
||||
Root: &specs.Root{
|
||||
Path: "rootfs",
|
||||
Readonly: true,
|
||||
},
|
||||
"rlimits": [
|
||||
Hostname: "runsc",
|
||||
Mounts: []specs.Mount{
|
||||
{
|
||||
"type": "RLIMIT_NOFILE",
|
||||
"hard": 1024,
|
||||
"soft": 1024
|
||||
}
|
||||
]
|
||||
},
|
||||
"root": {
|
||||
"path": "rootfs",
|
||||
"readonly": true
|
||||
},
|
||||
"hostname": "runsc",
|
||||
"mounts": [
|
||||
{
|
||||
"destination": "/proc",
|
||||
"type": "proc",
|
||||
"source": "proc"
|
||||
},
|
||||
{
|
||||
"destination": "/dev",
|
||||
"type": "tmpfs",
|
||||
"source": "tmpfs",
|
||||
"options": []
|
||||
},
|
||||
{
|
||||
"destination": "/sys",
|
||||
"type": "sysfs",
|
||||
"source": "sysfs",
|
||||
"options": [
|
||||
"nosuid",
|
||||
"noexec",
|
||||
"nodev",
|
||||
"ro"
|
||||
]
|
||||
}
|
||||
],
|
||||
"linux": {
|
||||
"namespaces": [
|
||||
{
|
||||
"type": "pid"
|
||||
Destination: "/proc",
|
||||
Type: "proc",
|
||||
Source: "proc",
|
||||
},
|
||||
{
|
||||
"type": "network"
|
||||
Destination: "/dev",
|
||||
Type: "tmpfs",
|
||||
Source: "tmpfs",
|
||||
},
|
||||
{
|
||||
"type": "ipc"
|
||||
Destination: "/sys",
|
||||
Type: "sysfs",
|
||||
Source: "sysfs",
|
||||
Options: []string{
|
||||
"nosuid",
|
||||
"noexec",
|
||||
"nodev",
|
||||
"ro",
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "uts"
|
||||
},
|
||||
Linux: &specs.Linux{
|
||||
Namespaces: []specs.LinuxNamespace{
|
||||
{
|
||||
Type: "pid",
|
||||
},
|
||||
{
|
||||
Type: "network",
|
||||
Path: netns,
|
||||
},
|
||||
{
|
||||
Type: "ipc",
|
||||
},
|
||||
{
|
||||
Type: "uts",
|
||||
},
|
||||
{
|
||||
Type: "mount",
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "mount"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
}`, cwd)
|
||||
|
||||
return []byte(template)
|
||||
e := json.NewEncoder(w)
|
||||
e.SetIndent("", " ")
|
||||
return e.Encode(spec)
|
||||
}
|
||||
|
||||
// Spec implements subcommands.Command for the "spec" command.
|
||||
type Spec struct {
|
||||
bundle string
|
||||
cwd string
|
||||
netns string
|
||||
}
|
||||
|
||||
// Name implements subcommands.Command.Name.
|
||||
@@ -148,21 +146,26 @@ func (*Spec) Synopsis() string {
|
||||
|
||||
// Usage implements subcommands.Command.Usage.
|
||||
func (*Spec) Usage() string {
|
||||
return `spec [options] - create a new OCI bundle specification file.
|
||||
return `spec [options] [-- args...] - create a new OCI bundle specification file.
|
||||
|
||||
The spec command creates a new specification file (config.json) for a new OCI bundle.
|
||||
The spec command creates a new specification file (config.json) for a new OCI
|
||||
bundle.
|
||||
|
||||
The specification file is a starter file that runs the "sh" command in the container. You
|
||||
should edit the file to suit your needs. You can find out more about the format of the
|
||||
specification file by visiting the OCI runtime spec repository:
|
||||
The specification file is a starter file that runs the command specified by
|
||||
'args' in the container. If 'args' is not specified the default is to run the
|
||||
'sh' program.
|
||||
|
||||
While a number of flags are provided to change values in the specification, you
|
||||
can examine the file and edit it to suit your needs after this command runs.
|
||||
You can find out more about the format of the specification file by visiting
|
||||
the OCI runtime spec repository:
|
||||
https://github.com/opencontainers/runtime-spec/
|
||||
|
||||
EXAMPLE:
|
||||
$ mkdir -p bundle/rootfs
|
||||
$ cd bundle
|
||||
$ runsc spec
|
||||
$ runsc spec -- /hello
|
||||
$ docker export $(docker create hello-world) | tar -xf - -C rootfs
|
||||
$ sed -i 's;"sh";"/hello";' config.json
|
||||
$ sudo runsc run hello
|
||||
|
||||
`
|
||||
@@ -173,18 +176,29 @@ func (s *Spec) SetFlags(f *flag.FlagSet) {
|
||||
f.StringVar(&s.bundle, "bundle", ".", "path to the root of the OCI bundle")
|
||||
f.StringVar(&s.cwd, "cwd", "/", "working directory that will be set for the executable, "+
|
||||
"this value MUST be an absolute path")
|
||||
f.StringVar(&s.netns, "netns", "", "network namespace path")
|
||||
}
|
||||
|
||||
// Execute implements subcommands.Command.Execute.
|
||||
func (s *Spec) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus {
|
||||
// Grab the arguments.
|
||||
containerArgs := f.Args()
|
||||
if len(containerArgs) == 0 {
|
||||
containerArgs = []string{"sh"}
|
||||
}
|
||||
|
||||
confPath := filepath.Join(s.bundle, "config.json")
|
||||
if _, err := os.Stat(confPath); !os.IsNotExist(err) {
|
||||
Fatalf("file %q already exists", confPath)
|
||||
}
|
||||
|
||||
var spec = genSpec(s.cwd)
|
||||
configFile, err := os.OpenFile(confPath, os.O_WRONLY|os.O_CREATE, 0664)
|
||||
if err != nil {
|
||||
Fatalf("opening file %q: %v", confPath, err)
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(confPath, spec, 0664); err != nil {
|
||||
err = writeSpec(configFile, s.cwd, s.netns, containerArgs)
|
||||
if err != nil {
|
||||
Fatalf("writing to %q: %v", confPath, err)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user