แสดงบทความที่มีป้ายกำกับ linux แสดงบทความทั้งหมด
แสดงบทความที่มีป้ายกำกับ linux แสดงบทความทั้งหมด

วันอังคารที่ 26 มิถุนายน พ.ศ. 2555

10 ซอฟต์แวร์เพื่อบริการ web site สำหรับทุกวันนี้


Cores แกนหลักๆ ซึ่งก็คือ LAMP นั่นเอง

  1. Linux ซึ่งปกติใช้ Debian ตอนนี้รุ่น stable คือ squeeze (6.0) บนสถาปัตยกรรม amd64 คงไม่มีใครใช้ 32 bit นะ
  2. Apache httpd โดยใช้ MPM แบบ worker แม้ว่าจะมีคู่แข่งอย่าง lighttpd หรือ nginx แต่ apache httpd มีฟีเจอร์มากมายและตั้งค่าได้ง่าย ในเรื่องความเร็วในการให้บริการเว็บแบบ dynamic content ด้วย PHP ไม่ได้ต่างกันมาก
  3. MySQL จริงๆ คือ database server สักตัว แต่ส่วนใหญ่ developer ยังถนัดจะใช้ mysql กันอยู่ ก็ตามนั้นไปก่อน ทางเลือกอื่นๆ ก็มี percona ซึ่งเป็น mysql clone, postgreSQL หรือจะ NoSQL ก็ mongodb, couchdb เป็นต้น
  4. PHP ตอนนี้ใช้รุ่น 5.3 อยู่ แต่รันแบบ fpm (php5-fpm) ตัวนี้ยังไม่มีบน squeeze แต่สามารถลงได้จาก repo ของ dotdeb.org เป็นตัวที่ รัน php5 ในโหมด fastcgi ซึ่งมีระบบบริหารจัดการโพรเซสด้วย ต่างจาก php5-cgi ที่แม้ว่าจะรันเป็น fastcgi ได้แต่ชอบมีปัญหา process ค้าง

Extensions ส่วนขยายที่ทำให้ระบบทำงานได้ดีขึ้น

  1. varnish ตัวนี้เป็น reverse proxy สำหรับรับ connection ที่ port 80 ก่อนจะส่งต่อให้ apache จุดเด่นคือ ทำ caching ได้, มี apache เป็น backend หลายๆ เครื่องได้ คือทำ load balance ได้นั่นเอง, เขียน script เพื่อจัดการกับภาระกิจบางอย่างได้ เช่น backend เรียกไปแล้ว error 503  กลับมา ก็สั่งให้เรียกไปใหม่ หรือให้แสดงหน้ารอ แล้ว refresh ใหม่ เป็นต้น (503 มักเกิดจาก backend ไม่พร้อมให้บริการในขณะนั้น ส่วนใหญ่รอสักพักแล้ว refresh ก็ใช้ได้ตามปกติ) ปัญหาหนึ่งของการใช้ varnish + apache คือข้อมูลล็อกของ apache จะเก็บ client IP เป็น IP ของ varnish เอง ไม่ใช่ของ client ที่แท้จริง แก้โดยใช้ libapache2-mod-rpaf
  2. couchbase ใช้ทำหน้าที่เป็น memcache โดยใช้สำหรับ 1. เก็บ php session data 2. ใช้เป็น memcache สำหรับเก็บข้อมูล cache ชั่วคราว โดยไม่ต้อง query จาก database บ่อยๆ (ต้องเขียนแอปให้รองรับการใช้ memcache ด้วย) เดิมใช้ memcached แต่ couchbase ดีกว่าตรงที่ สามารถทำงานแบบ cluster คือมีหลายๆ เครื่องช่วยกันทำงานได้ สามารถเก็บลงดิสก์ได้ มีหน้าเว็บสำหรับ monitor และตั้งค่าต่างๆ ได้
  3. ufw การกำหนดค่า firewall ด้วย iptables (netfilter) นั้นสำหรับผมเองถือว่ายุ่งยากมาก โดยเฉพาะเวลาที่ต้องกลับมาแก้หรือปรับบางค่าใหม่ พอมาลอง ufw แล้วสะดวกสบายขึ้นมาก

Luxuries ไม่ได้ทำให้ระบบทำงานดีขึ้น แต่ช่วยสนับสนุนในการติดตามเฝ้าดูระบบ

  1. munin เอาไว้เก็บข้อมูลการทำงานของระบบไว้ตรวจสอบ โดยมันจะสร้างเป็นชุดของแผนภูมิให้ดูง่ายๆ และสวยงามเลยทีเดียว สามารถใช้เก็บข้อมูลจากหลายๆ เครื่องได้โดยติดตั้งเฉพาะแพกเกจชื่อ munin-node แล้วให้ munin ตัวหลักไปเรียกเอาข้อมูลมาประมวลเป็นแผนภูมิ
  2. monit เอาไว้คอย monitor ระบบและจัดการแจ้งเตือน หรือรันคำสั่งที่ตั้งไว้ เมื่อตรวจพบเหตุบางอย่าง เช่นเปิดหน้าเว็บที่กำหนดไว้ไม่ได้ ดิสก์เหลือน้อย พบแพทเทิร์นล็อกที่กำหนดไว้ เป็นต้น
  3. webalizer เอาไว้วิเคราะห์ล็อกของ web server แสดงเป็นรูปแผนภูมิสวยงาม ดูง่าย และน่าจะคุ้นเคยกันดี

วันพฤหัสบดีที่ 7 มิถุนายน พ.ศ. 2555

การเซ็ต IPv6 แบบ 6to4 ให้ server

