Bii o ṣe le ṣe autoscaler tirẹ fun iṣupọ kan

Pẹlẹ o! A ṣe ikẹkọ eniyan lati ṣiṣẹ pẹlu data nla. Ko ṣee ṣe lati fojuinu eto eto-ẹkọ lori data nla laisi iṣupọ tirẹ, lori eyiti gbogbo awọn olukopa ṣiṣẹ papọ. Fun idi eyi, eto wa nigbagbogbo ni o 🙂 A n ṣiṣẹ ni iṣeto rẹ, iṣatunṣe ati iṣakoso, ati pe awọn eniyan n ṣe ifilọlẹ awọn iṣẹ MapReduce taara nibẹ ati lo Spark.

Ninu ifiweranṣẹ yii a yoo sọ fun ọ bii a ṣe yanju iṣoro ti ikojọpọ iṣupọ aiṣedeede nipa kikọ autoscaler tiwa nipa lilo awọsanma Mail.ru awọsanma Solutions.

Isoro

A ko lo iṣupọ wa ni ipo aṣoju. Isọnu jẹ aidọgba pupọ. Fun apẹẹrẹ, awọn kilasi ti o wulo wa, nigbati gbogbo eniyan 30 ati olukọ kan lọ si iṣupọ ati bẹrẹ lilo rẹ. Tabi lẹẹkansi, awọn ọjọ wa ṣaaju akoko ipari nigbati ẹru ba pọ si pupọ. Iyoku akoko iṣupọ n ṣiṣẹ ni ipo agberu.

Solusan #1 ni lati tọju iṣupọ kan ti yoo koju awọn ẹru ti o ga julọ, ṣugbọn yoo wa ni aiṣiṣẹ ni akoko to ku.

Ojutu #2 ni lati tọju iṣupọ kekere kan, eyiti o fi ọwọ kun awọn apa ṣaaju kilaasi ati lakoko awọn ẹru oke.

Solusan #3 ni lati tọju iṣupọ kekere kan ati kọ autoscaler ti yoo ṣe atẹle ẹru lọwọlọwọ ti iṣupọ ati, ni lilo awọn API lọpọlọpọ, ṣafikun ati yọ awọn apa kuro ninu iṣupọ naa.

Ninu ifiweranṣẹ yii a yoo sọrọ nipa ojutu #3. Autoscaler yii jẹ igbẹkẹle pupọ lori awọn ifosiwewe ita ju awọn ti inu lọ, ati awọn olupese nigbagbogbo ko pese rẹ. A lo Mail.ru Awọn solusan awọsanma awọsanma ati kọ ohun autoscaler nipa lilo MCS API. Ati pe niwọn igba ti a nkọ bi o ṣe le ṣiṣẹ pẹlu data, a pinnu lati ṣafihan bii o ṣe le kọ iru autoscaler fun awọn idi tirẹ ki o lo pẹlu awọsanma rẹ

Prerequisites

Ni akọkọ, o gbọdọ ni iṣupọ Hadoop kan. Fun apẹẹrẹ, a lo HDP pinpin.

Ni ibere fun awọn apa rẹ ni kiakia lati ṣafikun ati yọkuro, o gbọdọ ni pinpin awọn ipa kan laarin awọn apa.

  1. Titunto ipade. O dara, ko si iwulo lati ṣalaye ohunkohun ni pataki: oju ipade akọkọ ti iṣupọ, lori eyiti, fun apẹẹrẹ, awakọ Spark ti ṣe ifilọlẹ, ti o ba lo ipo ibaraenisepo.
  2. Oju ipade ọjọ. Eyi ni ipade ti o fi data pamọ sori HDFS ati nibiti awọn iṣiro ti waye.
  3. Ipade iširo. Eleyi jẹ a ipade ibi ti o ko ba fi ohunkohun lori HDFS, sugbon ibi ti isiro ṣẹlẹ.

