Nao000のぶろぐ

蝶を追っている少年になりたい

L7ロードバランサーにお近づきになるために docker コンテナで HAProxy を体験してみる

コンテナの構成

以下のコンテナ構成でホストPCからリクエストを行って体験します。

  • HAProxy コンテナ1台
  • Apache httpd コンテナ2台
    • コンテナ名は httpd-1, httpd-2 です
  • php-fpm コンテナ2台
    • コンテナ名は phpfpm-1, phpfpm-2 です

設定ファイルは割愛しますが、httpd-1コンテナは phpfpm-1コンテナにリクエストを転送し、httpd-2コンテナは phpfpm-2コンテナにリクエストを転送します。

図解するよ以下のようになります。

コンテナの構成の図解

HAProxy を動かすための Dockerfile を用意

パッケージインストールするところから始めたいのでここからスタートします。

FROM ubuntu:22.04

ENV TZ Asia/Tokyo
RUN apt update -y && apt upgrade -y
RUN apt install less -y
RUN apt install unzip -y
RUN apt install vim -y
RUN apt install inetutils-ping -y

RUN apt install -y language-pack-ja-base language-pack-ja locales
RUN locale-gen ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8

compose.yaml はこんな感じです

services:
  ha_proxy:
    build:
      context: ./docker
      dockerfile: ./dev-Dockerfile-HAProxy
    ports:
      - "80:80"
  httpd-1:
    container_name: httpd-1
    build:
      context: ./docker
      dockerfile: ./dev-Dockerfile-httpd
    depends_on:
      - phpfpm-1
    environment:
      PHP_FPM_CONTAINER: "phpfpm-1"
  httpd-2:
    container_name: httpd-2
    build:
      context: ./docker
      dockerfile: ./dev-Dockerfile-httpd
    depends_on:
      - phpfpm-2
    environment:
      PHP_FPM_CONTAINER: "phpfpm-2"
  phpfpm-1:
    container_name: phpfpm-1
    build:
      context: ./docker
      dockerfile: ./dev-Dockerfile-phpfpm
  phpfpm-2:
    container_name: phpfpm-2
    build:
      context: ./docker
      dockerfile: ./dev-Dockerfile-phpfpm

HAProxy コンテナに haproxy をインストールしました

HAProxy のバージョンは 2.4.24 でした。

root@952d31c187d4:/# which haproxy
/usr/sbin/haproxy
root@952d31c187d4:/# /usr/sbin/haproxy -h
HAProxy version 2.4.24-0ubuntu0.22.04.1 2023/10/31 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2 2026.

HAProxy の設定

httpd-1, httpd-2 は Apache httpd が稼働するコンテナ2台のそれぞれのコンテナ名です。 Dockerではコンテナ名で相互に接続できるので名前で指定しています。

振り分けアルゴリズムはラウンドロビンにしました。後述しますが、リクエストごとに振り分け先を変更したかったのですが、そういう動作にはなりませんでした。

~^^^^ 上には初期設定がありますが省略 ^^^^~
frontend myfrontend
  bind 0.0.0.0:80
  default_backend myservers

backend myservers
  balance roundrobin
  server server1 httpd-1:80
  server server2 httpd-2:80

ホストPCからリクエストしてみる

HAProxy コンテナは80番ポートでリクエストを受け付けています。また、Apache httpd コンテナは2台とも ServerName に www.nao000.internal を設定しています。

ホストPCから http://www.nao000.internal/ という URL でアクセスできるようになります。

また、HAProxy コンテナによる振り分けが出来ているか判別できるように、画面には php-fpm コンテナ2台それぞれのホスト名を出力しています。

振り分けアルゴリズムをラウンドロビンにしてリクエストごとに php-fpm コンテナ2台に交互にアクセスする動作を確認したかったのですが、実際にはなりませんでした。

以下はブラウザからアクセスしたときの様子の gif です。F5で更新しています。

ブラウザからアクセスしたときに HAProxy によって振り分けられる様子

リクエストごとにコンテナが切り替わる動作にはなりませんでしたが、時々変わっているのが確認できました。

追記▶▶▶▶▶▶▶▶▶▶▶▶

2025-01-05 23:38

時々しか振り分け先サーバーが変わらないのは、リクエストヘッダーの Connection: KeepAlive が関係してそうです。

curl で試すと毎回変わっていました。

◀◀◀◀◀◀◀◀◀◀◀◀◀◀

追記▶▶▶▶▶▶▶▶▶▶▶▶

2025-01-06 21:50

curl で Connection: keep-alive をつけても毎回変わりました。謎です。

curl -H 'Connection: keep-alive' http://www.nao000.internal

実は HAProxy からのレスポンスはキャッシュされていて、同じTCPコネクションならキャッシュを返しているとかですかね。

curl の場合ってTCPコネクションを毎回破棄しているのですかね。

◀◀◀◀◀◀◀◀◀◀◀◀◀◀

なお、以下の index.php がレスポンスされています。

<!DOCTYPE html>
<html>
<head>
    <title>Document</title>
</head>
<body>
    <p>hello from</p>
    <p style="font-size: 24px;"><?php echo htmlspecialchars(gethostname()); ?></p>
</body>
</html>

おわり

ロードバランサーがより身近に感じれるようになりました。

今回は振り分け先サーバーの負荷状況は見ていませんが多分出来ますよね。それを行うには振り分け先サーバーにもエージェント的なツールをインストールする必要があるかなと思います。