首页 > 系统相关 >k8s中 fpm 和 nginx 的文件共享问题

k8s中 fpm 和 nginx 的文件共享问题

时间:2023-05-24 14:26:05浏览次数:51  
标签:文件共享 fpm 代码 nginx 镜像 docker php

目录

  1. 引言
  2. docker 镜像构建哲学
  3. 为什么一定要共享文件
  4. 代码的迭代更新问题

引言

初看这是一个值得记录的问题吗?或者说这算是一个问题吗?各种数据卷挂载,然后一顿操作不就完成了么?我也是这么认为的。看人讨论 fpm 与 nginx 的文件共享问题。想到自己当初也遇到了类似的困惑,记得当时很是纠结和折腾。但是一时之间记不起来具体是哪一个环节遇到了问题。索性打开以前写的编排代码查了个究竟,记录之。

docker 镜像构建哲学

  • 首先当然是镜像体积越小越好。有利于网络传输有利于分发,镜像体积小也是 docker 比之于虚拟机方案最大的优势之一呐。alpine 等小体积基础 linux 镜像的问世就是例证。
  • 一个容器一个服务。说出话来这个可能有的同学会不服,直接将所需要的服务打包运行在一个镜像中不就好了。拿经典的 lnmp 来说,将操作系统、数据库、fpm、nginx全部打包到一个镜像中启动起来不就好了么。省去了存储和网络隔离的各种麻烦。即使不打包数据库,打包个lnp也行呐。确实可以这么做,但是实际操作起来并不是那么理想。想想有一个进程意外退出的情况,我们可能需要再打包一个supervisor进去。或者写一个 shell 脚本打包进去以实现健康检查的逻辑,以借助 k8s 的健康检查策略避免一个服务进程挂掉导致整个容器无法提供服务的情况出现。这样就好了么?考虑日志收集和性能测量监控问题,又有很多事情要做了……。显然一般情况下将所有关联服务打包到一个镜像之中不会给我们带来便利,相反会让我们失去 docker 和 k8s 这两个神器给我们带来的各种便利。

为什么一定要共享文件

php-fpm 无法直接提供服务,必须借助 nginx 或者是 apache 之类的 web 服务器才能对外提供服务。 虽然有 -S 选项可以启动一个 web 服务,但是遗憾的是只能同时执行一次请求,不能用于生产环境。web 服务需要解析 http url 以确定需要执行哪个脚本文件,接着通过 fcgi 协议从 php-fpm 获取数据最终返回给前端。啰嗦了这么多,其实只是为了说明:php-fpm 和 nginx 都需要访问同一套 php 的代码,无论如何都无法避开这个文件共享问题。

代码的迭代更新问题

理所当然的,我们需要将同一份 php 代码文件挂载到 nginx 和 fpm 的容器中。此时我们还需要考虑代码的迭代和更新问题。以下讨论几种方式的优劣:

  • 将代码统一更新到一个外部数据卷中,所有的 lnp pod 都挂载这个外部数据卷。就可以很容易的实现代码的迭代更新。这种方式的优势在于更新很方便快速,毕竟只需要更新维护一份代码。事实上,我认为这种方式百害而无一利。我们需要做到整个代码文件的同步映射需要费很大的劲。当然可以简单粗暴的直接删除目录下的所有文件,然后再推送新的代码进去,但是在部署的这段时间将会导致所有服务短暂的不可用。回滚等操作也是一大难的问题。最致命的是堆外部存储的访问是有网络 io 消耗的。解释型语言的性能问题已经堪忧了,再来这么一道岂不是雪上加霜。虽然有 CSI 插件可以实现将存储同步至本地,但是仍然无法规更新时避服务不可用的问题以及其他更多的风险。还有一个问题是不规范的编码会直接将日志写到文件,而且是到处分散的项目目录下的文件中,很是随心所欲。一些老旧项目尤为明显,改都改不过来,这种飘逸的做法无力吐槽。这会导致共享存储可能被塞满,或者影响文件同步……这种方案想想就好。

  • 编写一个可以拉取代码的镜像,比如使用 git 进行代码拉取。然后通过initContainers选项在nginx 和 fpm 容器启动前代码拉取到共享目录中。嗯~很有逼格的一个方案,但是代码一般都是存储在私有仓库中的,你可能需要将 git 仓库的认证信息打包到镜像中或者是 k8s 的 secret 中。这也好办,但是如何告诉这个容器要更新什么代码呢?哪一个标签还是哪一个分支?虽然没有共享外部存储那么鸡肋但是实施起来是真的要费些吃奶的力气的。虽然有 gitRepo 等实现可以达成这个目标,但是仍然不是最优。

  • 将 php 的代码直接打包到一个镜像中,比如 fpm 镜像。代码更新后直接更新 deployment 的镜像标签不就好了嘛。虽然镜像体积会变得有些大,但是有 docker 镜像的分层缓存策略,实际上后续的更新中只会拉取新增的代码下来。这个看起来是最简便安全的,事实也是如此。然而最让人郁闷的地方也就是这里了。

docker 的 VOLUME 指令(匿名数据卷)可以在容器启动时自动创建一个挂载目录,并且将镜像中对应目录下的文件拷贝到该目录挂载的实际系统目录中。按照以上所述,此时只需要将 nginx 也挂载到这个代码目录就完成了代码共享。至少在docker-compose 和 swarm 中没有问题。

