【云原生|实战入门】1:Docker、K8s简单实战与核心概念理解(一)

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 我们将通过操作系统管理进程这个例子来形象的理解容器的概念。

一:容器与镜像


1、简单理解容器

我们将通过操作系统管理进程这个例子来形象的理解容器的概念。


当登录到操作进程之后,可以看到各种进程,这些进程由系统自带的服务进程和用户进程组成。


这些进程之间有这些特点:

1、这些进程可以相互看到、相互通信。

2、使用的是同一个文件系统,可以对同一个文件进行读写操作。

3、使用的是相同的系统资源。


但正是由于这三个特点将会引发一些进程之间的问题等,如:


由于能够互相看到和通信,所以更高权限的进程可以攻击其他的进程。

对于第二点,由于用的同一个文件系统,这些进程都可以对已有的数据进行增删改查,所以,进程之间可能会误删其他进程的数据(例如具有更高级别权限的进程删掉别的进程的数据),这样就会破坏其他进程的正常运行。

进程和进程之间因为是同一个文件系统,所以可能存在依赖冲突,这样会造成不必要的宕机损失。

因为是使用相同的系统资源(即一个宿主机的资源),可能存在资源抢占的问题,当一个应用进程需要大量的CPU和内存资源的时候,就会导致其他应用进程等待、进入死锁等不能提供服务了。

那么针对上述的问题,该怎么样为进程提供一个独立的运行环境来解决问题?


针对不同进程使用同一个文件系统所造成的问题,Linux 和 Unix 操作系统可以通过 chroot 系统调用将子目录变成根目录,达到视图级别的隔离;进程在 chroot 的帮助下可以具有独立的文件系统,对于这样的文件系统进行增删改查不会影响到其他进程。

使用 Namespace 技术来实现进程在资源的视图上进行隔离(因为进程之间可以相互看见和通信)。在 chroot 和 Namespace 的帮助下,进程就能够运行在一个独立的环境下了。

在独立的环境下,进程所使用的还是同一个操作系统的资源,一些进程可能会侵蚀掉整个系统的资源。为了减少进程彼此之间的影响,可以通过 Cgroup 来限制其资源使用率,设置其能够使用的 CPU 以及内存量。

能够解决上述问题的进程运行环境,就是容器了。


容器,就是一个视图隔离、资源可限制、独立文件系统的进程集合。所谓“视图隔离”就是能够看到部分进程以及具有独立的主机名等;控制资源使用率则是可以对于内存大小以及 CPU 使用个数等进行限制。它将系统的其他资源隔离开来,具有自己独立的资源视图。


容器具有一个独立的文件系统,因为使用的是系统的资源,所以在独立的文件系统内不需要具备内核相关的代码或者工具,我们只需要提供容器所需的二进制文件、配置文件以及依赖即可。只要容器运行时所需的文件集合都能够具备,那么这个容器就能够运行起来。

2、Docker容器的三大函数

通过下述三大函数,Docker就实现了解决上述问题。

文件系统问题:chroot & pivot_root

作为一个容器,首要任务就是限制容器中进程的活动范围——能访问的文件系统目录。决不能让容器中的进程去肆意访问真实的系统目录,得将他们的活动范围划定到一个指定的区域,保证上述的问题得到解决。

而限制访问指定的活动区域,就是chroot & pivot_root,通过这两个函数,可以修改进程和系统目录到一个新的位置。有了这两个函数,Docke就可以来“伪造”一个文件系统来欺骗容器中的进程。

Docker用操作系统镜像文件挂载到容器进程的根目录下,变成容器的rootfs,和真实系统目录一模一样:

$ ls /
bin dev etc home lib lib64 mnt opt proc root run sbin sys tmp usr var

资源视图隔离:namespace

文件系统的问题解决了,但是还有一个问题,那就是如何把真实宿主机子系统所在的世界隐藏起来,不能使容器中的进程看到。

