从操作系统内核到产品部署(三)

从操作系统内核到产品部署理解

Posted by Jingming on November 24, 2020

上一篇介绍了Web服务器。Web程序部署,Docker image里面打包了这些服务器。 这一篇将介绍,能进一步管理Docker image的工具:Kubernetes。

一、Kubernetes

Kubernetes是管理Docker容器的软件,它可以为容器提供部署运行、资源调度、服务发现、动态伸缩等功能。

Kubernetes集群:指的就是一个计算机集群,集群中部署了k8s。所谓部署,说白了,就是每个机器上都安装了k8s,只不过有的机器安装的是master(调度集群)版本, 有些是安装的客户端版,也就是被任命为工作结点node(负责运行应用)。

与传统集群区别:传统集群里面,机器管理的应用是固定的,不灵活的,而k8s中的机器是基于docker的,因此应用部署起来更灵活。

使用kubectl cluster-info 查看集群信息

信息例如:k8s的核心模块(例如集群面板、DNS)模块运行在哪个ip以及端口

常用命令:kubectl log pod名 -c 容器名 // 进入pod内某container查看日志 kubectl exec -it pod名 -c 容器名 // 进入container的shell

图像化理解:k8s就是很多台的电脑,里面有一台机器,可以管理其他每台机器上面装什么程序,怎么运行。电脑之间的通信是借着API技术(也就是有些机器要负责API server/ scheduler)。

Node(工作结点)

Node就是集群中的机器(虚拟机或物理计算机)。

使用kubectl get nodes 查看集群中所有node信息。

信息例如:名字,角色(master、control-panel),年龄,版本。

图像化理解:Node就像我们刚买来的计算机,里面刚装完操作系统和一些最基本的软件,将来要来跑一些程序的,这些程序可以是虚拟机,也就是不同操作系统。

Pod

Pod是k8s的部署单元,部署一个应用程序(服务)就是创建一个pod。

是一种应用服务的闭包(程序加环境: 环境例如网络环境、存储环境等)。

pod与node关系:一个node里面可以有多个pods。一个pod一开始会在某个node上创建,创建完之后根据需要也可以被挪动到其他node,就是pod会根据node需要而被调度。

Pod首先本身自带了一个容器,以提供网络栈、文件系统等基础服务。在此基础上,Pod里面可以放多个容器(例如一个pod里面可以放Nginx容器和一个Ruby on Rails应用容器),

这些容器相当于在一台机器上,共享localhost和文件目录。当然,一个pod往往放在一个物理机器中,这样就能保证Pod里面的服务之间的访问不会有太大物理延迟。

kubectl create deployment 服务名 –image=docker image url 部署一个服务(创建一个pod)

kubectl get pods 查看集群中所有pods的信息

kubectl describe pods 查看所有pods的详细信息(状态)

图像化理解:pod就像我们现在正在使用的电脑,上面可以跑若干程序,上面有存放证书的位置,以及对应的硬盘(卷)和文件目录,这个电脑环境就是pod。

Service

k8s的Service的作用是提供公开服务(网络服务),曝露pod的端口,提供访问的入口,

另外,提供访问策略(称为微服务),它根据pods的标签管理一组pods。根据selector把对应的标签pod选进来。

访问策略例如:负载平衡和网络配置(为组pod提供相同的DNS名)。

Service可以定义内部网络或外部网络的IP地址以及DNS表,可以创建和管理AWS的ELB(灵活负载平衡)来管理集群的数据入口。

图形化理解:就相当于AWS里面的一个VPC,由一个机器提供网络入口,负载平衡,网络策略,其他机器在里面可以同时跑同一个程序。

Controller

Controller的作用是维护pod的创建(多少pod)和运行规则(什么时候运行,优雅的rollback,scale up),例如:Deployment是一种Controller(kind: Deployment)。

kubectl apply -f deployment.yaml // 这个命令的意思是部署Deployment Controller到集群里面

Deployment对应一个应用服务,可以管理若干个pods,包括:

  • 每个pod的副本replica数量

  • pod滚动更新(可以无缝衔接的更新升级Pods服务)

  • pod健康运行
  • 自动扩展

kubectl get deployments 查看Deployment。

PS. Deployment是不管负载平衡的。

Controller的种类: (1)Job: 干完一个活就结束的短存的任务程序; (2)CronJob: 定时运行的程序; (3)Deployment: 一直运行的程序,例如Web服务(主程序一般使用Deployment部署); (4)DaemonSets: 每个节点被强制保证只能有一个DaemonSet pod,在后台一直运行,作用是做系统级的监控,包括node里面pods的健康程度(通过运行server来收集服务的metrics信息),每个pod的日志收集; (5)StatefulSets: 一直运行的有状态的程序,有状态的意思是,虽然部署的程序看似一样,但是这些程序的职责并不一定相等,例如主从服务的数据库。

