この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
本日時点でのHAProxyの安定最新版である1.6.5で一つ不具合があったので、その解決方法をご紹介します。
3行まとめ
- HAProxy 1.6.5の動的DNS解決の仕組みの部分にバグ
- 1.6.5にパッチを当てるか
- 1.6.4を使うことで修正される
HAProxyとは
HAProxyは高機能なプロキシ・ロードバランサとして開発されているOSSです。HAProxyを利用することで、WEBアプリケーションやDBサーバの負荷分散に利用することが可能です。AWSにもロードバランササービスとしてELBがありますが、ELBはRDSインスタンスを登録できないなどの成約があります。一方でHAProxyではRDSやElastiCacheなど、AWSのマネージドサービスも登録することが可能です。
ただ、HAProxy 1.5以前ではHAProxyの起動時にのみDNSの名前解決が行われていました。ですが、AWSの各種マネージドサービスはフェイルオーバー等でFQDNの指すIPアドレスが変わる可能性があるため、HAProxyをAWSサービスと組み合わせて利用する際にはIPアドレスが変更するたびにreloadやHAProxyの再起動が必要でした。
2015/10にリリースされたHAProxy1.6で、動的DNS解決の機能が追加され、定期的にDNSの名前解決を行うことでIPアドレスの変更に追従することが可能になりました。ですがこの仕組が1.6.5では機能していないようです。
原因
DNS問い合わせのヘッダ定義に問題があり、DNSリクエストが全てDNSレスポンス形式として解釈されてしまっているようです。以下の画像はHAProxy1.6.5を稼働させているAmazon Linux上でtcpdumpしたものをWiresharkで可視化したものになります。
対応策
以下ページでやりとりがされています。
- Dynamic DNS resolution does not work for me after 1.6.4 to 1.6.5 upgrade - Help! - HAProxy community
途中のコメントにある通り、このパッチを適用するか、このバグの出ない1.6.4を使ってほしい、とのことです。1.6.5での修正分が必要ないようであれば1.6.4を利用したほうがよさそうです。
[ec2-user@ip-172-31-12-20 ~]$ cd haproxy-1.6.5/
[ec2-user@ip-172-31-12-20 haproxy-1.6.5]$ cat patch
--- a/include/types/dns.h
+++ b/include/types/dns.h
@@ -63,16 +63,16 @@
/* DNS request or response header structure */
struct dns_header {
unsigned short id:16; /* identifier */
- unsigned char qr :1; /* query/response 0: query, 1: response */
- unsigned char opcode :4; /* operation code */
- unsigned char aa :1; /* authoritative answer 0: no, 1: yes */
- unsigned char tc :1; /* truncation 0:no, 1: yes */
unsigned char rd :1; /* recursion desired 0: no, 1: yes */
- unsigned char ra :1; /* recursion available 0: no, 1: yes */
- unsigned char z :1; /* not used */
- unsigned char ad :1; /* authentic data */
- unsigned char cd :1; /* checking disabled */
+ unsigned char tc :1; /* truncation 0:no, 1: yes */
+ unsigned char aa :1; /* authoritative answer 0: no, 1: yes */
+ unsigned char opcode :4; /* operation code */
+ unsigned char qr :1; /* query/response 0: query, 1: response */
unsigned char rcode :4; /* response code */
+ unsigned char cd :1; /* checking disabled */
+ unsigned char ad :1; /* authentic data */
+ unsigned char z :1; /* not used */
+ unsigned char ra :1; /* recursion available 0: no, 1: yes */
unsigned short qdcount :16; /* question count */
unsigned short ancount :16; /* answer count */
unsigned short nscount :16; /* authority count */
[ec2-user@ip-172-31-12-20 haproxy-1.6.5]$ patch -u include/types/dns.h < patch
[ec2-user@ip-172-31-12-20 haproxy-1.6.5]$ make
[ec2-user@ip-172-31-12-20 haproxy-1.6.5]$ sudo make install
一応、1.6.5に上記パッチを当てたものを再インストールして試してみました。以下がtcpdumpの結果です。
正常にDNSリクエストとレスポンスが返ってきたのが確認できました:)
HAProxyを新規導入される際やバージョンアップの際にはこの不具合にご注意ください。