心地よいライフハック

これ便利だな〜と思ったことなど

HAproxy ( docker コンテナ版 ) 設定のリロード

 

 
HAproxy コンテナ起動中でもサクッと設定をリロード。config  reload 。グレイスフル リロード
 

 
起動中のコンテナのコンフィグを上書き更新する。
docker ホスト側からコマンド。
 
# docker cp ./dockerホスト側のディレクトリ/haproxy.cfg コンテナID:/usr/local/etc/haproxy/haproxy.cfg
 
上書きしたコンフィグファイルのリロード
グレイスフル・リロード方法 )
 
# docker kill -s HUP 動作中のコンテナ名
 
コマンド例
# docker kill -s HUP my-running-haproxy
 
参考:
 

 
動作確認環境 ( 2019年 2月初旬 )
 
Docker version 1.13.1, build 07f3374/1.13.1
docker-compose version 1.23.2, build 1110ad01
CentOS Linux release 7.4.1708 (Core)
HAproxy 1.9
 

 
 

docker コンテナの HAproxy で、config と一緒に ユーザーリスト を取り込む方法

 
docker 版 HAproxy を使う。その際に、Basic 認証 などで使う ユーザーリスト や、設定ファイル ( haproxy.cfg )を どうやって取り込ませるか?食わせるか?
 
できたので、記録しておく。
 
ついでに https で使う pem ファイルも取り込んだ。
 

  
 

 
 

  1. docker pull

 
    # docker pull haproxy
 

  2. haproxy の稼働に必要なファイルの準備

 
    ・ haproxy.cfg
    ・ userlist.cfg (Basic認証で使うユーザーリストなど必要に応じて)
    ・ SSL(HTTPS)で使うpemファイルなど 取り込みたいファイル
 

  3. DockerFile の作成

 
    Dockerfile という名前のファイルを作る。中身
 
 

 
    FROM haproxy:1.9
    COPY ./haproxy.cfg    /usr/local/etc/haproxy/haproxy.cfg
    COPY ./userlist.cfg   /usr/local/etc/haproxy/userlist.cfg
    COPY ./haproxy.pem    /usr/local/etc/haproxy/cert/haproxy.pem
 

 
 
    ここで、COPY コマンドの引数2つについて。
    左側: コマンドを打つDocker ホスト側の世界。ファイル名(パス)
    右側: コンテナ内のファイル名(パス)
 
    haproxy コンテナ内に /usr/local/etc/haproxy というパスがあるので、
    その中に、手元のファイルを放り込んであげる形。
 
    ( 挙動を見ている限りではビルド時にコピーされるようなので、稼働中は、難しそう )
 
    ・用意ができたら確認
 
    自分はこんな感じです。
 
 

 
    # pwd
    /root/dev/haproxy
 
    # ls
    Dockerfile  haproxy.cfg  haproxy.pem  userlist.cfg
 

 
 

  4. docker build

 
    上記、場所にいる状態で コマンドを打つ。
 
    # docker build -t myhaproxyなど任意コンテナ名 .
 

  5. HAproxyコンテナの設定検証

 
    haproxy 設定ファイル の docker 検証を行います。 
 
    # docker run -it --rm --name haproxy-syntax-check myhaproxy haproxy -c -f /usr/local/etc/haproxy/haproxy.cfg -f /usr/local/etc/haproxy/userlist.cfg
 
    < 解説 >
    ・ -f で haproxy に 直接食わせたいコンフィグファイルを指定。
    ・ -c で 設定ファイルのチェック。
 
 
 
 

 
 
    設定ファイルのチェックでNGなら 問題箇所を修正して 2.から再度チャレンジ。
 
    OKなら 以下に進んでコンテナを起動する。
 

   6. docker run

 
     (ユーザーリストなどなしの例)
    # docker run -d --name my-running-haproxy myhaproxy
 
     (ユーザーリストなどありの例)
    # docker run -d --name my-running-haproxy myhaproxy -c -f /usr/local/etc/haproxy/haproxy.cfg -f /usr/local/etc/haproxy/userlist.cfg
 
 -f で指定するファイルパスは、コンテナ内のファイルパス。
   DcokerFile で指定、Build でコピーしてあげたファイル。
 
    これで起動できても、haproxy が監視するサーバーが止まっているかアクセスできていないと、haproxyも止まってしまうようなので、注意。
 
 
 

 
 
run した後、何らかの理由で停止状態としていた際に、もう一度 その設定を保持した状態で動作させたい場合は、以下コマンドも便利。
 
