-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Description
Description
Using v2.0.0-rc.3 together with user namespaces on Kubernetes v1.30, I have ran into an issue running a very basic nginx container:
apiVersion: v1
kind: Pod
metadata:
name: nginx-userns
spec:
hostUsers: false
containers:
- name: nginx
image: nginx:1.27.0
ports:
- containerPort: 80
Nginx is unable to start due a permission issue:
$ kubectl logs nginx-userns
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
nginx: [alert] could not open error log file: open() "/var/log/nginx/error.log" failed (13: Permission denied)
2024/08/15 06:40:40 [emerg] 1#1: open() "/var/log/nginx/error.log" failed (13: Permission denied)
The pod runs fine if I remove hostUsers: false
. Looking at the nginx image, what they do is create a symlink to /dev/stderr
:
root@nginx-userns:/# ls -l /var/log/nginx/error.log
lrwxrwxrwx. 1 root root 11 Aug 13 01:11 /var/log/nginx/error.log -> /dev/stderr
A way to get it running with user namespaces is to allocate a tty in the container:
spec:
hostUsers: false
containers:
- name: nginx
tty: true
So I'm not completely sure what is going on here but I have also been able to reproduce the issue by simply doing a cat /dev/stderr
with basically any container image:
spec:
hostUsers: false
containers:
- name: stdio-test
image: alpine
command: ["cat"]
args: ["/dev/stderr"]
resulting in: cat: can't open '/dev/stderr': Permission denied
Steps to reproduce the issue
- Create an nginx pod with
hostUsers: false
as described above - Observe the pod erroring with
open() "/var/log/nginx/error.log" failed (13: Permission denied)
Edit: I have also tried to reproduce this using ctr run
and using --uidmap
etc. but I could not get it to fail that way.
Describe the results you received and expected
/dev/stdout
and /dev/stderr
are not accessible when using user namespaces and no tty is allocated. This works without user namespaces so I would expect this to also work with them enabled.
What version of containerd are you using?
containerd github.com/containerd/containerd/v2 v2.0.0-rc.3 27de5fe
Any other relevant information
$ runc --version
runc version 1.2.0-rc.2
commit: v1.2.0-rc.2-0-gf2d2ee5e-dirty
spec: 1.2.0
go: go1.22.3
libseccomp: 2.5.5
$ sha256sum /usr/bin/runc
7bf38e9bc6c7a3feb5ec92e5e333015ccd0f360cdd1810a5a13f5ab81731cd62 /usr/bin/runc
$ crictl info
{
"status": {
"conditions": [
{
"type": "RuntimeReady",
"status": true,
"reason": "",
"message": ""
},
{
"type": "NetworkReady",
"status": true,
"reason": "",
"message": ""
},
{
"type": "ContainerdHasNoDeprecationWarnings",
"status": true,
"reason": "",
"message": ""
}
]
},
"cniconfig": {
"PluginDirs": [
"/opt/cni/bin"
],
"PluginConfDir": "/etc/cni/net.d",
"PluginMaxConfNum": 1,
"Prefix": "eth",
"Networks": [
{
"Config": {
"Name": "cni-loopback",
"CNIVersion": "0.3.1",
"Plugins": [
{
"Network": {
"ipam": {},
"type": "loopback"
},
"Source": "{\"type\":\"loopback\"}"
}
],
"Source": "{\n\"cniVersion\": \"0.3.1\",\n\"name\": \"cni-loopback\",\n\"plugins\": [{\n \"type\": \"loopback\"\n}]\n}"
},
"IFName": "lo"
},
{
"Config": {
"Name": "portmap",
"CNIVersion": "0.3.1",
"Plugins": [
{
"Network": {
"ipam": {},
"type": "cilium-cni"
},
"Source": "{\"enable-debug\":false,\"log-file\":\"/var/run/cilium/cilium-cni.log\",\"type\":\"cilium-cni\"}"
},
{
"Network": {
"capabilities": {
"portMappings": true
},
"ipam": {},
"type": "portmap"
},
"Source": "{\"capabilities\":{\"portMappings\":true},\"type\":\"portmap\"}"
}
],
"Source": "\n{\n \"cniVersion\": \"0.3.1\",\n \"name\": \"portmap\",\n \"plugins\": [\n {\n \"type\": \"cilium-cni\",\n \"enable-debug\": false,\n \"log-file\": \"/var/run/cilium/cilium-cni.log\"\n },\n {\n \"type\": \"portmap\",\n \"capabilities\": {\"portMappings\": true}\n }\n ]\n}\n"
},
"IFName": "eth0"
}
]
},
"config": {
"containerd": {
"defaultRuntimeName": "runc",
"runtimes": {
"runc": {
"runtimeType": "io.containerd.runc.v2",
"runtimePath": "",
"PodAnnotations": null,
"ContainerAnnotations": null,
"options": {
"BinaryName": "",
"CriuImagePath": "",
"CriuWorkPath": "",
"IoGid": 0,
"IoUid": 0,
"NoNewKeyring": false,
"Root": "",
"ShimCgroup": "",
"SystemdCgroup": true
},
"privileged_without_host_devices": false,
"privileged_without_host_devices_all_devices_allowed": false,
"baseRuntimeSpec": "",
"cniConfDir": "",
"cniMaxConfNum": 0,
"snapshotter": "",
"sandboxer": "podsandbox",
"io_type": ""
}
},
"ignoreBlockIONotEnabledErrors": false,
"ignoreRdtNotEnabledErrors": false
},
"cni": {
"binDir": "/opt/cni/bin",
"confDir": "/etc/cni/net.d",
"maxConfNum": 1,
"setupSerially": false,
"confTemplate": "",
"ipPref": "",
"useInternalLoopback": false
},
"enableSelinux": false,
"selinuxCategoryRange": 1024,
"maxContainerLogSize": 16384,
"disableCgroup": false,
"disableApparmor": false,
"restrictOOMScoreAdj": false,
"disableProcMount": false,
"unsetSeccompProfile": "",
"tolerateMissingHugetlbController": true,
"disableHugetlbController": true,
"device_ownership_from_security_context": false,
"ignoreImageDefinedVolumes": false,
"netnsMountsUnderStateDir": false,
"enableUnprivilegedPorts": true,
"enableUnprivilegedICMP": true,
"enableCDI": true,
"cdiSpecDirs": [
"/etc/cdi",
"/var/run/cdi"
],
"drainExecSyncIOTimeout": "0s",
"ignoreDeprecationWarnings": null,
"containerdRootDir": "/var/lib/containerd",
"containerdEndpoint": "/run/containerd/containerd.sock",
"rootDir": "/var/lib/containerd/io.containerd.grpc.v1.cri",
"stateDir": "/run/containerd/io.containerd.grpc.v1.cri"
},
"golang": "go1.22.4",
"lastCNILoadStatus": "OK",
"lastCNILoadStatus.default": "OK"
}
$ uname -a
Linux hostname 6.6.36-flatcar #1 SMP PREEMPT_DYNAMIC Mon Jul 1 22:47:51 -00 2024 x86_64 Intel(R) Xeon(R) Silver 4210R CPU @ 2.40GHz GenuineIntel GNU/Linux
Note: I'm not sure why this runc version is "dirty", the checksum matches the one of the release artifacts.
Show configuration if it is related to CRI plugin.
No response