def test_average_schedule(test_db): # 4个16核, 不限制共享数 group, pod = _create_data(10, -1, 4) assert len(average_schedule(group, pod, ncontainer=100, ncore=2)) == 0 assert len(average_schedule(group, pod, ncontainer=130, ncore=0, nshare=5)) == 0 r = average_schedule(group, pod, ncontainer=10, ncore=1) assert len(r) == 4 assert sum(i[1] for i in r.keys()) == 10 for (host, count), cores in r.iteritems(): assert count in (2, 3) if count == 2: assert len(cores['full']) == 2 assert len(cores['part']) == 0 if count == 3: assert len(cores['full']) == 3 assert len(cores['part']) == 0 r = average_schedule(group, pod, ncontainer=9, ncore=2) assert len(r) == 4 assert sum(i[1] for i in r.keys()) == 9 for (host, count), cores in r.iteritems(): assert count in (2, 3) if count == 2: assert len(cores['full']) == 4 assert len(cores['part']) == 0 if count == 3: assert len(cores['full']) == 6 assert len(cores['part']) == 0 r = average_schedule(group, pod, ncontainer=40, ncore=1, nshare=5) assert len(r) == 4 assert sum(i[1] for i in r.keys()) == 40 for (host, count), cores in r.iteritems(): assert count == 10 assert len(cores['full']) == 10 assert len(cores['part']) == 10 assert len(set(cores['part'])) == 5 r = average_schedule(group, pod, ncontainer=22, ncore=2, nshare=3) assert len(r) == 4 assert sum(i[1] for i in r.keys()) == 22 for (host, count), cores in r.iteritems(): assert count in (5, 6) if count == 5: assert len(cores['full']) == 10 assert len(cores['part']) == 5 assert len(set(cores['part'])) == 2 if count == 6: assert len(cores['full']) == 12 assert len(cores['part']) == 6 assert len(set(cores['part'])) == 2
def test_average_schedule(test_db): # 4个16核, 不限制共享数 pod = _create_data(10, -1, 4) assert len(average_schedule(pod, ncontainer=100, ncore=2)) == 0 assert len(average_schedule(pod, ncontainer=130, ncore=0, nshare=5)) == 0 r = average_schedule(pod, ncontainer=10, ncore=1) assert len(r) == 4 assert sum(i[1] for i in r.keys()) == 10 for (host, count), cores in r.iteritems(): assert count in (2, 3) if count == 2: assert len(cores['full']) == 2 assert len(cores['part']) == 0 if count == 3: assert len(cores['full']) == 3 assert len(cores['part']) == 0 r = average_schedule(pod, ncontainer=9, ncore=2) assert len(r) == 4 assert sum(i[1] for i in r.keys()) == 9 for (host, count), cores in r.iteritems(): assert count in (2, 3) if count == 2: assert len(cores['full']) == 4 assert len(cores['part']) == 0 if count == 3: assert len(cores['full']) == 6 assert len(cores['part']) == 0 r = average_schedule(pod, ncontainer=40, ncore=1, nshare=5) assert len(r) == 4 assert sum(i[1] for i in r.keys()) == 40 for (host, count), cores in r.iteritems(): assert count == 10 assert len(cores['full']) == 10 assert len(cores['part']) == 10 assert len(set(cores['part'])) == 5 r = average_schedule(pod, ncontainer=22, ncore=2, nshare=3) assert len(r) == 4 assert sum(i[1] for i in r.keys()) == 22 for (host, count), cores in r.iteritems(): assert count in (5, 6) if count == 5: assert len(cores['full']) == 10 assert len(cores['part']) == 5 assert len(set(cores['part'])) == 2 if count == 6: assert len(cores['full']) == 12 assert len(cores['part']) == 6 assert len(set(cores['part'])) == 2
def migrate_container(container_id, need_to_remove=True): container = Container.get_by_container_id(container_id) if not container: _log.error('container %s is not found, ignore migration', container_id) return ncore, nshare = container.host.pod.get_core_allocation(container.ncore) host_cores = average_schedule(container.host.pod, 1, ncore, nshare, None) if not host_cores: _log.error('not enough cores to migrate') return cids = [container.id] spec_ips = cidrs = container.get_ips() (host, container_count), cores = next(host_cores.iteritems()) props = { 'ncontainer': 1, 'entrypoint': container.entrypoint, 'env': container.env, 'full_cores': [c.label for c in cores.get('full', [])], 'part_cores': [c.label for c in cores.get('part', [])], 'ports': None, 'args': None, 'nshare': nshare, 'networks': cidrs, 'image': None, 'route': '', 'callback_url': container.callback_url, 'container_ids': cids, } task = Task.create(consts.TASK_MIGRATE, container.version, host, props) if not task: _log.error('create migrate task error') return _log.info('start migration...') if need_to_remove: remove_containers.apply(args=(task.id, cids, False), task_id='task:%s' % task.id) create_containers.apply(args=(task.id, 1, nshare, cores, cidrs, spec_ips), task_id='task:%s' % task.id) _log.info('migration done')
def migrate_container(container_id, need_to_remove=True): container = Container.get_by_container_id(container_id) if not container: _log.error('container %s is not found, ignore migration', container_id) return ncore, nshare= container.host.pod.get_core_allocation(container.ncore) host_cores = average_schedule(container.host.pod, 1, ncore, nshare, None) if not host_cores: _log.error('not enough cores to migrate') return cids = [container.id] spec_ips = cidrs = container.get_ips() (host, container_count), cores = next(host_cores.iteritems()) props = { 'ncontainer': 1, 'entrypoint': container.entrypoint, 'env': container.env, 'full_cores': [c.label for c in cores.get('full', [])], 'part_cores': [c.label for c in cores.get('part', [])], 'ports': None, 'args': None, 'nshare': nshare, 'networks': cidrs, 'image': None, 'route': '', 'callback_url': container.callback_url, 'container_ids': cids, } task = Task.create(consts.TASK_MIGRATE, container.version, host, props) if not task: _log.error('create migrate task error') return _log.info('start migration...') if need_to_remove: remove_containers.apply(args=(task.id, cids, False), task_id='task:%s' % task.id) create_containers.apply(args=(task.id, 1, nshare, cores, cidrs, spec_ips), task_id='task:%s' % task.id) _log.info('migration done')
def create_private(group_name, pod_name, appname): """ncore: 需要的核心数, 可以是小数, 例如1.5个""" data = request.get_json() vstr = data['version'] group, pod, application, version = validate_instance(group_name, pod_name, appname, vstr) # TODO check if group has this pod core_require = int(float(data['ncore']) * pod.core_share) # 是说一个容器要几个核... ncore = core_require / pod.core_share nshare = core_require % pod.core_share ncontainer = int(data['ncontainer']) networks = Network.get_multi(data.get('networks', [])) spec_ips = data.get('spec_ips', []) appconfig = version.appconfig strategy = data.get('strategy', 'average') # 指定的host, 如果没有则按照编排分配host hostname = data.get('hostname', '') host = hostname and Host.get_by_name(hostname) or None if host and not (host.group_id == group.id and host.pod_id == pod.id): current_app.logger.error('Host must belong to pod/group (hostname=%s, pod=%s, group=%s)', host, pod_name, group_name) raise EruAbortException(consts.HTTP_BAD_REQUEST, 'Host must belong to this pod and group') if not data['entrypoint'] in appconfig.entrypoints: current_app.logger.error('Entrypoint not in app.yaml (entry=%s, name=%s, version=%s)', data['entrypoint'], appname, version.short_sha) raise EruAbortException(consts.HTTP_BAD_REQUEST, 'Entrypoint %s not in app.yaml' % data['entrypoint']) ts, keys = [], [] with rds.lock('%s:%s' % (group_name, pod_name)): if strategy == 'average': host_cores = average_schedule(group, pod, ncontainer, ncore, nshare, spec_host=host) elif strategy == 'centralized': host_cores = centralized_schedule(group, pod, ncontainer, ncore, nshare, spec_host=host) else: raise EruAbortException(consts.HTTP_BAD_REQUEST, 'strategy %s not supported' % strategy) if not host_cores: current_app.logger.error('Not enough cores (name=%s, version=%s, ncore=%s)', appname, version.short_sha, data['ncore']) raise EruAbortException(consts.HTTP_BAD_REQUEST, 'Not enough core resources') for (host, container_count), cores in host_cores.iteritems(): t = _create_task( version, host, container_count, cores, nshare, networks, spec_ips, data['entrypoint'], data['env'], image=data.get('image', ''), ) if not t: continue host.occupy_cores(cores, nshare) ts.append(t.id) keys.append(t.result_key) return {'r': 0, 'msg': 'ok', 'tasks': ts, 'watch_keys': keys}
def test_scheduler(test_db): # 10000个16核, 不限制共享数 pod = _create_data(10, -1, 10000) def test_max_container_count(ncore, nshare, expected): start = time.time() assert get_max_container_count(pod, ncore, nshare) == expected delta = time.time() - start _log.debug('test_max_container_count with ncore={}, nshare={}, expected={} takes {}'.format(ncore, nshare, expected, delta)) test_max_container_count_cases = ( (1, 0, 160000), (2, 0, 80000), (3, 0, 50000), (4, 0, 40000), (5, 0, 30000), (1, 5, 100000), (2, 5, 60000), (3, 5, 40000), (1, 1, 140000), (2, 1, 70000), ) for case in test_max_container_count_cases: test_max_container_count(*case) start = time.time() assert len(average_schedule(pod, ncontainer=100, ncore=2)) == 100 print time.time() - start start = time.time() assert len(average_schedule(pod, ncontainer=130, ncore=0, nshare=5)) == 130 print time.time() - start start = time.time() r = average_schedule(pod, ncontainer=10, ncore=1) print time.time() - start assert len(r) == 10 assert sum(i[1] for i in r.keys()) == 10 for (host, count), cores in r.iteritems(): assert len(cores['full']) == 1 assert len(cores['part']) == 0 start = time.time() r = average_schedule(pod, ncontainer=10000, ncore=2) print time.time() - start assert len(r) == 10000 assert sum(i[1] for i in r.keys()) == 10000 for (host, count), cores in r.iteritems(): assert count == 1 assert len(cores['full']) == 2 assert len(cores['part']) == 0 start = time.time() r = average_schedule(pod, ncontainer=10000, ncore=1, nshare=5) print time.time() - start assert len(r) == 10000 assert sum(i[1] for i in r.keys()) == 10000 for (host, count), cores in r.iteritems(): assert count == 1 assert len(cores['full']) == 1 assert len(cores['part']) == 1 start = time.time() r = average_schedule(pod, ncontainer=10000, ncore=2, nshare=3) print time.time() - start assert len(r) == 10000 assert sum(i[1] for i in r.keys()) == 10000 for (host, count), cores in r.iteritems(): assert count == 1 assert len(cores['full']) == 2 assert len(cores['part']) == 1 start = time.time() assert len(centralized_schedule(pod, ncontainer=100, ncore=2)) == 13 print time.time() - start start = time.time() assert len(centralized_schedule(pod, ncontainer=130, ncore=0, nshare=5)) == 5 print time.time() - start start = time.time() r = centralized_schedule(pod, ncontainer=10000, ncore=1) print time.time() - start assert len(r) == 625 assert sum(i[1] for i in r.keys()) == 10000 for (host, count), cores in r.iteritems(): assert count == 16 assert len(cores['full']) == 16 assert len(cores['part']) == 0 start = time.time() r = centralized_schedule(pod, ncontainer=100, ncore=2) print time.time() - start assert len(r) == 13 assert sum(i[1] for i in r.keys()) == 100 for (host, count), cores in r.iteritems(): assert count in (4, 8) if count == 4: assert len(cores['full']) == 8 assert len(cores['part']) == 0 if count == 8: assert len(cores['full']) == 16 assert len(cores['part']) == 0 start = time.time() r = centralized_schedule(pod, ncontainer=30, ncore=1, nshare=5) print time.time() - start assert len(r) == 3 assert sum(i[1] for i in r.keys()) == 30 for (host, count), cores in r.iteritems(): assert count == 10 assert len(cores['full']) == 10 assert len(cores['part']) == 10 assert len(set(cores['part'])) == 5 start = time.time() r = centralized_schedule(pod, ncontainer=20, ncore=2, nshare=3) print time.time() - start assert len(r) == 4 assert sum(i[1] for i in r.keys()) == 20 for (host, count), cores in r.iteritems(): assert count in (2, 6) if count == 2: assert len(cores['full']) == 4 assert len(cores['part']) == 2 assert len(set(cores['part'])) == 1 if count == 6: assert len(cores['full']) == 12 assert len(cores['part']) == 6 assert len(set(cores['part'])) == 2