目的
Nginxをhttpロードバランサとして用いるケースはよくある。nginxはTCPやUDPでもルーティング出来る様なので、今回はそれを試す。
構成
ディレクトリ構造
- docker-compose.yml
- Dockerfile
- docker-log
- unbound.conf
- nginx
- Dockerfile
- nginx.conf
- start.sh
docker-compose.yml
unbound1, unbound2で2台のDNSを構築する。nginxl4でL4loadbalancerを構築
version: "3.9"
services:
unbound1:
build: .
image: unbound-alma:1.0.0
container_name: unbound1
tty: true
networks:
vlan0:
ipv4_address: 172.24.20.210
volumes:
- unbound1:/etc/unbound/log/
unbound2:
build: .
image: unbound-alma:1.0.0
container_name: unbound2
tty: true
networks:
vlan0:
ipv4_address: 172.24.20.211
volumes:
- unbound2:/etc/unbound/log/
nginxl4:
container_name: nginxl4
restart: always
build: ./nginx
image: nginxl4
tty: true
stdin_open: true
networks:
vlan0:
ipv4_address: 172.24.20.15
networks:
vlan0:
name: vlan0
driver: macvlan
driver_opts:
parent: enp1s0
ipam:
config:
- subnet: 172.24.20.0/24
gateway: 172.24.20.254
volumes:
unbound1:
unbound2:
DNSの構築
以下には実際のDNSの設定を入れていく。
Dockerfile
FROM almalinux:latest
RUN yum -y update && yum -y install unbound
ADD unbound.conf /etc/unbound/
ENV TZ=Asia/Tokyo
ADD docker-log /etc/logrotate.d/
RUN mkdir -p /etc/unbound/log/
RUN chmod 777 /etc/unbound/log/ && \
chown unbound:unbound /etc/unbound/log/ && \
touch /etc/unbound/log/unbound.log && \
chmod 777 /etc/unbound/log/unbound.log && \
chown unbound:unbound /etc/unbound/log/unbound.log && \
chmod 644 /etc/logrotate.d/*
ENTRYPOINT ["/usr/sbin/unbound","-d","-c","/etc/unbound/unbound.conf"]
docker-log
ログの設定を入れる。
/etc/unbound/log/unbound.log { # 対象のログファイル
ifempty # ログファイルが空でもローテーションする
dateformat .%Y%m%d # dateフォーマットを任意のものに変更する
missingok # ログファイルがなくてもエラーを出さない
compress # 圧縮する
rotate 10 # 10世代分古いログを残す
postrotate # ローテート後にsyslogを再起動
/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
endscript
}
unbound.conf
unbound自体の設定ファイル。
ローカルドメインを一つ設定しておく。
server:
# Send minimum amount of information to upstream servers to enhance
# privacy. Only sends minimum required labels of the QNAME and sets
# QTYPE to NS when possible.
# See RFC 7816 "DNS Query Name Minimisation to Improve Privacy" for
# details.
# qname-minimisation: yes
# allow local address
access-control: 0.0.0.0/0 allow
# listen interface
interface: 0.0.0.0
# hide version
hide-version: yes
hide-identity: yes
logfile: "/etc/unbound/log/unbound.log"
use-syslog: no
log-queries: yes
log-time-ascii: yes
local-data: "www.tmcit.sho IN A 172.24.20.25"
# local-data: "fuga.example.com. IN A 172.16.0.2"
# local-data: "foo.example.com. IN A 172.16.0.3"
# local-data: "bar.example.com. IN A 172.16.0.4"
#forward-zone:
# name: "example.org."
# forward-addr: 192.168.10.5
forward-zone:
name: "."
forward-addr: 8.8.8.8
forward-addr: 8.8.4.4
forward-addr: 172.24.2.51
Nginxの構築
Dockerfile
FROM almalinux:latest
ADD start.sh /
ADD nginx.conf /usr/local/nginx-1.25.1/conf/nginx.conf
RUN chmod +x /start.sh
RUN yum -y update && yum -y install wget gcc openssl-devel pcre-devel openssl-devel libxslt-devel gd-devel perl-ExtUtils-Embed epel-release nginx-mod-stream
RUN yum -y groupinstall "Development Tools"
RUN yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
RUN yum -y install GeoIP-devel
RUN wget http://nginx.org/download/nginx-1.25.1.tar.gz
RUN tar -zxvf nginx-1.25.1.tar.gz
RUN cd nginx-1.25.1 && ./configure --prefix=/usr/local/nginx-1.25.1 \
--user=www \
--group=www \
--pid-path=/var/run/nginx.pid \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--lock-path=/var/run/nginx.lock \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_stub_status_module \
--without-http_rewrite_module \
--without-http_gzip_module \
--with-stream \
--with-stream=dynamic \
--with-stream_ssl_module \
--with-stream_geoip_module \
--with-stream_geoip_module=dynamic
RUN cd nginx-1.25.1 && make && make install
RUN groupadd www && useradd -g www www && usermod -s /bin/false www
ENTRYPOINT ["/start.sh"]
start.sh
起動時に実行するスクリプト
start.sh
#!/bin/bash
/usr/local/nginx-1.25.1/sbin/nginx -c /usr/local/nginx-1.25.1/conf/nginx.conf
while true; do echo test >> /dev/null; sleep 1s; done
nginx.conf
1行目で、モジュールの読み込みを行う。
stream
ディレクティブで、proxy先のサーバーを指定する
load_module /usr/local/nginx-1.25.1/modules/ngx_stream_module.so;
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
}
# include mime.types;
# default_type application/octet-stream;
#
# #log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# # '$status $body_bytes_sent "$http_referer" '
# # '"$http_user_agent" "$http_x_forwarded_for"';
#
# #access_log logs/access.log main;
#
# sendfile on;
# #tcp_nopush on;
#
# #keepalive_timeout 0;
# keepalive_timeout 65;
#
# #gzip on;
stream {
proxy_protocol on;
upstream dns {
server 172.24.20.210:53;
server 172.24.20.211:53;
}
server {
listen 53 udp;
proxy_pass dns;
}
}
# server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
# location / {
# root html;
# index index.html index.htm;
# }
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# root html;
# }
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
# }
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
確認
現状の課題
- VPN越しだと解決が出来ない。同じセグメントに属している場合は問題なく解決できる
→ DNSをホストか、portsで公開