Ansible Connection Check

June 5 2019

အသိတစ်ယောက်က သူတို့ လုပ်နေကြတဲ့ project တစ်ခုမှာ Ansible သုံးပြီး Server တွေ Deploy လုပ်ရင်းကြုံရတာလေးတစ်ခုပြောပြတယ်။ Server လေး၊ ငါးလုံးက တစ်ခုနဲ့တစ်ခု အပြန်အလှန်တွေ ချိပ်ဆက်အလုပ်လုပ်ရတာဖြစ်ပြီး connection တိုင်းက Firewall ကိုဖြတ်သွားရတဲ့အတွက် ဘယ် Server ကနေ ဘယ် Server ရဲ့ ဘယ် Port ကိုပဲ Access လုပ်လို့ရမယ်ဆိုတဲ့ Rules တွေနဲ့ကန့်သတ်ထားတွေရှိနေတာပါ။ အဲ့ဒီအတွက် Scale out အနေနဲ့ Node အသစ်တိုးတဲ့အခါတိုင်း တိုးမယ့် Server ကို သက်ဆိုင်ရာ အခြား Server တွေကနေ Access လုပ်လို့ရမရဆိုတာမျိုးကို ကြိုစစ်ပြီးမှ service deploy လုပ်ဖို့လိုတဲ့အခြေအနေမျိုးပါ။ လေ့လာရသလောက် Ansible မှာက service run ထားပြီးအခြေအနေမှာမှ Reachable ဖြစ်မဖြစ်ကို wait_for module သုံးပြီးစစ်ကြတာများပါတယ်။ နောက်ထပ်နည်းလမ်းကတော့ shell module သုံးပြီး netcat command နဲ့ socket တစ်ခုဖွင့်ပြီး wait_for နဲ့ စစ်ကြည့်တာမျိုးတွေလည်း တွေ့ရပါတယ်။

ပထမနည်းလမ်းကတော့ သူတို့ရဲ့ Deployment ပုံစံနဲ့မကိုက်ညီပါဘူး။ Firewall က လိုအပ်တဲ့ IP နဲ့ Port ကိုဖွင့်ပေးထားပြီးတာသေချာမှ Deployment ကိုလုပ်မှာဖြစ်တဲ့အတွက်ကြောင့်ပါ။ Deployment မပြီးသေးတဲ့အတွက် Service က run နေမှာမဟုတ်သလို Service ရဲ့ Port ကိုလည်း wait_for နဲ့လှမ်းစစ်ကြည့်လို့မရပါဘူး။

ဒုတိယနည်းလမ်းကတော့ Service ရဲ့ Port နံပါတ်အတိုင်း netcat နဲ့ socket တစ်ခုလုပ်ပြီး Listen လုပ်ခိုင်းတာဖြစ်တဲ့အတွက် တကယ့် Service မ run သေးပဲ wait_for နဲ့ စစ်လို့ရပါတယ်။ သို့ပေမဲ့ အဲ့ဒီ Server ထဲမှာ netcat install လုပ်ထားဖို့လိုပါတယ်။ ဒါမှသာ Ansible က shell command အနေနဲ့ netcat ကိုလှမ်း run လို့ရမှာပါ။ ဒီလို Connection စစ်တာလေး တစ်ခုအတွက်လောက်နဲ့ package တွေထပ် install လုပ်နေရတာကလည်း သဘာဝသိပ်မကျပြန်ပါဘူး။ ဒါကြောင့် Ansible နဲ့တင်အဆင်ပြေအောင် Module လေးတစ်ခု စမ်းရေးကြည့်ဖို့ စိတ်ကူးရသွားတယ်။

အဓိကက တကယ့် Service မ run ခင် Server ပေါ်မှာ ဘာ package မှထပ်မတင်ပဲ run မယ့် Service ရဲ့ Port ကိုသုံးပြီး connection ချိပ်လို့ရမရကို စမ်းဖို့ပါ။ အဲ့ဒီအတွက် Python နဲ့ Socket တစ်ခုလုပ်ပေးနိုင်မယ့် Module တစ်ခုရေးကြည့်လိုက်တယ်။ listen လို့နာမည်ပေးထားပြီး Port နံပါတ်တစ်ခုကိုပဲ Argument အနေနဲ့ထည့်သွင်းပေးခိုင်းထားပါတယ်။

