【原创】ansible-自动注册

摘要

由于ansible与agent之间的通信使用的是openssh,每次新增机器之后需要在ansible的inventory文件中添加新增机器的相关配置。虽然配置起来很简单,但是一旦短时间新增大量机器、或者是长时间的维护过程中难免会有遗漏或配置重复的情况出现,因此类似salt的agent自动向server注册的功能就显得十分重要。

目前为至还未发现世面上有这种类似saltstack的agent自动向server端自动注册的机制,其实实现起来很简单,也不需要修改现有的ansible,只需要用到几个服务,以及手写几个脚本就可以按照你自己定义好的规则实现自动注册。

需要用到的服务

  • ansible
  • etcd
  • confd
  • python or shell

原理

  • 采用etcd作为节点发现数据库
  • 提前定义好etcd数据库的目录数据结构
  • 制作模板机,配置自动运行脚本
  • 通过confd的监控功能监控etcd相关数据,实时生成ansible的inventory文件

本文安装配置过程极为简单

etcd数据结构的定义还很简陋,这部分以及脚本的编写自由度非常高,你可以随意按照你的情况进行修改

实际上本文只是体现一个思路,或者也可以说只是etcd+confd配置管理的一个应用而已。

本文记录的整个过程中一些细节部分没有体现,请你自己注意;本文仅供参考

安装配置

ansible

1
pip install ansible

配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# /etc/ansible/ansible.cfg
[defaults]
inventory = /etc/ansible/hosts
remote_tmp = $HOME/.ansible/tmp
roles_path = /data/ansible/roles:/etc/ansible/roles
transport = smart
gathering = smart
fact_caching_timeout = 30
require_sudo = False
module_name = shell
private_key_file = /root/.ssh/id_rsa
ansible_managed = Ansible managed: {file} modified on %Y-%m-%d %H:%M:%S by {uid} on {host}
nocolor = 0
fact_caching = memory
host_key_checking = False
timeout = 10
pattern = *
forks = 20
poll_interval = 15
remote_user = devops
remote_port = 9555
log_path = /data/logs/ansible/ansible.log

[inventory]

[privilege_escalation]
become=True
become_exe=sudo
become_method=sudo
become_user=root
become_ask_pass=False

[paramiko_connection]
record_host_keys=False

[ssh_connection]
pipelining = True

[accelerate]
accelerate_port = 5099
accelerate_timeout = 30
accelerate_connect_timeout = 5.0
accelerate_daemon_timeout = 30

etcd安装配置

安装

1
2
3
4
5
6
7
8
9
10
11
LOCAL_DIR="/usr/local/src"

ETCD_VER="v3.3.6"
DOWNLOAD_URL="https://github.com/coreos/etcd/releases/download"

cd ${LOCAL_DIR} && curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o ${LOCAL_DIR}/etcd-${ETCD_VER}-linux-amd64.tar.gz

mkdir -p ${LOCAL_DIR}/etcd && tar xzvf ${LOCAL_DIR}/etcd-${ETCD_VER}-linux-amd64.tar.gz -C ${LOCAL_DIR}/etcd --strip-components=1

cd ${LOCAL_DIR}/etcd/ && cp etcd etcdctl /usr/local/bin
etcd -version

systemd配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
mkdir /etc/etcd/

tee /etc/etcd/etcd.conf <<-'EOF'
# [member]
ETCD_NAME="infra1"
ETCD_IP="172.16.1.1"
ETCD_DATA_DIR="/data/infra.etcd/"
#ETCD_WAL_DIR=""
#ETCD_SNAPSHOT_COUNT="10000"
#ETCD_HEARTBEAT_INTERVAL="100"
#ETCD_ELECTION_TIMEOUT="1000"
ETCD_LISTEN_PEER_URLS="http://172.16.1.1:2380"
ETCD_LISTEN_CLIENT_URLS="http://172.16.1.1:2379,http://127.0.0.1:2379"
#ETCD_MAX_SNAPSHOTS="5"
#ETCD_MAX_WALS="5"
#ETCD_CORS=""

# [cluster]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://172.16.1.1:2380"
ETCD_INITIAL_CLUSTER="infra1=http://172.16.1.1:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster-test"
ETCD_ADVERTISE_CLIENT_URLS="http://172.16.1.1:2379"
EOF

修改 /usr/lib/systemd/system/etcd.service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
tee  /usr/lib/systemd/system/etcd.service <<-'EOF'
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
NotifyAccess=all
WorkingDirectory=/
EnvironmentFile=-/etc/etcd/etcd.conf
User=root

