வணக்கம்! பெரிய தரவுகளுடன் பணிபுரிய மக்களுக்கு நாங்கள் பயிற்சி அளிக்கிறோம். அதன் சொந்த கிளஸ்டர் இல்லாமல் பெரிய தரவுகளில் ஒரு கல்வித் திட்டத்தை கற்பனை செய்வது சாத்தியமில்லை, அதில் பங்கேற்பாளர்கள் அனைவரும் ஒன்றாக வேலை செய்கிறார்கள். இந்த காரணத்திற்காக, எங்கள் நிரல் எப்போதும் அதை கொண்டுள்ளது :) நாங்கள் அதன் கட்டமைப்பு, ட்யூனிங் மற்றும் நிர்வாகம் ஈடுபட்டுள்ளோம், மற்றும் தோழர்களே நேரடியாக MapReduce வேலைகளை அங்கு தொடங்க மற்றும் Spark பயன்படுத்த.
இந்த இடுகையில், மேகத்தைப் பயன்படுத்தி எங்கள் சொந்த ஆட்டோஸ்கேலரை எழுதுவதன் மூலம் சீரற்ற கிளஸ்டர் ஏற்றுதல் சிக்கலை எவ்வாறு தீர்த்தோம் என்பதை நாங்கள் உங்களுக்குக் கூறுவோம்.
பிரச்சனை
எங்கள் கிளஸ்டர் வழக்கமான முறையில் பயன்படுத்தப்படவில்லை. அகற்றுவது மிகவும் சீரற்றது. எடுத்துக்காட்டாக, நடைமுறை வகுப்புகள் உள்ளன, 30 பேரும் ஒரு ஆசிரியரும் கிளஸ்டருக்குச் சென்று அதைப் பயன்படுத்தத் தொடங்கும் போது. அல்லது மீண்டும், சுமை அதிகமாக அதிகரிக்கும் போது காலக்கெடுவிற்கு முந்தைய நாட்கள் உள்ளன. மீதமுள்ள நேரத்தில் கிளஸ்டர் அண்டர்லோட் முறையில் செயல்படுகிறது.
தீர்வு #1 உச்ச சுமைகளைத் தாங்கும் ஒரு கிளஸ்டரை வைத்திருப்பது, ஆனால் மீதமுள்ள நேரத்தில் செயலற்றதாக இருக்கும்.
தீர்வு #2 ஒரு சிறிய கிளஸ்டரை வைத்திருப்பது, இதில் நீங்கள் வகுப்புகளுக்கு முன் மற்றும் உச்ச சுமைகளின் போது கைமுறையாக முனைகளைச் சேர்க்கலாம்.
தீர்வு #3 என்பது ஒரு சிறிய கிளஸ்டரை வைத்து, கிளஸ்டரின் தற்போதைய சுமையைக் கண்காணிக்கும் ஒரு ஆட்டோஸ்கேலரை எழுதுவது மற்றும் பல்வேறு APIகளைப் பயன்படுத்தி, கிளஸ்டரிலிருந்து முனைகளைச் சேர்த்து அகற்றுவது.
இந்த இடுகையில் தீர்வு எண் 3 பற்றி பேசுவோம். இந்த ஆட்டோஸ்கேலர் உள் காரணிகளை விட வெளிப்புற காரணிகளை அதிகம் சார்ந்துள்ளது, மேலும் வழங்குநர்கள் பெரும்பாலும் அதை வழங்குவதில்லை. நாங்கள் Mail.ru Cloud Solutions கிளவுட் உள்கட்டமைப்பைப் பயன்படுத்துகிறோம் மற்றும் MCS API ஐப் பயன்படுத்தி ஒரு ஆட்டோஸ்கேலரை எழுதுகிறோம். தரவுகளுடன் எவ்வாறு செயல்படுவது என்பதை நாங்கள் கற்பிப்பதால், உங்கள் சொந்த நோக்கங்களுக்காக இதேபோன்ற ஆட்டோஸ்கேலரை எவ்வாறு எழுதலாம் மற்றும் அதை உங்கள் மேகக்கணியில் எவ்வாறு பயன்படுத்தலாம் என்பதைக் காட்ட முடிவு செய்தோம்.
முன்நிபந்தனைகள்
முதலில், உங்களிடம் ஒரு ஹடூப் கிளஸ்டர் இருக்க வேண்டும். எடுத்துக்காட்டாக, HDP விநியோகத்தைப் பயன்படுத்துகிறோம்.
உங்கள் கணுக்கள் விரைவாகச் சேர்க்கப்படுவதற்கும் அகற்றப்படுவதற்கும், நீங்கள் முனைகளுக்கு இடையே ஒரு குறிப்பிட்ட பங்களிப்பைக் கொண்டிருக்க வேண்டும்.
- முதன்மை முனை. சரி, இங்கே விளக்க வேண்டிய அவசியம் எதுவும் இல்லை: கிளஸ்டரின் முக்கிய முனை, எடுத்துக்காட்டாக, நீங்கள் ஊடாடும் பயன்முறையைப் பயன்படுத்தினால், ஸ்பார்க் இயக்கி தொடங்கப்படும்.
- தேதி முனை. இது HDFS இல் நீங்கள் தரவைச் சேமிக்கும் முனை மற்றும் கணக்கீடுகள் நடைபெறும் இடமாகும்.
- கம்ப்யூட்டிங் முனை. இது HDFS இல் நீங்கள் எதையும் சேமிக்காத ஒரு முனையாகும், ஆனால் அங்கு கணக்கீடுகள் நடக்கும்.
முக்கியமான புள்ளி. மூன்றாம் வகை முனைகளின் காரணமாக ஆட்டோஸ்கேலிங் ஏற்படும். நீங்கள் இரண்டாவது வகையின் முனைகளை எடுத்து சேர்க்கத் தொடங்கினால், மறுமொழி வேகம் மிகக் குறைவாக இருக்கும் - நீக்குதல் மற்றும் மறுபரிசீலனை செய்வதற்கு உங்கள் கிளஸ்டரில் மணிநேரம் எடுக்கும். இது நிச்சயமாக, ஆட்டோஸ்கேலிங்கில் இருந்து நீங்கள் எதிர்பார்ப்பது அல்ல. அதாவது, முதல் மற்றும் இரண்டாவது வகைகளின் முனைகளைத் தொடுவதில்லை. அவை நிரலின் காலம் முழுவதும் இருக்கும் குறைந்தபட்ச சாத்தியமான கிளஸ்டரைக் குறிக்கும்.
எனவே, எங்கள் ஆட்டோஸ்கேலர் பைதான் 3 இல் எழுதப்பட்டுள்ளது, கிளஸ்டர் சேவைகளை நிர்வகிக்க அம்பாரி 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
மேகக்கணிக்குள் திட்ட ஐடி மற்றும் பயனர் ஐடி மற்றும் அவரது கடவுச்சொல்லை அனுப்புகிறோம். செயல்பாட்டில் vm_turn_on
இயந்திரங்களில் ஒன்றை இயக்க விரும்புகிறோம். இங்கே தர்க்கம் இன்னும் கொஞ்சம் சிக்கலானது. குறியீட்டின் தொடக்கத்தில், மற்ற மூன்று செயல்பாடுகள் அழைக்கப்படுகின்றன: 1) நாம் ஒரு டோக்கனைப் பெற வேண்டும், 2) ஹோஸ்ட்பெயரை MCS இல் இயந்திரத்தின் பெயராக மாற்ற வேண்டும், 3) இந்த இயந்திரத்தின் ஐடியைப் பெறுங்கள். அடுத்து, நாங்கள் ஒரு இடுகை கோரிக்கையை உருவாக்கி இந்த இயந்திரத்தை தொடங்குகிறோம்.
டோக்கனைப் பெறுவதற்கான செயல்பாடு இதுபோல் தெரிகிறது:
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
ஆட்டோஸ்கேலர் வகுப்பு
இந்த வகுப்பில் இயங்கு தர்க்கம் தொடர்பான செயல்பாடுகள் உள்ளன.
இந்த வகுப்பிற்கான குறியீட்டின் ஒரு பகுதி இப்படி இருக்கும்:
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 இல் உள்ள முனைக்கு ஒதுக்கப்பட்டது. q_ram, q_cpu ஆகிய 2 உள் அளவுருக்களும் உள்ளன, அவை வரிசைகளாகும். அவற்றைப் பயன்படுத்தி, தற்போதைய கிளஸ்டர் சுமையின் மதிப்புகளை நாங்கள் சேமிக்கிறோம். கடந்த 5 நிமிடங்களில் தொடர்ந்து ஏற்றம் அதிகரித்திருப்பதைக் கண்டால், கிளஸ்டரில் +1 முனையைச் சேர்க்க வேண்டும் என்று முடிவு செய்கிறோம். க்ளஸ்டர் குறைவான பயன்பாட்டு நிலைக்கும் இதுவே உண்மை.
மேலே உள்ள குறியீடு, கிளஸ்டரிலிருந்து ஒரு இயந்திரத்தை அகற்றி அதை மேகக்கணியில் நிறுத்தும் செயல்பாட்டின் ஒரு எடுத்துக்காட்டு. முதலில் ஒரு பணிநீக்கம் உள்ளது YARN Nodemanager
, பின்னர் பயன்முறை இயக்கப்படும் Maintenance
, பின்னர் கணினியில் அனைத்து சேவைகளையும் நிறுத்திவிட்டு, மேகக்கணியில் உள்ள மெய்நிகர் இயந்திரத்தை அணைக்கிறோம்.
2. Script observer.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
, க்ளஸ்டரில் இருந்து எதையும் சேர்க்கவோ அல்லது அகற்றவோ செய்யாமல், சுமையைக் கண்காணிக்கும் போது. அது நிலைப்படுத்தப்பட்டு, உகந்த சுமை மதிப்புகளின் தாழ்வாரத்திற்குள் இருந்தால், நாங்கள் தொடர்ந்து கண்காணிப்போம். ஒரு முனை போதுமானதாக இல்லாவிட்டால், இன்னொன்றைச் சேர்க்கிறோம்.
எங்களிடம் பாடம் இருக்கும் சந்தர்ப்பங்களில், ஒரு முனை போதுமானதாக இருக்காது என்பதை நாங்கள் ஏற்கனவே அறிந்திருக்கிறோம், எனவே உடனடியாக அனைத்து இலவச முனைகளையும் தொடங்கி, பாடம் முடியும் வரை அவற்றை செயலில் வைத்திருக்கிறோம். செயல்பாட்டு நேர முத்திரைகளின் பட்டியலைப் பயன்படுத்தி இது நிகழ்கிறது.
முடிவுக்கு
நீங்கள் சீரற்ற கிளஸ்டர் ஏற்றுதலை அனுபவிக்கும் போது, ஆட்டோஸ்கேலர் ஒரு நல்ல மற்றும் வசதியான தீர்வாகும். நீங்கள் ஒரே நேரத்தில் உச்ச சுமைகளுக்கு தேவையான கிளஸ்டர் உள்ளமைவை அடைவீர்கள், அதே நேரத்தில் இந்த கிளஸ்டரை குறைந்த சுமையின் போது வைத்திருக்க வேண்டாம், பணத்தை மிச்சப்படுத்துங்கள். சரி, உங்கள் பங்களிப்பு இல்லாமல் இவை அனைத்தும் தானாகவே நடக்கும். ஆட்டோஸ்கேலர் என்பது ஒரு குறிப்பிட்ட தர்க்கத்தின்படி எழுதப்பட்ட கிளஸ்டர் மேலாளர் API மற்றும் கிளவுட் வழங்குநர் APIக்கான கோரிக்கைகளின் தொகுப்பைத் தவிர வேறில்லை. நீங்கள் நிச்சயமாக நினைவில் கொள்ள வேண்டியது என்னவென்றால், நாங்கள் முன்பு எழுதியது போல, முனைகளை 3 வகைகளாகப் பிரிப்பது. மேலும் நீங்கள் மகிழ்ச்சியாக இருப்பீர்கள்.
ஆதாரம்: www.habr.com