Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions completions/bash/crio
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ h
--default-sysctls
--default-transport
--default-ulimits
--drop-infra-ctr
--enable-metrics
--gid-mappings
--global-auth-file
Expand Down
1 change: 1 addition & 0 deletions completions/fish/crio.fish
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ complete -c crio -n '__fish_crio_no_subcommand' -f -l default-runtime -r -d 'Def
complete -c crio -n '__fish_crio_no_subcommand' -f -l default-sysctls -r -d 'Sysctls to add to the containers'
complete -c crio -n '__fish_crio_no_subcommand' -f -l default-transport -r -d 'A prefix to prepend to image names that cannot be pulled as-is'
complete -c crio -n '__fish_crio_no_subcommand' -f -l default-ulimits -r -d 'Ulimits to apply to containers by default (name=soft:hard) (default: [])'
complete -c crio -n '__fish_crio_no_subcommand' -f -l drop-infra-ctr -d 'Determines whether pods are created without an infra container (when the pod is not using a pod level PID namespace). Requires ManageNSLifecycle to be true (default: false)'
complete -c crio -n '__fish_crio_no_subcommand' -f -l enable-metrics -d 'Enable metrics endpoint for the server on localhost:9090'
complete -c crio -n '__fish_crio_no_subcommand' -f -l gid-mappings -r -d 'Specify the GID mappings to use for the user namespace (default: "")'
complete -c crio -n '__fish_crio_no_subcommand' -l global-auth-file -r -d 'Path to a file like /var/lib/kubelet/config.json holding credentials necessary for pulling images from secure registries (default: "")'
Expand Down
2 changes: 1 addition & 1 deletion completions/zsh/_crio
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ it later with **--config**. Global options will modify the output.' 'version:dis
_describe 'commands' cmds

local -a opts
opts=('--additional-devices' '--allow-userns-annotation' '--apparmor-profile' '--big-files-temporary-dir' '--bind-mount-prefix' '--cgroup-manager' '--cni-config-dir' '--cni-default-network' '--cni-plugin-dir' '--config' '--config-dir' '--conmon' '--conmon-cgroup' '--conmon-env' '--container-attach-socket-dir' '--container-exits-dir' '--ctr-stop-timeout' '--decryption-keys-path' '--default-capabilities' '--default-env' '--default-mounts-file' '--default-runtime' '--default-sysctls' '--default-transport' '--default-ulimits' '--enable-metrics' '--gid-mappings' '--global-auth-file' '--grpc-max-recv-msg-size' '--grpc-max-send-msg-size' '--hooks-dir' '--image-volumes' '--insecure-registry' '--listen' '--log' '--log-dir' '--log-filter' '--log-format' '--log-journald' '--log-level' '--log-size-max' '--manage-ns-lifecycle' '--metrics-port' '--metrics-socket' '--namespaces-dir' '--no-pivot' '--pause-command' '--pause-image' '--pause-image-auth-file' '--pids-limit' '--pinns-path' '--profile' '--profile-port' '--read-only' '--registries-conf' '--registry' '--root' '--runroot' '--runtimes' '--seccomp-profile' '--selinux' '--signature-policy' '--storage-driver' '--storage-opt' '--stream-address' '--stream-enable-tls' '--stream-port' '--stream-tls-ca' '--stream-tls-cert' '--stream-tls-key' '--uid-mappings' '--version-file' '--version-file-persist' '--help' '--version')
opts=('--additional-devices' '--allow-userns-annotation' '--apparmor-profile' '--big-files-temporary-dir' '--bind-mount-prefix' '--cgroup-manager' '--cni-config-dir' '--cni-default-network' '--cni-plugin-dir' '--config' '--config-dir' '--conmon' '--conmon-cgroup' '--conmon-env' '--container-attach-socket-dir' '--container-exits-dir' '--ctr-stop-timeout' '--decryption-keys-path' '--default-capabilities' '--default-env' '--default-mounts-file' '--default-runtime' '--default-sysctls' '--default-transport' '--default-ulimits' '--drop-infra-ctr' '--enable-metrics' '--gid-mappings' '--global-auth-file' '--grpc-max-recv-msg-size' '--grpc-max-send-msg-size' '--hooks-dir' '--image-volumes' '--insecure-registry' '--listen' '--log' '--log-dir' '--log-filter' '--log-format' '--log-journald' '--log-level' '--log-size-max' '--manage-ns-lifecycle' '--metrics-port' '--metrics-socket' '--namespaces-dir' '--no-pivot' '--pause-command' '--pause-image' '--pause-image-auth-file' '--pids-limit' '--pinns-path' '--profile' '--profile-port' '--read-only' '--registries-conf' '--registry' '--root' '--runroot' '--runtimes' '--seccomp-profile' '--selinux' '--signature-policy' '--storage-driver' '--storage-opt' '--stream-address' '--stream-enable-tls' '--stream-port' '--stream-tls-ca' '--stream-tls-cert' '--stream-tls-key' '--uid-mappings' '--version-file' '--version-file-persist' '--help' '--version')
_describe 'global options' opts

