最近看到一篇文章介绍Metaparticle, 就花了点时间看了看。 吐槽一下, 我个人并不认为类似Metaparticle这类的框架是个好主意。
Metaparticle提供在code里直接编码生docker image, kubernetes pods等等云组件,期望通过这种方式使程序员能够用本身熟悉的语言来操纵dockerfile, 减少编程时来回切换的工作量。 Metaparticle的原理是通过 annotation 或者 decorate pattern的方式在源码里嵌入docker及kubernetes需要的信息。
Metaparticle提供了对java, javascript, python, ruby, go and rust 等多种语言的支持。 下面是以python为例,进行代码分析,看看他是如何实现的。
from metaparticle import Containerize @Containerize(package={'name': 'testcontainer', 'repo': 'brendanburns', 'publish': True}) def main(): print('hello world') if __name__ == '__main__': main()
decorate function source code
通过write_dockerfile函数来生成docker file, 然后在类Containerize里build/run image.
def write_dockerfile(package, exec_file): if hasattr(package, 'dockerfile') and package.dockerfile is not None: shutil.copy(package.dockerfile, 'Dockerfile') return copy_files = "\n".join([addFile.render() for addFile in package.additionalFiles]) with open('Dockerfile', 'w+t') as f: f.write("""FROM python:{version}-alpine COPY ./ /app/ {copy_files} RUN pip install --no-cache -r /app/requirements.txt CMD python -u /app/{exec_file} """.format(version=package.py_version, exec_file=exec_file, copy_files=copy_files)) class Containerize(object): def __init__(self, runtime={}, package={}): self.runtime = option.load(option.RuntimeOptions, runtime) self.package = option.load(option.PackageOptions, package) self.image = "{repo}/{name}:latest".format( repo=self.package.repository, name=self.package.name ) self.builder = builder.select(self.package.builder) self.runner = runner.select(self.runtime.executor) def __call__(self, func): def wrapped(*args, **kwargs): if is_in_docker_container(): return func(*args, **kwargs) exec_file = sys.argv[0] slash_ix = exec_file.find('/') if slash_ix != -1: exec_file = exec_file[slash_ix:] write_dockerfile(self.package, exec_file) self.builder.build(self.image) if self.package.publish: self.builder.publish(self.image) def signal_handler(signal, frame): self.runner.cancel(self.package.name) sys.exit(0) signal.signal(signal.SIGINT, signal_handler) self.runner.run(self.image, self.package.name, self.runtime) return self.runner.logs(self.package.name) return wrapped
这种Metaparticle方式的问题在于生成docker image的方式太死了而且严重的依赖Metaparticle本身的实现, 而且配置的改动要改code,容易引起问题。我认为解决这个痛点的方式,应该从编译模块入手。例如在对于Java,可以在maven里加入插件来实现直接生成部署docker image。
Refer to: