使用 HAProxy 替 ASP.NET Core on CentOS 做 High Availability (設定篇)

  • 332
  • 0

最近有個案子,環境限定 CentOS + PostgreSQL 而且還要 HA(High availability) 的架構。是我完全不熟的東西,在經過多方摸索以後,把相關安裝設定方式記錄一下。

首先提到 HA,正式環境是用 L4 Switch 做 Round Robin AA,由於 L4 Switch 不是我玩的起的硬體,所以 Google 了一下,看看有沒有什麼替代方案?於是找到了富人用 L4 Switch,窮人用 Linux HAProxy!大致上應該可以用在我們測試環境上,我們就來試試看了。

我們準備三個 VM 分別是 HAProxy, Web 1, Web2 IP 分配如下:

Server IP
HAProxy 192.168.0.130
Web 1 192.168.0.131
Web 2 192.168.0.132

先來準備兩台 Web Server 吧。安裝 CentOS 8 就跳過了,安裝完後,習慣先更新一下已經安裝的套件:

sudo dnf update

接著安裝 dotnet sdk:

sudo dnf install dotnet

由於之後會用 HAProxy 所以這邊就省略用 nginx 做 reverse proxy 了,正式環境會加上 nginx 做 reverse proxy。因此這邊防火牆我們直接開 5000 的 port 就好:

sudo firewall-cmd --permanent --zone=public --add-port=5000/tcp
sudo firewall-cmd --reload

接著我將寫好的 service 複製到指定位置:

sudo cp frank.service /etc/systemd/system/frank.service

service 內容如下:

[Unit]
Description=Frank Web Server

[Service]
WorkingDirectory=/var/www/Frank
ExecStart=/usr/bin/dotnet /var/www/Frank/Frank.dll --urls http://0.0.0.0:5000
Restart=always
RestartSec=10
SyslogIdentifier=frank-web-server
User=frank
Environment=ASPNETCORE_ENVIRONMENT=Development
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

[Install]
WantedBy=multi-user.target

這邊 --urls http://0.0.0.0:5000 很重要,如果多張網卡,可以指定特定 IP,如果這邊沒用 --urls 那只能從 localhost 連了。

以及將發行好的檔案複製到指定位置,並變更目錄擁有者:

sudo mkdir /var/www
sudo cp -r Frank /var/www
sudo chmod g+w -R /var/www/Frank
sudo chown -R frank.frank /var/www/Frank

最後啟用 service 並執行他:

sudo systemctl enable frank.service
sudo systemctl start frank.service
sudo systemctl status frank.service

到這邊正常來說沒遇到什麼問題,你用:

curl http://192.168.0.131:5000

應該會通了。

Web 2 依樣畫葫蘆,也可以順利完成。當然,如果 appsettings.json 裡面有和自身 IP 相關的地方,要記得修改。

接著我們來安裝 HAProxy,一樣先更新已安裝套件:

sudo dnf update

接著安裝 HAProxy:

sudo dnf install haproxy

準備好的憑證,複製到指定位置:

sudo cp frank.pem /etc/ssl/certs/frank.pem

事先準備好的 config 覆蓋原本的:

sudo cp haproxy.cfg /etc/haproxy/haproxy.cfg

我這邊 config 設定:

global
    log         127.0.0.1 local2

    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon
    tune.ssl.default-dh-param 4096
    stats socket /var/lib/haproxy/stats
    ssl-default-bind-ciphers PROFILE=SYSTEM
    ssl-default-server-ciphers PROFILE=SYSTEM

defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000

# HAProxy 監控儀表板
listen stats
    # port 可以調整自己喜歡的
    bind *:8080
    mode http
    stats enable
    stats hide-version
    stats realm Haproxy\ Statistics
    stats uri /
    # 帳號密碼,這邊帳密可以改成自己想要的
    stats auth frank:haproxy
    stats refresh 10s

frontend main
    mode http
    bind *:443 ssl crt /etc/ssl/certs/frank.pem
    default_backend frank

backend frank
    balance roundrobin
    server  web1 192.168.0.131:5000 check
    server  web2 192.168.0.132:5000 check

設定防火牆,開啟 https 以及 8080(HAProxy 狀態頁面用的,可於 config 修改 port):

sudo firewall-cmd --permanent --zone=public --add-service=https
sudo firewall-cmd --permanent --zone=public --add-port=8080/tcp
sudo firewall-cmd --reload

到這邊如果順利的話,連 192.168.0.130 應該就會把流量分到 web 1, web 2 上,可以分別在兩個 site 上面做些區別,用不同瀏覽器試試看。

參考文章:
ASP.NET Core + Nginx on CentOS 安裝筆記
指定 ASP.NET Core Kestrel 接聽 Port
富人用 L4 Switch,窮人用 Linux HAProxy!
HAProxy 整合 SSL/TLS Client Certificate 教學
[CentOS] Install and tuning HAproxy1.8