# docker restart コンテナID
 
 

 
 
次回は、HAproxy コンテナ 動作中でもできる 設定ファイルの リロードについて。
 
別途、docker compose でも できたので機会があればそちらも記録しておこうかなと思う。
 

 
動作確認環境 ( 2019年 2月初旬 )
 
Docker version 1.13.1, build 07f3374/1.13.1
docker-compose version 1.23.2, build 1110ad01
CentOS Linux release 7.4.1708 (Core)
HAproxy 1.9
 

 
 
 

HAproxy 設定  ( Basic認証の結果で分岐 )

REST API サーバーのフロントに立たせる HAproxyの設定において、Basic認証の結果をもとに分岐させたい。
その場合の HAproxy 設定について、挙動の結果を経てここに記録。
 
< 動作環境 >
CentOS Linux release 7.5.1804 (Core) 
Linux 3.10.0-862.14.4.el7.x86_64 #1 SMP Wed Sep 26 15:12:11 UTC 2018
HAproxy 1.5x
 
< 前提知識 > HAproxy の設定について
・ユーザーリストの定義ができること
BASIC認証で分岐できること
・簡単な front_end 定義
ACL で 意図した back_end、ホストへ誘導できること
 
#ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
 
その上で、以下 2行の設定方法をマスターする。
 
#ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
 
acl auth_ok     http_auth(定義済みユーザーリスト)
http-request deny   unless   auth_ok
 
#ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
 
 
 

 
< " http-request deny " について >
例えば、BASIC認証で NGだった場合、403 を返したい。
その際に、 http-request により、 宛先を deny とすることで、実現できた。
 
  deny : 認めない     (参照: eow.alc.co.jp)
 
 
< " unless " について >
 
まず普通に辞書を紐解く
 
  unless :  ~でない限り、~である場合を除いて   (参照: eow.alc.co.jp)
 
 
以上を踏まえて 以下を読み解く。
 
#ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
 
" http-request deny   unless   auth_ok "
 
(BASIC認証の結果) auth_ok でなければ deny へ飛ばすぞ😤
 
#ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
 
です。
deny へ飛ばされると 403 エラー となります。
(403エラー関連のHAproxyの設定がデフォルトから更新されていなければ)
 
 
以上より、この2行の設定方法がわかった。
#ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
 
acl auth_ok     http_auth(定義済みユーザーリスト)
http-request deny   unless   auth_ok
 
#ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
 
 
 

 
 
また、似たような書き方として以下もある。
 
#ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
 
acl auth_ok http_auth(user_list)
http-request auth if !auth_ok
 
#ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
 
auth_OK でない場合、つまり認証が通らなかったら、もう一度 認証を行う。
(以後 通らないと 同じく繰り返す)
 
これは、REST API ではなく、ブラウザで見るwebサイトへの対応では、親切な書き方かもしれない。
( パスワード入力画面を出してくれるなど )
 
ただし、REST API クライアントからこの処理を叩くと、 503 エラーを返却してしまう。
 
REST APIBASIC認証を 叩いて認証NGの際、 HAproxy から 403 エラーを出して欲しい場合は、前者の書き方でいくべき。
 
前者は REST API ( CUI )向き、後者は ブラウザからみる webサイト( GUI )向き と思われる。
 
目的に応じて 好きな方 を使おう。
 

 
 
また、OR条件で繋げることもできる。
( ユーザーか 管理者 いずれかのBASIC認証が通ってなければ、 403エラー。)
 
#ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
 
http-request   deny unless  auth_user_ok or auth_mngr_ok
 
#ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
 
 
( 応用例 ) こんな書き方もできた。
 
# 前略
#ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
# ユーザーリスト定義
#ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
 
userlist user_list
  user userman  insecure-password ippandaze
userlist mngr_list
  user mngrman  insecure-password watasigakanrisya
 
#ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
frontend main *:80
 
    acl auth_user_ok     http_auth(user_list)
    acl auth_mngr_ok     http_auth(mngr_list)
    http-request deny    unless    auth_user_ok or auth_mngr_ok
 
    acl ・・・ 分岐させたい acl 処理や default_backend など
 
#ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
 
 
 

docker コンテナ内 時刻が 日本時間 じゃないので

docker コンテナ内 時刻が日本時間じゃない;;;
 
NTP使って同期させる?

-> コンテナ 1つずつ それぞれ 安易に NTP 使わなくてもできるのでは?
 
できたのか(゚O゚)
 

 
 
docker コンテナ内は 通常 デフォルト UTC時刻
 
$ date 
 
