8月XNUMX日 会议
按照传统,我们很高兴向您展示
K8s 中的核心和附加功能
Kubernetes 正在改变行业和早已建立的管理方法:
- 感谢他 抽象,我们不再使用设置配置或运行命令(Chef、Ansible...)等概念进行操作,而是使用容器、服务等分组。
- 我们可以在不考虑细微差别的情况下准备申请 具体站点,它将在其上启动:裸机、提供商之一的云等。
- 有了 K8s,您变得前所未有的方便 最佳实践 关于组织基础设施:扩展技术、自我修复、容错等。
然而,当然,一切并不是那么顺利:Kubernetes也带来了自己的新挑战。
Kubernetes 没有 是一个解决所有用户所有问题的组合。 核心 Kubernetes 只负责一组最低限度的必要功能,这些功能存在于 每 簇:
Kubernetes 核心定义了一组基本原语,用于对容器进行分组、管理流量等。 我们在中更详细地讨论了它们
另一方面,K8s 提供了扩展可用功能的绝佳机会,这有助于关闭其他功能 - 具体的 ——用户需求。 Kubernetes 的添加是集群管理员的责任,他们必须安装和配置一切必要的东西,以使集群“处于正确的状态”[以解决他们的特定问题]。 这些都是什么样的补充呢? 让我们看一些例子。
附加组件示例
安装 Kubernetes 后,我们可能会感到惊讶,节点内和节点之间的 Pod 交互所必需的网络无法自行运行。 Kubernetes 内核不保证必要的连接;相反,它决定网络 接口 (
一个很接近的例子是数据存储解决方案(本地磁盘、网络块设备、Ceph...)。 最初它们位于核心,但随着出现
其他示例包括:
- 入口-控制器 (请参阅他们的评论
我们最近的文章 ). -
证书经理 : -
运营商 是一整类附加组件(其中包括提到的证书管理器),它们定义原语和控制器。 他们的工作逻辑仅受我们想象力的限制,并允许我们将现成的基础设施组件(例如 DBMS)转换为原语,这比使用一组容器及其设置更容易使用。 已经编写了大量的运算符 - 即使其中许多尚未准备好用于生产,但这只是时间问题: - 指标 - Kubernetes 如何将接口(Metrics API)与实现(第三方附加组件,如 Prometheus 适配器、Datadog 集群代理...)分离的另一个例子。
- 为 监测与统计,在实践中不仅需要
普罗米修斯和格拉法纳 ,还有 kube-state-metrics、node-exporter 等。
这不是完整的添加列表...例如,在 Flant 公司,我们目前安装 29 个补充 (所有这些总共创建了 249 个 Kubernetes 对象)。 简而言之,如果没有添加,我们就无法看到集群的生命周期。
自动化
Operator 旨在自动化我们每天遇到的日常操作。 以下是现实生活中的示例,编写运算符将是一个很好的解决方案:
- 有一个私有(即需要登录)注册表,其中包含应用程序的图像。 假设每个 pod 都分配有一个特殊的秘密,允许在注册表中进行身份验证。 我们的任务是确保在命名空间中找到这个秘密,以便 Pod 可以下载图像。 可能有很多应用程序(每个应用程序都需要一个秘密),并且定期更新秘密本身很有用,因此消除了手动布置秘密的选项。 这就是操作员发挥作用的地方:我们创建一个控制器,它将等待命名空间出现,并根据此事件向命名空间添加一个秘密。
- 默认情况下,禁止从 pod 访问互联网。 但有时可能需要:访问权限机制简单地工作是合乎逻辑的,不需要特定的技能,例如,通过命名空间中存在某个标签。 运营商可以如何帮助我们? 创建一个控制器,等待标签出现在命名空间中,并添加适当的 Internet 访问策略。
- 类似的情况:假设我们需要添加某个
污点 ,如果它有类似的标签(带有某种前缀)。 操作员的动作是显而易见的......
在任何集群中,必须解决日常任务,并且 正确地 这可以使用运算符来完成。
总结所有描述的故事,我们得出的结论是 为了在 Kubernetes 中舒适地工作,您需要: 但) 安装附加组件, b) 发展经营者 (用于解决日常管理任务)。
如何为 Kubernetes 编写声明?
一般来说,该方案很简单:
...但事实证明:
- Kubernetes API 是一个相当重要的东西,需要花费大量时间才能掌握;
- 编程也不适合所有人(选择 Go 语言作为首选语言是因为它有一个特殊的框架 -
运营商SDK ); - 框架本身的情况类似。
底线: 编写一个控制器 (操作员)必须 花费大量资源 研究材料。 这对于“大型”运营商来说是合理的——例如,对于 MySQL DBMS。 但是,如果我们还记得上面描述的示例(揭露秘密、将 Pod 访问互联网......),我们也希望正确执行这些示例,那么我们就会明白,所付出的努力将超过我们现在需要的结果:
一般来说,会出现一个两难的困境:花费大量资源并找到合适的工具来编写语句,或者以老式的方式(但速度很快)进行编写。 为了解决这个问题 - 在这些极端之间找到折衷方案 - 我们创建了自己的项目:
Shell 操作符
他如何工作? 该集群有一个 pod,其中包含带有 shell 操作符的 Go 二进制文件。 他旁边有一套 钩子 (有关它们的更多详细信息 - 见下文)。 shell 操作符本身订阅了某些 发展 在 Kubernetes API 中,一旦发生就会启动相应的钩子。
shell 操作符如何知道针对哪些事件调用哪些钩子? 这些信息由钩子本身传输到 shell 操作符,而且它们做得非常简单。
钩子是 Bash 脚本或任何其他接受单个参数的可执行文件 --config
并以 JSON 进行响应。 后者确定它感兴趣的对象以及应该响应哪些事件(对于这些对象):
我将说明我们示例之一的 shell 运算符的实现 - 分解用于使用应用程序映像访问私有注册表的秘密。 它由两个阶段组成。
练习:1.写一个hook
首先,在hook中我们将处理 --config
,表明我们对命名空间感兴趣,特别是它们的创建时刻:
[[ $1 == "--config" ]] ; then
cat << EOF
{
"onKubernetesEvent": [
{
"kind": "namespace",
"event": ["add"]
}
]
}
EOF
…
逻辑会是什么样的? 也很简单:
…
else
createdNamespace=$(jq -r '.[0].resourceName' $BINDING_CONTEXT_PATH)
kubectl create -n ${createdNamespace} -f - << EOF
Kind: Secret
...
EOF
fi
第一步是找出创建了哪个命名空间,第二步是使用以下命令创建它 kubectl
此名称空间的秘密。
练习:2. 组装图像
剩下的就是将创建的钩子传递给 shell 操作符 - 如何做到这一点? shell-operator 本身是一个 Docker 镜像,所以我们的任务是将钩子添加到该镜像中的一个特殊目录中:
FROM flant/shell-operator:v1.0.0-beta.1
ADD my-handler.sh /hooks
剩下的就是组装它并推动它:
$ docker build -t registry.example.com/my-operator:v1 .
$ docker push registry.example.com/my-operator:v1
最后一步是将映像部署到集群。 为此,我们要写 部署:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-operator
spec:
template:
spec:
containers:
- name: my-operator
image: registry.example.com/my-operator:v1 # 1
serviceAccountName: my-operator # 2
有两点需要注意:
- 新创建的图像的指示;
- 这是一个系统组件(至少)需要订阅 Kubernetes 中的事件并向命名空间分配机密的权限,因此我们为该钩子创建一个 ServiceAccount(和一组规则)。
结果——我们解决了问题 给亲戚 对于 Kubernetes,以创建分解秘密的操作符的方式。
其他 shell 操作符功能
要限制钩子将使用的所选类型的对象, 它们可以被过滤,根据某些标签进行选择(或使用 matchExpressions
):
"onKubernetesEvent": [
{
"selector": {
"matchLabels": {
"foo": "bar",
},
"matchExpressions": [
{
"key": "allow",
"operation": "In",
"values": ["wan", "warehouse"],
},
],
}
…
}
]
假如 去重机制,它 - 使用 jq 过滤器 - 允许您将大型 JSON 对象转换为小型对象,其中仅保留那些我们想要监视更改的参数。
当调用钩子时,shell 操作符会传递它 对象数据,可用于任何需要。
触发钩子的事件不限于 Kubernetes 事件:shell-operator 提供支持 按时间调用钩子 (类似于传统调度程序中的 crontab),以及特殊事件 启动时。 所有这些事件都可以组合并分配给同一个钩子。
shell 运算符的另外两个功能:
- 它的作品 异步地。 由于接收到 Kubernetes 事件(例如正在创建的对象),集群中可能会发生其他事件(例如正在删除同一对象),并且钩子需要考虑到这一点。 如果钩子执行时出错,那么默认情况下它将是 记起 直到成功完成(可以更改此行为)。
- 它出口 指标 对于 Prometheus,您可以通过它了解 shell 操作符是否正常工作,找出每个钩子的错误数量和当前队列大小。
总结一下报告的这一部分:
附加组件安装
为了舒适地使用 Kubernetes,还提到需要安装附加组件。 我将用我们公司现在的做法为例来向您介绍这一点。
我们开始使用具有多个集群的 Kubernetes,唯一添加的是 Ingress。 它需要在每个集群中进行不同的安装,我们为不同的环境做了几种YAML配置:裸机、AWS……
由于集群越多,配置也就越多。 此外,我们还改进了这些配置本身,因此它们变得非常异构:
为了让一切井井有条,我们从一个脚本开始(install-ingress.sh
),它将我们将部署到的集群类型作为参数,生成必要的 YAML 配置并将其推广到 Kubernetes。
简而言之,我们的进一步路径以及与之相关的推理如下:
- 要使用 YAML 配置,需要一个模板引擎(在第一阶段,这是简单的 sed);
- 随着集群数量的增加,自动更新的需求来了(最早的解决方案是将脚本放在Git中,使用cron更新并运行);
- Prometheus 需要类似的脚本(
install-prometheus.sh
),然而,值得注意的是,它需要更多的输入数据及其存储(以一种好的方式 - 集中式和集群中),并且可以自动生成一些数据(密码): - 向越来越多的集群推出错误的风险不断增加,因此我们意识到安装程序 (即两个脚本:Ingress 和 Prometheus) 需要暂存(Git 中的多个分支,几个 cron 来在相应的稳定或测试集群中更新它们);
- с
kubectl apply
它变得很难使用,因为它不是声明性的,只能创建对象,但不能决定它们的状态/删除它们; - 我们缺少一些当时根本没有实现的功能:
- 完全控制集群更新的结果,
- 根据可以从集群获取的数据(发现)自动确定一些参数(安装脚本的输入),
- 它以不断发现的形式逻辑发展。
我们在其他项目的框架内实施了所有这些积累的经验 -
附加操作符
它基于已经提到的 shell 运算符。 整个系统如下所示:
以下内容被添加到 shell-operator 挂钩中:
- 值存储,
- 舵图,
- 组件 监控值存储 并且 - 如果发生任何变化 - 要求 Helm 重新滚动图表。
因此,我们可以对 Kubernetes 中的事件做出反应,启动一个钩子,通过这个钩子我们可以对存储进行更改,之后图表将被重新下载。 在结果图中,我们将一组钩子和图表分离成一个组件,我们称之为 模组:
可以有很多模块,我们向它们添加全局钩子、全局值存储以及监视该全局存储的组件。
现在,当 Kubernetes 中发生某些情况时,我们可以使用全局钩子对其做出反应并更改全局存储中的某些内容。 此更改将被注意到,并将导致集群中的所有模块被推出:
该方案满足安装上述附加组件的所有要求:
- Helm 负责模板化和声明性。
- 自动更新的问题是使用全局钩子解决的,该钩子按计划进入注册表,如果在那里看到新的系统映像,则将其推出(即“自身”)。
- 在集群中存储设置是通过使用 配置映射,其中包含存储的主要数据(在启动时它们被加载到存储中)。
- 使用钩子解决了密码生成、发现和持续发现的问题。
- 分段是通过标签实现的,Docker 开箱即用地支持标签。
- 使用指标来监控结果,通过这些指标我们可以了解状态。
整个系统在 Go 中以单个二进制文件的形式实现,称为 addon-operator。 这使得图表看起来更简单:
该图中的主要组件是一组模块 (下面以灰色突出显示)。 现在,我们可以花一点力气为所需的附加组件编写一个模块,并确保它将安装在每个集群中,将被更新并响应集群中所需的事件。
“植物”用途
我在哪里可以获得 addon-operator 的模块? 发布我们的库是我们的下一阶段;我们计划在夏天进行。
视频和幻灯片
表演视频(约 50 分钟):
报告介绍:
PS
我们博客上的其他报道:
- «
数据库和 Kubernetes “; (Dmitry Stolyarov;8 年 2018 月 XNUMX 日,HighLoad++); - «
监控和 Kubernetes “; (德米特里·斯托利亚罗夫;28 年 2018 月 XNUMX 日在 RootConf); - «
Kubernetes 和 GitLab 的 CI/CD 最佳实践 “; (Dmitry Stolyarov;7 年 2017 月 XNUMX 日,HighLoad++); - «
我们在小型项目中使用 Kubernetes 的经验 “; (德米特里·斯托利亚罗夫;6 年 2017 月 XNUMX 日,RootConf).
您可能还对以下出版物感兴趣:
来源: habr.com