return
Expand Down
3 changes: 3 additions & 0 deletions docs/crio.8.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ crio
[--default-sysctls]=[value]
[--default-transport]=[value]
[--default-ulimits]=[value]
[--drop-infra-ctr]
[--enable-metrics]
[--gid-mappings]=[value]
[--global-auth-file]=[value]
Expand Down Expand Up @@ -170,6 +171,8 @@ crio [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...]

**--default-ulimits**="": Ulimits to apply to containers by default (name=soft:hard) (default: []) (default: [])

**--drop-infra-ctr**: Determines whether pods are created without an infra container (when the pod is not using a pod level PID namespace). Requires ManageNSLifecycle to be true (default: false)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest we implicitly set ManageNSLifecycle to true if this toggle switches on.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is more clear (as an experimental feature) that we fail quickly when it's not set. By the time DropInfra is set to true by default, I like to think we won't have ManageNSLifecycle as an option anymore


**--enable-metrics**: Enable metrics endpoint for the server on localhost:9090

**--gid-mappings**="": Specify the GID mappings to use for the user namespace (default: "")
Expand Down
4 changes: 4 additions & 0 deletions docs/crio.conf.5.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ the container runtime configuration.
**manage_ns_lifecycle**=true
Determines whether we pin and remove namespaces and manage their lifecycle.

**drop_infra_ctr**=false
Determines whether we drop the infra container when a pod does not have a private PID namespace, and does not use a kernel separating runtime (like kata).
Requies **manage_ns_lifecycle** to be true.

**namespaces_dir**="/var/run"
The directory where the state of the managed namespaces gets tracked. Only used when manage_ns_lifecycle is true