รับกระแส World IPv6 Launch Day ที่เพิ่งมีไปเมื่อวาน (6/6/2012) ซึ่งแปลว่าต่อจากนี้จะเริ่มมีการให้บริการ IPv6 ขนานไปกับ IPv4 มากขึ้น ผู้ที่ต้องตื่นตัวก่อนคือผู้ให้บริการต่างๆ บน Internet นั่นเอง ที่ต้องเตรียมพร้อมรับมือกับมัน (อย่างน้อยก็แสดงให้เห็นว่าเราไม่ตกยุค) ส่วนรายละเอียดว่าทำไมเราต้องเปลี่ยนจาก IPv4 มาเป็น IPv6 ขอให้อ่านจาก http://www.blognone.com/topics/ipv6 นะครับ ในที่นี้ขอพูดถึงประเด็นเดียวคือ เมื่อเรามี server ที่ให้บริการบนเครือข่าย IPv4 อยู่ จะทำอย่างไรให้สามารถบริการ IPv6 ได้
ถ้าเป็นก่อนนี้จะวุ่นวายน่าดูเพราะต้องทำ tunnel ไปยัง IPv6 broker ต่างๆ แต่ตอนนี้มีเทคนิคที่เรียกว่า 6to4 โดยให้ IPv6 encapsulate ไปกับ IPv4 เลย โดยใช้ protocol 41 ซึ่งการตั้งค่าจะเป็นแบบอัตโนมัติ คือไม่ต้องไปหา tunnel ให้วุ่นวาย โดยเมื่อเรามี IPv4 แล้ว เราจะได้รับการจอง subnet ของ IPv6 ไว้ช่วงหนึ่งโดยอัตโนมัติ

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

  • server ที่มี IP จริง (global IP) IP แบบ private ใช้ไม่ได้ อ่อ dynamic IP ก็ไม่ได้นะครับ
  • โปรแกรม ipv6calc (ติดตั้งบน debian ได้โดยสั่ง apt-get install ipv6calc)

วิธีการ

  • แปลงที่อยู่ IPv4 เป็น IPv6 ด้วย ipv6calc โดยสมมติว่า IPv4 คือ 202.183.164.17
    # ipv6calc --quiet --action conv6to4 202.183.164.17
    2002:cab7:a411::
  • แก้ไขไฟล์ /etc/network/interfaces โดยเพิ่มเนื้อหาตามนี้เข้าไป
    auto tun6to4
    iface tun6to4 inet6 v4tunnel
            address 2002:cab7:a411::1
            netmask 16
            gateway ::192.88.99.1
            endpoint any
            local 202.183.164.17
    ตรง 2002:cab7:a411::1 มาจาก ipv6calc โดยเพิ่มเลข 1 ต่อท้ายเข้าไป ส่วน local 202.183.164.17 ก็คือ IPv4 ปกติของ server เรา และ gateway ::192.88.99.1 ไม่ต้องแก้นะครับ จะเป็น anycast address สำหรับรับส่ง packet กับ 6to4 relay router ที่ใกล้ที่สุดซึ่งจะมีกระจายอยู่ทั่วโลก
  • เริ่มใช้งานโดยสั่ง
    # ifup tun6to4
  • ทดสอบโดยสั่ง
    # ping6 google.com
  • ถ้าใช้ไม่ได้อาจจะเกิดจาก firewall ในเครื่องเราเองที่ปกติจะไม่รับ protocol 41 ให้แก้โดยสั่ง
    # iptables -I INPUT -p 41 -j ACCEPT
    # iptables -I OUTPUT -p 41 -j ACCEPT
    แล้วลองทดสอบใหม่ ถ้าใช้ได้ก็เอาไปเพิ่มใน firewall script ของเรา เช่นผมใช้ ufw ก็เพิ่ม -I INPUT -p 41 -j ACCEPT และ -I OUTPUT -p 41 -j ACCEPT ไว้ที่ /etc/ufw/before.rules ก่อนหน้าบรรทัด COMMIT
  • แต่ถ้าใช้ไม่ได้เพราะ firewall ของ NOC ไม่ forward protocol 41 มาให้ ก็ต้องคุยกับผู้ให้บริการให้เปิดรับ protocol 41 ด้วย ปกติไม่เคยเจอปัญหานี้ที่ผู้ให้บริการทั่วไป แต่ถ้าภายในองค์กรอาจจะมีปัญหานี้ได้
  • ทดสอบการใช้บริการต่างๆ ผ่าน IPv6 ในที่นี้เราต้องใช้ IPv6 จากเครื่อง client ได้ก่อน
    เช่น เปิด browser ไปยัง url http://[2002:cab7:a411::1] หรือ ssh 2002:cab7:a411::1
  • ตรวจสอบบริการต่างๆ ให้รองรับ IPv6 ตรวจสอบการตั้งค่า firewall ให้รองรับ IPv6
  • ถ้ามั่นใจแล้วก็เพิ่ม record AAAA 2002:cab7:a411::1 ไปที่ DNS ของเราได้เลย เพื่อให้ผู้ใช้ที่ใช้ IPv6 ได้ สามารถติดต่อกับ site ของเราผ่าน IPv6 ได้โดยตรง
 ดูเพิ่มเติม : http://wiki.debian.org/DebianIPv6

วันพฤหัสบดีที่ 1 กันยายน พ.ศ. 2554

MD RAID Migration จาก partition ธรรมดา เป็น RAID1,5,6,10

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

ปกติเรามักจะทำ RAID ก่อนที่จะติดตั้งระบบ โดยเฉพาะเมื่อต้องคอนฟิก hardware RAID นั้น เป็นไปไม่ได้เลยที่จะติดตั้งระบบบนดิสก์ตัวเดียวก่อน แล้วค่อยเปลี่ยนเป็น RAID ภายหลัง
แต่ความยืดหยุ่นของ Linux MD RAID ทำให้การ migrate จากพาร์ทิชันธรรมดา มาเป็น RAID ได้ ซึ่งทำได้เฉพาะกับ RAID ที่รองรับ redundant ดังนั้นจึงใช้กับ RAID0 ไม่ได้
ในขั้นแรก ขอยกตัวอย่างการ migrate จาก พาร์ทิชันธรรมดา -> RAID1
สถานการณ์ เดิมมีฮาร์ดดิสก์ 1 ตัว (sda) แบ่งเป็น

  1. /boot
  2. swap
  3. /
  4. /var
