5

我正在尝试在 kubernetes 中运行 indy 节点。这些 indy 节点是沙箱节点,将数据写入/var/lib/indy容器内的目录中。当我运行挂载了卷的 pod 时,它不会在卷目录中写入任何内容。尽管它在卷内创建了一个目录,但它始终是空的。但是,当我创建一个没有卷挂载选项的 pod 时,容器会将数据写入/var/lib/indy.

以下是 Dockerfile:
Hastebin:https ://hastebin.com/hitinefizi.nginx

Kubernetes 部署:

{{- $root := .}}
{{- range .Values.indy}}
---
apiVersion: apps/v1
kind: Deployment
metadata:
  # namespace: {{$root.Values.namespace}}
  name: {{.name}}
spec:
  selector:
    matchLabels:
      name: {{.name}}
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        name: {{.name}}
    spec:
      containers:
        - name: {{.name}}
          image: {{.image}}
          volumeMounts:
            - name: {{$root.Values.pv.metadata.name}}
              mountPath: "/var/lib/indy/sandbox"
              subPath: "volume/indy/{{.name}}/sandbox"
          ports:
            - containerPort: {{ index .ports 0 }}
            - containerPort: {{ index .ports 1 }}
      nodeSelector:
        nodeType: {{$root.Values.hosts.blockchain}}
      volumes:
        - name: {{$root.Values.pv.metadata.name}}
          {{- if eq $root.Values.storage.type "nfs" }}
          persistentVolumeClaim:
            claimName: {{$root.Values.pvc.metadata.name}}
          {{- else }}
          hostPath:
            path: /var/kubeshare/
          {{- end }}
{{- end}}

卷内的目录:

[root@centos1 kubeshare]# tree volume/indy/
volume/indy/
|-- indy-node1
|-- indy-node2
|-- indy-node3
`-- indy-node

/var/lib/indy容器内没有卷的目录:

root@indy-node1-587c4758bf-2hpp6:/var/lib/indy# tree -L 3
.
|-- plugins
`-- sandbox
    |-- data
    |   `-- Node1
    |-- domain_transactions_genesis
    |-- keys
    |   |-- Node1
    |   |-- Node1C
    |   |-- Node2
    |   |-- Node3
    |   `-- Node4
    |-- node1_additional_info.json
    |-- node1_info.json
    |-- node1_version_info.json
    `-- pool_transactions_genesis

我不确定为什么会这样。任何帮助/建议将不胜感激。

更新:当我尝试使用本地卷时,这与 docker-compose 发生的情况相同。

4

1 回答 1

3

在 docker 中挂载与在 Linux 上挂载的标准行为一致。Linuxmount命令文档说

The previous contents (if any) and owner and mode of dir become invisible, and as long as this filesystem remains mounted

这也是 Docker 中的工作方式。如果你挂载一个本地目录,或者一个现有的命名 docker 卷,挂载位置的容器中文件系统的内容将被遮蔽(或者我们可以称之为“覆盖”)。

正在发生的事情的简化示例

拥有 dockerfile

FROM alpine:3.9.6

WORKDIR /home/root/greetings
RUN echo "hello world" > /home/root/greetings/english.txt
CMD sleep 60000

并建造它docker build -t greetings:1.0 .

现在创建以下内容docker-compose.yml

version: '3.7'

services:
  greetings:
    container_name: greetings
    image: greetings:1.0
    volumes:
      - ./empty:/home/root/greetings

empty并在其旁边创建空目录。

开始吧docker-compose up -d。当容器运行时,让我们进入容器,看看里面的文件结构是什么样的。docker exec -ti greetings sh. 现在当我们在里面时,如果你运行ls /home/root/greetings你会看到目录是空的——即使在 Dockerfile 中我们已经将文件烘焙/home/root/greetings/english.txt到图像的文件系统中。

如果命名的 docker 容器是新的并且不包含任何数据,则命名的 docker 容器的行为更理想。如果您将此类容器安装在已经有一些数据的容器中的位置,则命名卷将在其上复制此数据。

你可以通过调整这个docker-compose.yml来试试这个

version: '3.7'

services:
  greetings:
    container_name: greetings
    image: greetings:1.0
    volumes:
      - greetingsvol:/home/root/greetings

volumes:
  greetingsvol:
    driver: local

如果您重复该过程并将自己执行到容器中,您会看到该文件/home/root/greetings/english.txt仍然存在。

那是因为当您cd自己进入时/home/root/greetings,您不是在查看实际容器的文件系统,而是查看已安装的设备 - 名称 docker volume - 该设备已通过该给定位置上的容器原始文件的副本进行初始化。(假设 docker 卷greetingsvol以前不存在。)

解决您的问题

您正在将/var/kubeshare主机上的目录安装到容器的/var/lib/indy/sandbox. 让我们看看容器在启动时存储在该位置的内容(indypool我是如何在本地主机上命名内置的独立沙盒图像的)

docker run --rm indypool ls /var/lib/indy/sandbox
domain_transactions_genesis
keys
pool_transactions_genesis

因此,如果您将本地目录挂载到 上/var/lib/indy/sandbox,它将隐藏这些文件,并且池将无法启动(因此不会创建诸如node1_additional_info.jsonetc 之类的文件)。

所以我认为你有两个选择:

  1. 除非您有充分的理由不这样做,否则请使用命名的 docker 卷。
  2. 将容器中的原始图像数据复制/var/lib/indy/sandbox到您的/var/kubeshare. 然后你保持一切原样。这样,该目录将被包含与容器期望在那里找到的完全相同的数据的新文件系统所隐藏。
于 2020-04-27T07:20:37.423 回答