Skip to content

Nginx как TCP, HTTP Load Balancer

My Diagram Реализуем LoadBalancer с функциями: - умеет прокидывать в докер контейнеры на хосте - умеет проксировать на другие сервера в локальной сети - умеет прокидывать tcp в kubernetes кластер Это дает возможность терминировать tls как на хосте(для контейнеров и для хостов в локальной сети) так и в кластере(и получать сертификаты через cert-manager)

Основная магия здесь в ssl_preread_server_name. Используется в Nginx для извлечения имени сервера (Server Name Indication - SNI) из SSL/TLS ClientHello сообщения во время установки SSL-соединения с клиентом. Это позволяет еще до момента терминации tls определять куда направить трафик

Сертификаты в кластере cert-manager сможет получить только через DNS01, потому что 80 порт на хосте , а на нем нет записей о ресурсах, которые развернуты через ingress nginx.

Минус это схемы в том, что не получится использовать external-dns, потому что ingress будут создаваться с ExternalIP внутренним, а нам нужен внешний, чтобы запись А создавалась корректно. Получается хосты придется добавлят вручную в nginx.

Nginx из-за пропускной скорости и меньших задержек на данный момент лучше подходит для prod, Traefik более динамичный используем под test, stage. https://medium.com/beyn-technology/is-nginx-dead-is-traefik-v3-20-faster-than-traefik-v2-f28ffb7eed3e

/etc/nginx/nginx.conf
stream {
    upstream truedev {
        server 127.0.0.1:8443;
    }

    upstream k8s {
        server 10.0.1.102:31443;
        server 10.0.1.103:31443;
    }
    #upstream host { 
    #    server 127.0.0.1; 
    #}
    # ...

    map $ssl_preread_server_name $upstream {
        truedev.ru truedev;
        k8ss.truedev.ru k8s;
        # ...
    }

    server {
        listen 443;

        resolver 1.1.1.1;
        proxy_connect_timeout 1s;
        proxy_timeout 3s;

        proxy_pass $upstream;
        ssl_preread on;
    }
}
http {
    sendfile on;
    tcp_nopush on;
    types_hash_max_size 2048;
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
    ssl_prefer_server_ciphers on;
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
    gzip on;
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}
/etc/nginx/sites-enabled/k8ss.truedev.ru.conf
upstream k8ss_server {
    server 10.0.1.102:31080;
    server 10.0.1.103:31080;
}

server {
    listen 80;
    server_name k8ss.truedev.ru;
    location / {
      proxy_pass  http://k8ss_server;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Forwarded-Host $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
    include /etc/nginx/templates/letsencrypt.conf;
}
IBS
server {
    server_name ibs-java.truedev.ru;
    access_log /var/log/nginx/ibs-java.truedev.ru-access.log;
    error_log /var/log/nginx/ibs-corenet.truedev.ru-error.log;

    client_max_body_size 0;
    fastcgi_connect_timeout 60;
    fastcgi_send_timeout 1200;
    fastcgi_read_timeout 1200;
    proxy_read_timeout 1d;
    proxy_buffering off;

    location / {
#       limit_req zone=darkfire burst=50 nodelay;
        proxy_pass http://127.0.0.1:8083;
        proxy_http_version 1.1;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_buffers 16 4k;
        proxy_buffer_size 2k;
    }
    listen 8443 ssl http2;
    ssl_certificate /etc/letsencrypt/live/ibs-java.truedev.ru/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ibs-java.truedev.ru/privkey.pem;

    include /etc/nginx/ssl_params;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header Content-Security-Policy "block-all-mixed-content";

    ssl_dhparam /etc/ssl/certs/dhparam.pem;

    include /etc/nginx/templates/letsencrypt.conf;
}
ssl params
ssl_protocols TLSv1.2 TLSv1.3; # Only allow TLS 1.2 and TLS 1.3
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384';
ssl_stapling on;
ssl_stapling_verify on;
ssl_prefer_server_ciphers off; # Disable prefer_server_ciphers
letsencrypt.conf
location ^~ /.well-known/acme-challenge/ {
   default_type "text/plain";
   root /var/www/letsencrypt;
}
location = /.well-known/acme-challenge/ {
   return 404;
}