#การติดตั้ง Ansible บน CentOS 7.9 แบบทีละขั้นตอน

Ansible เป็นเครื่องมือสำหรับทำงานอัตโนมัติด้าน Infrastructure เช่น การติดตั้งแพ็กเกจ การแก้ไขไฟล์ Configuration การจัดการ Service และการ Deploy ระบบไปยังเซิร์ฟเวอร์หลายเครื่อง โดย Ansible ทำงานแบบ Agentless กล่าวคือไม่ต้องติดตั้ง Ansible Agent บนเครื่องปลายทาง แต่เชื่อมต่อผ่าน SSH และเรียกใช้ Python ที่เครื่องปลายทาง

บทความนี้อธิบายการติดตั้ง Ansible บน CentOS 7.9 ตั้งแต่การแก้ปัญหา Repository หลังระบบหมดอายุ การตั้งค่า SSH และ Inventory ไปจนถึงการรัน Playbook แรก

[!WARNING] CentOS Linux 7 สิ้นสุดการสนับสนุนเมื่อวันที่ 30 มิถุนายน 2024 และไม่ได้รับ Security Update อีกต่อไป แพ็กเกจที่อยู่ใน CentOS Vault เป็นเพียง Snapshot ของแพ็กเกจเก่าและจะไม่มีการอัปเดตด้านความปลอดภัย คู่มือนี้จึงเหมาะสำหรับห้องปฏิบัติการ การเรียนการสอน หรือการดูแลระบบเดิมชั่วคราว สำหรับระบบ Production ใหม่ควรใช้ระบบที่ยังได้รับการสนับสนุน เช่น Rocky Linux 9, AlmaLinux 9 หรือ RHEL 9

#ภาพรวมการทำงาน

ระบบตัวอย่างประกอบด้วยเครื่อง 2 ประเภท

เครื่อง หน้าที่ สิ่งที่ต้องติดตั้ง
Control Node เครื่องที่ใช้สั่งงาน Ansible Ansible, SSH Client และ Python
Managed Node เครื่องปลายทางที่ Ansible เข้าไปจัดการ SSH Server และ Python

ตัวอย่าง IP Address ที่ใช้ในบทความ

Hostname IP Address บทบาท
control 192.168.1.100 Ansible Control Node
web01 192.168.1.101 Managed Node
web02 192.168.1.102 Managed Node

ให้เปลี่ยน IP Address และชื่อผู้ใช้ให้ตรงกับระบบจริงของผู้อ่าน

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

  • CentOS 7.9 แบบ 64 บิตสำหรับ Control Node
  • บัญชีผู้ใช้ที่สามารถใช้ sudo ได้
  • การเชื่อมต่ออินเทอร์เน็ตสำหรับดาวน์โหลดแพ็กเกจ
  • เครื่อง Managed Node ที่เปิดใช้งาน SSH
  • IP Address หรือ DNS Name ของทุกเครื่องปลายทาง

#ขั้นตอนที่ 1: ตรวจสอบเวอร์ชันของ CentOS

เข้าสู่ระบบ Control Node แล้วตรวจสอบเวอร์ชันของระบบปฏิบัติการ

cat /etc/centos-release

ผลลัพธ์ที่คาดว่าจะได้รับ

CentOS Linux release 7.9.2009 (Core)

ตรวจสอบสถาปัตยกรรมของระบบ

uname -m

สำหรับระบบ 64 บิตควรแสดงผลดังนี้

x86_64

#ขั้นตอนที่ 2: สำรองค่า Repository เดิม

CentOS 7 หมดอายุแล้ว Mirror เดิมจึงอาจใช้งานไม่ได้ ก่อนแก้ไขควรสำรองไฟล์ Repository ไว้ก่อน

sudo cp -a /etc/yum.repos.d "/root/yum.repos.d.backup-$(date +%Y%m%d-%H%M%S)"

สร้างไดเรกทอรีสำหรับเก็บ Repository เดิม แล้วนำไฟล์ของ CentOS เดิมออกจากตำแหน่งที่ yum อ่าน

sudo mkdir -p /etc/yum.repos.d/disabled
sudo mv /etc/yum.repos.d/CentOS-*.repo /etc/yum.repos.d/disabled/

การย้ายไฟล์แทนการลบทำให้สามารถนำไฟล์เดิมกลับมาใช้ได้ในภายหลัง

#ขั้นตอนที่ 3: เปลี่ยนไปใช้ CentOS Vault

สร้างไฟล์ Repository ใหม่

sudo vi /etc/yum.repos.d/CentOS-Archive.repo

เพิ่มเนื้อหาต่อไปนี้

[centos-base]
name=CentOS 7.9.2009 - Base
baseurl=https://vault.centos.org/7.9.2009/os/$basearch/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

