问题描述
我决定使用Buildkit的无根版本从kubernetes的容器内部构建并将Docker映像推送到GCR(Google容器注册表)。
我偶然发现了这个错误:
/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
作为deployment
链接到buildkit documentation指定的service
这些资源在Google Kubernetes引擎上托管的Kubernetes集群中运行。
我正在使用以下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 documentation相同。
然后从另一个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
解决方法
无根需要在主机上执行各种准备步骤(这需要在运行kubernetes节点的VM主机上的Kubernetes外部完成)。有关步骤的完整列表,请参见rootless documentation。请注意,这些步骤因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 allow_mounts_in_userns = 1(Debian专用内核) 补丁,在Debian 10中引入)。将配置添加到 /etc/modprobe.d以保持持久性。
已知可在Debian 9和10上工作。仅从Debian 10开始才支持overlay2,并且需要上述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,但容器运行时尚不支持。运行sudo grubby --update-kernel = ALL --args =“ systemd.unified_cgroup_hierarchy = 0”以使用cgroup v1。
您可能需要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 --experimental --storage-driver vfs
在CentOS 7.7上可以使用。较早的版本需要其他配置步骤。
CentOS 7.6和更早的版本要求安装COPR软件包vbatts / shadow-utils-newxidmap。
CentOS 7.5和更早的版本要求运行sudo grubby --update-kernel = ALL --args =“ user_namespace.enable = 1”,然后重新启动。
您可能正在点击:https://github.com/moby/buildkit/issues/879
请使用GKE Ubuntu节点,而不要使用Google容器优化的OS节点。