-
1、简介 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app)。几乎没有性能开销,可以很容易地在机器和数据中心中运行。最重要的是,他们不依赖于任何语言、框架包括系统。 官方链接:https://www.docker.com/ 类别:虚拟化2、基础环境类别子项版本获取地址(方法)华为云虚拟机RC3(916)--OSCentOS7.5 Kernel4.14 软件包Docker1.13.1 3、依赖安装无4、组件编译安装清理 yum 缓存yum clean all下载服务器包到本地缓存yum makecache更新yum 包yum -y update安装dockeryum -y install docker5、系统配置无6、测试测试内容:docker命令是否可正常使用测试结果:正常 7、参考信息官方文档:https://docs.docker.com/部署:https://docs.docker.com/install/linux/docker-ce/centos/ https://get.docker.com/8、FAQA: 运行命令提示“Is the docker daemon running?”Q: docker服务未正常启动,运行systemctl start docker 或 service docker start
-
发现现在华为云还没有 docker-ce 软件源,建议新增 docker-ce 软件源。https://download.docker.com/
-
本期【云享专家·微话题】由云享专家Tsjsdbd与大家一起讨论“容器与虚机,谁将主宰云世界”,希望大家能够畅所欲言。如果大家有其他任何与PaaS相关的问题,也可以在本帖回复直接咨询云享专家Tsjsdbd。 =======【云享专家·微话题】容器与虚机,谁将主宰云世界?=======如今Docker容器技术已经比较普及,在各个领域都开始发挥出价值。并且容器与虚拟机十分和谐的共存,两者各自具有不同的特征和相应适合的应用场景。然而,渐渐地你会发现在各个云基础设所涉及的领地,容器正在以它的角度重建这个世界,容器存储,容器网络,容器调度都全部长出自己的枝干。在实际的领域,容器也开始崭露头角,HPC,基因测序,边缘云,微服务等等。相信有一天,容器会与虚机平起平坐,然后在那之后,迅速超越,成为云计算的中流砥柱。Container will Rebuild the World。每个人对“容器与虚机”都有不一样的理解,今天我们就“容器与虚机”一起来讨论,希望看到大家精彩的评论:1、讲讲你在容器使用过程中存在的问题?2、讲讲容器技术如何在各个技术领域渐露头角?3、容器一直被诟病的薄弱点安全相关进展?4、你觉得容器是否和虚机的各自发展前景?微话题活动:参与本次微话题讨论,有机会获得优质评论奖活动时间:2018年7月16日-7月27日参与方式:直接在本帖回复你关于以上4个问题的理解或评论获奖方式:活动结束后,将由云享专家Tsjsdbd选取出3名优质评论奖,各送出《Docker 容器与容器云》书籍1本。优质评论:建赟:1、讲讲你在容器使用过程中存在的问题? 在容器使用过程中存在的问题有:a、安装非常缓慢,而且经常安装失败。b、Docker所有的镜像都依赖于基础镜像,而这些基础镜像都在国外的docker hub上,镜像pull非常慢。c、默认的dockerhub所有镜像都是公开的,私有仓库价格是非常贵的,而且速度还很慢。d、要在VM上使用docker,需要对网络、存储等做一些特殊的处理。e、使用docker的出发点是降低运维成本,提升效率,但是管理上的成本相反却会上升,需要专业的公司来处理。f、容器的性能。 g、容器的安全。 h、网络的问题。i、容器型运维人员短缺2、讲讲容器技术如何在各个技术领域渐露头角? 容器带来了之前技术所没有的几个新特点。a、与之前的方法相比,Docker让容器部署和使用起来更容易、更安全。b、由于Docker与其他容器领域的巨擘进行了合作,包括Canonical、谷歌、红帽和Parallels,共同开发其关键的开源组件libcontainer,它为容器带来了迫切需要的标准化。c、容器易于部署到云端。3、容器一直被诟病的薄弱点安全相关进展? 对docker容器安全质疑最大的一点就是其隔离的彻底性,将docker生命周期拆为两个大阶段,非生产环境阶段和生产环境阶段,这两个阶段安全控制的目标如下:非生产环境中保证镜像安全可信,生产环境中保证镜像正确的运行。4、你觉得容器是否和虚机的各自发展前景? 说docker代替vm来说还为时过早,长期来看docker会在更多的场景上逐步替代vm的功能,vm技术也会在很长的时间内继续发挥着重要的作用,也许将来两种技术会进行融合,vm技术拥有docker的一些特性,同时docker也会克服自身的一些缺点,变得更加易用。ecstatic:1、讲讲你在容器使用过程中存在的问题? a.项目中docker容器中生成的日志文件名称乱码 b.怎样才能在容器中使用iptables呢 c.容易安装失败 d.kubernetes,mesos框架用不明白2、讲讲容器技术如何在各个技术领域渐露头角? 容器技术最早可以追溯到1979年UNIX系统中的chroot,最初是为了方便切换root目录,为每个进程提供了文件系统资源的隔离,这也是OS虚拟化思想的起源。 2013年Docker诞生,Docker最早是dotCloud(Docker公司的前身,是一家PaaS公司)内部的项目,和Warden类似,Docker最初也用了LXC,后来才自己写了 libcontainer 替换了 LXC。和其它容器技术不同的是,Docker 围绕容器构建了一套完整的生态,包括容器镜像标准、容器Registry、REST API、CLI、容器集群管理工具Docker Swarm等; 2016年微软公司发布基于Windows 的容器技术Hyper-V Container,Hyper-V Container原理和Linux下的容器技术类似,可以保证在某个容器里运行的进程与外界是隔离的,兼顾虚拟机的安全性和容器的轻量级。 为什么要关注Docker或者容器技术呢?容器可以提供隔离性,可以为各种测试提供一个良好的沙盒环境。并且,容器本身就是具有“标准性”的特征,非常适合为服务创建构建块。加速本地开发和构建流程,使其更加高效、更加轻量化。本地开发人员可以构建运行并分享Docker容器。容器可以在开发环境中构建,然后轻松的提交到测试环境,最终 进入生产环境。能够让独立服务或者应用程序在不同的环境中,得到相同的运行结果。用Docker创建隔离的环境来进行测试。eg :JenkinsCIDocker可以让开发者在本机上构建一个复杂的程序或者架构来进行测试,而不是一开始就在生产环境部署、测试。构建一个多用户的平台及服务基础设施。为开发、测试提供一个轻量级的独立沙盒环境,或者将独立的沙盒环境用于技术教学,eg:unix shell 的使用。提供软件及服务应用程序高性能、超大规模的宿主机部署。3、容器一直被诟病的薄弱点安全相关进展? Docker中可能会出现的安全问题 内核漏洞(Kernel exploits) 容器是基于内核的虚拟化,主机(host)和主机上的所有容器共享一套内核。如果某个容器的操作造成了内核崩溃,那么反过来整台机器上的容器都会受到影响。 拒绝服务攻击(Denial-of-service attacks) 所有的容器都共享了内核资源,如果一个容器独占了某一个资源(内存、CPU、各种ID),可能会造成其他容器因为资源匮乏无法工作(形成DoS攻击)。 容器突破(Container breakouts) Linux的namespace机制是容器的核心之一,它允许容器内部拥有一个PID=1的进程而在容器外部这个进程号又是不一样的(比如1234)。现在问题在于如果一个PID=1的进程突破了namespace的限制,那么他将会在主机上获得root权限。 有毒镜像(Poisoned images) 主要是考虑到镜像本身的安全性,没太多好说的。 密钥获取(Compromising secrets) 容器中的应用可能会获取一些容器外部的服务,这些服务之间可能会有密钥(secret key)等,如果因为密钥保存不当,那么这些服务对于攻击者来说就是可获取的了,这就会造成很多隐患。特别的,这样的问题如果出现在微服务架构中就特别严重。 安全方案 主机级别的隔离 主机级别的隔离(Segregate Containers by Host)即将不同用户的容器放在不同的机器上、将那些存放了敏感数据的容器 和普通的容器隔离开来、将哪些直接暴露给终端用户的容器(web容器)隔离开来。 主机级别的隔离的好处是可以防止容器突破攻击、DoS攻击,但是这样的隔离会付出成本甚至性能的代价的。 限制容器的网络 容器应向外暴露尽可能少的端口,此外,对于容器之间的通信,最好是需要通信的容器才是连通的。 移除SUID和SGID的二进制位 限制内存 限制CPU 限制重启 限制文件系统4、你觉得容器是否和虚机的各自发展前景? 随着容器生态圈的继续扩大,容器技术正在与越来越多的行业搭界,不论是过去八竿子打不着的大数据、物联网领域,还是已经闹得沸沸腾腾的微服务、虚拟化,一个更加广阔的后容器技术时代正在到来,他们都将会有更大的发展前景。小修:1、讲讲你在容器使用过程中存在的问题?1. 在docker容器中vi指令找不到2.docker容器启动后没有ifconfig和ping3.Docker客户端和服务器端版本不一致,在某些操作过中会出现错误4.对于基于busybox, alpine等镜像的容器,在执行命令时可能会出现错误5.容器启动后自动退出、或进入“restarting”状态2、讲讲容器技术如何在各个技术领域渐露头角?容器技术已经引起了业内的广泛关注,有充分的证据表明,容器技术能够大大提升工作效率。 现在,虚拟化技术已经成为一种被大家广泛认可的服务器资源共享方式,它可以在按需构建操作系统实例的过程当中为系统管理员提供极大的灵活性。由于hypervisor虚拟化技术仍然存在一些性能和资源使用效率方面的问题,因此出现了一种称为容器(Container)的新型虚拟化技术来帮助解决这些问题。起初,大家普遍认为基于hypervisor的方式可以在最大程度上提供灵活性。所有虚拟机实例都能够运行任何其所支持的操作系统,而不受其他实例的影响。然而,现在越来越多的用户发现hypervisor提供这样一种广泛支持的特性其实是在给自己制造麻烦。对于hypervisor环境来说,每个虚拟机实例都需要运行客户端操作系统的完整副本以及其中包含的大量应用程序。从实际运行的角度来说,由此产生的沉重负载将会影响其工作效率及性能表现。 首先,每种操作系统和应用程序堆栈都需要使用DRAM。对于多个运行简单应用程序的小型虚拟机实例来说,这种方式可能产生很大的系统开销,降低性能表现。加载并卸载这些堆栈镜像需要花费很长时间,并且还会增加容器技术服务器的网络连接数量。对于极端情况来说,如果用户在上午9点同时启动上千台虚拟桌面,还有可能导致网络风暴的发生。部署虚拟服务器的目的之一在于快速创建新的虚拟机实例。然而从网络存储当中复制镜像需要花费大量时间,这些操作会延长启动过程,无疑会限制系统灵活性。 因此我们可以选择使用容器技术。只需要通过简单的观察我们便能够发现容器技术的出现是为了解决多操作系统/应用程序堆栈的问题:在单台服务器当中为所有虚拟机实例使用相同的操作系统对于大部分数据中心来说都不算是真正的限制。流程管理(Orchestration)可以轻松处理这种变化许多应用程序堆栈都是相同的(如LAMP)对于大规模集群来说,在本地硬盘当中存储操作系统副本将会使得更新过程变得更为复杂最为重要的是,容器技术可以同时将操作系统镜像和应用程序加载到内存当中。还可以从网络磁盘进行加载,因为同时启动几十台镜像不会对网络和存储带来很大负载。之后的镜像创建过程只需要指向通用镜像,大大减少了所需内存。 容器技术能够在同一台服务器上创建相比于之前两倍的虚拟机实例数量,因此无疑将会降低系统总投入。但是必须认真进行规划,因为双倍的实例数量同样意味着对于运行这些实例的服务器带来了双倍的I/O负载。 我们需要了解除了避免可能发生的启动风暴之外,容器技术是否还有任何其他性能方面的优势。能否改进IOPS?能够提升网络连接效率并且降低容器间的延迟,解决伴随实例数量增加而产生的问题?美国某传统服务器大厂商的某实验室完成了至今为止大部分权威实验,其研究结果表明容器技术相比于hypervisor,容器技术的许多关键指标都有重大改进。在进行的所有测试当中,容器技术几乎拥有和本地平台一样的运行速度,尽管网络延迟测试还没有完成。 上述厂商的研究表明容器技术在多个领域当中都比hypervisor拥有更好的性能表现。容器技术的运行速度几乎是hypervisor的两倍,在评分当中非常接近于本地操作系统。在和KVM的对比当中,容器技术在硬盘随机读取(84,000 vs 48,000 IOPS)和写入(110,000 vs 60,000 IOPS )方面拥有非常优秀的表现,如果使用本地固态硬盘可以实现更好的SQL性能表现。高性能计算(HPC)社区也在转而使用虚拟化和容器技术。一项由巴西天主教大学进行的研究已经取得了一定成果。“如果可以降低基本的系统开销(比如CPU、内存、硬盘和网络),那么HPC无疑会选择使用虚拟化系统,”研究人员表示。“从这个角度来说,我们发现所有基于容器的系统在CPU、内存、硬盘和网络方面都拥有接近于本地操作系统的性能表现。”美国某虚拟化公司V***re也针对容器技术进行了一系列评测对比。容器技术研究结果印证了容器技术拥有接近本地系统的性能表现,尽管其并没有像IBM实验室那样针对VMware的hypervisor发布非常详细的测试报告。而这项报告的容器技术结果有可能促使VMware做出调整,以降低hypervisor的系统开销。VMware的报告当中没有提及硬盘I/O问题。 为了扩展适用范围,容器技术仍然需要在安全方面不断改进。但是现在,我们可以看到的是这种方式可以解决hypervisor虚拟化当中的大多数性能问题。再加上更加轻松和快捷的部署方式,容器技术将会在不久的将来占据虚拟化市场3、容器一直被诟病的薄弱点安全相关进展?容器安全需要自下而上全面考虑安全风险,从内核,OS ,OS层的网络、软件版本、Selinux策略,Docker版本,Docker的优化配置以及使用方式,image中所依赖的base 以及软件包,容器间的网络隔离。真的是每一处都需要去考虑,任何一个环节的小问题,都有可能造成事故。感觉Docker 安全是个全方位的问题,任何一点疏漏都会带来灾难性后果。有些问题不是Docker本身能解决的,需要多方配合。Docker在这个方面做了哪些工作?4、你觉得容器是否和虚机的各自发展前景?容器实例与主机共享操作系统内核,通过内核提供的运行时隔离能力为服务提供独立的用户域、文件系统、网络以及进程运行空间。虚拟机的每个实例自带操作系统,因而是一种硬件级的虚拟化隔离。容器通常是专用于运行特定服务的,它的镜像通常只包含运行该服务所需的上下文内容,许多广泛使用的镜像都只有几十MB,甚至几MB大小。虚拟机则需要提供包括内核在内的通用进程运行环境,它的镜像偏向于大而完整的全功能集合,即使一个最小精简镜像的体积也有几百MB。容器的使用方式倾向于开箱即用,镜像提供的是一个“不可变的基础设施环境”。虚拟机则倾向于让用户根据所用的系统,自定义初始化操作,使用Ansible、Puppet这样的配置工具来进行基础设施的管理。容器在启动速度和运行性能上更有优势,虚拟机在安全性上更有优势。如果从这些十分清晰的定义来看,近一年来开源界出现的一些虚拟化“边界破坏者”们已经完全无视了这些规则。它们要么是运行在虚拟机中的操作系统,却有着容器一样的使用体验,要么是基于容器技术的运行时隔离,却应该当成虚拟机使用。因此,尽管这些技术的实现细节上差异巨大,但它们都有一个共同特征:携带着容器和虚拟机各一部分的基因,具备两者优势的结合。
-
《直播回看》栏目会将“华为云开发者者联盟”移动端课程平台的精品音视频直播课,定期进行展播,支持各位伙伴进行回看学习本期推荐: 容器-Docker容器和镜像相关技术讨论和解答【主讲人介绍】主讲人:Jarrey Zhou【课程大纲】我们将讨论Docker的基础知识,从Docker的安装到镜像和容器的制作和启动,致力于解决用户使用Docker制作镜像和运行容器遇到的问题,帮大家更快的掌握Docker的原理和学习21天转型云容器课程。【课程链接】可扫描下方二维码进入“华为云开发者联盟“移动端直播间收听课程
-
什么是“容器”和“虚拟机”容器和虚拟机它们的目的很相似:即将应用程序和它的依赖放到一个可以在任何环境运行的自足单元中。此外,容器和虚拟机消除了对物理硬件的需求,从而在能源消耗和成本效益方面能让我们更有效地使用计算资源,容器和虚拟机的主要区别在于它们的架构方式。让我们继续深入了解。虚拟机虚拟机在本质上是对现实中计算机的仿真,它会像真实的计算机一样执行程序。使用 “hypervisor” 可以将虚拟机运行于物理机上。hypervisor 可以在主机运行,也可以在“裸机”上运行。让我们来揭开这些术语的面纱:hypervisor(之后都以虚拟机管理程序称呼)是能让虚拟机在其上运行的软件,固件或者硬件。虚拟机管理程序本身会在物理计算机上运行,称为**“主机”**。主机为虚拟机提供资源,包括 RAM 和 CPU。这些资源在虚拟机之间被划分并且可以根据需要进行分配。所以如果一个虚拟机上运行了资源占用更大的应用程序,相较于其它运行在同一个主机的虚拟机你可以给其分配更多的资源。运行在主机上的虚拟机(再次说明,通过使用虚拟机管理程序)通常也被叫做“访客机”。访客机包含了应用以及运行这个应用所需要的全部依赖(比如:系统二进制文件和库)。它还带有一个自己的完整虚拟化硬件栈,包括虚拟化的网络适配器,储存和 CPU-这意味着它还拥有自己成熟的整个访客操作系统。从虚拟机内部来看,访客机的操作都认为其使用的都是自己的专用资源。从外部来看,我们知道它是一个虚拟机-和其它虚拟机一起共享主机提供的资源。就像前面所提到的,访客机既可以运行在托管的虚拟机管理程序上,也可以运行在裸机虚拟机管理程序上。它们之间存在一些重要的差别。首先,托管的虚拟化管理程序是在主机的操作系统上运行。比如说,可以在一台运行 OSX 操作系统的计算机的系统上安装虚拟机(例如:VirtualBox 或者 VMware Workstation 8)。虚拟机无法直接访问硬件,因此必须通过主机上运行的操作系统访问(在我们的例子中,也就是 Mac 的 OSX 操作系统)。托管虚拟机管理程序的好处是底层硬件并不那么重要。主机的操作系统会负责硬件的驱动而不需要管理程序参与。因此这种方式被认为具备更好的“硬件兼容性”。在另一方面,在硬件和管理程序之间这个额外的附加层会产生更多的资源开销,这会降低虚拟机的性能。裸机虚拟机管理程序通过直接在主机硬件上安装和运行来解决这个性能问题。因为它直接面对底层的硬件,所以并不需要运行在主机的操作系统之上。在这种情况下,安装在主机上第一个作为操作系统运行的就是这个裸机虚拟机管理程序。与托管虚拟机管理程序不同,它有自己的设备驱动直接与每个组件交互,以执行任何 I/O,处理或特定于操作系统的任务。这样可以获得更好的性能,可伸缩性和稳定性。这里的权衡在于其对硬件的兼容性有限,因为裸机虚拟机管理程序内置的设备驱动只有那么多。在讨论了虚拟机管理程序之后,你可能想知道为什么我们需要在虚拟机和主机之间这个额外的“虚拟机管理程序”层。好吧,虚拟机管理程序在其中确实发挥了重要的作用,由于虚拟机拥有自己的虚拟操作系统,管理程序为虚拟机管理和执行访客操作系统提供了一个平台。它允许主机与作为客户端运行的虚拟机之间共享其资源。虚拟机图示正如你可以在图示中所看到的,VMS 会为每个新的虚拟机打包虚拟硬件,一个内核(即操作系统)和用户空间。容器与提供硬件虚拟化的虚拟机不同,容器通过抽象“用户空间”来提供操作系统级别的虚拟化。当我们详解容器这个术语的时候你就会明白我的意思。从所有的意图和目的来看,容器看起来就像一个虚拟机。比如说,它们有执行进程的私有空间,可以使用 root 权限执行命令,具有专有的网络接口和 IP 地址,允许自定义路由和 iptable 规则,可以挂载文件系统等。容器和虚拟机之间的一个重要区别在于容器和其它容器共享主机系统的内核。容器图示这图表明容器只会打包用户空间,而不是像虚拟机那样打包内核或虚拟硬件。每个容器都有自己独立的用户空间从而可以让多个容器在单个主机上运行。我们可以看到所有操作系统级别的体系架构是所有容器共享的。要从头开始创建的部分只有 bins 和 libs 目录。这就是容器如此轻巧的原因。Docker 是从哪来的?Docker 是基于 Linux 容器技术的开源项目。它使用 Luinux 的内核功能(如命名空间和控制组)在操作系统上创建容器。容器已经远远不是一个新技术:Google 已经使用他们自己的容器技术好多年了。其它的容器技术包括 Solaris Zones、BSD jails 和 LXC 也已经存在好多年。那么为啥 Docker 会突然取得成功呢?使用简单:Docker 使得任何人(开发人员,运维,架构师和其他人)都可以更轻松的利用容器的优势来快速构建和测试可移植的应用程序。它可以让任何人在他们的笔记本电脑上打包应用程序,不需要任何修改就可以让应用运行在公有云,私有云甚至裸机上。Docker 的口头禅是:“一次构建,处处运行”。速度:Docker 容器非常轻量级和快速。因为容器只是运行在内核上的沙盒环境,因此它们占用的资源更少。与可能需要更多时间来创建的虚拟机相比,你可以在几秒钟内创建一个 Docker 容器,因为虚拟机每次都必须启动一个完整的操作系统。Docker Hub:Docker 用户也可以从日益丰富的 Docker Hub 生态中受益,你可以把 Docker Hub 看作是 “Docker 镜像的应用商店”。Docker Hub 拥有数万个由社区构建的公共镜像,这些镜像都是随时可用的。在其中搜索符合你需求的镜像非常容易,你只需要准备拉取镜像而且几乎不需要任何修改。模块化和可扩展性:Docker 可以让你轻松地把应用程序按功能拆分为单个独立的容器。比如说,你的 Postgre 数据库可以运行在一个容器中,Redis 服务运行在另一个容器中,而 Node.js 应用运行在另一个容器中。使用 Docker,将这个容器链接在一起以创建你的应用程序将会变得更简单,同时在将来可以很轻松地扩展和更新单独的组件。最后但并不重要的是,有谁不喜欢 Docker 的鲸鱼(Docker 的标志)呢?:)
-
docker官方下载实在是无力吐槽了。前阵子,华为云提供了DockerHub镜像加速。考虑到windows的用户还是有很多,能不能为windows用户提供docker for windows 版本的stable安装包。
-
1 前言前两天有同事发现,通过华为云 ServiceStage 的流水线部署基于模板创建的 CSEJavaSDK demo 服务时,会在容器启动过程中报错。初步排查是由于 JVM 占用的内存超出了 docker 内存配额的上限,导致容器被 kill 掉。于是我们需要排查一下问题出在哪里,为什么以前没有这类问题,而现在却发生了。2 基本定位要确定 docker 容器内存超限问题的直接原因并不难。直接进入docker容器,执行 top 命令,我们发现宿主机是一台8核16G的机器,而且 docker 并不会屏蔽这些信息,也就是 JVM 会认为自己工作于一台 16G 内存的机器上。而查看 demo 服务的 Dockerfile,发现运行服务时并没有对 JVM 的内存进行任何限制,于是 JVM 会根据默认的设置来工作 —— 最大堆内存为物理内存的1/4(这里的描述并不完全准确,因为 JVM 的默认堆内存大小限制比例其实是根据物理内存有所变化的,具体内容请自行搜索资料),而基于模板创建的 ServiceStage 流水线,在部署应用堆栈的时候会把 docker 容器的内存配额默认设置为 512M,于是容器就会在启动的时候内存超限了。至于以前没有碰到过这种问题的原因,只是因为以前没将这么高规格的 ECS 服务器用于流水线部署应用堆栈。在查询过相关资料后,我们找到了两种问题解决方案,一个是直接在 jar 包运行命令里加上 -Xmx 参数来指定最大堆内存,不过这种方式只能将 JVM 堆内存限制为一个固定的值;另一个方法是在执行 jar 包时加上 -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap 参数,让 JVM 能够感知到docker容器所设置的 cgroup 限制,相应地调整自身的堆内存大小,不过这个特性是 JDK 8u131 以上的版本才具备的。最终,我们提醒 ServiceStage 流水线的同学将 CSEJavaSDK demo 的创建模板做了改进,在 Dockerfile 中将打包的基础镜像版本由原先的 java:8u111-jre-alpine 升级为了 openjdk:8u181-jdk-alpine,并且在运行服务 jar 包的命令中加上了 -Xmx256m参数。问题至此已经解决了。3 进一步的探究虽然问题已经解决,但是在好奇心的驱使下,我还是打算自己找个 demo 实际去触发一下问题,另外看看从网上搜到的解决方法到底好不好用 : )3.1 准备工作3.1.1 创建云上工程首先需要在华为云 ServiceStage 创建一个云上工程。在 ServiceStage -> 应用开发 -> 微服务开发 -> 工程管理 -> 创建云上工程中,选择“基于模板创建”,语言选择 Java, 框架选择 CSE-Java (SpringMVC),部署系统选择“云容器引擎CCE”,给你的云上工程取一个名字,比如test-memo-consuming,最后选择存放代码的仓库,就可以完成云上工程的创建了。之后云上工程会根据你的选项自动地生成脚手架代码,上传到你指定的代码仓库中,并且为你创建一条流水线,完成代码编译、构建、打包、归档镜像包的操作,并且使用打好的 docker 镜像包在 CCE 集群中部署一个应用堆栈。创建云上工程和流水线不是本文的重点,我就不详细讲操作了 : )。同一个应用堆栈的实例可以部署多个,在这里为了实验方便就按照默认值1个来部署。由于云上工程已经改进了脚手架代码的模板,不会再出现内存超限的问题,所以我们现在能看到 demo 服务已经正常的跑起来,微服务实例已经注册到服务中心了。登录到 demo 服务所部署的容器,使用curl命令可以调用 demo 服务的 helloworld 接口,可以看到此时服务已经可以正常工作。3.1.2 增加实验代码为了能够触发微服务实例消耗更多的内存,我在项目代码中增加了如下接口,当调用/allocateMemory接口时,微服务实例会不停申请内存,直到 JVM 抛出 OOM 错误或者容器内存超限被 kill 掉。private HashMap<String, long[]> cacheMap = new HashMap<>(); @GetMapping(value = "/allocateMemory") public String allocateMemory() { LOGGER.info("allocateMemory() is called"); try { for (long i = 0; true; ++i) { cacheMap.put("key" + i, new long[1024 * 1024]); } } catch (Throwable t) { LOGGER.info("allocateMemory() gets error", t); } return "allocated"; }此时用来打镜像包的基础镜像是openjdk:8u181-jdk-alpine,jar 包启动命令中加上了-Xmx256m参数。执行流水线,应用堆栈部署成功后,调用/allocateMemory接口触发微服务实例消耗内存,直到 JVM 抛出 OOM 错误,可以在 ServiceStage -> 应用上线 -> 应用管理中选择相应的应用,点击进入概览页面,查看应用使用内存的情况。应用使用的内存从 800M+ 陡然下降的时间点就是我重新打包部署的时间,而之后由于调用/allocateMemory接口,内存占用量上升到了接近 400M,并且在这个水平稳定了下来,显示-Xmx256m参数发挥了预期的作用。3.2 复现问题现在将 demo 工程中的 Dockerfile 修改一下,将基础镜像改为 java:8u111-jre-alpine,并且删除启动命令中的-Xmx256m参数,将其提交为noLimit_oldBase分支,推送到代码仓库中。然后编辑流水线,将 source 阶段的任务所使用的代码分支改为noLimit_oldBase分支,保存并重新运行流水线,将新的代码打包部署到应用堆栈中。在微服务实例列表中查询到新的微服务实例的 endpoint IP 后,调用`/allocateMemory`接口,观察内存情况,内存从接近 400M 突然掉下去一下,然后又上升到约 450M 的时间点就是修改代码后的微服务实例部署成功的时间点,之后内存占用量突然下跌就是因为调用`/allocateMemory`接口导致容器内存超限被 kill 掉了。如果你事先使用docker logs -f命令查看容器日志的话,那么日志大概是这个样子的2018-11-23 15:40:04,920 INFO SCBEngine:152 - receive MicroserviceInstanceRegisterTask event, check instance Id... 2018-11-23 15:40:04,920 INFO SCBEngine:154 - instance registry succeeds for the first time, will send AFTER_REGISTRY event. 2018-11-23 15:40:04,925 WARN VertxTLSBuilder:116 - keyStore [server.p12] file not exist, please check! 2018-11-23 15:40:04,925 WARN VertxTLSBuilder:136 - trustStore [trust.jks] file not exist, please check! 2018-11-23 15:40:04,928 INFO DataFactory:62 - Monitor data sender started. Configured data providers is {com.huawei.paas.cse.tcc.upload.TransactionMonitorDataProvider,com.huawei.paas.monitor.HealthMonitorDataProvider,} 2018-11-23 15:40:04,929 INFO ServiceCenterTask:51 - read MicroserviceInstanceRegisterTask status is FINISHED 2018-11-23 15:40:04,939 INFO TestmemoconsumingApplication:57 - Started TestmemoconsumingApplication in 34.81 seconds (JVM running for 38.752) 2018-11-23 15:40:14,943 INFO AbstractServiceRegistry:258 - find instances[1] from service center success. service=default/CseMonitoring/latest, old revision=null, new revision=28475010.1 2018-11-23 15:40:14,943 INFO AbstractServiceRegistry:266 - service id=8b09a7085f4011e89f130255ac10470c, instance id=8b160d485f4011e89f130255ac10470c, endpoints=[rest://100.125.0.198:30109?sslEnabled=true] 2018-11-23 15:40:34,937 INFO ServiceCenterTaskMonitor:39 - sc task interval changed from -1 to 30 2018-11-23 15:47:03,823 INFO SPIServiceUtils:76 - Found SPI service javax.ws.rs.core.Response$StatusType, count=0. 2018-11-23 15:47:04,657 INFO TestmemoconsumingImpl:39 - allocateMemory() is called Killed可以看到allocateMemory方法被调用,然后 JVM 还没来得及抛出 OOM 错误,整个容器就被 kill 掉了。这里也给大家提了一个醒:不要以为自己的服务容器能启动起来就万事大吉了,如果没有特定的限制,JVM 会在运行时继续申请堆内存,也有可能造成内存用量超过 docker 容器的配额!3.3 让 JVM 感知cgroup限制前文提到还有另外一种方法解决 JVM 内存超限的问题,这种方法可以让 JVM 自动感知 docker 容器的 cgroup 限制,从而动态的调整堆内存大小,感觉挺不错的。我们也来试一下这种方法,看看效果如何 ; )回到demo项目代码的master分支,将 Dockerfile 中启动命令参数的-Xmx256m替换为-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap,提交为useCGroupMemoryLimitForHeap分支,推送到代码仓库里。再次运行流水线进行构建部署。等 demo 服务部署成功后,再次调用`/allocateMemory`接口,容器的内存占用情况如上图所示(最右边的那一部分连续曲线),内存上升到一定程度后,JVM 抛出了 OOM 错误,没有继续申请堆内存。看来这种方式也是有效果的。不过,仔细观察容器的内存占用情况,可以发现容器所使用的内存仅为不到 300M,而我们对于这个容器的内存配额限制为 512M,也就是还有 200M+ 是闲置的,并不会被 JVM 利用。这个利用率,比起上文中直接设置-Xmx256m的内存利用率要低 : ( 。推测是因为 JVM 并不会感知到自己是部署在一个 docker 容器里的,所以它把当前的环境当成一个物理内存只有 512M 的物理机,按照比例来限制自己的最大堆内存,另一部分就被闲置了。如此看来,如果想要充分利用自己的服务器资源,还是得多花一点功夫,手动调整好-Xmx参数。4 参考资料Java and Docker, the limitationsJava inside docker: What you must know to not FAIL本文转载自Docker容器内部署Java微服务的内存限制问题
-
本文基于华为云容器镜像服务实践所编写,将一个单体应用进行容器改造为例,展示如何写出可读性更好的Dockerfile,从而提升镜像构建速度,构建层数更少,体积更小的镜像。下面是一个常见企业门户网站架构,由一个Web Server和一个数据库组成,Web Server提供web服务,数据库保存用户数据。通常情况下,这样一个门户网站安装在一台服务器上。如果把应用运行在一个Docker容器中,那么很可能写出下面这样的Dockerfile来。FROM ubuntuADD . /appRUN apt-get update RUN apt-get upgrade -y RUN apt-get install -y nodejs ssh mysql RUN cd /app && npm install# this should start three processes, mysql and ssh# in the background and node app in foreground# isn't it beautifully terrible? <3CMD mysql & sshd & npm start当然这样Dockerfile有很多问题,这里CMD命令是错误的,只是为了说明问题而写。下面的内容中将展示对这个Dockerfile进行改造,说明如何写出更好的Dockerfile,共有如下几种处理方法。一个容器只运行一个进程不要在构建中升级版本将变化频率一样的RUN指令合一使用特定的标签删除多余文件选择合适的基础镜像设置WORKDIR和 CMD使用ENTRYPOINT (可选)在entrypoint脚本中使用exec优先使用COPY合理调整COPY与RUN的顺序设置默认的环境变量,映射端口和数据卷使用EXPOSE暴露端口使用VOLUME管理数据卷使用LABEL设置镜像元数据添加HEALTHCHECK使用USER做权限控制编写.dockerignore文件使用多阶段构建一个容器只运行一个进程从技术角度讲,Docker容器中可以运行多个进程,您可以将数据库,前端,后端,ssh等都运行在同一个Docker容器中。但是,这样跟未使用容器前没有太大区别,且这样容器的构建时间非常长(一处修改就要构建全部)、镜像体积大、横向扩展时非常浪费资源(不同的应用需要运行的容器数并不相同)。通常所说的容器化改造是对应用整体微服务架构改造,再容器化,这样做可以带来如下好处。单独扩展:拆分为微服务后,可单独增加或缩减每个微服务的实例数量。提升开发速度:各微服务之间解耦,某个微服务的代码开发不影响其他微服务。通过隔离确保安全:整体应用中,若存在安全漏洞,会获得所有功能的权限。微服务架构中,若攻击了某个服务,只可获得该服务的访问权限,无法入侵其他服务。隔离崩溃:如果其中一个微服务崩溃,其它微服务还可以持续正常运行。如前面的示例可以改造成下面架构,Web应用和MySQL运行在不同容器中。MySQL运行在单独的镜像中,下面的示例中删掉了MySQL,只安装node.js。FROM ubuntuADD . /appRUN apt-get update RUN apt-get upgrade -yRUN apt-get install -y nodejs RUN cd /app && npm installCMD npm start不要在构建中升级版本为了降低复杂性、减少依赖、减小文件大小、节约构建时间,你应该避免安装任何不必要的包。例如,不要在数据库镜像中包含一个文本编辑器。apt-get upgrade会使得镜像构建非常不确定,在构建时不确定哪些包会被安装,此时可能会产生不一致的镜像,因为你不再有你的应用程序该如何运行以及包含在镜像中依赖的哪种版本的正确源文件。如果基础镜像中的某个包过时了,你应该联系它的维护者。如果你确定某个特定的包,比如 foo,需要升级,使用 apt-get install -y foo 就行,该指令会自动升级 foo 包。删掉apt-get upgrade后,Dockerfile如下:FROM ubuntuADD . /appRUN apt-get updateRUN apt-get install -y nodejsRUN cd /app && npm installCMD npm start将变化频率一样的RUN指令合一Docker镜像是分层的,类似于洋葱,它们都有很多层,为了修改内层,则需要将外面的层都删掉。Docker镜像有如下特性:Dockerfile中的每个指令都会创建一个新的镜像层。镜像层将被缓存和复用。Dockerfile修改后,复制的文件变化了或者构建镜像时指定的变量不同了,对应的镜像层缓存就会失效。某一层的镜像缓存失效之后,它之后的镜像层缓存都会失效。镜像层是不可变的,如果我们再某一层中添加一个文件,然后在下一层中删除它,则镜像中依然会包含该文件,只是这个文件在Docker容器中不可见。将变化频率一样的指令合并在一起,目的是为了更好的将镜像分层,避免带来不必要的成本。如本例中将node.js安装与npm模块安装放在一起的话,则每次修改源代码,都需要重新安装node.js,这显然不合适。FROM ubuntuADD . /appRUN apt-get update \ && apt-get install -y nodejs \ && cd /app \ && npm install CMD npm start因此,正确的写法是这样的:FROM ubuntuRUN apt-get update && apt-get install -y nodejs ADD . /appRUN cd /app && npm installCMD npm start使用特定的标签当镜像没有指定标签时,将默认使用latest 标签。因此, FROM ubuntu 指令等同于FROM ubuntu:latest。当镜像更新时,latest标签会指向不同的镜像,这时构建镜像有可能失败。如下示例中使用16.04作为标签。FROM ubuntu:16.04RUN apt-get update && apt-get install -y nodejs ADD . /app RUN cd /app && npm installCMD npm start删除多余文件假设我们更新了apt-get源,下载解压并安装了一些软件包,它们都保存在/var/lib/apt/lists/目录中。但是,运行应用时Docker镜像中并不需要这些文件。因此最好将它们删除,因为它会使Docker镜像变大。示例Dockerfile中,删除/var/lib/apt/lists/目录中的文件。FROM ubuntu:16.04RUN apt-get update \ && apt-get install -y nodejs \ && rm -rf /var/lib/apt/lists/* ADD . /app RUN cd /app && npm installCMD npm start选择合适的基础镜像在示例中,我们选择了ubuntu作为基础镜像。但是我们只需要运行node程序,没有必要使用一个通用的基础镜像,node镜像应该是更好的选择。更好的选择是alpine版本的node镜像。alpine是一个极小化的Linux发行版,只有4MB,这让它非常适合作为基础镜像。FROM node:7-alpineADD . /app RUN cd /app && npm installCMD npm start设置WORKDIR和 CMDWORKDIR指令可以设置默认目录,也就是运行RUN / CMD / ENTRYPOINT指令的地方。CMD指令可以设置容器创建是执行的默认命令。另外,您应该将命令写在一个数组中,数组中每个元素为命令的每个单词。FROM node:7-alpineWORKDIR /app ADD . /app RUN npm installCMD ["npm", "start"]使用ENTRYPOINT (可选)ENTRYPOINT指令并不是必须的,因为它会增加复杂度。ENTRYPOINT是一个脚本,它会默认执行,并且将指定的命令作为其参数。它通常用于构建可执行的Docker镜像。FROM node:7-alpineWORKDIR /app ADD . /app RUN npm installENTRYPOINT ["./entrypoint.sh"] CMD ["start"]在entrypoint脚本中使用exec在前文的entrypoint脚本中,我使用了exec命令运行node应用。不使用exec的话,我们则不能顺利地关闭容器,因为SIGTERM信号会被bash脚本进程吞没。exec命令启动的进程可以取代脚本进程,因此所有的信号都会正常工作。优先使用COPYCOPY指令非常简单,仅用于将文件拷贝到镜像中。ADD相对来讲复杂一些,可以用于下载远程文件以及解压压缩包。FROM node:7-alpineWORKDIR /appCOPY . /appRUN npm installENTRYPOINT ["./entrypoint.sh"] CMD ["start"]合理调整COPY与RUN的顺序将变化最少的部分放在Dockerfile的前面,这样可以充分利用镜像缓存。示例中,源代码会经常变化,则每次构建镜像时都需要重新安装NPM模块,这显然不是我们希望看到的。因此我们可以先拷贝package.json,然后安装NPM模块,最后才拷贝其余的源代码。这样的话,即使源代码变化,也不需要重新安装NPM模块。FROM node:7-alpineWORKDIR /appCOPY package.json /app RUN npm install COPY . /appENTRYPOINT ["./entrypoint.sh"] CMD ["start"]设置默认的环境变量,映射端口和数据卷运行Docker容器时很可能需要一些环境变量。在Dockerfile设置默认的环境变量是一种很好的方式。另外,我们应该在Dockerfile中设置映射端口和数据卷。示例如下:FROM node:7-alpineENV PROJECT_DIR=/appWORKDIR $PROJECT_DIRCOPY package.json $PROJECT_DIR RUN npm install COPY . $PROJECT_DIRENTRYPOINT ["./entrypoint.sh"] CMD ["start"]ENV指令指定的环境变量在容器中可以使用。如果你只是需要指定构建镜像时的变量,你可以使用ARG指令。使用EXPOSE暴露端口EXPOSE 指令用于指定容器将要监听的端口。因此,你应该为你的应用程序使用常见的端口。例如,提供 Apache web 服务的镜像应该使用 EXPOSE 80,而提供 MongoDB 服务的镜像使用 EXPOSE 27017。对于外部访问,用户可以在执行 docker run 时使用一个标志来指示如何将指定的端口映射到所选择的端口。FROM node:7-alpineENV PROJECT_DIR=/appWORKDIR $PROJECT_DIRCOPY package.json $PROJECT_DIR RUN npm install COPY . $PROJECT_DIRENV APP_PORT=3000EXPOSE $APP_PORTENTRYPOINT ["./entrypoint.sh"] CMD ["start"]使用VOLUME管理数据卷VOLUME 指令用于暴露任何数据库存储文件,配置文件,或容器创建的文件和目录。强烈建议使用 VOLUME来管理镜像中的可变部分和用户可以改变的部分。下面示例中填写一个媒体目录。FROM node:7-alpineENV PROJECT_DIR=/appWORKDIR $PROJECT_DIRCOPY package.json $PROJECT_DIR RUN npm install COPY . $PROJECT_DIRENV MEDIA_DIR=/media \ APP_PORT=3000VOLUME $MEDIA_DIR EXPOSE $APP_PORTENTRYPOINT ["./entrypoint.sh"] CMD ["start"]使用LABEL设置镜像元数据你可以给镜像添加标签来帮助组织镜像、记录许可信息、辅助自动化构建等。每个标签一行,由 LABEL 开头加上一个或多个标签对。 注意:如果你的字符串中包含空格,必须将字符串放入引号中或者对空格使用转义。如果字符串内容本身就包含引号,必须对引号使用转义。FROM node:7-alpine LABEL com.example.version="0.0.1-beta"添加HEALTHCHECK运行容器时,可以指定--restart always选项。这样的话,容器崩溃时,docker daemon会重启容器。对于需要长时间运行的容器,这个选项非常有用。但是,如果容器的确在运行,但是不可用怎么办?使用HEALTHCHECK指令可以让Docker周期性的检查容器的健康状况。我们只需要指定一个命令,如果一切正常的话返回0,否则返回1。当请求失败时,curl --fail 命令返回非0状态。示例如下:FROM node:7-alpine LABEL com.example.version="0.0.1-beta"ENV PROJECT_DIR=/app WORKDIR $PROJECT_DIRCOPY package.json $PROJECT_DIR RUN npm install COPY . $PROJECT_DIRENV MEDIA_DIR=/media \ APP_PORT=3000VOLUME $MEDIA_DIR EXPOSE $APP_PORT HEALTHCHECK CMD curl --fail http://localhost:$APP_PORT || exit 1ENTRYPOINT ["./entrypoint.sh"] CMD ["start"]使用USER做权限控制如果某个服务不需要特权执行,建议使用 USER 指令切换到非 root 用户。先在 Dockerfile 中使用类似 RUN groupadd -r postgres && useradd -r -g postgres postgres 的指令创建用户和用户组。你应该避免使用 sudo,因为它不可预期的 TTY 和信号转发行为可能造成的问题比它能解决的问题还多。如果你真的需要和 sudo 类似的功能(例如,以 root 权限初始化某个守护进程,以非 root 权限执行它),你可以使用 gosu。最后,为了减少层数和复杂度,避免频繁地使用 USER 来回切换用户。 注意:在镜像中,用户和用户组每次被分配的 UID/GID 都是不确定的,下次重新构建镜像时被分配到的 UID/GID 可能会不一样。如果要依赖确定的 UID/GID,你应该显示的指定一个 UID/GID。编写.dockerignore文件.dockerignore 的作用和语法类似于 .gitignore,可以忽略一些不需要的文件,这样可以有效加快镜像构建时间,同时减少Docker镜像的大小。构建镜像时,Docker需要先准备context ,将所有需要的文件收集到进程中。默认的context包含Dockerfile目录中的所有文件,但是实际上,我们并不需要.git目录等内容。示例如下:.git/使用多阶段构建在 Docker 17.05 以上版本中,你可以使用多阶段构建来减少所构建镜像的大小。
-
本期【云享专家·微话题】由云享专家Tsjsdbd与大家一起讨论“容器与虚机,谁将主宰云世界”,希望大家能够畅所欲言。如果大家有其他任何与PaaS相关的问题,也可以在本帖回复直接咨询云享专家Tsjsdbd。 =======【云享专家·微话题】容器与虚机,谁将主宰云世界?=======如今Docker容器技术已经比较普及,在各个领域都开始发挥出价值。并且容器与虚拟机十分和谐的共存,两者各自具有不同的特征和相应适合的应用场景。然而,渐渐地你会发现在各个云基础设所涉及的领地,容器正在以它的角度重建这个世界,容器存储,容器网络,容器调度都全部长出自己的枝干。在实际的领域,容器也开始崭露头角,HPC,基因测序,边缘云,微服务等等。相信有一天,容器会与虚机平起平坐,然后在那之后,迅速超越,成为云计算的中流砥柱。Container will Rebuild the World。每个人对“容器与虚机”都有不一样的理解,今天我们就“容器与虚机”一起来讨论,希望看到大家精彩的评论:1、讲讲你在容器使用过程中存在的问题?2、讲讲容器技术如何在各个技术领域渐露头角?3、容器一直被诟病的薄弱点安全相关进展?4、你觉得容器是否和虚机的各自发展前景?微话题活动:参与本次微话题讨论,有机会获得优质评论奖活动时间:2018年7月16日-7月27日参与方式:直接在本帖回复你关于以上4个问题的理解或评论获奖方式:活动结束后,将由云享专家Tsjsdbd选取出3名优质评论奖,各送出《Docker 容器与容器云》书籍1本。
-
很多同学在使用镜像构建的时候可能对构建配置选项里的 “Dockerfile目录” 和 “自定义构建路径” 要怎么填感觉有点懵逼,这里给大家分享一点干货帮助大家正确地填写这两个配置项,让大家更好的使用镜像构建功能。 19455 以下图weathermap工程为例,Dockerfile位于工程的 weather/Dockerfile目录下,因此只需要在“Dockerfile目录”中填写weather/Dockerfile即可,记住一定要带上Dockerfile这个文件名哟。所以这里的填写方法就是以工程的跟目录为起始完整地填写Dockerfile的文件路径+文件名即可。 19457 那“自定义构建路径”要怎么填写呢,这里就得说到华为镜像构建一个很人性化的功能,我们平时自己在进行构建时一般会使用如下命令 docker build -t xxx/xxxx:xxx . (这个红色的点不是句号,这个红色的点不是句号,这个红色的点不是句号重要的事情说三遍) 那问题来了这个点到底是什么意思呢,这个点其实就是我们的构建路径,一般我们使用 . 表示在当前目录下进行构建,还是以上面那个工程为例,当你进入到weathermap的根目录的执行上述命令的时候 . 的含义就是 ./ 表示在当前工程的根目录进行构建,当你进入到Dockerfile所在的weather目录执行以上命令的时候 . 的路径其实就是 ./weather 是不是有些明白了,但是又有点糊涂了这个配置项的到底有什么作用呢? 再来举一个栗子···· 我写了一个Dockerfile, 里边有一行COPY run.sh /home/workspace 经常写Dockerfile的同学对这样的命令肯定一点都不陌生,它就是拷贝一个文件到容器的/home/workspace下,那它是从哪里拷呢?就是从我们上面说到的构建目录里去拷,如果我们还是采用上述命令,以 . 作为构建路径,那我们就必须要保证执行构建命令路径下有该文件,否则制作镜像就会失败。 华为的镜像构建默认都是在工程的根目录下进行构建的,但是我就是任性,我就是不一样的花火,我就是要把需要拷贝的文件放到Dockerfile所在的目录下,这个时候要怎么办呢?还是以weathermap工程为例,我们只需要把“自定义构建路径”填写成 /weather 这样就相当于我们进入到了weather 目录再进行构建,这样我们就可以拷贝 weather 目录下的文件了。 辣么...问题来了,华为的镜像构建为啥不直接进入到Dockerfile所在的目录再执行构建呢, 我说了我就是任性,我就是不一样的花火, 我现在就要把Dockerfile放到/weather 目录下,但是我还想要把被拷贝的run.sh 文件放到工程的根目录下,这个时候对华为的镜像构建而言一切也很简单,我们只需要和上面一样继续指定Dockerfile的目录为weather/Dockerfile 然后把 “自定义构建路径”填成 . (亦或 / 亦可不填), 就满足了这样的场景 所以 “自定义构建路径” 提供了一个更灵活的方式让大家去组合Dockerfile 和构建路径的关系。 PS: 有一点要补充的是,Dockerfile文件必须要在个构建路径之下, 这个要怎么解释呢,比如你的Dockerfile是放在 pathA/pathB/pathC/Dockerfile目录下那你的构建路径只能是 / 或 /pathA 或 /pathA/pathB 或 /pathA/pathB/pathC。 至于为什么要这样呢,这个就得去问问Docker了。。。
-
摘要:本文不讲晦涩难懂的概念、不讲实现原理、不讲内核机制,仅仅从搭建一个简单web应用的场景出发,讲讲如何复用docker完成我们开发过程中的一些日常事务,达到提升研发效率的目的。Docker自12年发布,经过几年的蛰伏,15,16年势头猛劲,在大量的企业得到的实施,尤其是在互联网、大数据相关领域更是势不可挡。然而,在一些传统行业、政府、事业机关、小企业中,Docker的使用率还是相对较低的,原因是多方面的,但其中很重要一个原因,源于对这些铺天盖地席卷而来的新技术的“恐惧”。企业发展到一定规模后,其技术架构、组织架构、研发模式基于已经稳定,新技采用势必会对现有组织、业务产生影响,而这种影响的好坏,早期是很难判断的,因此除了少数技术狂热派,一般都会比较谨慎,然而小的初创公司,又很难承担一次技术选型的失败,因此更愿意去采用生态相对成熟、实施过程能有较大容错空间的技术。但是经过这些年的市场的磨练,Docker其实已经成为了云计算领域的一员老将,技术栈、生态各方面已经得到完善。本次以部署一个简单的web应用为例,希望能给还徘徊在Docker门口的开发者、决策者们一些启发,如何利用Docker来简化日常研发工作、提升研发效率。本文所讲解示例如下图,是一个简化的web应用模型,包含了常用的组件,下面将详细讲解如何基于Docker快速完成整个环境的搭建和软件的部署。搭建MySQL数据库一行命令搞定!docker run –dti-e MYSQL_ROOT_PASSWORD=123456 mysql:5.7执行docker ps|grep mysql命令,能看到mysql的容器已经启动,比起下载、安装还有各种配置,够快吧。当然这样运行起来的MySQL,还没有办法供外部服务直接访问,,需要把容器内的服务开个通道,让外部服务通过宿主机的地址找到这个特殊通道,才能实现与外部服务的交互。在宿主机上执行netstat发现3306端口并未对外开放 把容器内的服务映射到宿主机上加上参数 -p 宿主机监听port:容器开放port,建立“通道”,这样当用户访问宿主机的port时,请求会自动发送到容器内对应的端口上docker run -dti -p 3306:3306 -eMYSQL_ROOT_PASSWORD=123456 --namemysql-service mysql:5.7加上端口映射后就可以通过宿主机访问了 对容器运行时产生的数据进行持久化因为每次执行docker run,相当于从指定镜像重新启动一台电脑,镜像是静态不变的,那么意味着,重启后之前运行时产生的数据会全部丢失,一切回归到初始状态,这个对数据库是致命的,如果不能持久化存储数据,也就失去了其意义,Docker也就不可能走到现在。在启动容器时,加上参数 -v 宿主机目录:容器内目录,即可将宿主机的目录mount到容器中,这样容器销毁时,宿主机目录的数据还在,重新启动容器,会继续从宿主机加载数据,借尸还魂,很机智。docker run -dti -p 3306:3306 -eMYSQL_ROOT_PASSWORD=123456 -v /usr1/mysql_data:/var/lib/mysql --name mysql-service mysql:5.7现在运行起来的MySQL就基本上已经能满足日常的需求了。当然,MySQL镜像本身还提供了强大的业务参数(这个是镜像制作者提供的,并非Docker提供),通过dockerrun的 -e 参数指定容器运行的环境变量(等价于Dockerfile里的ENV参数),实现相应的mysql能力,非常有用:MYSQL_ROOT_PASSWORD:指定root用户的密码MYSQL_USER: 新创建一个普通用户MYSQL_PASSWORD:新创建用户的密码MYSQL_DATABASE:新创建一个databaseMYSQL_ALLOW_EMPTY_PASSWORD:是允许无密码登陆想要使用时只需要通过加到命令行里即可,如:docker run -d -p 3306:3306 --namemysql-service -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_USER=visitor -eMYSQL_PASSWORD=visitor -e MYSQL_DATABASE=visitordb -eMYSQL_ALLOW_EMPTY_PASSWORD=true -v /usr1/mysql_data:/var/lib/mysql mysql:5.7这为我们制作业务镜像提供了一些参考,把部署、运行时所需要的变量,通过容器环境变量的方式传递给业务组件,当然业务组件也需要实现从这些约定好的变量里取值。使用定制的MySQL镜像,初始化数据当然,仅仅把MySQL启动起来大部分场景下是不够的,还需要创建业务需要的database、tables,有些时候可能还要导入一些初始的数据。接下来就讲一下,如何通过对官方镜像进行定制,实现在启动容器时,自动执行指定脚本,来创建表、初始化数据。定制镜像,就是基于官方的mysql镜像,加上一些脚本、修改一些权限,再统一打包到新的镜像里,在容器启动后自动执行这些脚本,做一些我们需要的业务操作。首先,我们以mysql:5.7作为基础镜像FROM mysql:5.7(语法:FROM 镜像名称:镜像版本号)然后,把需要在MySQL容器启动后执行的脚本拷贝到目录/docker-entrypoint-initdb.d下。(MySQL镜像启动后会扫描这个目录,然后自动执行里面的shell和sql脚本)COPY ./setup.sh/docker-entrypoint-initdb.d/setup.sh (语法:COPY 文件所在的主机路径:镜像中的绝对路径)接着,把setup.sh会引用到的其它文件,如shell,sql,config等,放到脚本中引用的目录下。(如果有多个脚本需要执行,都放在mysql指定目录下时,mysql并不知道脚本的执行先后顺序,因此一般是在mysql指定目录下放一个执行入口文件,在该文件中去按业务逻辑调用其它文件)COPY ./init.sql /myinfo/init.sql最后,在执行shell脚本时,希望root用户不输入密码就能登陆MySQL,这里需要按MySQL镜像的规范,设置一个环境变量:ENV MYSQL_ALLOW_EMPTY_PASSWORD yes(语法:ENV 环境变量名称 环境变量值)这样就生成了我们需要的Dockerfile文件执行 docker build . -t mysql:cust1就能生成我们自己的镜像了,后面加上参数-t就可以给生成的镜像打上标签,以便进行版本管理。运行该镜像的命令与最开始提到的一样,只是镜像的版本需要使用最新生成的mysql:cust1,这里不再赘述。上面MySQL的示例,涵盖了80%常用的docker制作和运行的指令和参数,这也就是我一直认为,Docker技术也许很高深,但使用确实很简单的原因。搭建tomcat,运行后台服务接下来按照制作MySQL镜像的方式,制作tomcat服务镜像,一个带有VisitorService应用的tomcat定制镜像,这里不再一步步讲解,直接把成品的Dockerfile拿出来给大家分享。FROM tomcat:7-jre8COPY ./VisitorService.war /usr/local/tomcat/webapps就是这么简单,两行搞定,思路和写MySQL的Dockerfile是一样的:1、先选择一个基础镜像:因为程序是基于JDK1.8开发的,所以选择了tomcat:7的jre1.8版本进行定制,具体还有哪些可用的镜像版本,可以在dockerhub官网查到2、然后把自定义的内容塞到镜像里:把编译好的war包拷贝到tomcat的webapps目录下,就像平时在自己测试机上操作一样。如果我们不想每次编译完war包都重新构建镜像,也可以用类似于MySQL目录映射的方法,在运行tomcat镜像时,把本地存放war包的路径,映射到容器的webapps目录下。3、设置环境变量:因为应用中会连接数据库,需要在启动容器时,把数据库信息加入到环境变量中,或在dockerfile中通过EVN参数设置,但因为值是会变的,直接写在dockerfile中,灵活性会差很多,因此我们采用了在启动时通过-e 的方式来设置,代码里已实现从环境变量获取这些信息。最终运行业务软件镜像容器的命令参考如下,命令行完成了目录映射、环境变量设置,并指定要启动的镜像版本:docker run -p 9999:8080 -v 本地目录/war文件:/usr/local/tomcat/webapps/xxx.war-eMYSQL_ADDR=mysql_ip:3306 -e MYSQL_DB=visitordb -e MYSQL_USER=visitor -eMYSQL_PWD=visitor -dti tomcat:7-jre8搭建nginx,运行静态web服务与Tomcat类似,也是有两种方法一种是,把需要部署在Nginx上的文件,以及配置打包到镜像中:FROM nginx:v2COPY ./index.html /usr/visitor/index.htmlCOPY ./visitor.conf/etc/nginx/conf.d/visitor.conf另一种是,从本地目录映射:docker run -p 80:80 -v 本地目录/xx.conf:/etc/nginx/conf.d/xx.conf -v本地目录:容器目录-dti nginx搭建并运行Redis服务因为只是存取一些缓存数据,因此不考虑对容器内的数据做持久化,直接放在容器里,因此这里不对redis镜像做任何改造,直接使用。docker run –p 6379:6379 –dti redis:2.8.23大功告成好了,一套简易的web应用环境就搭好了,下面就是最终效果我们来对比一下Docker帮我们提升了多少效率:环境搭建效率提升明显 说实话,以前搭环境最怕的就是像Nginx这种,下完还要编译之后才能运行的,一旦报错,那真是对耐性的考验。现在好了,一个Dockerfile,加docker build,docker run两个命令,轻轻松松搞定环境的搭建,以前这些困难全没了。最关键的是,日常研发过程中,搭建3至5套环境是最基本的要求了,使用编写好的Dockerfile,可以让我们快速完成各种TEST/QA/STAGE环境、Demo演示环境的搭建与复制,而不需要为拷贝动辄几十G的安装包而苦恼,也不会因为各各环境操作系统版本的差异而痛苦,着实为我们省了不少时间和精力。后记正因为Docker这么火,所有的公有云厂商不约而同的都提供了容器服务,这进一步降低了用户的使用门槛,让企业用户无需关心日常运维、问题处理、版本升级、技术演进等纷繁复杂的事务,使用户更专注于自身业务竞争力的提升。华为云提供的容器服务包括云容器引擎服务(CCE)和云容器实例服务(CCI),围绕着云容器,还提供了镜像管理、应用编排、应用运维管理、微服务管理、云中间件等一系列构建容器化应用生态所需的配套服务,并在兼容社区的基础上,针对游戏、电商、基因等行业,对容器的网络性能、计算性能、存储性能、安全等方面进行了优化,能满足广大用户CI/CD、自动化运维、秒级弹性伸缩、高并发低时延、高性能运算的诉求。赶紧点击下面的链接来体验一下吧:华为云容器引擎:https://console.huaweicloud.com/cce2.0/华为云容器实例:https://console.huaweicloud.com/cci/
-
华为云docker镜像加速何时启用?
-
作者介绍:田晓亮,8年软件行业经验,曾就职于三星,2012年进入云计算领域,对PaaS,DevOps,APM有深入的研究和实践经验,方案支撑近千台VM中的应用部署监控。 2016年加入华为担任架构师,负责微服务的Go语言开发框架及Service Mesh设计和落地,Go语言微服务框架已被华为5G核心网络采用,Service Mesh服务也已在华为云商用上线。 微服务架构是个难题,但解法有多个微服务是一个很大的概念,从团队组织到最佳实践似乎都有实施微服务的一些指导。我们这里只提构建微服务的架构模式,也就是关乎到你用什么样的方式来构建你以微服务架构来组织的应用系统。近些年随着微服务的火热,越来越多的团队开始进行实践,将微服务纷纷落地,也许你是从0开始,一步步地完成了单体应用向微服务的改造,让我们来看看,你解决了多少问题。 13830图1 微服务架构需要解决的问题 微服务将原本内存中函数的调用转换为网络中的调用后,就牵扯到这些问题,而任何一个分支展开,都会涉及一系列的问题。业务开发者也许真的有精力去学习架构相关的复杂问题,然而对于公司来说,真正有价值的是业务本身,让业务开发者解决这些问题需要花费浪费大量的时间精力,导致业务上线受到影响。那我们来看看是否有便捷的方式来解决业务开发者的痛点。Chassis模式 一句话来概括:一种语言开发框架来作为微服务开发的底座,封装掉复杂性,帮助你解决跨网络带来的问题,让用户聚焦在上层业务逻辑的开发。通常情况下会实现以下功能: [*]日志、Metrics、分布式追踪数据上报 [*]健康检查 [*]对接统一的配置中心实现动态配置 [*]对接注册中心 [*]实现负载均衡、熔断降级、容错、限流等保证高可靠运行的功能 现在我们来看看业界有哪些可用的Chassis框架 [*]Spring Cloud [*]ServiceComb [*]Dubbo [*]Go-Micro [*]Go-Kit 先不细去纠结微服务的严格定义,也先暂且搁置诸如“某些老旧框架是否是真的微服务框架”这类争议,从实现方式来看,上述服务化框架都是将分布式系统开发的复杂性进行了一定程度的封装然后提供了简便的开发接口供使用者调用。但是,用这种方式构建微服务还有一些问题: [*]多语言SDK支持:微服务提倡不同组件使用最适合它的语言开发,但是这需要每种语言都有开发框架,不断实现相同的功能。上面可以看到只有go语言和Java语言出现了微服务开发框架,其他语言呢? [*]不论代码侵入程度,都需要开发者思考如何与SDK结合,并从代码层面做出改变,对于大部分开发者来说都是一个高曲线的学习过程。 [*]绑定了特定技术栈,一旦想抽身就需要一定程度上的代码改造。 [*]老旧单体应用由于无人维护,耦合程度高等问题无法进行改造,在进行微服务拆分的过程中重用遗留代码变得无比困难。而且微服务的拆分难以分步进行,需要一个相对较长的周期将系统整体拆分后才能上线。 我们知道技术演进来自于在实践中不断地将功能抽象,解耦,封装,服务化。 [*]云计算技术出现前是数据中心虚拟化,不断地实践使技术发展形成理论和新的实践。IaaS是一种封装,如今开发者与大部分技术团队不需要再学习虚拟化等技术以及如何维护数据中心。 [*]没有TCP/IP的时代,开发人员需要自己考虑网络间数据包的传输,以及网络传输代码与业务代码完全耦合的问题,如今,开发者已经不需要关心,操作系统和开发语言已经封装好网络传输过程。 是否也可以把语言框架提供的能力抽象,成为服务? 在引入后面内容前,我先介绍下SideCar模式SideCar模式 [*]在近些年受到Kubernetes对容器调度方式的启示而日渐受到关注的一种功能部署模式,也是一种微服务的设计模式。 [*]主要利用了一个Pod中的容器可以共享存储与网络的能力,或者说在一个Host中,这个模式也同样适用。 [*]一般分为应用容器和工具容器,工具容器可以重用。 一个典型的场景如下: 13831图2 SideCar典型场景 应用容器与日志同步工具在同一个Pod下,共享存储卷,应用程序生成的日志文件会由日志同步工具收集并发送到类似kafka,elasticsearch这样服务中。在这样的架构下我们获得了什么呢? [*]以容器作为基础打包单元,那么就可以分给不同的团队进行开发测试 [*]Sidecar容器可重用,可以与不同的容器结合 [*]以容器作为错误边界,使服务能够独立开发和测试,比如应用服务在没有日志保存功能的情况下也可以独立运行 [*]独立回滚与更新(但需要考虑复杂的版本组合,建议使用语义版本管理对版本进行控制) 在这个模式的基础之下,我们引入了Service mesh。Service Mesh 新瓶中的那一杯老酒什么是Service Mesh Service mesh最早是由Linkerd给出的定义,我们来看看英文版:[indent]A service mesh is a dedicated infrastructure layer for handling service-to-service communication. It’s responsible for the reliable delivery of requests through the complex topology of services that comprise a modern, cloud native application. In practice, the service mesh is typically implemented as an array of lightweight network proxies that are deployed alongside application code, without the application needing to be aware. (But there are variations to this idea, as we’ll see.)The concept of the service mesh as a separate layer is tied to the rise of the cloud native application. In the cloud native model, a single application might consist of hundreds of services; each service might have thousands of instances; and each of those instances might be in a constantly-changing state as they are dynamically scheduled by an orchestrator like Kubernetes. Not only is service communication in this world incredibly complex, it’s a pervasive and fundamental part of runtime behavior. Managing it is vital to ensuring end-to-end performance and reliability.[/indent]大致的意思如下: [*]一种基础设施层服务,服务间的通信通过service mesh进行 [*]可靠地传输复杂拓扑中服务的请求,将它们变成现代的云原生服务 [*]一种网络代理的实现,通常与业务服务部署在一起,业务服务不感知 [*]一种网络模型,在TCP/IP之上的抽象层,TCP/IP负责将字节码可靠地在网络节点间传递,Service mesh则复杂将服务间的协议请求可靠地在服务间进行传输。它们不关心传输的内容 [*]TCP/IP仅仅负责传输,但Service mesh可对运行时进行控制,使服务变得可监控,可管理。 为什么使用Service Mesh [*]无需考虑每种语言都要解决的问题 [*]对业务代码0侵入,开发者无需关心分布式架构带来的复杂性以及引入的技术问题 [*]对于不适合改造的老旧单体应用,提供了一种接入分布式环境的方式 [*]微服务化的进程通常不是一蹴而就的,很多应用选择了演进的方式,就是将单体应用一部分一部分地进行拆分。而在这个过程中,使用Service Mesh就可以很好地保证未拆分的应用与已经拆分出来的微服务之间的互通和统一治理 [*]开发出的应用既是云原生的又具有云独立性,不将业务代码与任何框架,平台或者服务绑定 依然没有银弹,我们来看看Service mesh解决不了的问题 [*]无分布式事务方案 [*]Service Mesh组件代理请求转发,会在一定程度上降低系统通信性能 [*]没有Event Driven的框架 [*]侵入式框架以源码和业务代码结合,有较强定制和扩展能力,Service mesh相对不易定制扩展 [*]在运行时,依赖单独的Service Mesh代理,多了一个故障点。整个系统的运行和运维也强依赖于Service Mesh组件的能力 Service Mesh的实践历程和设计思路Service Mesh在华为公司内部的发展历程 第一代: 基于NGINX的微服务代理该平台是华为公司内部使用的微服务开发部署运行平台,开发于2013年,用于公司内部某电信业务。在这个业务系统中有大概400多个左右的微服务,实例数量根据局点大小不一样,一个典型的部署为800多个左右实例的规模。整体架构如下:13832图3基于NGINX的微服务代理的平台整体架构 其中的Internal Router组件用来给开发者解决分布式架构中的可靠传输问题: [*]使用高性能nginx及其相应的lua扩展作为Internal Router,将Http服务接入 [*]使用RouteAgent负责注册/注销实例,更新IR的实例信息 [*]使用zookeeper作为注册中心 [*]以Per-Host的方式部署在微服务所运行的环境中 用这种方式构建的微服务环境已经在超过200个局点的生产环境下得到使用,整体运行情况良好。但是随着时间的推移,当业务对敏捷的要求越来越大,而且容器的使用也越来越广泛,这种方式带来了一些问题: [*]使用lua脚本扩展注册发现,负载均衡,熔断,降级,容错,限流,但lua的扩展性有一定的局限 [*]用RouteAgent负责服务的注册以及每个NGINX上服务实例路由的刷新,RA需清楚地感知本节点上的微服务都有哪些,但是使用Kubernetes做容器调度后微服务和实例的分布信息在K8S里面集中记录 [*]容器的IP更多,变化更频繁,使用RouteAgent刷新NGINX路由的方式会导致NGINX服务受到影响,频繁的路由刷新导致业务运行收到影响 [*]当IR服务失败后,整个Host中的服务都会丢失,无法与外界建立联系 为了解决这些问题,出现了第二代的解决方案: HSA Sidecar13833图4 HSA Sidecar设计 HSA是华为内部的一套微服务开发框架,它提供了注册中心,配置中心,java开发框架,以及SideCar等组件 [*]基于Java 微服务框架开发,非侵入式通信方式,支持RPC与Http,提供SOAP协议转换,但会导致性能下降 [*]与微服务部署在一个Pod中即Sidecar模式 [*]作为代理服务,使微服务自动获得注册发现,负载均衡,熔断,降级,容错限流等功能 [*]占用资源很高,一个应用实例一个Sidecar实例的部署方式,会占用过高资源 虽然第一代的问题解决了,但是第二代的Sidecar在性能和资源占用上有很大的问题,在少量的技术项目中试用后,因为资源占用过高的问题无法在大规模环境中推广使用。CSE Mesher介绍 Service Mesh 模式的一种实现。基于自研的Go语言微服务框架(该框架即将开源)开发,使用ServiceComb注册中心(已经开源)与CSE配置中心,以Sidecar的方式部署在微服务所运行的环境中,也可以PerHost模式运行。在用户数据面使用,提供VM部署、公有云部署、容器部署,占用资源小(闲置10多M,并发运行时30多M)。基本能力 注册发现注册中心为插件化模块,目前对接了ServiceComb、Service Center,未来还会有更多的系统对接进来 13834图5 可插件化的注册中心 路由规则管理根据预定义的路由规则对请求进行引流 [*]支持权重引流:比如将5%的流量引到购物车的1.0版本,20%引到2.0版本 [*]可根据服务请求特征进行引流:比如消费者的请求中Header带有的用户名为Json,那么可以引流到某个服务的特定版本中 [*]利用读写锁,路由可在运行时更新,并且不丢失请求 协议转换与不同框架的对接与统一治理使用标准OpenAPI契约,可以实现Dubbo RPC协议与Http协议的互转,用于透明地接入遗留的Dubbo应用并对遗留应用进行统一的服务治理使用负载均衡与重试策略 [*]负载均衡器会调用注册中心插件进行实例查询 [*]在查询中的实例里表中,使用Filter进行过滤 [*]将过滤后的实例传入Strategy中进行实例选择 [*]默认提供RoundRobin Random,会话粘滞策略 [*]具备容错能力且加入Backoff算法,增强网络稳定性 使用熔断降级熔断使用的断路器对一个执行过程进行包装,断路器负责监控维护每个执行过程的状态、结果、错误、超时。当达到一定阀值时就会熔断,并触发降级。以这样的机制来保护服务提供者,不会出现级联的雪崩式错误。使用限流提供了消费者端与提供者端限流用户可以通过配置来限制每秒只允许多少个请求被发出或者接受对接监控Metrics:提供了主动上报到CSE Dashborad的方式。也可与华为公有云APM,Prometeus对接 分布式追踪:对接Zipkin架构设计 整体架构13835图6 CSE Mesher整体架构 Mesher背靠CSE组件,使用微服务引擎中的服务中心与配置中心等服务作为控制面,Mesher与业务代码部署在一起运行在数据面数据面13836图7 CSE Mesher数据面 即Service mesh组件本身,对所有请求进行处理,它有以下功能 [*]发现服务 [*]执行路由策略 [*]负载均衡 [*]拦截所有请求并处理,转发 [*]认证鉴权 [*]生成监控数据 控制面13837图8 CSE Mesher控制面 为管理人员提供统一的管理入口,为所有运行的mesher提供配置下发但不会介入服务请求 [*]注册中心:服务上下线感知 [*]下发配置:使用Web Console对运行时更改,负载均衡,熔断容错,限流等策略 [*]对接监控服务与监控页面 [*]调度引擎:这里并非是微服务引擎提供的组件,是可选组件,这个组件负责拉起服务,维护实例数,在资源池中调度分配实例,这里推荐使用ServiceStage负责实例的生命周期管理 运行场景 不同的部署方式与业务服务部署在一起有3种运行模式1.仅消费者使用Mesher,提供者为使用ServiceComb开发框架的服务或者裸服务,下图为例:ServiceC为裸服务,它既不用mesher也不用SDK,那么起码它需要自己注册到服务中心中,供其它服务发现,否则无法进行访问。13838图9 仅消费者使用Mesher 2.消费者与提供者均使用Mesher13839图10 消费者与提供者均使用Mesher 以这种方式运行的服务可以使用透明TLS传输,并且拥有了服务端限流3.提供者使用Mesher,消费者A使用ServiceComb SDK进行开发可直接发现服务B,但是消费者C作为裸服务需要自己发现服务B 13840图11 仅提供者使用Mesher 运行时请求处理消费者端请求 13841图12 消费端发送请求流程 上图为例:SockShop服务将mesher作为代理并使用地址http://order/list访问订单服务 [*]Destination Resolver 目标微服务名解析,支持插件定制,可根据请求特征决定微服务名是什么 [*]Source Resolver 将IP地址解析为微服务实体信息 [*]路由决策 根据Source和Destination 信息决定最终要访问哪个微服务 [*]处理链 处理链为可随时**或减少的模块,在这里Mesher实现了限流,熔断,降级,负载均衡等功能 [*]传输层 最终请求通过传输层发送到目标微服务实例 提供者端接收请求 13842图13 提供者端接收请求流程 上图为收到远程请求后的处理过程 [*]服务端接到请求,将IP地址解析为微服务信息 [*]进入处理链,这一步并没有负载均衡而是直接使用local selection 进行处理 性能对比 13843图14 Mesher1.0、Istio 0.1.6 (Envoy)、Linkerd1.1.3性能对比 在性能对比后,我聊下自己的看法 [*]Linkerd 作为java实现的service mesh,受到资源占用的拖累,考虑到数据中心成本,不适合作为SideCar和应用部署在一起,相信它的主要场景在于Kubernetes Ingress和Daemonset,并且由于只有数据面,需要和别的生态系统对接获得控制面能力,否则,业务团队又要考虑自己开发控制面。 [*]目前Istio已知问题是每次请求都要调用一次Mixer API来传送metric数据,相信未来版本能够解决,但不能满足我们内部的产品节奏。 [*]作为对比,Mesher通过Channel与Go协程机制主动上报metric数据,以此获得更高的性能,机制如下:模块将数据传送到channel中,协程收到信号并主动上报,在这样的机制下开启监控,性能只有百分之2左右的下降。 13844图15 Metric数据上报机制 一些思考以及未来华为为什么开发了自己的Service Mesh [*]Istio的性能问题没有解决,Envoy每次访问请求Mixer API导致性能下降 [*]Istio强绑定Kubernetes平台(1.7.4+),虽然有着良好的架构,对接不同平台不是问题但需要时间,Mesher贯彻不将开发者绑定到任何框架和平台的理念 [*]从成本角度讲Linkerd并不适合做SideCar部署,JVM资源占用较多 [*]过去在ServiceComb中的积累:Service center,Config center,Go SDK,Governance UX已经提供了大量技术积累,可用于做Mesher的控制面。 [*]既然非侵入式与侵入式都不是银弹,侵入式(ServiceComb Java)与Mesher提供的非侵入式框架的无缝结合,混编就变得有价值了,开发者可以因地制宜,选择适合自己的方案。 Service Mesh是个大舞台 现在已经出现了越来越多的Service mesh实现: [*]数据面:Linkerd,Nginx,Envoy [*]控制面:Istio Linkerd 是在2016年出现的,Envoy在6个月后出现,不过Envoy已经在2015年就商用了。这两个项目也是最有名的Service Mesh。Istio在2017年5月出现,它提供了控制面,并使用Envoy作为数据面的Service Mesh。目前已经开始有些Service Mesh提供者宣布与Istio进行集成,比如Linkerd和Nginx。这意味着控制面与数据面是解耦的,任何的控制面都可以和数据面Service Mesh进行集成。CSE Mesher也会考虑与Istio进行集成,成为除了Envoy之外的另一种数据面选择。实际上在开源项目之外,很多公司内部也早已用类似的方案进行自己系统的构建,各自有各自的特点用来解决自己的实际问题。Istio成为CNCF里面一个被认为是“Kubernetes之后的第二个爆款”是有理由的,它提供了一种从平台的角度解决应用架构的思路,进一步简化了应用的开发。我们也相信在这个大舞台上会有更多的方案出现,而这些方案的出现也会让微服务和Cloud Native应用的构建方式有更多地选择。我们团队也已经基于多年的实践经验将当前的内部Service Mesh方案包含在华为云的“微服务引擎”中,开放给外部用户使用。希望可以作为一种参考,可以给正在选择实施微服务架构方案的读者一些帮助。
-
在docker中可以使用docker save命令将镜像保存为本地文件,有如下两种方式:1. docker save imageid,例如: 11574 2. docker save imagename:tag,例如: 11575 如果要使用docker save命令保存下来的文件在SWR前端界面上传的话,需要使用方法2来保存文件。 如果使用方法1保存的文件在前端上传的话,前端会提示镜像格式不合法。 原因:使用方式1保存的镜像中manifest.json文件中的Repotag字段为NULL,这样在前端上传后,SWR后端无法解析 出该镜像到底属于哪个仓库,导致上传失败。方法2保存的镜像中manifest.json文件中的Repotag字段则会保存仓库地址和tag信息, 这样在前端上传就不会出现问题。
推荐直播
-
HDC深度解读系列 - Serverless与MCP融合创新,构建AI应用全新智能中枢2025/08/20 周三 16:30-18:00
张昆鹏 HCDG北京核心组代表
HDC2025期间,华为云展示了Serverless与MCP融合创新的解决方案,本期访谈直播,由华为云开发者专家(HCDE)兼华为云开发者社区组织HCDG北京核心组代表张鹏先生主持,华为云PaaS服务产品部 Serverless总监Ewen为大家深度解读华为云Serverless与MCP如何融合构建AI应用全新智能中枢
回顾中 -
关于RISC-V生态发展的思考2025/09/02 周二 17:00-18:00
中国科学院计算技术研究所副所长包云岗教授
中科院包云岗老师将在本次直播中,探讨处理器生态的关键要素及其联系,分享过去几年推动RISC-V生态建设实践过程中的经验与教训。
回顾中 -
一键搞定华为云万级资源,3步轻松管理企业成本2025/09/09 周二 15:00-16:00
阿言 华为云交易产品经理
本直播重点介绍如何一键续费万级资源,3步轻松管理成本,帮助提升日常管理效率!
回顾中
热门标签