ดูแลเซิร์ฟเวอร์หลายเครื่องพร้อมกันด้วย Ansible

เริ่มใช้ Ansible จากศูนย์ ตั้ง inventory เขียน Playbook แรก และสั่งงานหลายเครื่องพร้อมกันโดยไม่ต้องติดตั้งอะไรบนเครื่องปลายทาง

โดย ทีมงาน THAI DATA CLOUD อัปเดต อ่าน 11 นาที เข้าชม 7 ครั้ง

แชร์FacebookXLINELinkedIn
Ansible — ดูแลเซิร์ฟเวอร์หลายเครื่องพร้อมกันด้วย Ansible
ดูแลเซิร์ฟเวอร์หลายเครื่องพร้อมกันด้วย Ansible

คำตอบสั้น ๆ: เริ่มใช้ Ansible จากศูนย์ ตั้ง inventory เขียน Playbook แรก และสั่งงานหลายเครื่องพร้อมกันโดยไม่ต้องติดตั้งอะไรบนเครื่องปลายทาง

คู่มือนี้อธิบาย Ansible ทีละขั้นตอน พร้อมคำสั่งที่ใช้ได้จริงและปัญหาที่พบบ่อย

เมื่อมีเซิร์ฟเวอร์เกินสามเครื่อง การ SSH เข้าไปแก้ทีละเครื่องเริ่มเป็นปัญหา ไม่ใช่เพราะช้าอย่างเดียว แต่เพราะเครื่องจะค่อย ๆ ต่างกันโดยไม่มีใครรู้ เครื่องหนึ่งมีการตั้งค่าที่อีกเครื่องไม่มี และเมื่อเกิดปัญหาจึงไล่ไม่ถูกว่าต่างกันตรงไหน

Ansible แก้เรื่องนี้ด้วยการเขียนสิ่งที่ต้องการให้เป็นไฟล์ แล้วสั่งให้ทุกเครื่องเป็นไปตามนั้น จุดเด่นคือไม่ต้องติดตั้งอะไรบนเครื่องปลายทางเลย ใช้ SSH ที่มีอยู่แล้ว

สิ่งที่ต้องเตรียม

  • เครื่องควบคุมหนึ่งเครื่อง จะเป็นเครื่อง Mac หรือ Linux ของคุณเองก็ได้
  • SSH Key ที่เข้าเซิร์ฟเวอร์ปลายทางได้โดยไม่ต้องใส่รหัสผ่าน
  • Python บนเครื่องปลายทาง ซึ่งมีมาให้แล้วในทุกดิสทริบิวชัน
# macOS
brew install ansible

# Ubuntu / Debian
sudo apt install -y ansible

ansible --version

ขั้นตอนที่ 1: สร้างโครงงาน

mkdir -p ~/infra/{playbooks,group_vars,files}
cd ~/infra
nano inventory.ini
[web]
web1 ansible_host=10.0.0.11
web2 ansible_host=10.0.0.12

[db]
db1 ansible_host=10.0.0.21

[production:children]
web
db

[all:vars]
ansible_user=deploy
ansible_ssh_common_args='-o [email protected]'
ansible_python_interpreter=/usr/bin/python3

บรรทัด ansible_ssh_common_args ทำให้ Ansible วิ่งผ่าน Bastion Host ได้เหมือนที่คุณ SSH ด้วยมือ

สร้างไฟล์ตั้งค่า

nano ansible.cfg
[defaults]
inventory = inventory.ini
host_key_checking = True
retry_files_enabled = False
stdout_callback = yaml
interpreter_python = auto_silent

[ssh_connection]
pipelining = True

pipelining = True ทำให้เร็วขึ้นอย่างเห็นได้ชัดเพราะลดจำนวนรอบการเชื่อมต่อ SSH

ขั้นตอนที่ 2: ทดสอบการเชื่อมต่อ

ansible all -m ping
ansible web -m ping
ansible all -a "uptime"
ansible all -a "df -h /" 

คำสั่งเหล่านี้เรียกว่า ad-hoc command เหมาะกับการดูข้อมูลเร็ว ๆ โดยไม่ต้องเขียน Playbook

ดูข้อมูลของเครื่องที่ Ansible เก็บได้

ansible web1 -m setup | head -50
ansible all -m setup -a 'filter=ansible_distribution*'

ขั้นตอนที่ 3: เขียน Playbook แรก

