使用与容器 securityContext 中指定的用户不同的用户构建 Alpine 容器映像时,Pod 不会失败

Pod is not failing when building Alpine Container Image with different user than specified in container securityContext

我将 securityContext 设置为 运行 作为 Docker 图像中定义的不同用户,但它仍然可以部署并且应用程序启动没有问题。

应该是失败了还是我哪里搞错了?

我正在使用 GKE 和 Helm。 库伯内斯 1.22

Docker文件:

FROM openjdk:17-alpine as java17

FROM alpine:3.15.4

COPY --from=java17 /opt/openjdk-17 /opt/openjdk-17
ENV JAVA_HOME=/opt/openjdk-17
ENV PATH=$PATH:${JAVA_HOME}/bin
ARG JAVA_FILE="1.0-SNAPSHOT"

RUN apk add --no-cache java-cacerts && addgroup -S 10033 && adduser -S 10033 -G 10033

USER 10033:10033

COPY --chown=10033:10033 ${JAVA_FILE} /opt/app/app.jar

ENTRYPOINT ["java","-jar","/opt/app/app.jar", "$JVM_OPTS"]

部署:

  containers:
  - name: "myproject"
    image: "eu.gcr.io/mycompany/myproject:1.0"
    imagePullPolicy: "IfNotPresent"
    securityContext:
      readOnlyRootFilesystem: true
      allowPrivilegeEscalation: false
      privileged: false
      runAsUser: 10005
      runAsGroup: 20050
      runAsNonRoot: true

kubectl 版本

Client Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.5", GitCommit:"5c99e2ac2ff9a3c549d9ca665e7bc05a3e18f07e", GitTreeState:"clean", BuildDate:"2021-12-16T08:38:33Z", GoVersion:"go1.16.12", Compiler:"gc", Platform:"windows/amd64"}
Server Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.7-gke.1500", GitCommit:"565bc494bfc66bfb42aec331000c61f72b020f1a", GitTreeState:"clean", BuildDate:"2022-03-10T09:33:51Z", GoVersion:"go1.16.14b7", Compiler:"gc", Platform:"linux/amd64"}

编辑:

我已经用 root 用户构建了镜像,它仍然有效。

/opt/app $ ls -la
total 73024
drwxr-xr-x    2 root     root          4096 May 20 12:03 .      
drwxr-xr-x    1 root     root          4096 May 20 12:04 ..     
-rw-r--r--    1 root     root      74765459 May 20 12:01 app.jar

我还检查了以下内容,不知何故它的工作,但奇怪的是可以执行 root 拥有的 app.jar。我想我在这里遗漏了一些概念。

因此可以 运行 从外部将任何图像设置为特定用户,这非常酷。这对我来说是一种魔法,所以也许有人可以解释它是如何工作的?

/ $ id
uid=10005 gid=20050 groups=101(20050)

/ $ ps aux
PID   USER     TIME  COMMAND
    1 10005     0:40 java -jar /opt/app/app.jar $JVM_OPTS
   45 10005     0:00 sh
   61 10005     0:00 ps aux

文件通常是 world-readable,除非您另外明确设置。您的 ls -l 输出也表明:在输出 -rw-r--r-- 中,文件(前导 -)是可读和可写的,但其所有者(rw-)不可执行,并且是可读的但其组所有者 (r--) 和其他任何人 (r--) 都不可写或可执行。

这意味着哪个用户拥有 jar 文件实际上并不重要。您通常不希望您的应用程序代码被 运行 的用户写入,以免错误导致它在 运行 时被修改。我建议让 root 拥有您的应用程序代码并且其他用户不可写是一个好习惯。

# without a --chown option, so it's owned by root
COPY ${JAVA_FILE} /opt/app/app.jar

# change users as the last thing in your Dockerfile
USER 10333
CMD ["java", "-jar", "/opt/app/app.jar"]

如果您的应用程序需要在其容器内写入数据,首先要考虑是否可以将其写入其他地方,例如数据库。这在 Kubernetes 上更是如此,你经常会有一个 pod 的多个副本,并且 pods 可以在你的控制之外被删除。如果您确实需要 container-local 状态,请将其保存在一个目录中;使该目录由 Dockerfile 中的默认容器用户拥有;并在 运行 容器(在 Kubernetes 中,通过 StatefulSet)时在该目录上安装一个卷。