重启容器就不能这么简单粗暴的多线程同时重启了,上边也说了,同时重启就会有服务宕机的风险。线上服务器都有一定的冗余,不能同时重启那么可以分批重启嘛,每次重启多少?分析了流量情况,我们想到了一个算法,如果项目主机少于8台,那么就单线程滚动重启,也用不了太长时间,如果项目主机大于8台,那么用项目主机数/8向上取整,作为多线程重启的线程数多线程重启,这样差不多能保证项目里边有80%左右的主机一直对外提供服务,降低服务不可用的风险,优化后的代码如下:
import threading from math import ceil # 再导入上一个示例里边的Conn类 class DeployThread(threading.Thread): def __init__(self, thread_max_num, host, project_name, environment_name, image_url): threading.Thread.__init__(self) self.thread_max_num = thread_max_num self.host = host self.project_name = project_name self.environment_name = environment_name self.image_url = image_url def run(self): self.smile_host = [] with self.thread_max_num: Conn(self.host).cmd('docker stop %s && docker rm %s' % (self.project_name, self.project_name)) r5 = Conn(self.host).cmd( 'docker run -d --env ENVT=%s --env PROJ=%s --restart=always --name=%s -p 80:80 %s' % ( self.environment_name, self.project_name, self.project_name, self.image_url) ) if r5.get('state'): self.smile_host.append(self.host) print('---->%s镜像更新完成' % (self.host)) else: print('---->%s服务器执行docker run命令失败,details:%s' % (self.host, r5.get('message'))) # check镜像重启状态 and 重启失败需要回滚代码省略 def get_result(self): return self.smile_host if __name__ == '__main__': # 演示代码简化了很多,整体逻辑不变 alive_host = ['10.82.9.47', '10.82.9.48'] image_url = 'ops-coffee:latest' project_name = 'coffee' environment_name = 'prod' # alive_host / 8 向上取整作为最大线程数 thread_max_num = threading.Semaphore(ceil(len(alive_host) / 8)) threads = [] for host in alive_host: t = DeployThread(thread_max_num, host, project_name, environment_name, image_url) threads.append(t) for t in threads: t.start() for t in threads: t.join() smile_host = [] for t in threads: smile_host.append(t.get_result()) print('---->%d台主机更新成功' % (len(smile_host)))Docker环境的持续部署优化实践 (7)
内容版权声明:除非注明,否则皆为本站原创文章。