Kubernetes 在部署内的容器之间共享卷

Kubernetes share volume between containers inside a Deployment

在发布这个问题之前,我遵循了这个答案,但它对我不起作用。

我有 2 个容器:

节点图像里面是什么:

$ docker run node ls -l
> clientBuild/
> package.json
> ...

nginx.prod.conf的一部分:

location ~* \.(jpeg|jpg|gif|png|ico|css|js|gz|map|json)$ {
  include /etc/nginx/mime.types;
  root /usr/local/nginx/html/clientBuild/;
}

以及部署设置:

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: pwa-app-production
  labels:
    app: MyApp
spec:
  replicas: 1
  template:
    metadata:
      name: app
      labels:
        app: MyApp
        env: production
    spec:
      containers:
      - name: nginx
        image: nginx
        command: [nginx, -c, /nginx.prod.conf, -g, 'daemon off;']
        resources:
          limits:
            memory: "500Mi"
            cpu: "100m"
        imagePullPolicy: Always
        volumeMounts:
          - mountPath: /usr/local/nginx/html
            name: pwa-disk
            readOnly: true
        ports:
        - name: nginx
          containerPort: 80
      initContainers:
      - name: node
        image: node
        command: [npm, start]
        resources:
          limits:
            memory: "500Mi"
            cpu: "100m"
        imagePullPolicy: Always
        volumeMounts:
          - mountPath: /var/www
            name: pwa-disk
        ports:
        - name: app
          containerPort: 3000
        - name: api
          containerPort: 3001
      volumes:
        - name: pwa-disk
          emptyDir: {}

我首先尝试将两个图像放在同一个 containers 键中,但我得到了: /var/www/package.json not found on npm start

然后我将它移到 initContainers 中,但现在我只注意到它失败了,但没有告诉我原因。查看日志也不显示任何详细信息。

请注意,当我删除音量部分时,npm start 有效。

我假设您的资产已经打包在 /var/www 的图像中。如果您在该路径上安装一个 emptyDir 卷,那么那里的所有内容都会被 emptyDir 卷的内容覆盖——最初什么都没有。这意味着您的所有资产都通过该挂载被删除 - 这就是您的节点服务器最有可能失败的原因。

您要做的是将 emptyDir 卷挂载到其他路径,比如 /data。然后你用 cp -r /var/www/* /data 覆盖你的节点容器 cmd 以将资产复制到你的 pwa-disk 卷中。现在,您可以将此卷装载到您的 nginx 容器中。

我认为对 initContainers 的工作方式存在误解。它们旨在终止。它们 运行 BEFORE 启动任何其他容器 - 在您的 initContainers 成功终止之前,您的 pod 中没有其他容器启动。所以很可能您不想将节点服务器启动为 initContainer。我猜你的节点服务器不应该终止,在这种情况下你的 nginx 容器将永远不会启动。相反,您可能希望在 containers 部分内将节点服务器与 nginx 一起声明。此外,您还将具有覆盖的 cmd (cp -r /var/www/* /data) 的节点容器添加到 initContainers 部分,以将资产复制到卷。整个事情可能看起来像这样:

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: pwa-app-production
  labels:
    app: MyApp
spec:
  replicas: 1
  template:
    metadata:
      name: app
      labels:
        app: MyApp
        env: production
    spec:
      containers:
      - name: nginx
        image: nginx
        command: [nginx, -c, /nginx.prod.conf, -g, 'daemon off;']
        resources:
          limits:
            memory: "500Mi"
            cpu: "100m"
        imagePullPolicy: Always
        volumeMounts:
          - mountPath: /usr/local/nginx/html
            name: pwa-disk
            readOnly: true
        ports:
        - name: nginx
          containerPort: 80
      - name: node
        image: node
        command: [npm, start]
        resources:
          limits:
            memory: "500Mi"
            cpu: "100m"
        imagePullPolicy: Always
        ports:
        - name: app
          containerPort: 3000
        - name: api
          containerPort: 3001

      initContainers:
      - name: assets
        image: node
        command: [bash, -c]
        args: ["cp -r /var/www/* /data"]
        imagePullPolicy: Always
        volumeMounts:
          - mountPath: /data
            name: pwa-disk
      volumes:
        - name: pwa-disk
          emptyDir: {}