# set GOMAXPROCS to number of processors
ExecStart=/bin/bash -c "GOMAXPROCS=$(nproc) /usr/local/bin/etcd --name=\"${ETCD_NAME}\" --data-dir=\"${ETCD_DATA_DIR}\" --listen-client-urls=\"${ETCD_LISTEN_CLIENT_URLS}\" --listen-peer-urls=\"${ETCD_LISTEN_PEER_URLS}\" --advertise-client-urls=\"${ETCD_ADVERTISE_CLIENT_URLS}\" --initial-advertise-peer-urls=\"${ETCD_INITIAL_ADVERTISE_PEER_URLS}\" --initial-cluster=\"${ETCD_INITIAL_CLUSTER}\" --initial-cluster-state=\"${ETCD_INITIAL_CLUSTER_STATE}\" --initial-cluster-token=\"${ETCD_INITIAL_CLUSTER_TOKEN}\""
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

启动服务

1
2
systemctl enable etcd.service
systemctl start etcd.service

配置

etcd采用默认的api2接口

1
export ETCDCTL_API=2

创建etcd目录数据结构

1
2
3
4
5
6
7
etcdctl mkdir /ansible/default
etcdctl mkdir /ansible/default/test
etcdctl mkdir /ansible/default/dev
etcdctl mkdir /ansible/default/gamma
etcdctl mkdir /ansible/default/prod
etcdctl mkdir /ansible/default/zookeeper
etcdctl mkdir /ansible/custom
  • /ansible/default/* 用于默认的数据存储
  • /ansible/custom 预留作为其他一些自定义的配置

confd安装配置

安装

1
2
3
4
5
CONFD_VER="0.16.0"
curl -L https://github.com/kelseyhightower/confd/releases/download/v${CONFD_VER}/confd-${CONFD_VER}-linux-amd64 -o /usr/local/bin/confd

chmod +x /usr/local/bin/confd
confd --version

配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
mkdir -p /etc/confd/{conf.d,templates}

tee /etc/confd/confd.toml <<-'EOF'
backend = "etcd"
confdir = "/etc/confd"
log-level = "debug"
interval = 1
nodes = [
"http://0.0.0.0:2379",
]
prefix = "/"
scheme = "https"
EOF


tee /usr/lib/systemd/system/confd.service <<-'EOF'
[Unit]
Description=Confd Server
After=etcd.service

[Service]
User=root
ExecStart=/usr/local/bin/confd
Restart=always
LimitNOFILE=65536

[Install]
WantedBy=basic.target
EOF
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
cat conf.d/ansible.toml
[template]
src = "ansible.cfg.tmpl"
dest = "/etc/ansible/h"
keys = [
"/ansible/default",
]

# 这里生成的配置/etc/ansible/h 暂时先不生成正式的inventory配置

cat templates/ansible.cfg.tmpl
{{ range $dir := lsdir "/ansible/default" -}}
[{{ base $dir -}}]
{{ $custdir := printf "/ansible/default/%s/*" $dir -}}
{{ range gets $custdir -}}
{{ $data := json .Value -}}
{{ $data.name }} ansible_ssh_host={{ $data.ip }} ansible_ssh_port={{ $data.port}}
{{ end }}
{{ end }}

#
#{{ base .Key }} ansible_ssh_host={{ $data.ip }}

启动

1
2
systemctl enable confd
systemctl start confd

注册脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 脚本目前写的比较简单,后续还会进行修改
# 我的所有机器主机名是采用的标准定义格式
# ecs.ali-bj-vpc.manager.172.16.1.1.ansible
cat set.sh
#!/bin/bash

env=$(hostname | awk -F'.' '{print $3}')
ip=$(hostname | awk -F'.' '{print $4"."$5"."$6"."$7}')
key=$(hostname | awk -F'.' '{print $NF}')
port=$(netstat -ntlp | grep sshd | awk '{print $4}' | sed 's/.*://')
url="http://172.16.1.1:2379/v2/keys/ansible/default"
env="zookeeper"
echo curl -X PUT "${url}/${env}/${ip}" -d value="{\"ip\":\"${ip}\",\"name\":\"${env}-${key}\",\"port\":\"${port}\"}"
curl -X PUT "${url}/${env}/${ip}" -d value="{\"ip\":\"${ip}\",\"name\":\"${env}-${key}\",\"port\":\"${port}\"}"

未来展望

  • 目前整个结构比较简单,生成的inventory文件结构还很原始
  • 实际使用中后续的配置过程还是有些麻烦
  • 后续会更新的一些功能(如果有时间和兴趣的话)
    • 数据中端口的配置 已添加
    • 一些自定义custom的数据结构
    • 命令行管理工具
    • web管理功能