03 实战 Ansible-Playbook之初始化服务器
时间:2022-07-25
本文章向大家介绍03 实战 Ansible-Playbook之初始化服务器,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
批量初始化服务器
初始化步骤
- 配置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
- 程序员炒股,如何计算股票投资组合的风险和收益
- Docker 容器化部署运维 OpenStack 和 Ceph
- 关于设计模式的思考
- Spring 框架之 AOP 原理剖析
- Java 平台反应式编程(Reactive Programming)入门
- 从原理到实例,他用区块链技术做一了个COIN 客户端
- 解锁Spring Data Redis的正确使用姿势
- 互联网厂工必知必会:SQL基础篇
- 算法入门,其实可以像读小说一样有趣
- 互联网中小型企业的持续集成CICD
- Hybris平台Web架构模式演变:前后端分离
- 资源控制在大数据和云计算平台中的应用
- SharifCTF 2018 Crypto writeup
- 如何使用ABSL代码调用Web service
- 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 数组属性和方法
- BERT文本摘要
- 【NPM库】- 0x01
- 基于分类任务的信号(EEG)处理--代码分步解析
- 文件操作——举例
- flink之udf执行流程分析篇
- VBA调用外部对象02:FileSystemObject——操作文本文件
- 打卡群刷题总结0723——组合
- VBA根据单元格底色统计个数
- 打卡群刷题总结0724——子集
- 打卡群刷题总结0726——删除排序数组中的重复项 II
- VBA调用外部对象02:FileSystemObject——OpenTextFile参数
- 使用HTTP 404-File Not Found的C2
- MySQL主从复制详解
- Excel VBA事件——ActiveX控件
- Excel VBA事件