kubernetes in action读书笔记(四)ConfigMap、Secret、滚动升级、downwardAPI、Deployment、Statefulset

  • ConfigMap
  • Secret
  • 如何访问pod的元数据
  • 由滚动升级引出Deployment
    • 原始的RC人工滚动升级
      • 缺陷
    • Deployment
  • Statefulset
  • 读书前对它们的理解

ConfigMap

没有太多好说的,一个用来解决服务配置的资源,可以避免硬编码,相对自由的在pod中使用。我们可以将configMap作为环境变量使用,也可以将configMap作为一个配置文件使用(直接映射到持久卷上),因此在创建configMap到时候,可以通过字面量创建,也可以将一个文件或者目录创建为一个configMap,需要注意的是,在使用configMap挂载到一个持久卷时,会将对应的目录其他文件覆盖掉,这个需要关注,避免把有用的文件覆盖掉了。

Secret

和configMap差不多都是作为pod的配置属性来使用的,不过secret不在磁盘存储,都是在内存中的,因此安全性上要比configMap要高。

如何访问pod的元数据

应用程序往往需要访问当前pod的一些基本的在K8S集群中的信息,比如版本号、镜像名称、hostname、ip等等,可以一般可以通过以下几种方式来获取:

通过环境变量获取元数据
看一段代码

env:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.name

这样能拿到pod的元数据,但是缺点是一旦这些元数据更新,这种环境变量的方式是不会更新的,必须重启pod。

通过downward API获取元数据
看一段代码

metadata:name: downwardlabels: foo: barannotations:key1: value1key2:multilinevalue
spec:containers:volumeMounts:- name: downwardmountPath: /etc/downward
volumes:
- name: downwarddownwardAPI:items:# podName会被写入到/etc/downward/podName这个文件里- path: "podName"filedRef:fieldPath: metadata.name# labels会被写入到/etc/downward/labels这个文件里- path: "labels"filedRef:fieldPath: metadata.labels

所以通过这种方式,只要在volumes下定义的内容,最后都会在volumeMounts下对应到一个文件,而且此时如果当元数据发生变化是,文件也会对应的刷新,环境变量就不不会刷新了,除了这个优点之外,环境变量也只能在当前pod中使用,如果一个pod有多个容器,那就得分开定义不能用重名的环境变量,但是通过downwardAPI就可以使用同样的名字,但是放在不同的目录下就行了。如果是只需要获取一次pod元数据的情况下,通过env其实也行。
downwardAPI解决了数据刷新以及多个容器在一个pod的问题,但是能够获取的数据是有限的(metadata.XXXX),如果需要更多的信息,需要通过k8s的api server查询。

通过api server获取元数据
不进行赘述,这个属于在服务内部实施的,即时性和数据的范围都是最大的。不过有个点倒是值得注意,书中提到了一种ambassador容器,类似一个代理容器,用来解决所有和api server的交互问题。因为和api server交互是需要鉴权认证的,不希望每个服务都做重复的事情,因此需要这个容器来解决公共的需求。

由滚动升级引出Deployment

原始的RC人工滚动升级

从第一张到现在基本上能够看到的资源就是RC(ReplicaController)和RS(ReplicaSet),我们平时最常用的Deployment和Statefulset始终没有出现过,本章总算讲到了Deployment。
RC本身已经是一种对pod声明式的管理,我们在RC中的定义包括replicas、images、selectors等等,K8S在进行根据定义对pod进行操作时,都是通过对定义的内容进行声明式的扫描和管理,需要什么样的资源,就提供什么样的资源,而不是RC本身定义好了之后,去向K8S去申请。Deployment被引出的一个关键点在于应用的升级,一个RC的典型升级过程如下:

1、当前RC有3个pod,都是v1版本,要升级到v2版本
2、修改RC的版本定义,改成V2
3、此时K8S 发现RC需要的pod版本是v2,就创建v2版本的pod
4、与此同时,v1版本的pod并不会自己销毁,所以需要手动销毁
5、销毁过程伴随服务不可用
6、等待v2版本pod都起来之后,服务恢复正常

为了避免出现服务不可用情况,考虑等v2版本的pod起来了,再删掉v1版本的pod,将上面从第三步开始,稍作修改:

等待v2版本的pod都完成创建,同时,v2版本的pod将标签修改的和v1不同
将SVC的labelSelector修改到v2版本的标签,这样SVC就将流量切换到了v2版本的pod上
删除v1版本的pod

