如何在不禁用沙箱的情况下在GKE Autopilot上运行Puppeteer
问题背景
我尝试在不禁用沙箱的情况下在GKE Autopilot上运行Puppeteer。镜像在Google Cloud Run上运行完全正常,但在GKE Autopilot上却无法运行。本地Docker运行该镜像需要添加--cap-add=SYS_ADMIN参数,但GKE Autopilot不允许这个权限,报错如下:
linux capability 'SYS_ADMIN' on container 'xxxxx-1' not allowed; Autopilot only allows the capabilities: 'AUDIT_WRITE,CHOWN,DAC_OVERRIDE,FOWNER,FSETID,KILL,MKNOD,NET_BIND_SERVICE,NET_RAW,SETFCAP,SETGID,SETPCAP,SETUID,SYS_CHROOT,SYS_PTRACE'
我尝试添加了上述所有允许的权限,但问题仍未解决。请问有没有其他方法实现需求?禁用沙箱是唯一的解决方案吗?
参考Dockerfile:
FROM node:16 WORKDIR /app # Install latest chrome dev package and fonts to support major charsets (Chinese, Japanese, Arabic, Hebrew, Thai and a few others) # Note: this installs the necessary libs to make the bundled version of Chromium that Puppeteer # installs, work. RUN apt-get update \ && apt-get install -y wget gnupg \ && wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \ && sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \ && apt-get update \ && apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 \ --no-install-recommends \ && rm -rf /var/lib/apt/lists/* COPY . . RUN yarn install --frozen-lockfile \ && yarn build \ && groupadd -r pptruser && useradd -r -g pptruser -G audio,video pptruser \ && mkdir -p /home/pptruser/Downloads \ && chown -R pptruser:pptruser /home/pptruser \ && chown -R pptruser:pptruser /app # Run everything after as non-privileged user. USER pptruser CMD node dist/server.js
可行解决方案
1. 调整Puppeteer启动配置,适配GKE Autopilot环境
你的Dockerfile已安装系统版Chrome,优先使用它而非Puppeteer内置的Chromium,同时添加适配GKE环境的启动参数:
const browser = await puppeteer.launch({ executablePath: '/usr/bin/google-chrome-stable', args: [ '--sandbox', // 保留沙箱 '--disable-dev-shm-usage', // 避免/dev/shm空间不足导致崩溃 '--disable-gpu', '--no-zygote', // 禁用zygote进程,降低权限依赖 '--window-size=1920,1080' ] });
--disable-dev-shm-usage会让Chrome使用/tmp目录替代默认的/dev/shm,解决GKE容器中共享内存不足的问题;--no-zygote可以避免Chrome创建子进程时的权限限制。
2. 配置Deployment的安全上下文与共享内存挂载
在GKE Deployment的YAML中,添加允许的权限并挂载足够的共享内存:
spec: template: spec: containers: - name: your-container-name image: your-image-url securityContext: capabilities: add: ["AUDIT_WRITE", "CHOWN", "DAC_OVERRIDE", "FOWNER", "FSETID", "KILL", "MKNOD", "NET_BIND_SERVICE", "NET_RAW", "SETFCAP", "SETGID", "SETPCAP", "SETUID", "SYS_CHROOT", "SYS_PTRACE"] runAsUser: 1000 # 匹配Dockerfile中pptruser的UID(默认useradd创建的UID为1000) runAsNonRoot: true volumeMounts: - mountPath: /dev/shm name: dshm volumes: - name: dshm emptyDir: medium: Memory sizeLimit: 2Gi # 给Chrome分配足够的共享内存
3. 验证文件权限一致性
确保Dockerfile中创建的pptruser对/app和/home/pptruser目录拥有完全权限,你的现有Dockerfile已经完成了这一步,但可以通过id pptruser命令确认UID是否为1000,确保Deployment中的runAsUser参数与之匹配。
4. 最后选项:禁用沙箱(仅当上述方法无效时)
如果所有保留沙箱的尝试都失败,可考虑禁用沙箱(注意:此操作会降低安全性,仅建议在可信环境中使用):
const browser = await puppeteer.launch({ executablePath: '/usr/bin/google-chrome-stable', args: [ '--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--disable-gpu' ] });
内容的提问来源于stack exchange,提问作者Hammerbot