ต่อมาเพิ่มฮาร์ดดิสก์อีกตัวขนาดเท่ากัน (sdb) จะทำ RAID1 ทุกพาร์ทิชัน ยกเว้น swap

หลักการคือ เราจะทำให้ sdb ทำงานเป็น RAID1 ที่มีสถานะ degraded คือมีดิสก์ไม่ครบ แต่ยังทำงานได้ คือมีดิสก์เพียง 1 ตัว จากที่ต้องการจริงคือ 2 ตัว แล้วย้ายข้อมูลจาก sda แต่ละพาร์ทิชัน ไปยัง RAID1 แต่ละพาร์ทิชันที่สร้างขึ้น ปรับ boot parameter ต่างๆ ให้บูตและเมานท์จาก RAID ทั้งหมด แล้วรีบูต แล้วค่อยเพิ่ม sda แต่ละพาร์ทิชันเข้ามาใน RAID แต่ละชุด

ขั้นตอน
โคลนโครงสร้างพาร์ทิชัน
# sfdisk -d /dev/sda | sfdisk -L /dev/sdb

เปลี่ยนชนิดของพาร์ทิชันเป็น Linux raid autodetect (fd)
# fdisk /dev/sdb
t
1
fd
t
3
fd
t
4
fd
w

สร้าง swap
# mkswap /dev/sdb2

ติดตั้ง mdadm
# apt-get install mdadm

สร้าง RAID1 ในพาร์ทิชัน 1,3,4
# mdadm --create /dev/md0 --level=1 --raid-devices=2 --metadata=0.9 missing /dev/sdb1

# mdadm --create /dev/md1 --level=1 --raid-devices=2 missing /dev/sdb3
# mdadm --create /dev/md2 --level=1 --raid-devices=2 missing /dev/sdb4
สำหรับ raid ชุดแรกที่จะให้บูตได้ ควรกำหนดให้ใช้ metadata version 0.9 ส่วนตัวอื่นๆ ไม่ระบุ มันจะใช้ metadata version 1.2 และจะระบุ device เป็น missing เพื่อเว้นไว้เพิ่ม sda เข้ามาภายหลัง

จากนั้นสร้าง filesystem
# mkfs.ext2 -L boot -m 0 /dev/md0
# mkfs.ext4 -L root /dev/md1
# mkfs.ext4 -L var /dev/md2

เมานท์และคัดลอกไฟล์ จากพาร์ทิชันเดิม ในขั้นตอนนี้ ถ้ามีโปรแกรม หรือ service อะไรรันไว้ แ้ล้วอาจจะมีการเปิดไฟล์ค้างไว้ ควรหยุดโปรแกรมหรือ service นั้นก่อน เช่น MySQL มิฉะนั้นแล้วข้อมูลที่คัดลอกไปจะไม่สมบูรณ์ ถ้าไม่แน่ใจ ให้ reboot ระบบเป็น single user mode ก่อน
# mkdir /mnt/root
# mount /dev/md1 /mnt/root
# mkdir /mnt/old-root
# mount -o bind / /mnt/old-root
# (cd /mnt/old-root ; tar c . ) | (cd /mnt/root ; tar xpv )
# umount /mnt/old-root
# rmdir /mnt/old-root
# rmdir /mnt/root/mnt/old-root
# rmdir /mnt/root/mnt/root
# mount /dev/md0 /mnt/root/boot
# (cd /boot ; tar c . ) | (cd /mnt/root/boot ; tar xpv )
# mount /dev/md2 /mnt/root/var
# (cd /var ; tar c . ) | (cd /mnt/root/var ; tar xpv )

ต่อไปจะ chroot และติดตั้ง boot loader ใหม่ และแก้ไขค่าเกี่ยวกับการบูตทั้งหมด
# mount -o bind /dev /mnt/root/dev
# mount -t proc none /mnt/root/proc
# mount -t devpts none /mnt/root/dev/pts
# mount -t sysfs none /mnt/root/sys
# chroot /mnt/root /bin/bash --login
# vi /etc/fstab
   (หรือ nano /etc/fstab แล้วแต่ถนัด editor ใด)
   แล้้วแก้ไขพาร์ทิชัน หรือ UUID เดิมให้เป็น /dev/md0 สำหรับ /boot, /dev/md1 สำหรับ / และ /dev/md2 สำหรับ /var และเพิ่ม swap ให้กับ /dev/sdb2
mdadm --examine --scan >> /etc/mdadm/mdadm.conf
update-grub

# grub-install /dev/sda
# grub-install /dev/sdb
# update-initramfs -u

  ตรวจดูในไฟล์ /boot/grub/grub.cfg ว่า ในบรรทัดที่ขึ้นต้นด้วย linux ได้กำหนด root=/dev/md1 ถูกต้องหรือไม่ โดยปกติจะถูกกำหนดไว้ถูกต้องแล้วด้วยโปรแกรม update-grub
จากนั้นสั่ง reboot

# exit
# umount /mnt/root/sys
# umount /mnt/root/dev/pts
# umount /mnt/root/proc
# umount /mnt/root/dev
# umount /mnt/root
# reboot

เมื่อบูตแล้วระบบควรจะใช้ /dev/md1 เป็น root ลองตรวจสอบด้วยคำสั่ง mount
# mount
ควรจะพบบรรทัดนี้
/dev/md1 on / type ext4 (rw,noatime)

เมื่อสั่ง
# cat /proc/mdstat
จะพบระบบ RAID ยังเป็น degraded อยู่ ดังนี้
md0 : active raid1 sdb1[1]
      262140 blocks [2/1] [_U]
md1 : active raid1 sdb3[1]
      5242816 blocks [2/1] [_U]
md2 : active raid1 sdb4[1]
      41942480 blocks [2/1] [_U]

ตรวจสอบระบบและข้อมูลต่างๆ ว่ายังปกติดี เมื่อมั่นใจแล้วก็เอาพาร์ทิชันต่างๆ ใน sda มารวมเข้ากับระบบ RAID
# fdisk /dev/sda
t
1
fd
t
3
fd
t
4
fd
w
# mdadm /dev/md0 --add /dev/sda1
# mdadm /dev/md1 --add /dev/sda3
# mdadm /dev/md2 --add /dev/sda4
# cat /proc/mdstat
md0 : active raid1 sdb1[1]
      262140 blocks [2/1] [_U]
      [============>........]  recovery = 63.5% (166458/262140) finish=0.4min speed=3504K/sec
