Nginx配置管理(2021)

本来其实是总结博客搭建的,结果总结了半天发现里面最有意义的部分就是我nginx的配置和管理了。所以就单独抽出来水一贴。


以这个博客来说。这个博客是pub域名结尾,那么根据我的策略,国内用户访问其实要经过整整5次nginx转发:CN CDN -> SG CDN -> USA CDN -> k8s nginx -> pub nginx -> Ghost

网络转发逻辑虽然确实蠢了一点,但这个问题本身并不复杂,只是没有动手解决罢了。而这背后真正的问题其实是:在这些nginx本身的运行环境和管理方式都有很大差异的情况下的配置与管理的问题(CDN独立于集群管理,且有两个独立的集群)。

我的nginx大概是这么个结构(命名就不要吐槽了,没钱又懒得改)。

首先看2层:

nginx
├── Dockerfile
├── certs
│   ├── xxxxxx
│   └── pub
└── nginxConfig
    ├── http
    ├── nginx.conf
    └── streams

Dockerfile不解释了。
certs里面包含两个域名的证书也不多说了。
nginxConfig,是具体nginx的配置,里面包含了根nginx.conf,以及httpstream两个folder。其中http是所有http请求相关配置,streams里面是tcp/udp的转发配置。

streams里面就是一个个具体的.conf就不多展开了。这里展开http这个folder。

http
├── default
└── specific.conf

http里面主要分两块,一个是specific,一个是default
其中specific是各个环境、场景定制的配置。但约定所有的定制都只能是覆盖和修改default的配置。对于较少的覆盖,specific可以和这里一样是一个具体的.conf文件,对于较多的覆盖,specific可以也是一个folder。
default是所有环境、所有场景共享的配置。只要是我所用到的nginx,里面这个folder下的内容要求是完全一致的。

这里先展开default

default
├── destination
│   ├── cn.conf
│   ├── defaultProxy.conf
│   ├── sg.conf
│   └── usa.conf
├── https
│   ├── https.conf
│   ├── xxxxxx-certificate.conf
│   └── pub-certificate.conf
└── services
    ├── 80To443.conf
    ├── apps.conf
    ├── infrastructure.conf
    ├── pub.conf
    └── test.conf

destination里面定义的是几个CDN节点的位置。defaultProxy.conf里面就是一些默认的proxy配置,被{location}.conf共同使用。{location}.conf里面几乎就纯是proxy_pass
https里面就是证书信息。https.conf里面就是一些通用的https配置。和destination一样,被{domain}.config共同使用。而{domain}.config里就是指一下证书路径。
services里面包含了所有服务的信息,或者更准确的说,是所有服务的位置信息。

这里进一步阐述一下default/services的内容。以gogs.xloypaypa.pubblog.xloypaypa.pub为例。
pub.conf中,gogs和blog的配置如下:

server {
    server_name ~^gogs\..*xloypaypa\.pub$;

    access_log            /var/log/nginx/pub.gogs.access.log;
    include /etc/nginx/http/default/https/pub-certificate.conf;

    location / {
        include /etc/nginx/http/default/destination/cn.conf;
    }
}

server {
    server_name ~^blog\..*xloypaypa\.pub$;

    access_log            /var/log/nginx/pub.blog.access.log;
    include /etc/nginx/http/default/https/pub-certificate.conf;
    location / {
        include /etc/nginx/http/default/destination/usa.conf;
    }
}

个人能力有限,到这我就满足了。
对于gogs,由于其服务在国内,那么server_name不管是gogs.usa.xloypaypa.pub还是gogs.cn.xloypaypa.pub还是gogs.xloypaypa.pub都将被转发至CN CDN的服务器。而这个博客无论如何都会被转发到USA。

而对于specific。这里就得话分两头说,先说较为简单的CDN上的nginx。
根据default的配置,对于其他CDN节点的服务自然会被转发到其他的CDN。但对于自己负责的服务就需要特殊配置。以CN CDN为例,配置如下:

upstream cn.xloypaypa.pub {
    server v2xxx:443;
}

cn.xloypaypa.pub是配置在nginx/nginx/http/default/destinationcn.conf的。
无疑,CN CDN自然是负责我家里的物理机上的集群的。而我是采用某V姓网络工具,通过内网穿透暴露服务的。因此,CN CDN上的nginx只需要在specific里将所有cn的流量转发到这个V姓网络工具即可。
总之,这里就是在default要求我把流量转发给我自己的时候,转发给真正的目标。仅此而已。

然后CN CDNsepcific里其实也有下面这段配置:

upstream usa.xloypaypa.pub {
    server sg.xloypaypa.pub:443;
    server usa.xloypaypa.pub:443 backup;
}

这就是默认走sg绕一圈的原因。

根据上面的操作,流量其实已经到了k8s里了。配置的结构大概长这个样子:

http
├── default
│   ├── destination
│   ├── https
│   └── services
├── specific
│   ├── app.conf
│   ├── infrastructure.conf
│   └── pub.conf
└── specific.conf

其中specific.conf大概长这个样子:

include /etc/nginx/http/specific/*.conf;
include /etc/nginx/http/default/services/*.conf;

简而言之就是一个个覆盖default/services的东西,只不过不是直接修改,而是新写一个文件,并且确保这个文件比default里的文件优先级高就好了(specific.conf就是做这个事情的)。

这里其实是有个缺陷。其实处于根部的nginx.conf并不会主动加载default里的任何东西。nginx.conf里面的配置其实是include /etc/nginx/http/*.conf;。也就是实际上只会加载specific.conf。而default的加载是需要在specific.conf显式的写出来的。其实稍微抽一下就可以解决,但懒得弄了,没必要。

我大概就是通过这个方式,维护一个统一的default,然后各个环境各自去维护自己的specific.conf完成伪·CDN和两个k8s里面一堆nginx的配置管理的。菜的不行,轻喷。


这里附上一个完整的配置结构:

nginx
├── Dockerfile
├── certs
│   ├── xxxxxx
│   │   ├── cert.pem
│   │   ├── chain.pem
│   │   ├── fullchain.pem
│   │   ├── privkey.pem
│   │   └── README
│   └── pub
│       ├── cert.pem
│       ├── chain.pem
│       ├── fullchain.pem
│       ├── privkey.pem
│       └── README
└── nginxConfig
    ├── http
    │   ├── default
    │   │   ├── destination
    │   │   │   ├── cn.conf
    │   │   │   ├── defaultProxy.conf
    │   │   │   ├── sg.conf
    │   │   │   └── usa.conf
    │   │   ├── https
    │   │   │   ├── https.conf
    │   │   │   ├── xxxxxx-certificate.conf
    │   │   │   └── pub-certificate.conf
    │   │   └── services
    │   │       ├── 80To443.conf
    │   │       ├── apps.conf
    │   │       ├── infrastructure.conf
    │   │       ├── pub.conf
    │   │       └── test.conf
    │   ├── specific
    │   │   ├── app.conf
    │   │   ├── infrastructure.conf
    │   │   └── pub.conf
    │   └── specific.conf
    ├── nginx.conf
    └── streams
        ├── gogs.conf
        └── ldap.conf


最后解释一下为什么k8s nginx后面还会有pub nginx
简而言之,就是pub域名毕竟不是亲儿子的。因此专门设置了pub nginx进行全局限速。至于为什么pub nginx为什么在k8s nginx后面,这个主要是懒,直接开会端口冲突。改端口又要防火墙,偷个懒。