CLOVER🍀

That was when it all began.

HAProxyの実行時の情報を、コマンドラインやWeb UIから見たり、操作したりしてみる

これは、なにをしたくて書いたもの?

HAProxyに、実行中の情報をコマンドラインやWeb UIで見たり、また操作したりできるみたいなので、ちょっと試してみようかと。

環境

今回利用したHAProxyは、こちら。

$ haproxy -v
HA-Proxy version 1.8.8-1ubuntu0.4 2019/01/24
Copyright 2000-2018 Willy Tarreau <willy@haproxy.org>

バックエンドのサーバーには、nginxを3つ用意しました。

それぞれ、IPアドレスは以下とします。

  • HAProxy … 172.17.0.2
  • nginx … 172.17.0.3〜5

HAProxyのベースの設定は、以下から始めます。
/etc/haproxy/haproxy.cfg

global
    log /dev/log    local0
    log /dev/log    local1 notice
    chroot /var/lib/haproxy
    user haproxy
    group haproxy
    daemon

defaults
    log global
    mode    http
    option  httplog
    option  dontlognull
        timeout connect 5000
        timeout client  50000
        timeout server  50000

frontend http
    bind *:80
    default_backend servers

backend servers
    balance roundrobin
    mode http
    http-request set-header X-Forwarded-Port %[dst_port]
    http-request add-header X-Forwarded-Proto https if { ssl_fc }

    server server1 172.17.0.3:80
    server server2 172.17.0.4:80
    server server3 172.17.0.5:80

コマンドラインから見る

HAProxyの操作を、ソケットファイルやTCPソケットで行うことができます。

ドキュメントは、こちら。

Unix Socket commands

ドキュメントにも記載がありますが、この機能を利用するためにはglobalセクションにソケットの定義をする必要があります。

global
    log /dev/log    local0
    log /dev/log    local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
    stats socket ipv4@localhost:9999 level admin
    stats timeout 30s
    user haproxy
    group haproxy
    daemon

この部分ですね。

    stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
    stats socket ipv4@localhost:9999 level admin
    stats timeout 30s

ソケットファイルのみでいい場合は、こんな感じに。

    stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
    stats timeout 30s

こちらは、TCPソケットを使う場合です。ローカルアドレスにのみバインドしてあります。

    stats socket ipv4@localhost:9999 level admin

設定したら、HAProxyを再起動します。

使い方ですが、ソケットファイルを使う場合はsocatコマンドと組み合わせます。

例えば、以下のように入力すると

$ sudo socat stdin /var/run/haproxy/admin.sock

待ち状態になるので「show info」と入力してみます。

show info

すると、現在の情報が表示されます。

Name: HAProxy
Version: 1.8.8-1ubuntu0.4
Release_date: 2019/01/24
Nbthread: 1
Nbproc: 1
Process_num: 1
Pid: 358
Uptime: 0d 0h21m05s
Uptime_sec: 1265
Memmax_MB: 0
PoolAlloc_MB: 0
PoolUsed_MB: 0
PoolFailed: 0
Ulimit-n: 4041
Maxsock: 4041
Maxconn: 2000
Hard_maxconn: 2000
CurrConns: 0
CumConns: 37
CumReq: 37
MaxSslConns: 0
CurrSslConns: 0
CumSslConns: 0
Maxpipes: 0
PipesUsed: 0
PipesFree: 0
ConnRate: 0
ConnRateLimit: 0
MaxConnRate: 0
SessRate: 0
SessRateLimit: 0
MaxSessRate: 0
SslRate: 0
SslRateLimit: 0
MaxSslRate: 0
SslFrontendKeyRate: 0
SslFrontendMaxKeyRate: 0
SslFrontendSessionReuse_pct: 0
SslBackendKeyRate: 0
SslBackendMaxKeyRate: 0
SslCacheLookups: 0
SslCacheMisses: 0
CompressBpsIn: 0
CompressBpsOut: 0
CompressBpsRateLim: 0
ZlibMemUsage: 0
MaxZlibMemUsage: 0
Tasks: 5
Run_queue: 0
Idle_pct: 100
node: 6ebd8af752eb

ドキュメントによると、以下のようにしてもOKみたいです。が、手元の環境では、どうもうまく動かず…。

$ echo 'show info' | sudo socat stdin /var/run/haproxy/admin.sock

