క్లస్టర్ కోసం మీ స్వంత ఆటోస్కేలర్‌ను ఎలా తయారు చేసుకోవాలి

నమస్కారం! మేము బిగ్ డేటాతో పనిచేయడానికి ప్రజలకు శిక్షణ ఇస్తాము. పాల్గొనేవారందరూ కలిసి పనిచేసే సొంత క్లస్టర్ లేకుండా ఒక బిగ్ డేటా విద్యా కార్యక్రమాన్ని ఊహించడం అసాధ్యం. అందుకే మా ప్రోగ్రామ్‌లో ఎల్లప్పుడూ ఒకటి ఉంటుంది. 🙂 మేము దానిని కాన్ఫిగర్ చేసి, ట్యూన్ చేసి, నిర్వహిస్తాము, మరియు విద్యార్థులు వాస్తవానికి MapReduce జాబ్‌లను రన్ చేసి, స్పార్క్‌ను ఉపయోగిస్తారు.

ఈ పోస్ట్‌లో, క్లౌడ్‌ను ఉపయోగించి మా స్వంత ఆటోస్కేలర్‌ను రాయడం ద్వారా అసమాన క్లస్టర్ లోడ్ సమస్యను మేము ఎలా పరిష్కరించామో మీకు చూపిస్తాము. Mail.ru క్లౌడ్ సొల్యూషన్స్.

సమస్య

మా క్లస్టర్‌ను సాధారణ పద్ధతిలో ఉపయోగించరు. వినియోగం చాలా అస్థిరంగా ఉంటుంది. ఉదాహరణకు, కొన్ని ప్రాక్టికల్ క్లాసులలో 30 మందితో పాటు ఇన్‌స్ట్రక్టర్ కూడా క్లస్టర్‌లోకి లాగిన్ అయి దాన్ని ఉపయోగించడం ప్రారంభిస్తారు. ఆ తర్వాత, గడువు తేదీలకు ముందు రోజులలో వినియోగం గణనీయంగా పెరుగుతుంది. మిగతా సమయమంతా, క్లస్టర్ తక్కువ వినియోగ రేటుతో పనిచేస్తుంది.

పరిష్కారం #1 ఏమిటంటే, గరిష్ట లోడ్‌లను నిర్వహించగల క్లస్టర్‌ను నిర్వహించడం, కానీ మిగిలిన సమయంలో అది నిష్క్రియంగా ఉంటుంది.

పరిష్కారం #2 ఏమిటంటే, ఒక చిన్న క్లస్టర్‌ను నిర్వహిస్తూ, తరగతులకు ముందు మరియు అధిక లోడ్ల సమయంలో దానికి మాన్యువల్‌గా నోడ్‌లను జోడించడం.

పరిష్కారం #3 ఏమిటంటే, ఒక చిన్న క్లస్టర్‌ను నిర్వహిస్తూ, ప్రస్తుత క్లస్టర్ లోడ్‌ను పర్యవేక్షించే మరియు వివిధ APIలను ఉపయోగించి క్లస్టర్‌కు నోడ్‌లను జోడించడం మరియు తొలగించడం చేసే ఒక ఆటోస్కేలర్‌ను వ్రాయడం.

ఈ పోస్ట్‌లో, మనం పరిష్కారం #3 గురించి చర్చిద్దాం. ఈ రకమైన ఆటోస్కేలర్ అంతర్గత కారకాల కంటే బాహ్య కారకాలపై ఎక్కువగా ఆధారపడుతుంది, మరియు ప్రొవైడర్లు తరచుగా దీనిని అందించరు. మేము Mail.ru క్లౌడ్ సొల్యూషన్స్ వారి క్లౌడ్ ఇన్‌ఫ్రాస్ట్రక్చర్‌ను ఉపయోగిస్తాము మరియు MCS APIని ఉపయోగించి ఒక ఆటోస్కేలర్‌ను రాశాము. మేము డేటా మేనేజ్‌మెంట్‌ను బోధిస్తాము కాబట్టి, మీరు మీ స్వంత ప్రయోజనాల కోసం ఇలాంటి ఆటోస్కేలర్‌ను ఎలా రాయవచ్చో మరియు దానిని మీ క్లౌడ్‌తో ఎలా ఉపయోగించవచ్చో చూపించాలని నిర్ణయించుకున్నాము.

కనీసావసరాలు

ముందుగా, మీకు ఒక హడూప్ క్లస్టర్ అవసరం. ఉదాహరణకు, మేము HDP డిస్ట్రిబ్యూషన్‌ను ఉపయోగిస్తాము.

