什么是容器
容器是镜像的可运行实例。容器是您机器上的沙盒进程,与主机上的所有其他进程隔离。总而言之,一个容器:
- 是图像的可运行实例。您可以使用 DockerAPI 或 CLI 创建、启动、停止、移动或删除容器。
- 可以在本地机器、虚拟机上运行或部署到云端。
- 可移植(可以在任何操作系统上运行)
- 容器彼此隔离并运行自己的软件、二进制文件和配置。
容器的最初的目的不是为了部署软件,而是为了隔离计算机中的各类资源,以便降低软件开发、测试阶段可能产生的误操作风险,或者专门充当蜜罐,吸引黑客的攻击,以便监视黑客的行为。
容器是云计算、微服务等诸多软件业界核心技术的共同基石,容器的首要目标是让软件分发部署过程从传统的发布安装包、靠人工部署转变为直接发布已经部署好的、包含整套运行环境的虚拟化镜像。在容器技术成熟之前,主流的软件部署过程是由系统管理员编译或下载好二进制安装包,根据软件的部署说明文档准备好正确的操作系统、第三方库、配置文件、资源权限等各种前置依赖以后,才能将程序正确地运行起来。
什么是容器镜像?
运行容器时,它使用隔离的文件系统。此自定义文件系统由容器映像提供。由于镜像包含容器的文件系统,它必须包含运行应用程序所需的一切——所有依赖项、配置、脚本、二进制文件等。镜像还包含容器的其他配置,例如环境变量、运行的默认命令、和其他元数据。
什么是Docker
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器镜像中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。
epub360 docker file 介绍
Kubernetes:
如果说以 Docker 为代表的容器引擎将软件的发布流程从分发二进制安装包转变为直接分发虚拟化后的整个运行环境,令应用得以实现跨机器的绿色部署;那以 Kubernetes 为代表的容器编排框架,就是把大型软件系统运行所依赖的集群环境也进行了虚拟化,令集群得以实现跨数据中心的绿色部署,并能够根据实际情况自动扩缩。
以容器构建系统
自从 Docker 提出“以封装应用为中心”的容器发展理念,成功取代了“以封装系统为中心”的 LXC 以后,一个容器封装一个单进程应用已经成为被广泛认可的最佳实践。然而单体时代过去之后,分布式系统里应用的概念已不再等同于进程,此时的应用需要多个进程共同协作,通过集群的形式对外提供服务,以虚拟化方法实现这个目标的过程就被称为容器编排(Container Orchestration)。
容器之间顺畅地交互通信是协作的核心需求,但容器协作并不仅仅是将容器以高速网络互相连接而已。如何调度容器,如何分配资源,如何扩缩规模,如何最大限度地接管系统中的非功能特性,让业务系统尽可能免受分布式复杂性的困扰都是容器编排框架必须考虑的问题,只有恰当解决了这一系列问题,云原生应用才有可能获得比传统应用更高的生产力
Docker 设计的 Dockerfile 只允许有一个 ENTRYPOINT,这并非无故添加的人为限制,而是因为 Docker 只能通过监视 PID 为 1 的进程(即由 ENTRYPOINT 启动的进程)的运行状态来判断容器的工作状态是否正常,容器退出执行清理,容器崩溃自动重启等操作都必须先判断状态。设想一下,即使我们使用了supervisord之类的进程控制器来解决同时启动 Nginx 和 Filebeat 进程的问题,如果因某种原因它们不停发生崩溃、重启,那 Docker 也无法察觉到,它只能观察到 supervisord 的运行状态,
额外知识:Pod 名字的由来与含义
Pod 的概念在容器正式出现之前的 Borg 系统中就已经存在,Kubernetes 时代的 Pod 整合了 Borg 时代的“Prod”(Production Task 的缩写)与“Non-Prod”的职能。
Pod 是隔离与调度的基本单位,也是我们接触的第一种 Kubernetes 资源。Kubernetes 将一切皆视为资源,不同资源之间依靠层级关系相互组合协作,这个思想是贯穿 Kubernetes 整个系统的两大核心设计理念之一,不仅在容器、Pod、主机、集群等计算资源上是这样,在工作负载、持久存储、网络策略、身份权限等其他领域中也都有着一致的体现。
- 容器(Container):延续了自 Docker 以来一个容器封装一个应用进程的理念,是镜像管理的最小单位。
- 生产任务(Pod):补充了容器化后缺失的与进程组对应的“容器组”的概念,Pod 中容器共享 UTS、IPC、网络等名称空间,是资源调度的最小单位。
- 节点(Node):对应于集群中的单台机器,这里的机器即可以是生产环境中的物理机,也可以是云计算环境中的虚拟节点,节点是处理器和内存等资源的资源池,是硬件单元的最小单位。
- 集群(Cluster):对应于整个集群,Kubernetes 提倡理念是面向集群来管理应用。当你要部署应用的时候,只需要通过声明式 API 将你的意图写成一份元数据(Manifests),将它提交给集群即可,而无需关心它具体分配到哪个节点(尽管通过标签选择器完全可以控制它分配到哪个节点,但一般不需要这样做)、如何实现 Pod 间通信、如何保证韧性与弹性,等等,所以集群是处理元数据的最小单位。
- 集群联邦(Federation):对应于多个集群,通过联邦可以统一管理多个 Kubernetes 集群,联邦的一种常见应用是支持跨可用区域多活、跨地域容灾的需求。
故障恢复、滚动更新、自动扩缩这些特性,在云原生中时代里常被概括成服务的弹性(Elasticity)与韧性(Resilience),ReplicaSet、Deployment、Autoscaling 的用法,也属于是所有 Kubernetes 教材资料都会讲到的“基础必修课”。
k8s资源及应用资源介绍
在想要创建的 Kubernetes 对象对应的 .yaml
文件中,需要配置如下的字段:
-
apiVersion
- 创建该对象所使用的 Kubernetes API 的版本 -
kind
- 想要创建的对象的类型 -
metadata
- 帮助识别对象唯一性的数据,包括一个name
字符串、UID 和可选的namespace
也需要提供对象的 spec
字段。对象 spec
的精确格式对每个 Kubernetes 对象来说是不同的,包含了特定于该对象的嵌套字段。Kubernetes API 参考能够帮助我们找到任何我们想创建的对象的 spec 格式。
Deployment
Deployment 为 Pod 和 ReplicaSet 提供了一个声明式定义(declarative)方法,用来替代以前的ReplicationController 来方便的管理应用。典型的应用场景包括:
- 定义Deployment来创建Pod和ReplicaSet
- 滚动升级和回滚应用
- 扩容和缩容
- 暂停和继续Deployment
Service
“Service” 简写 “svc”。如上文提到的,Pod不能直接提供给外网访问,而是应该使用service。Service就是把Pod暴露出来提供服务,Service才是真正的“服务”,它的中文名就叫“服务”。Service代理Pod集合,对外表现为一个访问入口,访问该入口的请求将经过负载均衡,转发到后端Pod中的容器。
k8s使用service还有一个原因。一般而言,k8s每创建一个新的Pod,它的ip地址都是不一样的,一个Service与特定的一个或者一组Pod挂钩,即使Pod挂掉了,k8s又创建了新的特定的Pod,Service仍然与这个新的Pod挂钩,这样,Pod的ip不一样了,哪怕端口也不一样了,仍然能通过Service来获取Pod所提供的服务。
Service是如何保持这种与特定Pod绑定的关系的呢?那就是“Label”和“Label Selector”,可以给Pod分配特定的Label,然后配置Service,通过“Lable Selector”选择具有这些特定“Label”的Pod来接受请求、提供服务。
容器配额
为容器设定最大的资源配额的做法从 cgroups 诞生后已经屡见不鲜,但你是否注意到 Kubernetes 给出的配置中有limits和requests两个设置项?这两者的区别其实很简单:requests是给调度器用的,Kubernetes 选择哪个节点运行 Pod,只会根据requests的值来进行决策;limits才是给 cgroups 用的,Kubernetes 在向 cgroups 的传递资源配额时,会按照limits的值来进行设置。
几种port
- nodePort
外部流量访问k8s集群service入口的一组方式(另一种方式是LoadBalaner),即nodeIP:nodePort是提供给外部流量访问k8s集群中service的入口。比如外部用户要访问k8s集群中的一个Web应用,那么我们可以配置对应service的type=NodePort,nodePort=30001。其他用户就可以通过浏览器http://node:30001访问到该web服务。而数据库等服务可能不需要被外界访问,只需被内部服务访问即可,那么我们就不必设置service的NodePort。 - port
k8s集群内部服务之间访问service的入口。即cluseterIP:poer是service保留是clusterIP上的端口 - targetPort
容器的端口(最终流量的端口)。targrtPort是pod上的端口,从port和nodePort上来的流量,经过kube-prosy流入到后端的pod的targetPort上,最终进入容器。