几个月前,神雕做系统性的云原生主题分享的时候,提到云原生背后的一个诉求是要解决碎片化变化的问题,要解决一致性的问题,那么如何解决呢?本篇开始,神雕要来着重分享其中一个最重要的解决方案:容器化。无论是在之前公司内部还是帮助金融客户研发云原生平台,或者是目前做电商公司云原生系统演进,首当其冲的一步就是容器化改造,这足以表明容器在云原生领域里的重要性。本文来聊一聊什么是容器、容器的本质、以及容器解决环境一致性问题。
- 什么是容器
容器这个词的字面意思很好理解,用来装东西的基本装置,装的东西类型不同对应各种不同的容器。对于我们程序猿/媛们来讲,容器自然是用来装程序相关的东西,从对象容器(class)、到集合容器(list/set/map)、到 bean容器(Spring)、到web容器(如tomcat)等等,很多YUAN们就是这么一步一步伴随着对这些大大小小“容器”的研究成长起来的。今天我们讲到容器,往往会想到docker,以及他的一句口号:“ build once,run anywhere” ! 然而,容器不仅仅只有docker,但是docker确实最优秀使用最广的一种容器,也是许多公司容器化改造的选择方案。
简单地说,云原生领域的容器包含了完整的运行时环境:除了应用程序本身之外,这个应用所需的全部依赖、类库、其他二进制文件、配置文件等,都统一被打入了一个称为容器镜像的包中。
回顾在云原生第一篇中神雕梳理过容器的发展历史:容器的概念在LCX(Linux Container)的完整能力合入linux主线之后基本定型的,docker是在此五年之后才发布。而docker一出现就凭借着分层的镜像模型、完善的生态体系、以及良好的rest api迅速走红,干掉了CoreOS公司的rkt容器和Google的lmctfy容器,直接变成了容器的事实标准。也就有了前文所说的一提到容器就想到Docker。
后续的故事当然越发精彩:Linux基金会成立了OCI(Open Container Initiative)组织,旨在围绕容器格式和运行时制定一个开放的工业化标准,也就是我们常说的OCI标准;G家的Kubernetes,作为容器云平台的事实标准,先原生支持Docker,然后随着开源的容器运行时Containerd(实现了CRI接口,同样由Docker捐给CNCF)的成熟,K8s不再维护dockershim,仅负责维护标准的CRI,解除与某特定容器运行时的绑定。
- 容器的本质
讲了这么多,好像又是一堆概念,下面以docker作为探寻的对象,我们来聊聊容器的本质. 我们知道作为猿类,用docker来安装一些研发依赖的程序(组件)特别方便,神雕经常这样来启动本地mysql和redis来做local的开发自测。
docker run -itd --name mysql -e MYSQL_ROOT_PASSWORD=123456 mysql
docker run --name pe_redis -p 6379:6379 -d redis:latest redis-server
一行命令,docker便会自动去pull镜像并且运行起来,相比之前下载dmg双击安装确实要方便不少.
命令解释:
docker run //运行docker容器命令
-itd //参数i即interactive打开标准输入,参数t即tty, 参数d后台运行
--name mysql //参数--name 为运行的容器起名mysql
-e MYSQL_ROOT_PASSWORD=123456 //-e设定root密码
mysql //即mysql:latest镜像
完整的命令则是长这个样子:
其中command是运行的命令,如果没有指定则会运行镜像中的CMD,如果镜像也没有指定COMMAND,则会抛出错误,至于镜像是什么,放到后续介绍。现在我们运行:
docker run -d --name="hello_world" dockerinaction/hello_world /bin/sh -c "while true; do echo hello world; sleep 1; done"
他其实是启动了一个进程,从宿主机上看一个运行的容器进程:
然后,我们可以通过exec可以进入该容器
docker exec -it fa00bf48b8b7 /bin/sh
ps一下,发现1号进程正是我们运行容器的CMD,显然1号进程是容器的障眼法而已.
**所以,容器的本质就是进程,是一个和系统其他部分隔离开的进程。**这背后的技术当然还是之前介绍的namespace,回顾下之前的贴图。
- 容器保证运行环境的一致性
在容器出现之前,常常会出现研发人员开发出一个应用后,在笔记本上可以运转起来,但在数据中心就运转不起来的情况,原因在于环境不一致,操作系统系统版本、库版本等等。有了容器之后,这些问题就大大地减少了。因为除了应用程序本身之外,这个应用所需的全部依赖、类库、其他二进制文件、配置文件等,都统一被打入了一个称为容器镜像的包中。
- 小结
容器,云原生时代无处不在的基础设施,除了使用他可以方便的启动依赖的组件,以及他带来的运行一致性的便捷性,我们平时的开发中经常会发现在项目工程里有容器化的一些脚本文件,一般常见的会有一个dockerfile和一个或者多个sh脚本。作为云原生时代的猿,掌握容器相关的技术也将是研发必备能力。