また、「stdin」の部分を「readline」にすると、対話モードで実行することができます。

「prompt」コマンドを実行しても、対話モードに入ることができます。

$ sudo socat stdin /var/run/haproxy/admin.sock
prompt

> 

TCPソケットをリッスンしている場合は、ncコマンドで行うとよいでしょう。

$ echo 'show info' | nc localhost 9999
Name: HAProxy
Version: 1.8.8-1ubuntu0.4
Release_date: 2019/01/24
Nbthread: 1
Nbproc: 1
Process_num: 1
Pid: 358
Uptime: 0d 0h23m09s
Uptime_sec: 1389
Memmax_MB: 0
PoolAlloc_MB: 0
PoolUsed_MB: 0
PoolFailed: 0
Ulimit-n: 4041
Maxsock: 4041
Maxconn: 2000
Hard_maxconn: 2000
CurrConns: 0
CumConns: 38
CumReq: 38
MaxSslConns: 0
CurrSslConns: 0
CumSslConns: 0
Maxpipes: 0
PipesUsed: 0
PipesFree: 0
ConnRate: 0
ConnRateLimit: 0
MaxConnRate: 0
SessRate: 0
SessRateLimit: 0
MaxSessRate: 0
SslRate: 0
SslRateLimit: 0
MaxSslRate: 0
SslFrontendKeyRate: 0
SslFrontendMaxKeyRate: 0
SslFrontendSessionReuse_pct: 0
SslBackendKeyRate: 0
SslBackendMaxKeyRate: 0
SslCacheLookups: 0
SslCacheMisses: 0
CompressBpsIn: 0
CompressBpsOut: 0
CompressBpsRateLim: 0
ZlibMemUsage: 0
MaxZlibMemUsage: 0
Tasks: 5
Run_queue: 1
Idle_pct: 100
node: 6ebd8af752eb

ここからは、ncコマンドを使って確認してみます。

まず、どんなコマンドがあるか見てみましょう。
※「help」って入力しても、認識してないんですけど…

$ echo 'help' | nc localhost 9999
Unknown command. Please enter one of the following commands only :
  help           : this message
  prompt         : toggle interactive mode with prompt
  quit           : disconnect
  show tls-keys [id|*]: show tls keys references or dump tls ticket keys when id specified
  set ssl tls-key [id|keyfile] <tlskey>: set the next TLS key for the <id> or <keyfile> listener to <tlskey>
  show errors    : report last request and response errors for each proxy
  disable agent  : disable agent checks (use 'set server' instead)
  disable health : disable health checks (use 'set server' instead)
  disable server : disable a server for maintenance (use 'set server' instead)
  enable agent   : enable agent checks (use 'set server' instead)
  enable health  : enable health checks (use 'set server' instead)
  enable server  : enable a disabled server (use 'set server' instead)
  set maxconn server : change a server's maxconn setting
  set server     : change a server's state, weight or address
  get weight     : report a server's current weight
  set weight     : change a server's weight (deprecated)
  show sess [id] : report the list of current sessions or dump this session
  shutdown session : kill a specific session
  shutdown sessions server : kill sessions on a server
  clear table    : remove an entry from a table
  set table [id] : update or create a table entry's data
  show table [id]: report table usage stats or dump this table's contents
  clear counters : clear max statistics counters (add 'all' for all counters)
  show info      : report information about the running process
  show stat      : report counters for each proxy and server
  show schema json : report schema used for stats
  show startup-logs : report logs emitted during HAProxy startup
  show resolvers [id]: dumps counters from all resolvers section and
                     associated name servers
  set maxconn global : change the per-process maxconn setting
  set rate-limit : change a rate limiting value
  set severity-output [none|number|string] : set presence of severity level in feedback information
  set timeout    : change a timeout setting
  show env [var] : dump environment variables known to the process
  show cli sockets : dump list of cli sockets
  show fd [num] : dump list of file descriptors in use
  show activity : show per-thread activity stats (for support/developers)
  disable frontend : temporarily disable specific frontend
  enable frontend : re-enable specific frontend
  set maxconn frontend : change a frontend's maxconn setting
  show servers state [id]: dump volatile server information (for backend <id>)
  show backend   : list backends in the current running config
  shutdown frontend : stop a specific frontend
  set dynamic-cookie-key backend : change a backend secret key for dynamic cookies
  enable dynamic-cookie backend : enable dynamic cookies on a specific backend
  disable dynamic-cookie backend : disable dynamic cookies on a specific backend
  show cache     : show cache status
  add acl        : add acl entry
  clear acl <id> : clear the content of this acl
  del acl        : delete acl entry
  get acl        : report the patterns matching a sample for an ACL
  show acl [id]  : report available acls or dump an acl's contents
  add map        : add map entry
  clear map <id> : clear the content of this map
  del map        : delete map entry
  get map        : report the keys and values matching a sample for a map
  set map        : modify map entry
  show map [id]  : report available maps or dump a map's contents
  show pools     : report information about the memory pools usage

コマンド自体の説明は、ドキュメントに書かれています。

Unix Socket commands

サーバーの統計情報を見てみます。

$ echo 'show stat' | nc localhost 9999
# pxname,svname,qcur,qmax,scur,smax,slim,stot,bin,bout,dreq,dresp,ereq,econ,eresp,wretr,wredis,status,weight,act,bck,chkfail,chkdown,lastchg,downtime,qlimit,pid,iid,sid,throttle,lbtot,tracked,type,rate,rate_lim,rate_max,check_status,check_code,check_duration,hrsp_1xx,hrsp_2xx,hrsp_3xx,hrsp_4xx,hrsp_5xx,hrsp_other,hanafail,req_rate,req_rate_max,req_tot,cli_abrt,srv_abrt,comp_in,comp_out,comp_byp,comp_rsp,lastsess,last_chk,last_agt,qtime,ctime,rtime,ttime,agent_status,agent_code,agent_duration,check_desc,agent_desc,check_rise,check_fall,check_health,agent_rise,agent_fall,agent_health,addr,cookie,mode,algo,conn_rate,conn_rate_max,conn_tot,intercepted,dcon,dses,
http,FRONTEND,,,0,0,2000,0,0,0,0,0,0,,,,,OPEN,,,,,,,,,1,2,0,,,,0,0,0,0,,,,0,0,0,0,0,0,,0,0,0,,,0,0,0,0,,,,,,,,,,,,,,,,,,,,,http,,0,0,0,0,0,0,
servers,server1,0,0,0,0,,0,0,0,,0,,0,0,0,0,no check,1,1,0,,,1817,,,1,3,1,,0,,2,0,,0,,,,0,0,0,0,0,0,,,,,0,0,,,,,-1,,,0,0,0,0,,,,,,,,,,,,172.17.0.3:80,,http,,,,,,,,
servers,server2,0,0,0,0,,0,0,0,,0,,0,0,0,0,no check,1,1,0,,,1817,,,1,3,2,,0,,2,0,,0,,,,0,0,0,0,0,0,,,,,0,0,,,,,-1,,,0,0,0,0,,,,,,,,,,,,172.17.0.4:80,,http,,,,,,,,
servers,server3,0,0,0,0,,0,0,0,,0,,0,0,0,0,no check,1,1,0,,,1817,,,1,3,3,,0,,2,0,,0,,,,0,0,0,0,0,0,,,,,0,0,,,,,-1,,,0,0,0,0,,,,,,,,,,,,172.17.0.5:80,,http,,,,,,,,
servers,BACKEND,0,0,0,0,200,0,0,0,0,0,,0,0,0,0,UP,3,3,0,,0,1817,0,,1,3,0,,0,,1,0,,0,,,,0,0,0,0,0,0,,,,0,0,0,0,0,0,0,-1,,,0,0,0,0,,,,,,,,,,,,,,http,roundrobin,,,,,,,

show stat

frontend、backendの情報が見れます。ちょっとわかりにくいですが、バックエンドに3つのサーバーがいることもわかります。

「typed」や「json」を指定することで、フォーマットが変わります。

$ echo 'show stat typed' | nc localhost 9999
F.2.0.0.pxname.1:KNS:str:http
F.2.0.1.svname.1:KNS:str:FRONTEND
F.2.0.4.scur.1:MGP:u32:0
F.2.0.5.smax.1:MMP:u32:0
F.2.0.6.slim.1:CLP:u32:2000
F.2.0.7.stot.1:MCP:u64:0
F.2.0.8.bin.1:MCP:u64:0
F.2.0.9.bout.1:MCP:u64:0
F.2.0.10.dreq.1:MCP:u64:0
F.2.0.11.dresp.1:MCP:u64:0
〜省略〜


