无根buildkitd在容器内引发权限错误



我决定使用Buildkit的无根版本来构建Docker映像,并将其从Kubernetes的容器中推送到GCR(Google Container Registry(。

我偶然发现了这个错误:

/moby.buildkit.v1.Control/Solve returned error: rpc error: code = Unknown desc = failed to solve with frontend dockerfile.v0: failed to read dockerfile: failed to mount /home/user/.local/tmp/buildkit-mount859701112: [{Type:bind Source:/home/user/.local/share/buildkit/runc-native/snapshots/snapshots/2 Options:[rbind ro]}]: operation not permitted

我将buildkitd作为链接到构建工具包文档中指定的servicedeployment运行这些资源在Google Kubernetes引擎上托管的Kubernete集群中运行。

我正在使用以下YAML进行部署和服务

apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: buildkitd
name: buildkitd
spec:
replicas: 1
selector:
matchLabels:
app: buildkitd
template:
metadata:
labels:
app: buildkitd
annotations:
container.apparmor.security.beta.kubernetes.io/buildkitd: unconfined
container.seccomp.security.alpha.kubernetes.io/buildkitd: unconfined
spec:
containers:
- name: buildkitd
image: moby/buildkit:master-rootless
args:
- --addr
- unix:///run/user/1000/buildkit/buildkitd.sock
- --addr
- tcp://0.0.0.0:1234
- --oci-worker-no-process-sandbox
readinessProbe:
exec:
command:
- buildctl
- debug
- workers
initialDelaySeconds: 5
periodSeconds: 30
livenessProbe:
exec:
command:
- buildctl
- debug
- workers
initialDelaySeconds: 5
periodSeconds: 30
securityContext:
runAsUser: 1000
runAsGroup: 1000
ports:
- containerPort: 1234
---
apiVersion: v1
kind: Service
metadata:
labels:
app: buildkitd
name: buildkitd
spec:
ports:
- port: 1234
protocol: TCP
selector:
app: buildkitd

它与没有TLS证书设置的buildkit文档相同。

在另一个Pod中,我使用以下命令联系Buildkit守护程序:

./bin/buildctl 
--addr tcp://buildkitd:1234 
build 
--frontend=dockerfile.v0 
--local context=. 
--local dockerfile=. 
--output type=image,name=eu.gcr.io/$PROJECT_ID/test-image,push=true

buildkitd容器成功接收到请求,但抛出上述错误。

buildctl命令的输出如下:

#1 [internal] load .dockerignore
#1 transferring context: 2B done
#1 DONE 0.1s
#2 [internal] load build definition from Dockerfile
#2 transferring dockerfile: 120B done
#2 DONE 0.1s
error: failed to solve: rpc error: code = Unknown desc = failed to solve with frontend dockerfile.v0: failed to read dockerfile: failed to mount /home/user/.local/tmp/buildkit-mount859701112: [{Type:bind Source:/home/user/.local/share/buildkit/runc-native/snapshots/snapshots/2 Options:[rbind ro]}]: operation not permitted

这是来自守护进程的错误。

让我印象深刻的是,我能够使用完全相同的YAML文件将buildkitd容器化到minikube集群中:

NAME                             READY   STATUS    RESTARTS   AGE
pod/buildkitd-5b46d94f5d-xvnbv   1/1     Running   0          36m
NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/buildkitd    ClusterIP   10.100.72.194   <none>        1234/TCP   36m
service/kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP    36m
NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/buildkitd   1/1     1            1           36m
NAME                                   DESIRED   CURRENT   READY   AGE
replicaset.apps/buildkitd-5b46d94f5d   1         1         1       36m

我在minikube内部部署服务和部署,并使用以下命令转发服务端口,以便能够访问minikube外部的部署。

kubectl port-forward service/buildkitd 2000:1234

有了这个设置,我就可以毫无问题地执行buildctl命令(图像构建和推送到GCR(。

我想知道为什么它在minikube上有效,而在Google Kubernetes引擎上无效。

这是容器启动日志,如果这对有任何帮助的话

auto snapshotter: using native
NoProcessSandbox is enabled. Note that NoProcessSandbox allows build containers to kill (and potentially ptrace) an arbitrary process in the BuildKit host namespace. NoProcessSandbox should be enabled only when the BuildKit is running in a container as an unprivileged user.
found worker "wdukby0uwmjyvf2ngj4e71s4m", labels=map[org.mobyproject.buildkit.worker.executor:oci org.mobyproject.buildkit.worker.hostname:buildkitd-5b46d94f5d-xvnbv org.mobyproject.buildkit.worker.snapshotter:native], platforms=[linux/amd64 linux/386]"
rootless mode is not supported for containerd workers. disabling containerd worker.
found 1 workers, default="wdukby0uwmjyvf2ngj4e71s4m"
currently, only the default worker can be used.
TLS is not enabled for tcp://0.0.0.0:1234. enabling mutual TLS authentication is highly recommended
running server on /run/user/1000/buildkit/buildkitd.sock
running server on [::]:1234

Rootless需要在主机上执行各种准备步骤(这需要在运行Kubernetes节点的VM主机上的Kubernetes之外执行(。有关步骤的完整列表,请参阅无根文档。请注意,这些步骤因Linux发行版而异,因为不同的发行版已经执行了部分或全部这些先决条件步骤。

Ubuntu

  • 无需任何准备。

  • overlay2存储驱动程序默认启用(Ubuntu特定的内核补丁(。

  • 已知可在Ubuntu 16.04、18.04和20.04上运行。

Debian GNU/Linux

  • 将kernel.unprivileged_userns_clone=1添加到/etc/sysctl.conf(或/etc/sysctl.d(并运行sudo sysctl--system。

  • 要使用overlay2存储驱动程序(推荐(,请运行sudo modprobe overlay permit_mounts_in_userns=1(Debian特定内核Debian 10中介绍的补丁(。将配置添加到/etc/modprobe.d用于持久性。

  • 已知用于Debian 9和10。overlay2仅在Debian 10之后才被支持,并且需要如上所述的modprobe配置。

Arch Linux

  • 将kernel.unprivileged_userns_clone=1添加到/etc/sysctl.conf(或/etc/sysctl.d(并运行sudo sysctl--system

openSUSE

  • sudo modprobe ip_tables iptable_mangle iptable_nat iptable_filter是必需的。这可能在其他发行版上也是必需的,具体取决于关于配置。

  • 已知在openSUSE 15上工作。

Fedora 31和更高版本的

  • Fedora 31默认使用cgroup v2,但containerd运行时还不支持它。运行sudo gruby--update kernel=ALL--args=";systemd.unified_group_hierarchy=0";使用cgroupv1。

  • 您可能需要sudo dnf install-y iptables。

CentOS 8

  • 您可能需要sudo dnf install-y iptables

CentOS 7

  • 将user.max_user_namespaces=28633添加到/etc/sysctl.conf(或/etc/sysctl.d(并运行sudo sysctl--system。

  • systemctl——默认情况下,用户不工作。不使用systemd:dockerd-rootless.sh--实验--存储驱动程序vfs 直接运行守护程序

  • 已知可在CentOS 7.7上工作。旧版本需要额外的配置步骤。

  • CentOS 7.6及更早版本需要安装COPR包vbatts/shadow-utils-newxidmap。

  • CentOS 7.5及更早版本要求运行sudo gruby--update kernel=ALL--args="user_namespace.enable=1";然后重新启动。

您可能遇到了以下问题:https://github.com/moby/buildkit/issues/879

请使用GKE Ubuntu节点,而不是谷歌容器优化操作系统节点。

最新更新