กลุ่มชุมชนแลกเปลี่ยนความรู้แบ่งปั่น และช่วยเหลือ ต่อการใช้งาน OpenSource Zabbix เพราะการแบ่งปัน นั้นยิ่งใหญ่กว่า.

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

การตรวจสอบการทำงานผ่านพอร์ทให้บริการของเซอร์วิสโดยไม่ต้องใช้ Zabbix Agent (Monitoring everything service ports with agent less)

   ในการตรวจสอบการทำงาน (Monitoring) บนระบบ Production ในหลายๆ ครั้งนั้น สิ่งที่ผู้ดูแลระบบมักจะกลัว และไม่ค่อยมักจะอยากให้ทำบนระบบคือ การติดตั้งโปรแกรมใดๆ ลงบนเครื่องนั้น โดยเฉพาะกับเครื่องที่มีการทำงานโหลดสูงๆ (High utilization) มีการทำงานที่สำคัญ (Critical function) รวมไปถึงขอปิดระบบยากๆ  (Less down time)

   ดังนั้นทางเลือกหนึ่งที่จะสามารถทำการตรวจสอบการทำงานเกี่ยวกับการให้บริการแต่ละเซอร์วิสผ่านทางพอร์ท (Port) ได้ คือการ connect เข้าไปผ่านช่องทางของพอร์ทการทำงานในเซอร์วิสเหล่านั้น

   ข้อดี:

  1. ไม่ต้องติดตั้งโปรแกรมใดๆ ลงบนเครื่องนั้นๆ ใช้ช่องทางปกติที่เซอร์วิสนั้นเปิดให้บริการอยู่แล้ว
  2. สามารถทำงานได้เกือบเทียบเท่า Agent โดยสามารถทำได้เท่าที่พอร์ทนั้นให้บริการ
  3. เวลาระบบมีปัญหา เราจะไม่เป็น แพะ!!!
   ข้อเสีย:
  1. อาจจะทำงานได้ไม่เทียบเท่ากับการติดตั้ง Agent ในบางกรณีที่รันบางคำสั่งไม่สามารถใช้งานผ่านพอร์ทนั้นได้
  2. ต้องเขียนโปรแกรมนึดนึง
  3. อาจจะมีการติดตั้งบาง Module บน Zabbix Server(Proxy) ในกรณีที่เป็นเซอร์วิสแปลกๆ

   สิ่งที่ต้องเตรียม
  • การกำหนด Zabbix Item, Macro และ External Script
  • การเขียนโปรแกรม (Python, Shell Script)

   ทำความรู้จักกับ Zabbix Item
      สำหรับ Item ใน Zabbix นั้น คือการสร้างการ monitor หนึ่งอย่าง เช่นต้องการสร้างการ monitor ระบบ MSSQL เราสามารถสร้าง Item ที่ Host ได้ดังนี้ (ปกติควรสร้าง Item ที่ Template แต่เพื่อความเข้าใจที่ง่าน และลดขั้นตอน จึงของแสดงตัวอย่างในการสร้าง Item ที่ Host)

Configuration -> Hosts -> Items -> Create item

