k8s系列-k8s基础

K8S-基础组件

集群容器编排经过Swarm,Mesos,K8S的竞争,最终kubernetes以大优势胜出。Kubernetes最初源于谷歌内部的Borg,提供了面向应用的容器集群部署和管理系统。Kubernetes的目标旨在消除编排物理/虚拟计算,网络和存储基础设施的负担,并使应用程序运营商和开发人员完全将重点放在以容器为中心的原语上进行自助运营。K8S提供完善的管理工具,涵盖开发、部署测试、运维监控各个环节。比如集成日志组件和监控组件等。K8S支持5000个节点。

image

Borg系统介绍

Borg是google内部大规模集群管理系统,负责对google内部很多核心服务的调度和管理,让用户专注于自己的核心业务。Borg主要由BorgMaster,Borglet,borgcfg,Scheduler组成

支持规格

  • BorgMaster是集群的大脑,负责维护整个集群的状态,将数据存储到Paxos存储中
  • Scheduler负责任务的调度,根据应用的特点调度到具体的机器上去
  • Borglet负责真正的运行任务
  • borgcfg是Borg的命令行工具,用于跟Borg系统交互,一般通过一个配置文件来提交任务

Kubernetes基础组件

Kubernetes也是google开源的一个项目,所以正是有borg系统借鉴而来,整体架构与borg系统非常相似。K8S不同于Swarm和Mesos,他一开始就站在让他们无法企及的高度上,借鉴的同时也修复了很多在Borg中遗留的缺陷和问题。

kubernetes架构
kubernetes主要有如下核心组件

  • ectd保存整个集群的状态和配置,所有节点都从etcd中获取其他机器状态也保存自己的状态
  • apiserver提供整个集群的资源操作唯一入口,并提供授权、认证、访问控制、API注册和发现机制,提供HTTP Rest接口
  • controller manager负责维护集群状态,比如Pod副本、故障检测、自动检测、滚动更新等
  • scheduler负责资源的调度,按照预期的调度策略将Pod调度到合适的机器上
  • kubelet负责维护容器的生命周期,负责这台Node的所有容器,同时也维护Volume和网络的管理,维护Volume和网络分别通过CNI(Container Network Interface)和CSI(Container Storage Interface)进行交互
  • Container Runtime负责镜像管理以及Pod和容器的真正运行
  • kube proxy负责为Service提供内部的服务发现和负载均衡,使用etcd watch机制监控集群的数据动态变化,保证Pod的IP变化Service感知

同时还有一些推荐的插件

  • CoreDNS负责为整个集群提供DNS服务
  • Ingress Controller为服务提供外网入口
  • Prometheus提供资源监控
  • Dashboard提供K8S的gui
  • Federation提供跨可用区的集群
  1. Borg系统虽然与k8s项目不相同,但是出发点都一样,如何管理、编排、调度用户提交的作业。
    对于google来说,docker的出现只不过是让他们换了一种打包方式,大规模作业管理和调度的思路可以直接套在k8s上。
  2. k8s并不是把Docker作为一种核心架构,只是作为一种底层容器的实现而已。

运行在大规模集群中各种任务之间,实际上存在各种关系,这些关系的处理,才是作业编排和管理系统最困难的地方。

平时场景中随处可见这种依赖关系场景,比如一个web应用和数据库,负载均衡和代理的后端服务,一般情况下来说都会把这些依赖关系的服务部署在一个机子上,容器技术出现后,原先挤在一台机子上的各个应用、组件、守护进程都可以分别做成镜像运行,容器隔离互不干涉,有自己的资源配额,运行在集群的任何一台机器上。

Kubernetes资源组件介绍

Pod

Kubernetes中最小的调度单位不再是容器,而是一个Pod,Pod里面可以有多个容器,比如两个应用之间需要非常频繁的交互和访问,或者直接通过本地文件进行信息交换,这种情况就可以使用Pod部署两个容器进去。

Service

Kubernetes中因为应用常常不在一台机器上,通常情况下如果某一台节点宕机,上面的所有Pod会根据资源需求在最合适的节点上重新启动起来,这也就造成了IP地址的不稳定性,比如我们现在部署一个数据库Pod和web应用Pod,web配置了数据库Pod的IP地址,万一数据库Pod所在节点宕机,则会被调度到其他节点进行重启,IP地址发生改变,这种情况下就需要Service服务这个概念了,Service类似负载均衡器,可以帮助我们代理Pod不管Pod在哪个节点上运行,都能通过配置对应的Service来找到。web应用只需要关心Service的信息而不需要关系到数据库Pod当前的IP等信息。