md1 : active raid1 sdb3[1]
      5242816 blocks [2/1] [_U]
       resync=DELAYED
md2 : active raid1 sdb4[1]
      41942480 blocks [2/1] [_U]
       resync=DELAYED

RAID จะ resync จาก sdb ไปยัง sda ซึ่งระยะเวลาขึ้นอยู่กับขนาดของพาร์ทิชันและความเร็วในการอ่านเขียนดิสก์ รวมถึงความ busy ของดิสก์ด้วย
ในระหว่างนี้ ถ้าเป็น server เราก็สามารถให้บริการได้ตามปกติ แต่ก็จะทำให้การ sync ข้อมูลของ RAID ช้าไปด้วย

ถ้าจะ migrate จากพาร์ทิชันธรรมดา ไปเป็น RAID5,6 หรือ RAID10 ก็ทำได้ในลักษณะเดียวกัน คือให้จัดการดิสก์ที่นำเข้ามาเพิ่มให้ทำงานเป็น RAID ที่ไม่สมบูรณ์ หรือ degraded ก่อน แล้วดัดแปลงขั้นตอนจากข้างบนได้เลย

มีข้อควรระวังคือพาร์ทิชันที่จะใช้ boot (ปกติคือ /boot หรือถ้าไม่ได้แยกไว้ ก็จะเป็น /) ต้องกำหนดเป็น RAID1 และใช้ metadata version 0.9 เสมอ ถ้าเป็นแบบอื่น อาจจะบูตไม่ได้ แต่ไม่แน่ใจว่า grub2 นี่รองรับ MD RAID ได้ขนาดไหนแล้ว

วันเสาร์ที่ 27 สิงหาคม พ.ศ. 2554

การเปลี่ยน harddisk ใน MD RAID + ประสบการณ์ harddisk เสียพร้อมกัน 2 ตัว

ปกติเวลาทำ RAID บน server เราจะคาดหวังว่าข้อมูลมันจะปลอดภัยเป็นอันดับแรก โดยหลักการคือเราเชื่อว่าฮาร์ดดิสก์มันจะเสียไม่พร้อมกันหรอก พอเสียก็รีบเปลี่ยนตัวใหม่มาแทนทันที มันก็ควรจะอยู่ไปได้เรื่อยๆ นั่นคือเราคาดว่าฮาร์ดดิสก์มันควรจะเสียทีละตัว มีโอกาสน้อยมากที่มันจะเสียพร้อมๆ กัน

แต่ก็ไม่ใช่ว่าจะเป็นไปไม่ได้ เร็วๆ นี้ผมเจอเคสหนึ่ง เซิร์ฟเวอร์ที่เคยไปติดตั้งให้ลูกค้าเมื่อ 2 ปีกว่ามาแล้ว ส่งเมลมาแจ้งว่ามีดิสก์ตัวหนึ่งของ RAID เสีย (อันนี้เป็นข้อดีประการสำคัญของ Linux MD RAID ที่มันมีตัว monitor ที่จะส่งเมลบอกเราได้เมื่อพบดิสก์เสีย) ผมก็รีบแจ้งลูกค้าให้เตรียมฮาร์ดดิสก์ไปเปลี่ยน แล้วก็นัดกันเข้าไปเปลี่ยนที่ NOC แห่งหนึ่ง

เริ่มจาก ตรวจสอบดูสถานะของ RAID โดยสั่ง

# cat /proc/mdstat

ถ้าระบบ RAID มันปกติ จะพบสถานะแสดงเป็น [UU] อันนี้เป็นกรณี RAID1 ถ้ามีตัวหนึ่งเสีย จะเป็น [U_] และหลังชื่อ device ที่เสีย จะมี (F) บอกไว้
ในที่นี้ระบบดังกล่าวผมทำ RAID1 ไว้ 5 ชุด บนดิสก์ 4 ตัว ชุดหนึ่งเป็น RAID1 ที่สร้างจาก partition เล็กๆ 4 partition จากแต่ละดิสก์ เพื่อใช้เป็น /boot และติดตั้ง bootloader ไว้บนทุกดิสก์ นั่นคือระบบนี้จะต้องบูตได้จากดิสก์ทุกตัว แล้วรวมชุดที่เหลืออีกทีเป็น RAID0 2 ชุด สำหรับเก็บข้อมูล

ในที่นี้ดิสก์ตัวที่เสียคือ sda จึงสั่ง remove ตัวที่เสียออก

# mdadm /dev/md0 --remove /dev/sda1
mdadm: hot removed /dev/sda1
# mdadm /dev/md1 --remove /dev/sda3
mdadm: hot removed /dev/sda3

บางทีมันพบจุดเสียเฉพาะในบางพาร์ทิชัน แต่เราต้องเปลี่ยนด้วยกัน ก็ให้สั่ง fail มันก่อนแล้วค่อย remove

# mdadm /dev/md1 --fail /dev/sda3 --remove /dev/sda3
mdadm: hot removed /dev/sda3


เครื่องนี้มี hot swap bay ซึ่งมีหลอดแสดงสถานะการทำงานของดิสก์แต่ละตัวแยกกัน แต่เนื่องจากไม่ได้ใช้ hardware RAID จึงไม่มีไฟบอกสถานะว่าดิสก์ตัวไหนเสีย จึงเล่นมุกง่ายๆ โดยลองสั่งให้ดิสก์ตัวที่เสียมันทำงาน โดยสั่ง

# dd if=/dev/sda of=/dev/null bs=1G count=1

