k8s-02-基础概念_docker

Kubernetes Service

(1) 拥有一个唯一指定的名字(比如mysql-server)
(2) 拥有一个虚拟IP (Cluster IP、ServiceIP或VIP)和端口号
(3) 能够提供某种远程服务能力
(4) 被映射到了提供这种服务能力的一组容器应用上

k8s-02-基础概念_ip地址_02

Pod

Pod运行在一个我们称之为节点Node的环境中,每个Pod里运行着一个特殊的被称之为Pause的容器,其他容器则为业务容器,这些业务容器共享Pause容器的网络栈和volume挂载卷,因此他们之间的通讯和数据交换更为高效。【在设计时我们可以充分利用这一特征将一组密切相关的服务进程放入同一个Pod中。】

k8s-02-基础概念_sed_03

普通的Pod 【控制器管理】:

普通Pode一旦被创建,就会被放入到etcd中存储,

静态Pod (STatic Pod) 【自主式、不被控制器管理】

静态Pod是由kubelet进行管理的仅存在于特定Node上的Pod。他们不能通过API Server进行管理,无法与ReplicationController(RC)、Deployment、或者DaemonSet进行关联,并且kubelet也无法对它们进行健康检查。静态Pod总是由kubelet进行创建的,并且总是在kubelet所在的Node上运行的

Service 和Pod如何关联

为了建立Service 和Pod间的关联关系,Kubernetes 首先给每个Pod填上了一个标签Label, Service
要作用于所有包含对应 Label的Pod上。这样就巧妙的解决了Service和Pod关联问题 (通过标签关联)

RC

Replication Controller 用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器的异常退出,会自动创建新的pod来代替,如果异常多出来的容器也会自动回收(新版本建议使用Replica Set)

RS

它与RC当前存在的唯一区别是:Replica Sets支持基于集合的Label selector(Set-based selector基于集合的标签选择器),而RC只支持基于等式的Label Selector(equality-based selector基于等式),这使得Replica Set的功能更强

Deployment

(Kubernetes1.2引入的新概念,引入的目的是为了更好的解决Pod的编排问题)不负责pod创建,
为Pod和ReplicaSet提供了一个声明式定义方法,用来替代以前的RC来方便的管理应用 (Deployment 创建RS,RS创建pod ;升级时 在创建一个RS1 ,RS1创建pod1 替换pod ,老的不删除,只是停用,随时回滚)

典型的应用场景:

  • 定义Deployment来创建Pod和ReplicaSet
  • 滚动升级和回滚应用
  • 扩容和缩容
  • 暂停和继续Deployment

HPA

Horizontal Pod Autoscaling
仅适用于ReplicaSet和Deployment【在V1版本中支持Pod的CPU利用率扩容】,目前HPA可以从两个地方获取数据

  • Heapster: 仅支持CPU使用率
  • 自定义监控

DaemonSet

确保全部(或者一些)node上运行一个pod的副本,当有node加入集群时,也会为他们新增一个pod。当有node从集群中移除时,这些pod也会被回收,删除时将会删除它创建的所有pod

典型用法:

  • 运行集群存储daemon,例如在每个node上运行glusterd,ceph
  • 在每个node上运行日志搜集daemon,例如fluentd,logstash
  • 在每个node上运行监控daemon,例如Promethues,Node Exporter

StatefulSet

是为了解决有状态服务的问题(ReplicaSet和Deployment
为无状态服务)例如MySQL集群、MongoDB集群、Akka集群、ZooKeeper集群等。【Kubernetes在1.4版本引入了PetSet这个新资源对象,在1.5更名为"StatefulSet"】

应用场景:

  • 稳定的持久化存储,pod重新调度后还是能访问到相同的持久化数据,基于PVC实现
  • 稳定的网络标志,pod重新调度后podname和hostname不变,基于Headless Service(即没有Cluster
    IP的Service)来实现
  • 有序部署,有序扩展,pod的部署是有顺序的, 基于 init containers来实现
  • 有序收缩,有序删除

Job和CronJob

job负责批处理任务,即仅执行一次的任务,他保证批处理任务的一个或多个pod成功结束 cron job管理基于时间的job

应用场景:

  • 数据库备份

Label

一个Label是一个key=value的键值对,其中key与value由用户自己指定。Label可以附加到各种资源上,例如Node Pod Service RC等。一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上去,Label通常在资源对象定义时确认,也可以在对象创建后动态添加或者删除。我们可以通过给指定的资源对象捆绑一个或多个不同的Label来实现多维度的资源分组管理功能,以便于灵活、方便地进行资源分配、调度、配置、部署等管理工作。【长度不超过63个字符。 可以为空 首位字符必须为字母数字字符 中间必须是横线、_、.、数字、字母。】

常用的Label实例如下:

版本标签:“release” : “stable” , “release” :“canary”
环境标签:“environment”:“dev”, “environment”:“qa”,
“environment”:“production” 架构标签:“tier”:“frontend”, “tier”:“backend”,
“tier”:“middleware” 分区标签:“partition”:“customerA”,
“partition”:“customerB” 质量管控标签:“track”:“daily”, “track”:“weekly”

Label Selector

通过Label Selector 标签选择器 查询和筛选有某些Label的资源对象。Kubernetes通过这种方式实现了类似SQL的简单又通用的对象查询机制。

