使用Metaparticle在code中直接编码docker/kubernetes是个好主意吗?

作者 Lu Liang 日期 2018-09-29
使用Metaparticle在code中直接编码docker/kubernetes是个好主意吗?

最近看到一篇文章介绍Metaparticle, 就花了点时间看了看。 吐槽一下, 我个人并不认为类似Metaparticle这类的框架是个好主意。

Metaparticle提供在code里直接编码生docker image, kubernetes pods等等云组件,期望通过这种方式使程序员能够用本身熟悉的语言来操纵dockerfile, 减少编程时来回切换的工作量。 Metaparticle的原理是通过 annotation 或者 decorate pattern的方式在源码里嵌入docker及kubernetes需要的信息。

Metaparticle提供了对java, javascript, python, ruby, go and rust 等多种语言的支持。 下面是以python为例,进行代码分析,看看他是如何实现的。

  • python usage example:
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: