Ansible - DAY3

一、Ansible Playbook进阶语法

任务块
  • block任务块

    • 可以通过block关键字,将多个任务组合到一起
    • 可以将整个block任务组,一起控制是否要执行

## 样例

# 判断webservers主机组内主机系统发行版为Rocky的主机,安装nginx并启动服务

[root@pubserver ansible]# vim block1.yml

---

- name: block tasks

  hosts: webservers

  tasks:

    - name: group tasks

      block:

        - name: install nginx

          yum:

            name: nginx

            state: present

        - name: start nginx

          service:

            name: nginx

            state: started

            enabled: true

      when: ansible_distribution == "Rocky"     #条件作用与整组任务

[root@pubserver ansible]# ansible-playbook block1.yml 

  • rescue和always

    • 主要用于补充block任务

    • block中的任务都执行成功则rescue中的任务不执行

    • block中的任务出现失败则执行rescue中的任务

    • always中的任务总会执行

## 样例

# 测试block任务执行成功

[root@pubserver ansible]# vim block2.yml

---

- name: test block/rescue/always

  hosts: webservers

  tasks:

    - name: test

      block:

        - name: touch file1

          file:

            path: /tmp/test1.txt

            state: touch

      rescue:

        - name: touch file2

          file:

            path: /tmp/test2.txt

            state: touch

      always:

        - name: touch file3

          file:

            path: /tmp/test3.txt

            state: touch

[root@pubserver ansible]# ansible-playbook block2.yml 

[root@pubserver ansible]# ansible webservers -a "ls /tmp/test*" #未创建/tmp/test2.txt

web1 | CHANGED | rc=0 >>

/tmp/test1.txt

/tmp/test3.txt

web2 | CHANGED | rc=0 >>

/tmp/test1.txt

/tmp/test3.txt

# 测试block任务执行失败

[root@pubserver ansible]# vim block3.yml

---

- name: test block/rescue/always

  hosts: webservers

  tasks:

    - name: test 

      block:

        - name: touch file11

          file:

            path: /tmp/abcd/test11.txt

            state: touch

      rescue:

        - name: touch file22

          file:

            path: /tmp/test22.txt

            state: touch

      always:

        - name: test file33

          file:

            path: /tmp/test33.txt

            state: touch

[root@pubserver ansible]# ansible-playbook block3.yml 

[root@pubserver ansible]# ansible webservers -a "ls /tmp/test*"

web1 | CHANGED | rc=0 >>

/tmp/test1.txt

/tmp/test22.txt

/tmp/test33.txt

/tmp/test3.txt

web2 | CHANGED | rc=0 >>

/tmp/test1.txt

/tmp/test22.txt

/tmp/test33.txt

/tmp/test3.txt

loop循环

  • 用法相当于使用shell中的for循环

  • 特点是loop中的变量名固定为:item

## 变量定义方法

    简单变量:单个元素赋值给item

        loop: [a,b,c,d]

        loop:

          - a

          - b

          - c

    复杂变量:整体赋值给item,可以用item.key获取指定value

        loop: 

          - {"key": "value", "key": "value"}

## 样例

# 简单变量

[root@pubserver ansible]# vim loop1.yml

---

- name: create dirs

  hosts: webservers

  tasks:

    - name: create dir with loop

      file:

        path: /tmp/{{item}}

        state: directory

      loop: [aa,bb,cc]

[root@pubserver ansible]# ansible-playbook loop1.yml 

# 复杂变量

[root@pubserver ansible]# vim loop2.yml

---

- name: create users

  hosts: webservers

  tasks:

    - name: create user with loop

      user:

        name: "{{item.iname}}"

        password: "{{item.ipass|password_hash('sha512')}}"

        state: present

      loop:

        - {"iname":"sunwukong", "ipass":"123456"}

        - {"iname":"zhubajie", "ipass":"654321"}

[root@pubserver ansible]# ansible-playbook loop2.yml 

[root@pubserver ansible]# ansible webservers -a "id sunwukong;id zhubajie"

二、Ansible角色

Roles产生原因

  • 在实际生产环境中,为了实现不同功能,我们会编写大量的Playbook文件
  • 每个Playbook文件可能还会调用其他文件,如变量文件
  • 对于海量的、无规律的文件,管理起来是一件非常困难的事情

什么是Roles

  • ansible自1.2版本引入的新特性,用于层次性、结构化地组织playbook
  • roles能够根据层次型结构自动装载变量文件、tasks以及handlers等
  • 要使用roles只需要在playbook中使用include指令引入即可
  • 简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷的include它们的一种机制
  • 角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中
  • playbook局限在于如果文件较多的情况,不清楚哪些主机执行了哪些状态的yml文件,roles能清楚哪些主机应用哪些角色,主要使用场景代码复用度较高的情况下