比如进程列表、网络设备、用户列表这些,是决不能让容器中的进程知道的,得让他们看到的世界是一个干净如新的系统。Docker虽然叫容器,但这只是表面现象,容器内的进程其实和自己一样,都是运行在宿主操作系统上面的一个个进程。


Docker想过用HOOK的方式,欺骗进程,但实施起来工作太过复杂,兼容性差,稳定性也得不到保障,于是就有了第二个命令:namespace。


这个namespace是linux提供的一种机制,通过它可以划定一个个的命名空间,然后把进程划分到这些命名空间中。(有点类似flask框架中的websocket接口划分namespace命名空间)如下图所示:每个命名空间都是独立存在的,命名空间里面的进程都无法看到空间之外的进程、用户、网络等等信息。将进程的“视野”锁定在容器规定的范围内,如此一来,容器内的进程再也看不到外面的系统资源。

CPU限制率:CGroup

通过上述的两个命令,试着运行了一段时间,一切都在Docker的运行之中,容器中的进程都能正常的运行,都能通过虚拟文件系统和隔离出来的系统环境来运行。


但这个时候redis、nginx等进程也开始加入,这个时候就容易出现问题了,内存容易被Redis等用光,这样Docker就崩了。如果容器中的某个进程可以随意的占用内存、cpu、网络、硬盘等各种资源,那么Docker肯定会崩掉。于是有了CGroup命令来限制资源使用。

CGroup是Linux帝国的一套机制,通过它可以划定一个个的分组,然后限制每个分组能够使用的资源,比如内存的上限值、CPU的使用率、硬盘空间总量等等。系统内核会自动检查和限制这些分组中的进程资源使用量。

3、简单理解镜像

将这些容器运行时所需要的所有的文件集合称之为容器镜像。

通常情况下,会采用 Dockerfile 来构建镜像,这是因为 Dockerfile 提供了非常便利的语法糖,能够很好地描述构建的每个步骤。当然,每个构建步骤都会对已有的文件系统进行操作,这样就会带来文件系统内容的变化,我们将这些变化称之为 changeset。把构建步骤所产生的变化依次作用到一个空文件夹上,就能够得到一个完整的镜像。


changeset有几个很显著的特点:


能够提高分发效率,对于大的镜像而言,如果将其拆分成各个小块就能够提高镜像的分发效率,这是因为镜像拆分之后就可以并行下载这些数据;

因为这些数据是相互共享的,也就意味着当本地存储上包含了一些数据的时候,只需要下载本地没有的数据即可,举个简单的例子就是 golang 镜像是基于 alpine 镜像进行构建的,当本地已经具有了 alpine 镜像之后,在下载 golang 镜像的时候只需要下载本地 alpine 镜像中没有的部分即可;

因为镜像数据是共享的,因此可以节约大量的磁盘空间,简单设想一下,当本地存储具有了 alpine 镜像和 golang 镜像,在没有复用的能力之前,alpine 镜像具有 5M 大小,golang 镜像有 300M 大小,因此就会占用 305M 空间;而当具有了复用能力之后,只需要 300M 空间即可。

4、构造镜像代码

上述的Dockerfile适用于描述如何构建golang应用,每一行的意思大致如下:

FROM 行表示以下的构建步骤基于什么镜像进行构建,正如前面所提到的,镜像是可以复用的;

WORKDIR 行表示会把接下来的构建步骤都在哪一个相应的具体目录下进行,其起到的作用类似于 Shell 里面的 cd;

COPY 行表示的是可以将宿主机上的文件拷贝到容器镜像内;

RUN 行表示在具体的文件系统内执行相应的动作。当我们运行完毕之后就可以得到一个应用了;

CMD 行表示使用镜像时的默认程序名字。

当有了 Dockerfile 之后,就可以通过 docker build 命令构建出所需要的应用。构建出的结果存储在本地,一般情况下,镜像构建会在打包机或者其他的隔离环境下完成。


