如何正确使用带有投影卷和 configMap 的子目录

How to correctly use subdirs with projected volumes and configMaps

我有一个用 docker swarm 部署的 nginx 网络服务器,我希望也能用 kubernetes 部署它。

现在我无法将 nginx 配置文件插入到容器中。

我会首先post这里是我在docker swarm 中已经做过的,然后是我在 kubernetes 中尝试过的。

Dockerfile:

FROM    "nginx:1.19.1-alpine"   AS nginx
[...]
RUN                                                             \
        rm -fv  /etc/nginx/nginx.conf                           && \
        ln -svT /usr/local/etc/nginx/nginx.conf                 \
                /etc/nginx/nginx.conf                           && \
        rm -frv /etc/nginx/conf.d                               && \
        ln -svT /usr/local/etc/nginx/conf.d                     \
                /etc/nginx/conf.d
[...]

基本上我设置了图像,这样我就可以将我的自定义 nginx 配置文件放入 /usr/local/etc/ 而不是 /etc/

Docker群:

docker-compose.yaml:

configs:
    nginx_conf:
        file: /run/configs/www/etc/nginx/nginx.conf
    nginx_conf_security-parameters:
        file: /run/configs/www/etc/nginx/conf.d/security-parameters.conf
    nginx_conf_server:
        file: /run/configs/www/etc/nginx/conf.d/server.conf

networks:
    alejandro-colomar:

services:
    www:
        configs:
        -
            mode: 0440
            source: nginx_conf
            target: /usr/local/etc/nginx/nginx.conf
        -
            mode: 0440
            source: nginx_conf_security-parameters
            target: /usr/local/etc/nginx/conf.d/security-parameters.conf
        -
            mode: 0440
            source: nginx_conf_server
            target: /usr/local/etc/nginx/conf.d/server.conf
        deploy:
            placement:
                constraints:
                -   node.role == worker
            replicas: 1
            restart_policy:
                condition: any
        image: "alejandrocolomar/www:0.16-a6-kube"
        networks:
        -
            "alejandro-colomar"
        ports:
        -   "32001:8080"

version: "3.8"

这里我使用 nginx 自定义配置文件,我首先用脚本将其放入 /run/configs/ 以便它们位于 ram 中,然后将它们作为配置引入容器中正确的位置(/usr/local/etc/nginx/ 及其子目录 conf.d/).

我想在 kubernetes 中做同样的事情,我读到我应该为此使用一个预计卷(如果它可以用普通卷或以其他方式实现,而不必使用任何肮脏的解决方法,我我也对此持开放态度),所以我尝试了以下方法(在看到一些我不太清楚的例子之后):

config.sh:


kubectl create configmap "nginx-conf-cm"                        \
        --from-file "/run/configs/www/etc/nginx/nginx.conf"
kubectl create configmap "nginx-conf-security-parameters-cm"    \
        --from-file "/run/configs/www/etc/nginx/conf.d/security-parameters.conf"
kubectl create configmap "nginx-conf-server-cm"                 \
        --from-file "/run/configs/www/etc/nginx/conf.d/server.conf"

deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
    name: www-deploy
spec:
    replicas: 1
    selector:
        matchLabels:
            service: www-svc
    template:
        metadata:
            labels:
                service: www-svc
        spec:
            containers:
            -
                image: "alejandrocolomar/www:0.16-a6-kube"
                name: www-container
                volumeMounts:
                -
                    mountPath: /usr/local/etc/nginx/
                    name: nginx-volume
                    readOnly: true
            volumes:
            -
                name: nginx-volume
                projected:
                    sources:
                    -
                        configMap:
                            name: nginx-conf-cm
                            path: "nginx.conf"
                    -
                        configMap:
                            name: nginx-conf-security-parameters-cm
                            path: "conf.d/security-parameters.conf"
                    -
                        configMap:
                            name: nginx-conf-server-cm
                            path: "conf.d/server.conf"

service.yaml:(这个我放在这里只是为了完整)

apiVersion: v1
kind: Service
metadata:
    name: www
spec:
    ports:
    -
        nodePort: 32001
        port: 8080
    selector:
        service: www-svc
    type: NodePort

部署当然失败了,但我认为这并不是什么大错。进入容器调试的时候,问题是三个文件都放到了/usr/local/etc/nginx/,subdirconf.d/没有创建:

/usr/local/etc/nginx/nginx.conf
/usr/local/etc/nginx/security-parameters.conf
/usr/local/etc/nginx/server.conf

我应该如何解决这个问题(大概在 deployment.yaml 中)以便我在容器中有以下文件?:

/usr/local/etc/nginx/nginx.conf
/usr/local/etc/nginx/conf.d/security-parameters.conf
/usr/local/etc/nginx/conf.d/server.conf

有多种方法可以处理这个问题。一种解决方案是从这些单独的配置映射创建 3 个单独的卷,并将每个卷安装到其适当的目的地 file/folder。

volumes:
        - name: nginx-cm
          configMap:
              name: nginx-conf-cm
        - name: nginx-sec
          configMap:
              name: nginx-conf-security-parameters-cm
        - name: nginx-serv
          configMap:
              name: nginx-conf-server-cm

        ...
        containers:
            -
                image: "alejandrocolomar/www:0.16-a6-kube"
                name: www-container
                volumeMounts:
                -   mountPath: /usr/local/etc/nginx/nginx.conf
                    name: nginx-cm
                    subPath: nginx.conf
                    readOnly: true
                -   mountPath: /usr/local/etc/nginx/conf.d/security-parameters.conf
                    name: nginx-sec
                    subPath: security-parameters.conf
                    readOnly: true
                -   mountPath: /usr/local/etc/nginx/conf.d/server.conf
                    name: nginx-serv
                    subPath: server.conf
                    readOnly: true

volumeMounts 中使用 mountPathsubPath 允许您从给定的配置映射中选择特定的文件(无关紧要,因为您每厘米都有一个文件)并挂载它作为一个文件(不覆盖现有文件夹中的其他内容)。

稍微解释一下上面的代码:

-   mountPath: /usr/local/etc/nginx/nginx.conf
    name: nginx-cm
    subPath: nginx.conf

告诉 kubernetes 使用具有 nignx-cmname 的卷(在卷部分中定义)。选择可以在相关配置映射中找到的文件 nginx.conf(通过 subpath),并将其公开在位于 /usr/local/etc/nginx/nginx.conf.[=25= 位置的容器 (mountPath) 中]

我没有运行代码所以可能有错别字

PS:请注意,在 ../etc/nginx/conf.d/ 中创建自定义配置文件可能比覆盖 ../etc/nginx/nginx.conf 更好。这样你就不需要担心破坏原始文件 ../etc/nginx/ 并且你可以挂载整个卷而不是使用 subpath (以避免配置更新问题)