నోడ్‌లను త్వరగా జోడించడానికి మరియు తొలగించడానికి, నోడ్‌ల మధ్య పాత్రల యొక్క నిర్దిష్ట పంపిణీ తప్పనిసరిగా ఉండాలి.

  1. మాస్టర్ నోడ్. సరే, ఇక్కడ ఏమీ వివరించాల్సిన అవసరం లేదు: ఇది క్లస్టర్ యొక్క ప్రధాన నోడ్, ఉదాహరణకు, మీరు ఇంటరాక్టివ్ మోడ్‌ను ఉపయోగిస్తుంటే ఇది స్పార్క్ డ్రైవర్‌ను నడుపుతుంది.
  2. డేటా నోడ్. ఇది మీరు HDFSలో మీ డేటాను నిల్వ చేసే మరియు గణనలు నిర్వహించే నోడ్.
  3. కంప్యూట్ నోడ్. ఇది HDFSలో దేన్నీ నిల్వ చేయని నోడ్, కానీ ఇక్కడ గణనలు నిర్వహించబడతాయి.

ఒక ముఖ్యమైన విషయం: ఆటోస్కేలింగ్ మూడవ రకం నోడ్‌లను ఉపయోగించి జరుగుతుంది. మీరు రెండవ రకం నోడ్‌లను తీసివేయడం మరియు జోడించడం ప్రారంభిస్తే, ప్రతిస్పందన సమయం చాలా నెమ్మదిగా ఉంటుంది – మీ క్లస్టర్‌లో డీకమిషనింగ్ మరియు రీకమిషనింగ్‌కు గంటల సమయం పడుతుంది. వాస్తవానికి, ఆటోస్కేలింగ్ నుండి మీరు ఆశించేది ఇది కాదు. మరో మాటలో చెప్పాలంటే, మేము మొదటి మరియు రెండవ రకాల నోడ్‌లను ముట్టుకోము. అవి ప్రోగ్రామ్ మొత్తం వ్యవధిలో ఉండే ఒక కనీస ఆచరణీయ క్లస్టర్‌ను ఏర్పరుస్తాయి.

కాబట్టి, మా ఆటోస్కేలర్ పైథాన్ 3 లో వ్రాయబడింది, క్లస్టర్ సేవలను నిర్వహించడానికి అంబారి API ని ఉపయోగిస్తుంది, Mail.ru క్లౌడ్ సొల్యూషన్స్ నుండి API యంత్రాలను ప్రారంభించడానికి మరియు ఆపడానికి (MCS).

సొల్యూషన్ ఆర్కిటెక్చర్

  1. మాడ్యూల్ autoscaler.pyఇందులో మూడు క్లాసులు ఉన్నాయి: 1) అంబారితో పనిచేయడానికి ఫంక్షన్లు, 2) MCSతో పనిచేయడానికి ఫంక్షన్లు, 3) ఆటోస్కేలర్ లాజిక్‌కు నేరుగా సంబంధించిన ఫంక్షన్లు.
  2. స్క్రిప్ట్ observer.pyముఖ్యంగా, ఇది ఆటోస్కేలర్ ఫంక్షన్‌లను ఎప్పుడు మరియు ఏ సమయాల్లో పిలవాలి అనే వివిధ నియమాలను కలిగి ఉంటుంది.
  3. కాన్ఫిగరేషన్ పారామితులతో కూడిన ఫైల్ config.pyఉదాహరణకు, ఆటోస్కేలింగ్ కోసం అనుమతించబడిన నోడ్‌ల జాబితా మరియు కొత్త నోడ్‌ను జోడించిన తర్వాత ఎంతసేపు వేచి ఉండాలి వంటి వాటిని ప్రభావితం చేసే ఇతర పారామీటర్‌లు ఇందులో ఉంటాయి. ఇందులో క్లాస్ ప్రారంభ టైమ్‌స్టాంప్‌లు కూడా ఉంటాయి, తద్వారా క్లాస్‌కు ముందు గరిష్టంగా అనుమతించబడిన క్లస్టర్ కాన్ఫిగరేషన్ ప్రారంభించబడుతుంది.

ఇప్పుడు మొదటి రెండు ఫైళ్ళలోని కోడ్ భాగాలను చూద్దాం.

1. ఆటోస్కేలర్.పై మాడ్యూల్

అంబారి క్లాస్