ဒါပေမဲ့ Ansible ရဲ့ ထုံးစံက ပုံမှန်အတိုင်းဆိုရင် run ခိုင်းလိုက်တဲ့ task ရဲ့ Module က success ဖြစ်လား fail ဖြစ်လားဆိုတဲ့ status ကို အဲဒီ Module ရဲ့ လုပ်ဆောင်ချက် ပြီးသွားတဲ့အချိန်မှာမှ သိရပြီး နောက် task ကိုဆက်သွား၊ မသွား ဆုံးဖြတ်တာပါ။ အခုရေးထားတဲ့ listen.py Module ကလည်း သတ်မှတ်ပေးလိုက်တဲ့ Port နဲ့ Listen လုပ်နေမှာဖြစ်တဲ့အတွက် အခြား Host ကနေ client connection တစ်ခုအနေနဲ့ လာချိပ်လို့အဆင်ပြေတယ်ဆိုမှ အဲ့ဒီ Module ရဲ့ လုပ်ဆောင်ချက် ရပ်သွားပြီး နောက် task တစ်ခုကိုဆက်သွားမှာပါ။ ဒါကြောင့် listen Module ကိုသုံးတဲ့အခါ async နဲ့တွဲသုံးမှဆင်ပြပါလိမ့်မယ်။

နမူနာ playbook မှာမြင်ရတဲ့အတိုင်း servera ပေါ်မှာ task ၂ခု run ထားပါတယ်။ servera အနေနဲ့ serverb မှာ run နေမယ့် service ရဲ့ Port - 8888 ကိုချိပ်လို့ရမရစစ်ချင်တာပါ။ ဒါကြောင့် ပထမ task အနေနဲ့ serverb ပေါ်မှာ တကယ့် service မ run ရသေးတဲ့အတွက် listen Module ကိုသုံးပြီး 8888 နဲ့ listen လုပ်ခိုင်းလိုက်ပါတယ်။ ဒါပေမဲ့ async နဲ့ poll သာမသုံးဘူးဆိုရင် အဲဒီ task မှာတင်ရပ်နေပြီး နောက် task ကိုဆက်သွားမှာမဟုတ်ပါဘူး။ နောက်ကွယ်မှာ run ခိုင်းထားပြီး နောက် task တစ်ခုကိုဆက်သွားစေချင်တဲ့အတွက် async နဲ့ poll ကိုထည့်သုံးလိုက်တာပါ။

ဒုတိယ task မှာကတော့ ပထမ task ကနေ listen လုပ်ခိုင်းထားတဲ့ serverb ရဲ့ Port 8888 ကို wait_for Module သုံးပြီး servera ကနေ လှမ်းပြီး connect လုပ်ကြည့်ခိုင်းလိုက်တာပါ။ serverb ပေါ်မှာ 8888 နဲ့ listen လုပ်နေပြီးသားဖြစ်တဲ့အတွက် အကယ်၍များ ဒီ task သာ Fail ဖြစ်ခဲ့ရင် Firewall ဒါမှမဟုတ် Network ပြဿနာတစ်ခုခုကြောင့် ချိပ်မရတာဆိုတာမျိုး အကြမ်းပျဉ်း သုံးသပ်လို့ရသွားမှာပါ။

Module လေးတစ်ခုစမ်းရေးကြည့်ချင်တာကြောင့် ဒီနည်းလမ်းကိုသုံးလိုက်တာဖြစ်တဲ့အတွက် ဒီထက်ပိုကောင်းတဲ့နည်းလမ်းလဲ ရှိနိုင်ပါသေးတယ်။ လေ့လာကြည့်ပြီး ဆွေးနွေး အကြံပေးနိုင်ပါတယ်။

Download Sample Playbook: connection_check.tgz


comments powered by Disqus