$ echo 'show stat json' | nc localhost 9999
[[{"objType":"Frontend","proxyId":2,"id":0,"field":{"pos":0,"name":"pxname"},"processNum":1,"tags":{"origin":"Key","nature":"Name","scope":"Service"},"value":{"type":"str","value":"http"}},{"objType":"Frontend","proxyId":2,"id":0,"field":{"pos":1,"name":"svname"},"processNum":1,"tags":{"origin":"Key","nature":"Name","scope":"Service"},"value":{"type":"str","value":"FRONTEND"}},{"objType":"Frontend","proxyId":2,"id":0,"field":{"pos":4,"name":"scur"},"processNum":1,"tags":{"origin":"Metric","nature":"Gauge","scope":"Process"},"value":{"type":"u32","value":0}},{"objType":"Frontend","proxyId":2,"id":0,"field":{"pos":5,"name":"smax"},"processNum":1,"tags":{"origin":"Metric","nature":"Max","scope":"Process"},"value":{"type":"u32","value":0}},{"objType":"Frontend","proxyId":2,"id":0,"field":{"pos":6,"name":"slim"},"processNum":1,"tags":{"origin":"Config","nature":"Limit","scope":"Process"},"value":{"type":"u32","value":2000}},
〜省略〜

また、値を変更することもできます。

例えば、maxconnは現在デフォルトの2000で起動していますが

$ echo 'show info' | nc localhost 9999 | grep -i maxconn
Maxconn: 2000
Hard_maxconn: 2000
MaxConnRate: 0

これを、100に変更してみましょう。

$ echo 'set maxconn global 100' | nc localhost 9999

maxconnは、frontend、backend、server、globalと複数の箇所で設定できますが、今回はglobalで変更してみます。

set maxconn global

確認。

$ echo 'show info' | nc localhost 9999 | grep -i maxconn
Maxconn: 100
Hard_maxconn: 2000
MaxConnRate: 0

maxconnが変更されていますね。

Web UIから統計情報を見る

ここまでコマンドラインでアクセスしてきましたが、ちょっと見づらい感じもします。

Web UIで統計情報を見ることもできるようなので、そちらを試してみましょう。

frontendセクションを追加して、statsを有効にします。

frontend stats
    bind *:8404
    stats enable
    stats uri /stats
    stats refresh 10s
    stats admin if { src 192.168.0.2 }

まずは、「stats enable」。それから、8404ポートで、パス「/stats」で見られるようにしています。
また、10秒ごとにリフレッシュして、アクセス元は絞る感じで。

stats enable

HAProxy越しに、nginxに何度かアクセスしてみます。

$ curl 172.17.0.2

この状態で、「http://172.17.0.2:8404/stats」にアクセス。

f:id:Kazuhira:20190710225756p:plain

だいぶわかりやすく、統計情報を見ることができます。

また、ドキュメントに記載のある通り、backendにも設定することができます。

例えば、こんな感じで。

frontend http
    bind *:80
    default_backend servers

backend servers
    balance roundrobin
    mode http
    http-request set-header X-Forwarded-Port %[dst_port]
    http-request add-header X-Forwarded-Proto https if { ssl_fc }

    server server1 172.17.0.3:80
    server server2 172.17.0.4:80
    server server3 172.17.0.5:80

    stats enable
    stats uri /stats
    stats refresh 10s
    stats admin if { src 192.168.0.2 }

この場合、「http://172.17.0.2/stats」のように、バックエンドに対するパスが一部奪われる形でWeb UIが参照できます。

f:id:Kazuhira:20190710230239p:plain

この設定方法だと、指定されたbackendに関する情報(とその前段のfrontendの情報)が表示されるようです。

こういう機能は、アクセスに関する制限をかけたりする必要があると思うので、そのあたりに関する設定は考慮しておきましょう、と。

stats realm

stats auth

stats admin

stats http-requet

まとめ

HAProxyの実行時の情報をコマンドラインやWeb UIから見たり、コマンドラインからは操作したりしてみました。

HAProxyの情報はややわかりにくいところもあるので、こうやって確認する方法は把握しておいた方がいいのかなぁと思います。
Web UIは、助かります…。

参考)

Exploring the HAProxy Stats Page - HAProxy Technologies

Haproxy: Unix Socket commands

haproxyを試す 4.ソケット接続とステータス出力 – harumaki.net