kubernetes 对象的 yaml 描述语法说明
环境信息
- Centos7 5.4.212-1
- Docker 20.10.18
- containerd.io-1.6.8
- kubectl-1.25.0
- kubeadm-1.25.0
- kubelet-1.25.0
几乎所有的 Kubernetes 对象都包含两个嵌套的对象字段:
spec- 对象的期望状态(desired state)的描述信息status- 对象当前的状态(current state)
Kubernetes 系统的目标就是不停的调整对象的当前状态( current state )直到和期望状态( desired state )匹配。
常用字段说明
必需字段
在想要创建的 Kubernetes 对象所对应的 .yaml 文件中,必须配置的字段如下:[1]
apiVersion- 创建该对象所使用的 Kubernetes API 的版本kind- 想要创建的对象的类别metadata- 帮助唯一标识对象的一些数据,包括一个name字符串、UID和可选的namespacespec- 你所期望的该对象的状态
metadata
帮助唯一标识对象的一些数据,包括一个 name 字符串、 UID 和可选的 namespace
集群中的每一个对象都有一个 名称 ( name )来标识在同类资源中的唯一性。 name 也用来作为 url 中的资源名称 [2]
每个 Kubernetes 对象也有一个 UID ( uid )来标识在整个集群中的唯一性。
apiVersion: apps/v1 |
标签和选择算符
标签(labels) 是附加到 Kubernetes 对象(比如 Pod)上的键值对。 标签旨在用于指定对用户有意义且相关的对象的标识属性,但不直接对核心系统有语义含义。 标签可以用于组织和选择对象的子集。标签可以在创建时附加到对象,随后可以随时添加和修改。 每个对象都可以定义一组键/值标签。每个键对于给定对象必须是唯一的。[3]
通过 标签选择算符 ,客户端/用户可以识别一组对象。 标签选择算符 是 Kubernetes 中的核心分组原语。
对于某些 API 类别(例如
ReplicaSet)而言,两个实例的标签选择算符不得在命名空间内重叠, 否则它们的控制器将互相冲突,无法确定应该存在的副本个数。
比较新的资源,例如 Job 、 Deployment 、 ReplicaSet 和 DaemonSet , 也支持基于集合的需求。
selector: |
matchLabels 是由 {key,value} 对组成的映射。 matchLabels 映射中的单个 {key,value} 等同于 matchExpressions 的元素, 其 key 字段为 key , operator 为 In ,而 values 数组仅包含 value 。 matchExpressions 是 Pod 选择算符需求的列表。 有效的运算符包括 In 、 NotIn 、 Exists 和 DoesNotExist 。 在 In 和 NotIn 的情况下,设置的值必须是非空的。 来自 matchLabels 和 matchExpressions 的所有要求都按 逻辑与 的关系组合到一起 – 它们必须都满足才能匹配 。
字段选择器
字段选择器(Field selectors) 允许你根据一个或多个资源字段的值 筛选 Kubernetes 资源
下面是一些使用字段选择器查询的例子:
metadata.name=my-servicemetadata.namespace!=defaultstatus.phase=Pending
下面这个 kubectl 命令将筛选出 status.phase 字段值为 Running 的所有 Pod:
kubectl get pods --field-selector status.phase=Running |
不同的 Kubernetes 资源类型支持不同的字段选择器。 所有资源类型都支持 metadata.name 和 metadata.namespace 字段。 使用不被支持的字段选择器会产生错误
你可在字段选择器中使用 = 、 == 和 != ( = 和 == 的意义是相同的)操作符。 例如,下面这个 kubectl 命令将筛选所有不属于 default 命名空间的 Kubernetes 服务:
kubectl get services --all-namespaces --field-selector metadata.namespace!=default |
同标签和其他选择器一样, 字段选择器可以通过使用逗号分隔的列表组成一个选择链。 下面这个 kubectl 命令将筛选 status.phase 字段不等于 Running 同时 spec.restartPolicy 字段等于 Always 的所有 Pod:
kubectl get pods --field-selector=status.phase!=Running,spec.restartPolicy=Always |
你能够跨多种资源类型来使用字段选择器。 下面这个 kubectl 命令将筛选出所有不在 default 命名空间中的 StatefulSet 和 Service :
kubectl get statefulsets,services --all-namespaces --field-selector metadata.namespace!=default |
metadata.ownerReferences
在 Kubernetes 中,一些对象是其他对象的 属主(Owner) 。 例如, ReplicaSet 是一组 Pod 的属主。 具有属主的对象是属主的 附属(Dependent) 。[4]
附属对象有一个 metadata.ownerReferences 字段,用于引用其属主对象。 一个有效的属主引用,包含与附属对象同在一个命名空间下的对象名称和一个 UID。 Kubernetes 自动为一些对象的附属资源设置属主引用的值, 这些对象包含 ReplicaSet 、 DaemonSet 、 Deployment 、 Job 、 CronJob 、 ReplicationController 等。
附属对象还有一个 ownerReferences.blockOwnerDeletion 字段,该字段使用布尔值, 用于控制特定的附属对象是否可以阻止垃圾收集删除其属主对象。 如果控制器(例如 Deployment 控制器) 设置了 metadata.ownerReferences 字段的值,Kubernetes 会自动设置 blockOwnerDeletion 的值为 true 。
ownerReferences: |
Pod
apiVersion: v1 |
.spec.containers[*].ports[*].containerPort-Pod暴露的端口.spec.containers[*].ports[*].name-Pod暴露的端口的自定义名称,可在Service的targetPort属性中,Probe 等功能中引用这些名称.spec.restartPolicy- 重启策略,适用于Pod中的所有容器,可取值如下Always- 默认值OnFailureNever
Sidecar Container(使用
initContainers定义的容器) 会忽略 Pod 级别定义的restartPolicy,initContainers定义的容器有其容器级别的restartPolicy,默认也为Always当 Kubelet 使用
restartPolicy重启 Pod 中的容器时,会使用指数级别的时间间隔(10s, 20s,40s, …),5m 封顶.spec.containers[*].args- 定义容器启动后执行的命令,会替换镜像中定义的默认执行程序.spec.nodeSelector- 根据节点标签将Pod调度到指定节点 [13].spec.nodeName: foo-node- 将Pod调度到指定节点。 使用nodeName规则的优先级会高于使用nodeSelector或亲和性与非亲和性的规则,如果所指代的节点不存在,则 Pod 无法运行,而且在某些情况下可能会被自动删除。如果所指代的节点无法提供用来运行 Pod 所需的资源,Pod 会失败, 而其失败原因中会给出是否因为内存或 CPU 不足而造成无法运行。[12].spec.containers[*].env- 创建 Pod 时,可以为其下的容器设置环境变量。通过配置文件的env或者envFrom字段来设置环境变量。 [15].spec.containers[*].volumeMounts- 挂载卷,subPath可用于指定挂载卷(name: html)的子目录到容器路径(mountPath),而不是直接挂载卷目录。.spec.containers[*].resources- 资源限制
容器探针
探针(Probe) 主要用来检测 Pod 的状态,主要有 活跃(Liveness) 、 就绪(Readiness) 和 启动(Startup) 探针 [10]
livenessProbe-kubelet使用 存活探针 来确定什么时候要重启容器,例如,存活探针可以探测到应用死锁(应用程序在运行,但是无法继续执行后面的步骤)情况。 重启这种状态下的容器有助于提高应用的可用性,即使其中存在缺陷。readinessProbe-kubelet使用 就绪探针 可以知道容器何时准备好接受请求流量,当一个Pod内的所有容器都就绪时,才能认为该Pod就绪。 这种信号的一个用途就是控制哪个Pod作为Service的后端。 若Pod尚未就绪,会被从Service的负载均衡器中剔除。startupProbe-kubelet使用 启动探针 来了解应用容器何时启动。 如果配置了这类探针,你就可以控制容器在启动成功后再进行存活性和就绪态检查, 确保这些存活、就绪探针不会影响应用的启动。 启动探针可以用于对慢启动容器进行存活性检测,避免它们在启动运行之前就被杀掉。
Probe 是由 kubelet 对容器执行的定期诊断。 要执行诊断, kubelet 既可以在容器内执行代码,也可以发出一个网络请求。[11]
使用探针来检查容器有四种不同的方法。 每个探针都必须准确定义为这四种机制中的一种:
exec- 在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。grpc- 使用 gRPC 执行一个远程过程调用。 目标应该实现 gRPC 健康检查。 如果响应的状态是 “SERVING”,则认为诊断成功。 gRPC 探针是一个 alpha 特性,只有在你启用了 “GRPCContainerProbe” 特性门控时才能使用。httpGet- 对容器的 IP 地址上指定端口和路径执行 HTTP GET 请求。如果响应的状态码大于等于 200 且小于 400,则诊断被认为是成功的。tcpSocket- 对容器的 IP 地址上的指定端口执行 TCP 检查。如果端口打开,则诊断被认为是成功的。 如果远程系统(容器)在打开连接后立即将其关闭,这算作是健康的
exec方式的探针,因为其实现涉及到对进程的creation/forking,这会导致额外的资源消耗,如果主机上资源紧张,可能会导致探测失败。 [18]
每次探测都将获得以下三种结果之一:
Success(成功) - 容器通过了诊断。Failure(失败) - 容器未通过诊断。Unknown(未知) - 诊断失败,因此不会采取任何行动。
livenessProbe
exec 方式的 livenessProbe
apiVersion: v1 |
.spec.containers[*].args- 容器启动后执行的命令,取代镜像中默认的命令.spec.containers[*].livenessProbe- 配置存活探针exec.command- 配置探测方式为exec以及在容器内执行的命令,如果命令执行成功并且返回值为 0,kubelet就会认为这个容器是健康存活的。 如果这个命令返回非 0 值,kubelet会杀死这个容器并 重新启动 它。periodSeconds- 指定kubelet应该每 5 秒执行一次存活探测,默认是 10 秒。最小值是 1initialDelaySeconds-kubelet在执行第一次探测前等待 5 秒, 默认是 0 秒timeoutSeconds- 探测的超时后等待多少秒。默认值是 1 秒。最小值是 1。successThreshold- 探针在失败后,被视为成功的最小连续成功数。默认值是 1。 存活和启动探测的这个值必须是 1。最小值是 1。failureThreshold- 当探测失败时,Kubernetes 的重试次数。默认值是 3。最小值是 1
httpGet 方式的 livenessProbe
apiVersion: v1 |
.spec.containers[*].livenessProbe- 配置存活探针httpGet.path- 配置存活探针的探测方式为httpGet,并指定 HTTP GET 请求的路径(默认为/)。返回大于或等于 200 并且小于 400 的任何代码都标示成功。其它返回代码都标示失败,失败时kubelet会杀死这个容器并将其重启httpGet.port- 指定 HTTP GET 请求的端口httpGet.httpHeaders- 请求中自定义的 HTTP 头。HTTP 头字段允许重复。host- 连接使用的主机名,默认是Pod的 IP。也可以在 HTTP 头中设置Host来代替scheme- 用于设置连接主机的方式(HTTP 还是 HTTPS)。默认是 “HTTP”
tcpSocket 方式的 livenessProbe
kubelet 会尝试在指定端口和容器建立套接字链接。 如果能建立连接,这个容器就被看作是健康的,如果不能则这个容器就被看作是有问题的。
对于 TCP 探测而言,kubelet 在节点上(不是在 Pod 里面)发起探测连接, 这意味着你不能在 host 参数上配置服务名称,因为 kubelet 不能解析服务名称。
apiVersion: v1 |
.spec.containers[*].livenessProbe- 配置存活探针tcpSocket.port- 配置存活探针的探测方式为tcpSocket,并指定 TCP 探测连接的端口,可以使用命名的端口
Init Containers
Init Containers 是 Pod 中的一个或多个特殊的容器,它会在应用容器 之前启动 , Init Containers 中一般会包含一些工具或者是在应用容器启动之前需要执行的脚本或者初始化事项。 [19]
sidecar container 是会在应用容器启动之前启动,并且会一直持续运行的容器。而 Init Containers 要在 Pod 初始化阶段(应用容器就绪前)结束(completion)。
在 Pod 的 Spec 配置中, Init Containers (使用 initContainers 字段) 处于和应用容器(使用 containers 字段) 同一级。
相比于普通的应用容器, Init Containers 有以下特征:
- 在整个 Pod 就绪前,
Init Containers中的容器都要成功完成(completion) - 每个
init container都必须在另一个init container启动成功之后才能启动 - 如果
init container启动失败,kubelet会一直重启它(restartPolicy是Always或OnFailure),直到成功;如果Init Containers的restartPolicy是Never,并且Init Containers中有容器启动失败,那么 Kubernetes 会判定此 Pod 启动失败。
Init Containers 支持和普通容器一样的配置项,如资源限制、volumes、安全配置等。 但是, init containers 不支持 lifecycle 、 livenessProbe 、 readinessProbe 和 startupProbe 字段 。Init containers 必须在 Pod 准备就绪前成功执行完成(completion)。 sidecar containers 会在 Pod 的生命周期中持续运行,支持探针。
Init Containers 中如果有多个容器, kubelet 会按照顺序依次启动这些容器,前一个容器启动成功,后一个容器才能启动。所有的 init containers 都启动成功并完成后, kubelet 才会初始化应用容器。
Pod 拓扑分布约束
你可以使用 拓扑分布约束(Topology Spread Constraints) 来控制 Pod 在集群内故障域之间的分布, 例如区域(Region)、可用区(Zone)、节点和其他用户自定义拓扑域。 这样做有助于实现高可用并提升资源利用率。[16]
apiVersion: v1 |
maxSkew- 描述 Pod 在 由topologyKey选中的节点组成的区域 中均匀分布的程度(最大偏差)。比如值为 1 表示 任何给定的区域与其他区域之间的 Pod 数量的差异不能超过 1topologyKey- 节点标签的 键 ,如果节点使用此 键 标记并且具有相同的 标签值 , 则将这些节点视为处于同一区中。whenUnsatisfiable- 指示如果 Pod 不满足分布约束时如何处理:DoNotSchedule-(默认)告诉调度器不要调度。ScheduleAnyway- 告诉调度器仍然继续调度,只是根据如何能将偏差最小化来对节点进行排序。
labelSelector- 定这个约束应该应用于哪些 Pod
拓扑域说明
topologyKey 中指定的 键 会用来获取每个 Node 上对应的 值 ,拥有 相同值的 Node 会被视为属于 同一个区域 ,而拥有 指定键( topologyKey ) 的 Node 属于 同一个拓扑域 。
Kubernetes 将会尽量确保 Pods 在这些 拓扑域 (拥有相同 topologyKey 的 Node) 中的 区域 (拥有 相同值的 Node) 上均匀分布。
假设有以下四个 Node,它们分别位于两个不同的可用区(Zone):
Node1:
topology.kubernetes.io/zone=zoneANode2:
topology.kubernetes.io/zone=zoneANode3:
topology.kubernetes.io/zone=zoneBNode4:
topology.kubernetes.io/zone=zoneB
如果你的 topologyKey 设置为 topology.kubernetes.io/zone ,则 Kubernetes 将会认为 Node1 和 Node2 属于(拓扑域 topology.kubernetes.io/zone )的同一个区域, Node3 和 Node4 属于此拓扑域的另一个区域。因此,它会尽量保持这两个区域中的 Pod 数量均衡。
apiVersion: apps/v1 |
在这个例子中,Kubernetes 将会尽量确保 zoneA 和 zoneB 中的 Pod 数量差异不超过 maxSkew(1 ),从而确保这些 Pods 在不同的区域中均匀分布。
Deployment
apiVersion: apps/v1 |
.spec.replicas- Pod 副本的数量,会根据配置产生 附属对象 ReplicaSet.spec.selector- 字段定义了Deployment如何查找要管理的Pod.spec.template- 定义了Pod相关的必要信息,本质上是定义一个Pod对象.metadata.labels- 为容器添加的标签,slector可以使用此标签查找要管理的Pod.spec.containers- 容器相关定义,包含启动的容器名称,使用的镜像,容器暴露的端口等
.spec.strategy- 指定用于用新 Pod 替换旧 Pod 的策略。.spec.strategy.type可以是Recreate或RollingUpdate。RollingUpdate是默认值。[17].spec.strategy.type==Recreate- 如果值为Recreate,在创建新 Pod 之前,所有现有的 Pod 会被杀死.spec.strategy.type==RollingUpdate- Deployment 会在.spec.strategy.type==RollingUpdate时,采取 滚动更新的方式更新 Pod。你可以指定maxUnavailable和maxSurge来控制滚动更新 过程。.spec.strategy.rollingUpdate.maxUnavailable- 是一个可选字段,用来指定 更新过程中不可用的 Pod 的个数上限,默认值为 25%。如果.spec.strategy.rollingUpdate.maxSurge为 0,则此值不能为 0.spec.strategy.rollingUpdate.maxSurge- 是一个可选字段,用来指定可以创建的超出期望 Pod 个数的 Pod 数量, 如果MaxUnavailable为 0,则此值不能为 0,此字段的默认值为 25%
Service
将运行在一组 Pods 上的应用程序公开为网络服务的抽象方法。主要为后端的一组 POD (通过选择算符选定)提供 Cluster-IP 和负载均衡(默认轮询)及高可用(只有就绪的 POD 才会被对外公布,未就绪的 POD 不会对外发布)。 [5]
有选择算符的 Service
Service 所针对的 Pod 集合通常是通过 选择算符 来确定的
apiVersion: v1 |
.spec.selector- 根据 选择算符 选择后端的POD.spec.ports[*].name- 对于某些服务,可能需要公开多个端口。 Kubernetes 允许在Service对象上配置多个端口定义。 为服务使用多个端口时,必须提供所有端口名称,以使它们无歧义 。.spec.ports[*].protocol-Service监听的端口协议,默认为 TCP.spec.ports[*].port-Service监听的端口.spec.ports[*].targetPort- 后端POD监听的端口,不指定的情况(默认)下,targetPort将被设置为与port字段相同的值。.spec.sessionAffinity- 要确保每次都将来自特定客户端的连接传递到同一Pod,可以设置为ClientIP(默认为None) 来基于客户端的 IP 地址选择会话亲和性。还可以通过适当设置.spec.sessionAffinityConfig.clientIP.timeoutSeconds来设置最大会话停留时间。(默认值为 10800 秒,即 3 小时).spec.ipFamilies- 定义分配 ip 版本(IPv4,IPv6)的顺序,此字段是不可变的,因为系统无法为已经存在的服务重新分配.spec.ClusterIP。如果你想改变.spec.ipFamilies,则需要删除并重新创建服务。可以配置为以下值:IPv4IPv6"IPv4","IPv6""IPv6","IPv4"
.spec.ipFamilyPolicy- IP 地址族策略。[7]SingleStack- 默认值。单栈服务。控制面使用第一个配置的服务集群 IP 范围为服务分配集群 IPPreferDualStack- 为服务分配 IPv4 和 IPv6 集群 IP 地址RequireDualStack- 从基于在.spec.ipFamilies数组中第一个元素的地址族的.spec.ClusterIPs列表中选择.spec.ClusterIP
.spec.clusterIPs- IP 的主要字段,值根据ipFamilies,ipFamilyPolicy的配置计算而出,规则参考.spec.clusterIP- IP 的次要字段,其取值从.spec.ClusterIPs计算而来。也可以通过此字段配置自定义的 IP 地址 [9].spec.type- 指定Service的类型,默认为ClusterIP,可选值如下[8]:ClusterIP- 通过集群的内部 IP 暴露服务,选择该值时服务只能够在集群内部访问。 这也是默认值。NodePort- 通过每个节点上的 IP 和静态端口(NodePort,默认范围30000-32767)暴露服务。NodePort服务会路由到自动创建的ClusterIP服务,此种类型,服务可通过节点 ip 和NodePort(nodeIP:.spec.ports[*].nodePort)对外访问,也可以通过.spec.clusterIP:.spec.ports[*].port对外可见。 1.24 及以后版本,nodePort对应的端口不会在节点上监听LoadBalancer- 使用云提供商的负载均衡器向外部暴露服务。 外部负载均衡器可以将流量路由到自动创建的NodePort服务和ClusterIP服务上。ExternalName- 通过返回CNAME和对应值,可以将服务映射到externalName字段的内容(例如,foo.bar.example.com)。 无需创建任何类型代理。
.spec.externalTrafficPolicy- 控制来自于外部的流量是如何路由的, 可选值有Cluster和LocalCluster- 将外部流量路由到所有就绪的端点Local- 只路由到当前节点上就绪的端点,如果当前节点上没有就绪的端点,kube-proxy不会转发请求相关服务的任何流量
.spec.internalTrafficPolicy- 控制内部来源的流量是如何转发的,可选值有Cluster和Local
Kubernetes 为该服务分配一个 IP 地址(有时称为 “集群 IP”),该 IP 地址由服务代理使用。
Pod 中的端口定义是有名字的,你可以在 Service 的 targetPort 属性中引用这些名称。 例如,我们可以通过以下方式将 Service 的 targetPort 绑定到 Pod 端口:
apiVersion: v1 |
没有选择算符的 Service
由于选择算符的存在,服务最常见的用法是为 Kubernetes Pod 的访问提供抽象, 但是当与相应的 Endpoints 对象一起使用且没有选择算符时, 服务也可以为其他类型的后端提供抽象,包括在集群外运行的后端 [6]
定义没有选择算符的 Service 实例:
apiVersion: v1 |
由于此服务没有选择算符,因此不会自动创建相应的 Endpoints 对象。 你可以通过手动添加 Endpoints 对象,将服务手动映射到运行该服务的网络地址和端口:
apiVersion: v1 |
当你为某个 Service 创建一个 Endpoints 对象时,你要将新对象的名称设置为与 Service 的名称相同。
说明 :
端点 IPs 必须不可以 是:本地回路(IPv4 的 127.0.0.0/8, IPv6 的 ::1/128) 或本地链接(IPv4 的 169.254.0.0/16 和 224.0.0.0/24,IPv6 的 fe80::/64)。
端点 IP 地址不能是其他 Kubernetes 服务的集群 IP,因为 kube-proxy 不支持将虚拟 IP 作为目标。
无头服务(Headless Services)
有时不需要或不想要负载均衡,以及单独的 Service IP。 遇到这种情况,可以通过指定 Cluster IP( spec.clusterIP )的值为 None 来创建 Headless Service 。[14]
创建 Headless Services
apiVersion: v1 |
使用此配置创建的 Headless Services ,系统不会为其分配 CLUSTER-IP 。
当通过此服务的 FQDN kubia-headless.default.svc.cluster.local 解析时,系统会返回此服务 选择算符 .spec.selector 选择的 就绪 的后端 POD 的 IP。
如果配置的是 不带选择算符的服务,解析规则如是,如果查找到了和 Service 的 name 一样的 endpoint ,则解析到此 endpoint 。
Ingress
Ingress 可为 Service 提供外部可访问的 URL、负载均衡流量、终止 SSL/TLS,以及基于名称的虚拟托管。
Ingress 不会公开任意端口或协议 。 将 HTTP 和 HTTPS 以外的服务公开到 Internet 时,通常使用 Service.Type=NodePort 或 Service.Type=LoadBalancer 类型的 Service 。
你必须拥有一个 Ingress 控制器 才能满足 Ingress 的要求。 仅创建 Ingress 资源本身没有任何效果。
安装 ingress-nginx controller
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.3.1/deploy/static/provider/cloud/deploy.yaml |
编辑 ingress-nginx 的 Deployment 配置文件,在 Deployment 中的 .spec.template.spec 下添加字段 hostNetwork: true ,以使 ingress-nginx-controller 可以使用节点的主机网络提供对外访问
创建 Ingress 对象
apiVersion: networking.k8s.io/v1 |
配置完成后,查看 Ingress 资源
kubectl get ingress -o wide |
将域名解析到 ingress-nginx-controller 所在节点的 IP,即可在外部访问服务。
为了将 ingress-nginx-controller 固定启动在边缘节点,可以使用 DaemonSet 替代 Deployment 。
Ingress Controller不会将请求转发给Service,只通过Service获取到Endpoints,从而决定将请求转发到哪个 Pod。从流量的流经路径看,流量是直接从Ingress Controller发送到了 Pod
脚注
- 1.必需字段 ↩
- 2.对象名称和 IDs ↩
- 3.标签和选择算符 ↩
- 4.属主与附属 ↩
- 5.服务(Service) ↩
- 6.没有选择算符的 Service ↩
- 7.配置 IPv4/IPv6 双协议栈 ↩
- 8.NodePort 类型 ↩
- 9.选择自己的 IP 地址 ↩
- 10.配置存活、就绪和启动探针 ↩
- 11.容器探针 ↩
- 12.nodeName ↩
- 13.将 Pod 指派给节点 ↩
- 14.无头服务(Headless Services) ↩
- 15.为容器设置环境变量 ↩
- 16.Pod 拓扑分布约束 ↩
- 17.策略 ↩
- 18.Container probes ↩
- 19.Init Containers ↩