为什么 Docker CMD 在 GKE 中作为 chronos 运行?

问题描述

我有一个 Pod 和 NodePort 服务在 GKE 上运行。

在 Pod 中容器的 Dockerfile 中,我使用 gosu特定用户身份运行命令:

startup.sh

exec /usr/local/bin/gosu mytestuser "$@"

Dockerfile

FROM ${DOCKER_HUB_PUBLIC}/opensuse/leap:latest

# Download and verify gosu
RUN gpg --batch --keyserver-options http-proxy=${env.HTTP_PROXY} --keyserver hkps://keys.openpgp.org \
      --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 && \
    curl -o /usr/local/bin/gosu -SL "https://github.com/tianon/gosu/releases/download/1.12/gosu-amd64" && \
    curl -o /usr/local/bin/gosu.asc -SL "https://github.com/tianon/gosu/releases/download/1.12/gosu-amd64.asc" && \
    gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu && \
    chmod +x /usr/local/bin/gosu

# Add tini
ENV tini_VERSION v0.18.0
ADD https://github.com/krallin/tini/releases/download/${tini_VERSION}/tini /tini
RUN chmod +x /tini
ENTRYPOINT ["/tini","--","/startup/startup.sh"]

# Add mytestuser
RUN useradd mytestuser

# Run startup.sh which will use gosu to execute following `CMD` as `mytestuser`
RUN /startup/startup.sh
CMD ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/helloworld.jar"]

我刚刚注意到,当我登录 GKE 上的容器并查看正在运行的进程时,我希望以 mytestuser 运行的 java 进程实际上以 chronos 运行:

me@gke-cluster-1-default-ool-1234 ~ $ ps aux | grep java
root        9551  0.0  0.0   4296   780 ?        Ss   09:43   0:00 /tini -- /startup/startup.sh java -Djava.security.egd=file:/dev/./urandom -jar /helloworld.jar
chronos     9566  0.6  3.5 3308988 144636 ?      Sl   09:43   0:12 java -Djava.security.egd=file:/dev/./urandom -jar /helloworld.jar

谁能解释发生了什么,即谁是 chronos 用户,为什么我的进程没有以 mytestuser 身份运行?

解决方法

当您 sqlpackage /a:publish /sf:"C:\SQL Server Management Studio\DAC Packages\source.dacpac" /tsn:tcp:test.windows.net,1433 /tdn:target_db /tu:admin /tp:password 时,它会在 图像的 RUN adduser 文件中分配一个用户 ID。您的脚本使用该数字用户 ID 启动进程。但是,当您随后从主机运行 /etc/passwd 时,它会在 主机的 ps 文件中查找该用户 ID,并得到不同的结果。

这种差异通常无关紧要。如果您要从主机绑定挂载目录,则只有数字用户 ID 对文件系统权限等事项很重要。出于安全目的,数字用户 ID 不能为 0 很重要,但它的名称非常普遍,/etc/passwd

,

当您在容器内(或作为映像构建的一部分)运行 useradd 时,它会将 am 条目添加到 /etc/passwd 容器内。 uid/gid 将在与主机共享的命名空间中,除非您启用用户命名空间。然而,这些 id 到名称的映射将特定于进程正在运行的文件系统命名空间。所以在这个场景中,容器内mytestuser的uid恰好和宿主机上的chronos是同一个uid。