例如数据库,数据库主程序是提供读写服务的,有些从程序是只提供读服务的。而且,根据数据的分片,每次数据库的请求会被导向到特定的数据库程序里面。

所以,有状态就是意味着部署的程序会有属于自己的数据(状态),这些数据描述了他们的特别之处。

PS. StatefulSets能够在k8s组件的频繁重启过程中维护着自身固有属性。这类程序需要持久化的数据库,通常会集合挂载EBS来达到扩容效果。

Controller层级

Controller之间可以嵌套,以便每层实现自己的特点和复用:

CronJob (定时调度器) ↓ 定时创建 Job (任务管理器) ↓ 创建 Pod (容器运行器) ↓ 运行 Container (应用程序)

Deployment (声明式管理器) ↓ 创建/管理 ReplicaSet (副本管理器) ← 这层在YAML中不显示 ↓ 创建/管理 Pod (容器运行器) ↓ 运行
Container (应用程序)

资源类型的Service、ConfigMap、Secret、PV不能被嵌套。

图形化理解:容器嵌套就是先要有一个什么,然后在往下细分,每层只负责自己的关心的配置。像电脑上面运行steam:

Steam外面还没有进入具体游戏的时候,就可以配置了,然后进入游戏后又有具体的配置。

但是有些资源类型就不能被嵌套,例如有些图片,视频等。

组件

k8s的组件是实现k8s pod、service这些单位的基础。组件包括:控制面板组件、node组件。

控制面板组件,顾名思义就是可见的操作面板,它的前端是基于kube-apiserver组件的,这个组件提供了操作k8s的api; 另外还包括etcd组件(全局一致性的键值数据库)、kube-scheduler组件(就是根据pods、系统的情况进行调度)、 kube-controller-manager组件(简单理解:相当于windows的进程管理器,它的关注点是任务级别的,这些任务例如普通的job、故障通知、创建令牌等) cloud-controller-manager组件(顾名思义,就是对集群链接的云服务进行管理)

控制面板组件往往单独的运行在k8s集群的某台机器上。

Node组件:包括kubelet组件(负责管理pod里面的容器,保证他们的健康)、kube-proxy组件(负责管理node的网络规则,也就是控制一个pod能否被哪些外界所访问)、 container runtime组件(管理运行容器的软件、例如管理docker)

kubelet原理理解:其实可以安装在本地,负责发送指令到集群,操作集群。

Addsons组件(插件组件):包括DNS、web界面(UI)、资源监控(汇总所有容器的指标信息)、日志(集群总日志管理)等组件。

API server/ scheduler

管理容器的API服务。scheduler可以通过调用API来把pod调度到节点上。

图形化理解:API就是“芝麻开门”的这种话语式的命令,scheduler就是负责这些话语脚本(也就是若干话语的组合)能正确健康的运行的机制。

Namespace

namespace可以类比为文件系统中的App目录,它就相当于用户自己建立目录把程序隔开,例如,不同namespace下可以有同名的程序,但是 这两个程序实际上并不是同一个。

实例:公司内的一个组对应一个namespace,他们可以把所有自己开发相关的服务deploy到里面。

kubectl

操作(增删改查)集群的总命令,说白了,是由客户端工具提供的命令,要使用前需要配置好它与哪个具体集群链接,然后就可以用了。

kubeconfig

k8s为了支持组控制,例如对于不同用户,希望他们访问到不同集群,例如,在中国的程序员访问中国地区的集群,美国的程序员访问美国地区的集群,又或者是 生产环境集群或者测试集群。

也就是说,k8s里面可以不止管理一个集群,实际上,k8s可以管理不同的context,每个context下面有clusters,users和namespaces。

使用kubeconfig可以控制kubctl的环境,包括集群名、用户、命名空间、认证机制。

kubeconfig默认所在位置:$home/.kube里面的config文件。

KUBECONFIG环境变量里面包括很多的kubeconfig文件,以;分割,查看命令:kubectl config view。

多个文件里面如果对同一个key做了多次配置,那么还是以第一次加载到的为结果(也就是不允许重写)

注意:namespace是context下层的概念,切换context好比切换计算机,切换namesapace好比切换文件夹。

Replication Controller(ReplicaSet)

管理Pod数量,对于配置好的数量,集群中实际如果多了,那么会停止一些容器,反之,添加容器满足这个值。