通过这种方式,服务升级过程是没有中断的。只不过需要手动改一下RC的标签,手动修改一下SVC的labelSelector,最后再恢复回来。设想一下,如果我们直接使用两个RC来操作整个过程,是不是更简单一点?

1、创建v2版本的RC,v2版本的RC对应v2版本的pod创建,v1/v2 pod的labelSelector是一样的,只是RC名字不一样,所以v1/v2的pod创建好之后都会挂载一个SVC上
2、V2的RC创建好一个pod,V1就将replica减少1个
3、直到V2的RC全部建好,V1 RC的replica减少到0
需要注意的是第一步,v2版本的RC创建出来的pod,可能会被v1版本的RC识别并删除掉,所以在升级过程中两个版本的RC的labelSelector是不同的
假设V1版本的是:Selector:app=myService
为了让SVC能够识别到v2版本的pod,所以v2版本的pod也得具备app=myService这个标签,为了避免冲突,所以在v1/v2的RC分别都增加了一个标签:
v1的RC:Selector:app=myService,version=v1
v2的RC:Selector:app=myService,version=v2
这样一来,两个RC就是各论各的pod,而SVC的labelSelector只包含了app=myService,所以v1/v2的pod都会挂在SVC下

这个过程相比之前,简单的地方就在于我们不用在操作pod了,只用控制量两个RC的状态就行,在不同的时期对两个RC的replica个数进行控制,而且也不用改SVC了。

缺陷

这种人工手动升级的方式,首先得自己写代码控制状态,比较费劲,其次最大的问题在于这个升级状态是客户端执行的,是通过一个客户端程序对RC进行修改来实现的,如果说次数客户端的机器发生故障,那么升级也就中断了,可能会造成很大的损失,而且kubernetes一直强调的都是通过声明的方式来实现对系统状态的改变,所以应该考虑,如何在不费劲不手工的情况下,由集群本身对声明进行管理来实现滚动升级。

Deployment

按刚才说的,其实创建了一个deployment的同时其实也创建了一个ReplicaSet(新一代的ReplicaController),我们在使用deployment的过程,对pod管理其实是由RS来干的。yaml就不进行列举了,对比ReplicaController创建出的pod,样子看起来就不太一样~
RC声明的pod:

NAME                 READY       STATUS
myService-musda         1/1         running
myService-bfzxd         1/1         running

Deployment声明的pod:

NAME                         READY       STATUS
myService-1918372-sdgfs         1/1         running
myService-5981813-qasda         1/1         running

中间多了个数字,这个数字是pod模板的hash值,这样一方面deployment可以创建多个RS,另一方面这个名字既然和pod的模板hash一致,那也就能减少了不必要的名称的浪费,这些对应关系啥都要在etcd管理,这种方式也能减少不必要的名称膨胀。列举这个名字的区别主要是希望能够理解到,deployment内部本质上还是一个/多个的RS,刚才费半天劲说的滚动升级过程,在deployment中就是一个配置的操作就能搞定。而且deployment还顺便把回滚做了,每次滚动升级后,原先的RS并不会被立刻删除,deployment会保留一段时间内的RS,当发生回滚操作时,立刻就可以启用之前版本的RS资源,历史版本的默认数量是2。
感觉真正讲到了deployment又没有太多的内容,基本上还是沿用了RS/RC的思想,不过支持了滚动升级和回滚,其他的一些特性/场景,后面看看是不是讲到了kubernetes原理后有更多的细节介绍。

Statefulset

之前对statefulset的理解就是当需要挂盘的时候,才用到了statefulset,原因是statefulset的名称是固定的,一般都是my-service-0这种格式,如果是多实例,那就会逐个递增,当发生replica个数改变或重启时,pod的名称不变还是这个,所以对应的pvc啥的都不变,因为挂盘信息呀啥的都是基于名称在etcd中记录的映射关系,这种名字不变的pod就能实现有状态了。
除了上面说的这个名字会变的原因之外,另一个原因就是deployment或者说ReplicaSet是无法为多个pod创建多个PVC的,所以如果非要给ReplicaSet下的pod每个都搞一个独立的存储,那就得:

