如何模仿' - 卷 - 来自'在Kubernetes

时间:2015-05-29 20:08:31

标签: docker kubernetes google-kubernetes-engine

我正在寻找一种模式,允许在Kubernetes的同一个pod上运行的两个容器之间共享卷。

我的用例是: 我有一个在docker容器中运行的Ruby on Rails应用程序。 docker镜像包含/app/<app-name>/public目录中的静态资源,我需要从同一个pod中并行运行的nginx容器中访问这些资源。

香草&#39; docker我会用--volumes-from标志来共享这个目录:

docker run --name app -v /app/<app-dir>/public <app-image>
docker run --volumes-from app nginx

阅读此文档后:https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/volumes.md 我试过这个(只提供相关条目):

spec:
  containers:
    - image: <app-image>
      name: <app-name>
      volumeMounts:
        - mountPath: /app/<app-name>/public
          name: assets
    - image: nginx
      name: nginx
      volumeMounts:
        - mountPath: /var/www/html
          name: assets
          readOnly: true
    volumes:
      - name: assets
        hostPath:
          path: /tmp/assets

可是:

  • 即使节点上存在/tmp/assets,它也是空的
  • 应用容器内的
  • /app/<app-name>/public也是空的

作为一种解决方法,我会在应用程序容器启动时尝试填充共享目录(只需cp /app/<app-name>/public/*到共享目录),但我真的不喜欢这个想法。

问题:如何在Kubernetes中模仿--volumes-from,或者如果没有直接对应物,我如何将文件从一个容器共享到另一个容器中运行?

apiVersion: v1beta3

Client Version: version.Info{Major:"0", Minor:"17", GitVersion:"v0.17.0", GitCommit:"82f8bdac06ddfacf493a9ed0fedc85f5ea62ebd5", GitTreeState:"clean"}
Server Version: version.Info{Major:"0", Minor:"17", GitVersion:"v0.17.0", GitCommit:"82f8bdac06ddfacf493a9ed0fedc85f5ea62ebd5", GitTreeState:"clean"}

5 个答案:

答案 0 :(得分:36)

[update-2016-8] 在最新的Kubernetes版本中,您可以使用名为init-container的非常好的功能替换下面我的答案中的postStart部分,将确保集装箱订单。

enter image description here

注意:initContainer仍然是测试版功能,因此此yaml的工作版本实际上是:http://kubernetes.io/docs/user-guide/production-pods/#handling-initialization,请注意pod.beta.kubernetes.io/init-containers一部分。

---原始答案开始---

实际上,你可以。您需要使用容器生命周期处理程序来控制要与其他容器共享的文件/目录。像:

---
apiVersion: v1
kind: Pod
metadata:
    name: server
spec:
    restartPolicy: OnFailure
    containers:
    - image: resouer/sample:v2
      name: war
      lifecycle:
        postStart:
          exec:
            command:
              - "cp"
              - "/sample.war"
              - "/app"
      volumeMounts:
      - mountPath: /app
        name: hostv1 
    - name: peer
      image: busybox
      command: ["tail", "-f", "/dev/null"]
      volumeMounts:
      - name: hostv2
        mountPath: /app/sample.war
    volumes:
    - name: hostv1
      hostPath:
          path: /tmp
    - name: hostv2
      hostPath:
          path: /tmp/sample.war

请查看我的要点以获取更多详细信息:

https://gist.github.com/resouer/378bcdaef1d9601ed6aa

当然你可以使用emptyDir。因此,war容器可以将其/sample.war共享到peer容器而不会出现peer peer&app目录。

如果我们能够容忍/ app被覆盖,那就更简单了:

---
apiVersion: v1
kind: Pod
metadata:
  name: javaweb-2
spec:
  restartPolicy: OnFailure
  containers:
  - image: resouer/sample:v2
    name: war
    lifecycle:
      postStart:
        exec:
          command:
            - "cp"
            - "/sample.war"
            - "/app"
    volumeMounts:
    - mountPath: /app
      name: app-volume
  - image: resouer/mytomcat:7.0
    name: tomcat
    command: ["sh","-c","/root/apache-tomcat-7.0.42-v2/bin/start.sh"]
    volumeMounts:
    - mountPath: /root/apache-tomcat-7.0.42-v2/webapps
      name: app-volume
    ports:
    - containerPort: 8080
      hostPort: 8001 
  volumes:
  - name: app-volume
    emptyDir: {}

答案 1 :(得分:9)

答案是 - 现在 - 你做不到。以下是Kubernetes问题的几个讨论主题:

但是,我可以建议您使用可能更好的替代设计吗?

  1. 如果您的资产被锁定在容器上线点, 你可以用gitRepo之类的东西 在上线时将其复制到emptyDir的音量,并且意味着您不必移动内容 所有,只需将其直接下载到共享目录即可。
  2. 如果您的资产被锁定在容器的位置 正在构建,最好是在那时复制它们,使用 Docker COPY命令。
  3. 如果您真的想坚持自己的方式,那么您必须将内容复制到emptyDir卷,该卷专为您所寻找的内容而设计(减去缺少的内容)必须复制它。)
  4. NFS [1]卷也可以解决您的问题,但可能过于复杂。

    此外,我建议这两种服务存在于不同的pod中,因此您可以单独扩展它们。如果需要,您可以创建服务端点以在它们之间进行通信。

    [1] https://github.com/GoogleCloudPlatform/kubernetes/blob/master/examples/nfs/nfs-web-pod.yaml

答案 2 :(得分:1)

future 的进一步更新:

现在有一个Docker卷的FlexVol插件:https://github.com/dims/docker-flexvol

在撰写本文时,FlexVol仍然是一个alpha功能,因此需要注意。

答案 3 :(得分:1)

Kubernetes具有自己的卷类型,这些是最常用的卷类型:

  1. emptyDir
  2. 秘密
  3. gitRepo
  4. hostPath(类似于--volumes-from)
  5. 配置地图
  6. 永久存储(云平台提供的存储磁盘)

您可以在此处找到有关kubernets卷的更多信息-https://kubernetes.io/docs/concepts/storage/volumes/

主机路径卷的示例:

for i in range(0,4):
    while(x < 8):
        attempt = attempt + 1
        x = np.random.uniform(low=0, high=10, size=1)

hostpath会将主机/节点目录挂载到容器目录中。一个容器中的多个容器可以使用不同或相同的卷。您需要在每个容器中提及它。 hostPath卷与pod生命周期无关,但是它会在node和pod之间建立紧密的耦合,因此应避免使用hostPath。

答案 4 :(得分:0)

如果您使用的是Docker v17.0.5或更高版本,则可以在构建期间使用多阶段构建将文件从一个容器复制到另一个容器。这是https://medium.com/@tonistiigi/advanced-multi-stage-build-patterns-6f741b852fae

上高级功能的重要入门

将静态资产从后端容器复制到Nginx代理中的方式是

ARG API_BACKEND_CONTAINER="api:backend"
FROM $API_BACKEND_CONTAINER as source

FROM nginx:mainline-alpine

ARG NGINX_ROOT=/usr/share/nginx/html/
COPY --from=source  /var/share/api/static/ ${NGINX_ROOT}

很棒的是,因为API_BACKEND_CONTAINER是一个构建参数,所以我可以传递最新API构建的标签。