Etcd + Confd 动态配置 nginx 站点

Etcd + Confd 动态配置 nginx 站点

运行环境为 Debian 11docker

1. 安装 nginx-proxy (该方案无直接安装 nginx 方便)

使用 docker 下载 nginx-proxy

1
2
docker pull nginxproxy/nginx-proxy:alpine
docker network create nginx-proxy
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
version: '2'

services:
  nginx-proxy:
    image: nginxproxy/nginx-proxy:alpine
    restart: always
    ports:
      - "80:80"
      - "443:443"
    environment:
      - ENABLE_IPV6=true
    volumes:
      - ./conf.d:/etc/nginx/conf.d
      - ./vhost.d:/etc/nginx/vhost.d:ro
      - ./certs:/etc/nginx/certs:ro
      - /var/run/docker.sock:/tmp/docker.sock:ro
    networks:
      - nginx-proxy

networks:
  nginx-proxy:
    external: true

2. 安装 nginx

直接安装源里的 nginx

1
apt install nginx

3. 运行 etcd

参考 使用 docker 运行 etcd

可以把 etcd keeper 一并运行,方便以图形化的界面管理 etcd 的值。

4. 运行 confd

参考资料: 官网

1. 下载

1
2
3
4
wget https://github.com/kelseyhightower/confd/releases/download/v0.16.0/confd-0.16.0-linux-amd64

mv confd-0.16.0-linux-amd64 /usr/local/sbin/confd
chmod +x /usr/local/sbin/confd

2. 配置

创建目录

1
mkdir -p /etc/confd/{conf.d,templates}

新建默认配置文件 /etc/confd/confd.toml

1
2
3
4
5
6
7
backend = "etcdv3"
confdir = "/etc/confd"
log-level = "debug"
interval = 600
nodes = [
  "http://127.0.0.1:2379"
]

新建模板配置文件 /etc/confd/conf.d/nginx-demo-web.toml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
[template]

src = "nginx-demo-web.tmpl"

dest = "/etc/nginx/sites-enabled/demo_sites"

keys = [
  "/demo-web"
]

owner = "root"
mode = "0644"

check_cmd = "nginx -t"
reload_cmd = "nginx -s reload"

新建模板文件 /etc/confd/templates/nginx-demo-web.tmpl

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
![*" ]( range gets "/demo-web/*" )
upstream upstream_![ replace (base .Key) "." "_" -1 ]( replace (base .Key) "." "_" -1 ) {
![= printf "%s/*" .Key ]( $server_dir := printf "%s/*" .Key ) ![ range gets $server_dir ]( range gets $server_dir )
    server ![ base .Key ]( base .Key ); ![ end ]( end )
}

server {
    # listen 80;
    listen 443 ssl http2;

    server_name ![ base .Key ]( base .Key );

    ssl_certificate /etc/nginx/certs/demo.example.com.crt;
    ssl_certificate_key /etc/nginx/certs/demo.example.com.key;

    index index.html index.htm index.nginx-debian.html;

    client_max_body_size 20M;

    location / {
        #try_files $uri $uri/ =404;
        proxy_set_header Host                 $http_host;
        proxy_set_header X-Real-IP            $remote_addr;
        proxy_set_header X-Real-PORT          $remote_port;
        proxy_set_header X-Forwarded-Proto    $scheme;
        proxy_set_header X-Forwarded-For      $proxy_add_x_forwarded_for;
        proxy_pass                            http://upstream_![ replace (base .Key) "." "_" -1 ]( replace (base .Key) "." "_" -1 );
    }
}

![ end ]( end )

3. 注册服务

新建文件 /etc/systemd/system/confd.service

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[Unit]
Description=Confd
Wants=network-online.target
After=network-online.target

[Service]
ExecStart=/usr/local/sbin/confd
Restart=always

[Install]
WantedBy=default.target

运行

1
2
systemctl daemon-reload
systemctl start confd

4. 测试

增加站点示例

打开 etcd keeper ,在 etcd 中增加如下示例节点

1
2
3
4
/demo-web/demo1.example.com/127.0.0.1:8080
/demo-web/demo1.example.com/127.0.0.1:8081
/demo-web/demo2.example.com/127.0.0.1:8082
/demo-web/demo2.example.com/127.0.0.1:8083

过一会儿可以看到生成 /etc/nginx/sites-enabled/demo_sites 文件,文件里的内容便是上面配置的网站。

TODO: 与 nginx-proxy 整合

整合之后,既可以通过 etcd 动态配置外部 web server,也能代理 docker 里面的 web server。