ลดความยุ่งยากในการใช้คลาวด์ พูดคุยกับเจ้าหน้าที่

ตั้งค่าเซิร์ฟเวอร์อัตโนมัติตั้งแต่บูตแรกด้วย cloud-init
Home ตั้งค่าเซิร์ฟเวอร์อัตโนมัติตั้งแต่บูตแรกด้วย cloud-init

ตั้งค่าเซิร์ฟเวอร์อัตโนมัติตั้งแต่บูตแรกด้วย cloud-init

ทุกครั้งที่สร้างเซิร์ฟเวอร์ใหม่ มีชุดงานเดิมที่ต้องทำซ้ำเสมอ สร้างผู้ใช้ วาง SSH Key ปิดการล็อกอินด้วยรหัสผ่าน ตั้ง Timezone ติดตั้งแพ็กเกจพื้นฐาน และเปิด Firewall การทำด้วยมือทุกครั้งกินเวลาและพลาดได้ง่าย โดยเฉพาะขั้นตอนด้านความปลอดภัยที่ลืมแล้วเครื่องเปิดโล่งอยู่หลายชั่วโมง

cloud-init คือระบบที่อ่านคำสั่งตอนเครื่องบูตครั้งแรกแล้วทำให้ทั้งหมดโดยอัตโนมัติ มันติดตั้งมาพร้อมกับอิมเมจ Ubuntu, Debian, AlmaLinux และ Rocky Linux สำหรับคลาวด์อยู่แล้ว

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

  • ผู้ให้บริการคลาวด์ที่มีช่องให้ใส่ User Data ตอนสร้างเครื่อง
  • Public Key ของคุณ ดูได้จาก cat ~/.ssh/id_ed25519.pub

ตรวจว่าอิมเมจรองรับ cloud-init หรือไม่ โดย SSH เข้าเครื่องที่มีอยู่แล้วรัน

cloud-init --version
sudo cloud-init status

ขั้นตอนที่ 1: เขียนไฟล์ cloud-config พื้นฐาน

ไฟล์ต้องขึ้นต้นด้วย #cloud-config บรรทัดแรกเสมอ ถ้าขาดบรรทัดนี้ cloud-init จะไม่อ่านเลย

#cloud-config

hostname: web1
fqdn: web1.example.com
timezone: Asia/Bangkok
locale: en_US.UTF-8

users:
  - name: deploy
    groups: [sudo]
    shell: /bin/bash
    sudo: "ALL=(ALL) NOPASSWD:ALL"
    lock_passwd: true
    ssh_authorized_keys:
      - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... your-name@company

package_update: true
package_upgrade: true
packages:
  - ufw
  - fail2ban
  - unattended-upgrades
  - htop
  - curl
  - git
  - nftables

lock_passwd: true ทำให้ผู้ใช้นี้ล็อกอินด้วยรหัสผ่านไม่ได้เลย เข้าได้เฉพาะด้วย SSH Key ซึ่งเป็นสิ่งที่ควรเป็นสำหรับเซิร์ฟเวอร์ที่เปิดสู่อินเทอร์เน็ต

ขั้นตอนที่ 2: ปิดช่องทางที่ไม่ปลอดภัย

ssh_pwauth: false
disable_root: true

write_files:
  - path: /etc/ssh/sshd_config.d/99-hardening.conf
    permissions: '0644'
    content: |
      PermitRootLogin no
      PasswordAuthentication no
      KbdInteractiveAuthentication no
      MaxAuthTries 3
      X11Forwarding no
      ClientAliveInterval 300
      ClientAliveCountMax 2

การเขียนลงไฟล์ในโฟลเดอร์ sshd_config.d ดีกว่าการแก้ไฟล์หลัก เพราะไม่ถูกเขียนทับเมื่ออัปเดตแพ็กเกจ

ขั้นตอนที่ 3: สั่งคำสั่งที่ต้องรันหลังติดตั้งเสร็จ

runcmd:
  # Firewall
  - ufw --force reset
  - ufw default deny incoming
  - ufw default allow outgoing
  - ufw allow 22/tcp
  - ufw allow 80/tcp
  - ufw allow 443/tcp
  - ufw --force enable

  # เปิดอัปเดตความปลอดภัยอัตโนมัติ
  - dpkg-reconfigure -f noninteractive unattended-upgrades

  # ปรับค่าเคอร์เนลพื้นฐาน
  - sysctl -w vm.swappiness=10
  - echo 'vm.swappiness = 10' > /etc/sysctl.d/99-swappiness.conf

  # โหลดคอนฟิก SSH ใหม่
  - sshd -t && systemctl reload ssh

  - systemctl enable --now fail2ban

คำสั่งใน runcmd รันด้วยสิทธิ์ root และรันครั้งเดียวตอนบูตแรกเท่านั้น เรียงตามลำดับที่เขียน

ขั้นตอนที่ 4: เพิ่ม Swap และตั้งค่าดิสก์

swap:
  filename: /swapfile
  size: 2G
  maxsize: 2G