[centos-updates]
name=CentOS 7.9.2009 - Updates
baseurl=https://vault.centos.org/7.9.2009/updates/$basearch/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

[centos-extras]
name=CentOS 7.9.2009 - Extras
baseurl=https://vault.centos.org/7.9.2009/extras/$basearch/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

ล้าง Cache และสร้าง Metadata ใหม่

sudo yum clean all
sudo yum makecache

ตรวจสอบว่า Repository เปิดใช้งานได้

yum repolist enabled

ควรพบ Repository ต่อไปนี้

centos-base
centos-updates
centos-extras

CentOS Vault เป็นคลังแพ็กเกจแบบ Archive จึงไม่มี Security Update ใหม่ แม้คำสั่ง yum update จะทำงานสำเร็จก็ตาม

#ขั้นตอนที่ 4: เพิ่ม EPEL 7 Archive

แพ็กเกจ Ansible 2.9 สำหรับ CentOS 7 อยู่ใน EPEL ให้ติดตั้งแพ็กเกจที่เตรียม GPG Key และไฟล์ Repository ก่อน

sudo yum install -y epel-release

Repository ปกติของ EPEL 7 หมดอายุแล้ว จึงปิด Repository เดิม

sudo sed -i 's/^enabled=1/enabled=0/' /etc/yum.repos.d/epel.repo

สร้างไฟล์สำหรับ EPEL Archive

sudo vi /etc/yum.repos.d/epel-archive.repo

เพิ่มเนื้อหาต่อไปนี้

[epel-archive]
name=EPEL 7 - Archive - $basearch
baseurl=https://archives.fedoraproject.org/pub/archive/epel/7/$basearch/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7

จากนั้นสร้าง Cache ใหม่อีกครั้ง

sudo yum clean all
sudo yum makecache

ตรวจสอบ EPEL Archive

yum repolist enabled | grep epel

ผลลัพธ์ควรพบ epel-archive

#ขั้นตอนที่ 5: ติดตั้ง Ansible

ติดตั้ง Ansible ด้วย yum

sudo yum install -y ansible

ตรวจสอบแพ็กเกจที่ติดตั้ง

rpm -q ansible

บน EPEL 7 Archive โดยทั่วไปจะได้ Ansible รุ่นสุดท้ายในสาย 2.9 เช่น

ansible-2.9.27-1.el7.noarch

ตรวจสอบรายละเอียด Ansible

ansible --version

ตัวอย่างผลลัพธ์

ansible 2.9.27
  config file = /etc/ansible/ansible.cfg
  executable location = /usr/bin/ansible
  python version = 2.7.5

Ansible 2.9 และ Python 2.7 เป็นซอฟต์แวร์รุ่นเก่า วิธีนี้เลือกใช้เพื่อให้เข้ากันได้กับ CentOS 7.9 เท่านั้น ไม่ควรนำไปออกแบบระบบใหม่

#ขั้นตอนที่ 6: เตรียม Managed Node

ทำขั้นตอนต่อไปนี้บนเครื่อง web01 และ web02

#6.1 ตรวจสอบ SSH Server และ Python

sudo yum install -y openssh-server python sudo
sudo systemctl enable --now sshd

ตรวจสอบสถานะ SSH

sudo systemctl status sshd

ตรวจสอบ Python

python --version

CentOS 7.9 จะแสดง Python 2.7 ซึ่งทำงานร่วมกับ Ansible 2.9 ได้

#6.2 สร้างผู้ใช้สำหรับ Ansible

sudo useradd -m ansible
sudo passwd ansible
sudo usermod -aG wheel ansible

กลุ่ม wheel อนุญาตให้ผู้ใช้เรียก sudo ได้ตามค่าเริ่มต้นของ CentOS 7 การรันงานที่ต้องใช้สิทธิ์ผู้ดูแลระบบสามารถใช้ตัวเลือก --ask-become-pass หรือ -K เพื่อให้ Ansible ถามรหัสผ่าน sudo

สำหรับ ห้องทดลองเท่านั้น หากต้องการให้ Ansible ใช้ sudo โดยไม่ถามรหัสผ่าน สามารถสร้างไฟล์ดังนี้

echo 'ansible ALL=(ALL) NOPASSWD: ALL' | sudo tee /etc/sudoers.d/ansible
sudo chmod 440 /etc/sudoers.d/ansible
sudo visudo -cf /etc/sudoers.d/ansible

ควรจำกัดคำสั่งที่อนุญาตและจัดการสิทธิ์ตามนโยบายขององค์กรเมื่อใช้ในระบบจริง

#ขั้นตอนที่ 7: สร้าง SSH Key บน Control Node

กลับมาที่เครื่อง Control Node และเข้าสู่ระบบด้วยผู้ใช้ที่จะใช้รัน Ansible