roles:                  #角色必须放在roles目录下,可以自定义位置,默认/etc/ansible/roles/

    project:            #角色项目名称

        files:          #用于存放静态文件,如copy或script模块需要调用的文件

        templates:      #用于存放动态文件,即jinja2模板,template模块会自动到此目录下寻找模板文件

        tasks:          #定义任务列表的地方

            main.yml        #任务列表内容编写在此文件中

        handlers:       #定义触发器的地方

            main.yml        #触发器内容编写在此文件中

        vars:           #定义变量的地方(优先级高)

            main.yml        #变量定义在此文件中

        defaults:       #定义变量缺省值的地方(优先级低)

            main.yml

        meta:           #定义作者、版本等描述信息、依赖关系等

            main.yml

        README.md       #整个角色的描述信息

Roles使用

  • 不使用Roles完成文件同步

## 使用Playbook结合template文件完成文件同步

# 编写j2模板

[root@pubserver ansible]# vim motd.j2

Hostname: "{{ansible_hostname }}"

Date: "{{ansible_date_time.date}}"

Contact to: "{{admin}}"

# 编写Playbook

[root@pubserver ansible]# vim motd.yml

---

- name: modify /etc/motd

  hosts: webservers

  vars:

    admin: root@tedu.cn

  tasks:

    - name: modify motd

      template:

        src: motd.j2

        dest: /etc/motd

# 执行剧本测试结果

[root@pubserver ansible]# ansible-playbook motd.yml 

[root@pubserver ansible]# ansible webservers -a "cat /etc/motd"

web2 | CHANGED | rc=0 >>

Hostname: "web2"

Date: "2024-03-28"

Contact to: "root@tedu.cn"

web1 | CHANGED | rc=0 >>

Hostname: "web1"

Date: "2024-03-28"

Contact to: "root@tedu.cn"

[root@pubserver ansible]# 

  • 使用Roles完成文件同步

## 使用角色完成文件分发

# 修改配置文件

[root@pubserver ansible]# mkdir roles

[root@pubserver ansible]# vim ansible.cfg 

[defaults]

inventory = inventory

host_key_checking = false

module_name = shell

roles_path = ./roles

## 创建角色

[root@pubserver ansible]# ansible-galaxy init roles/motd

- Role roles/motd was created successfully

[root@pubserver ansible]# tree roles/motd/

roles/motd/

├── defaults

│   └── main.yml

├── files

├── handlers

│   └── main.yml

├── meta

│   └── main.yml

├── README.md

├── tasks

│   └── main.yml

├── templates

├── tests

│   ├── inventory

│   └── test.yml

└── vars

    └── main.yml

8 directories, 8 files

[root@pubserver ansible]# ansible-galaxy list

# /root/ansible/roles

- motd, (unknown version)

## 配置角色

# 创建模板文件

[root@pubserver ansible]# vim roles/motd/templates/motd.j2

Hostname: "{{ansible_hostname}}"

Date: "{{ansible_date_time.date}}"

Contact to: "{{admin}}"

# 创建变量

[root@pubserver ansible]# vim roles/motd/vars/main.yml 

---

# vars file for roles/motd

admin: "test@tedu.cn"

# 创建任务

[root@pubserver ansible]# vim roles/motd/tasks/main.yml 

---

# tasks file for roles/motd

- name: modify motd

  template:

    src: motd.j2

    dest: /etc/motd

## 使用角色

[root@pubserver ansible]# vim role_motd.yml

---

- name: modify motd with role

  hosts: webservers

  roles:

    - motd

[root@pubserver ansible]# ansible-playbook role_motd.yml 

[root@pubserver ansible]# ansible webservers -a "cat /etc/motd"

web2 | CHANGED | rc=0 >>

Hostname: "web2"

Date: "2024-03-28"

Contact to: "test@tedu.cn"

web1 | CHANGED | rc=0 >>

Hostname: "web1"

Date: "2024-03-28"

Contact to: "test@tedu.cn"

Roles练习

## 创建一个角色用于安装指定软件

# 创建角色

[root@pubserver ansible]# ansible-galaxy init roles/pkgs

- Role roles/pkgs was created successfully

[root@pubserver ansible]# ansible-galaxy list

# /root/ansible/roles

- motd, (unknown version)

- pkgs, (unknown version)

# 配置角色

[root@pubserver ansible]# vim roles/pkgs/tasks/main.yml 

---

# tasks file for roles/pkgs

- name: install pkg

  yum:

    name: "{{pkg}}"

    state: present

[root@pubserver ansible]# vim roles/pkgs/defaults/main.yml  #defaults优先级低于vars

---

# defaults file for roles/pkgs

pkg: nginx

# 测试角色