nano playbooks/base.yml
---
- name: ตั้งค่าพื้นฐานของเซิร์ฟเวอร์ทุกเครื่อง
  hosts: all
  become: true

  vars:
    common_packages:
      - htop
      - curl
      - git
      - unattended-upgrades

  tasks:
    - name: ตั้ง Timezone เป็นเวลาไทย
      community.general.timezone:
        name: Asia/Bangkok

    - name: อัปเดตรายการแพ็กเกจ
      ansible.builtin.apt:
        update_cache: true
        cache_valid_time: 3600
      when: ansible_os_family == "Debian"

    - name: ติดตั้งแพ็กเกจพื้นฐาน
      ansible.builtin.package:
        name: "{{ common_packages }}"
        state: present

    - name: ตั้งค่า sshd ให้ปลอดภัย
      ansible.builtin.copy:
        dest: /etc/ssh/sshd_config.d/99-hardening.conf
        mode: '0644'
        content: |
          PermitRootLogin no
          PasswordAuthentication no
          MaxAuthTries 3
      notify: reload sshd

    - name: เปิดใช้งาน fail2ban
      ansible.builtin.service:
        name: fail2ban
        state: started
        enabled: true

  handlers:
    - name: reload sshd
      ansible.builtin.service:
        name: ssh
        state: reloaded

ส่วน handlers คือแนวคิดสำคัญ มันจะทำงานเฉพาะเมื่องานที่ notify มีการเปลี่ยนแปลงจริงเท่านั้น ทำให้ไม่ต้องรีโหลดบริการทุกครั้งที่รัน

ขั้นตอนที่ 4: ตรวจก่อนรันจริงเสมอ

# ตรวจไวยากรณ์
ansible-playbook playbooks/base.yml --syntax-check

# ดูว่าจะทำอะไรบ้างโดยไม่แตะเครื่องจริง
ansible-playbook playbooks/base.yml --check --diff

# จำกัดให้ทำเครื่องเดียวก่อน
ansible-playbook playbooks/base.yml --limit web1

ลำดับนี้คือนิสัยที่ควรทำทุกครั้ง โดยเฉพาะ --check --diff ซึ่งแสดงความต่างของไฟล์ที่จะถูกแก้ ทำให้เห็นผลกระทบก่อนเกิดขึ้นจริง

ขั้นตอนที่ 5: รันจริง

ansible-playbook playbooks/base.yml

อ่านผลสรุปท้ายสุด ตัวเลข changed คือจำนวนงานที่แก้อะไรจริง หากรันซ้ำครั้งที่สองแล้วได้ changed=0 ทั้งหมด แปลว่า Playbook ของคุณเขียนถูกหลัก คือสั่งเดิมกี่ครั้งผลก็เหมือนเดิม

สำหรับการเปลี่ยนแปลงที่กระทบผู้ใช้ ให้ทยอยทำทีละส่วน

ansible-playbook playbooks/base.yml --serial 1
ansible-playbook playbooks/deploy.yml --limit 'web*' --serial '30%'

ขั้นตอนที่ 6: เก็บความลับด้วย Ansible Vault

อย่าเก็บรหัสผ่านเป็นข้อความธรรมดาในไฟล์ที่เข้า Git

ansible-vault create group_vars/production/secrets.yml
db_root_password: "รหัสผ่านจริง"
api_token: "token"
ansible-vault edit group_vars/production/secrets.yml
ansible-vault view group_vars/production/secrets.yml
ansible-playbook playbooks/base.yml --ask-vault-pass

ขั้นตอนที่ 7: ใช้ Role เมื่อ Playbook เริ่มยาว

ansible-galaxy init roles/nginx
tree roles/nginx -L 1

โครงสร้าง Role แยกงาน ไฟล์ ตัวแปร และเทมเพลตออกจากกัน ทำให้นำไปใช้ซ้ำกับโครงงานอื่นได้ เรียกใช้ใน Playbook ด้วย

---
- hosts: web
  become: true
  roles:
    - nginx
    - php-fpm

ปัญหาที่พบบ่อย

ping ไม่ผ่าน ขึ้น Permission denied

ตรวจว่า SSH ด้วยมือเข้าได้ก่อน ssh [email protected] ถ้าเข้าได้แต่ Ansible ไม่ได้ ให้ตรวจ ansible_user ใน inventory และลองเพิ่ม -vvv เพื่อดูรายละเอียดการเชื่อมต่อ

ขึ้น sudo: a password is required

ผู้ใช้ยังต้องใส่รหัสผ่านตอน sudo ให้เพิ่ม --ask-become-pass หรือตั้ง NOPASSWD ให้ผู้ใช้นั้นบนเครื่องปลายทาง

รันครั้งที่สองยังขึ้น changed ทุกงาน

แปลว่ามีงานที่ไม่ได้เขียนให้ตรวจสถานะก่อนทำ มักเกิดกับ command และ shell ให้ใช้โมดูลเฉพาะทางแทน หรือเพิ่ม creates และ changed_when เพื่อบอกเงื่อนไขว่าเมื่อไรถือว่ามีการเปลี่ยนแปลง

ช้ามากเมื่อมีหลายเครื่อง

เปิด pipelining = True เพิ่มจำนวนงานขนานด้วย -f 20 และหลีกเลี่ยงการใช้ with_items กับโมดูลติดตั้งแพ็กเกจ ให้ส่งเป็นรายการเดียวแทนเพื่อให้ติดตั้งรอบเดียว