สร้าง SSH Key

ssh-keygen -t ed25519 -C "ansible-control"

กด Enter เพื่อใช้ตำแหน่งเริ่มต้น หากเป็นระบบจริงควรกำหนด Passphrase ให้กับ Private Key

คัดลอก Public Key ไปยัง Managed Node

ssh-copy-id ansible@192.168.1.101
ssh-copy-id ansible@192.168.1.102

ทดสอบการเชื่อมต่อ

ssh ansible@192.168.1.101

หากเข้าสู่ระบบสำเร็จโดยไม่ต้องกรอกรหัสผ่านของผู้ใช้ปลายทาง แสดงว่า SSH Key ทำงานถูกต้อง จากนั้นออกจาก Managed Node

exit

#ขั้นตอนที่ 8: สร้างโครงการ Ansible

สร้างไดเรกทอรีสำหรับเก็บไฟล์ Inventory, Configuration และ Playbook

mkdir -p ~/ansible-lab
cd ~/ansible-lab

โครงสร้างที่เราจะสร้างมีดังนี้

ansible-lab/
├── ansible.cfg
├── inventory.ini
└── install-httpd.yml

#ขั้นตอนที่ 9: สร้าง Inventory

สร้างไฟล์ inventory.ini

vi inventory.ini

เพิ่มข้อมูลต่อไปนี้

[webservers]
web01 ansible_host=192.168.1.101
web02 ansible_host=192.168.1.102

[webservers:vars]
ansible_user=ansible
ansible_python_interpreter=/usr/bin/python

ตรวจสอบว่า Ansible อ่าน Inventory ได้ถูกต้อง

ansible-inventory -i inventory.ini --graph

ผลลัพธ์ที่คาดว่าจะได้รับ

@all:
  |--@ungrouped:
  |--@webservers:
  |  |--web01
  |  |--web02

#ขั้นตอนที่ 10: สร้างไฟล์ ansible.cfg

สร้างไฟล์ ansible.cfg

vi ansible.cfg

เพิ่มเนื้อหาต่อไปนี้

[defaults]
inventory = ./inventory.ini
host_key_checking = True
retry_files_enabled = False

เมื่อตั้งค่า Inventory ใน ansible.cfg แล้ว คำสั่งภายในไดเรกทอรีนี้ไม่จำเป็นต้องระบุ -i inventory.ini ทุกครั้ง

ตรวจสอบไฟล์ Configuration ที่ Ansible เลือกใช้

ansible --version

บรรทัด config file ควรชี้มาที่ไฟล์ ~/ansible-lab/ansible.cfg

#ขั้นตอนที่ 11: ทดสอบการเชื่อมต่อด้วยโมดูล ping

สั่งให้ Ansible ทดสอบทุกเครื่องใน Inventory

ansible all -m ping

ผลลัพธ์ที่สำเร็จจะมีลักษณะดังนี้

web01 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
web02 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

คำสั่ง ansible -m ping ไม่ได้ส่ง ICMP Ping แต่เป็นการตรวจสอบว่า Ansible สามารถเชื่อมต่อผ่าน SSH เรียก Python และรันโมดูลที่เครื่องปลายทางได้หรือไม่

หากใช้ sudo แบบมีรหัสผ่าน ให้ทดสอบสิทธิ์ด้วยคำสั่ง

ansible all -b -K -m command -a "id"

หากตั้งค่า NOPASSWD สำหรับห้องทดลอง สามารถใช้คำสั่งนี้

ansible all -b -m command -a "id"

ในผลลัพธ์ควรพบ uid=0(root)

#ขั้นตอนที่ 12: สร้าง Playbook แรก

ตัวอย่างนี้จะติดตั้ง Apache HTTP Server เปิดใช้งาน Service และสร้างหน้าเว็บทดสอบบนกลุ่ม webservers

สร้างไฟล์ install-httpd.yml

vi install-httpd.yml

เพิ่ม Playbook ต่อไปนี้

---
- name: Install and configure Apache
  hosts: webservers
  become: true

  tasks:
    - name: Install httpd package
      yum:
        name: httpd
        state: present

    - name: Create test web page
      copy:
        dest: /var/www/html/index.html
        content: |
          <h1>Deployed by Ansible</h1>
          <p>Server: {{ inventory_hostname }}</p>
        owner: root
        group: root
        mode: '0644'

    - name: Enable and start httpd
      service:
        name: httpd
        state: started
        enabled: true

ตรวจสอบ Syntax ก่อนรันจริง

ansible-playbook --syntax-check install-httpd.yml

รัน Playbook โดยถามรหัสผ่าน sudo

ansible-playbook -K install-httpd.yml

หากใช้ NOPASSWD ในห้องทดลอง ให้รันโดยไม่ต้องใส่ -K