ไฟหลอดไหนกระพริบก็แสดงว่าคือตัวนั้น จึงถอดออกและใส่ตัวใหม่แทน แต่พบว่าปัญหาคือ hotswap มันทำงานผิดปกติหรือเปล่าไม่ทราบ ตัวใหม่จึงเห็นเป็น sde ซึ่งเป็นไปได้มากกว่าพอบูตใหม่ มันจะกลับมาแสดงเป็น sda แทนตัวเก่าอีกที แต่อันที่จริงไม่น่าจะมีปัญหาเพราะ RAID มันจะตรวจสอบจาก uuid ของ partition ไม่ใช่ชื่อ device

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

# sfdisk -d /dev/sdb | sfdisk /dev/sde

และเพิ่มดิสก์ใหม่เข้าไปใน RAID

# mdadm /dev/md0 --add /dev/sde1
# mdadm /dev/md1 --add /dev/sde3

ตรวจสอบดู

# cat /proc/mdstat

ก็จะพบว่า RAID กำลังถูก rebuild

อื่นๆ ที่ทำคือติดตั้ง grub ใน boot record เพื่อให้มันบูตได้ ซึ่งยังไม่ขอกล่าวถึงในที่นี้

ซึ่งทั้งหมดที่ทำนี้เครื่องนี้ยังให้บริการต่อตามปกติ แต่เพื่อความแน่ใจจึงขอรีบูตเครื่องใหม่เพื่อดูว่า RAID ยังทำงานได้ แต่พบว่า BIOS แจ้งว่าพบดิสก์เพียง 3 ตัว ปรากฏว่ามีดิสก์อีกตัวที่เดิมไม่ได้เสีย แต่พอรีบูตเครื่องแล้วไม่สามารถกลับมาทำงานได้ตามปกติ ซึ่งเป็นเรื่องในตำนานที่เคยได้ยินมาเหมือนกันว่า ระบบที่เปิดทิ้งไว้นานนับหลายปี ทำงานปกติดี แต่พอรีบูตแล้ว ดิสก์ไม่กลับมาทำงานอีก แต่ไม่คิดว่าจะเจอกับตัว แถม RAID ยัง rebuild ไม่เสร็จด้วย ตั้งสติกันสักพัก แล้วมาลุ้นกันว่าตัวไหนจะเสีย คือถ้าตัวที่เสียคือตัวที่คู่กับมันใน raid1 ก็โบกมือลาข้อมูลได้เลย แต่โชคดีที่ไปเสียตัวที่ไม่ใช่คู่มัน ไปเสียที่ raid1 อีกชุดหนึ่ง จึงต้องถอดดิสก์ตัวที่เสียอีกตัวให้ลูกค้าเอาไปเคลม โดยปล่อยให้ระบบทำงานในโหมด degraded ไปก่อน แล้วอีกอาทิตย์หนึ่งจึงกลับมาใส่และ rebuild มันคล้ายๆ step ข้างบนอีกรอบ

เพื่อความปลอดภัย เผื่อในกรณีซวยซ้ำซวยซ้อนแบบที่เจอมานี้ ควรใช้ RAID ที่ยอมให้ดิสก์เสียได้มากกว่า 1 ตัว เช่น RAID6 ที่ยอมให้ดิสก์เสียได้ถึง 2 ตัว (ส่วน RAID5 ยอมให้เสียได้เพียง 1 ตัว) RAID1+0 ก็พอไหว เสียได้ 1 ตัว กับอีกตัวที่ไม่ใช่คู่ของมัน (2 ใน 3 ตัว) อันนี้คือกรณีทำ RAID1 2 ชุด แล้วมารวมเป็น RAID0 อีกชุดหนึ่ง ถ้าทำ RAID0 2 ชุด แล้วมารวมเป็น RAID1 ผมคิดว่าไม่ใช่ไอเดียที่ดี เพราะถ้ามีดิสก์เสีย 1 ตัว อีก 1 ตัวที่จะเสียได้ ต้องเป็นคู่ของมันเท่านั้น (1 ใน 3 ตัว)

มีอีกแนวทางหนึ่งคือใช้ Linux MD RAID 10 ซึ่งเป็น non-standard RAID ซึ่งสามารถกำหนด layout ได้ว่าให้บันทึกข้อมูลในดิสก์ในลักษณะใด ซึ่งสามารถทำให้ระบบยอมให้ดิสก์เสียได้พร้อมกัน 2 ตัว ไม่ว่าจะเป็นตัวไหนก็ได้ โดย Linux MD RAID 10 นี้ยังให้ประสิทธิภาพทั้งการอ่านและเขียนสูงกว่าแบบอื่นๆ ซึ่งขึ้นอยู่กับ layout ที่เลือกอีกด้วย ไว้โอกาสหน้าจะเอามานำเสนออีกครั้งครับ

วันศุกร์ที่ 26 สิงหาคม พ.ศ. 2554

btrfs: ทำ profile แบบ RAID ในระดับ filesystem

คุณสมบัติหนึ่งของ btrfs คือ มันสามารถใช้ดิสก์หลายๆ ตัวมารวมเป็นพื้นที่เดียวกันได้ โดยไม่จำเป็นต้องพึ่ง RAID หรือ LVM ซึ่งสามารถกำหนด metadata profile และ data profie ได้ว่าให้มีคุณสมบัติคล้าย RAID แบบใด ซึ่งปัจจุบันสามารถกำหนดให้เป็น raid0, raid1, raid10

ตอนสร้าง filesystem แบบ btrfs มันจะใช้ metadate profile เป็น raid1 และ data profile เป็น raid0 ถ้าสร้างบนดิสก์ตัวเดียว metadata จะเก็บบนดิสก์ตัวเดียวกัน 2 สำเนา

# mkfs.btrfs /dev/sda1
เทียบเท่า
# mkfs.btrfs -m raid1 -d raid0 /dev/sda1

สร้างจากดิสก์ 2 ตัว
# mkfs.btrfs /dev/sda1 /dev/sdb1
เวลาเมานท์ก็ระบุตัวใดตัวหนึ่งก็ได้เช่น
# mount /dev/sda1 /mnt/data

