資料夾結構
github位置
.
├── README.md
├── ansible.cfg
├── ansible.log
├── callback_plugins
│ ├── __pycache__
│ │ ├── profile_tasks.cpython-310.pyc
│ │ └── profile_tasks.cpython-39.pyc
│ ├── profile_tasks.py
│ └── profile_tasks.pyc
├── group_vars
│ └── CentOS7.yaml
├── host_vars
│ ├── Centos8.yaml
│ ├── localhost.yaml
│ └── prometheus_server
├── hosts
├── roles
│ ├── docker
│ │ ├── tasks
│ │ │ └── main.yaml
│ │ └── vars
│ │ └── main.yaml
│ ├── nginx
│ │ ├── tasks
│ │ │ └── main.yaml
│ │ └── vars
│ │ └── main.yaml
│ └── ubuntu_base
│ ├── files
│ │ ├── ansible.pub
│ │ └── kaka.pub
│ ├── handlers
│ │ └── main.yml
│ ├── tasks
│ │ └── main.yaml
│ ├── templates
│ │ └── sshd_config.j2
│ └── vars
│ └── main.yaml
├── site.yaml
└── test.yaml
- 因為檔案太多了,讀的順序會是入口點
site.yaml
看是使用哪個role - 到
roles
資料夾底下看對應role,ex ubuntu_base
,他底下也有一堆資料夾 ubuntu_base
資料夾底下看tasks
裡面的main.yaml,基本上該role會做的各指令就會在上面tasks
裡面會用到的變數要看vars
資料夾 or host_vars
or group_vars
等資料夾,變數有很多層級會依據優先序去拿值!files
資料夾會放要複製過去的文件,ex.這邊放的是公鑰,也可以放更新的憑證等templates
資料夾也是放要複製到目標主機的文件,跟file
資料夾差別是templates
裡面放的文件可以透過挖變數把值放入,例如我要設定目標主機的sshd_config,做到吃變數以改ssh port這類操作handlers
資料夾裡面放的是當某條件達成後會執行的指令,常常用在設定檔有改動,才會重啟服務的操作.
roles
結束後,會確認目標主機,這邊是放在hosts
文件內(有很多放法,可以參考官方建議best pratices).
執行指令
ansible-playbook -i /path/to/your/inventory site.yml --limit 'yourInstancesGroup'
之後示範是先用這個指令,指定主機跟劇本!
ansible-playbook -i ./hosts site.yaml --limit 'Ubuntu22'
詳細各檔案內容
會以ubuntu為例,之後會寫判斷主機系統!
site.yml
第一個 play 針對 Ubuntu22 主機群組執行。gather_facts: True 表示在運行 play 之前搜集主機的事實。roles 中指定了 ubuntu_base 角色,其他意思差不多,預設情況下,Ansible 會在對應的roles資料夾的 tasks 資料夾中尋找並執行 main.yml 檔案。
site.yml
---
- hosts: Ubuntu22
gather_facts: True
roles:
- ubuntu_base
- hosts: Docker
gather_facts: False
roles:
- docker
- hosts: Nginx
gather_facts: True
roles:
- nginx
roles/ubuntu_base
這邊會用ubuntu_base資料夾做目標,底下tasks做的事情是對系統的基礎操作.ansible_distribution 是 Ansible 的系統事實 (system fact) 之一,它是 Ansible 在目標主機上執行時自動收集的系統相關資訊之一。
roles/ubuntu_base/tasks/main.yaml
- name: diskable SELinux
selinux:
state: disabled
when: ansible_distribution == 'CentOS'
- name: Check if Service Exists
shell: "systemctl -a|grep {{ need_to_stopped_service}}|wc -l"
register: service_exists
- name: Stop service firewalld, if started
ansible.builtin.service:
name: "{{ need_to_stopped_service }}"
state: stopped
enabled: false
when: service_exists|int > 0
- name: Set a hostname
ansible.builtin.hostname:
name: "{{ hostname }}"
become: true
- name: install Base package
apt:
name: "{{ item }}"
state: latest
loop: "{{ base_packages }}"
become: true
- name: Set timezone to Asia/Manila
community.general.timezone:
name: "{{ time_zone }}"
become: true
- name: Set sysctl file limits
become: true
pam_limits:
dest: "{{ item.dest }}"
domain: '*'
limit_type: "{{ item.limit_type }}"
limit_item: "{{ item.limit_item }}"
value: "{{ item.value }}"
with_items:
- { dest: '/etc/security/limits.conf',limit_type: 'soft',limit_item: 'nofile', value: '655350' }
- { dest: '/etc/security/limits.conf',limit_type: 'hard',limit_item: 'nofile', value: '655350'}
- { dest: '/etc/security/limits.conf',limit_type: 'soft',limit_item: 'nproc', value: '102400' }
- { dest: '/etc/security/limits.conf',limit_type: 'hard',limit_item: 'nproc', value: '102400' }
- { dest: '/etc/security/limits.conf',limit_type: 'soft',limit_item: 'sigpending', value: '255377' }
- { dest: '/etc/security/limits.conf',limit_type: 'hard',limit_item: 'sigpending', value: '255377' }
- { dest: '/etc/security/limits.d/90-nproc.conf', limit_type: 'soft',limit_item: 'nproc', value: '262144' }
- { dest: '/etc/security/limits.d/90-nproc.conf', limit_type: 'hard',limit_item: 'nproc', value: '262144' }
tags:
- setlimits
- name: Ensure group "ops" exists
become: true
ansible.builtin.group:
name: ops
state: present
- name: Add the user 'ops' with a bash shell, appending the group ops
become: true
ansible.builtin.user:
name: ops
shell: /bin/bash
groups: ops
append: yes
- name: Config /etc/sudoers
become: true
lineinfile: dest=/etc/sudoers state=present line='{{item}}' validate='visudo -cf %s'
with_items:
- "ops ALL=(ALL) NOPASSWD: ALL"
- "Defaults: ops !requiretty"
- name: Set up multiple authorized keys
become: true
authorized_key:
user: ops
state: present
key: '{{ item }}'
with_file: "{{ ssh_pub_key }}"
- name: Update sshd configuration safely, avoid locking yourself out
become: true
ansible.builtin.template:
src: sshd_config.j2
dest: /etc/ssh/sshd_config
owner: root
group: root
mode: '0600'
validate: /usr/sbin/sshd -t -f %s
backup: yes
notify:
- (Handler) Restart SSHD Service
tags:
- ssd_config
開頭的條件判斷,ansible_distribution 是用於條件判斷的一部分,以確定 SELinux 禁用任務僅在 CentOS 發行版上執行,在ubuntu不需要操作!
中間的檔案限制, /etc/security/limits.conf 中的 nofile 限制是限制每個進程允許打開的檔案數量./etc/security/limits.conf 中的 nproc 限制是設定單個使用者可啟動的最大進程數量./etc/security/limits.conf 中的 sigpending 限制是設定單個使用者可以等待處理的信號(作業系統和程式互相溝通的機制)數量上限./etc/security/limits.d/90-nproc.conf 中的 nproc 限制也是限制是設定單個使用者可啟動的最大進程數量.會以90-nproc.conf優先,簡言之就是限制以下這幾件事.
- 開啟檔案數量
- 可以開啟的進程數
- 可等待處理的信號數
文尾是告訴他怎麼複製sshd檔案到對面主機,而當一個任務包含了 notify 指令,那麼只有當這個任務的結果是「改變」(change)的時候,對應的 handler 才會被觸發。並且,無論有多少個任務觸發了同一個 handler,在整個 playbook 的運行過程中,那個 handler 都只會被運行一次,並且是在所有的任務都運行完成後。這種模式非常適合於管理那些只需要在配置改變時才需要運行的任務,比如服務的重啟。
roles/ubuntu_base/vars/main.yaml
base_packages:
- vim
- git
- tree
- lrzsz
- lsof
- net-tools
- wget
time_zone: Asia/Manila
ssh_config:
port: 22
disalbe_root_login: False
disalbe_password_login: False
ssh_pub_key:
- files/test.pub
need_to_stopped_service: firewalld
定義挖空的變數,基本上變數順序很多,常用的優先序如下
tasks/var
host_vars
group_vars
他有很多順序,詳細看官網這邊
roles/ubuntu_base/templates/sshd_config.j2
Port {{ ssh_config.port }}
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
SyslogFacility AUTHPRIV
{% if ssh_config.disalbe_root_login %}
PermitRootLogin no
{% else %}
PermitRootLogin yes
{% endif %}
AuthorizedKeysFile .ssh/authorized_keys
{% if ssh_config.disalbe_password_login %}
PasswordAuthentication no
{% else %}
PasswordAuthentication yes
{% endif %}
ChallengeResponseAuthentication no
GSSAPIAuthentication yes
GSSAPICleanupCredentials no
UsePAM yes
X11Forwarding yes
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS
Subsystem sftp /usr/lib/openssh/sftp-server
這邊就是sshd的config,會把變數填入補空!如果相同則不會change!
roles/ubuntu_base/handlers/main.yaml
- name: (Handler) Restart SSHD Service
become: true
service:
name: sshd
state: restarted
enabled: yes
handels底下的yaml會對應tasks裡面某個有設定notify的task,當狀態為change會觸發handler操作,主要用途是用於修改設定檔後的服務重啟,如果設定沒改變就當然不用重啟了.
hosts
hosts
[Ubuntu22]
prometheus_server ansible_host=10.0.0.112
[Ubuntu22:vars]
ansible_user=ubuntu
[CentOS7]
localhost
Centos8
[Docker]
localhost
Centos8
[Nginx]
localhost
Centos8
因為我這邊主要示範對ubnutu部署,所以來看[Ubuntu22]
,這邊定義主機寫法prometheus_server ansible_host=10.0.0.112
是因為方邊辨認,直接用ip看不出來是server用途.要注意的是,如果想要對host直接定義變數值,就需要在host_vars底下做一個對應的prometheus_server文件,這個很重要![Ubuntu22:vars]ansible_user=ubuntu
這個是定義ansible連進去的使用者,因為預設會連到root,但有些ssh config是限制root不能連入!
vars
host_vars/prometheus_server
---
test1: value1
ansible_ssh_port: 22
hostname: backend1
這就是前面說的,很重要!要針對特定主機設定變數,你的檔名一定要跟你定義在hosts的相同!ex.host_vars/prometheus_server
就會對應到hosts
文件內的那行prometheus_server ansible_host=10.0.0.112
,如果沒有對到就會沒變數!
group_vars也是要對應到[group]
這樣,跟hosts_vars很像!
檢查指令
你設定完之後,除了直接對主機執行等他跑完看結果,還有其他方式做檢查嗎?
以下指令可以檢查各台主機有吃到的變數
ansible-inventory -i hosts --list
檢查預計改變狀況,同時如果文件有異動,顯示異動情況,帶--check跟--diff
ansible-playbook -i ./hosts site.yaml --limit 'Ubuntu22' --diff --check