ansible-playbook install-httpd.yml

เมื่อทำงานสำเร็จ ให้ทดสอบจาก Control Node

curl http://192.168.1.101
curl http://192.168.1.102

หากเชื่อมต่อพอร์ต 80 ไม่ได้ ให้ตรวจสอบ Firewall ของ Managed Node และเปิด Service http ตามนโยบายความปลอดภัยของระบบ

ตัวอย่างการเปิดพอร์ต HTTP บน CentOS 7

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload

คำสั่งนี้ต้องรันบน Managed Node หรือเพิ่มเป็น Task ใน Playbook โดยติดตั้งแพ็กเกจและเปิดใช้งาน firewalld ให้เรียบร้อยก่อน

#คำสั่ง Ansible พื้นฐานที่ควรรู้

#แสดงรายชื่อ Host

ansible all --list-hosts

#ตรวจสอบ Uptime

ansible all -m command -a "uptime"

#ตรวจสอบพื้นที่ดิสก์

ansible all -m command -a "df -h"

#ตรวจสอบข้อมูลระบบ

ansible all -m setup

#ติดตั้งแพ็กเกจด้วย Ad-hoc Command

ansible webservers -b -K -m yum -a "name=git state=present"

#การแก้ปัญหาที่พบบ่อย

#ปัญหา: Cannot find a valid baseurl

สาเหตุหลักคือ CentOS 7 Mirror เดิมหยุดให้บริการแล้ว ให้ตรวจสอบว่าไฟล์ CentOS-Archive.repo ใช้ URL ของ vault.centos.org และ Repository เดิมถูกปิดหรือย้ายออกแล้ว

yum repolist all
sudo yum clean all
sudo yum makecache

#ปัญหา: No package ansible available

ตรวจสอบว่า EPEL Archive เปิดใช้งานอยู่

yum repolist enabled | grep epel
yum --enablerepo=epel-archive list available ansible

ตรวจสอบว่ามีไฟล์ GPG Key

ls -l /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7

#ปัญหา: Host is unreachable

ทดสอบ SSH โดยตรงก่อน

ssh -vvv ansible@192.168.1.101

ตรวจสอบรายการต่อไปนี้

  • IP Address ถูกต้องหรือไม่
  • Service sshd ทำงานอยู่หรือไม่
  • Firewall อนุญาตพอร์ต 22 หรือไม่
  • Public Key ถูกบันทึกใน ~ansible/.ssh/authorized_keys หรือไม่
  • Permission ของ .ssh และ authorized_keys ถูกต้องหรือไม่

#ปัญหา: Missing sudo password

เพิ่มตัวเลือก -K เพื่อให้ Ansible ถามรหัสผ่าน sudo

ansible-playbook -K install-httpd.yml

หรือกำหนด sudoers แบบไม่ถามรหัสผ่านเฉพาะในห้องทดลอง

#ปัญหา: Python interpreter not found

ติดตั้ง Python บน Managed Node

sudo yum install -y python

และกำหนด Interpreter ใน Inventory

ansible_python_interpreter=/usr/bin/python

#ปัญหา: SSH host key checking failed

เชื่อมต่อด้วย SSH โดยตรงหนึ่งครั้งเพื่อตรวจสอบ Fingerprint แล้วบันทึก Host Key

ssh ansible@192.168.1.101

ไม่แนะนำให้ปิด host_key_checking ในระบบ Production เพราะ Host Key ช่วยป้องกันการเชื่อมต่อไปยังเครื่องที่ไม่ถูกต้องหรือการโจมตีแบบ Man-in-the-Middle

#สรุป

การติดตั้ง Ansible บน CentOS 7.9 ในปัจจุบันต้องคำนึงถึงการหมดอายุของทั้งระบบปฏิบัติการและ Repository ขั้นตอนหลักประกอบด้วย

  1. ตรวจสอบ CentOS 7.9 และสำรอง Repository เดิม
  2. เปลี่ยน Repository ไปยัง CentOS Vault
  3. เพิ่ม EPEL 7 Archive
  4. ติดตั้งและตรวจสอบ Ansible 2.9
  5. เตรียม SSH และ Python บน Managed Node
  6. สร้าง Inventory และ ansible.cfg
  7. ทดสอบด้วยโมดูล ping
  8. รัน Playbook เพื่อติดตั้ง Apache

แม้วิธีนี้จะช่วยให้ระบบเดิมยังใช้งาน Ansible ได้ แต่แนวทางที่ปลอดภัยสำหรับระยะยาวคือย้าย Control Node และ Managed Node ไปยังระบบปฏิบัติการที่ยังได้รับการสนับสนุน แล้วใช้ ansible-core รุ่นที่ยังอยู่ในรอบการบำรุงรักษา

#แหล่งอ้างอิง