Salve! Nos homines ad operandum magnis data exercemus. Impossibile est imaginari programmatum scholasticum in magnis data notitia sine suo botro, in quo omnes participes simul cooperantur. Quam ob rem progressio noster semper eam habet Nos in eius configuratione, tuning et administratione versamur, et guys MapReduce jobs illic directe deducunt et scintilla utuntur.
In hac posta narrabimus tibi quomodo problema de inaequale botri oneratum solvimus scribendo nostro autoschali utendo nube.
quaestio
Botrus noster in typico modo non est usus. Dispositio valde inaequabilis. Exempli gratia, sunt classes practicae, cum omnes XXX homines et magister vadunt ad botrum et committitur utendo. Vel iterum sunt dies ante fatalibus cum onus multum crescit. Reliquum temporis botrus operatur in modus underload.
Solutio #1 est botrum servare qui apicem onerum sustinebit, sed reliquum temporis erit otiosum.
Solutio #2 est serva botrum parvum, cui manually nodos ante classes et in cacumine sarcinas addis.
Solutio #3 est botrum servare et scribe autoscalarium qui monetam oneris botri monebit et, variis APIs utens, nodos ex botro adiciet et removebit.
In hac posta de solutione loquemur. Hic autoscaler a factoribus externis magis quam internis valde pendet, et provisores saepe id non praebent. Utimur in Mail.ru Solutiones Nubes infrastructurae nubem et autoscalem scripserunt utentes MCS API. Et quoniam docemus quomodo operandum cum notitia, decrevimus ostendere quomodo simile autoscaler ad proposita tua scribere possis, et cum tua nube utere.
DE PRAEREQUISITIS
Primum, habebis botrum Hadoop. Exempli gratia, distributione HDP utimur.
Ut nodos tuos cito adiiciantur et tollantur, necesse est ut certam distributionem munerum inter nodos habeas.
- Magister nodi. Bene, nihil opus est singulas res explicare: principalis nodi botri, in quo, exempli gratia, scintilla agitator emittitur, si modo interactive uteris.
- Date node. Hic est nodi, in quo repones notitias in HDFS et ubi calculi fiunt.
- Nodus computans. Nodus hic est ubi tu nihil in HDFS condis, sed ubi calculi fiunt.
Clarus locus. Occurret autoscaling ex nodis tertii generis. Si initium sumere ac addere nodis secundi generis, celeritas responsionis valde gravis erit - decommissionis et remittendi horas in botro tuo accipiet. Quod quidem ex autoscaling non exspectas. Id est, primae et secundae specierum nodos non attingimus. Minimum viable botrum repraesentabunt, qui per durationem programmatis existet.
Itaque noster autoscaler in Pythone 3 scribitur, Ambari API ad officia botri administranda, usus
Solutio architecturae
- OMNIBUS
autoscaler.py
. Tria genera continet: 1) munera ad operandum cum Ambari, 2) munera ad operandum cum MCS, 3) munera directe ad logicam autoscaler pertinentia. - Script
observer.py
. Per se consistit in diversis regulis: quando et quibus momentis functiones autoscales appellamus. - Configurationis file
config.py
. Continet, exempli gratia, index nodis permissos pro autoscaling et alios parametros, qui afficiunt, exempli gratia, quousque exspectandum sit a momento, novus nodi additus est. Sunt etiam indicationes in initio classium, ita ut ante genus maximum permittitur figura botri emissa.
Nunc inspiciamus fragmenta codicis in duobus primis fasciculis.
1. Autoscaler.py moduli
Ambari classis
Hoc est fragmen codice continentur in genere similis 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
Superius, ut exemplum, exsecutionem muneris intueri potes stop_all_services
qui sistit in optato nodo muneris omnes.
In faucibus in class Ambari
transibis;
ambari_url
exempli gratia, sicut'http://localhost:8080/api/v1/clusters/'
,cluster_name
nomen botri in Ambari.headers = {'X-Requested-By': 'ambari'}
- et intus
auth
Hic est username et password pro Ambari:auth = ('login', 'password')
.
Munus ipsum nihil aliud est quam duo vocat via CAETERA API Ambari. Secundum rationem logicam, primum album cursus officiorum in nodo accipimus, et deinde dato nodo datam botrum petimus ut operas e indice in rem publicam transferamus. INSTALLED
. Munera pro omnibus officiis deducendis, nodis transferendis in statum Maintenance
etc. vide similes — paucae petitiones per API sunt.
Classis Mcs
Hoc est fragmen codice continentur in genere similis 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
In faucibus in class Mcs
Project id intra nubem et id utentis transimus, necnon tesseram eius. In munus vm_turn_on
in unam machinis converti volumus. Dialectica hic paulo est multiplex. In initio codicis tria alia munera vocantur: 1) signum acquirere, 2) nomen hostname in nomen machinae in MCS convertere, 3) id machinae obtinere. Deinde simpliciter postulationem facimus et hanc machinam deducimus.
Hoc est quod munus obtinendi signum similis est;
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
Classis Autoscaler
Hoc genus munera continet ad ipsam logicam operantem pertinentia.
Hoc est quod fragmen codice huic classis similis:
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
Classes pro ingressu accipimus. Ambari
и Mcs
, index nodi qui ad scalas permittitur, necnon parametri conformationis nodi: memoria et cpu nodi in NARRATIO partita. Sunt etiam 2 parametri interni q_ram, q_cpu, que sunt queues. Illis utentes, valores botri currentis onus condimus. Si viderimus per ultimam 5 minutam onus constanter auctum fuisse, decernimus nos nodi -1 botro addere opus esse. Idem dicendum est de botri underutilizationis statu.
Codex superius est exemplum functionis quae machinam a botro removet et in nube sistit. Primum est decommissioning YARN Nodemanager
Ergo modus volvitur in Maintenance
cessamus ergo omnia officia in machina et virtualem machinam in nube averte.
2. Script observer.py
Sample codicem inde:
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)
In ea perspicimus num condiciones factae sint ad augendam capacitatem botri et num aliquae machinae in subsidiis sint, unum ex eis nomen accipe, botrum adde et nuntium de illo in quadrigis nostris Slack evulgare. Post quem incipit cooldown_period
quando non addimus vel de botro aliquid auferimus, sed onus simpliciter monuimus. Si confirmatae sunt et intra in ANDRON bonarum bonorum onus est, tunc simpliciter vigilantia permanemus. Si una nodi satis fuit, aliam addimus.
Cum enim praemissam lectionem habeamus, iam pro certo scimus unam nodi non esse satis, ita statim omnes nodos liberas incipimus et eas activas usque ad finem lectionis servamus. Hoc fit utens indice actionis indicationibus.
conclusio,
Autoscaler bona et commoda solutio casuum est cum inaequale oneratum botrum experieris. Simul optatum botri configurationem ad apicem onerum assequeris et simul hoc botrum in onere sub onere non servas, pecuniam salvificam. Bene, plus haec omnia fiunt statim sine participatione tua. Ipsum autoscaler nihil aliud est quam postulationes ad botrum procurator API et nubes provisor API, scripta secundum quamdam logicam. Quod certe meminisse debes est divisio nodis in 3 species, sicut antea scripsimus. Et beatus eris.
Source: www.habr.com