Kubernetes
kubernetes介绍
Kubernetes, also known as K8s, is an open-source system for automating deployment, scaling, and management of containerized applications. 用于自动部署、扩展和管理“容器化(containerized)应用程序”的开源系统。
kubernetes,简称K8s,是用8代替名字中间的8个字符“ubernete”而成的缩写。是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效,Kubernetes是用于自动部署、扩展和管理容器化应用程序的开源系统,简单理解就是一个编排容器的工具。 kubernetes的本质是一组服务器集群,它可以在集群的每个节点上运行特定的程序,来对节点中的容器进行管理。目的是实现资源管理的自动化,主要提供了如下功能:
-
自我修复:一旦某一个容器崩溃,能够在1秒中左右迅速启动新的容器
-
弹性伸缩:可以根据需要,自动对集群中正在运行的容器数量进行调整
-
服务发现:服务可以通过自动发现的形式找到它所依赖的服务
-
负载均衡:如果一个服务启动了多个容器,能够自动实现请求的负载均衡
-
版本回退:如果发现新发布的程序版本有问题,可以立即回退到原来的版本
-
存储编排:可以根据容器自身的需求自动创建存储卷
Kubernetes重要概念
Pod
官方对于Pod的解释是:Pod是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。 pod是k8s调度的最小单元,包含一个或者多个容器(这里的容器你可以暂时认为是docker)。 简单来说,Pod可以被理解成一群可以共享网络、存储和计算资源的容器化服务的集合。再打个形象的比喻,在同一个Pod里的几个Docker服务/程序,好像被部署在同一台机器上,可以通过localhost互相访问,并且可以共用Pod里的存储资源(这里是指Docker可以挂载Pod内的数据卷,数据卷的概念,后文会详细讲述,暂时理解为“需要手动mount的磁盘”)。笔者总结Pod如下图,可以看到:同一个Pod之间的Container可以通过localhost互相访问,并且可以挂载Pod内所有的数据卷;但是不同的Pod之间的Container不能用localhost访问,也不能挂载其他Pod的数据卷。
K8S Pod示意图
K8S中所有的对象都通过yaml来表示,下面是官网一个 Pod 示例,它由一个运行镜像 nginx:1.14.2 的容器组成。
apiVersion: v1
kind: Pod
me tadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:- containerPort: 80
apiVersion记录K8S的API Server版本,现在看到的都是v1,用户不用管。
- containerPort: 80
kind记录该yaml的对象,比如这是一份Pod的yaml配置文件,那么值内容就是Pod。
me tadata记录了Pod自身的元数据,比如这个Pod的名字、这个Pod属于哪个namespace(命名空间的概念,后文会详述,暂时理解为“同一个命名空间内的对象互相可见”)。
spec记录了Pod内部所有的资源的详细信息,看懂这个很重要:
containers记录了Pod内的容器信息,containers包括了:name容器名,image容器的镜像地址
Volume
K8S支持很多类型的volume数据卷挂载,具体请参见K8S卷。前文就“如何理解volume”提到:“需要手动mount的磁盘”,此外,有一点可以帮助理解:数据卷volume是Pod内部的磁盘资源。 其实,单单就Volume来说,不难理解。但是上面还看到了volumeMounts,这俩是什么关系呢? volume是K8S的对象,对应一个实体的数据卷;而volumeMounts只是container的挂载点,对应container的其中一个参数。但是,volumeMounts依赖于volume,只有当Pod内有volume资源的时候,该Pod内部的container才可能有volumeMounts。
Deployment
除了Pod之外,K8S中最常听到的另一个对象就是Deployment了。那么,什么是Deployment呢?官方的解释:一个 Deployment 控制器为 Pods 和 ReplicaSets 提供声明式的更新能力。 你负责描述 Deployment 中的 目标状态,而 Deployment 控制器以受控速率更改实际状态, 使其变为期望状态。你可以定义 Deployment 以创建新的 ReplicaSet,或删除现有 Deployment,并通过新的 Deployment 收养其资源。 翻译一下:Deployment的作用是管理和控制Pod和ReplicaSet,管控它们运行在用户期望的状态中。 新的问题又来了:那什么是ReplicaSets呢? ReplicaSet 的目的是维护一组在任何时候都处于运行状态的 Pod 副本的稳定集合。 因此,它通常用来保证给定数量的、完全相同的 Pod 的可用性。
K8S Deployment、ReplicaSet和Pod关系图
但是,从K8S使用者角度来看,用户会直接操作Deployment部署服务,而当Deployment被部署的时候,K8S会自动生成要求的ReplicaSet和Pod。在K8S官方文档中也指出用户只需要关心Deployment而不操心ReplicaSet: This actually means that you may never need to manipulate ReplicaSet objects: use a Deployment instead, and define your application in the spec section. 这实际上意味着您可能永远不需要操作ReplicaSet对象:直接使用Deployments并在规范部分定义应用程序。
Service和Ingress
Deployment和ReplicaSet主要管控Pod程序服务;Service和Ingress则负责管控Pod网络服务。 官方对Service的定义:将运行在一组 Pods 上的应用程序公开为网络服务的抽象方法。 使用 Kubernetes,您无需修改应用程序即可使用不熟悉的服务发现机制。 Kubernetes 为 Pods 提供自己的 IP 地址,并为一组 Pod 提供相同的 DNS 名, 并且可以在它们之间进行负载均衡。 翻译下:K8S中的服务(Service)并不是我们常说的“服务”的含义,而更像是网关层,是若干个Pod的流量入口、流量均衡器。 那么,为什么要Service呢? 官方文档的解释: Kubernetes Pod 是有生命周期的。 它们可以被创建,而且销毁之后不会再启动。 如果您使用 Deployment 来运行您的应用程序,则它可以动态创建和销毁 Pod。 每个 Pod 都有自己的 IP 地址,但是在 Deployment 中,在同一时刻运行的 Pod 集合可能与稍后运行该应用程序的 Pod 集合不同。 这导致了一个问题: 如果一组 Pod(称为“后端”)为群集内的其他 Pod(称为“前端”)提供功能, 那么前端如何找出并跟踪要连接的 IP 地址,以便前端可以使用工作量的后端部分? 补充:Service是K8S服务的核心,屏蔽了服务细节,统一对外暴露服务接口,真正做到了“微服务”。举个例子,我们的一个服务A,部署了3个备份,也就是3个Pod;对于用户来说,只需要关注一个Service的入口就可以,而不需要操心究竟应该请求哪一个Pod。优势非常明显:一方面外部用户不需要感知因为Pod上服务的意外崩溃、K8S重新拉起Pod而造成的IP变更,外部用户也不需要感知因升级、变更服务带来的Pod替换而造成的IP变化,另一方面,Service还可以做流量负载均衡。 Service在 K8s中有以下四种类型: ① ClusterIp 默认类型,自动分配一个仅Cluster内部可以访问的虚拟IP。 ② NodePort 在ClusterIP基础上为Service在每台机器上绑定一个端口,这样就可以通过NodePort来访问该服务。 ③ LoadBalancer 在NodePort的基础上,借助Cloud Provider创建一个外部负载均衡器,并将请求转发到NodePort。 ④ ExternalName 把集群外部的服务引入到集群内部来,在集群内部直接使用。没有任何类型代理被创建,这只有Kubernetes 1.7或更高版本的kube-dns才支持。
但是,Service主要负责K8S集群内部的网络拓扑。那么集群外部怎么访问集群内部呢?这个时候就需要Ingress了,官方文档中的解释是: Ingress 是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。 Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。 翻译一下:Ingress是整个K8S集群的接入层,复杂集群内外通讯。
K8S Ingress、Service和Pod关系图
namespace 命名空间
和前文介绍的所有的概念都不一样,namespace跟Pod没有直接关系,而是K8S另一个维度的对象。或者说,前文提到的概念都是为了服务Pod的,而namespace则是为了服务整个K8S集群的。
那么,namespace是什么呢?
官方文档定义: Kubernetes 支持多个虚拟集群,它们底层依赖于同一个物理集群。 这些虚拟集群被称为名字空间。
翻译一下:namespace是为了把一个K8S集群划分为若干个资源不可共享的虚拟集群而诞生的。 也就是说,可以通过在K8S集群内创建namespace来分隔资源和对象。比如我有2个业务A和B,那么我可以创建ns-a和ns-b分别部署业务A和B的服务,如在ns-a中部署了一个deployment,名字是hello,返回用户的是“hello a”;在ns-b中也部署了一个deployment,名字恰巧也是hello,返回用户的是“hello b”(要知道,在同一个namespace下deployment不能同名;但是不同namespace之间没有影响)。
Kubernetes实战—搭建WordPress
详细步骤:https://kubernetes.io/zh-cn/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/