4

spring boot 应用部署在 openshift 4 上。这个应用需要在 nfs-share 上创建一个文件。openshift 容器已在 NFS 类型上配置了卷挂载。openshift 上的容器创建一个具有随机用户 ID 的 pod

sh-4.2$ id
uid=1031290500(1031290500) gid=0(root) groups=0(root),1031290500

挂载点是 /nfs/abc

sh-4.2$ ls -la /nfs/
ls: cannot access /nfs/abc: Permission denied
total 0
drwxr-xr-x. 1 root root 29 Nov 25 09:34 .
drwxr-xr-x. 1 root root 50 Nov 25 10:09 ..
d?????????? ? ?    ?     ?            ? abc

在 docker 映像上,我使用 uid= gid=48760 创建了一个用户“技术”,如下所示。

FROM quay.repository
MAINTAINER developer

LABEL description="abc image" \
      name="abc" \
      version="1.0"

ARG APP_HOME=/opt/app
ARG PORT=8080

ENV JAR=app.jar \
    SPRING_PROFILES_ACTIVE=default \
    JAVA_OPTS=""

    
RUN mkdir $APP_HOME 

ADD $JAR $APP_HOME/

WORKDIR $APP_HOME
EXPOSE $PORT
ENTRYPOINT java $JAVA_OPTS -Dspring.profiles.active=$SPRING_PROFILES_ACTIVE -jar $JAR

我的部署配置文件如下所示

 spec:
      volumes:
        - name: bad-import-file
          persistentVolumeClaim:
            claimName: nfs-test-pvc
      containers:
        - resources:
            limits:
              cpu: '1'
              memory: 1Gi
            requests:
              cpu: 500m
              memory: 512Mi
          terminationMessagePath: /dev/termination-log
          name: abc
          env:
            - name: SPRING_PROFILES_ACTIVE
              valueFrom:
                configMapKeyRef:
                  name: abc-configmap
                  key: spring.profiles.active
            - name: DB_URL
              valueFrom:
                configMapKeyRef:
                  name: abc-configmap
                  key: db.url
            - name: DB_USERNAME
              valueFrom:
                configMapKeyRef:
                  name: abc-configmap
                  key: db.username
            - name: BAD_IMPORT_PATH
              valueFrom:
                configMapKeyRef:
                  name: abc-configmap
                  key: bad.import.path
            - name: DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: abc-secret
                  key: db.password
          ports:
            - containerPort: 8080
              protocol: TCP
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: bad-import-file
              mountPath: /nfs/abc
      dnsPolicy: ClusterFirst
      securityContext:
        runAsGroup: 44337
        runAsNonRoot: true
        supplementalGroups:
          - 44337

PV请求如下

apiVersion: v1
kind: PersistentVolume
metadata:
  name: abc-tuc-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  storageClassName: classic-nfs
  mountOptions:
    - hard
    - nfsvers=3
  nfs:
    path: /tm03v06_vol3014
    server: tm03v06cl02.jit.abc.com
    readOnly: false

现在 openshift 用户有了 id

sh-4.2$ id
        uid=1031290500(1031290500) gid=44337(technical) groups=44337(technical),1031290500

最近的更新

为了清楚问题,下面我有来自同一个 pod 终端的两个命令,

sh-4.2$ cd /nfs/
sh-4.2$ ls -la (The first command I tried immediately after pod creation.)
total 8
drwxr-xr-x.  1 root  root    29 Nov 29 08:20 .
drwxr-xr-x.  1 root  root    50 Nov 30 08:19 ..
drwxrwx---. 14 technical technical 8192 Nov 28 19:06 abc
sh-4.2$ ls -la(few seconds later on the same pod terminal)
ls: cannot access abc: Permission denied
total 0
drwxr-xr-x. 1 root root 29 Nov 29 08:20 .
drwxr-xr-x. 1 root root 50 Nov 30 08:19 ..
d?????????? ? ?    ?     ?            ? abc

所以问题是我在挂载点上看到了这些问号(???)。安装工作正常,但我无法访问此 /nfs/abc 目录,我看到了这个 ????? 由于某些原因

更新

sh-4.2$ ls -la /nfs/abc/
ls: cannot open directory /nfs/abc/: Stale file handle
sh-4.2$ ls -la /nfs/abc/ (after few seconds on the same pod terminal)
ls: cannot access /nfs/abc/: Permission denied

这个 STALE FILE HANDLE 可能是导致此问题的原因吗?

4

1 回答 1

1

TL;博士

您可以使用anyuid安全上下文运行 pod 以避免让 OpenShift 分配任意 UID,并将卷上的权限设置为用户的已知 UID。


OpenShift 将覆盖图像本身可能指定它应该运行的用户 ID

用户 ID 实际上并不是完全随机的,而是分配给您的项目唯一的用户 ID。事实上,您的项目被分配了一系列用户 ID,应用程序可以作为这些用户 ID 运行。用户 ID 集不会与其他项目重叠。您可以通过在项目上运行 oc describe 查看分配给项目的范围。

为每个项目分配不同范围的用户 ID 的目的是,在多租户环境中,来自不同项目的应用程序永远不会以相同的用户 ID 运行。使用持久存储时,应用程序创建的任何文件在文件系统中也将具有不同的所有权。

...这是一种祝福和诅咒,例如,当使用共享持久卷声明时(例如,PVC 安装在ReadWriteMany多个读取/写入数据的 pod 中 - 一个 pod 创建的文件将无法被另一个 pod 访问,因为文件所有权和权限不正确)。

解决此问题的一种方法是使用anyuid“提供受限 SCC 的所有功能,但允许用户使用任何 UID 和任何 GID 运行”的安全上下文。

使用anyuid安全上下文时,我们知道 pod 将要运行的用户和组 ID,我们可以提前设置共享卷的权限。例如,restricted默认情况下,所有 pod 都使用安全上下文运行:

受限的安全上下文

当使用anyuid安全上下文运行 pod 时,OpenShift 不会从为命名空间分配的 UID 范围内分配任意 UID:

anyuid 安全上下文

这只是一个例子,但是使用具有固定 UID 和 GID 的非 root 用户(1000:1000例如1000:1000可以在 PVC 上设置已知用户的 UID 和 GID 来运行服务。例如,我们可以创建一个新的 PVC:

cat <<EOF |kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data
  namespace: k8s
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 8Gi
  storageClassName: portworx-shared-sc
EOF

...然后将其安装在吊舱中:

kubectl run -i --rm --tty ansible --image=lazybit/ansible:v4.0.0 --restart=Never -n k8s --overrides='
{
  "apiVersion": "v1",
  "kind": "Pod",
  "spec": {
    "serviceAccountName": "default",
    "containers": [
      {
        "name": "nginx",
        "imagePullPolicy": "Always",
        "image": "lazybit/ansible:v4.0.0",
        "command": ["ash"],
        "stdin": true,
        "stdinOnce": true,
        "tty": true,
        "env": [
          {
            "name": "POD_NAME",
            "valueFrom": {
              "fieldRef": {
                "apiVersion": "v1",
                "fieldPath": "metadata.name"
              }
            }
          }
        ],
        "volumeMounts": [
          {
            "mountPath": "/data",
            "name": "data"
          }
        ]
      }
    ],
    "volumes": [
      {
        "name": "data",
        "persistentVolumeClaim": {
          "claimName": "data"
        }
      }
    ]
  }
}'

...并在 PVC 中创建文件作为USERDockerfile 中的集合

创建为 anyuid USER 的示例文件

于 2021-12-08T13:41:05.820 回答