我有一个使用felipeogutierrez/tpch-dbgen
构建的docker image docker-compose
,并使用travis-CI
将其推送到docker-hub注册表。
version: "3.7"
services:
other-images: ....
tpch-dbgen:
build: ../docker/tpch-dbgen
image: felipeogutierrez/tpch-dbgen
volumes:
- tpch-dbgen-data:/opt/tpch-dbgen/data/
- datarate:/tmp/
stdin_open: true
这是构建此图像的Dockerfile
:FROM gcc AS builder
RUN mkdir -p /opt
COPY ./generate-tpch-dbgen.sh /opt/generate-tpch-dbgen.sh
WORKDIR /opt
RUN chmod +x generate-tpch-dbgen.sh && ./generate-tpch-dbgen.sh
最后,此脚本使用一些文件创建目录/opt/tpch-dbgen/data/
,我想从我在Kubernetes上运行的另一个Docker镜像中读取这些文件。然后,我创建了一个Flink图像以运行到Kubernetes中。此图像启动3个Flink任务管理器和一个从图像tpch-dbgen-data
读取文件的流应用程序。我认为正确的方法是创建一个PersistentVolumeClaim
,以便可以在Kubernetes中将目录/opt/tpch-dbgen/data/
从图像felipeogutierrez/tpch-dbgen
共享到我的flink图像。所以,首先我有这个文件来创建PersistentVolumeClaim
:apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: tpch-dbgen-data-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 200Mi
然后,我创建一个initContainers
来启动图像felipeogutierrez/tpch-dbgen
,然后启动我的图像felipeogutierrez/explore-flink:1.11.1-scala_2.12
:apiVersion: apps/v1
kind: Deployment
metadata:
name: flink-taskmanager
spec:
replicas: 3
selector:
matchLabels:
app: flink
component: taskmanager
template:
metadata:
labels:
app: flink
component: taskmanager
spec:
initContainers:
- name: tpch-dbgen
image: felipeogutierrez/tpch-dbgen
#imagePullPolicy: Always
env:
command: ["ls"]
# command: ['sh', '-c', 'for i in 1 2 3; do echo "job-1 `date`" && sleep 5s; done;', 'ls']
volumeMounts:
- name: tpch-dbgen-data
mountPath: /opt/tpch-dbgen/data
containers:
- name: taskmanager
image: felipeogutierrez/explore-flink:1.11.1-scala_2.12
#imagePullPolicy: Always
env:
args: ["taskmanager"]
ports:
- containerPort: 6122
name: rpc
- containerPort: 6125
name: query-state
livenessProbe:
tcpSocket:
port: 6122
initialDelaySeconds: 30
periodSeconds: 60
volumeMounts:
- name: flink-config-volume
mountPath: /opt/flink/conf/
- name: tpch-dbgen-data
mountPath: /opt/tpch-dbgen/data
securityContext:
runAsUser: 9999 # refers to user _flink_ from official flink image, change if necessary
volumes:
- name: flink-config-volume
configMap:
name: flink-config
items:
- key: flink-conf.yaml
path: flink-conf.yaml
- key: log4j-console.properties
path: log4j-console.properties
- name: tpch-dbgen-data
persistentVolumeClaim:
claimName: tpch-dbgen-data-pvc
Flink流应用程序正在启动,但无法读取图像/opt/tpch-dbgen/data
的目录felipeogutierrez/tpch-dbgen
上的文件。我收到错误消息:java.io.FileNotFoundException: /opt/tpch-dbgen/data/orders.tbl (No such file or directory)
。这很奇怪,因为当我尝试进入felipeogutierrez/tpch-dbgen
容器时,我可以列出文件。所以我想我的Kubernetes配置有问题。有谁知道指出我在Kubernetes配置文件上缺少的内容吗?$ docker run -i -t felipeogutierrez/tpch-dbgen /bin/bash
root@10c0944a95f8:/opt# pwd
/opt
root@10c0944a95f8:/opt# ls tpch-dbgen/data/
customer.tbl dbgen dists.dss lineitem.tbl nation.tbl orders.tbl part.tbl partsupp.tbl region.tbl supplier.tbl
另外,当我列出容器tpch-dbgen
的日志时,我可以看到要读取的目录tpch-dbgen
。虽然我无法在Kubernetes配置文件中执行command: ["ls tpch-dbgen"]
命令。$ kubectl get pods
NAME READY STATUS RESTARTS AGE
flink-jobmanager-n9nws 1/1 Running 2 17m
flink-taskmanager-777cb5bf77-ncdl4 1/1 Running 0 4m54s
flink-taskmanager-777cb5bf77-npmrx 1/1 Running 0 4m54s
flink-taskmanager-777cb5bf77-zc2nw 1/1 Running 0 4m54s
$ kubectl logs flink-taskmanager-777cb5bf77-ncdl4 tpch-dbgen
generate-tpch-dbgen.sh
tpch-dbgen
最佳答案
Docker具有一项不寻常的功能,在某些特定情况下,它将根据镜像填充新创建的卷。您不应该依赖此功能,因为它会完全忽略基础镜像中的更新,并且在Kubernetes上不起作用。
在Kubernetes设置中,您将创建一个新的空PersistentVolumeClaim,然后将其挂载在init和main容器中的实际数据上。与所有Unix挂载一样,这将隐藏该目录中以前的数据。没有任何原因导致数据被复制到该卷中。除了Docker named-volume挂载外,其他所有挂载的工作方式相同:如果更改Compose设置以进行主机绑定(bind)挂载,或者使用本地开发系统,则会看到相同的行为。使用USB驱动器作为“卷”。
您需要使init容器(或其他容器)显式地将数据复制到目录中。例如:
initContainers:
- name: tpch-dbgen
image: felipeogutierrez/tpch-dbgen
command:
- /bin/cp
- -a
- /opt/tpch-dbgen/data
- /data
volumeMounts:
- name: tpch-dbgen-data
mountPath: /data # NOT the same path as in the image
如果主进程在适当位置修改了这些文件,则可以使命令更智能,或者将脚本写入图像,仅在单个文件不存在的情况下才将其复制到其中。让镜像在启动时而不是在镜像生成时生成数据文件可能更有意义。可能看起来像:
FROM gcc
COPY ./generate-tpch-dbgen.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/generate-tpch-dbgen.sh
CMD ["generate-tpch-dbgen.sh"]
然后,在您的init容器中,您可以运行默认命令(生成脚本),并将工作目录设置为卷目录initContainers:
- name: tpch-dbgen
image: felipeogutierrez/tpch-dbgen
volumeMounts:
- name: tpch-dbgen-data
mountPath: /opt/tpch-dbgen/data # or anywhere really
workingDir: /opt/tpch-dbgen/data # matching mountPath
关于docker - 为什么我不能从Kubernetes中的容器之间的共享PersistentVolumeClaim中读取文件?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/64008325/