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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章