于是兴高采烈的创建一个 emptyDir 存储卷,并且将 nginx 和 fpm 镜像中VOLUME路径挂载到这个数据卷中。然后就很郁闷的发现nginx并不能共享到预期的 php 代码文件。此时 fpm 容器下面的的目录中也找不到预期的代码文件。我一度认为这是 k8s 的 bug 。微信上呼叫宋进超大神,得到的回复是emptyDir起始是空的,细品!按理来说最终都会挂载到一个系统路径上,docker应该依然把匿名卷中的内容拷贝过去才是。但是人家 k8s 就是这么严谨。不知道是屏蔽了 docker 的复制操作还是自己将目录清空了。

知道了问题原因,解决起来也简单。将共享目录和存放代码的docker匿名卷路径分开,使用initContainers执行一个复制操作即可。

nginx 和 fpm 可以不在一个pod中吗

是不是可以将 nginx 分离出去呢,这样在启动很多 php 项目的时候可以少启动很多个nginx减少了集群资源的消耗。原理上可行,即使不能共享网络空间(nginx中通过127.0.0.1访问fpm),但是仍然可以通过servicecgi请求发送的目标 fpm 。共享存储卷换成hostPath。但是在维护上会带来很多不便,比如 nginx的配置会变得很杂,由于hostPath的特性同样会给代码的迭代跟新带来额外的负担。 综上nginx和fpm最好是在同一个pod中。

标签:文件共享,fpm,代码,nginx,镜像,docker,php
From: https://www.cnblogs.com/shanhubei/p/17428158.html

相关文章

  • Nginx location 匹配规则
    =#用于标准uri前,需要请求字串与uri完全匹配,如果匹配成功就停止向下匹配并立即处理请求。~#区分大小写~*#不区分大写!~#区分大小写不匹配!~*#不区分大小写不匹配^#匹配正则开头$#匹配正则结尾\#转义字符。可以转.*?等*......
  • Nginx 编译安装和守护进程
    在CentOS7中下载、编译和安装Nginx1.20.1源代码需要以下步骤:安装编译环境及相关依赖sudoyuminstall-ygccmakepcre-develzlib-developenssl-devel下载Nginx1.20.1版本源代码进入Nginx官网https://nginx.org/en/download.html将Nginx1.20.1的源代码链接复制到终端中......
  • 安科瑞AFPM消防设备电源监控系统的设计与应用
    安科瑞虞佳豪5月17日,福建福州市闽侯县一厂房着火。当日,记者从闽侯县政府办获悉,火灾已扑灭,无人员伤亡。现场视频显示,闽侯县甘蔗街道一工业区内一厂房内冒出火苗和黑色浓烟,有消防人员正在救援。事发地附近一商户介绍,起火的是当地一个厂房,火灾发生后有多辆消防车赶到,火灾并未从厂......
  • windows环境下的vue部署(使用nginx)
    首先需要将vue项目打包成dist,在需要部署的服务器上进行解压然后我们使用nginx进行反向代理设置,具体操作如下打开解压后的nginx,进入目录:nginx-1.23.4->conf,打开编辑nginx.conf*注意:对于后端路径的映射这里一定是^~/前缀/对应于地址的端口/前缀/,这里一定是两个//包裹。以下......
  • 解决nginx+django+swagger打开swagger需要进行Django Login
    一、将drf-yasg包的static目录拷贝到Django项目根目录下二、修改nginx配置,添加如下红框中的内容三、重启nginxsystemctlrestartnginx这样再次打开http://XXX:XX/swagger/即可直接打开swagger接口文档 ......
  • Nginx 配置
    #172.18.150.198epros-test-01upstreameprosdesignerService{server172.18.150.198:8080;}upstreameprosviewerService{server172.18.150.198:8088;}upstreameprosssoService{server172.18.150.198:8099;}upstreameprosapiService{......
  • docker 安装 nginx
    从https://blog.csdn.net/u010148813/article/details/126172372摘要的内容1.下载镜像dockerpullnginx:1.22.02.创建挂载目录mkdir/root/apply/docker/apply/nginx3.从容器中复制要挂载的文件dockerrun--namenginx1.22-p10080:80-dnginx:1.22.0dockercpngi......
  • https部署与docker下nginx的转发+文件获取
    进入nginx容器查看是否有etc/nginx/cert目录将https的域名证书放到cert目录下配置80和443server{#listen80;#侦听80端口listen80;#侦听443端口,用于SSLserver_name127.zyfdtsite.com;client_max_body_size1024m;#charsetkoi8-r;#acc......
  • nginx常用配置
    常用配置路径代理映射http和https配置nginx路径下的配置文件:/etc/nginx/conf.d/nginx.conf (每个人的可能不一样,但是我这个就是yum直接安装的)如下配置配置http和https、ws和wss#自定义配置地址upstreamhalo{server127.0.0.1:8090;}server{listen80;l......
  • Nginx 可视化神器!复杂配置一键生成,监控管理一条龙!
    功能说明nginxWebUI是一款图形化管理nginx配置的工具,可以使用网页来快速配置nginx的各项功能,包括http协议转发、tcp协议转发、反向代理、负载均衡、静态html服务器、ssl证书自动申请、续签、配置等。配置好后可一建生成nginx.conf文件,同时可控制nginx使用此文件进行启动与重载,完成......