Ojuami pataki. Autoscaling yoo waye nitori awọn apa ti iru kẹta. Ti o ba bẹrẹ gbigba ati fifi awọn apa ti iru keji kun, iyara esi yoo kere pupọ - piparẹ ati atunṣe yoo gba awọn wakati lori iṣupọ rẹ. Eyi, nitorinaa, kii ṣe ohun ti o nireti lati iwọn aifọwọyi. Iyẹn ni, a ko fi ọwọ kan awọn apa ti awọn oriṣi akọkọ ati keji. Wọn yoo ṣe aṣoju iṣupọ ti o le yanju ti o kere julọ ti yoo wa jakejado iye akoko eto naa.

Nitorinaa, autoscaler wa ni kikọ ni Python 3, nlo Ambari API lati ṣakoso awọn iṣẹ iṣupọ, awọn lilo API lati Mail.ru Awọn solusan awọsanma (MCS) fun ibẹrẹ ati awọn ẹrọ idaduro.

Solusan faaji

  1. Module autoscaler.py. O ni awọn kilasi mẹta: 1) awọn iṣẹ fun ṣiṣẹ pẹlu Ambari, 2) awọn iṣẹ fun ṣiṣẹ pẹlu MCS, 3) awọn iṣẹ ti o ni ibatan taara si imọran ti autoscaler.
  2. Iwe afọwọkọ observer.py. Ni pataki o ni awọn ofin oriṣiriṣi: nigbawo ati ni awọn akoko wo lati pe awọn iṣẹ autoscaler.
  3. Faili iṣeto ni config.py. O ni, fun apẹẹrẹ, atokọ ti awọn apa ti a gba laaye fun autoscaling ati awọn paramita miiran ti o kan, fun apẹẹrẹ, bawo ni o ṣe pẹ to lati duro lati akoko ti a ti ṣafikun ipade tuntun kan. Awọn akoko akoko tun wa fun ibẹrẹ awọn kilasi, nitorinaa ṣaaju ki kilasi iṣeto iṣupọ ti o pọ julọ ti ṣe ifilọlẹ.

Jẹ ki a ni bayi wo awọn ege koodu inu awọn faili meji akọkọ.

1. Autoscaler.py module

Abari kilasi

Eyi ni nkan ti koodu ti o ni kilasi kan dabi 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

Loke, bi apẹẹrẹ, o le wo imuse ti iṣẹ naa stop_all_services, eyi ti o da gbogbo awọn iṣẹ duro lori ipade iṣupọ ti o fẹ.

Ni ẹnu-ọna si kilasi Ambari o kọja:

  • ambari_url, fun apẹẹrẹ, bi 'http://localhost:8080/api/v1/clusters/',
  • cluster_name – Orukọ iṣupọ rẹ ni Ambari,
  • headers = {'X-Requested-By': 'ambari'}
  • ati inu auth eyi ni orukọ olumulo ati ọrọ igbaniwọle rẹ fun Ambari: auth = ('login', 'password').

Iṣẹ naa funrararẹ kii ṣe nkan diẹ sii ju awọn ipe meji lọ nipasẹ API REST si Ambari. Lati oju wiwo ọgbọn, a kọkọ gba atokọ ti awọn iṣẹ ṣiṣe lori ipade kan, ati lẹhinna beere lori iṣupọ ti a fun, lori ipade ti a fun, lati gbe awọn iṣẹ lati atokọ lọ si ipinlẹ INSTALLED. Awọn iṣẹ fun ifilọlẹ gbogbo awọn iṣẹ, fun gbigbe awọn apa si ipo Maintenance ati bẹbẹ lọ wo iru - wọn jẹ awọn ibeere diẹ nipasẹ API.

Kilasi Mcs

Eyi ni nkan ti koodu ti o ni kilasi kan dabi 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

Ni ẹnu-ọna si kilasi Mcs a kọja id ise agbese inu awọsanma ati id olumulo, bakanna bi ọrọ igbaniwọle rẹ. Ni iṣẹ vm_turn_on a fẹ lati tan ọkan ninu awọn ẹrọ. Awọn kannaa nibi ni kekere kan diẹ idiju. Ni ibẹrẹ koodu, awọn iṣẹ mẹta miiran ni a pe: 1) a nilo lati gba ami kan, 2) a nilo lati yi orukọ olupin pada si orukọ ẹrọ ni MCS, 3) gba id ẹrọ yii. Nigbamii, a kan ṣe ibeere ifiweranṣẹ ati ṣe ifilọlẹ ẹrọ yii.

