Add hostport support

Signed-off-by: Lantao Liu <lantaol@google.com>
This commit is contained in:
Lantao Liu 2017-08-23 01:25:00 +00:00
parent 8f898cb3b8
commit f6d99abcf4
7 changed files with 124 additions and 26 deletions

View File

@ -32,7 +32,7 @@ ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"/..
BUILD_IMAGE=golang:1.8 BUILD_IMAGE=golang:1.8
RUNC_PKG=github.com/opencontainers/runc RUNC_PKG=github.com/opencontainers/runc
CNI_PKG=github.com/containernetworking/cni CNI_PKG=github.com/containernetworking/plugins
CNI_DIR=/opt/cni CNI_DIR=/opt/cni
CNI_CONFIG_DIR=/etc/cni/net.d CNI_CONFIG_DIR=/etc/cni/net.d
CONTAINERD_PKG=github.com/containerd/containerd CONTAINERD_PKG=github.com/containerd/containerd
@ -51,31 +51,33 @@ go get -d ${CNI_PKG}/...
cd ${GOPATH}/src/${CNI_PKG} cd ${GOPATH}/src/${CNI_PKG}
git fetch --all git fetch --all
git checkout ${CNI_VERSION} git checkout ${CNI_VERSION}
./build ./build.sh
sudo mkdir -p ${CNI_DIR} sudo mkdir -p ${CNI_DIR}
sudo cp -r ./bin ${CNI_DIR} sudo cp -r ./bin ${CNI_DIR}
sudo mkdir -p ${CNI_CONFIG_DIR} sudo mkdir -p ${CNI_CONFIG_DIR}
sudo bash -c 'cat >'${CNI_CONFIG_DIR}'/10-containerd-bridge.conf <<EOF sudo bash -c 'cat >'${CNI_CONFIG_DIR}'/10-containerd-net.conflist <<EOF
{ {
"cniVersion": "0.2.0", "cniVersion": "0.3.1",
"name": "containerd-bridge", "name": "containerd-net",
"type": "bridge", "plugins": [
"bridge": "cni0", {
"isGateway": true, "type": "bridge",
"ipMasq": true, "bridge": "cni0",
"ipam": { "isGateway": true,
"ipMasq": true,
"ipam": {
"type": "host-local", "type": "host-local",
"subnet": "10.88.0.0/16", "subnet": "10.88.0.0/16",
"routes": [ "routes": [
{ "dst": "0.0.0.0/0" } { "dst": "0.0.0.0/0" }
] ]
}
},
{
"type": "portmap",
"capabilities": {"portMappings": true}
} }
} ]
EOF'
sudo bash -c 'cat >'${CNI_CONFIG_DIR}'/99-loopback.conf <<EOF
{
"cniVersion": "0.2.0",
"type": "loopback"
} }
EOF' EOF'

View File

@ -21,7 +21,7 @@ source $(dirname "${BASH_SOURCE[0]}")/test-utils.sh
# FOCUS focuses the test to run. # FOCUS focuses the test to run.
FOCUS=${FOCUS:-} FOCUS=${FOCUS:-}
# SKIP skips the test to skip. # SKIP skips the test to skip.
SKIP=${SKIP:-"attach|RunAsUser|host port"} SKIP=${SKIP:-"attach|RunAsUser"}
REPORT_DIR=${REPORT_DIR:-"/tmp/test-cri"} REPORT_DIR=${REPORT_DIR:-"/tmp/test-cri"}
if [[ -z "${GOPATH}" ]]; then if [[ -z "${GOPATH}" ]]; then

View File

