diff --git a/docs/containers.md b/docs/containers.md new file mode 100644 index 0000000000..261a7a0792 --- /dev/null +++ b/docs/containers.md @@ -0,0 +1,47 @@ +# Container with Kubernetes + +## Capabilities + +By default, Docker containers are "unprivileged" and cannot, for example, run a Docker daemon inside a Docker container. We can have fine grain control over the capabilities using cap-add and cap-drop.More details [here](https://docs.docker.com/reference/run/#runtime-privilege-linux-capabilities-and-lxc-configuration). + +The relationship between Docker's capabilities and [Linux capabilities](http://man7.org/linux/man-pages/man7/capabilities.7.html) + +| Docker's capabilities | Linux capabilities | +| ---- | ---- | +| SETPCAP | CAP_SETPCAP | +| SYS_MODULE | CAP_SYS_MODULE | +| SYS_RAWIO | CAP_SYS_RAWIO | +| SYS_PACCT | CAP_SYS_PACCT | +| SYS_ADMIN | CAP_SYS_ADMIN | +| SYS_NICE | CAP_SYS_NICE | +| SYS_RESOURCE | CAP_SYS_RESOURCE | +| SYS_TIME | CAP_SYS_TIME | +| SYS_TTY_CONFIG | CAP_SYS_TTY_CONFIG | +| MKNOD | CAP_MKNOD | +| AUDIT_WRITE | CAP_AUDIT_WRITE | +| AUDIT_CONTROL | CAP_AUDIT_CONTROL | +| MAC_OVERRIDE | CAP_MAC_OVERRIDE | +| MAC_ADMIN | CAP_MAC_ADMIN | +| NET_ADMIN | CAP_NET_ADMIN | +| SYSLOG | CAP_SYSLOG | +| CHOWN | CAP_CHOWN | +| NET_RAW | CAP_NET_RAW | +| DAC_OVERRIDE | CAP_DAC_OVERRIDE | +| FOWNER | CAP_FOWNER | +| DAC_READ_SEARCH | CAP_DAC_READ_SEARCH | +| FSETID | CAP_FSETID | +| KILL | CAP_KILL | +| SETGID | CAP_SETGID | +| SETUID | CAP_SETUID | +| LINUX_IMMUTABLE | CAP_LINUX_IMMUTABLE | +| NET_BIND_SERVICE | CAP_NET_BIND_SERVICE | +| NET_BROADCAST | CAP_NET_BROADCAST | +| IPC_LOCK | CAP_IPC_LOCK | +| IPC_OWNER | CAP_IPC_OWNER | +| SYS_CHROOT | CAP_SYS_CHROOT | +| SYS_PTRACE | CAP_SYS_PTRACE | +| SYS_BOOT | CAP_SYS_BOOT | +| LEASE | CAP_LEASE | +| SETFCAP | CAP_SETFCAP | +| WAKE_ALARM | CAP_WAKE_ALARM | +| BLOCK_SUSPEND | CAP_BLOCK_SUSPEND | diff --git a/pkg/api/types.go b/pkg/api/types.go index 20c8b51047..a9179a16b2 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -293,6 +293,17 @@ const ( PullIfNotPresent PullPolicy = "IfNotPresent" ) +// CapabilityType represent POSIX capabilities type +type CapabilityType string + +// Capabilities represent POSIX capabilities that can be added or removed to a running container. +type Capabilities struct { + // Added capabilities + Add []CapabilityType `json:"add,omitempty"` + // Removed capabilities + Drop []CapabilityType `json:"drop,omitempty"` +} + // Container represents a single container that is expected to be run on the host. type Container struct { // Required: This must be a DNS_LABEL. Each container in a pod must @@ -319,6 +330,8 @@ type Container struct { Privileged bool `json:"privileged,omitempty"` // Optional: Policy for pulling images for this container ImagePullPolicy PullPolicy `json:"imagePullPolicy"` + // Optional: Capabilities for container. + Capabilities Capabilities `json:"capabilities,omitempty"` } // Handler defines a specific action that should be taken diff --git a/pkg/api/v1beta1/types.go b/pkg/api/v1beta1/types.go index 99d1460e05..6940734702 100644 --- a/pkg/api/v1beta1/types.go +++ b/pkg/api/v1beta1/types.go @@ -241,6 +241,17 @@ const ( PullIfNotPresent PullPolicy = "PullIfNotPresent" ) +// CapabilityType represent POSIX capabilities type +type CapabilityType string + +// Capabilities represent POSIX capabilities that can be added or removed to a running container. +type Capabilities struct { + // Added capabilities + Add []CapabilityType `json:"add,omitempty" description:"added capabilities"` + // Removed capabilities + Drop []CapabilityType `json:"drop,omitempty" description:"droped capabilities"` +} + // Container represents a single container that is expected to be run on the host. type Container struct { // Required: This must be a DNS_LABEL. Each container in a pod must @@ -267,6 +278,8 @@ type Container struct { Privileged bool `json:"privileged,omitempty" description:"whether or not the container is granted privileged status; defaults to false"` // Optional: Policy for pulling images for this container ImagePullPolicy PullPolicy `json:"imagePullPolicy" description:"image pull policy; one of PullAlways, PullNever, PullIfNotPresent; defaults to PullAlways if :latest tag is specified, or PullIfNotPresent otherwise"` + // Optional: Capabilities for container. + Capabilities Capabilities `json:"capabilities,omitempty" description:"capabilities for container"` } // Handler defines a specific action that should be taken diff --git a/pkg/api/v1beta2/types.go b/pkg/api/v1beta2/types.go index 39c1eb4953..052b4ee777 100644 --- a/pkg/api/v1beta2/types.go +++ b/pkg/api/v1beta2/types.go @@ -205,6 +205,17 @@ const ( PullIfNotPresent PullPolicy = "PullIfNotPresent" ) +// CapabilityType represent POSIX capabilities type +type CapabilityType string + +// Capabilities represent POSIX capabilities that can be added or removed to a running container. +type Capabilities struct { + // Added capabilities + Add []CapabilityType `json:"add,omitempty" description:"added capabilities"` + // Removed capabilities + Drop []CapabilityType `json:"drop,omitempty" description:"droped capabilities"` +} + // Container represents a single container that is expected to be run on the host. type Container struct { // Required: This must be a DNS_LABEL. Each container in a pod must @@ -231,6 +242,8 @@ type Container struct { Privileged bool `json:"privileged,omitempty" description:"whether or not the container is granted privileged status; defaults to false"` // Optional: Policy for pulling images for this container ImagePullPolicy PullPolicy `json:"imagePullPolicy" description:"image pull policy; one of PullAlways, PullNever, PullIfNotPresent; defaults to PullAlways if :latest tag is specified, or PullIfNotPresent otherwise"` + // Optional: Capabilities for container. + Capabilities Capabilities `json:"capabilities,omitempty" description:"capabilities for container"` } // Handler defines a specific action that should be taken diff --git a/pkg/api/v1beta3/types.go b/pkg/api/v1beta3/types.go index 015e546602..26c7a07478 100644 --- a/pkg/api/v1beta3/types.go +++ b/pkg/api/v1beta3/types.go @@ -311,6 +311,17 @@ const ( PullIfNotPresent PullPolicy = "IfNotPresent" ) +// CapabilityType represent POSIX capabilities type +type CapabilityType string + +// Capabilities represent POSIX capabilities that can be added or removed to a running container. +type Capabilities struct { + // Added capabilities + Add []CapabilityType `json:"add,omitempty"` + // Removed capabilities + Drop []CapabilityType `json:"drop,omitempty"` +} + // Container represents a single container that is expected to be run on the host. type Container struct { // Required: This must be a DNS_LABEL. Each container in a pod must @@ -337,6 +348,8 @@ type Container struct { Privileged bool `json:"privileged,omitempty"` // Optional: Policy for pulling images for this container ImagePullPolicy PullPolicy `json:"imagePullPolicy"` + // Optional: Capabilities for container. + Capabilities Capabilities `json:"capabilities,omitempty"` } // Handler defines a specific action that should be taken diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index 5d011a81cf..cc6d060d97 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -527,6 +527,20 @@ func milliCPUToShares(milliCPU int64) int64 { return shares } +func makeCapabilites(capAdd []api.CapabilityType, capDrop []api.CapabilityType) ([]string, []string) { + var ( + addCaps []string + dropCaps []string + ) + for _, cap := range capAdd { + addCaps = append(addCaps, string(cap)) + } + for _, cap := range capDrop { + dropCaps = append(dropCaps, string(cap)) + } + return addCaps, dropCaps +} + // A basic interface that knows how to execute handlers type actionHandler interface { Run(podFullName string, uid types.UID, container *api.Container, handler *api.Handler) error @@ -675,12 +689,16 @@ func (kl *Kubelet) runContainer(pod *api.BoundPod, container *api.Container, pod } else if container.Privileged { return "", fmt.Errorf("container requested privileged mode, but it is disallowed globally.") } + + capAdd, capDrop := makeCapabilites(container.Capabilities.Add, container.Capabilities.Drop) hc := &docker.HostConfig{ PortBindings: portBindings, Binds: binds, NetworkMode: netMode, IpcMode: ipcMode, Privileged: privileged, + CapAdd: capAdd, + CapDrop: capDrop, } if pod.Spec.DNSPolicy == api.DNSClusterFirst { if err := kl.applyClusterDNS(hc, pod); err != nil {