อันที่จริงแล้วมันไม่ได้เป็น RAID จริงๆ คือไม่ได้เป็นลักษณะของ disk array แต่เป็นการกำหนดว่าหน่วยข้อมูลที่จัดเก็บใน filesystem บนดิสก์หลายๆ ตัว ให้มีลักษณะของการเก็บอย่างไร ได้แก่

raid0
เก็บหน่วยข้อมูลในลักษณะ stripping คือกระจายหน่วยข้อมูลที่ต่อเนื่องกัน ให้ไปอยู่บนดิสก์หลายๆ ตัว ทำให้การอ่านและเขียนเร็วขึ้นมากตามจำนวนดิสก์ที่มี

ต้องใช้ดิสก์อย่างน้อย 1 ตัว อันนี้จะต่างจาก RAID ปกติ ที่จะต้องใช้ดิสก์ 2 ตัวขึ้นไป คือถ้ามีดิสก์เพียง 1 ตัว มันก็จะเก็บข้อมูลตามปกตินั่นเอง
ถ้าในตอนแรกมีดิสก์ 2 ตัว เมื่อสั่ง delete ดิสก์ออก 1 ตัว มันจะคัดลอกข้อมูลจากตัวที่จะเอาออก มาที่ตัวที่เหลือ แล้วจึงเอาออก ซึ่งในการทำแบบนี้ สามารถทำในขณะที่ filesystem กำลังทำงานอยู่ได้ทันที ในการเพิ่ม ก็สามารถเพิ่มดิสก์เข้ามาได้ทันที โดยสามารถสั่ง balance เพื่อกระจายหน่วยข้อมูลออกไปเก็บบนดิสก์ทุกตัวอีกที
ความปลอดภัยของข้อมูล
แบบ raid0 นี้ข้อมูลแต่ละหน่วยมีเพียงชุดเดียว ไม่มีสำเนา หากมีดิสก์ตัวใดตัวหนึ่งเสีย ข้อมูลที่อยู่ในดิสก์ตัวนั้นจะเสียไปเลย

raid1
เก็บข้อมูลหน่วยละ 2 ชุด และอยู่คนละดิสก์กันเสมอ หรือเรียกอีกอย่างหนึ่งว่า mirroring ต้องใช้ดิสก์ 2 ตัวขึ้นไปเสมอ ดังนั้นถ้าตอนแรกสร้างบนดิสก์ 2 ตัว จะสั่ง delete ตัวใดตัวหนึ่งออกไม่ได้เลย แต่ถ้าดิสก์เกิดเสีย ยังสามารถเมานท์แบบ degrade ได้เพราะข้อมูลมีครบทั้งสองตัว

ตัวอย่าง
# mkfs.btrfs -d raid1 /dev/sda1 /dev/sdb1 /dev/sdc1 /dev/sdd1
# mount /dev/sda1 /mnt/data

raid10
เก็บข้อมูลหน่วยละ 2 ชุดคนละดิสก์กัน และเรียงข้อมูลแบบ stripping ด้วย ทำให้ได้ทั้งความปลอดภัย และความเร็วในการอ่านและบันทึกข้อมูล แบบนี้ใช้ดิสก์ 4 ตัวขึ้นไปเสมอ ถ้ามีเพียง 4 ตัวจะ delete ตัวใดตัวหนึ่งออกไม่ได้

ตัวอย่าง
# mkfs.btrfs -m raid10 -d raid10 /dev/sd[a-d]1
# mount /dev/sda1 /mnt/data

สามารถเพิ่มดิสก์เข้าไปใน pool ของมันได้เรื่อยๆ เช่นเพิ่มดิสก์ตัวที่ 5 เข้ามา ก็สร้าง partition แล้วเพิ่มเข้ามาได้เลย
# btrfs device add /dev/sde1 /mnt/data
# btrfs filesystem balance /mnt/data
สังเกตว่าไม่ต้อง mkfs.btrfs แล้ว แค่เพิ่มเข้าไปเลย และหลังจากเพิ่ม สามารถสั่ง balance เพื่อกระจายข้อมูลไปยังดิสก์ตัวใหม่ด้วย

การถอดดิสก์ออกจาก pool ใช้คำสั่งตามตัวอย่างนี้
# btrfs device delete /dev/sde1 /mnt/data

การเมานท์เมื่อมีดิสก์บางตัวเสียหาย หรือถูกถอดออกไปโดยไม่ได้สั่ง delete
# mount -o degraded /dev/sda1 /mnt/data
ซึ่งก็ควรจัดหาดิสก์มาทดแทนให้เร็วที่สุดแล้วสั่ง
# btrfs device add /dev/sde1 /mnt/data
# btrfs device delete missing /mnt/data

ข้อสังเกตจากการทดลองใช้งานจริงมาระยะหนึ่ง

  1. data profile raid1 เวลาสร้างบนดิสก์ที่มากกว่า 2 ตัว มันชอบเอาข้อมูลไปกองอยู่บนดิสก์แค่ 2 ตัว ไม่ค่อยกระจายเท่าไหร่ ทำให้ดิสก์บางตัวทำงานหนัก ขณะที่บางตัวไม่ค่อยถูกใช้งาน เมื่อสั่ง balance ยิ่งทำให้ข้อมูลถูกย้ายมาเก็บแค่ 2 ตัว
  2. data profile raid10 เวลาถอดดิสก์ออกจากเครื่อง แล้วสั่งเมานท์ จะเมานท์ไม่ได้ แม้ว่าจะระบุอ็อพชัน -o degraded แล้วก็ตาม ส่วนแบบ raid1 ยังไม่ได้ลอง
  3. กำหนด layout ของการเก็บข้อมูลไม่ได้ จึงไม่สามารถระบุให้เก็บข้อมูลเป็น 3 ชุด แทนที่จะเป็น 2 ชุดได้ ซึ่งทำให้เสี่ยงที่จะเกิดปัญหาถ้ามีดิสก์เสีย 2 ตัวพร้อมๆ กัน
  4. ยังไม่รองรับ profile แบบ raid5, raid6
  5. ยังเปลี่ยน profile ไม่ได้ ถ้าสร้างแบบไหน ก็ต้องใช้แบบนั้นตลอดไป
  6. แต่ละ subvolume ไม่สามารถกำหนด profile แตกต่างกันได้
  7. การ balance ทำได้ช้ามาก
  8. สามารถสั่ง defragment ได้ แต่ก็ช้ามากเช่นกัน
  9. ยังไม่สามารถสั่งตรวจสอบ filesystem แบบ online คือกำลังเมานท์อยู่ได้ และการตรวจสอบแบบ offline ก็ยังไม่สมบูรณ์