$ ls -lasrt /etc/localtime 
ls: cannot access 'ls': No such file or directory
0 lrwxrwxrwx 1 root root 27 Feb  4 00:00 /etc/localtime -> /usr/share/zoneinfo/Etc/UTC
 
$ date
Fri Feb 22 06:02:13 UTC 2019

f:id:asuki_y:20190222153306p:plain

utc
 
これを 東京にしてしまおう!
$ ln -sf  /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
 
root権限がなければコンテナの外に出て、Docker host側 から。
# docker exec -it -u root コンテナID  ln \-sf '/usr/share/zoneinfo/Asia/Tokyo' '/etc/localtime'
 
 
コンテナの中で date コマンドを 打ってみると、、

$ date
Fri Feb 22 15:05:42 JST 2019
 

f:id:asuki_y:20190222153333p:plain

jtc
 
コンテナ内の時刻が JST 表示で わかりやすくなった!
 

 
 
参考:
Docker コンテナの時刻同期(時刻データ)について
 
ln コマンドのオプションについて

 

最近 ssh  ログイン接続が 著しく遅くなった ( D-Bus 関連バグ )

最近 ( 2018年10月初旬現在 )、 メイン開発マシンへの ssh ログイン動作が とても鈍くが 著しく遅くなった。。
( CentOS7 ( 7.5.1804 )  )
 
とりあえず 感覚的には、本体のサービス周りと睨み、一旦システムログの情報を得る。
 
# journalctl -xe
 
早速 それらしいのが いた(゚O゚)
 
 

 
○  D-Bus エラー
 