Eyi ni iṣẹ fun gbigba ami-ami kan dabi:

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 kilasi

Kilasi yii ni awọn iṣẹ ti o ni ibatan si ọgbọn iṣẹ funrararẹ.

Eyi ni nkan ti koodu kan fun kilasi yii dabi:

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

A gba awọn kilasi fun titẹsi. Ambari и Mcs, atokọ ti awọn apa ti o gba laaye fun iwọn, bakanna bi awọn ipilẹ iṣeto oju ipade: iranti ati cpu ti a pin si ipade ni YARN. Awọn paramita inu inu 2 tun wa q_ram, q_cpu, eyiti o jẹ awọn ila. Lilo wọn, a tọju awọn iye ti fifuye iṣupọ lọwọlọwọ. Ti a ba rii pe ni iṣẹju marun 5 sẹhin fifuye ti pọ si nigbagbogbo, lẹhinna a pinnu pe a nilo lati ṣafikun +1 node si iṣupọ. Bakan naa ni otitọ fun ipo iṣupọ ailagbara.

Koodu ti o wa loke jẹ apẹẹrẹ ti iṣẹ kan ti o yọ ẹrọ kan kuro ninu iṣupọ ati da duro ninu awọsanma. Ni akọkọ ti wa ni decommissioning YARN Nodemanager, lẹhinna ipo naa wa ni titan Maintenance, lẹhinna a da gbogbo awọn iṣẹ duro lori ẹrọ naa ki o si pa ẹrọ foju ni awọsanma.

2. Oluwoye iwe afọwọkọ.py

Apeere koodu lati ibẹ:

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)

Ninu rẹ, a ṣayẹwo boya awọn ipo ti ṣẹda fun jijẹ agbara ti iṣupọ ati boya awọn ẹrọ eyikeyi wa ni ipamọ, gba orukọ olupin ti ọkan ninu wọn, ṣafikun si iṣupọ naa ki o gbejade ifiranṣẹ kan nipa rẹ lori Slack ẹgbẹ wa. Lẹhin eyi o bẹrẹ cooldown_period, nigba ti a ko ba fikun tabi yọ ohunkohun lati awọn iṣupọ, sugbon nìkan bojuto awọn fifuye. Ti o ba ti ni iduroṣinṣin ati pe o wa laarin ọdẹdẹ ti awọn iye fifuye to dara julọ, lẹhinna a tẹsiwaju ni abojuto nirọrun. Ti ipade kan ko ba to, lẹhinna a ṣafikun ọkan miiran.

Fun awọn ọran nigba ti a ba ni ẹkọ ti o wa niwaju, a ti mọ daju pe apa kan kii yoo to, nitorinaa a bẹrẹ lẹsẹkẹsẹ gbogbo awọn apa ọfẹ ki o jẹ ki wọn ṣiṣẹ titi di opin ẹkọ naa. Eyi ṣẹlẹ nipa lilo atokọ ti awọn akoko ṣiṣe ṣiṣe.

ipari

Autoscaler jẹ ojutu ti o dara ati irọrun fun awọn ọran wọnyẹn nigbati o ba ni iriri ikojọpọ iṣupọ aiṣedeede. Nigbakanna o ṣaṣeyọri iṣeto iṣupọ ti o fẹ fun awọn ẹru tente oke ati ni akoko kanna ma ṣe tọju iṣupọ yii lakoko fifuye, fifipamọ owo. O dara, pẹlu gbogbo eyi yoo ṣẹlẹ laifọwọyi laisi ikopa rẹ. Autoscaler funrararẹ kii ṣe nkan diẹ sii ju eto awọn ibeere lọ si oluṣakoso iṣupọ API ati olupese awọsanma API, ti a kọ ni ibamu si ọgbọn kan. Ohun ti o nilo lati ranti ni pato ni pipin awọn apa si awọn oriṣi 3, bi a ti kọ tẹlẹ. Ati pe iwọ yoo ni idunnu.

orisun: www.habr.com

Fi ọrọìwòye kun