سلام! موږ خلکو ته روزنه ورکوو چې د لوی ډیټا سره کار وکړي. دا ناشونې ده چې د لوی ډیټا په اړه یو تعلیمي برنامه د خپل کلستر پرته تصور کړئ، چې ټول ګډونوال په ګډه کار کوي. د دې دلیل لپاره، زموږ برنامه تل دا لري 🙂 موږ د دې په ترتیب کولو ، تنظیم کولو او اداره کولو کې بوخت یو ، او هلکان په مستقیم ډول هلته د MapReduce دندې پیلوي او سپارک کاروي.
پدې پوسټ کې به موږ تاسو ته ووایو چې څنګه موږ د کلاوډ په کارولو سره زموږ د خپل آټوسکلر لیکلو سره د غیر مساوي کلستر بار کولو ستونزه حل کړه
ستونزه
زموږ کلستر په عادي حالت کې نه کارول کیږي. تصفیه خورا غیر مساوي ده. د مثال په توګه، عملي ټولګي شتون لري، کله چې ټول 30 کسان او یو ښوونکی کلستر ته لاړ شي او کارول یې پیل کړي. یا بیا، د نیټې څخه مخکې ورځې شتون لري کله چې بار خورا ډیریږي. پاتې وخت کلستر د انډرلوډ حالت کې کار کوي.
د حل # 1 دا دی چې یو کلستر وساتئ چې د لوړ بارونو سره مقاومت وکړي، مګر پاتې وخت به بې کاره وي.
د حل # 2 دا دی چې یو کوچنی کلستر وساتئ، کوم چې تاسو په لاسي ډول د ټولګیو څخه مخکې او د لوړ بارونو په وخت کې نوډونه اضافه کړئ.
د حل # 3 دا دی چې یو کوچنی کلستر وساتئ او یو آٹو سکیلر ولیکئ چې د کلستر اوسنی بار وڅاري او د مختلف APIs په کارولو سره له کلستر څخه نوډونه اضافه او لرې کړي.
پدې پوسټ کې به موږ د حل # 3 په اړه وغږیږو. دا آټوسکلر د داخلي فاکتورونو پرځای په بهرني فکتورونو پورې اړه لري ، او چمتو کونکي اکثرا دا نه وړاندې کوي. موږ د Mail.ru کلاوډ سولیوشن کلاوډ زیربنا کاروو او د MCS API په کارولو سره یو آټوسکلر لیکلی. او له هغه ځایه چې موږ د ډیټا سره کار کولو څرنګوالی ښوولی ، موږ پریکړه وکړه چې وښیو چې تاسو څنګه کولی شئ د خپلو موخو لپاره ورته آټوسکلر ولیکئ او د خپل کلاوډ سره یې وکاروئ.
اړتیاوې
لومړی، تاسو باید د هډوپ کلستر ولرئ. د مثال په توګه، موږ د HDP توزیع کاروو.
د دې لپاره چې ستاسو نوډونه په چټکۍ سره اضافه او لرې شي، تاسو باید د نوډونو ترمنځ د رولونو یو مشخص ویش ولرئ.
- ماسټر نوډ. ښه، په ځانګړې توګه د هیڅ شی تشریح کولو ته اړتیا نشته: د کلستر اصلي نوډ، په کوم کې، د بیلګې په توګه، سپارک ډرایور په لاره اچول شوی، که تاسو د متقابل حالت کاروئ.
- د نیټې نوډ. دا هغه نوډ دی چې تاسو یې په HDFS کې ډاټا ذخیره کوئ او چیرې چې حسابونه ترسره کیږي.
- د کمپیوټري نوډ. دا یو نوډ دی چیرې چې تاسو په HDFS کې هیڅ شی نه ذخیره کوئ ، مګر چیرې چې محاسبه کیږي.
مهم ټکی. اتوماتیک کول به د دریم ډول نوډونو له امله پیښ شي. که تاسو د دویم ډول نوډونو اخیستل او اضافه کول پیل کړئ، د غبرګون سرعت به خورا ټیټ وي - له منځه وړل او بیا تکرار کول به ستاسو په کلستر کې ساعتونه ونیسي. دا، البته، هغه څه ندي چې تاسو یې د اتوماتیک کولو څخه تمه لرئ. دا دی، موږ د لومړي او دویم ډول نوډونو ته لاس نه ورکوو. دوی به د لږترلږه ګټور کلستر استازیتوب وکړي چې د پروګرام په ټوله موده کې به شتون ولري.
نو، زموږ آټوسکلر په Python 3 کې لیکل شوی، د کلستر خدماتو اداره کولو لپاره Ambari API کاروي، کاروي
د حل جوړښت
- انډول
autoscaler.py
. دا درې ټولګي لري: 1) د امباري سره کار کولو لپاره فنکشنونه، 2) د MCS سره کار کولو لپاره فنکشنونه، 3) د آټوسکلر منطق سره مستقیم تړاو لري. - سکریپټ
observer.py
. په لازمي ډول دا مختلف مقررات لري: کله او په کومو شیبو کې د آټوسکلر فنکشن ته زنګ ووهئ. - د ترتیب فایل
config.py
. دا د مثال په توګه، د نوډونو لیست لري چې د اتوماتیک کولو او نورو پیرامیټونو لپاره اجازه لري چې اغیزه کوي، د بیلګې په توګه، د نوي نوډ اضافه کولو څخه څومره وخت انتظار کول. د ټولګیو د پیل لپاره مهال ویشونه هم شتون لري، ترڅو د ټولګي څخه مخکې د کلستر ډیری اجازه ورکړل شوي ترتیب پیل شي.
راځئ چې اوس د لومړي دوه فایلونو دننه د کوډ ټوټې وګورو.
1. Autoscaler.py ماډل
د امباري ټولګي
دا هغه څه دي چې د کوډ یوه ټوټه چې ټولګي لري داسې ښکاري Ambari
:
class Ambari:
def __init__(self, ambari_url, cluster_name, headers, auth):
self.ambari_url = ambari_url
self.cluster_name = cluster_name
self.headers = headers
self.auth = auth
def stop_all_services(self, hostname):
url = self.ambari_url + self.cluster_name + '/hosts/' + hostname + '/host_components/'
url2 = self.ambari_url + self.cluster_name + '/hosts/' + hostname
req0 = requests.get(url2, headers=self.headers, auth=self.auth)
services = req0.json()['host_components']
services_list = list(map(lambda x: x['HostRoles']['component_name'], services))
data = {
"RequestInfo": {
"context":"Stop All Host Components",
"operation_level": {
"level":"HOST",
"cluster_name": self.cluster_name,
"host_names": hostname
},
"query":"HostRoles/component_name.in({0})".format(",".join(services_list))
},
"Body": {
"HostRoles": {
"state":"INSTALLED"
}
}
}
req = requests.put(url, data=json.dumps(data), headers=self.headers, auth=self.auth)
if req.status_code in [200, 201, 202]:
message = 'Request accepted'
else:
message = req.status_code
return message
پورته، د مثال په توګه، تاسو کولی شئ د فعالیت تطبیق وګورئ stop_all_services
، کوم چې په مطلوب کلستر نوډ کې ټول خدمات ودروي.
ټولګي ته د ننوتلو په وخت کې Ambari
تاسو تېر شئ:
ambari_url
د مثال په توګه، لکه'http://localhost:8080/api/v1/clusters/'
,cluster_name
- په امباري کې ستاسو د کلستر نوم،headers = {'X-Requested-By': 'ambari'}
- او دننه
auth
دلته د امباري لپاره ستاسو ننوتل او پټنوم دی:auth = ('login', 'password')
.
فنکشن پخپله امباري ته د REST API له لارې د څو زنګونو څخه ډیر څه ندي. د منطقي نظر څخه، موږ لومړی په نوډ کې د چلولو خدماتو لیست ترلاسه کوو، او بیا په ورکړل شوي کلستر کې، په ورکړل شوي نوډ کې، د لیست څخه دولت ته د خدماتو لیږدولو غوښتنه کوو. INSTALLED
. د ټولو خدماتو پیل کولو لپاره دندې، دولت ته د نوډونو لیږدولو لپاره Maintenance
وغيره ورته ورته ښکاري - دا د API له لارې یوازې یو څو غوښتنې دي.
کلاس Mcs
دا هغه څه دي چې د کوډ یوه ټوټه چې ټولګي لري داسې ښکاري Mcs
:
class Mcs:
def __init__(self, id1, id2, password):
self.id1 = id1
self.id2 = id2
self.password = password
self.mcs_host = 'https://infra.mail.ru:8774/v2.1'
def vm_turn_on(self, hostname):
self.token = self.get_mcs_token()
host = self.hostname_to_vmname(hostname)
vm_id = self.get_vm_id(host)
mcs_url1 = self.mcs_host + '/servers/' + self.vm_id + '/action'
headers = {
'X-Auth-Token': '{0}'.format(self.token),
'Content-Type': 'application/json'
}
data = {'os-start' : 'null'}
mcs = requests.post(mcs_url1, data=json.dumps(data), headers=headers)
return mcs.status_code
ټولګي ته د ننوتلو په وخت کې Mcs
موږ د پروژې ID په کلاوډ کې دننه او د کارونکي ID او همدارنګه د هغه پټنوم پاس کوو. په فعالیت کې vm_turn_on
موږ غواړو چې یو له ماشینونو څخه فعال کړو. دلته منطق یو څه ډیر پیچلی دی. د کوډ په پیل کې، درې نورې دندې ویل کیږي: 1) موږ اړتیا لرو یو نښه ترلاسه کړو، 2) موږ اړتیا لرو چې کوربه نوم په MCS کې د ماشین په نوم بدل کړو، 3) د دې ماشین ID ترلاسه کړئ. بیا ، موږ په ساده ډول د پوسټ غوښتنه کوو او دا ماشین لانچ کوو.
دا هغه څه دي چې د نښه ترلاسه کولو فعالیت داسې ښکاري:
def get_mcs_token(self):
url = 'https://infra.mail.ru:35357/v3/auth/tokens?nocatalog'
headers = {'Content-Type': 'application/json'}
data = {
'auth': {
'identity': {
'methods': ['password'],
'password': {
'user': {
'id': self.id1,
'password': self.password
}
}
},
'scope': {
'project': {
'id': self.id2
}
}
}
}
params = (('nocatalog', ''),)
req = requests.post(url, data=json.dumps(data), headers=headers, params=params)
self.token = req.headers['X-Subject-Token']
return self.token
د Autoscaler ټولګي
دا ټولګي پخپله د عملیاتي منطق پورې اړوند دندې لري.
دا هغه څه دي چې د دې ټولګي لپاره د کوډ یوه برخه داسې ښکاري:
class Autoscaler:
def __init__(self, ambari, mcs, scaling_hosts, yarn_ram_per_node, yarn_cpu_per_node):
self.scaling_hosts = scaling_hosts
self.ambari = ambari
self.mcs = mcs
self.q_ram = deque()
self.q_cpu = deque()
self.num = 0
self.yarn_ram_per_node = yarn_ram_per_node
self.yarn_cpu_per_node = yarn_cpu_per_node
def scale_down(self, hostname):
flag1 = flag2 = flag3 = flag4 = flag5 = False
if hostname in self.scaling_hosts:
while True:
time.sleep(5)
status1 = self.ambari.decommission_nodemanager(hostname)
if status1 == 'Request accepted' or status1 == 500:
flag1 = True
logging.info('Decomission request accepted: {0}'.format(flag1))
break
while True:
time.sleep(5)
status3 = self.ambari.check_service(hostname, 'NODEMANAGER')
if status3 == 'INSTALLED':
flag3 = True
logging.info('Nodemaneger decommissioned: {0}'.format(flag3))
break
while True:
time.sleep(5)
status2 = self.ambari.maintenance_on(hostname)
if status2 == 'Request accepted' or status2 == 500:
flag2 = True
logging.info('Maintenance request accepted: {0}'.format(flag2))
break
while True:
time.sleep(5)
status4 = self.ambari.check_maintenance(hostname, 'NODEMANAGER')
if status4 == 'ON' or status4 == 'IMPLIED_FROM_HOST':
flag4 = True
self.ambari.stop_all_services(hostname)
logging.info('Maintenance is on: {0}'.format(flag4))
logging.info('Stopping services')
break
time.sleep(90)
status5 = self.mcs.vm_turn_off(hostname)
while True:
time.sleep(5)
status5 = self.mcs.get_vm_info(hostname)['server']['status']
if status5 == 'SHUTOFF':
flag5 = True
logging.info('VM is turned off: {0}'.format(flag5))
break
if flag1 and flag2 and flag3 and flag4 and flag5:
message = 'Success'
logging.info('Scale-down finished')
logging.info('Cooldown period has started. Wait for several minutes')
return message
موږ د ننوتلو لپاره ټولګي منو. Ambari
и Mcs
، د نوډونو لیست چې د اندازه کولو لپاره اجازه لري، او همدارنګه د نوډ ترتیب کولو پیرامیټونه: حافظه او cpu په YARN کې نوډ ته تخصیص شوي. دلته 2 داخلي پیرامیټونه q_ram، q_cpu هم شتون لري، کوم چې قطارونه دي. د دوی په کارولو سره، موږ د اوسني کلستر بار ارزښتونه ذخیره کوو. که موږ وګورو چې په تیرو 5 دقیقو کې په دوامداره توګه ډیر شوی بار شتون لري ، نو موږ پریکړه کوو چې موږ اړتیا لرو په کلستر کې +1 نوډ اضافه کړو. ورته د کلستر د کم استعمال حالت لپاره ریښتیا ده.
پورته کوډ د یو فنکشن مثال دی چې ماشین له کلستر څخه لیرې کوي او په بادل کې یې ودروي. لومړی دلته یو له منځه وړل دی YARN Nodemanager
، بیا موډ فعالیږي Maintenance
، بیا موږ په ماشین کې ټول خدمات ودروو او په بادل کې مجازی ماشین بند کړو.
2. سکریپټ څارونکي.py
له دې ځایه کوډ نمونه:
if scaler.assert_up(config.scale_up_thresholds) == True:
hostname = cloud.get_vm_to_up(config.scaling_hosts)
if hostname != None:
status1 = scaler.scale_up(hostname)
if status1 == 'Success':
text = {"text": "{0} has been successfully scaled-up".format(hostname)}
post = {"text": "{0}".format(text)}
json_data = json.dumps(post)
req = requests.post(webhook, data=json_data.encode('ascii'), headers={'Content-Type': 'application/json'})
time.sleep(config.cooldown_period*60)
په دې کې، موږ ګورو چې ایا د کلستر ظرفیت لوړولو لپاره شرایط رامینځته شوي او ایا په ذخیره کې کوم ماشینونه شتون لري، د دوی څخه یو کوربه نوم ترلاسه کړئ، په کلستر کې یې اضافه کړئ او زموږ د ټیم سلیک کې یې په اړه پیغام خپور کړئ. له هغې وروسته پیل کیږي cooldown_period
، کله چې موږ له کلستر څخه هیڅ شی نه اضافه کوو یا لرې کوو ، مګر په ساده ډول د بار څارنه کوو. که دا ثبات ولري او د غوره بار ارزښتونو دهلیز کې وي، نو موږ په ساده ډول څارنې ته دوام ورکوو. که یو نوډ کافی نه و، نو موږ یو بل اضافه کړو.
د هغو قضیو لپاره چې موږ مخکې درس لرو، موږ دمخه په ډاډه توګه پوهیږو چې یو نوډ به کافي نه وي، نو موږ سمدلاسه ټول وړیا نوډونه پیل کوو او د لوست تر پای پورې یې فعال وساتو. دا د فعالیت مهال ویشونو لیست په کارولو سره پیښیږي.
پایلې
Autoscaler د هغو قضیو لپاره یو ښه او مناسب حل دی کله چې تاسو د غیر مساوي کلستر بار کولو تجربه کوئ. تاسو په ورته وخت کې د لوړ بارونو لپاره مطلوب کلستر ترتیب ترلاسه کوئ او په ورته وخت کې دا کلستر د انډرلوډ پرمهال مه ساتئ، پیسې خوندي کړئ. ښه، دا ټول ستاسو د ګډون پرته په اتوماتيک ډول پیښیږي. آټوسکلر پخپله د کلستر مدیر API او د کلاوډ چمتو کونکي API ته د غوښتنو له یوې سیټ پرته نور څه ندي ، د یو ځانګړي منطق سره سم لیکل شوي. هغه څه چې تاسو حتما په یاد ولرئ د نوډونو ویش په 3 ډولونو کې دی ، لکه څنګه چې موږ دمخه لیکلي. او تاسو به خوشحاله شئ.
سرچینه: www.habr.com