โดยจะปรากฏหน้าจอ Create item  โดยใส่ข้อมูลดังนี้
  • Name: MSSQL_mon  => คือชื่อของ Item นี้
  • Type: External check  => คือการเลือกรูปแบบในการตรวจสอบ ในที่นี้เลือก External check เพื่อให้ Zabbix ใช้ script ที่เราจะสร้างขึ้นในขั้นตอนต่อไปมาใช้งาน
  • *Key: mssqlchk.py["{HOST.CONN}","{DBQUERY}","{DBUSER}","{DBPASS}","{DBNAME}"]  => คือการกำหนด script ที่จะใช้งานในการตรวจสอบ โดยมีพารามิเตอร์ภายใน [] ซึ่งพารามิเตอร์นั้นจะใช้การนำ Macro มาใช้งานเพื่อความสะดวกในการกำหนดค่าปรับแต่ง (Configuration)
    • รูปแบบของ script คือ scriptname[<parameter1>,<parameter2>,...]  => โดยที่ script อยู่ที่ /etc/zabbix/externalscripts ใน Zabbix Server/Proxy
    • *Macro คือสิ่งที่เปรียนเสมือนตัวแปรที่สามารถกำหนดได้ในระบบ Zabbix ซึ่งมี macro อยู่สามแบบคือ System (supported) macro, Function macro และ User macro (ดูรายละเอียดเพิ่มเติมที่ https://www.zabbix.com/documentation/4.0/manual/config/macros)
  • Host interface: IPADDR  => คือหมายเลขไอพีของเครื่องที่จะต้องการตรวจสอบการทำงาน
  • Type of information: Numeric (float)  => คือชนิดข้อมูลที่จะต้องการเก็บ กำหนดเป็น Numeric (float) คือทศนิยม ที่เป็นได้ทั้งค่าบวก และลบ (พิจารณาสิ่งที่ script ได้ return ผลมา ณ ที่นี้คือ เวลา response time  เป็นวินาที)
  • Units: s  => คือหน่วยของค่าที่ต้องการกำหนดของ Item นี้ เช่น ms คือ มิลลิวินาที
  • Update interval: 300s  => คือเวลาทุกๆ ที่ต้องการให้ตรวจสอบ Item นี้ เช่น 300s คือ 300 วินาที
  • History storage period: 90d  => คือระยะเวลาที่ให้ระบบเก็บค่าทุกๆ ครั้งที่มีการตรวจสอบ Item นี้ เช่น 90d คือ 90 วัน
  • Trend storage period: 365d  => คือระยะเวลาที่ให้ระบบเก็บค่าที่ถูกประมวลผลแล้วเช่น Min,Max,Avg
  • Show value: As is  =>  คือรูปแบบการเก็บค่า Item สำหรับ As is คือได้ค่ามายังไงก็เก็บค่านั้น



   ทำความรู้จักกับ Macro
      สำหรับ Macro ใน Zabbix นั้นคือตัวแปรที่สามารถเก็บค่าต่างๆ ได้ ซึ่ง macro นั้นมี 3 รุปแบบคือ
  1. System (supported) macro คือ macro ของระบบเช่น หมายเลขไอพีของ host นั้น
  2. Function macro คือการกำหนด macro ที่สามารถคำนวนค่าได้จาก function
  3. User marco คือ macro ที่สามารถกำหนดชื่อ และค่าได้จากผู้ใช้งาน ซึ่งจะมีระดับในการกำหนดค่า (Level) ดังต่อไปนี้
    • Host level macro (ใช้งานก่อน)
    • Macro ที่ถูกำหนดไว้ใน 1'st level templates ของ host (พิจารณาใช้งานตามลำดับ link template), จากนั้นเรียงการใช้งานตามหมายเลข ID ของ template
    • Macros ที่ถูกำหนดไว้ใน 2'nd level templates ของ host, เรียงการใช้งานตามหมายเลข ID ของ template
    • ที่ถูกำหนดไว้ใน 3'rd level templates ของ host, รียงการใช้งานตามหมายเลข ID ของ template
    • Global macros (ใช้งานลำดับสุดท้าย)
      ตัวอย่างการสร้าง Macro (ระดับ Host)

Configuration -> Hosts -> [SELECTED HOST] -> Macro

โดยจะปรากฏหน้าจอ Create item  โดยใส่ข้อมูลดังนี้

  • Macro: QUERY  => คือชื่อของ macro (ใส่ให้ตรงกับพารามิเตอร์)
  • Value: SELECT COUNT(ID) FROM Product  => คือค่าของ macro นั้น ยกตัวอย่างต้องการทดสอบการ query ฐานข้อมูล จึงทำการใส่ SQL เข้าไป

*** โดยปกติจะไม่มีการใส่รหัสผ่าน (Password) ใน macro เพราะจะทำให้เห็นรหัสผ่าน วิธีการที่แนะนำคือการทำ mapping ระหว่าง host และรหัสผ่านใน script แทน***



ทำความรู้จักกับ Zabbix External Script
    Zabbix External Script คือการเขียน script เพื่อเติมเพื่อให้สามารถทำการ monitor ได้ตามที่ต้องการอย่างไม่มีขอบเขต เนื่องจากเป็นการเขียนโปรแกรมเพื่อทำการ monitor ซึ่งสามารถเขียนได้ทั้งจาก Shell Script, ภาษา Python, ภาษา Perl และภาษาอื่นๆ ที่เครื่อง Zabbix สามารถ execute ได้
   ซึ่งความคิดเป็นส่วนตัว การใช้งาน external script นั้นมีแนวทางการใช้งานดังนี้

  1. ข้อมูล Input กำหนด (ได้มาจากการสั่งจาก Zabbix ที่มี macros)
  2. การดำเนินการใน Script (จะดูรายละเอียดในตัวอย่างโปรแกรม)
  3. ผลที่ได้จากการตรวจสอบ return value โดยมีตัวเลขในการส่งผลดังนี้
    • ถ้า Return Response time ที่ได้จากการทำงาน ตั่งแต่ 0 เป็นในทางบวก นั่นหมายถึงระบบทำงานได้ (ขึ้นอยู่ว่าจะทำงานได้เร็วหรือช้า)
    • ถ้า Return เป็น -1 จะหมายถึงระบบทำงานไม่ได้/มีปัญหา

   สำหรับโปรแกรม script นั้น โดยปกติจะอยู่ที่ไดเร็กทอรี /etc/zabbix/externalscripts ซึ่งจากตัวอย่างการกำหนดใน Item ในส่วนของ Key มีรายละเอียดดังนี้

mssqlchk.py["{HOST.CONN}","{DBQUERY}","{DBUSER}","{DBPASS}","{DBNAME}"]

   การ mapping parameters

    • {HOST.CONN} <--> sys.argv[1]
    • {DBQUERY} <--> sys.argv[2]
    • {DBUSER} <--> sys.argv[3]
    • {DBPASS} <--> sys.argv[4]
    • {DBNAME} <--> sys.argv[5]


  • สร้างไฟล์ script ชื่อ mssqlchk.py (**ต้องกำหนด permission ใน OS  ให้ผู้ใช้งานชื่อ zabbix สามารถ execute ไฟล์นี้ได้, chown zabbix mssqlchk.py; chmod 500 mssqlchk.py **

และในไฟล์ สามารถเขียนโปรแกรมให้ทำงานได้ดังนี้ (ตัวอย่างภาษา Python)

#!/usr/bin/python
import pymssql #import module pymssql เพื่อ connection ไปยังฐานข้อมูล
          import sys #import module sys เพื่อรับ parameter จาก command line
import time  #import module time เพื่อใช้จับเวลา
try: #ขึ้นตอนคำสั่ง except 
   start = int(round(time.time() * 1000)) #ดูเวลาเริ่ม script
   db = pymssql.connect(sys.argv[1], sys.argv[3], sys.argv[4], sys.argv[1]) #connection to database
   cursor = db.cursor()
   sql = sys.argv[2] #คำสั่ง SQL
   cursor.execute(sql) #ทำการ Query database
   results = cursor.fetchall()
   db.close()
   end = int(round(time.time() * 1000)) #ดูเวลาจบการรัน script
   time = end-start #ให้ time=end-start แล้วส่งเป็นค่า time เวลาหน่วยเป็น ms
   print int(time)
except pymssql.OperationalError: #ถ้าเกิด Error หรือรัน Script ไม่ผ่านให้ส่ง -1
   print int(-1)

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


ตัวอย่าง script อื่นๆ
   Script สำหรับตรวจสอบ Website
#!/usr/bin/python
import sys  #import module sys เพื่อใช้รับข้อมูลจาก Parameter
import time  #import module time เพื่อใช้นับเวลา
import urllib2  #import module urllib2 ใช้ในการเรียกค่าจากหน้าเว็บ
try: #ขึ้นตอนคำสั่ง except
   s = int(round(time.time() * 1000))  #ดูเวลาเริ่ม script
   url = sys.argv[1] #รับค่าจาก parameter ที่1 เข้าตัวแปร url
   response = urllib2.urlopen(url) #เปิดหน้าเว็บ
   webContent = response.read() #อ่านค่าจะหน้าเว็บ
   e = int(round(time.time() * 1000)) #ดูเวลาจบการรัน script
   find = webContent.find(sys.argv[2]) #ค้นหา คำตาม Key ที่ใส่มาใน Parameter ที่ 2
   if  find < 0: #ถ้าคนหาได้ น้อยกว่า 0 คำ ให้ส่งเป็น -1
           t = -1
           print int(t)
   else: #นอกนั้นให้ t=e-s แล้วส่งเป็นค่า t เวลาหน่วยเป็น ms
           t = e-s
           print int(t)
except urllib2.URLError: #ถ้าเกิด Error หรือรัน Script ไม่ผ่านให้ส่ง -1
   print int(-1)


   Script สำหรับตรวจสอบ DNS
#!/usr/bin/python
import time  #import module time เพื่อใช้นับเวลา
import sys
import socket #import module socket ตรวจสอบ DNS
start = int(round(time.time()*1000)) #ดูเวลาเริ่ม script
name = sys.argv[1]  #ชื่อ DNS
try: #ขึ้นตอนคำสั่ง except
    host = socket.gethostbyname(name)  #ตรวจสอบชื่อ DNS ว่าเป็น IP อะไรถ้า DNS ทราบถือว่าใช้ได้
    end = int(round(time.time()*1000)) #ดูเวลาจบ script
    time = end-start #ให้ time=end-start แล้วส่งเป็นค่า time เวลาหน่วยเป็น ms
    print int(time)
except socket.gaierror, err: #ถ้าไม่สามารถถาม IP จาก DNS ได้จะเกิด socket.gaierror จะส่งค่าเป็น -1
    print int(-1)


   Script สำหรับตรวจสอบ Oracle
#!/usr/bin/python
import cx_Oracle #import module cx_Oracle เพื่อ connection ไปหา database
import sys
import time  #import module time เพื่อใช้นับเวลา
try: #ขึ้นตอนคำสั่ง except
   start = int(round(time.time() * 1000)) #ดูเวลาเริ่ม script
   connection = cx_Oracle.connect(sys.argv[1]) #connection string to database
   cursor = connection.cursor()
   sql = sys.argv[2] #คำสั่ง SQL
   cursor.execute(sql) #ทำการ Query database
   count = cursor.fetchall()
   connection.close()
   end = int(round(time.time() * 1000)) #ดูเวลาจบการรัน script
   time = end-start #ให้ time=end-start แล้วส่งเป็นค่า time เวลาหน่วยเป็น ms
   print int(time)
except pymssql.OperationalError: #ถ้าเกิด Error หรือรัน Script ไม่ผ่านให้ส่ง -1
   print int(-1)



   Script สำหรับตรวจสอบ LDAP
#!/usr/bin/perl
use Net::LDAP;
use Time::HiRes qw( gettimeofday tv_interval );
     
my $chkSuccess = 0;
my $ldapserver = "LDAPSERVERIP";
my $ldapversion = 2;
my $ldapuser = "cn=ldadm,o=test";
my $ldapbase = "uniqueId=lduser1,ou=local,deptName=it,o=users,o=TESTER";
my $ldappass = "pass123";
my $searchstring = "objectclass=*";
my @attribs = ('uniqueID');
sub LDAPsearch {
my ($ldap,$searchString,$attrs,$base) = @_;
my $result = $ldap->search ( base => "$base",
scope => "base",
filter => "$searchString",
attrs   =>  $attrs
);
}
my $t0 = [gettimeofday];
my $ldap = Net::LDAP->new ($ldapserver) or die ("-1\n");
$ldap->bind ($ldapuser, password => $ldappass, version => $ldapversion) or die ("-1\n");
my $search = LDAPsearch ($ldap, $searchstring, \@attribs, $ldapbase ) or die ("-1\n");
my @entries = $search->entries;
my ($uniqueID);

if (@entries) {
$uniqueID=$entries[0]->get_value('uniqueID');
if ($uniqueID=="lduser1") {
$chkSuccess = 1;
} else {
$chkSuccess = 0;
} } else {
$chkSuccess = 0;
}

$ldap->unbind;
my $elapsed = tv_interval ($t0, [gettimeofday]);
if($chkSuccess==1) {
        print $elapsed;
} else {
        print "-1";
}


Script สำหรับตรวจสอบ TACACS
#!/usr/bin/perl
use Net::TacacsPlus::Client;
use Net::TacacsPlus::Constants;
use Time::HiRes qw( gettimeofday tv_interval );
     
my $chkSuccess = 0;
my $tac = new Net::TacacsPlus::Client(
        host => 'TACACSSERVERIP',
        key => 'tacacskey');
     
my $t0 = [gettimeofday];
if ($tac->authenticate('tuser1', 'tuser1passwd', TAC_PLUS_AUTHEN_TYPE_PAP)){                

        #print "Authentication successful.\n";                                
        $chkSuccess = 1;
} else {                                                  
        #print "Authentication failed: ".$tac->errmsg()."\n";      
        $chkSuccess = 0;
}                                                        
my @args = ('service=junos-exec', 'local-user-name=staff');
my @args_response;
if($tac->authorize('tuser1', \@args, \@args_response))
{
        #print "Authorization successful.\n";
        #print "Arguments received from server:\n";
        #print join("\n", @args_response);
        $chkSuccess = 1;
} else {
        #print "Authorization failed: " . $tac->errmsg() . "\n";
        $chkSuccess = 0;
}
my $elapsed = tv_interval ($t0, [gettimeofday]);
if($chkSuccess==1) {
        print $elapsed;
} else {
        print "-1";
}


Script สำหรับตรวจสอบ Radius
#!/usr/bin/perl
use Authen::Radius;
use Time::HiRes qw( gettimeofday tv_interval );
     
my $chkSuccess = 0;
my $host = "RADUISSERVERIP";
my $port = 1812;
my $username = "ruser1";
my $password = "ruser1passwd";
my $secret = "secret";
my $nas = "192.168.99.100";
my $timeout = 5;
my $t0 = [gettimeofday];
$host = "$host:$port" if $port;
if (!(my $radius = Authen::Radius->new(Host => $host, Secret => $secret, TimeOut => $timeout))){
    my $err = "Could not connect to $host";
    $err .= ": " . Authen::Radius::strerror if (Authen::Radius::strerror);
    print $err, "\n";
    $status = &set_status(0);
}else{
    my $answer = $radius->check_pwd($username, $password, $nas);
$status = &set_status($answer);
print $status;
}
my $elapsed = tv_interval ($t0, [gettimeofday]);
if($chkSuccess==1) {
        print $elapsed;
} else {
        print "-1";
}
sub set_status {
    my $res = shift;
    my $status;
    if ($res) {
$status = "OK";
    }else {
$status = "CRITICAL";
    }
    print "$status\n";
    return($status);
}

Share:

How to monitoring tcp port on zabbix

Zabbix นั้นเป็น Monitoring ที่สามารถ Monitor ได้เกือบทุกอุปกกรณ์ไม่ว่าจะเป็น Server Switch หรือแม้กระทั้งอุปกรณ์ต่างๆที่ทำงานอยู่บนเครือข่ายเราก็สามารถใช้ Zabbix Monitor ได้ วันนี้ผมจะมาแนะนำวิธีการ Monitor tcp port โดยใช้ Zabbix ต้องบอกก่อนว่า Service บางตัวบน Linux นั้นสามารถกำหนดได้หลายๆ Port อย่างเช่น Nginx เป็นต้นซึ่งในบางสถานการณ์ Service อาจจะยังมีสถานะ On อยู่แต่ Port บาง Port ได้ Down ไปแล้วซึ่งเราไม่สามารถรู้ได้เลยถ้าหากเราไม่ได้ Monitor Port ไว้

1. เข้าไปหน้า Configuration > Host > Item  จากนั้นให้สร้าง Item ใหม่





2. ตั้งค่าต่างๆในหน้าสร้าง Item



ให้สังเกตุตรงที่หัวข้อ Key ให้เรากดที่ Select เพื่อเลือก Parameter ที่เราจะนำมาใช้ Monitor ซึ่ง Parameter ที่เราจะนำมาใช้ Monitor port tcp นั้นก็คือ  net.tcp.listen[port]










เมื่อเลือก Parameter เสร็จแล้วให้มาใส่ Port ที่ต้องการจะ Monitor ตามตัวอย่างดังภาพ









หลังจากนั้นก็กด Add ได้เลย เมื่อเราได้สร้าง Item เสร็จแล้วหลังจากนั้นให้เรามาสร้าง Trigger ด้วยเพื่อที่จะได้มีการแจ้งเตือนเมื่อ Port นั้น Down ไป



3. ตรงหน้าสร้าง Trigger ให้ตั้งชื่อ Trigger และกำหนด Serverity ให้เรียบร้อยจากนั้นมาดูตรงหัวข้อ Expression  ให้เรากด Add เพื่อเลือก Item ที่เราสร้างไว้ก่อนหน้านี้












เมื่อกำหนดรายละเอียดครบหมดแล้วจากนั้นให้กด Add ได้เลย
ตัวอย่าง Trigger การแจ้งเตือนเมื่อ Port ที่เราตั้งค่าไว้ Down





Writen by system747


Share:

Auto Service Recovery for Windows OS with Remote Execute Command from Zabbix Agent


การ Monitor Host ปกติ หากเกิด Trigger Alarm ขึ้น Zabbix ก็แค่แสดง Alarm ให้เราดูว่าเกิดอะไรขึ้นเท่านั้น แต่เราสามารถทำให้ Zabbix ดำเนินการอะไรบางอย่าง(Action) กับ Trigger นั้น แบบ Automatic ได้ มีวิธีการดังนี้

1.Enable Remote Command ที่ Zabbix Agent โดยแก้ไข Parameter ดังนี้
EnableRemoteCommands=1  


  Restart Service Zabbix Agent
 

2.ที่ Trigger (หรือ Trigger Prototype) กำหนด tags เป็น {#SERVICE.NAME}

 


เมื่อเกิด Trigger จะใส่ Tags ให้ตามชื่อ Service Name

3.เข้าไปที่ Configuration > Actions > Event Source เลือก Triggers > Create Action
 
4.ใส่ Condition โดยกำหนด  Trigger ที่เราต้องการ
5.ไปที่ Tab Operation เลือก new > Operation Type เลือก Remote Command > Command กำหนดค่าเป็น C:\Windows\System32\net start {EVENT.TAGS}

จากนั้นกด Save

**Macro {EVENT.TAGS} คือ value ที่ได้รับมาจาก {#SERVICE.NAME}  ใน Trigger 

ทำการทดสอบโดย Stop firewall service บน Windows 

 
หลังจากนั้น  Action log บน Zabbix จะ แสดง Message Remote Execute แปลว่า Command ทำงานแล้ว
 
เมื่อกลับไปดูที่ firewall service จะเห็นว่า กลับมา start เหมือนเดิม
 

By   Sathienpong Khunin
Share:
 
Zabbix in Thailand
Facebook Group · 701 members
Join Group
กลุ่มนี้จัดตั้งขึ้นเพื่อแลกเปลี่ยนความรู้ของ zabbix ใครมีคู่มือ เทคนิค หรือ ปัญหา มาร่วมมือกันแก้ไขกันสำหรับชาวไทย -----------------------------------...
 

Popular

ค้นหาบล็อกนี้

Labels

Album (2) CentOS (6) database (3) Grafana (2) Sercurity (2) ubuntu (2) VDO (6) Windows Server (1) Zabbix-Host (11) Zabbix-Notify (1) Zabbix-Server (14)

Comments

Labels

Recent Posts