Posted at

serfクラスタネットワークにアプリケーションサーバが増減したらLB(Nginx)の割り振り先を増やしたり、減らしたりするserf用イベントハンドラ書いた

More than 3 years have passed since last update.

GWに一人さみしくDockerとSerfと戯れてみた(๑´ڡ`๑) の続きです。


/usr/local/src/python/handler.py

#!/usr/bin/env python

# -*- coding: utf-8 -*-
from serf_master import SerfHandler, SerfHandlerProxy
from jinja2 import Environment, FileSystemLoader
import logging
import sys
import bsddb
import json
import subprocess
import os

class AppHandler(SerfHandler):
def member_join(self):
# nginx.confのテンプレート取得
env = Environment(loader=FileSystemLoader('/usr/local/src/python/', encoding='utf8'))
tpl = env.get_template('nginx.tpl.conf')

# ip管理用配列
ips = []
db=bsddb.hashopen('hashtest.db','c')

try:
dbips = json.loads(db["ips"])
for ip in dbips:
ips.append(ip)
except:
print "no cache"

  # 追加されたagent情報は標準入力で来るので(改行コード区切り)
for line in iter(sys.stdin.readline, ""):
print line
agent = line.split("\t")
node = agent[0] #node
ip = agent[1] #node
role = agent[2] #node
    
       # この時app roleに追加された場合、追加
if role == "app":
ips.append(ip)

db["ips"] = json.dumps(ips)
db.sync()

     # テンプレートから書き出すデータを生成
html = tpl.render({'backends':ips})

# nginxに読み込ませるconfファイルを作成
f = open("/etc/nginx/conf.d/proxy.conf", "w")
f.write(html)
f.close()

# Nginxを再起動
cmd = 'supervisorctl restart nginx'
ret = subprocess.check_output( cmd.split(" ") )
print ret

if __name__ == '__main__':
handler = SerfHandlerProxy()

# 存在するappとdefaultのみ許可される(Roleごとのハンドラを登録)
handler.register('default', AppHandler())
handler.run()


実際に書いたhandler.py

そして、この時のnginx.tpl.confはこちら


nginx.tpl.conf

upstream backend {

{% for backend in backends %}
server {{ backend }}:9000;
{% endfor %}
}
server {
listen 80;

location / {
proxy_set_header Host $host;
proxy_pass http://backend/cgi-bin/index.py;
proxy_redirect default;
break;
}

proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Real-IP $remote_addr;
}


html = tpl.render({'backends':ips}) で、upsteam の箇所が色々書き換わるイメージ

これで、app roleに追加があった場合、nginxはかってにupstreamを書き換えて再起動までやっちゃいます。

冒頭で増減と書きましたが、体力の関係で削除は飛ばしました。


終わり

全ソースコードは

https://github.com/shinofara/serf/tree/dbb46c60a24dede36b5546f6ff611131d9b4636a

Dockerとかも全部コミコミ版説明は

http://shinofara.hateblo.jp/entry/2016/05/05/124019

においてます。