10月 09 11:49:19 localhost.localdomain dbus[8806]: [system] Failed to activate service 'org.freedesktop.login1': timed out
10月 09 11:49:19 localhost.localdomain dbus[8806]: [system] Activating service name='org.freedesktop.problems' (using servicehelper)
10月 09 11:49:19 localhost.localdomain dbus[8806]: [system] Successfully activated service 'org.freedesktop.problems'
10月 09 11:49:21 localhost.localdomain NetworkManager[3099]: <warn>  [1539053361.5615] bus-manager: could not create org.freedesktop.DBus proxy (org.freedesktop.DBus を StartServiceByName で呼び出そうとしてエラー: 接続が
sending AddMatch() message: 接続が閉じています
 
 

 
 
< 対策 >
 
調べると、OS の バグらしいので、yum update で OSを更新することで直るとのこと。
 
< アップデート前の環境 > - - - - - - - - - - - - - - - 
 
CentOS Linux release 7.5.1804 (Core)
LinuxD-bus や polkitd 、ssh のバージョンは メモるの忘れた。。
firewall-cmd --version  0.4.4.4
 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
 
# yum update
 
# shutdown -r now
 
 
このホストへ 外からssh ログインした時のログ を journalctl で のぞいてみる。
 
 

 
 
10月 09 12:40:16 localhost.localdomain sshd[960]: pam_unix(sshd:session): session opened for user root by (uid=0)
10月 09 12:40:16 localhost.localdomain systemd[1]: Starting Session 2 of user ******.
-- Subject: Unit session-2.scope has begun start-up
-- Defined-By: systemd
-- 
-- Unit session-2.scope has begun starting up.
10月 09 12:40:16 localhost.localdomain dbus[597]: [system] Activating service name='org.freedesktop.problems' (using servicehelper)
10月 09 12:40:16 localhost.localdomain dbus[597]: [system] Successfully activated service 'org.freedesktop.problems'
 
 

 
CentOS7への ssh ログイン の快適さが元に戻った。
 
< アップデート後 > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
CentOS Linux release 7.5.1804 (Core) 
Linux 3.10.0-862.14.4.el7.x86_64 #1 SMP Wed Sep 26 15:12:11 UTC 2018
D-Bus Message Bus Daemon 1.10.24
polkit 0.112-14.el7
OpenSSH_7.4p1, OpenSSL 1.0.2k-fips  26 Jan 2017
firewall-cmd --version  0.4.4.4
 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 

当ブログ記事 アクセス解析 2018年10月 初旬

お仕事中の お時間に 検討・調査 で ご訪問いただいているみたい。
休みの日、グラフが凹む🤔
 
CentOS7 での コマンドや、QNAP 関連、その他、参考になる記事が一つでもあれば幸いです。

 

 firewall-cmd ポート番号 指定 と サービス名 指定。 挙動の違いについてまとめてみたら 少し危ないことが見えてきた。

気になったので、 動作を確認して、まとめておく。
 
○ この世界の中では、ポート番号指定 | サービス指定 、それぞれ少し別な動き。
 
○ filrewall-cmd --reload しなくても、 反映されたもの。reload しないといけないもの。  
「Firewalld Centos7」の画像検索結果
 

 
< 環境 >
CentOS Linux release 7.5.1804 (Core)
firewall-cmd --version  0.4.4.4
 

 
Q、 この世界( firewalld )の中での、ポート番号 指定 サービス指定、って それぞれなんであるの?
 
 サービスによっては、複数のポートを使っているため、サービス名で定義した方が、設定の「やり方」は  簡潔。
( ただし、ポート番号 指定による定義 と サービス名 指定による定義 を混在させてしまった場合は、設定確認が 煩雑になる。詳細は以下 )
 

 
Q、 サービス と ポート 両方 許可しないとダメか? ポートだけではダメか?
  
  -> どうやら、 同じ 80/tcp ないし http にしても、 厳密には、サービス名指定とポート番号指定 で 挙動に違いがあるようだ。
 
ざっくり動きを観た結果、80ポートを閉じても、http サービスが許可されている状態だと webサービスに接続することができた。
また逆に、 httpサービスを閉じて 80ポートを解放しても、 webサービスに接続することができた。
 
つまり OR条件 で 開放 された。
 
サービス名での指定 、ポート番号での指定 により、両方開けた場合は、両方 とも閉じることで、遮断された。
 
「Firewalld Centos7」の画像検索結果
 
 注記 :  " webサービス " とは 内部 tcp/80 でリッスン状態にある nodejs で たてた、 簡素なwebサーバー。アクセスされると、  適当なログを出させて確認した 。
 

 
ポート番号指定 ( --permanent オプションあり ) で firewall 設定時の疑問
 
Q、  " firewall-cmd --reload " コマンドって 意味あるの? reload しなくても反映されてるような。。
 
- - -
 
ポート番号 での 指定  --zone=public --remove-port=80/tcp では、  reload しなくても 反映された。
 
しかし、 サービス名 での指定の場合は、 reload  しないと、反映されていない部分が見受けられた。
( # firewall-cmd --list-all の結果に違いが出る  )
 
ただ  ポート番号の指定であっても、 reload する方が 確実で無難そう。冗長な気はするが、、
 

 
 
Q、サービスと ポート 両方 許可しないとダメか? ポートだけではダメか?
 
- - - 
 
-> ざっくり挙動 を 観た感じ では、片方で良いはず。
 
ただ、個人的には、 ポート番号指定 か サービス名指定  どちらかに統一すべき。
 
ポート番号 で指定した場合、コマンドで 確認しやすい。
# firewall-cmd --list-ports 
443/tcp 22/tcp
 
 
 両方の定義方法を混ぜた場合、煩雑であり、閉じたつもりが、認識違いで 片方空いていたら、目も当てられない。
 
 ただし、使い分けたい場合、もしくは、設定を2重で確実にしたい (?) などの場合は、両方の定義を使う ということになるかと思います。
 
「Firewalld Centos7」の画像検索結果
 
 

 < 余談 >
 
22/tcp 以外で ssh  させたい場合。
例えば 41451/tcp でやりたい場合は、Firewall の設定を以下のようにする。
 
# firewall-cmd --zone=public --remove-service=ssh --permanent
# firewall-cmd --zone=public --remove-port=22 --permanent
firewall-cmd --zone=public --add-port=41451/tcp --permanent
# firewall-cmd --reload
 
上から順に、
- 念のため ssh サービス を 閉じる ( 恒久的に )
- 22番ポート を 閉じる ( 恒久的に )
41451番ポート を開放する ( 恒久的に )
- 設定をリロード
 

 
< まとめ >
 
○ 本件、指定方法の違いにより、挙動が 微妙に違っていたので、その記録 が主旨です。
 
○ 例えば 普通の webサーバー が 80 番で 稼働中の時、firewalld 的に、 80/tcp が空いている状態 or httpサービスが 開放 状態の時、アクセス される。
 
○ サービス 名 指定 と ポート番号 指定、 どちらも 行なっている人は ここを特に気をつける。
意図せず、ポート or サービスが 空いていた、、なんてことがないようにしましょう。
 
○ また、 firewall-cmd は、 まだ version  が 0.4.4.4 ( 2018/10月 初旬現在 ) ということもあり、個人的には この仕様のままかどうかが懐疑的。
 仕様変更がないかどうか、 将来わからないので、大事なシステム導入の際には、今回のように挙動の確認 を 取っておくのがベター なのではないかと個人的には思った🤔