基于等式的(Equality-based)
name = redis-slave:
基于集合的(Set-based)
name in (redis-master,redis-slave):
name not in (php-fronted):

添加
kubectl label nodes k8s.node1.com label_name=label_value
查询
kubectl get nodes --show-labels
修改一个Label的值,需要加上--overwrite参数:
$ kubectl label nodes k8s.node1.com label_name=apache --overwrite
删除一个Label,只需在命令行最后指定Label的key名并与一个减号相连即可:
$ kubectl label nodes k8s.node1.com label_name-

Namespace

Namespace在很多情况下用于实现多租户的资源隔离。Namespace通过将集群内部的资源对象"分配"到不同的Namespace中,形成逻辑上分组的不同项目、小组或者用户组,便于不同的分组在共享整个集群的资源的同时还能被分别管理。Kubernetes集群启动后,会创建一个名为"default"的Namespace【如果不特别指明Namespace,默认用户创建的Pod、RC、Service都将被系统创建到名为"default"的Namespace中】

获取

kubectl get namespaces

创建

# namespace.yaml

apiVersion: v1
kind: Namespace
metadata:
name: deployment

# kubectl create -f namespace.yaml

删除

kubectl delete namespaces new-namespace

1.删除一个namespace会自动删除所有属于该namespace的资源。
2.default和kube-system命名空间不可删除。
3.PersistentVolumes是不属于任何namespace的,但PersistentVolumeClaim是属于某个特定namespace的。
4.Events是否属于namespace取决于产生events的对象。

ConfigMap

在Kubernetes1.2中新添加了功能ConfigMap,主要功能是为了解决应用程序会从配置文件、环境变量中获取配置信息。但是默认情况下配置信息需要与docker images解耦,ConfigMap API为我们提供了向容器中注入配置信息的机制,ConfigMap可以被用来保存单个属性,也可以用来保存整个配置文件或者JSON二进制对象【可以将它理解为Linux系统中的/etc目录,专门用来存储配置文件的目录】

网络通信方式

Kubernetes在网络模型设计的一个基础原则是:每个Pod都拥有一个独立的IP地址,而且假定所有Pod都在一个可以直接连通的、扁平的网路空间中,这在GCE(Google compute engine)里面是现成的网络模型,私有云上需要我们自己实现:将不同节点上的docker容器之间的互相访问打通。

  • 同一个pod内的多个容器之间:lo (localhost本机网卡)
  • 各个pod之间的通信:Overlay Network(覆盖网络)
  • pod与service 之间的通讯:各节点的iptables规则(新版中加入lvs转发,效率更高)

Flannel

Flannel是CoreOS团队针对Kubernetes设计的一个网络规划服务,简单来说,它的功能是让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址。他能在这些IP地址之间建立一个覆盖网络(Overlay
Network),通过这个覆盖网络,将数据包原封不动地传递到目标容器内。

1.使集群中的不同Node主机创建的Docker容器都具有全集群唯一的虚拟IP地址。
2.建立一个覆盖网络(overlay network),通过这个覆盖网络,将数据包原封不动的传递到目标容器。覆盖网络是建立在另一个网络之上并由其基础设施支持的虚拟网络。覆盖网络通过将一个分组封装在另一个分组内来将网络服务与底层基础设施分离。在将封装的数据包转发到端点后,将其解封装。
3.创建一个新的虚拟网卡flannel0接收docker网桥的数据,通过维护路由表,对接收到的数据进行封包和转发(vxlan)。
4.etcd保证了所有node上flanned所看到的配置是一致的。同时每个node上的flanned监听etcd上的数据变化,实时感知集群中node的变化。

k8s-02-基础概念_docker_04

  1. 主机上安装一个flanneld的守护进程,该进程会监听一个端口(用户转发数据包),他会开启一网桥flannel0专门收集docker0转发出的报文(可以理解为一个钩子函数,强行获取数据报文)
  2. docker0会分配自己的ip到对应的pod上
  3. 同一个pod内部访问 【共享同一个网络命名空间,共享同一个linux协议栈】
  4. 如果是同一个主机上的不同pod访问,走的是docker0的网桥 【不经过flannel】
  5. 跨主机访问(Web app2访问Backend)数据报文 先发送到他的网关docker0,docker0的报文被钩子函数抓取到flannel0,flannel0经过一堆的路由表(从etcd获取)判断路由到那台机器
  6. 数据报文到flanneld(flannel0是由flanneld开启的)后会对报文进行封装,采用udp转发数据包(速度更快),目标主机进行2次解析,最终把数据转发到Backend
    k8s-02-基础概念_数据_05

pod至server的网络,目前基于iptables维护和转发 (新版用lvs)
pod到外网:pod向外网发送请求,查找路由表,转发数据包到宿主机的网卡,宿主机网卡完成路由选择后,iptables执行masquerade,把源IP更改为宿主机的ip,然后向外网服务器发送请求
外网访问pod:需要通过service

ETCD与flannel关系:

  1. 存储管理flannel可分配的IP地址段资源
  2. 监控etcd中每个pod的实际地址,并在内存中简历维护pod节点路由表

三层网络(真实的网络只有节点网络)

k8s-02-基础概念_ip地址_06