โดยรวมๆ ยังมีหลายๆ อย่างไม่สมบูรณ์ แต่โดยส่วนตัวคิดว่า เมื่อสมบูรณ์กว่านี้ เราคงไม่จำเป็นต้องใช้ RAID อีกต่อไป

วันพฤหัสบดีที่ 25 สิงหาคม พ.ศ. 2554

ขอคืนพื้นที่ /var/log โดยการ compress log ด้วย xz

xz คล้ายๆ gzip แต่ compress ด้วยอัลกอริทึ่ม lzma2 มีใน squeeze ขึ้นมา หรือใน lenny-backports ดูเพิ่มเติมที่ http://tukaani.org/xz/


ทำไมต้องใช้ xz แทน gzip
  • บีบได้เยอะกว่ามาก พอเอามาใช้บีบ log เก่าที่ถูก rotate ทำให้ใช้พื้นที่น้อยลงมาก
  • ตอน decompress ทำได้ค่อนข้างเร็ว ช้ากว่า gunzip บ้าง แต่เร็วกว่า bunzip2 มาก
ข้อเสีย?
  • ใช้เวลา compress นานกว่ามาก เพราะใช้กำลังในการประมวลผลเยอะ (+ram เยอะๆ) แต่มันทำครั้งเดียว และก็ cpu กับ ram ไม่น่าเป็นปัญหากับ server ในปัจจุบันนัก ส่วนการอ่าน/นำไปใช้ก็มี xzcat, xzless ให้ เร็วใกล้เคียงกับ zcat, zless เลยทีเดียว
ติดตั้ง
# apt-get install xz-utils
# apt-get install xz-lzma   

เทียบคำสั่ง
gzip : xz
gunzip : unxz
zcat : xzcat
zless : xzless
zmore : xzmore
zgrep : xzgrep
zdiff : xzdiff
zcmp : xzcmp
zegrep : xzegrep

การประยุกต์ใช้กับ logrotate เพื่อขอคืนพื้นที่ใน /var/log
เพิ่มบรรทัดต่อไปนี้เข้าไปใน /etc/logrotate.conf
#---------------------------------
compresscmd /usr/bin/xz
uncompresscmd /usr/bin/unxz
compressext .xz
compressoptions -9
#---------------------------------

การแปลงจาก log เก่าที่เป็น .gz มาเป็น .xz
แปลงไฟล์เดียว
# gunzip access.log.2.gz
# xz -9 access.log.2

แปลงหลายๆ ไฟล์
# cd /var/log
# find . -name "*.gz" | sed 's/.gz$//' | xargs -I '{}' -n 1 -P 2 sh -c "gunzip '{}'.gz ; xz -9 '{}'"

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

ปล. คัดลอกมาจาก note เก่าใน Facebook ของผมเอง

วันพุธที่ 24 สิงหาคม พ.ศ. 2554

btrfs: การสร้าง snapshot ของข้อมูล ด้วยวิธี cp --reflink

ในครั้งก่อนเราได้ดูวิธีการทำ snapshot ของ subvolume ใน btrfs ไปแล้ว ซึ่งวิธีนั้นเหมาะกับผู้ที่เป็น admin เพราะมีสิทธิของ root ที่จะทำได้

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

วิธีการคือการใช้คำสั่ง cp (copy) โดยใช้อ็อพชั่น --reflink=always กับ -a ซึ่ง -a หรือ --archive คือการคัดลอกทั้ง subdirectory และไม่แปลง soft-link กลับเป็นไฟล์ และรักษาคุณสมบัติของไฟล์ทุกประการไว้
ส่วน --reflink ใช้กับการคัดลอกแบบ CoW คือไฟล์ที่ได้จะอยู่บนคนละ inode แต่ใน inode ชี้ไปหารายการบล็อคชุดเดียวกันกับต้นฉบับ เว้นแต่เมื่อบล็อคใดมีการแก้ไข จะถูกสำเนาไปเป็นบล็อคใหม่ทันที

เช่น ใน home ของผู้ใช้มีข้อมูลสำคัญเก็บใน Documents ต้องการสำเนาทั้งหมดเก็บไว้แบบ snapshot

$ mkdir backups
$ cp -a --reflink=always Documents backups/Documents-20110825

การคัดลอกจะใช้เวลาไม่นานนัก เพราะมีการอัพเดทเฉพาะส่วน metadata โดยส่วนข้อมูลยังชี้ไปที่เดิม พื้นที่ของดิสก์จะลดลงเล็กน้อย

สามารถสำเนาแบบนี้ได้อีกหลายๆ ครั้งตามต้องการ เช่น ในวันต่อมาก็สั่ง
$ cp -a --reflink=always Documents backups/Documents-20110826

เมื่อต้องการลบ snapshot เหล่านี้ออกบ้าง ก็ใช้คำสั่ง rm -rf ออกได้ เช่น

$ rm -rf backups/Documents-20110825

ซึ่งจะได้คืนเนื้อที่ที่เกิดจากความแตกต่างระหว่าง snapshot กับข้อมูลปัจจุบัน

วันจันทร์ที่ 22 สิงหาคม พ.ศ. 2554

btrfs: การสร้าง snapshot ของข้อมูล