[root@pubserver ansible]# vim inst_nginx.yml 

---

- name: install nginx with role

  hosts: webservers

  roles:

    - pkgs

[root@pubserver ansible]# ansible-playbook inst_nginx.yml 

# 使用角色

[root@pubserver ansible]# vim inst_mysql.yml

---

- name: installl mysql with role

  hosts: dbs

  vars:

    pkg: mysql-server       #自定义变量优先级高于defaults ,vars

  roles:

    - pkgs

[root@pubserver ansible]# ansible-playbook inst_mysql.yml 

三、Ansible加密解密文件

ansible-vault命令

  • 该命令用于实现数据加密/解密

## 常用选项

    encrypt:加密

    decrypt:解密

    view:查看

    rekey:重置密码

## 样例

# 创建测试文件

[root@pubserver ansible]# echo "Hello World" > hello.txt

[root@pubserver ansible]# cat hello.txt 

Hello World

# 加密文件

[root@pubserver ansible]# ansible-vault encrypt hello.txt 

New Vault password: 1234

Confirm New Vault password: 1234

Encryption successful

[root@pubserver ansible]# cat hello.txt 

$ANSIBLE_VAULT;1.1;AES256

33303462363266366362613937393833383635386234616464663462613234373436323761666238

3835323361616133346632323066313432316666343565390a306563313233353362333735316563

34646361633331386438393963376535386431303230613338626464323637336363346362623039

6262663438613938310a376238636462633638663338663239376137386230306463613533323663

3635

# 解密文件

[root@pubserver ansible]# ansible-vault decrypt hello.txt 

Vault password: 1234

Decryption successful

[root@pubserver ansible]# cat hello.txt 

Hello World

# 重置密码

[root@pubserver ansible]# ansible-vault encrypt hello.txt 

New Vault password: 1234

Confirm New Vault password: 1234

Encryption successful

[root@pubserver ansible]# ansible-vault rekey hello.txt 

Vault password: 1234

New Vault password: abcd

Confirm New Vault password: abcd

Rekey successful

[root@pubserver ansible]# 

# 不解密文件查看内容

[root@pubserver ansible]# cat hello.txt 

$ANSIBLE_VAULT;1.1;AES256

63326162313136393234623264366364363464653536303666656631653433356236366162643834

6430303335333666626632396433653838653236303734390a383038653832636437616563383738

32323135353865613334633731323166376535313033653463353730306266653035663439633435

3637326363393833660a393364343839393766326436393035336265343639356333633736343366

3331

[root@pubserver ansible]# ansible-vault view hello.txt 

Vault password: abcd

Hello World

[root@pubserver ansible]# cat hello.txt 

$ANSIBLE_VAULT;1.1;AES256

63326162313136393234623264366364363464653536303666656631653433356236366162643834

6430303335333666626632396433653838653236303734390a383038653832636437616563383738

32323135353865613334633731323166376535313033653463353730306266653035663439633435

3637326363393833660a393364343839393766326436393035336265343639356333633736343366

3331

# 使用密码文件

[root@pubserver ansible]# echo "tedu.cn" > pass.txt

[root@pubserver ansible]# echo "Hello Linux" > data.txt

[root@pubserver ansible]# ansible-vault encrypt --vault-password-file=pass.txt data.txt 

Encryption successful

[root@pubserver ansible]# cat data.txt 

$ANSIBLE_VAULT;1.1;AES256

64383062326638366339383539663866636665396131316166396230633130313064376532626331

3634393066383031313930363834383266363934356666390a373832303537366664333861373562

66653863353862316232333161333637306535373931393262346231613832363065353863313433

3464393964666330390a393362383034626238653566643065346439643732393738653663363836

3765

[root@pubserver ansible]# ansible-vault view --vault-password-file=pass.txt data.txt 

Hello Linux

[root@pubserver ansible]# ansible-vault decrypt --vault-password-file=pass.txt data.txt 

Decryption successful

[root@pubserver ansible]# cat data.txt 

Hello Linux

  • 使用Playbook管理被控节点,如果剧本中有敏感数据(如密码等)则需要对剧本加密
  • 执行剧本时通过--ask-vault-password选项提示数据密码

## 样例

# 编写测试剧本

[root@pubserver ansible]# vim user_test.yml

---

- name: create user

  hosts: webservers

  tasks:

    - name: create tangsanzang

      user:

        name: tangsanzang

        password: "{{'123'|password_hash('sha512')}}"

        state: present

# 加密剧本

[root@pubserver ansible]# ansible-vault encrypt user_test.yml 

New Vault password: 123456

Confirm New Vault password: 123456

Encryption successful

# 测试剧本执行

[root@pubserver ansible]# ansible-playbook user_test.yml    #报错无法执行

ERROR! Attempting to decrypt but no vault secrets found