1、手动一个个创建PVC并且挂盘,这种方式就是不能重启,重启了就得再来一遍
2、一个pod一个ReplicaSet,这样每个都各申请各的,这种办法也比较挫;
3、ReplicaSet的多个pod用一个卷的多个不同的目录,这个得像个办法在pod创建之后通过一个第三方的服务来为多个pod进行目录使用权的分配。

mark一下,所以说ReplicaSet不能给每个pod创建pvc?why?是因为RS下的pod名字老变所以只能按照RS的名称来创建PVC的对应关系吗?前面看过,忘了~

除了上面说到的statefulset可以为pod提供一对一的稳定的pvc,同时statefulset所管理的pod还具备稳定的ip地址,所以对于希望服务端ip地址固定的应用场景,statefulset就能发挥作用,有一种山寨的办法是利用SVC,为每一个deployment都创建一个SVC,这种办法倒是能让pod的ip固定。

之前在使用statefulset时要创建pvc,当时遇到的问题记录了一下,文章内容搬过来,也是关于deployment和statefulset的。

读书前对它们的理解

=====================================================================
今天在处理一个PVC无法自动创建的问题时,顺便理了一下。

在创建一个Deployment时发现PVC无法自动创建,查了一下相关内容,主要参考一下文章:
https://akomljen.com/kubernetes-persistent-volumes-with-deployment-and-statefulset/
其中:

译:可以通过ReadWriteOnce模式来给Deployment创建一个PVC,这样可以正常运行,但是前提是不能扩展Deployment,因为如果一旦有多个pod,那么当一个节点上的pod在使用pvc时,另一个pod在另一个节点上就没法用了,而且即便两个pod在一个节点上,都用一个pvc也会报错;(ReadWriteOnce意思是该pvc一次只能有一个node访问)

译:如果想跑一个有状态的服务,那就用stateful set,这样有很多好处,特别是你不用自己在创建PVC了,而且扩展起来特别容易,通过stateful set,可你可以定义volumeClaimTemplates来让每个pod自己自动创建pvc,你只用在一个地方定义你的持久卷(statefulset的yaml)

目前1.5版本以下还不支持Deployment用这种方式自动创建PVC/PV

顺便翻查了一下stateful set和deployment的区别,几篇blog写的可以参考。
https://draveness.me/kubernetes-statefulset
statefulset实现原理
http://www.unmin.club/?p=696
headeless.service的保证原理(通过这个文章发现我目前使用的stateful set的方式是不合理的,完全是为了用持久卷而用stateful set,因为clusterIp不是none,请求并不会稳定的转发到一个pod上,所以说白了不同实例建其实还是无状态的)
https://www.jianshu.com/p/18042b5f2682
stateful set deployment整体对比
另外mark一条老是记不住也查半天的命令:iptables -S -t nat

2020-01-15补充
kubernetes在应用过程最终都是围绕pod进行的管理,deployment/statefulset都作用于pod,作为不同的controller,两者的主要区别是deployment在调用api-server/scheduler时,不会指定固定名称的pod;statefulset在每次申请pod的时候,都会固定pod的名字,类似myservice-0、myservice-1,这个绑定关系存在,所以可以把这个关系再搭上一个PVC,就能实现statefulset的有状态了。

顺便补充一下关于调度的理解,整体看提交的过程,大体上是:

  1. 客户端提交一次请求到api-server创建一个deployment,持久化到etcd
  2. deployment controller订阅api-server发现有deployment要部署,获取到之后根据deployment的描述调用api-server创建pod,持久化到etcd
  3. scheduler订阅api-server,从etcd中发现需要创建pod,则根据pod属性找到对应的node
  4. node订阅scheduler发现有一个pod属于自己,则下载对应的image并拉起对应的pod