Expand Down
8 changes: 8 additions & 0 deletions internal/criocli/criocli.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,9 @@ func mergeConfig(config *libconfig.Config, ctx *cli.Context) error {
if ctx.IsSet("manage-ns-lifecycle") {
config.ManageNSLifecycle = ctx.Bool("manage-ns-lifecycle")
}
if ctx.IsSet("drop-infra-ctr") {
config.DropInfraCtr = ctx.Bool("drop-infra-ctr")
}
if ctx.IsSet("namespaces-dir") {
config.NamespacesDir = ctx.String("namespaces-dir")
}
Expand Down Expand Up @@ -725,6 +728,11 @@ func getCrioFlags(defConf *libconfig.Config) []cli.Flag {
Usage: fmt.Sprintf("Determines whether we pin and remove IPC, network and UTS namespaces and manage their lifecycle (default: %v)", defConf.ManageNSLifecycle),
EnvVars: []string{"CONTAINER_MANAGE_NS_LIFECYCLE"},
},
&cli.BoolFlag{
Name: "drop-infra-ctr",
Usage: fmt.Sprintf("Determines whether pods are created without an infra container (when the pod is not using a pod level PID namespace). Requires ManageNSLifecycle to be true (default: %v)", defConf.DropInfraCtr),
EnvVars: []string{"CONTAINER_DROP_INFRA_CTR"},
},
&cli.StringFlag{
Name: "pinns-path",
Usage: fmt.Sprintf("The path to find the pinns binary, which is needed to manage namespace lifecycle. Will be searched for in $PATH if empty (default: %q)", defConf.PinnsPath),
Expand Down
80 changes: 56 additions & 24 deletions internal/lib/container_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/cri-o/cri-o/internal/lib/sandbox"
"github.com/cri-o/cri-o/internal/oci"
"github.com/cri-o/cri-o/internal/storage"
crioann "github.com/cri-o/cri-o/pkg/annotations"
libconfig "github.com/cri-o/cri-o/pkg/config"
json "github.com/json-iterator/go"
rspec "github.com/opencontainers/runtime-spec/specs-go"
Expand All @@ -31,10 +32,6 @@ import (
// `io.container.manager`.
const ContainerManagerCRIO = "cri-o"

// UsernsMode is the user namespace mode to use
// TODO: move to the annotations pkg.
const UsernsModeAnnotation = "io.kubernetes.cri-o.userns-mode"

// ContainerServer implements the ImageServer
type ContainerServer struct {
runtime *oci.Runtime
Expand Down Expand Up @@ -203,7 +200,7 @@ func (c *ContainerServer) LoadSandbox(id string) (retErr error) {
return errors.Wrap(err, "parsing created timestamp annotation")
}

sb, err := sandbox.New(id, m.Annotations[annotations.Namespace], name, m.Annotations[annotations.KubeName], filepath.Dir(m.Annotations[annotations.LogPath]), labels, kubeAnnotations, processLabel, mountLabel, &metadata, m.Annotations[annotations.ShmPath], m.Annotations[annotations.CgroupParent], privileged, m.Annotations[annotations.RuntimeHandler], m.Annotations[annotations.ResolvPath], m.Annotations[annotations.HostName], portMappings, hostNetwork, created, m.Annotations[UsernsModeAnnotation])
sb, err := sandbox.New(id, m.Annotations[annotations.Namespace], name, m.Annotations[annotations.KubeName], filepath.Dir(m.Annotations[annotations.LogPath]), labels, kubeAnnotations, processLabel, mountLabel, &metadata, m.Annotations[annotations.ShmPath], m.Annotations[annotations.CgroupParent], privileged, m.Annotations[annotations.RuntimeHandler], m.Annotations[annotations.ResolvPath], m.Annotations[annotations.HostName], portMappings, hostNetwork, created, m.Annotations[crioann.UsernsModeAnnotation])
if err != nil {
return err
}
Expand Down Expand Up @@ -262,7 +259,9 @@ func (c *ContainerServer) LoadSandbox(id string) (retErr error) {
return err
}

cname, err := c.ReserveContainerName(m.Annotations[annotations.ContainerID], m.Annotations[annotations.ContainerName])
cID := m.Annotations[annotations.ContainerID]

cname, err := c.ReserveContainerName(cID, m.Annotations[annotations.ContainerName])
if err != nil {
return err
}
Expand All @@ -272,21 +271,34 @@ func (c *ContainerServer) LoadSandbox(id string) (retErr error) {
}
}()

scontainer, err := oci.NewContainer(m.Annotations[annotations.ContainerID], cname, sandboxPath, m.Annotations[annotations.LogPath], labels, m.Annotations, kubeAnnotations, m.Annotations[annotations.Image], "", "", nil, id, false, false, false, sb.RuntimeHandler(), sandboxDir, created, m.Annotations["org.opencontainers.image.stopSignal"])
if err != nil {
return err
var scontainer *oci.Container

// We should not take whether the server currently has DropInfraCtr specified, but rather
// whether the server used to.
wasSpoofed := false
if spoofed, ok := m.Annotations[crioann.SpoofedContainer]; ok && spoofed == "true" {
wasSpoofed = true
}
scontainer.SetSpec(&m)
scontainer.SetMountPoint(m.Annotations[annotations.MountPoint])

if m.Annotations[annotations.Volumes] != "" {
containerVolumes := []oci.ContainerVolume{}
if err = json.Unmarshal([]byte(m.Annotations[annotations.Volumes]), &containerVolumes); err != nil {
return fmt.Errorf("failed to unmarshal container volumes: %v", err)
if !wasSpoofed {
scontainer, err = oci.NewContainer(m.Annotations[annotations.ContainerID], cname, sandboxPath, m.Annotations[annotations.LogPath], labels, m.Annotations, kubeAnnotations, m.Annotations[annotations.Image], "", "", nil, id, false, false, false, sb.RuntimeHandler(), sandboxDir, created, m.Annotations["org.opencontainers.image.stopSignal"])
if err != nil {
return err
}
for _, cv := range containerVolumes {
scontainer.AddVolume(cv)
scontainer.SetSpec(&m)
scontainer.SetMountPoint(m.Annotations[annotations.MountPoint])

if m.Annotations[annotations.Volumes] != "" {
containerVolumes := []oci.ContainerVolume{}
if err = json.Unmarshal([]byte(m.Annotations[annotations.Volumes]), &containerVolumes); err != nil {
return fmt.Errorf("failed to unmarshal container volumes: %v", err)
}
for _, cv := range containerVolumes {
scontainer.AddVolume(cv)
}
}
} else {
scontainer = oci.NewSpoofedContainer(cID, cname, labels, created, sandboxPath)
}

if err := c.ContainerStateFromDisk(scontainer); err != nil {
Expand All @@ -296,14 +308,37 @@ func (c *ContainerServer) LoadSandbox(id string) (retErr error) {
// We write back the state because it is possible that crio did not have a chance to
// read the exit file and persist exit code into the state on reboot.
if err := c.ContainerStateToDisk(scontainer); err != nil {
return fmt.Errorf("failed to write container state to disk %q: %v", scontainer.ID(), err)
return fmt.Errorf("failed to write container %q state to disk: %v", scontainer.ID(), err)
}

sb.SetCreated()
if err := label.ReserveLabel(processLabel); err != nil {
if err := sb.SetInfraContainer(scontainer); err != nil {
return err
}
if err := sb.SetInfraContainer(scontainer); err != nil {

// We add an NS only if we can load a permanent one.
// Otherwise, the sandbox will live in the host namespace.
if c.config.ManageNSLifecycle || wasSpoofed {
namespacesToJoin := []struct {
rspecNS rspec.LinuxNamespaceType
joinFunc func(string) error
}{
{rspecNS: rspec.NetworkNamespace, joinFunc: sb.NetNsJoin},
{rspecNS: rspec.IPCNamespace, joinFunc: sb.IpcNsJoin},
{rspecNS: rspec.UTSNamespace, joinFunc: sb.UtsNsJoin},
{rspecNS: rspec.UserNamespace, joinFunc: sb.UserNsJoin},
}
for _, namespaceToJoin := range namespacesToJoin {
path, err := configNsPath(&m, namespaceToJoin.rspecNS)
if err == nil {
if nsErr := namespaceToJoin.joinFunc(path); err != nil {
return nsErr
}
}
}
}

sb.SetCreated()
if err := label.ReserveLabel(processLabel); err != nil {
return err
}

Expand Down Expand Up @@ -468,9 +503,6 @@ func (c *ContainerServer) ContainerStateFromDisk(ctr *oci.Container) error {
// ContainerStateToDisk writes the container's state information to a JSON file
// on disk
func (c *ContainerServer) ContainerStateToDisk(ctr *oci.Container) error {
if ctr == nil {
return nil
}
if err := c.Runtime().UpdateContainerStatus(ctr); err != nil {
logrus.Warnf("error updating the container status %q: %v", ctr.ID(), err)
}
Expand Down
12 changes: 7 additions & 5 deletions internal/lib/sandbox/namespaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,19 +69,21 @@ func (m *ManagedNamespace) Path() string {

// CreateManagedNamespaces calls pinnsPath on all the managed namespaces for the sandbox.
// It returns a slice of ManagedNamespaces it created.
func (s *Sandbox) CreateManagedNamespaces(managedNamespaces []NSType, idMappings *idtools.IDMappings, cfg *config.Config) ([]*ManagedNamespace, error) {
return s.CreateNamespacesWithFunc(managedNamespaces, idMappings, cfg, pinNamespaces)
func (s *Sandbox) CreateManagedNamespaces(managedNamespaces []NSType, idMappings *idtools.IDMappings, sysctls map[string]string, cfg *config.Config) ([]*ManagedNamespace, error) {
return s.CreateNamespacesWithFunc(managedNamespaces, idMappings, sysctls, cfg, pinNamespaces)
}

type namespacePinner func([]NSType, *config.Config, *idtools.IDMappings, map[string]string) ([]NamespaceIface, error)

// CreateManagedNamespacesWithFunc is mainly added for testing purposes. There's no point in actually calling the pinns binary
// in unit tests, so this function allows the actual pin func to be abstracted out. Every other caller should use CreateManagedNamespaces
func (s *Sandbox) CreateNamespacesWithFunc(managedNamespaces []NSType, idMappings *idtools.IDMappings, cfg *config.Config, pinFunc func([]NSType, *config.Config, *idtools.IDMappings) ([]NamespaceIface, error)) (mns []*ManagedNamespace, retErr error) {
func (s *Sandbox) CreateNamespacesWithFunc(managedNamespaces []NSType, idMappings *idtools.IDMappings, sysctls map[string]string, cfg *config.Config, pinFunc namespacePinner) (mns []*ManagedNamespace, retErr error) {
typesAndPaths := make([]*ManagedNamespace, 0, 4)
if len(managedNamespaces) == 0 {
return typesAndPaths, nil
}

namespaces, err := pinFunc(managedNamespaces, cfg, idMappings)
namespaces, err := pinFunc(managedNamespaces, cfg, idMappings, sysctls)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -305,7 +307,7 @@ func (s *Sandbox) nsPath(ns NamespaceIface, nsType NSType) string {
// if the infra container is nil, pid is returned negative
func infraPid(infra *oci.Container) int {
pid := -1
if infra != nil {
if infra != nil && !infra.Spoofed() {
var err error
pid, err = infra.Pid()
// There are some cases where ErrNotInitialized is expected.
Expand Down
18 changes: 17 additions & 1 deletion internal/lib/sandbox/namespaces_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"os"
"os/exec"
"path/filepath"
"strings"
"sync"

nspkg "github.com/containernetworking/plugins/pkg/ns"
Expand Down Expand Up @@ -64,7 +65,7 @@ func getMappingsForPinns(mappings []idtools.IDMap) string {

// Creates a new persistent namespace and returns an object
// representing that namespace, without switching to it
func pinNamespaces(nsTypes []NSType, cfg *config.Config, idMappings *idtools.IDMappings) ([]NamespaceIface, error) {
func pinNamespaces(nsTypes []NSType, cfg *config.Config, idMappings *idtools.IDMappings, sysctls map[string]string) ([]NamespaceIface, error) {
typeToArg := map[NSType]string{
IPCNS: "-i",
UTSNS: "-u",
Expand All @@ -77,6 +78,11 @@ func pinNamespaces(nsTypes []NSType, cfg *config.Config, idMappings *idtools.IDM
"-d", cfg.NamespacesDir,
"-f", pinnedNamespace,
}

if len(sysctls) != 0 {
pinnsArgs = append(pinnsArgs, "-s", getSysctlForPinns(sysctls))
}

type namespaceInfo struct {
path string
nsType NSType
Expand Down Expand Up @@ -152,6 +158,16 @@ func pinNamespaces(nsTypes []NSType, cfg *config.Config, idMappings *idtools.IDM
return returnedNamespaces, nil
}

func getSysctlForPinns(sysctls map[string]string) string {
// this assumes there's no sysctl with a `+` in it
const pinnsSysctlDelim = "+"
g := new(bytes.Buffer)
for key, value := range sysctls {
fmt.Fprintf(g, "'%s=%s'%s", key, value, pinnsSysctlDelim)
}
return strings.TrimSuffix(g.String(), pinnsSysctlDelim)
}

// getNamespace takes a path, checks if it is a namespace, and if so
// returns a Namespace
func getNamespace(nsPath string) (*Namespace, error) {
Expand Down
Loading