disk_setup:
  /dev/sdb:
    table_type: gpt
    layout: true
    overwrite: false

fs_setup:
  - device: /dev/sdb1
    filesystem: ext4
    label: data
    overwrite: false

mounts:
  - ["LABEL=data", "/srv/data", "ext4", "defaults,noatime,nofail", "0", "2"]

ระวังตัวเลือก overwrite ให้เป็น false เสมอ เพื่อไม่ให้ฟอร์แมตทับดิสก์ที่มีข้อมูลอยู่ในกรณีที่คอนฟิกถูกนำไปใช้ซ้ำ

ขั้นตอนที่ 5: ส่งข้อความเมื่อเสร็จ

final_message: "cloud-init เสร็จสิ้นเมื่อ $TIMESTAMP หลังบูต $UPTIME วินาที"

power_state:
  mode: reboot
  condition: test -f /var/run/reboot-required
  delay: 1
  message: รีบูตเพื่อใช้เคอร์เนลใหม่

บล็อก power_state สั่งรีบูตอัตโนมัติเฉพาะเมื่อการอัปเดตต้องการเท่านั้น ทำให้เครื่องพร้อมใช้งานจริงตั้งแต่ครั้งแรก

ขั้นตอนที่ 6: ตรวจไวยากรณ์ก่อนใช้

YAML อ่อนไหวกับการเว้นวรรคมาก ตรวจก่อนเสมอ

cloud-init schema --config-file cloud-config.yaml --annotate

หรือตรวจไวยากรณ์ YAML เบื้องต้นด้วย

python3 -c "import yaml,sys; yaml.safe_load(open('cloud-config.yaml'))" && echo OK

ขั้นตอนที่ 7: ใช้งานและตรวจผล

วางเนื้อหาทั้งไฟล์ลงในช่อง User Data ตอนสร้างเครื่อง เมื่อเครื่องขึ้นแล้ว SSH เข้าไปตรวจ

sudo cloud-init status --long
sudo cloud-init analyze show | head -30

ดู Log เมื่อมีอะไรไม่เป็นไปตามคาด

sudo cat /var/log/cloud-init-output.log
sudo grep -i -E 'error|fail|warn' /var/log/cloud-init.log | tail -30

ไฟล์แรกคือผลลัพธ์ของคำสั่งที่รัน ซึ่งมักบอกสาเหตุได้ตรงที่สุด

ขั้นตอนที่ 8: ทดสอบซ้ำบนเครื่องเดิม

ระหว่างพัฒนาคอนฟิก การสร้างเครื่องใหม่ทุกครั้งเสียเวลา สามารถล้างสถานะแล้วให้รันใหม่ได้บนเครื่องทดสอบ

sudo cloud-init clean --logs
sudo cloud-init init
sudo cloud-init modules --mode=config
sudo cloud-init modules --mode=final

ทำเฉพาะบนเครื่องทดสอบเท่านั้น อย่าทำกับเครื่องที่ให้บริการอยู่

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

cloud-init ไม่ทำงานเลย

ตรวจว่าบรรทัดแรกคือ #cloud-config พอดี ไม่มีช่องว่างนำหน้า และไม่มีบรรทัดว่างก่อนหน้า นี่คือสาเหตุอันดับหนึ่ง

SSH เข้าไม่ได้หลังสร้างเครื่อง

Public Key อาจใส่ผิดรูปแบบ ต้องเป็นบรรทัดเดียวเต็ม ๆ ขึ้นต้นด้วย ssh-ed25519 หรือ ssh-rsa ใช้ Console ของผู้ให้บริการเข้าไปตรวจ cat /home/deploy/.ssh/authorized_keys

คำสั่งใน runcmd ไม่ทำงาน

ตรวจลำดับ คำสั่งที่ต้องใช้แพ็กเกจต้องอยู่หลังการติดตั้ง และเครือข่ายอาจยังไม่พร้อมตอนต้น หากจำเป็นให้ใส่คำสั่งรอ เช่น cloud-init status --wait ในสคริปต์ที่เรียกทีหลัง

อยากใช้คอนฟิกเดียวกับหลายเครื่องที่ชื่อต่างกัน

ถอด hostname และ fqdn ออก แล้วให้ผู้ให้บริการตั้งชื่อให้ หรือใช้ตัวแปรที่ระบบรองรับ ทำให้คอนฟิกไฟล์เดียวใช้ได้กับทุกเครื่องในชุดเดียวกัน

ต้องการมาตรฐานการติดตั้งเซิร์ฟเวอร์ที่เหมือนกันทุกเครื่อง ติดต่อ THAI DATA CLOUD ได้ที่ https://thaidata.cloud/contact/

ผู้ให้บริการคลาวด์ไทย
เพื่อธุรกิจของคนไทย

"มุ่งมั่น" และ "มั่นคง"
พร้อมรับมือทุกการเติบโต
Trust Cloud
คลาว์ที่ปลอดภัย
คือรากฐานที่มั่นคง
cloud security