@ -25,6 +25,7 @@ import (
"time" "time"
"github.com/containerd/containerd" "github.com/containerd/containerd"
"github.com/cri-o/ocicni"
"github.com/golang/glog" "github.com/golang/glog"
imagespec "github.com/opencontainers/image-spec/specs-go/v1" imagespec "github.com/opencontainers/image-spec/specs-go/v1"
runtimespec "github.com/opencontainers/runtime-spec/specs-go" runtimespec "github.com/opencontainers/runtime-spec/specs-go"
@ -169,14 +170,20 @@ func (c *criContainerdService) RunPodSandbox(ctx context.Context, r *runtime.Run
if !config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetHostNetwork() { if !config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetHostNetwork() {
// Setup network for sandbox. // Setup network for sandbox.
// TODO(random-liu): [P2] Replace with permanent network namespace. // TODO(random-liu): [P2] Replace with permanent network namespace.
podName := config.GetMetadata().GetName() podNetwork := ocicni.PodNetwork{
if err = c.netPlugin.SetUpPod(sandbox.NetNS, config.GetMetadata().GetNamespace(), podName, id); err != nil { Name: config.GetMetadata().GetName(),
Namespace: config.GetMetadata().GetNamespace(),
ID: id,
NetNS: sandbox.NetNS,
PortMappings: toCNIPortMappings(config.GetPortMappings()),
}
if err = c.netPlugin.SetUpPod(podNetwork); err != nil {
return nil, fmt.Errorf("failed to setup network for sandbox %q: %v", id, err) return nil, fmt.Errorf("failed to setup network for sandbox %q: %v", id, err)
} }
defer func() { defer func() {
if retErr != nil { if retErr != nil {
// Teardown network if an error is returned. // Teardown network if an error is returned.
if err := c.netPlugin.TearDownPod(sandbox.NetNS, config.GetMetadata().GetNamespace(), podName, id); err != nil { if err := c.netPlugin.TearDownPod(podNetwork); err != nil {
glog.Errorf("failed to destroy network for sandbox %q: %v", id, err) glog.Errorf("failed to destroy network for sandbox %q: %v", id, err)
} }
} }
@ -372,3 +379,20 @@ func (c *criContainerdService) unmountSandboxFiles(rootDir string, config *runti
} }
return nil return nil
} }
// toCNIPortMappings converts CRI port mappings to CNI.
func toCNIPortMappings(criPortMappings []*runtime.PortMapping) []ocicni.PortMapping {
var portMappings []ocicni.PortMapping
for _, mapping := range criPortMappings {
if mapping.HostPort <= 0 {
continue
}
portMappings = append(portMappings, ocicni.PortMapping{
HostPort: mapping.HostPort,
ContainerPort: mapping.ContainerPort,
Protocol: strings.ToLower(mapping.Protocol.String()),
HostIP: mapping.HostIp,
})
}
return portMappings
}

View File

@ -20,6 +20,7 @@ import (
"os" "os"
"testing" "testing"
"github.com/cri-o/ocicni"
imagespec "github.com/opencontainers/image-spec/specs-go/v1" imagespec "github.com/opencontainers/image-spec/specs-go/v1"
runtimespec "github.com/opencontainers/runtime-spec/specs-go" runtimespec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -303,5 +304,70 @@ options timeout:1
} }
} }
func TestToCNIPortMappings(t *testing.T) {
for desc, test := range map[string]struct {
criPortMappings []*runtime.PortMapping
cniPortMappings []ocicni.PortMapping
}{
"empty CRI port mapping should map to empty CNI port mapping": {},
"CRI port mapping should be converted to CNI port mapping properly": {
criPortMappings: []*runtime.PortMapping{
{
Protocol: runtime.Protocol_UDP,
ContainerPort: 1234,
HostPort: 5678,
HostIp: "123.124.125.126",
},
{
Protocol: runtime.Protocol_TCP,
ContainerPort: 4321,
HostPort: 8765,
HostIp: "126.125.124.123",
},
},
cniPortMappings: []ocicni.PortMapping{
{
HostPort: 5678,
ContainerPort: 1234,
Protocol: "udp",
HostIP: "123.124.125.126",
},
{
HostPort: 8765,
ContainerPort: 4321,
Protocol: "tcp",
HostIP: "126.125.124.123",
},
},
},
"CRI port mapping without host port should be skipped": {
criPortMappings: []*runtime.PortMapping{
{
Protocol: runtime.Protocol_UDP,
ContainerPort: 1234,
HostIp: "123.124.125.126",
},
{
Protocol: runtime.Protocol_TCP,
ContainerPort: 4321,
HostPort: 8765,
HostIp: "126.125.124.123",
},
},
cniPortMappings: []ocicni.PortMapping{
{
HostPort: 8765,
ContainerPort: 4321,
Protocol: "tcp",
HostIP: "126.125.124.123",
},
},
},
} {
t.Logf("TestCase %q", desc)
assert.Equal(t, test.cniPortMappings, toCNIPortMappings(test.criPortMappings))
}
}
// TODO(random-liu): [P1] Add unit test for different error cases to make sure // TODO(random-liu): [P1] Add unit test for different error cases to make sure
// the function cleans up on error properly. // the function cleans up on error properly.