# 执行加密剧本

[root@pubserver ansible]# ansible-playbook --ask-vault-password user_test.yml 

Vault password: 123456

...

# 确认结果

[root@pubserver ansible]# ansible webservers -a "id tangsanzang"

web1 | CHANGED | rc=0 >>

uid=1046(tangsanzang) gid=1046(tangsanzang) groups=1046(tangsanzang)

web2 | CHANGED | rc=0 >>

uid=1046(tangsanzang) gid=1046(tangsanzang) groups=1046(tangsanzang)

四、sudo提权

sudo提权概念

  • 什么是sudo提权

    • superuser or another do

    • 以超级管理或其他人的身份执行命令

  • 为什么要提权

    • Linux系统维护过程中如果一直用root用户权限过大

    • 允许root用户远程登录存在风险

  • 提权流程

    • 管理员授权(修改/etc/sudoers文件)

    • 普通用户以sudo的形式执行命令

    • 可以通过sudo -l查看授权情况

  • sudo提权配置方式(修改/etc/sudoers文件)

    • 修改授权方法

      • visudo(带语法检查,默认没有颜色提示)

      • vim /etc/sudoers(不带语法检查,默认有颜色提示)

    • 授权格式

      用户名或组名(%groupname)      在集中认证域中有效,单机忽略      可以执行的命令列表

      用户/组                        ALL=(ALL)                   NOPASSWD: ALL

sudo提权测试

## 样例

# 测试未配置提权

[root@web1 ~]# useradd zhangsan

[root@web1 ~]# echo a | passwd --stdin zhangsan 

[root@web1 ~]# su - zhangsan

[zhangsan@web1 ~]$ useradd wangwu

useradd: Permission denied.

useradd: cannot lock /etc/passwd; try again later.

[zhangsan@web1 ~]$ exit

logout

[root@web1 ~]# 

# 测试提权

[root@web1 ~]# vim /etc/sudoers

100 root    ALL=(ALL)       ALL

101 zhangsan ALL=(ALL)      NOPASSWD: ALL       #新添加

[root@web1 ~]# su - zhangsan

[zhangsan@web1 ~]$ useradd wangwu

useradd: Permission denied.

useradd: cannot lock /etc/passwd; try again later.

[zhangsan@web1 ~]$ sudo -l

... 

User zhangsan may run the following commands on web1:

    (ALL) ALL

[zhangsan@web1 ~]$

[zhangsan@web1 ~]$ sudo useradd wangwu

[zhangsan@web1 ~]$ sudo id wangwu

uid=1047(wangwu) gid=1047(wangwu) groups=1047(wangwu)

[zhangsan@web1 ~]$ exit

五、特殊的主机清单变量

特殊情况处理
  • 如某个被控节点不能免密登录、ssh服务端口不是标准22端口等情况

  • 则需要配置特殊的主机清单变量

## 常用配置

    ansible_ssh_host:指定被控节点服务器IP地址

    ansible_ssh_user:指定登陆远程主机的用户名

    ansible_ssh_pass:指定登陆远程主机的密码

    ansible_ssh_port:指定登陆远程主机的端口号

## 样例

# 调整web1主机配置用于测试

[root@web1 ~]# rm -rf /root/.ssh/authorized_keys            #清理公钥恢复密码登录

[root@web1 ~]# systemctl disable --now firewalld            #关闭防火墙

[root@web1 ~]# vim +17 /etc/ssh/sshd_config                 #配置ssh端口为2222

Port 2222

[root@web1 ~]# systemctl restart sshd                       #重启sshd服务

# 调整pubserver的hosts文件注释web1主机名解析

[root@pubserver ansible]# vim /etc/hosts

...

#192.168.88.11  web1

...

# 创建新工作目录并配置Ansible

[root@pubserver ansible]# cd

[root@pubserver ~]# mkdir myansible

[root@pubserver ~]# cd myansible/

[root@pubserver myansible]# vim ansible.cfg 

[defaults]

inventory = inventory

[root@pubserver myansible]# vim inventory 

[group1]

web1

web2

db1

# 测试Ansible使用

[root@pubserver myansible]# ansible all -m ping #web1主机连接失败

web1 | UNREACHABLE! => {

    "changed": false,

    "msg": "Failed to connect to the host via ssh: ssh: Could not resolve hostname web1: Name or service not known",

    "unreachable": true

}

...

# 配置特殊的主机清单变量

[root@pubserver myansible]# vim inventory 

[group1]

web1 ansible_ssh_host=192.168.88.11 ansible_ssh_port=2222 ansible_ssh_user=root ansible_ssh_pass=a

web2

db1

# 测试特殊的主机清单变量,可以成功

[root@pubserver myansible]# ansible all -m ping

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值