Deployment

光有了pod还不够,我如何一次行新建多个pod做高可用,如何更新pod中镜像版本,k8s中,新建pod主要通过声明式的配置,要新建一个Pod时不应该通过运行命令的方式来新建出这个Pod,而且应该通过定义声明式文件来新建Pod,就比如可以声明一个Deployment类型的声明式文件,比如下面这种

制定pod的副本数量为3,为pod打上一个标签 app=nginx,指定container的名字为nginx,pod使用镜像为1.7.9版本的nginx,指定container端口为80

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80

StatefulSet

StatefulSet顾名思义,主要用来解决有状态服务的问题,Deployment针对无状态服务。比如像zookeeper和kafka等。
StatefulSet适用于有以下某个或多个需求的应用:

  • 稳定,唯一的网络标志
  • 稳定,持久化存储
  • 有序,优雅地部署和scale
  • 有序,优雅地删除和终止
  • 有序,自动的滚动升级

DaemonSet

DaemonSet确保全部或者指定的一些Node上运行一个Pod的副本,当有Node加入集群,就新增一个Pod到这个新增的Node节点上。Node从集群一处,Pod也被回收,删除DaemonSet时删除它创建的所有的Pod。
常见用法:

  • 运行集群存储Daemon,比如在每个Node上运行glusterd、ceph
  • 每个Node上运行日志收集 fluentd、logstash等
  • 每个Node上运行监控

Job

Job负责批处理任务,也就是只执行一次的任务,比如大数据任务。执行时产生一个Pod,运行指定的命令

CronJob

管理基于时间的Pod,类似linux的crontab

  1. 在给定时间点运行一次
  2. 周期得在给定时间点运行

Horizontal Pod Autoscaling

应用的资源使用率有高峰和低谷,如何提高集群的整体资源利用率,让service中的pod自动调整?HPA可以做到,不需要手动扩容缩容,可以自动化实现。

Ingress

Ingress和Service一样都是用来做服务发现的,Service通常用于提供集群内部的访问入口(但是也可以制定Service的Type=LoadBalancer或者是NodePort来暴露给外部,但是不推荐),Ingress是kubernetes集群外部访问集群内部服务的入口,Ingress需要配合IngressController配合使用,Ingress相当于我们nginx配置文件的转发规则等,Ingress配置转发到某个Service的某个port。常见Ingress Controller如下。

  • kubernetes当前支持和维护GCE和nginx两种controller
  • F5公司支持维护F5 BIG-IP Controller for Kubernetes
  • Kong支持维护社区版和企业版的Kong Ingress Controller for Kubernetes
  • Traefik是功能齐全的Ingress Controller
  • Istio使用CRD Gateway来控制Ingress流量

ConfigMap

ConfigMap API资源用来保存key-value pair配置数据,ConfigMap跟下面的Secret很相似,但是ConfigMap更方便处理不含敏感信息的字符串。就好像我们平时加载props下面properties文件或现在的yaml配置文件的信息到内存中,直接通过Spring的注解可以取到

Secret

如果两个Pod之间不仅仅有“访问关系”,还要在请求时加上授权信息,典型场景就是应用访问数据库需要数据库的用户名和密码信息,kubernetes中提供了一种叫做Secret的对象,其实是保存在Ectd中的键值对数据,把用户名和密码通过Secret的方式存在Etcd里面,kubernetes就会在你指定的Pod里面把Secret里的数据已Volume方式挂载到容器里或者以环境变量的方式引入,这样应用就能访问到数据库了

Label

Label是附加到一些对象上面的键值对,常用场景比如给pod打上一些label,Service通过标签找到对应的Pod,常常与Label Selector配合使用,Label Selector有两种类型:

  • equality-based :可以使用=、==、!=操作符,可以使用逗号分隔多个表达式
  • set-based :可以使用in、notin、!操作符,另外还可以没有操作符,直接写出某个label的key,表示过滤有某个key的object而不管该key的value是何值,!表示没有该label的object

Taint和Toleration

Taint(污点)和 Toleration(容忍)可以作用于 node 和 pod 上,其目的是优化 pod 在集群间的调度,Taint和Toleration配合使用可以避免Pod被分配到不合适的节点上。可以再Node上配置Taint,Pod上配置Toleration

配上一张图

image