ต้องการวางมาตรฐานการดูแลเซิร์ฟเวอร์ทั้งระบบ ติดต่อ THAI DATA CLOUD ได้ที่ https://thaidata.cloud/contact/

ทำความเข้าใจ Ansible ก่อนเริ่ม

เครื่องมือจัดการเครื่องจำนวนมากแบบนี้ให้ค่าจริงเมื่อคุณเลิกมองมันเป็นตัวรันคำสั่งทีละหลายเครื่อง แล้วมองเป็นเอกสารที่บอกว่าเซิร์ฟเวอร์ควรมีหน้าตาอย่างไร ไฟล์ playbook ที่เก็บใน Git คือคำตอบของคำถามที่ตอบไม่ได้เสมอเวลามีคนลาออก ว่าเครื่องนี้ติดตั้งอะไรไว้บ้างและทำไม คุณสมบัติที่ทำให้ใช้ได้จริงคือการทำงานซ้ำได้โดยผลลัพธ์ไม่เปลี่ยน รันสิบรอบกับรันรอบเดียวได้สถานะปลายทางเหมือนกัน จึงกล้ารันซ้ำเมื่อไม่แน่ใจ

สิ่งที่ต้องเตรียมก่อนใช้งาน Ansible

  • เครื่องควบคุมหนึ่งเครื่องที่ติดต่อเซิร์ฟเวอร์ปลายทางทาง SSH ได้ทุกเครื่อง
  • กุญแจ SSH ที่แจกไว้ครบแล้ว และบัญชีที่ยกสิทธิ์เป็น root ได้
  • ที่เก็บโค้ดสำหรับไฟล์ playbook เพราะคุณค่าหลักอยู่ที่ประวัติการเปลี่ยนแปลง ไม่ใช่ตัวคำสั่ง

ตรวจสอบว่า Ansible ทำงานถูกต้องแล้ว

  1. สั่งทดสอบการเชื่อมต่อแล้วทุกเครื่องในรายการตอบกลับ ไม่มีเครื่องใดค้าง
  2. รันแบบทดลองก่อนจริงหนึ่งรอบ แล้วอ่านรายการสิ่งที่จะถูกเปลี่ยนว่าตรงกับที่ตั้งใจ
  3. รันซ้ำอีกรอบหลังรันจริง ผลสรุปต้องไม่มีรายการที่เปลี่ยนแปลง ซึ่งพิสูจน์ว่างานนี้ทำซ้ำได้อย่างปลอดภัย

ข้อควรรู้และข้อจำกัดของ Ansible

  • เริ่มจากเครื่องทดสอบเสมอ และแบ่งกลุ่มเครื่องให้ชัดเจน การรันทับเครื่องที่ให้บริการอยู่ทั้งหมดพร้อมกันคือความเสี่ยงที่ไม่จำเป็น
  • ใช้การทยอยทำทีละชุดเมื่อแก้ไขเครื่องที่รับงานผู้ใช้จริง เพื่อให้ยังมีเครื่องรับงานอยู่ตลอด
  • อย่าเก็บรหัสผ่านหรือคีย์ไว้ในไฟล์ธรรมดาที่คอมมิตขึ้น Git ให้ใช้กลไกเก็บความลับที่เข้ารหัสไว้

คำถามที่พบบ่อยเกี่ยวกับ Ansible

ต้องติดตั้งอะไรบนเซิร์ฟเวอร์ปลายทางก่อนหรือไม่

ปลายทางต้องการเพียง SSH และตัวแปลภาษา Python ที่ระบบปฏิบัติการมีมาให้อยู่แล้ว จึงไม่ต้องติดตั้งตัวแทนค้างไว้บนเครื่อง

รันแล้วบางเครื่องล้มเหลว ควรทำอย่างไร

อ่านชื่อเครื่องและงานที่ล้มเหลวจากผลสรุป แก้เฉพาะเครื่องนั้น แล้วรันซ้ำทั้งชุดได้เลย เพราะเครื่องที่ผ่านไปแล้วจะไม่ถูกเปลี่ยนซ้ำ

เหมาะกับองค์กรที่มีเซิร์ฟเวอร์ไม่กี่เครื่องไหม

คุ้มตั้งแต่สามถึงห้าเครื่องขึ้นไป และคุ้มทันทีถ้าต้องสร้างเครื่องใหม่ให้เหมือนเดิมบ่อย ๆ เพราะเวลาที่ประหยัดได้มาจากการไม่ต้องจำว่าเคยตั้งค่าอะไรไว้

อ่านเพิ่มเติมเกี่ยวกับ Ansible

แชร์FacebookXLINELinkedIn

มีคำถามเรื่องบริการ? ติดต่อทีมงาน