AWSでALB→EC2(複数)という構成のお話をします。
AWSのL7ロードバランサー、ALBでEC2やらにヘルスチェックする際、HTTPまたはHTTPSプロトコルのGETのリクエストメソッドを使いますね。例えば対象のEC2のポート80に対して30秒に1回ヘルスチェックして200 OKが返ってきたらOK〜という感じで。
Webサーバのヘルスチェックならそれで十分なのですが、RESTfulなインタフェースを持っているシステムなら、RESTful APIを叩いてヘルスチェックしたいって思うケースがあると思うのです。私はそんな場面に出くわしました。で、これをALBでやってみようとするとなかなか難しい。 何が難しいって、
- リクエストヘッダを記載できないのでAPI Keyといった認証情報を乗せることができない
- HTTPメソッドがGETのみで、PUTやPATCHができるかは確認できない
- 当然更新用のdataといった情報は載せることができない
わけです。
私の場合はPowerDNSで更新のAPIをヘルスチェックで確認させたいな、と思っていて、何か良い方法ないかなぁと社内で相談したところ「EC2で動作するかんたんなWEBサーバを書いてヘルスチェックが来たらAPIでPOSTやPATCHするようにしたらどうか?」とアドバイスをいただき、なるほどそりゃ名案だ、ということでPythonで実装してみました。
↓こんな感じです。(healthcheck.py)
#!/usr/bin/env python3 from http.server import HTTPServer, BaseHTTPRequestHandler import json import urllib.request import urllib.parse import configparser config_ini = configparser.ConfigParser() config_ini.read('/etc/default/PdnsAPIHealth.ini', encoding='utf-8') class APIHandler(BaseHTTPRequestHandler): def do_GET(self): base_url = 'http://127.0.0.1:8081' path = 'api/v1/servers/localhost/zones/example.com' headers = { "X-API-Key": "" } headers["X-API-Key"] = config_ini['DEFAULT']['api_key'] data = { 'rrsets': [{ 'name': 'example.com.', 'type': 'MX', 'ttl': 3600, 'changetype': 'REPLACE', 'records': [{ 'content': '10 mail.example.com.', }], }], } url = urllib.parse.urljoin(base_url, path) req = urllib.request.Request(url, json.dumps(data).encode(), headers, method='PATCH') try: with urllib.request.urlopen(req) as res: if res.code == 204: statuscode = 200 else: statuscode = res.code except urllib.error.HTTPError as err: statuscode = err.code except urllib.error.URLError as err: statuscode = 500 self.send_response(statuscode) self.send_header('Content-type', 'text/plain; charset=utf-8') self.end_headers() self.wfile.write(str(statuscode).encode()) if __name__ == '__main__': server_address = ('0.0.0.0', int(config_ini['DEFAULT']['listen_port'])) with HTTPServer(server_address, APIHandler) as server: server.serve_forever()
これは何をやっているのかと言うと、ポート8080にHTTPのアクセスがきたらRESTfulなAPIを自分自身のポート8081に投入してレスポンスコードが正常なら200 OKを、そうでないなら500やらエラーのレスポンスコードを返します。
あとは以下のようなサービス起動設定を/usr/lib/systemd/system/
に配置して(CentOSです)、
[Unit] Description=PowerDNS API HealthCheck Daemon [Service] ExecStart=/bin/healthcheck.py Restart=always Type=simple PIDFile=/var/run/healthcheck.pid [Install] WantedBy=multi-user.target
サービスを起動させる。
$ sudo systemctl daemon-reload $ sudo systemctl start healthcheck
あと、ALBではターゲットグループに対して「ポート8081をターゲットにするけどヘルスチェックはポート8080を使うよ」という設定をしてあげます。 これでALBのヘルスチェックで「RESTfulなAPIで更新処理が動作するか」を監視できるようになりました! こういうことやりたい人、けっこういるんじゃないかなぁ、と思ったけれどもあまり参考になる情報がないなぁ、と思ったので書いたのでした。