Volume

Volume是k8s中管理文件共享的单位,Volume属于pod的一部分,volume的生命周期和pod一致,但其中文件在volume消失后仍然存在(持久化存储类型)。

容器重建时候,容器中的本地文件会丢失,因此k8s里,为了防止创建的文件丢失,pod中所有容器可以访问volume,原理是把volume挂载到容器中的任何目录。

PS. 挂载的意思:把操作系统和硬件(硬盘)进行分离的一种技术,操作系统需要使用硬盘时候,先把硬盘链接到操作系统,然后给这个硬盘分配一个子目录,把硬盘原先结构给映射上去,这整个过程叫做加载。

ETCD数据库

K8S里面的一个组件,专门负责保存集群的状态(节点信息,pod状态,service配置信息)。说白了,就是一套分布式的键值存储系统(数据库),可以被API server访问。

图像化理解:集群里面这么多机器,当然需要一个系统,若干台机器来保存其中的全局配置信息。

Secrets和ConfigMaps

都存放在ETCD中,组成都是键值对,可以作为文件被mount到容器或者作为环境变量注入到容器中。

区别: 一个是敏感数据,一个是不敏感数据。

K8S配置里面,Secret资源kind就是Secret;data对应的就是所有的键值对,key就是一个特殊的字符串,值是用base64编码的。

查看secrets:

kubectl get secrets 查看secret名字

kubectl describe secret名字

secrets的种类:一种是数据库密码,API密钥;另一种是证书,ssh文件,配置文件等。

secret如何注入pod:

两种方式,一种是当作卷(类型是secret)被挂载到pod一个路径上;一种是作为环境变量注入pod。

作为卷挂载的时候,在挂载路径上面,对每一个secret键值对,key对应一个文件名字,文件的内容是value。使用时用File.read(file_path)来读取。

作为环境变量注入就直接变成pod的环境变量,通过ENV.fetch(key)来直接使用。

PS. 1. 许多库(SSH、GPG、TLS)期望文件路径,不是字符串内容。 2. 作为类型是secret的卷的好处:更快(使用内存),更安全(权限控制更严格),更可追踪(k8s进行审计),实时更新(这个如果单靠环境变量注入pod就做不到),正确性(有原子更新机制)。 3. secretRef引用的是kind为Secret的资源。

图像化理解:每台应用机器pod在被配置的时候需要放置一些初始化的文件(例如证书),集群会把这些文件先保存在几台特定的机器上,在配置M的时候,从这些机器拿出文件,然后注入到pod里面。

Namespace

将K8S资源进行分组,K8S资源也就是pods,deployments等。

kubectl get namespaces 查看namespaces

kubectl get pods –namespace infra 查看infra命名空间下pods信息

kns infra 切换到infra命名空间

分组的用处包括:权限管理,把不同用户分到不同命名空间下;对不同app使用不同命名空间,控制他们的防火墙设置、控制安全、控制约束(compliance);

PV、PVC和StorageClass

PVC属于K8S的持久化存储类型。

首先理解云服务提供的三种存储:块存储、文件存储、对象存储: 块存储说白了,就相当于提供一个虚拟硬盘给你;

文件存储说白了,就是提供文件树、目录服务,存放的单位是文件;

对象存储说白了,介于两者之间,因为有的时候用户需要存储的不仅是单个文件,而是一个文件中的一部分或多个文件的组合, 这样,为了提高访问效率,干脆存储的元数据(metadata)不仅是文件的metadata,而是存储”对象”级别的抽象元数据, 这种元数据(metadata)的存储用到了分布式技术,也就是对所有metadata单独保存和管理。

其次,理解NFS(网络文件系统): 说白了,就是计算机之间通过RPC来共享共同的文件目录,客户端计算机可以根据自己的权限去访问文件,可以修改目录结构等。

PV就是k8s系统中的共享文件目录中文件资源的一种描述。

PVC就是pod对PV的要求的描述,例如大小和权限。

StorageClass:PV的创建需要底层文件细节,而StorageClass提供创建底层细节的快捷方式,让PVC可以根据需要创建自己的PV并绑定。

Network Polices

(1)可以构建允许列表

(2)可以适用到一组pods或者namespace下

(3)内部网络的允许列表(通过配置访问外部的IP、pod的来源和目标)

好处是可以分出例如QA,SandBox环境。

Kubernetes的配置文件

YAML文件 负责配置Kubernetes的资源;

kubectl apply -f app.yaml

与DataCenter的关系

每个DataCenter有自己的K8S集群,这些之间是完全独立的。

kctx 数据中心名字 选则数据中心