K8s(一) 入门
K8s简述演示实在是很难一句话把K8s是什么说清楚,我觉得还是直接看图比较直观。首选需要一个集群环境,使用3台虚拟机虚拟机构建1个主,2个从的模拟集群环境。在保证主机网络互通并且成功安装上kubernetes之后,就拥有了一个最基础的集群环境。使用 kubectl get node 命令可以查看整个k8s集群的节点情况,当所有节点都是Reday的时候就表示集群搭建成功。然后就可以在K8s上运行应用
K8s简述
演示
实在是很难一句话把K8s是什么说清楚,我觉得还是直接看图比较直观。
首选需要一个集群环境,使用3台虚拟机虚拟机构建1个主,2个从的模拟集群环境。在保证主机网络互通并且成功安装上kubernetes之后,就拥有了一个最基础的集群环境。
使用 kubectl get node 命令可以查看整个k8s集群的节点情况,当所有节点都是Reday的时候就表示集群搭建成功。
然后就可以在K8s上运行应用程序。使用yaml格式的声明文件去定义一个应用:
下面这段yaml格式的文件的含义只要这些就行了:
声明了一个服务资源,运行的是一个本地仓库中名称是hub.xiaosha.com/library/myapp 版本是v1的镜像,这个镜像启动之后就是一个服务容器,并且k8s将保障他在整个k8s集群中中始终维持三个副本数目。
apiVersion: extensions/v1beta1
kind: ReplicaSet
metadata:
name: frontend
spec:
replicas: 3 #三个副本数目
selector: #选择标签
matchLabels: #匹配
tier: frontend
template:
metadata:
labels:
tier: frontend
spec:
containers:
- name: myapp
image: hub.xiaosha.com/library/myapp:v1
env:
- name: GET_HOSTS_FROM
value: dns
ports:
- containerPort: 80
把定义好的这个剧本交给k8s之后,k8s就会按照剧本的意图在两个节点上创建-启动-运行了两个镜像服务,如下图。
因为在文件中规定了副本的数目是3,可以看到在node1上运行了2个容器,node2上运行了1个。
接下来就可以对服务进行访问,因为每一个服务都已经暴露了一个可访问的IP。
演示扩容
假设现在有比较大的并发请求访问这个服务,现在的3个副本数目撑不出,需要进行扩容,这个时候需要借助deployment组件定义服务:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: test-deployment
spec:
replicas: 3 #三个副本数目
template:
metadata:
labels:
tier: test
spec:
containers:
- name: test
image: hub.xiaosha.com/library/myapp:v1
ports:
- containerPort: 80
使用命令 kubectl scale deployment test-deployment --replicas=6
将test-deployment 的副本数目扩容为6个,结果图如下:
演示版本更新
假设现在有一个版本更新的动作,需要将代码的版本从v1升级为v2,使用命令:
kubectl set image deployment/test-deployment test=hub.xiaosha.com/library/myapp:v2
就可以将test-deployment下的镜像从v1升级为v2,效果截图如下:其实他是一个灰度发布的过程,等新版本的代码运行稳定之后才会删除原来旧版本的服务。
K8s是什么?
K8s指的是Kubernetes,K和s之间有8个字母,所以也叫K8s。
K8s中文社区的网址: https://www.kubernetes.org.cn/k8s
概况
最近几年在互联网企业里面最流行的词语有:云原生,容器,K8s,弹性计算等。应用软件重单一架构走到SOA再到微服务架构,将应用拆分、解耦,专注化,模块化的开发模式在技术上已经很成熟,越来越多的企业也开始往微服务模式转型。当服务模块化,微服务化的改造之后,这些服务在生产环境中如何高效可靠的运行、管理、调用又变成了难题。
容器
从Docker横空出世以来,给Paas的世界制定了一套统一的标准,容器化的服务部署技术也越来越成熟。Docker将代码打包成独立的镜像,借助于Linux系统内核,使用保留字指令编写dockerfile文件就能在docker里面轻松构建镜像,这是代码在容器化运维环境下表现形式,而将镜像启动,就能对外暴露服务端口,提供服务能力。
缺陷
然而,有时候容器的表现并不像原本想象的那么优秀,实际情况下,没有很好的部署规划,在集群环境下是很容易出错的。
1、比如,两个提供相同服务的容器部署在不同的服务器环境下,如何对外提供统一的访问接口,并且自动负载均衡?
是不是只能采用Nginx做一个服务代理,并且把对应的ip端口做映射之后才能解决。
2、比如,两个容器的对外端口是一样的,是不是必须要保证部署在不同的服务器上,避免发生端口冲突。但是实际的硬件资源其实在很多时候并不是很理想化。
3、比如,刚刚演示的扩容,需要手动在docker里面去启动新的容器来完成。至于代码版本升级发布、回滚这些情况处理起来也可想见也不是很轻松。
有缺陷,就会有改进策略,有需求,就一定会有实现的产品。于是乎,K8s在微服务配合Docker不易于维护的前置条件下,在2015年7月由谷歌发布诞生。
前世今生
Docke作为一种容器引擎一经发布就迅速火爆,很多大公司都不约而同的将目光瞄准这个利器。随着对它研究使用的深入,也就不难发现上面列举的诸多难题痛点。当然,发展的障碍不会阻碍发展。谷歌多年在容器技术和集群方面积累了很多的经验,他们也有一套容器编排调度框架——Borg。
Borg系统更像是一个容器管理器,上千万的服务器连接形成集群,Borg就处理这些集群中容器的调度,谷歌搜索、地图等等都能轻松的从数据中心获取数据然后撑起整个服务。这些系统提交的Job,Borg时时刻刻在处理这些Job的接收、调度、启动、停止、重启和监控。但是也仅仅是谷歌自己内部使用,所以在当时Borg框架真的是羡煞旁人一般的存在。
当时Borg确实是谷歌的一种核心竞争利器,也作为一种商业资本。但是之后,随着系统服务化、模块化的普及,Docker自身的发展,以及云计算的发展,越来越多的公司开始对这个领域发起冲锋。推特的工程师也构建起来了一个类似于Borg的系统。于是谷歌就开始研究一种以自己的技术理论为核心的开源产品。
2014年6月,谷歌云计算专家埃里克·布鲁尔(Eric Brewer)在旧金山的发布会为这款新的开源工具揭牌,它的名字Kubernetes在希腊语中意思是船长或领航员,这也恰好与它在容器集群管理中的作用吻合,即作为装载了集装箱(Container)的众多货船的指挥者,负担着全局调度和运行监控的职责。
虽然Google推出Kubernetes的目的之一是推广其周边的计算引擎(Google Compute Engine)和谷歌应用引擎(Google App Engine)。但Kubernetes的出现能让更多的互联网企业可以享受到连接众多计算机成为集群资源池的好处。
Kubernetes对计算资源进行了更高层次的抽象,通过将容器进行细致的组合,将最终的应用服务交给用户。Kubernetes在模型建立之初就考虑了容器跨机连接的要求,支持多种网络解决方案,同时在Service层次构建集群范围的SDN网络。其目的是将服务发现和负载均衡放置到容器可达的范围,这种透明的方式便利了各个服务间的通信,并为微服务架构的实践提供了平台基础。而在Pod层次上,作为Kubernetes可操作的最小对象,其特征更是对微服务架构的原生支持。
Kubernetes项目来源于Borg,可以说是集结了Borg设计思想的精华,并且吸收了Borg系统中的经验和教训。
Kubernetes作为容器集群管理工具,于2015年7月22日迭代到 v 1.0并正式对外公布,这意味着这个开源容器编排系统可以正式在生产环境使用。与此同时,谷歌联合Linux基金会及其他合作伙伴共同成立了CNCF基金会( Cloud Native Computing Foundation),并将Kuberentes 作为首个编入CNCF管理体系的开源项目,助力容器技术生态的发展进步。Kubernetes项目凝结了Google过去十年间在生产环境的经验和教训,从Borg的多任务Alloc资源块到Kubernetes的多副本Pod,从Borg的Cell集群管理,到Kubernetes设计理念中的联邦集群,在Docker等高级引擎带动容器技术兴起和大众化的同时,为容器集群管理提供独了到见解和新思路。
Pod
在Kubernetes中,最小的管理元素不是一个个独立的容器,而是Pod,Pod是最小的,管理,创建,计划的最小单元。
在Kubenetes中,所有的容器均在Pod中运行,借助于Docker,一个Pod里面可以包含一个或者多个相关容器。并且每一个Pod在启动的时候都会运行一个叫做pause的镜像,这个容器是伴随着k8s的,也是每一个pod中都会存在的一个很重要的容器。它的作用是为kubernetes提供一个扁平化的网络。
同一个Pod中的容器会部署在同一个物理机器上并且能够共享资源。磁盘、网络、计算、内存等等。
对于用户创建的每个Pod,K8s会自动选择那个健康并且有足够容量的机器,然后创建类似容器的容器,当容器创建失败的时候,容器会被一个叫kubelet的组件重启。
自己创建并管理Pod,Kubernetes将这些操作简化为两个操作:基于相同的Pod配置文件部署多个Pod复制品;创建可替代的Pod当一个Pod挂了或者机器挂了的时候。而Kubernetes API中负责来在存活的机器上启动一个新的Pod。如下图:
当删除一个之后,k8s发现不满足3个副本数,就会去存活的节点上去创建一个新的Pod。当然,这需要定义RS或者是Deployment,这个之后会有聊到。
有时候需要对一组Pod进行一些操作,比如说我希望对这组Pod在启动成功之后做一些事情,如何选择到这些Pod,K8s也是提供了一种标签选择的机制。可以给Kubernetes Api中的任何对象贴上一组 key:value的标签,然后,我们就可以通过标签来选择一组相关的Kubernetes Api 对象,然后去执行一些特定的操作。
关于Pod更多的内容可以查阅中文社区,对于一些概念名词的解释上面写的真的很到位。https://www.kubernetes.org.cn/kubernetes-pod
K8s的一些概念
- apiserver 所有服务访问的统一入口
- controllerManager: 护副本的期望数目
- Scheduler 负责接收任务,选择合适的节点进行分配任务
- etcd 键值对数据库,存储K8S集群所有的重要信息(持久化)能够为整个分布式集群存储一些关键数据,协助分布式集群的正常运转。
- kubelet 直接干容器引擎交互实现容器的生命周期管理
- kube-proxy 负责写入规则到iptables\ipvs 实现服务映射访问
- coreDNS 为集群中的SVC创建一个域名IP的对应关系解析
- dashboard 给k8s集群提供一个B/S结构的访问体系
- ingress controller :官方只能实现四层代理,ingress 可以实现七层代理 f
- ederation 提供一个可以跨集群中心多K8S统一管理功能
- prometheus 提供K8S集群的监控能力
- ELK 提供 K8S 集群日志统一分析介入平台
Pod
Pod 分为自主式Pod和控制器管理的Pod,自主式的Pod不被控制器管理的Pod,Pod死亡之后不会被拉起来,也不会创建副本满足副本的期望值。
在同一个Pod里面的容器,端口不能重复,他们共用pause的网络栈,也共享pause的存储卷,可以通过localhost相互见面。
Pod控制器类型
1、ReplicationController (RC) & ReplicaSet(RS) & Deployment 这三个其实是一种类型
RC:用来确保容器应用的副本数量始终保持在用户定义的副本数,如果有容器异常退出,会自动创建新的Pod来替代;如果异常多出来的容器也会被自动回收。
官方建议使用ReplicaSet来取代RC,ReplicaSet支持集合式的selector,但是实际建议使用Deployment来自动管理ReplicaSet,支持滚动更新。
deployment去创建RS,RS再去创建Pod,假如需要更新镜像的时候,deployment去创建一个RS,RS再去滚动更新一个个镜像。并且支持回滚。
2、Horizontal Pod Autoscaling (HPA)适用于Deployment和RS,支持根据CPU利用率去扩容,支持根据内存的使用情况和用户定义的值进行扩容。
比如规定最大镜像是10,最小是1,当CPU利用率超过80%之后就会进行水平扩容。
3、StatefulSet 解决了有状态的服务问题,对应Deployment和RS是无状态服务而设计的,适用场景有:
稳定的持久存储:Pod重新调度之后是能访问到相同的持久化数据,基于PVC来实现的
稳定的网络标志:Pod重新调度之后其PodName和HostName不变,基于Headless Service 来实现
有序部署,有扩展性:Pod是有序的,在部署或者扩展的时候要一局定义的顺序依次进行,从0到N-1,在下一个Pod运行之前所有的Pod必须是Running和Ready状态,基于init containers来实现
有序伸缩,有序删除。
有状态服务:把服务抽离出集群之后再放回来就无法正常工作。(Mysql)
无状态服务:Docker面对的就是无状态服务,对应的就是没有对应的存储需要去实时的保留。(Apache服务,IOS)
4、DaemonSet确保全部或者一些Node上运行一个Pod副本。当有Node加入集群的时候,也会为他们新增一个Pod。 当有Node从集群中移除的时候,这些Pod也会被回收。删除DaemonSet将会删除它创建的所有Pod
运行集群存储daemon 例如在每月Node上运行 glusterd ceph
在每一个Node上运行日志收集daemon 例如 fluentd logstash
在每一个Node上运行监控daemon 例如 Promentheus Node Exporter
5、Job 负责批处理任务,仅仅执行一次,保证批处理任务的一个或者多个pod成功结束
Cron Job管理基于事件的定时任务,在指定时间仅仅运行一次或者周期性的在给定时间点运行
Service 服务发现
客户端想要去访问一组Pod的时候,这些Pod如果没有相干性,是不能通过Service统一代理的。
这些Pod要具有一定的相关性才可以,比如说是用一个RS、RC、Deployment创建,或者是拥有同一组标签,都可以被Service统一代理。
Service去收集Pod的时候是去通过标签去选择的,这样些被Service发现的Pod组成一个服务,客户端就可以通过访问Service的ip+端口放完到这些Pod了
网络通讯
Kubernetes的网络模型假设了所有Pod都可以在一个可以直接连通的扁平的网络空间中,这在GCE(Google Compute Engine)里面是现成的网络模型。K8s假定这个网络已经存在。 而在私有云里搭建K8s集群,就不能假定这个网络已经存在了。我们需要自己实现这个网络假设,将不同节点上的Docker容器之间的相互访问打通,然后运行K8s。
扁平的意思就是:在K8s里面,所有的Pod都可以通过对方的Ip直接到达。
同一个Pod内的多个容器:直接使用localhost就可以访问到
各个Pod之间的通讯:Overlay Network
Pod与Service之间的通讯: 各节点的Iptables规则
Flannel是CoreOS团队针对K8s设计的一个网络规划服务,简单的来说,他的功能是让集群中不同节点的主机创建的Docker容器都具有全集群唯一的虚拟IP地址。而且它还能在这些IP地址之间建立一个覆盖网络(OverLay NetWork),通过这个覆盖网络,将数据包原封不动的传递到目标容器内。
Flannel对于跨主机的访问把数据包进行了二次封装和解封。
Flannel和ETCD之间的关联:ETCD存储管理Flannel可分配的IP地址段资源, ETCD监控每个Pod的实际地址,并且在内存中维护Pod节点的路由表
如上图:K8s里面有三层网络
Service网络:虚拟网络、Pod网络:虚拟网络、节点网络:唯一一个真实的物理网络
整张图描述了K8s内部怎么去方位容器,以及在集群之外又该怎么去访问。
1、同一个Pod内存通讯
同一个Pod共享一个网络命名空间,共享同一个Linux协议栈
2、Pod1至Pod2
Pod1与pod2不再同一个物理主机上,Pod的地址是与docker0在同一个网段的,但是docker0网段与两个宿主机网卡是两个完全不同的IP网段 并且不同的Node之间的通信只能通过宿主机的物理网卡进行,将Pod的IP和所在Node的IP关联起来,让两个Pod能够互相访问。
Pod1和Pod2在同一台机器,由docker0网桥直接转发请求至Pod2,不需要进过Flannel
3、Pod至Service
全部是由iptables维护和转发
4、Pod到外网
Pod像外网发送请求,查找路由表,转发数据包到宿主机的网卡,宿主网卡完成路由的选择,iptables执行masquerade,把源IP更改为宿主网卡的IP,然后向外网服务器发送请求。
5、外网访问Pod
要经过Service
结语
K8s是一个需要动手去体会的技术,这里有作者搭建K8s环境的全部步骤记录,也一直在更新中。
https://github.com/xiaoshaDestiny/My-Note-Utils-Learn/tree/master/K8s
自己是跟着 尚硅谷 汪洋 老师的视频进行搭建的,整体的集群规划设计如下图,不同的是我把镜像存储节点放到了node2上去,节省一个虚拟机的内存空间。
更多推荐
所有评论(0)