క్లాస్‌ను కలిగి ఉన్న కోడ్ భాగం ఈ విధంగా కనిపిస్తుంది 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ని పొందాలి. ఆ తర్వాత మనం కేవలం ఒక POST రిక్వెస్ట్ చేసి మెషీన్‌ను ప్రారంభిస్తాము.

టోకెన్ స్వీకరించే ఫంక్షన్ ఈ విధంగా ఉంటుంది:

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స్కేలింగ్ కోసం అనుమతించబడిన నోడ్‌ల జాబితా, మరియు నోడ్ కాన్ఫిగరేషన్ పారామీటర్లు: YARNలో ప్రతి నోడ్‌కు కేటాయించబడిన మెమరీ మరియు CPU. q_ram మరియు q_cpu అనే రెండు అంతర్గత పారామీటర్లు కూడా ఉన్నాయి, ఇవి క్యూలు. ప్రస్తుత క్లస్టర్ లోడ్ విలువలను నిల్వ చేయడానికి మేము వాటిని ఉపయోగిస్తాము. గత 5 నిమిషాలుగా స్థిరంగా అధిక లోడ్‌ను గమనిస్తే, క్లస్టర్‌కు మరో నోడ్‌ను జోడించాలని మేము నిర్ణయించుకుంటాము. తక్కువగా ఉపయోగించబడుతున్న క్లస్టర్‌లకు కూడా ఇదే వర్తిస్తుంది.

పైన ఉన్న కోడ్, క్లస్టర్ నుండి ఒక మెషీన్‌ను తీసివేసి, క్లౌడ్‌లో దాన్ని నిలిపివేసే ఫంక్షన్‌కు ఒక ఉదాహరణను చూపిస్తుంది. మొదట, డీకమిషన్ జరుగుతుంది. 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ఇక్కడ మేము క్లస్టర్‌కు ఏదీ జోడించము లేదా తొలగించము, కేవలం లోడ్‌ను పర్యవేక్షిస్తాము. అది స్థిరపడి, సరైన లోడ్ పరిధిలో ఉంటే, మేము పర్యవేక్షణను కొనసాగిస్తాము. ఒక నోడ్ లేకపోతే, మరొకదాన్ని జోడిస్తాము.

మనకు క్లాస్ ఉన్నప్పుడు, ఒక నోడ్ సరిపోదని మనకు ముందే తెలుసు, కాబట్టి మనం వెంటనే అందుబాటులో ఉన్న అన్ని నోడ్‌లను ప్రారంభించి, క్లాస్ ముగిసే వరకు వాటిని యాక్టివ్‌గా ఉంచుతాము. క్లాస్ టైమ్‌స్టాంప్‌ల జాబితాను ఉపయోగించి ఇది జరుగుతుంది.

తీర్మానం

మీరు అసమాన క్లస్టర్ లోడ్‌ను ఎదుర్కొంటున్న పరిస్థితులకు ఆటోస్కేలర్ ఒక మంచి మరియు సౌకర్యవంతమైన పరిష్కారం. దీని ద్వారా మీరు గరిష్ట లోడ్‌ల కోసం కావలసిన క్లస్టర్ కాన్ఫిగరేషన్‌ను సాధిస్తూనే, తక్కువ వినియోగంలో ఉన్న సమయాల్లో క్లస్టర్‌ను నిర్వహించడాన్ని నివారించి, డబ్బు ఆదా చేసుకోవచ్చు. అంతేకాకుండా, ఇదంతా మీ జోక్యం లేకుండా స్వయంచాలకంగా జరుగుతుంది. ఆటోస్కేలర్ అనేది ఒక నిర్దిష్ట తర్కం ప్రకారం వ్రాయబడిన, క్లస్టర్ మేనేజర్ API మరియు క్లౌడ్ ప్రొవైడర్ APIకి పంపే అభ్యర్థనల సముదాయం తప్ప మరేమీ కాదు. మేము ఇంతకు ముందు వివరించినట్లుగా, నోడ్‌లను మూడు రకాలుగా విభజించడాన్ని మీరు ఖచ్చితంగా గుర్తుంచుకోవాలి. అప్పుడు మీరు సంతోషంగా ఉంటారు.

మూలం: www.habr.com

DDoS రక్షణ, VPS VDS సర్వర్‌లతో సైట్‌ల కోసం నమ్మకమైన హోస్టింగ్‌ను కొనుగోలు చేయండి 🔥 DDoS రక్షణతో కూడిన నమ్మకమైన వెబ్‌సైట్ హోస్టింగ్, VPS VDS సర్వర్‌లను కొనండి | ProHoster