btrfs เป็น filesystem ของ Linux (น่าจะรองรับในทุก distro ในปัจจุบัน) ที่มีคุณสมบัติอย่างหนึ่งคือ CoW (Copy on Write) คือสามารถคัดลอกไฟล์เป็น 2 ชุดโดยอ้างอิงบล็อกของข้อมูลชุดเดียวกันได้ แต่เมื่อไฟล์ใดมีการแก้ไข จึงจะคัดลอกบล็อกที่แก้ไขเป็นอีกบล็อกหนึ่งแล้วจึงแก้ไขมัน ทำให้เวลาคัดลอกลักษณะนี้ มันใช้เนื้อที่น้อยมาก และจะใช้เนื้อที่เพิ่มขึ้นทีละนิดเมื่อไฟล์มีการเปลี่ยนแปลง และสามารถคัดลอกสำเนาในลักษณะนี้ได้หลายๆ ครั้ง (หลายๆ เวอร์ชัน) โดยที่เนื้อที่ที่ใช้เพิ่มขึ้นเฉพาะส่วนที่เปลี่ยนแปลงของแต่ละเวอร์ชันเท่านั้น

คุณสมบัตินี้ถูกใช้ในการทำ snapshot ของ filesystem ในระดับของ subvolume ด้วยคำสั่ง

 btrfs subvolume snapshot <source> [<dest>/]<name>

โดย <source> ต้องเป็น path ของ subvolume ที่ถูกเมานท์ ส่วน <dest> ต้องเป็น path ที่อยู่ใน subvolume ที่อยู่ใน btrfs pool เดียวกัน

เช่น
ในระบบมี subvolume ชื่อ @ เมานท์ไว้ที่ / (เป็น root directory)
และ @home เมานท์ไว้ที่ /home

# mkdir /backups
# btrfs subvolume snapshot /home /backups/home-20110822
Create a snapshot of '/home' in '/backups/home-20110822'


ใน /backups/home-20110822 จะมีข้อมูลเก็บอยู่เหมือนใน ้/home ในขณะเวลานั้นๆ ทันที โดยใช้เนื้อที่เพิ่มขึ้นเพียงเล็กน้อย และใช้เวลาในการทำ snapshot สั้นมากๆ แม้ว่าข้อมูลจะมีเป็นจำนวนมากก็ตาม ซึ่งผู้ดูแลระบบอาจจะแจ้งให้ผู้ใช้ทราบว่า สามารถมาเรียกคืนข้อมูลเก่าๆ ย้อนหลังจาก snapshot ที่เก็บไว้ที่ /backups ก็ได้

snapshot ที่สร้างขึ้น สามารถแก้ไขได้ โดยไม่กระทบกับข้อมูลปัจจุบัน ซึ่งในทางปฏิบัติเราไม่ควรมาแก้ตรงนี้

การลบ snapshot
เนื่องจากเนื้อของดิสก์จะถูกใช้เพิ่มขึ้น เมื่อข้อมูลปัจจุบันต่างจาก snapshot แต่ละรุ่น ดังนั้นการจะเรียกคืนเนื้อที่ส่วนนี้กลับมา ต้องลบ snapshot เก่าๆ ทิ้งไปบ้าง (อาจจะกำหนดเป็นนโยบายว่า จะเก็บย้อนหลังเพียง 7 วัน แล้วเขียน cron script เพื่อจัดการอัตโนมัติ เป็นต้น)

คำสั่ง
 btrfs subvolume delete <subvolume>

เช่น
# btrfs subvolume delete /backups/home-20110822
Delete subvolume '/backups/home-20110822'

ข้อควรระวังคือ ถ้าทำ snapshot ใน filesystem ที่มีไฟล์ถูกเปิดใช้งานอยู่ เช่น mysql server สำเนา snapshot ที่ได้จะไม่สมบูรณ์เพราะไฟล์ที่เปิดอยู่มักจะมีข้อมูลบางส่วนค้างอยู่ในหน่วยความจำ ยังไม่ได้ถูกบันทึกในไฟล์จริง ดังนั้นก่อนจะทำ snapshot ควรปิดระบบที่อาจจะเปิดไฟล์ค้างอยู่ก่อน (ในที่นี้คือให้ปิดโปรแกรม mysql server ก่อน) แล้วจึงสั่งทำ snapshot

ถ้าระบบของเราใช้ btrfs ที่มี data profile และ metadata profile เป็นแบบ RAID1 หรือสร้างบนระบบ RAID1, RAID10, RAID5/6 ไม่ว่าจะเป็นซอฟต์แวร์หรือฮาร์ดแวร์แล้วละก็ อาจจะกล่าวได้ว่า
"ลาก่อน โปรแกรม backup ทั้งหลาย"

วันอาทิตย์ที่ 12 พฤศจิกายน พ.ศ. 2549

Linux กับ software RAID part I

เดิมผมค่อนข้างเชื่อมั่นกับ hardware RAID (แท้ๆ) มากกว่า ด้วยว่าเคยใช้งานมัน ชอบที่มันทำงานที่ระดับล่างไปเลย และเชื่อว่า hardware RAID ทำงานเร็วกว่า software RAID และทราบว่าจะจัดการกับมันอย่างไรเมื่อดิสก์มีปัญหา อีกอย่างคือสะดวกดี ไม่ต้องทำอะไรที่ตัว OS คือ ทำ volume RAID เสร็จแล้ว OS จะมองเห็นเป็นฮาร์ดดิสก์ลูกใหญ่ๆ ลูกเดียว

พอดีว่าเครื่องพีซีที่บ้าน จะลง Gentoo ใหม่อยู่แล้ว ก็มีโจทย์ว่า Gentoo มันต้องคอมไพล์อะไรๆ ใหม่ค่อนข้างบ่อย และสังเกตว่า มันคอมไพล์ช้าเพราะดิสก์ ถ้าทำ raid-0 ได้ก็คงช่วยได้มาก เลยศึกษาเกี่ยวกับ software RAID บน Linux ดีๆ ก็พบว่า มันก็น่าใช้เหมือนกันนะ มันยืดหยุ่นกว่าด้วย และเรื่องประสิทธิภาพเค้าก็บอกว่าด้วยประสิทธิภาพอันเหลือเฟือของคอมพิวเตอร์ทั่วไปในปัจจุบัน ทำให้ software RAID มีประสิทธิภาพไม่ด้อยกว่า hardware RAID เลย