企业级运维之云原生与Kubernets实战课程
第一章第4讲 如何创建应用与暴露服务
视频地址:https://developer.aliyun.com/learning/course/913/detail/14499
摘要:本小节主要内容为K8s核心概念,包括声明式API、K8s组件控制器、SVC创建及使用、Pod生命周期管理及Kubectl常用命令和使用技巧。
目录
- 声明式API
- 创建Deployment
- 创建service服务
- Kubectl常用命令和使用技巧
一、声明式API
1. 什么是声明式API
声明式API:提交的API对象不再是一个单体应用的描述,而是一个完整的分布式应用集群的描述。
2. 命令式API与生命式API
- 命令式API:命令“机器”如何去做事情(how),这样不管你想要的是什么(what),它都会按照你的命令实现。
- 声明式API:告诉“机器”你想要的是什么,让机器想出如何去做。
3. 声明式API核心原理
- 当用户向 Kubernetes 提交了一个 API 对象的描述之后,Kubernetes会负责保障整个集群里各项资源的状态,确保与API 对象描述的需求相一致;
- 更重要的是,这个保证是一项“无条件的”、“没有期限”的承诺:对于每个保存在etcd里的API对象,Kubernetes都通过启动一种叫做“控制器模式”(Controller Pattern) 的无限循环,不断检查,然后调谐,最后确保整个集群的状态与这个API对象的描述一致;
- 简单理解就是对象的声明与对象的创建互相解耦,在普通程序中创建对象需要向操作系统申请资源,相似的在容器云平台上创建对象,需要向K8s申请资源;
- 在K8s环境中,只需要提交一个申请单,然后由K8s系统完成对象的创建。
4. 声明式API与控制器总结
二、创建Deployment
1. 什么是Deployment
简单来说,Deployment是管理无状态应用部署发布的控制器,相当于管理Pod的经理人。
在K8s中,组件控制器controller包括:
- Deployment:无状态
- Statefulset:有状态
- Job:运行一个任务
- Cronjob:周期性运行
- Daemonset:在指定的node或者所有的node上运行一个pod
- HPA :根据资源使用状况,来维持扩容/缩容副本数(客户自定义的资源维度)。
如图,通过Deployment将应用A、B、C分别规划到不同的容器组中,每个Deployment其实是管理的一组相同的应用Pod,这组Pod我们认为它是相同的一个副本。
2. Deployment功能
- 定义一组Pod的期望数量,Deployment控制器会维持Pod数量与期望数量一致;
- 配置Pod发布方式,Deployment控制器会按照给定策略更新Pod,保证更新过程中不可用的Pod数量在限定范围内;
- 如果发布有问题,支持“一键”回滚。
比如说应用A期望的Pod数量是4个,controller就会持续维持Pod数量为期望的数量,当Pod出现了网络问题或者宿主机问题,controller能将其恢复,也就是新扩出来对应的Pod,来保证可用Pod数量与期望数量一致。
3. Deployment语法
- Metadata:Deployment元信息;
- Replicas:Pod的最终数量;
- Selector:Pod的选择器;
- Template:Pod模板;
- Pod image:镜像版本;
- Labels:标签
在容器更新镜像时,Deployment要通过新建Pod更新容器镜像,可以通过maxsurge和maxUnavailable来保证副本数一致,如:
- replicas:4
- maxSurge:25%,那么4*1.25=5(最多5个running的副本)
- maxUnavailable:25%,那么4*0.75=3(最小3个不可用)
亦即,在滚动更新时,最多5个running的副本,最小3个不可用副本。
在Deployment中,revisionHistory可以设置保持历史版本的个数,在Deployment创建Pod时,会通过replicaset来拉起Pod,Deployment与Pod之间无直接联系,而是通过replicaset来管理Pod。
4. Deployment相关操作
a. Deployment创建无状态服务:
- kubectl rollout history deployment:查看历史Pod版本;
- kubectl rollout undo deployment:回滚发布;
- kubectl scale deployment/xxx(xxx为容器名)--replicas=n(n为副本数):进行副本的扩缩容;
- kubectl get pod -owide:查看Pod所运行的节点信息。
b. Statefulset:创建有状态服务(略);
c. Job会创建一个或者多个Pod,直到运行成功为止,运行成功后正常退出;
kubectl get job:查看job类型的Pod;
kubectl describe job xxx(job服务名):查看job的运行信息;
Parallelism:Job运行时并行数;
Completions:Job运行成功数;
backoffLimit(失败阀值):设置activeDeadlinesSeconds时间,一旦job运行时间达到这个设置值,终止所有的pod。可以编写yaml文件设置每次启动一个job运行五次和设置并行启动两个job运行六次,通过命令watch -d kubectl get 监控job创建的次数发现,job的启动是按照并行数启动,然后正常退出,直到完成所有运行次数。
d. CronJob:周期性的执行job类似Linux下crontab;
设置方式:Schedule:"*/1 * * * *"表示每分钟都运行1次
- startingDeadlineSeconds
如果startingDeadlineSeconds字段非空,则控制器会统计从startingDeadlineSeconds设置的值到现在、而不是从上一个计划时间到现在错过了多少次Job。例如,如果startingDeadlineSeconds是200,则控制器会统计在过去200秒中错过了多少次Job。
- concurrencyPolicy,共同运行的policy(allow,forbid)
如果未能在调度时间内创建CronJob,则计为错过。例如,如果concurrencyPolicy被设置为Forbid,并且当前有一个调度仍在运行的情况下,试图调度的CronJob将被计算为错过。
- 情况1:concurrencyPolicy=forbidstartingDeadlineSeconds默认,CronJob被设置为从08:30:00开始每隔一分钟创建一个新的Job;如果CronJob控制器从08:29:00到10:21:00终止运行,则该Job将不会启动,因为其错过的调度次数超过了100。
- 情况2:concurrencyPolicy=forbidstartingDeadlineSeconds=200,如果CronJob控制器恰好在与上一个示例相同的时间段(08:29:00到10:21:00)终止运行,则Job仍将从10:22:00开始。造成这种情况的原因是控制器现在检查在最近200秒(即3个错过的调度)中发生了多少次错过的Job调度,而不是从现在为止的最后一个调度时间开始。
e. Daemonset的Pod会在指定的node或者所有的node上运行。
三、创建Service暴露服务
1. 什么是service(SVC)
Service是Kubernetes中的服务发现与负载均衡。
为什么需要服务发现?Kubernetes应用应如何相互调用?Kubernetes应用应如何相互调用?
- Pod生命周期短暂,IP地址随时变化;
- Deployment等的Pod组需要统一访问入口和做负载均衡;
- 应用间在不同环境部署时保持同样的部署拓扑和访问方式;
- 集群内可以通过service name 直接访问
2. Service语法
3. Service类型
a. ClusterIP:分配一个集群内部的IP地址,只能在集群内部访问。
- kubectl get svc:查看创建了哪些SVC;
- kubectl get ep xxx(svc的名字):查看svc后端挂载的服务;
- curl命令:访问该服务。
- 流量流转:从client访问SVC,SVC通过iptables或Ipvs转发到后端Pod,SVC通过Lable选择Pod,ClusterIP暴露的SVC可以通过集群内部访问或Pod访问;
- 无头Service 指定 clusterlP: None
- Pod 通过 service_name 方式访问时可以获取到所有后端Pod IP;
- 客户端应用自主选择需要访问的Pod。
b. NodePort:分配一个集群内部的IP地址,并在每个节点上启用一个端口来暴露服务,可以在集群外部被访问。
c. Loadblalancer:分配一个集群内部的IP地址,并在每个节点上启用一个端口来暴露服务,除此之外,kubernetes会请求底层云平台上的负载均衡器,把Node节点作为后端添加进去。
- 通过NodePort与SLB配合的方式,创建NodePort模式的SVC并在前面加上负载均衡,通过NodePort把节点暴露出来,客户端可以访问节点端口就是访问了SVC进而访问了后端Pod;
- 可以通过命令kubectl describe svc xxx(svc服务名),查看NodePort暴露的端口;
- Loadblalancer的SVC,在master节点上有组件CCM (c1ond contro11er mannger)去创建/复用已经存在的SLB的设备,并把这些集群节点加到 SLB上,外部客户端访问SLB(ip)就会被转发到后端节点SVC上再转发到Pod,而SLB一般都是多可用区容灾,不存在单点故障。
d. Externalname:把外部相关域名或IP引入到集群内部;
- <svc name>.<ns>.svc.cluster.local:集群内部访问外部域名访问方式;
- 好处:内部代码不必写死外部的IP,如果外部IP改变,只需要变更SVC即可,不需要改动代码。
本讲小结
1. Deployment、daemonset、job、cronjob、svc等内容。
2. Kubectl的相关命令,Pod滚动更新等内容。
3. SVC。