这些镜像如何运行在生产环境或者测试环境上呢?这时候就需要一个中转站或者中心存储,我们称之为 docker registry,也就是镜像仓库,其负责存储所有产生的镜像数据。我们只需要通过 docker push 就能够将本地镜像推动到镜像仓库中,这样一来,就能够在生产环境上或者测试环境上将相应的数据下载下来并运行了。

5、如何运行容器

第一步:从镜像仓库中将相应的镜像下载下来;

第二步:当镜像下载完成之后就可以通过 docker images 来查看本地镜像,这里会给出一个完整的镜像列表,可以在列表中选中想要的镜像;

第三步:当选中镜像之后,就可以通过 docker run 来运行这个镜像得到想要的容器,当然可以通过多次运行得到多个容器。一个镜像就相当于是一个模板,一个容器就像是一个具体的运行实例,因此镜像就具有了一次构建、到处运行的特点。

6、容器生命周期与数据管理

容器是一组具有隔离特性的进程集合,在使用 docker run 的时候会选择一个镜像来提供独立的文件系统并指定相应的运行程序。这里指定的运行程序称之为 initial 进程,这个 initial 进程启动的时候,容器也会随之启动,当 initial 进程退出的时候,容器也会随之退出。


因此,可以认为容器的生命周期和 initial 进程的生命周期是一致的。当然,因为容器内不只有这样的一个 initial 进程,initial 进程本身也可以产生其他的子进程或者通过 docker exec 产生出来的运维操作,也属于 initial 进程管理的范围内。当 initial 进程退出的时候,所有的子进程也会随之退出,这样也是为了防止资源的泄漏。


但是这样的做法也会存在一些问题,首先应用里面的程序往往是有状态的,其可能会产生一些重要的数据,当一个容器退出被删除之后,数据也就会丢失了,这对于应用方而言是不能接受的,所以需要将容器所产生出来的重要数据持久化下来。容器能够直接将数据持久化到指定的目录上,这个目录就称之为数据卷。


数据卷有一些特点,其中非常明显的就是数据卷的生命周期是独立于容器的生命周期的,也就是说容器的创建、运行、停止、删除等操作都和数据卷没有任何关系,因为它是一个特殊的目录,是用于帮助容器进行持久化的。简单而言,我们会将数据卷挂载到容器内,这样一来容器就能够将数据写入到相应的目录里面了,而且容器的退出并不会导致数据的丢失。

7、VMware与容器对比

VM 利用 Hypervisor 虚拟化技术来模拟 CPU、内存等硬件资源,这样就可以在宿主机上建立一个 Guest OS,这是常说的安装一个虚拟机。

一个 Guest OS 都有一个独立的内核,比如 Ubuntu、CentOS 甚至是 Windows 等,在这样的 Guest OS 之下,每个应用都是相互独立的,VM 可以提供一个更好的隔离效果。但这样的隔离效果需要付出一定的代价,因为需要把一部分的计算资源交给虚拟化,这样就很难充分利用现有的计算资源,并且每个 Guest OS 都需要占用大量的磁盘空间,比如 Windows 操作系统的安装需要 10~30G 的磁盘空间,Ubuntu 也需要 5~6G,同时这样的方式启动很慢。正是因为虚拟机技术的缺点,催生出了容器技术。


容器是针对于进程而言的,因此无需 Guest OS,只需要一个独立的文件系统提供其所需要文件集合即可。所有的文件隔离都是进程级别的,因此启动时间快于 VM,并且所需的磁盘空间也小于 VM。但是相对的进程级别的隔离并没有想象中的那么好,隔离效果相比 VM 要差很多。

完结:Docker容器总结

