10-29 26,053 views
今天聊聊nginx配置的自动化管理。主要聊聊etcd和confd,之前一直使用puppet 管理nginx的配置文件,现在很多朋友也将etcd+confd作为配置文件自动管理的一种方法。
什么是confd?
confd 是一个轻量级的配置管理工具,可以将配置信息存储在etcd、consul、dynamodb、redis以及zookeeper等。confd定期会从这些存储节点pull最新的配置,然后reload服务,完成配置文件的update。
什么是etcd?
etcd 大家应该都听过吧,最近比较火的一项技术。它是一个用语共享配置和服务的高可用key-value存储系统,由CoreOS使用开发并作为CoreOS的基础服务启动。它的具体特点在这里就不在过多阐述,如果想更加深入学习etcd.可以查看它的官方文档.
系统架构设计图:
I. 首先通过etcd ClientApi 将一些可变的配置信息push 到etcd.
II. confd 设置模版,通过etcd获取指定配置信息,生成最新配置文件.
III. reload nginx服务,完成nginx自动更新配置.
往etcd push数据:
etcd的具体安装这里就不在多说了,详细了解etcd可以查看官方文档。
etcd服务启动以后,现在需要将数据灌进etcd Server服务器,然后才可以让confd 从etcd获取数据。我用python简单封装了一个etcd灌数据的工具:
#!/usr/bin/env python from __future__ import unicode_literals from optparse import OptionParser import etcd import sys class NginxEtcd(object): """Configuration with etcd storage nginx. Provide push, pull function.""" def __init__(self, host='', port=4001, *args, **kwargs): self.host = host self.port = port @property def _conn_etcd(self): """connection etcd Server.""" client = etcd.Client(host=self.host, port=self.port) return client def set_config(self, key='', value='', *args, **kwargs): """set configuration.""" client = self._conn_etcd try: if self.get_config(key) and isinstance(self.get_config(key), str): client.update(key, value) return_message = {'code': 200, 'message': 'set success.'} elif self.get_config(key) and isinstance(self.get_config(key), dict): return_message = self.get_config(key) else: client.write(key, value) return_message = {'code': 200, 'message': 'set success.'} except Exception as e: return_message = {'code': 500, 'message': e} finally: return return_message def get_config(self, key): """get configuration.""" try: client = self._conn_etcd return_message = client.get(key).value except Exception as e: return_message = {'code': 500, 'message': e} finally: return return_message def ops(): parser = OptionParser(usage="usage: %prog -host HOST -port PORT -key KEY -value VALUE") parser.add_option('-H', "--host", default='127.0.0.1', action='store', type='string', dest="host", help="etcd server ipaddress.") parser.add_option('-p', "--port", default=4001, action='store', type='int', dest="port", help="etcd listen port.") parser.add_option('-k', "--key", default='', action='store', type='string', dest="key", help="etcd key name.") parser.add_option('-v', "--value", default='', action='store', type='string', dest="value", help='etcd key value.') parser.add_option('-t', "--type", default='', action='store', type='string', dest='type', help="Operating etcd Type.") return parser.parse_args() def main(): options, args = ops() if options.host and options.port: client = NginxEtcd(host=options.host, port=options.port) if options.type == 'set' and client: data = client.set_config(key=options.key, value=options.value) if options.type == 'get' and client: data = client.get_config(options.key) return data if __name__ == "__main__": print(main())
现在可以通过该脚本,将你要更改的配置信息更新到etcd。该脚本的具体使用方法,可以查看帮助文档。
confd 配置管理:
confd的安装在这里就不在多说,so easy!。如果详细了解confd,可以参考confd的官方手册.
confd安装完成以后,需要创建一个配置文件和一个模版文件。
mkdir -p /etc/confd/{conf.d,templates}
confd配置文件:
现在我们需要配置confd的配置文件:
vim /etc/confd/conf.d/nginx.toml #nginx.toml具体内容 [template] src = "nginx.tmpl" dest = "/etc/nginx/conf.d/app1.conf" keys = [ "/www/app1" ] owner = "root" mode = "0644" check_cmd = "/usr/sbin/ngixn -t" relaod_cmd = "/usr/sbin/service nginx reload"
confd 模版文件:
创建我们在/etc/confd/conf.d/nginx.toml提到的模版文件,将其放在/etc/confd/templates目录下.
upstream app1_pool { {{ range getvs "/www/app1/*" }} server {{ . }}; {{ end }} } server { listen 80 default_server; listen [::]:80 default_server ipv6only=on; access_log /var/log/nginx/access.log upstreamlog; location / { proxy_pass http://app1_pool; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
创建confd启动脚本:
现在需要创建一个cond启动脚本,这个脚本主要有两个功能:
I. 在nginx 后端Server启动之前启动
II. 监听etcd的变化情况,然后重启nginx,以确保nginx配置的后端Server都是ok.
#!/bin/bash set -eo pipefail export ETCD_PORT=${ETCD_PORT:-4001} export HOST_IP=${HOST_IP:-x.x.x.x} export ETCD=$HOST_IP:$ETCD_PORT echo "[nginx] booting container. ETCD: $ETCD." util confd -onetime -node $ETCD -config-file /etc/confd/conf.d/nginx.toml; do echo "[nginx] waiting for confd to create initial nginx configuration." sleep 5 done confd -interval 10 -node $ETCD -config-file /etc/confd/conf.d/nginx.toml & echo "[nginx] confd is now monitoring etcd for changes." echo "[nginx] staring nginx service ..." service nginx restart
接下来, 从etcd中读取数据,并使用confd实例化nginx的配置文件。我们使用一个until循环来不停的执行这个操作。最后执行完该脚本会自动生成一个nginx的配置文件。
etcd+confd具体的性能现在还没有进行测试。
干货
push工具是我不会用还是有bug呢?[root@node4 ~]# ./pushData.py -host 127.0.0.1 -port 4001 -key ‘123’ -value ‘123’Usage: pushData.py -host HOST -port PORT -key KEY -value VALUEOptions: -h, –help show this help message and exit -H HOST, –host=HOST etcd server ipaddress. -p PORT, –port=PORT etcd listen port. -k KEY, –key=KEY etcd key name. -v VALUE, –value=VALUE
./pushData.py -H 127.0.0.1 -p 4001 -k ‘123’ -v ‘123’