批量初始化服务器
初始化步骤
- 配置ssh密钥认证
- 远程配置主机名
- 控制远程主机互相添加HOSTS解析
- 配置远程主机的yum源以及一些软件
- 时间同步配置
- 关闭selinux/iptables
- 修改sshd配置
配置ssh密钥认证
- 在主控节点的
/etc/ansible/hosts
配置节点
$ vim /etc/ansible/hosts
[new]
192.168.56.12
192.168.56.13
在控制节点配置到受控节点的ssh认证方式
# 主控节点执行
$ ssh-keygen -t rsa -f ~/.ssh/id_rsa -N ''
$ for host in 192.168.56.{11..12};do
ssh-keyscan $host >> ~/.ssh/hnow_hosts 2> /dev/null
sshpass -p '123456' ssh-copy-id root@$host &> /dev/null
done
将上面的方案playbook化:
---
- name: config ssh connection
hosts: new
gather_facts: false
tasks:
- name: configure ssh connection
shell: |
ssh-keyscan {{inventory_hostname}} >> ~/.ssh/know_hosts
sshpass -p '123456' ssh-copy-id root@{{inventory_hostname}}
ansible命令执行模块
以下的四个模块不满足幂等性
- command:执行简单的shell命令
- shell: 和command相同,但支持管道富豪
- raw: 执行底层shell命令,通常在目标主机上安装python时才使用这个模块
- script: 在远程主机上执行脚本
以下命令具备幂等性:
- creates: 当指定的文件或者目录不存在时执行,存在不执行
- removes:当指定的文件或者目录不存在时不执行,存在执行
---
- name: modules use
hosts: new
gather_facts: false
tasks:
- name: use shell module
shell: cp /tmp/my.cnf /etc/my.cnf
args:
creates: /etc/my.cnf
- name: exec perl scripts
script: /opt/script.pl
args:
executable: perl
重点
- connection: 连接方式(smart|ssh|paramiko|local|docker|winrm),默认为smart表示只能选择ssh或者paramiko
- delegate_to: 只能定义在task级别上,效果和connection相似
---
- name: play1
hosts: zabbix
gather_facts: false
tasks:
- name: task 1
debug:
msg: "{{ inventory_hostname }} is executing task"
delegate_to: localhost
authorized_key模块
特点:
- 分发ssh公钥
- 不负责主机认证阶段 前提需要配置好hosts下的ansible_passwd字段
[new]
192.168.56.11 ansible_hostname="centos7-node1"
192.168.56.12 ansible_hostname="centos7-node2"
[new:vars]
ansible_password="yeecallk8s"
分发认证配置
---
- name: "configure ssh connection"
hosts: new
gather_facts: false
tasks:
- authorized_key:
key: "{{lookup('file','~/.ssh/id_rsa.pub')}}"
state: present
user: root
外部数据读取的方式:
- lookup() :支持从file,redis,etcd,pipe,vars,list,dict
- fileglob: 支持统配文件名,file指定文件,pipe从命令执行结果中返回数据
---
- name: "fileglob and file task"
hosts: new
gather_facts: false
tasks:
- name: task1
debug:
msg: "filenames: {{ lookup('fileglob','/etc/*.conf')}}"
- name: task2
debug:
msg: "filecontents: {{ lookup('file','/etc/hosts')}}
- query() : 统配文件读取,返回list格式
---
- name: "fileglob and files query"
hosts: new
gather_facts: false
tasks:
- name: "fileglob"
debug:
msg: "fileglob {{lookup('fileglob','/etc/*.conf')}}"
- name: "fileglob wantlist"
debug:
msg: "fileglob wantlist {{lookup('fileglob','/etc/*.conf',wantlist=True)}}"
- name: "query"
debug:
msg: "query {{q('fileglob','/etc/*.conf')}}"
设置主机名
使用的是hostname模块,会直接修改/etc/hostname 配置文件
---
- name: set hostname
hosts: new
gather_facts: false
vars:
hostnames:
- host: 192.168.56.13
name: centos7-node3
- host: 192.168.56.14
name: centos7-node4
tasks:
- name: set hostname
hostname:
name: "{{ item.name }}"
when: item.host == inventory_hostname
loop: "{{ hostnames }}"
vars变量设置注意:
- 设置在play级别,该play范围内的task都能访问这些变量,其他的play则无法访问
- 设置在task级别,只有该task范围内才能访问这个变量
---
- name: vars task1
hosts: new
gather_facts: false
vars:
- var1: "value1"
tasks:
- name: access value1
debug:
msg: "var1 in task1 {{var1}}"
- name: vars task2
hosts: new
gather_facts: false
tasks:
- name: can not access vars from task1
debug:
msg: var1
- name: set and access var2 in this task
debug:
msg: var2
vars:
var2: "value2"
- name: cant access var2
debug:
msg: var2
when条件判断
- 当when判断为true的时候执行任务,反之不执行
---
- name: when judge
hosts: new
gather_facts: false
vars:
- myname: "alex"
tasks:
- name: task skip
debug:
msg: "my name is {{myname}}"
when: myname == "hello" #这个判断条件是false的
- name: task will execute
debug:
msg: "my name is {{myname}}"
when: myname == "alex"
loop循环: 解决重复问题
- 未使用循环的例子
---
- name: make dirs for localhost
hosts: localhost
gather_facts: false
tasks:
- name: create test1
file:
path: /tmp/test1
state: directory
- name: create test2
file:
path: /tmp/test2
state: directory
- 使用循环的例子
---
- name: mkdir loop
hosts: localhost
gather_facts: false
tasks:
- name: create test1,2 directory
file:
path: "{{item}}"
state: directory
loop:
- /tmp/test01
- /tmp/test02
互相添加hosts(DNS)主机名解析
互相添加指定hosts组的host之间的hosts解析
---
- name: add hosts DNS
hosts: new
gather_facts: false
tasks:
- name: add DNS
lineinfile:
path: /etc/hosts
line: "{{item}} {{hostvars[item].ansible_hostname}}"
when: item != inventory_hostname
loop: "{{ play_hosts }}"
- lineinfile模块: 在源文件中插入,删除,替换行,跟sed类似
# 创建测试文件a.txt
paragraph 1
first line in paragraph 1
second line in paragraph 1
paragraph 2
first line in paragraph 2
second line in paragraph 2
## lineinfile追加实例
---
- name: add line to a.txt
hosts: localhost
gather_facts: false
tasks:
- lineinfile:
path: "a.txt"
line: "append new line"
state: absent # 删除上面的line定义的行(append new line)
### 插入操作,定义在摸个行前或者行后新增(insertbefore,insertafter)
---
- name: lininfile demo for before and after insert
hosts: localhost
gather_facts: false
tasks:
- name: line infile
lineinfile:
path: "a.txt"
line: "LINE1"
insertbefore: '^para.* 2'
firstmatch: yes
lineinfile:
path: "a.txt"
line: "LINE2"
insertafter: '^para.* 2'
firstmatch: yes
- play_hosts和hostvars变量
- inventory_hostname: 表示在主机inventory中定义的名称
- play_hosts和hostvars: 是预定义变量,执行任务时可以直接拿出来使用,play_hosts相当于是new这个主机组里面的所有主机列表;
- hostvars: 保存了所有目标主机的变量
- name: add DNS
lineinfile:
path: /etc/hosts
line: "{{item}} {{hostvars[item].ansible_hostname}}"
when: item != inventory_hostname
loop: "{{ play_hosts }}"
配置yum源并下载安装软件
更换yum源,安装软件
---
- name: "init yum"
hosts: new
gather_facts: false
tasks:
- name: "backup old yum_repo"
shell:
cmd: "mkdir bak; mv *.repo bak"
chdir: /etc/yum.repos.d
creates: /etc/yum.repos.d/bak
- name: "add new os repo and release repo"
yum_repository:
name: "{{item.name}}"
description: "{{item.name}} repo"
baseurl: "{{item.baseurl}}"
file: "{{item.name}}"
enabled: 1
gpgcheck: 0
reposdir: /etc/yum.repos.d
loop:
- name: os
baseurl: "https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/os/$basearch"
- name: epel
baseurl: "https://mirrors.tuna.tsinghua.edu.cn/epel/$releasever/$basearch"
- name: install pkgs
yum:
name: vim,net-tools,git-core,lrzsz,wget,curl,sysstat,iotop,gcc,gcc-c++,cmake,pcre,pcre-devel,zlib,zlib-devel,openssl,openssl-devel,vim,wget,telnet,setuptool,lrzsz,dos2unix,
net-tools,bind-utils,tree,screen,iftop,ntpdate,tree,lsof,iftop,iotop,sysstat,procps
state: present
时间同步
使用ntpdate 同步时间
---
- name: sync time
hosts: new
gather_facts: false
tasks:
- name: install and sync time
block:
- name: install ntpdate
yum:
name: ntpdate
state: present
- name: ntpupdate to sync time
shell: |
ntpdate ntp1.aliyun.com
hwclock -w
- block是组织了两个有关联性的任务
关闭selinux
命令行关闭和修改配置文件两种手段
---
---
- name: disable selinux
hosts: new
gather_facts: false
tasks:
- block:
- name: disable selinux by command
shell: setenforce 0
- name: disable selinux by config
lineinfile:
path: /etc/selinux/config
line: "SELINUX=disabled"
regexp: '^SELINUX='
ignore_errors: true
配置防火墙
---
- name: set firewalld
hosts: new
gather_facts: false
tasks:
- name: set iptables rule
shell: |
iptables-save > /tmp/iptables.bak$(date +"%F-%T")
iptables -X
iptables -F
iptables -Z
systemctl disable firewalld
systemctl stop firewalld
配置sshd服务
- 需求:
- 禁止root用户登陆
- 不允许使用密码登陆
---
- name: "set sshd service"
hosts: new
gather_facts: false
tasks:
- name: backup old sshd config
shell: |
/usr/bin/cp -f {{path}} {{path}}.bak
vars:
- path: /etc/ssh/sshd_config
- name: disable root login
lineinfile:
path: "/etc/ssh/sshd_config"
line: "PermitRootLogin no"
regexpr: '^PermitRootLogin'
notify: "restart sshd"
- name: disable passwd auth
lineinfile:
path: "/etc/ssh/sshd_config"
line: "PasswordAuthentication no"
regexp: '^PasswordAuthentication yes'
notify: "restart sshd"
handlers:
- name: "restart sshd"
service:
name: sshd
state: restarted
参考
推荐专栏:https://blog.51cto.com/cloumn/detail/83from_distribution=VQcJVApVVQwxUwIHVQYFDA 代码gitee:https://gitee.com/wanghui1234/ansible_repo.git