kubernetes in action读书笔记(四)ConfigMap、Secret、滚动升级、downwardAPI、Deployment、Statefulset相关推荐

  1. Machine Learning in Action 读书笔记---第5章 Logistic回归

    Machine Learning in Action 读书笔记 第5章 Logistic回归 文章目录 Machine Learning in Action 读书笔记 一.Logistic回归 1.L ...

  2. Machine Learning in Action 读书笔记---第3章 决策树

    Machine Learning in Action 读书笔记 第3章 决策树 文章目录 Machine Learning in Action 读书笔记 一.决策树算法简介 1 决策树的构造 2 决策 ...

  3. Machine Learning in Action 读书笔记---第4章 基于概率论的分类方法:朴素贝叶斯

    Machine Learning in Action 读书笔记 第4章 基于概率论的分类方法:朴素贝叶斯 文章目录 Machine Learning in Action 读书笔记 一.基于贝叶斯决策理 ...

  4. Machine Learning in Action 读书笔记---第8章 预测数值型数据:回归

    Machine Learning in Action 读书笔记 第8章 预测数值型数据:回归 文章目录 Machine Learning in Action 读书笔记 一.回归 1.回归的一般过程 2 ...

  5. 3d游戏设计读书笔记四

    3d游戏设计读书笔记四 一.基本操作演练[建议做] 下载 Fantasy Skybox FREE, 构建自己的游戏场景 a. 在AssetStore中搜索Fantasy Skybox FREE并下载. ...

  6. 《关键对话——注意观察,如何判断对话氛围是否安全》读书笔记(四)

    <关键对话--注意观察,如何判断对话氛围是否安全>读书笔记(四) 在对话过程中,既要关注对话内容(即讨论的主题),也要观察对话气氛(即参与者的反应).越早意识到你和对方退出了对话机制,就越 ...

  7. LINQ IN ACTION读书笔记:LINQ 使用连接 1、组连接 2、内连接 3、左外连接 4、交叉连接 使用和区别...

    使用的数据源类型: static public class SampleData{static public Publisher[] Publishers ={new Publisher {Name= ...

  8. 《编程之美》读书笔记(四): 卖书折扣问题的贪心解法

    <编程之美>读书笔记(四):卖书折扣问题的贪心解法 每次看完<编程之美>中的问题,想要亲自演算一下或深入思考的时候,都觉得时间过得很快,动辄一两个小时,如果再把代码敲一遍的话, ...

  9. 《大型网站技术架构》读书笔记四:瞬时响应之网站的高性能架构

    来源:http://www.cnblogs.com/edisonchou/p/3809839.html 此篇已收录至<大型网站技术架构>读书笔记系列目录贴,点击访问该目录可获取更多内容. ...

  10. 《淘宝技术这十年》读书笔记 (四). 分布式时代和中间件

    前面两篇文章介绍了淘宝的发展历程.Java时代的变迁和淘宝开始创新技术:              <淘宝技术这十年>读书笔记 (一).淘宝网技术简介及来源              &l ...

最新文章

  1. python工程技巧_python 19个值得学习的编程技巧
  2. sockaddr_in中sin_zero的意义,以及sockaddr_in sockaddr in_addr区别联系
  3. 关于计算机的网络作文,关于网络世界的作文
  4. http 阮一峰_互联网协议入门(二)
  5. nginx限制恶意IP处理方法
  6. [APK拆解]谷歌眼镜XE16设置新语言,当你盯着屏幕时可同步检测
  7. 如何查看Dell服务器前面板LCD的报错资讯
  8. servlet详细理解
  9. android词根词缀,词根词缀记忆字典 - 好担心你们因为它的界面丑,而错过这款背单词神器 - Android 应用 - 【最美应用】...
  10. 宽带连接工具[bat]
  11. 酷派把用户手机当肉鸡,非一天两天
  12. 天大、中南、中山、北师、中科院地图学与地理信息系统GIS及遥感RS专业推免夏令营面试经历与题目汇总
  13. startx 启动的过程
  14. day56 JavaScript
  15. .net 邮箱验证码 邮箱验证码实现用户注册
  16. 用html写除法竖式代码,除法的竖式写法
  17. centos8 手动修改网络配置以及怎么重启网络,添加开机自启动
  18. 单源最短路径算法java_数据结构 - 单源最短路径之迪杰斯特拉(Dijkstra)算法详解(Java)...
  19. IMU数据仿真公式推导及代码实现
  20. 基于xwiki部署企业内部知识管理平台

热门文章

  1. openstack(云主机热迁移)
  2. Layui Form 如何主动验证表单是否通过
  3. 卡尔曼滤波原在温度测量中的应用
  4. Brave与Uphold合作推出钱包以奖励用户浏览
  5. android 钢琴识别音阶对错_练习音阶琶音的方法——你确定自己没弄错?
  6. 一图看懂互联网各职位都是干啥的
  7. RAITE Hypervisor介绍
  8. 01表盘控件-08时钟仪表盘-gaugeclock
  9. 国务院关于积极推进“互联网+”行动的指导意见
  10. COSOSWAP的这份NFT防盗指南,请给周杰伦转发