使用Ansible playbooks快速构建etcd集群
本篇文章记录一下使用
ansible-playbooks
进行快速构建一个可用的etcd集群。在阅读并实践本文章之前,请确保您有一个可用的ansible
环境。
一、集群规划
注意:本文档基于centos7+的操作系统上进行构建,在rhel7+系列也可用使用,其他发行版本可酌情参考
etcd_name |
节点 |
端口 |
---|---|---|
etcd1 |
10.0.0.77 |
2379/2380 |
etcd2 |
10.0.0.78 |
2379/2380 |
etcd3 |
10.0.0.79 |
2379/2380 |
以上节点详情信息用来规划集群规模以及名称角色,配置文件中ETCD_INITIAL_CLUSTER
选项中的etcd_name
和地址需要和主机规划中一致
二、etcd集群部署
环境前提:已经配置过ansible相关的环境,并且可以免密登录
1.etcd集群相关的配置文件
$ tree .
.
├──etcd-install.yml #ansible-playbook 脚本
├──etcd.conf.j2 #etcd主配置文件
├──etcd.service #systemd服务启动文件
├──host #etcd集群主机列表
# ansible-playbooks 脚本
$ cat etcd-install.yml
---
- hosts: "{{ host }}"
remote_user: root
vars:
hostip: "{{ ansible_all_ipv4_addresses[0] }}"
ipv6: "{{ ansible_all_ipv6_addresses[0].split(':')[-1] }}"
packagedir: /tmp/
serverdir: /export/servers/
download: https://github.com/coreos/etcd/releases/
etcd_version: etcd-v3.1.5-linux-amd64
tasks:
- name: "test ping"
ping:
- name: "init env"
shell: "mkdir -p /export/servers /etc/etcd/ /export/Data/etcd/ "
- name: "wget {{ etcd_version }}"
get_url:
url: "{{ item.url }}"
dest: "{{ item.dest }}"
mode: 0644
owner: root
group: root
with_items:
- { url: "{{ download }}{{ etcd_version }}.tar.gz" , dest: "{{ packagedir }}" }
- name: "untar the {{ etcd_version }}"
unarchive:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
owner: root
group: root
remote_src: yes
with_items:
- { src: "{{ packagedir }}{{ etcd_version }}.tar.gz", dest: "{{ serverdir }}" }
- name: "copy the etcd execfile"
shell: "cp -rp {{ serverdir }}{{ etcd_version }}/etcd* /usr/bin/"
- name: "init the es configuration!"
template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: 0755
owner: root
group: root
with_items:
#dest后面的引号与大括号中间一定不能有空格,还有后面引号的空格也要取消掉,不然文件会有空格
- { src: "etcd.conf.j2", dest: "/etc/etcd/etcd.conf" }
- { src: "etcd.service", dest: "/etc/systemd/system/" }
# etcd主配置文件模板,这里采用jinja2模板引擎
$ cat etcd.conf.j2
# [member]
BASE_DIR="/export"
# 由于etcd_name变量比较特殊,需要和ETCD_INITIAL_CLUSTER中的值一一对应,暂时写为etcd1,配置下发后需要将该值替换成对应节点的名称
ETCD_NAME="etcd1"
ETCD_DATA_DIR="/export/Data/etcd"
ETCD_LISTEN_PEER_URLS="http://{{ hostip }}:2380"
ETCD_LISTEN_CLIENT_URLS="http://{{ hostip }}:2379"
#[cluster]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://{{ hostip }}:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_ADVERTISE_CLIENT_URLS="http://{{ hostip }}:2379"
#[initial-cluster]
# 需要按照etcd集群规划节点来填写
ETCD_INITIAL_CLUSTER="etcd1=http://10.0.0.77:2380,etcd2=http://10.0.0.78:2380,etcd3=http://10.0.0.79:2380"
# systemd 启动脚本
$ cat etcd.service
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos
[Service]
Type=notify
# 数据目录,需要提前进行创建
WorkingDirectory=/export/Data/etcd/
EnvironmentFile=-/etc/etcd/etcd.conf
ExecStart=/usr/bin/etcd
--name ${ETCD_NAME}
--initial-advertise-peer-urls ${ETCD_INITIAL_ADVERTISE_PEER_URLS}
--listen-peer-urls ${ETCD_LISTEN_PEER_URLS}
--listen-client-urls ${ETCD_LISTEN_CLIENT_URLS},http://127.0.0.1:2379
--advertise-client-urls ${ETCD_ADVERTISE_CLIENT_URLS}
--initial-cluster-token ${ETCD_INITIAL_CLUSTER_TOKEN}
--initial-cluster ${ETCD_INITIAL_CLUSTER}
--initial-cluster-state new
--data-dir=${ETCD_DATA_DIR}
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
$ cat hosts
[etcd]
10.0.0.77
10.0.0.78
10.0.0.79
2.使用ansible-playbooks进行部署etcd集群
$ ansible-playbook -i host -e host=etcd etcd-install.yml
等待正确执行完成之后,三个节点的etcd就已经安装好了,由于是集群,所以各个节点上的配置还是有专属的部分,暂时没有想到如何进行一次性安装启动,将安装、修改配置、启动作为三部分操作.
3.登录每个节点进行修改etcd_name
修改每个节点上的/etc/etcd/etcd.conf
文件: 注意:需要将各个节点ip和etcd_name对应起来(etcd1->77 etcd2->78 etcd->79)
77节点上的配置如下(其他两个节点修改对应的etcd_name):
ETCD_NAME="etcd1"
ETCD_INITIAL_CLUSTER="etcd1=http://10.0.0.77:2380,etcd2=http://10.0.0.78:2380,etcd3=http://10.0.0.79:2380"
4.检测配置文件并进行启动集群
$ ansible -i host all -m shell -a 'systemctl daemon-reload && systemctl start etcd && systemctl enable etcd'
注意:由于etcd采用集群模式,在启动第一个实例的时候会一直监听其他实例,这个时候需要尽快启动其他实例,以完成集群发现,否则第一个实例会在一定时间内挂掉
5.集群状态监测
$ etcdctl cluster-health
member 4d946fabd2e1eb9f is healthy: got healthy result from http://10.0.0.79:2379
member 805150a1f1a44604 is healthy: got healthy result from http://10.0.0.77:2379
member 81ddc2f4095fe8a1 is healthy: got healthy result from http://10.0.0.78:2379
cluster is healthy
$ etcdctl member list
4d946fabd2e1eb9f: name=etcd3 peerURLs=http://10.0.0.79:2380 clientURLs=http://10.0.0.79:2379 isLeader=true
805150a1f1a44604: name=etcd1 peerURLs=http://10.0.0.77:2380 clientURLs=http://10.0.0.77:2379 isLeader=false
81ddc2f4095fe8a1: name=etcd2 peerURLs=http://10.0.0.78:2380 clientURLs=http://10.0.0.78:2379 isLeader=false
如此,可以发现我们的etcd集群已经迅速运行起来了!
三、etcd集群的基本使用
注意1:
由于是集群模式,所以可用在任何一个节点进行写入操作,用户也可用使用etcd的http接口进行使用 注意2:
etcd v2和v3的API是完全不同的两个存储实现,所以用户在使用的时候需要注意在etcd v2版本中是采用set存数据的,v3版本中采用put方式
指定API版本
$ export ETCDCTL_API=3
$ etcdctl put foo "Hello World!"
$ etcdctl get foo
以json格式输出
$ etcdctl --write-out="json" get foo
1.通过前缀获取数据
$ etcdctl --endpoints=$ENDPOINTS put web1 value1
$ etcdctl --endpoints=$ENDPOINTS put web2 value2
$ etcdctl --endpoints=$ENDPOINTS put web3 value3
$ etcdctl --endpoints=$ENDPOINTS get web --prefix
web1
value1
web2
value2
web3
value3
2.删除数据
$ etcdctl --endpoints=$ENDPOINTS put key myvalue
$ etcdctl --endpoints=$ENDPOINTS del key
$ etcdctl --endpoints=$ENDPOINTS put k1 value1
$ etcdctl --endpoints=$ENDPOINTS put k2 value2
$ etcdctl --endpoints=$ENDPOINTS del k --prefix
3.集群状态信息
v3 的API才有这个功能
$ etcdctl --write-out=table --endpoints=${HOST_1}:2379,${HOST_2}:2379,${HOST_3}:2379 endpoint status
+-------------------+------------------+---------+---------+-----------+-----------+------------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
+-------------------+------------------+---------+---------+-----------+-----------+------------+
| 10.0.0.77:2379 | 805150a1f1a44604 | 3.1.5 | 1.2 MB | false | 639 | 188421 |
| 10.0.0.78:2379 | 81ddc2f4095fe8a1 | 3.1.5 | 1.2 MB | false | 639 | 188421 |
| 10.0.0.79:2379 | 4d946fabd2e1eb9f | 3.1.5 | 1.2 MB | true | 639 | 188421 |
+-------------------+------------------+---------+---------+-----------+-----------+------------+
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 人心易变,这段有趣的C代码也一样!!!
- matplotlib绘制常见统计图形(一)
- python与安全(二)格式化字符串和Flask session
- ROS2机器人笔记20-07-24
- Postgresql 渗透利用总结
- Spring 基于注解(annotation)的配置之@Required注解
- 由一个系统激活工具引起的一次简单测试
- Golang channel 快速入门
- 潘石屹用Python解决100个问题 | 素数
- Spring 自动装配模式之构造函数装配方式
- 安全狗 {safedog} 最新版注入bypass
- C语言定时关机小程序
- 深入k8s:Pod对象中重要概念及用法
- Golang语言排序的几种方式
- 性能分析(1)- Java 进程导致 CPU 使用率升高,问题怎么定位?