View File

@ -64,11 +64,11 @@ func (c *criContainerdService) PodSandboxStatus(ctx context.Context, r *runtime.
state = runtime.PodSandboxState_SANDBOX_READY state = runtime.PodSandboxState_SANDBOX_READY
} }
} }
ip, err := c.netPlugin.GetContainerNetworkStatus(sandbox.NetNS, sandbox.Config.GetMetadata().GetNamespace(), sandbox.Config.GetMetadata().GetName(), id) ip, err := c.netPlugin.GetPodNetworkStatus(sandbox.NetNS)
if err != nil { if err != nil {
// Ignore the error on network status // Ignore the error on network status
ip = "" ip = ""
glog.V(4).Infof("GetContainerNetworkStatus returns error: %v", err) glog.V(4).Infof("GetPodNetworkStatus returns error: %v", err)
} }
return &runtime.PodSandboxStatusResponse{Status: toCRISandboxStatus(sandbox.Metadata, state, ip)}, nil return &runtime.PodSandboxStatusResponse{Status: toCRISandboxStatus(sandbox.Metadata, state, ip)}, nil

View File

@ -22,6 +22,7 @@ import (
"github.com/containerd/containerd" "github.com/containerd/containerd"
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/cri-o/ocicni"
"github.com/golang/glog" "github.com/golang/glog"
"golang.org/x/net/context" "golang.org/x/net/context"
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
@ -65,8 +66,13 @@ func (c *criContainerdService) StopPodSandbox(ctx context.Context, r *runtime.St
_, err = c.os.Stat(sandbox.NetNS) _, err = c.os.Stat(sandbox.NetNS)
if err == nil { if err == nil {
if !sandbox.Config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetHostNetwork() { if !sandbox.Config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetHostNetwork() {
if teardownErr := c.netPlugin.TearDownPod(sandbox.NetNS, sandbox.Config.GetMetadata().GetNamespace(), if teardownErr := c.netPlugin.TearDownPod(ocicni.PodNetwork{
sandbox.Config.GetMetadata().GetName(), id); teardownErr != nil { Name: sandbox.Config.GetMetadata().GetName(),
Namespace: sandbox.Config.GetMetadata().GetNamespace(),
ID: id,
NetNS: sandbox.NetNS,
PortMappings: toCNIPortMappings(sandbox.Config.GetPortMappings()),
}); teardownErr != nil {
return nil, fmt.Errorf("failed to destroy network for sandbox %q: %v", id, teardownErr) return nil, fmt.Errorf("failed to destroy network for sandbox %q: %v", id, teardownErr)
} }
} }

View File

@ -24,8 +24,8 @@ import (
"github.com/containerd/containerd/api/services/tasks/v1" "github.com/containerd/containerd/api/services/tasks/v1"
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
"github.com/containerd/containerd/images" "github.com/containerd/containerd/images"
"github.com/cri-o/ocicni"
"github.com/golang/glog" "github.com/golang/glog"
"github.com/kubernetes-incubator/cri-o/pkg/ocicni"
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
"k8s.io/kubernetes/pkg/kubelet/server/streaming" "k8s.io/kubernetes/pkg/kubelet/server/streaming"