这篇文章已超过一年。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已变得不正确。
每周 Kubernetes 社区聚会记录 - 2015年4月10日
每周,Kubernetes 贡献社区都会通过 Google Hangouts 进行虚拟会议。我们希望任何有兴趣的人都能了解这个论坛中讨论的内容。
议程
- kubectl 工具、滚动更新、部署、命令式命令。
- 向下 API / env. 替换,以及可能的前提条件/依赖关系。
会议记录
1. kubectl 改进
使其更易于使用,完成滚动更新,更高层次的部署概念。
滚动更新
今天
可以通过文件指定的另一个 rc 替换一个 rc。
没有对回滚的明确支持,可以通过对旧版本进行滚动更新来实现。
我们在 rcs 上保留注释以跟踪所需的实例数;对于回滚情况无效,因为不对称。
需要不可变的镜像 ID;当前没有与镜像、版本对应的 UUID,因此如果有人在其上推送,您将重新拉取它;在 API 服务器中,我们应该将镜像转换为 UUID(尽可能接近边缘)。
如果自动生成新的 rc 而不是让用户更新它(例如,当更改容器的镜像标签等时;当前需要更改 rc 名称和标签值;可以自动化生成新的 rc)。
将 rcs 视为宠物而不是牲畜。
“将我从 v1 滚动到 v2”(或从 v2 滚动到 v1) - 对大多数人来说足够了。不关心过去发生的事情的记录。
我们正在提供 ansible 可以调用的模块来完成某些事情。
如何跟踪多个模板;今天我们使用多个 RC。
如果我们有一个部署控制器;部署配置会产生一个运行滚动更新的 pos;触发器是镜像存储库的基于级别的更新。
替代的短期建议:创建一个新的 rc 作为旧的克隆,修改计数,使新的 rc 成为旧的 rc,反之亦然,将之前命名的 rc(宠物)降至零,然后使用新模板重新启动它(这与 Borg 如何进行作业更新非常相似)。
- 如果我们无论如何都想进行部署,这是否值得?是的,因为我们已经有很多概念;需要简化。
部署控制器会跟踪多个模板,这是滚动更新和金丝雀发布所需要的。
新事物的唯一原因是将进程移动到服务器而不是客户端?
可能不需要将其作为 API 对象;应该提供一种体验,使其不是 API 对象,而只是客户端的东西。
现在需要一种体验,因此需要在客户端完成,因为对象不会在 1.0 之前落地。
为只想与 RC 交互的人提供简化的体验。
回滚如何工作:ctrl-c,回滚 v2 v1。回滚模式可以在人的脑海中。两种回滚:我处于稳定状态并想返回,并且我进行了金丝雀部署并按下了 ctrl-c,我如何摆脱金丝雀部署(例如,新的部署失败)。ctrl-c 可能不起作用。删除金丝雀控制器及其 Pod。希望有一个命令也可以删除 Pod(有 -- kbectl stop)。不重复使用名称的理由:当您前进时,您可以停止新事物,您没问题,但是如果您替换旧事物并且您创建了一个副本,如果您按下 ctrl-c,您没有任何可以停止的东西。但是您可以等到最后再翻转名称,使用命名约定以便弄清楚发生了什么,等等。
两种不同的体验:(1)我正在使用版本控制,有上周的历史记录,本周滚动更新了两个文件 -> 创建 v2,??? v1,没有宠物 - 进入了版本控制的世界,在那里拥有累积的历史记录;(1)命令式 kubectl v1 v2,其中系统处理细节,这就是我们使用快照模式的地方。
其他命令式命令
run-container(或只是 run):命令行上的 spec 命令,使其更类似于 docker run;但不是多容器 Pod。
--forever vs. not(通过简单命令的一次性执行)。
希望它是交互式的 - run -it 并在集群中运行,但您有与进程的交互式终端。
命令行参数如何工作。可以说 --image 多次。cobra 会支持吗?在 openshift 中,我们有用于将参数分组在一起的巧妙语法。不适用于真正的结构化参数。
替代方案:创建 Pod;添加容器,添加容器 ...;运行 pod -- 构建并且在 'run pod' 之前不运行对象。
-- 用于分隔容器参数。
创建一个 Pod,在运行它之前对其进行修改 - 类似于初始化器模式。
类型发现
如果我们有 run,有时它会创建一个 rc,有时不会,如果用户想删除使用 run 创建的任何内容,他们如何知道要删除什么。
bburns 提出了一个建议,如果您执行 stop、delete 之类的命令,则不指定类型;让 kubectl 弄清楚。
替代方案:允许您定义从名称到资源类型的别名,例如,删除所有将遵循该别名(所有可能意味着某个命名空间中的所有内容,或者未限定范围等)- 有人明确地向集合中添加了一些内容,而不是意外地像节点一样出现。
希望看到扩展允许工具指定自己的别名(不仅仅是用户);例如,resize 可以说我可以处理 RC,delete 可以说我可以处理所有内容,等等,因此我们可以自动执行这些操作而无需用户指定内容。但正确的机制。
resourcebuilder 的概念是根据我们在目标命令中的适用方式来执行那种扩展。例如,如果您想向 Pod 和 rc 添加卷,则需要一些东西来查找 Pod 模板并进行更改。这里有搜索部分(删除 nginx -> 您必须弄清楚它们指的是哪个对象),然后命令可以说我得到了一个 Pod,我知道如何处理 Pod。
替代启发式:如果所有命令的默认目标是部署,会怎么样。kubectl run -> 部署。工作量太大,更容易清理现有的 CLI。为之敞开大门。宏对象可以,但要做更多工作才能使其正常工作。最终将需要索引来提高效率。可以更多地依赖 swagger 来告诉我们类型。
2. paul/向下 API:env 替换
- 创建像字符串这样的临时环境变量,例如 k8s_pod_name,系统会在对象中对其进行替换。
- 允许人们创建引用 k8s 对象字段的环境变量,而无需从其容器内部查询 API;在某些情况下,可以从其容器中查询 API(例如,传递对象名称、命名空间);例如,边车容器需要它才能从 API 服务器拉取内容。
- 另一个类似的建议:不要使用像名称这样的环境变量,而是使用类似 JSON 路径的语法来引用对象字段名称;例如,$.metadata.name 来引用当前对象的名称,可能有一些语法来引用相关对象,例如 Pod 所在的节点。类似 JSON 路径的语法的优点是它不那么临时。缺点是您只能引用对象的字段。
- 对于两者,如果您填充环境变量,则会存在一个缺点,即仅在创建容器时才设置字段。但耦合度最低 - 开箱即用的容器,容器无需知道如何与 k8s API 对话。将 k8s 概念保留在控制平面中。
- 我们正在向类似 JSON 路径的方法收敛。但是需要原型或至少更深入的提案来演示。
- paul:一种变体是,对于环境变量,除了值字段之外,还有不同的来源,您可以插入例如您用来描述对象字段的语法;另一个来源将是描述主机信息的来源。有部分原型。图像中的内容与控制平面中的内容之间有清晰的分离。可以为卷插件使用来源概念。
- 用例:为边车容器提供联系 API 服务器的信息。
- 用例:传递唯一标识符,例如使用 UID 作为唯一标识符。
- clayton:对于每个 Pod 都可用的 rocket 或 gce 元数据服务,以便进行更复杂的操作;大多数容器都希望找到服务的端点。
3. 前置条件/依赖关系
- 当您创建与服务通信的 Pod 时,只有在您以正确的顺序创建对象时,服务环境变量才会填充。如果您使用 DNS,问题就没那么严重,但有些应用程序很脆弱。如果它们依赖的服务不存在,可能会崩溃,可能需要很长时间才能重启。提案是设置前置条件,阻止 Pod 启动,直到它们依赖的对象存在。
- 如果我们要求人们声明他们想要哪些环境变量,或者在 Pod、RC 或对象级别设置依赖机制,以声明此对象在另一个对象存在之前不会激活,则可以自动推断。
- 可以使用事件钩子吗?只有应用所有者知道他们的依赖关系或服务何时准备好提供服务。
- 一种提案是使用 pre-start 钩子。另一种是前置条件探针 - pre-start 钩子可以执行探针。当我访问此服务地址或 IP 时,是否有任何响应,如果没响应则探针失败。可以在 pre-start 钩子中实现。比 post-start 更有用。是 rkt 规范的一部分。有 0、1、2 阶段。今天在 Docker 中很难实现,在 Rocket 中很容易实现。
- 容器中的 pre-start 钩子:如果使用 prestart 钩子实现,容器可能会锁定直到满足某些任意条件,这将如何影响就绪探针。 如果您有钩子,则在 kubelet 运行就绪/存活探针时必须进行一些补偿。 Systemd 在进程生命周期的各个阶段都有超时设置。
- 如果我们采用容器 pre-start 的黑盒模型,这是有意义的;如果容器规范变得更像 systemd 那样对进程模型进行描述,那么 kubelet 是否需要更多地了解进程模型才能做出正确的操作。
- 理想情况下,容器内部发送消息,表明我已完成所有 pre-start 操作。 systemd 的 sdnotify 可以做到这一点。 你告诉 systemd 你完成了,它会通知其他依赖项你已经存活。
- 但是...有人可以直接在他们的容器内实现前置条件。这样可以更容易地调整应用程序,而无需更改其镜像。另一种选择是制定他们自己实现它的模式,但我们不为他们做。