
那些看似不起波澜的日复一日,一定会在某一天让你看见坚持的意义。
文章标记颜色说明:
- 黄色:重要标题
- 红色:用来标记结论
- 绿色:用来标记一级论点
- 蓝色:用来标记二级论点
Kubernetes (k8s) 是一个容器编排平台,允许在容器中运行应用程序和服务。今天学习一下StatefulSet-存储状态。
希望这篇文章能让你不仅有一定的收获,而且可以愉快的学习,如果有什么建议,都可以留言和我交流
这是这篇文章所在的专栏,欢迎订阅:【深入解析k8s】专栏
简单介绍一下这个专栏要做的事:
主要是深入解析每个知识点,帮助大家完全掌握k8s,一下是已更新的章节
| 序号 | 文章 |
| 第一讲 | 深入解析 k8s:入门指南(一) |
| 第二讲 | 深入解析 k8s:入门指南(二) |
| 第三讲 | 深入解析Pod对象(一) |
| 第四讲 | 深入解析Pod对象(二) |
| 第五讲 | 深入解析无状态服务 |
| 第六讲 | 深入解析有状态服务 |
| 第七讲 | 深入解析控制器 |
| 第八讲 | 深入解析 ReplicaSet |
| 第九讲 | 深入解析滚动升级 |
| 第十讲 | 深入解析StatefulSet(一) |
StatefulSet 的设计,它把真实世界里的应用状态,抽象为了两种:
- 拓扑状态
- 存储状态
在前面一篇文章中,我们已经了解了拓扑状态,今天主要学习一下存储状态
StatefulSet 对存储状态的管理机制,主要使用的是一个叫作 Persistent Volume Claim 的功能。所以我们需要先来看下这个功能的介绍与使用。
持久卷(Persistent Volume)是一种独立于 Pod 的存储资源。持久卷可以独立于 Pod 的生命周期存在,并且可以在 Pod 重新调度后仍然保留数据。
在 Kubernetes 中,要使用持久卷,需要创建一个持久卷声明(Persistent Volume Claim),
Persistent Volume Claim (PVC) 是一种用于声明对持久存储资源的需求的资源对象。
PVC 允许将应用程序和存储资源的生命周期分开,以便在应用程序重新部署或迁移时保留持久存储数据。
Persistent Volume Claim(PVC)是在 Kubernetes 中定义一个存储资源的方式。PVC 允许 Pod 请求特定大小和访问模式的存储。
PVC 实际上是一个声明,它声明了 Pod 需要的存储资源。
Kubernetes 系统会根据 PVC 的要求选择或创建一个相应的持久卷来满足 Pod 的需求。
如果 PV 满足 PVC 的要求,则将 PV 绑定到 PVC,并将 PVC 暴露给应用程序使用。
PVC 可以在多个 Pod 之间共享,但每次只能绑定到一个 PV 上。
PVC 的访问模式指定了允许哪些节点以哪种方式使用持久卷。以下是 PVC 的三种访问模式:
- ReadWriteOnce:允许单个节点以读写模式挂载持久卷。
- ReadOnlyMany:允许多个节点以只读模式挂载持久卷。
- ReadWriteMany:允许多个节点以读写模式挂载持久卷。
需要注意的是,不是所有的存储插件都支持所有的访问模式。因此,在使用 PVC 的时候,需要确保所使用的存储插件支持所需的访问模式。
- 关系:PVC 和 Pod 是紧密相关的。
- 请求:一个 Pod 可以请求一个或多个 PVC,并将 PVC 挂载到容器中。
- 挂载:在 Pod 被调度到节点上时,Kubernetes 系统会为 Pod 中声明的每个 PVC 创建一个持久卷,并将其挂载到 Pod 上。
- 删除:当 Pod 被删除时,与之关联的 PVC 不会被删除,这些 PVC 可以在之后的 Pod 中继续使用。
下面是一个 PVC 的 YAML 文件示例:
apiVersion: v1
kind: PersistentVolumeClaim # PVC资源类型
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
在这个示例中,创建了一个名为 my-pvc 的 PVC,并指定了访问模式为 ReadWriteOnce,请求的存储容量为 1Gi。
接下来,可以创建一个使用这个 PVC 的 Pod。
下面是一个使用 my-pvc 的 Pod 的 YAML 文件示例:
apiVersion: v1
kind: Pod #资源类型
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: nginx
volumeMounts:
- name: my-pvc-volume
mountPath: /data
volumes:
- name: my-pvc-volume #当前pod对应的pvc名称
persistentVolumeClaim:
claimName: my-pvc #使用刚刚创建声明的pvc
在这个示例中,创建了一个名为 my-pod 的 Pod,并将其容器的 /data 目录挂载到 my-pvc-volume 卷中。该卷使用 my-pvc PVC。
当创建 my-pod Pod 时,Kubernetes 会自动扫描所有可用的 PV,并选择一个 PV 来满足 my-pvc PVC 的要求。
如果找到了可用的 PV,则将其绑定到 my-pvc,并将 my-pvc-volume 卷挂载到容器中的 /data 目录。
PVC 是 Kubernetes 中非常有用的资源对象,它允许将应用程序和存储资源的生命周期分开,并在应用程序重新部署或迁移时保留持久存储数据。
通过上面的示例,可以了解如何创建 PVC,并将其用于 Pod。
Kubernetes 中 PVC 和 PV 的设计,实际上类似于“接口”和“实现”的思想。
- 开发者只要知道并会使用“接口”,即:PVC;
- 而运维人员则负责给“接口”绑定具体的实现,即:PV。
这种解耦,就避免了因为向开发者暴露过多的存储系统细节而带来的隐患。
此外,这种职责的分离,往往也意味着出现事故时可以更容易定位问题和明确责任,从而避免“扯皮”现象的出现。
思考一下这个问题:
前面已经了解到,当 Pod 被删除时,与之关联的 PVC 不会被删除,这些 PVC 可以在之后的 Pod 中继续使用。
来看下StatefulSet 怎么做到的:
StatefulSet 的控制器直接管理的是 Pod。
因为,StatefulSet 里的不同 Pod 实例,不像 ReplicaSet 中那样都是完全一样的,而是有了细微区别的。
比如,每个 Pod 的 hostname、名字等都是不同的、携带了编号的。而 StatefulSet 区分这些实例的方式,就是通过在 Pod 的名字里加上事先约定好的编号。
Kubernetes 通过 Headless Service,为这些有编号的 Pod,在 DNS 服务器中生成带有同样编号的 DNS 记录。
只要 StatefulSet 能够保证这些 Pod 名字里的编号不变,那么 Service 里类似于
web-0.nginx.default.svc.cluster.local 这样的 DNS 记录也就不会变,而这条记录解析出来的 Pod 的 IP 地址,则会随着后端 Pod 的删除和再创建而自动更新。这是 Service 机制本身的能力,不需要 StatefulSet 操心。
StatefulSet 还为每一个 Pod 分配并创建一个同样编号的 PVC。
这样,Kubernetes 就可以通过 Persistent Volume 机制为这个 PVC 绑定上对应的 PV,从而保证了每一个 Pod 都拥有一个独立的 Volume。
在这种情况下,即使 Pod 被删除,它所对应的 PVC 和 PV 依然会保留下来。
所以,当这个 Pod 被重新创建出来之后,Kubernetes 会为它找到同样编号的 PVC,挂载这个 PVC 对应的 Volume,从而获取到以前保存在 Volume 里的数据。
apiVersion: apps/v1
kind: StatefulSet #资源类型
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.9.1
ports:
- containerPort: 80
name: web
volumeMounts:
- name: mypvc
mountPath: /usr/share/nginx/html
volumeClaimTemplates: #pvc声明
- metadata:
name: mypvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
在这个yaml中:添加了一个 volumeClaimTemplates 字段。
它跟 Deployment 里 Pod 模板(PodTemplate)的作用类似。凡是被这个 StatefulSet 管理的 Pod,都会声明一个对应的 PVC;
而这个 PVC 的定义,就来自于 volumeClaimTemplates 这个模板字段。更重要的是,这个 PVC 的名字,会被分配一个与这个 Pod 完全一致的编号。
这个自动创建的 PVC,与 PV 绑定成功后,就会进入 Bound 状态,这就意味着这个 Pod 可以挂载并使用这个 PV 了。
使用 kubectl create 创建了 StatefulSet 之后,就会看到 Kubernetes 集群里出现了两个 PVC:
kubectl create -f statefulset.yaml
执行创建命令:
kubectl get pvc -l app=nginx
结果如下:
NAME STATUS VOLUME CAPACITY ACCESSMODES AGE
mypvc-web-0 Bound pvc-15c268c7-b507-11e6-932f-42010a800002 1Gi RWO 48s
mypvc-web-1 Bound pvc-15c79307-b507-11e6-932f-42010a800002 1Gi RWO 48s
前面已讲到过,这个 StatefulSet 创建出来的所有 Pod,都会声明使用编号的 PVC。
可以看到,这些 PVC,都以“<PVC 名字 >-<StatefulSet 名字 >-< 编号 >”的方式命名,并且处于 Bound 状态。
1. 可以看出StatefulSet 其实就是一种特殊的 Deployment,它的特别之处在于,赋予了pod在整个集群里唯一的、可被的访问身份,主要通过它对创建的每个 Pod 都进行了编号。
2. 就是这个编号,给了pod一个唯一的身份,并且,这个编号还会体现在 Pod 的名字和 hostname 等标识信息上,这不仅代表了 Pod 的创建顺序,也是 Pod 的重要网络标识
3. 有了编号后,StatefulSet 就使用 Kubernetes 里的两个标准功能:
- Headless Service
- PV/PVC
实现了对 Pod 的拓扑状态和存储状态的维护。
我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我正在使用ruby1.9解析以下带有MacRoman字符的csv文件#encoding:ISO-8859-1#csv_parse.csvName,main-dialogue"Marceu","Giveittohimóhe,hiswife."我做了以下解析。require'csv'input_string=File.read("../csv_parse.rb").force_encoding("ISO-8859-1").encode("UTF-8")#=>"Name,main-dialogue\r\n\"Marceu\",\"Giveittohim\x97he,hiswife.\"\
这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,
简而言之错误:NOTE:Gem::SourceIndex#add_specisdeprecated,useSpecification.add_spec.Itwillberemovedonorafter2011-11-01.Gem::SourceIndex#add_speccalledfrom/opt/local/lib/ruby/site_ruby/1.8/rubygems/source_index.rb:91./opt/local/lib/ruby/gems/1.8/gems/rails-2.3.8/lib/rails/gem_dependency.rb:275:in`==':und
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
基础版云数据库RDS的产品系列包括基础版、高可用版、集群版、三节点企业版,本文介绍基础版实例的相关信息。RDS基础版实例也称为单机版实例,只有单个数据库节点,计算与存储分离,性价比超高。说明RDS基础版实例只有一个数据库节点,没有备节点作为热备份,因此当该节点意外宕机或者执行重启实例、变更配置、版本升级等任务时,会出现较长时间的不可用。如果业务对数据库的可用性要求较高,不建议使用基础版实例,可选择其他系列(如高可用版),部分基础版实例也支持升级为高可用版。基础版与高可用版的对比拓扑图如下所示。优势 性能由于不提供备节点,主节点不会因为实时的数据库复制而产生额外的性能开销,因此基础版的性能相对于
我正在使用ruby2.1.0我有一个json文件。例如:test.json{"item":[{"apple":1},{"banana":2}]}用YAML.load加载这个文件安全吗?YAML.load(File.read('test.json'))我正在尝试加载一个json或yaml格式的文件。 最佳答案 YAML可以加载JSONYAML.load('{"something":"test","other":4}')=>{"something"=>"test","other"=>4}JSON将无法加载YAML。JSON.load("
我想用Nokogiri解析HTML页面。页面的一部分有一个表,它没有使用任何特定的ID。是否可以提取如下内容:Today,3,455,34Today,1,1300,3664Today,10,100000,3444,Yesterday,3454,5656,3Yesterday,3545,1000,10Yesterday,3411,36223,15来自这个HTML:TodayYesterdayQntySizeLengthLengthSizeQnty345534345456563113003664354510001010100000344434113622315