如下图所示,左边是普通的操作系统管理进程,而右边是使用了容器之后的。

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
1月前
|
运维 Kubernetes 监控
构建高效自动化运维体系:基于Docker和Kubernetes的实践指南
【2月更文挑战第30天】 在当今快速发展的云计算时代,传统的IT运维模式已难以满足业务的敏捷性和稳定性需求。本文深入探讨了如何通过Docker容器化技术和Kubernetes集群管理工具构建一个高效、可靠的自动化运维体系。文章首先概述了容器化技术和微服务架构的基本概念,随后详细阐述了基于Docker的应用打包、部署流程,以及Kubernetes在自动化部署、扩展和管理容器化应用中的关键作用。最后,文中通过案例分析,展示了如何在实际场景中利用这些技术优化运维流程,提高系统的整体效率和可靠性。
|
22小时前
|
存储 运维 Kubernetes
Docker+Kubernetes/K8s+Jenkins视频资料【干货分享】
Docker+Kubernetes/K8s+Jenkins视频资料【干货分享】
Docker+Kubernetes/K8s+Jenkins视频资料【干货分享】
|
1天前
|
存储 Kubernetes Docker
Kubernetes(K8S)集群管理Docker容器(概念篇)
Kubernetes(K8S)集群管理Docker容器(概念篇)
|
12天前
|
Kubernetes 监控 Cloud Native
构建高效云原生应用:基于Kubernetes的微服务治理实践
【4月更文挑战第13天】 在当今数字化转型的浪潮中,企业纷纷将目光投向了云原生技术以支持其业务敏捷性和可扩展性。本文深入探讨了利用Kubernetes作为容器编排平台,实现微服务架构的有效治理,旨在为开发者和运维团队提供一套优化策略,以确保云原生应用的高性能和稳定性。通过分析微服务设计原则、Kubernetes的核心组件以及实际案例,本文揭示了在多变的业务需求下,如何确保系统的高可用性、弹性和安全性。
16 4
|
26天前
|
运维 Kubernetes 持续交付
构建高效自动化运维体系:基于Docker和Kubernetes的最佳实践
在现代云计算环境中,自动化运维成为保障系统稳定性与提升效率的关键。本文深入探讨了如何利用Docker容器化技术和Kubernetes容器编排工具构建一个高效、可靠的自动化运维体系。文中不仅介绍了相关的技术原理,还结合具体案例分析了实施过程中的常见问题及解决方案,为读者提供了一套行之有效的最佳实践指南。
|
28天前
|
Kubernetes 开发工具 Docker
K8S 极速入门
K8S 极速入门
50 0
|
1月前
|
Kubernetes Cloud Native Docker
【云原生】kubeadm快速搭建K8s集群Kubernetes1.19.0
Kubernetes 是一个开源平台,用于管理容器化工作负载和服务,提供声明式配置和自动化。源自 Google 的大规模运维经验,它拥有广泛的生态支持。本文档详细介绍了 Kubernetes 集群的搭建过程,包括服务器配置、Docker 和 Kubernetes 组件的安装,以及 Master 和 Node 的部署。此外,还提到了使用 Calico 作为 CNI 网络插件,并提供了集群功能的测试步骤。
219 0
|
1月前
|
Kubernetes 开发者 Docker
构建高效微服务架构:Docker与Kubernetes的完美搭档
【2月更文挑战第29天】在当今快速发展的软件开发领域,微服务架构已成为提高系统可维护性、扩展性和敏捷性的关键解决方案。本文将深入探讨如何利用Docker容器化技术和Kubernetes集群管理工具,共同构建一个既高效又可靠的微服务环境。我们将分析Docker和Kubernetes的核心功能,并展示它们如何协同工作以简化部署流程、增强服务发现机制以及实现无缝的服务伸缩。通过实际案例分析,本文旨在为开发者提供一套实用的微服务架构设计和实施指南。
|
1月前
|
人工智能 监控 Cloud Native
iLogtail 2.0 来了;通义灵码下载量破百万丨阿里云云原生 2 月产品月报
iLogtail 2.0 来了;通义灵码下载量破百万丨阿里云云原生 2 月产品月报
|
2月前
阿里云云原生恭祝大家新年快乐!
阿里云云原生恭祝大家新年快乐!