์๋ ํ์ธ์! ์ฐ๋ฆฌ๋ ๋น ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃฐ ์ ์๋๋ก ์ฌ๋๋ค์ ๊ต์กํฉ๋๋ค. ๋ชจ๋ ์ฐธ๊ฐ์๊ฐ ํจ๊ป ์์ ํ๋ ์์ฒด ํด๋ฌ์คํฐ ์์ด ๋น ๋ฐ์ดํฐ์ ๋ํ ๊ต์ก ํ๋ก๊ทธ๋จ์ ์์ํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํฉ๋๋ค. ์ด๋ฐ ์ด์ ๋ก ์ฐ๋ฆฌ ํ๋ก๊ทธ๋จ์๋ ํญ์ ๊ทธ๋ฐ ๊ฒ์ด ์์ต๋๋ค ๐ ์ฐ๋ฆฌ๋ ๊ตฌ์ฑ, ์กฐ์ ๋ฐ ๊ด๋ฆฌ์ ์ฐธ์ฌํ๊ณ ์์ผ๋ฉฐ ์ง์๋ค์ ๊ทธ๊ณณ์์ ์ง์ MapReduce ์์ ์ ์์ํ๊ณ Spark๋ฅผ ์ฌ์ฉํฉ๋๋ค.
์ด ๊ฒ์๋ฌผ์์๋ ํด๋ผ์ฐ๋๋ฅผ ์ฌ์ฉํ์ฌ ์์ฒด ์๋ ํฌ๊ธฐ ์กฐ์ ๊ธฐ๋ฅผ ์์ฑํ์ฌ ๊ณ ๋ฅด์ง ์์ ํด๋ฌ์คํฐ ๋ก๋ฉ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ๋ฐฉ๋ฒ์ ์๋ ค ๋๋ฆฌ๊ฒ ์ต๋๋ค.
๋ฌธ์
์ฐ๋ฆฌ ํด๋ฌ์คํฐ๋ ์ผ๋ฐ ๋ชจ๋์์ ์ฌ์ฉ๋์ง ์์ต๋๋ค. ์ฒ๋ฆฌ๊ฐ ๋งค์ฐ ๊ณ ๋ฅด์ง ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, 30๋ช ์ ์๊ณผ ์ ์๋ ํ ๋ช ์ด ํด๋ฌ์คํฐ์ ๊ฐ์ ์ฌ์ฉํ๊ธฐ ์์ํ๋ ์ค์ต ์์ ์ด ์์ต๋๋ค. ํน์ ๋ง๊ฐ์ผ์ ์๋๊ณ ๋ถํ๊ฐ ํฌ๊ฒ ๋์ด๋๋ ๋ ๋ ์์ต๋๋ค. ๋๋จธ์ง ์๊ฐ์๋ ํด๋ฌ์คํฐ๊ฐ ์ธ๋๋ก๋ ๋ชจ๋๋ก ์๋ํฉ๋๋ค.
์๋ฃจ์ #1์ ์ต๋ ๋ถํ๋ฅผ ๊ฒฌ๋ ์ ์์ง๋ง ๋๋จธ์ง ์๊ฐ์๋ ์ ํด ์ํ์ธ ํด๋ฌ์คํฐ๋ฅผ ์ ์งํ๋ ๊ฒ์ ๋๋ค.
์๋ฃจ์ #2๋ ํด๋์ค ์ด์ ๊ณผ ์ต๋ ๋ก๋ ์ค์ ๋ ธ๋๋ฅผ ์๋์ผ๋ก ์ถ๊ฐํ๋ ์์ ํด๋ฌ์คํฐ๋ฅผ ์ ์งํ๋ ๊ฒ์ ๋๋ค.
์๋ฃจ์ #3์ ์์ ํด๋ฌ์คํฐ๋ฅผ ์ ์งํ๊ณ ํด๋ฌ์คํฐ์ ํ์ฌ ๋ก๋๋ฅผ ๋ชจ๋ํฐ๋งํ๊ณ ๋ค์ํ API๋ฅผ ์ฌ์ฉํ์ฌ ํด๋ฌ์คํฐ์์ ๋ ธ๋๋ฅผ ์ถ๊ฐ ๋ฐ ์ ๊ฑฐํ๋ ์๋ ํฌ๊ธฐ ์กฐ์ ๊ธฐ๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋๋ค.
์ด๋ฒ ํฌ์คํ ์์๋ ์๋ฃจ์ #3์ ๋ํด ์ด์ผ๊ธฐํ๊ฒ ์ต๋๋ค. ์ด ์๋ ํฌ๊ธฐ ์กฐ์ ๊ธฐ๋ ๋ด๋ถ ์์ธ๋ณด๋ค๋ ์ธ๋ถ ์์ธ์ ํฌ๊ฒ ์์กดํ๋ฉฐ ๊ณต๊ธ์๊ฐ ์ด๋ฅผ ์ ๊ณตํ์ง ์๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ์ฐ๋ฆฌ๋ Mail.ru Cloud Solutions ํด๋ผ์ฐ๋ ์ธํ๋ผ๋ฅผ ์ฌ์ฉํ๊ณ MCS API๋ฅผ ์ฌ์ฉํ์ฌ ์๋ ํฌ๊ธฐ ์กฐ์ ๊ธฐ๋ฅผ ์์ฑํ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ฐ์ดํฐ ์์ ๋ฐฉ๋ฒ์ ๊ฐ๋ฅด์น๊ธฐ ๋๋ฌธ์ ์์ ์ ๋ชฉ์ ์ ๋ง๊ฒ ์ ์ฌํ ์๋ ํฌ๊ธฐ ์กฐ์ ๊ธฐ๋ฅผ ์์ฑํ๊ณ ํด๋ผ์ฐ๋์์ ์ฌ์ฉํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ ์ฃผ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค.
์ฌ์ ์กฐ๊ฑด
๋จผ์ Hadoop ํด๋ฌ์คํฐ๊ฐ ์์ด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด HDP ๋ถํฌ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
๋ ธ๋๋ฅผ ์ ์ํ๊ฒ ์ถ๊ฐํ๊ณ ์ ๊ฑฐํ๋ ค๋ฉด ๋ ธ๋ ๊ฐ์ ์ผ์ ํ ์ญํ ๋ถ๋ฐฐ๊ฐ ์์ด์ผ ํฉ๋๋ค.
- ๋ง์คํฐ ๋ ธ๋. ๊ธ์, ํน๋ณํ ์ค๋ช ํ ํ์๋ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ๋ํํ ๋ชจ๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ Spark ๋๋ผ์ด๋ฒ๊ฐ ์คํ๋๋ ํด๋ฌ์คํฐ์ ๊ธฐ๋ณธ ๋ ธ๋์ ๋๋ค.
- ๋ ์ง ๋ ธ๋. ์ด๋ HDFS์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ ๊ณ์ฐ์ด ์ํ๋๋ ๋ ธ๋์ ๋๋ค.
- ์ปดํจํ ๋ ธ๋. ์ด๋ HDFS์ ์๋ฌด ๊ฒ๋ ์ ์ฅํ์ง ์์ง๋ง ๊ณ์ฐ์ด ์ด๋ฃจ์ด์ง๋ ๋ ธ๋์ ๋๋ค.
์ค์ํ ์ . ์ธ ๋ฒ์งธ ์ ํ์ ๋ ธ๋๋ก ์ธํด ์๋ ํ์ฅ์ด ๋ฐ์ํฉ๋๋ค. ๋ ๋ฒ์งธ ์ ํ์ ๋ ธ๋๋ฅผ ๊ฐ์ ธ์ ์ถ๊ฐํ๊ธฐ ์์ํ๋ฉด ์๋ต ์๋๊ฐ ๋งค์ฐ ๋๋ ค์ง๋๋ค. ํด๋ฌ์คํฐ์์ ํด์ ํ๊ณ ๋ค์ ์ปค๋ฐํ๋ ๋ฐ ๋ช ์๊ฐ์ด ๊ฑธ๋ฆฝ๋๋ค. ๋ฌผ๋ก ์ด๋ ์๋ ํฌ๊ธฐ ์กฐ์ ์์ ๊ธฐ๋ํ๋ ๊ฒ๊ณผ๋ ๋ค๋ฆ ๋๋ค. ์ฆ, ์ฒซ ๋ฒ์งธ ๋ฐ ๋ ๋ฒ์งธ ์ ํ์ ๋ ธ๋๋ฅผ ๊ฑด๋๋ฆฌ์ง ์์ต๋๋ค. ์ด๋ ํ๋ก๊ทธ๋จ ๊ธฐ๊ฐ ๋์ ์กด์ฌํ ์ต์ ์คํ ๊ฐ๋ฅํ ํด๋ฌ์คํฐ๋ฅผ ๋ํ๋ ๋๋ค.
๋ฐ๋ผ์ ์๋ ํฌ๊ธฐ ์กฐ์ ๊ธฐ๋ Python 3์ผ๋ก ์์ฑ๋์์ผ๋ฉฐ Ambari API๋ฅผ ์ฌ์ฉํ์ฌ ํด๋ฌ์คํฐ ์๋น์ค๋ฅผ ๊ด๋ฆฌํ๊ณ
์๋ฃจ์ ์ํคํ ์ฒ
- ๊ธฐ์ค ์น์
autoscaler.py
. ์ฌ๊ธฐ์๋ 1) Ambari ์์ ์ ์ํ ํจ์, 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
โ Ambari์ ํด๋ฌ์คํฐ ์ด๋ฆheaders = {'X-Requested-By': 'ambari'}
- ๊ทธ๋ฆฌ๊ณ ๋ด๋ถ
auth
Ambari์ ๋ก๊ทธ์ธ ๋ฐ ๋น๋ฐ๋ฒํธ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.auth = ('login', 'password')
.
ํจ์ ์์ฒด๋ REST API๋ฅผ ํตํด Ambari์ ๋ํ ๋ช ๋ฒ์ ํธ์ถ์ ์ง๋์ง ์์ต๋๋ค. ๋
ผ๋ฆฌ์ ์ธ ๊ด์ ์์ ๋ณผ ๋, ์ฐ๋ฆฌ๋ ๋จผ์ ๋
ธ๋์์ ์คํ ์ค์ธ ์๋น์ค ๋ชฉ๋ก์ ๋ฐ์ ๋ค์ ํน์ ํด๋ฌ์คํฐ, ํน์ ๋
ธ๋์์ ๋ชฉ๋ก์์ ์ํ๋ก ์๋น์ค๋ฅผ ์ ์กํ๋๋ก ์์ฒญํฉ๋๋ค. INSTALLED
. ๋ชจ๋ ์๋น์ค๋ฅผ ์์ํ๊ณ ๋
ธ๋๋ฅผ ์ํ๋ก ์ ์กํ๋ ๊ธฐ๋ฅ Maintenance
๋ฑ์ ๋น์ทํด ๋ณด์
๋๋ค. API๋ฅผ ํตํ ๋ช ๊ฐ์ง ์์ฒญ์ผ ๋ฟ์
๋๋ค.
ํด๋์ค MC
ํด๋์ค๋ฅผ ํฌํจํ๋ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. 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)์
๋๋ค. ๋ํ ๋๊ธฐ์ด์ธ 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)
์ฌ๊ธฐ์์ ํด๋ฌ์คํฐ ์ฉ๋์ ๋๋ฆฌ๊ธฐ ์ํ ์กฐ๊ฑด์ด ์์ฑ๋์๋์ง, ์๋น ๋จธ์ ์ด ์๋์ง ํ์ธํ๊ณ , ๊ทธ ์ค ํ๋์ ํธ์คํธ ์ด๋ฆ์ ๊ฐ์ ธ์ ํด๋ฌ์คํฐ์ ์ถ๊ฐํ๊ณ ์ด์ ๋ํ ๋ฉ์์ง๋ฅผ ์ฐ๋ฆฌ ํ์ Slack์ ๊ฒ์ํฉ๋๋ค. ๊ทธ ํ์๋ ์์๋ฉ๋๋ค cooldown_period
, ํด๋ฌ์คํฐ์ ์๋ฌด๊ฒ๋ ์ถ๊ฐํ๊ฑฐ๋ ์ ๊ฑฐํ์ง ์๊ณ ๋จ์ํ ๋ก๋๋ฅผ ๋ชจ๋ํฐ๋งํ๋ ๊ฒฝ์ฐ์
๋๋ค. ์์ ํ๋์ด ์ต์ ์ ๋ถํ ๊ฐ ๋ฒ์ ๋ด์ ์์ผ๋ฉด ๊ณ์ ๋ชจ๋ํฐ๋งํ๋ฉด ๋ฉ๋๋ค. ํ๋์ ๋
ธ๋๊ฐ ์ถฉ๋ถํ์ง ์์ผ๋ฉด ๋ค๋ฅธ ๋
ธ๋๋ฅผ ์ถ๊ฐํฉ๋๋ค.
์์ผ๋ก ๊ฐ์๊ฐ ์๋ ๊ฒฝ์ฐ ํ๋์ ๋ ธ๋๋ก๋ ์ถฉ๋ถํ์ง ์๋ค๋ ๊ฒ์ ์ด๋ฏธ ์๊ณ ์์ผ๋ฏ๋ก ๋ชจ๋ ๋ฌด๋ฃ ๋ ธ๋๋ฅผ ์ฆ์ ์์ํ๊ณ ๊ฐ์๊ฐ ๋๋ ๋๊น์ง ํ์ฑ ์ํ๋ฅผ ์ ์งํฉ๋๋ค. ์ด๋ ํ๋ ํ์์คํฌํ ๋ชฉ๋ก์ ์ฌ์ฉํ์ฌ ๋ฐ์ํฉ๋๋ค.
๊ฒฐ๋ก
Autoscaler๋ ํด๋ฌ์คํฐ ๋ก๋ฉ์ด ๊ณ ๋ฅด์ง ์์ ๊ฒฝ์ฐ์ ์ ์ฉํ๊ณ ํธ๋ฆฌํ ์๋ฃจ์ ์ ๋๋ค. ์ต๋ ๋ก๋์ ๋ํด ์ํ๋ ํด๋ฌ์คํฐ ๊ตฌ์ฑ์ ๋์์ ๋ฌ์ฑํ๋ ๋์์ ๋ก๋๊ฐ ์ ์ ๋์์๋ ์ด ํด๋ฌ์คํฐ๋ฅผ ์ ์งํ์ง ์์ผ๋ฏ๋ก ๋น์ฉ์ด ์ ์ฝ๋ฉ๋๋ค. ๊ฒ๋ค๊ฐ ์ด ๋ชจ๋ ์ผ์ ๊ทํ์ ์ฐธ์ฌ ์์ด๋ ์๋์ผ๋ก ๋ฐ์ํฉ๋๋ค. ์๋ ํฌ๊ธฐ ์กฐ์ ๊ธฐ ์์ฒด๋ ํน์ ๋ ผ๋ฆฌ์ ๋ฐ๋ผ ์์ฑ๋ ํด๋ฌ์คํฐ ๊ด๋ฆฌ์ API ๋ฐ ํด๋ผ์ฐ๋ ๊ณต๊ธ์ API์ ๋ํ ์ผ๋ จ์ ์์ฒญ์ ์ง๋์ง ์์ต๋๋ค. ๋ฐ๋์ ๊ธฐ์ตํด์ผ ํ ๊ฒ์ ์์ ์ผ๋ ๊ฒ์ฒ๋ผ ๋ ธ๋๋ฅผ 3๊ฐ์ง ์ ํ์ผ๋ก ๋๋๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋น์ ์ ํ๋ณตํ ๊ฒ์ ๋๋ค.
์ถ์ฒ : habr.com