这篇文章发布已超过一年。较早的文章可能包含过时的内容。请检查页面信息自发布以来是否仍然正确。
使用 Kubernetes Pet Set 运行一千个 Cassandra 实例
编者注:本文是一系列关于 Kubernetes 1.3 新特性的深度文章之一
举办希腊神兽赛跑
为了庆祝Kubernetes 1.3 发布,我们想对新的 Pet Set 进行全面测试。通过测试一千个 Cassandra 实例,我们可以确保 Kubernetes 1.3 已准备好用于生产环境。请继续阅读,了解我们如何将 Cassandra 适配到 Kubernetes,并进行了我们有史以来最大规模的部署。
如今,将容器与基本有状态应用结合使用相当简单。使用持久卷,你可以在 Pod 中挂载磁盘,并确保数据在 Pod 生命周期结束后仍然存在。然而,部署分布式有状态应用可能会变得更复杂。借助 Kubernetes 1.3,新的Pet Set 组件让一切变得容易得多。为了大规模测试这个新特性,我们决定举办希腊神兽赛跑!我们在多个可用区进行了数十万场比赛,参赛者包括半人马和其他古希腊神兽。
正如你们许多人所知,Kubernetes 源自古希腊语:κυβερνήτης。这意味着舵手、飞行员、掌舵人或船长。所以为了跟踪比赛结果,我们需要一个数据存储,我们选择了 Cassandra。Κασσάνδρα,Cassandra 是特洛伊国王普里阿摩斯和赫卡柏王后的女儿。考虑到多次引用古希腊语,我们认为举办古希腊神兽赛跑会很合适。
故事从这里开始有点跑偏,因为 Cassandra 本身也是这些 Pet。请继续阅读,我们将进行解释。
Kubernetes 1.3 中一项令人兴奋的新特性是 Pet Set。为了组织 Kubernetes 内部容器的部署,有不同的部署机制可用。这些组件的示例包括 Resource Controller 和 Daemon Set。Pet Sets 是一项新特性,提供了在 Kubernetes 内部将容器作为 Pet 进行部署的能力。Pet Sets 为 Pet / Pod 部署的各个方面提供身份保证:DNS 名称、一致的存储和有序的 Pod 索引。以前,使用 Deployment 和 Replication Controller 等组件只能部署具有弱耦合身份的应用。弱身份非常适合管理微服务等应用,在微服务中,服务发现很重要,应用是无状态的,并且单个 Pod 的命名无关紧要。许多软件应用确实需要强身份,包括许多不同类型的分布式有状态系统。Cassandra 是需要一致网络身份和稳定存储的分布式应用的绝佳示例。
Pet Sets 提供以下功能
- 稳定的主机名,可在 DNS 中供其他资源使用。编号基于 Pet Set 名称,从零开始。例如 cassandra-0。
- Pet 的序号索引。0、1、2、3 等。
- 与 Pet 的序号和主机名关联的稳定存储。
- 可通过 DNS 进行对等发现。对于 Cassandra,对等节点的名称在 Pet 创建之前就已知。
- 启动和销毁顺序。已知下一个要创建的带编号 Pet 是哪个,以及在减小 Pet Set 大小时哪个 Pet 将被销毁。此特性对于在减小集群大小时从 Pet 排除数据等管理任务非常有用。
如果你的应用有一个或多个这些要求,那么它可能是 Pet Set 的候选者。
一个相关的类比是,Pet Set 由宠物狗组成。如果你有一只白色的、棕色的或黑色的狗,而棕色的狗跑丢了,你可以用另一只棕色的狗代替,没人会注意到。如果随着时间的推移,你一直只用白色的狗代替,那么就会有人注意到。Pet Set 允许你的应用保持你的 Pet 的唯一身份或毛色。
Pet Set 的示例工作负载
- 集群软件,如 Cassandra、Zookeeper、etcd 或 Elastic 需要稳定的成员身份。
- 数据库,如 MySQL 或 PostgreSQL,随时需要连接到持久卷的单个实例。
仅当你的应用需要这些属性中的部分或全部时,才使用 Pet Set。将 Pod 作为无状态副本进行管理要容易得多。
回到我们的比赛!
正如我们所提到的,Cassandra 是通过 Pet Set 部署的完美候选者。Pet Set 很像一个Replication Controller,但有一些新的额外功能。这里有一个 YAML 清单示例
用于提供 DNS 查找的 Headless Service
apiVersion: v1
kind: Service
metadata:
labels:
app: cassandra
name: cassandra
spec:
clusterIP: None
ports:
- port: 9042
selector:
app: cassandra-data
----
# new API name
apiVersion: "apps/v1alpha1"
kind: PetSet
metadata:
name: cassandra
spec:
serviceName: cassandra
# replicas are the same as used by Replication Controllers
# except pets are deployed in order 0, 1, 2, 3, etc
replicas: 5
template:
metadata:
annotations:
pod.alpha.kubernetes.io/initialized: "true"
labels:
app: cassandra-data
spec:
# just as other component in Kubernetes one
# or more containers are deployed
containers:
- name: cassandra
image: "cassandra-debian:v1.1"
imagePullPolicy: Always
ports:
- containerPort: 7000
name: intra-node
- containerPort: 7199
name: jmx
- containerPort: 9042
name: cql
resources:
limits:
cpu: "4"
memory: 11Gi
requests:
cpu: "4"
memory: 11Gi
securityContext:
privileged: true
env:
- name: MAX\_HEAP\_SIZE
value: 8192M
- name: HEAP\_NEWSIZE
value: 2048M
# this is relying on guaranteed network identity of Pet Sets, we
# will know the name of the Pets / Pod before they are created
- name: CASSANDRA\_SEEDS
value: "cassandra-0.cassandra.default.svc.cluster.local,cassandra-1.cassandra.default.svc.cluster.local"
- name: CASSANDRA\_CLUSTER\_NAME
value: "OneKDemo"
- name: CASSANDRA\_DC
value: "DC1-Data"
- name: CASSANDRA\_RACK
value: "OneKDemo-Rack1-Data"
- name: CASSANDRA\_AUTO\_BOOTSTRAP
value: "false"
# this variable is used by the read-probe looking
# for the IP Address in a `nodetool status` command
- name: POD\_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
readinessProbe:
exec:
command:
- /bin/bash
- -c
- /ready-probe.sh
initialDelaySeconds: 15
timeoutSeconds: 5
# These volume mounts are persistent. They are like inline claims,
# but not exactly because the names need to match exactly one of
# the pet volumes.
volumeMounts:
- name: cassandra-data
mountPath: /cassandra\_data
# These are converted to volume claims by the controller
# and mounted at the paths mentioned above. Storage can be automatically
# created for the Pets depending on the cloud environment.
volumeClaimTemplates:
- metadata:
name: cassandra-data
annotations:
volume.alpha.kubernetes.io/storage-class: anything
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 380Gi
你可能会注意到这些容器相当大,在生产环境中运行带有 8 个 CPU 和 16GB 内存的 Cassandra 并不罕见。上面你会注意到两个关键的新特性:动态卷置备,当然还有 Pet Set。上面的清单将创建 5 个 Cassandra Pet / Pod,编号从 0 开始:cassandra-data-0、cassandra-data-1 等。
为了生成比赛数据,我们使用了另一个 Kubernetes 特性,称为 Jobs。编写了简单的 Python 代码来为比赛的每一秒生成怪物的随机速度。然后将这些数据、位置信息、获胜者、其他数据点和指标存储在 Cassandra 中。为了可视化数据,我们使用 JHipster 生成了一个带有 Java Service 的 AngularJS UI,然后使用 D3 进行图表绘制。
其中一个 Job 的示例
apiVersion: batch/v1
kind: Job
metadata:
name: pet-race-giants
labels:
name: pet-races
spec:
parallelism: 2
completions: 4
template:
metadata:
name: pet-race-giants
labels:
name: pet-races
spec:
containers:
- name: pet-race-giants
image: py3numpy-job:v1.0
command: ["pet-race-job", --length=100", "--pet=Giants", "--scale=3"]
resources:
limits:
cpu: "2"
requests:
cpu: "2"
restartPolicy: Never
既然我们在谈论怪物,我们就得玩大的。我们在 Google Compute Engine (GCE) 上部署了 1,009 个 minion 节点,分布在 4 个可用区,运行定制版的 Kubernetes 1.3 beta。我们在 beta 代码上运行此演示,因为演示在 1.3 发布日期之前搭建完成。对于 minion 节点,选择了 GCE 虚拟机 n1-standard-8 机器大小,这是具有 8 个虚拟 CPU 和 30GB 内存的虚拟机。这将允许 Cassandra 的单个实例运行在一个节点上,这对于磁盘 I/O 是推荐的。
然后,这些 Pet 被部署了!一千个 Pet,分布在两个不同的 Cassandra 数据中心。Cassandra 分布式架构专门为多数据中心部署而设计。通常,多个 Cassandra 数据中心部署在同一个物理或虚拟数据中心内,以隔离工作负载。数据在所有数据中心之间复制,但不同数据中心的工作负载可以不同,因此应用调优也可以不同。名为 'DC1-Analytics' 和 'DC1-Data' 的数据中心分别部署了 500 个 Pet。比赛数据由连接到 DC1-Data 的 Python Batch Job 创建,而 JHipster UI 连接到 DC1-Analytics。
以下是最终数据
- 8,072 个核心。Master 使用了 24 个,minion 节点使用了其余的。
- 1,009 个 IP 地址
- Kubernetes 在 Google Cloud Platform 上设置的 1,009 条路由
- Minion 和 Master 使用了 100,510 GB 持久盘
- 380,020 GB SSD 持久盘。Master 使用 20 GB,每个 Cassandra Pet 使用 340 GB。
- 1,000 个部署的 Cassandra 实例。是的,我们部署了 1,000 个 Pet,但有一个不太想加入!从技术上讲,在当前的 Cassandra 设置下,即使丢失 333 个节点,也不会导致服务中断或数据丢失。
1.3 版本中 Pet Set 的限制
- Pet Set 是一个 Alpha 资源,在 1.3 之前的任何 Kubernetes 版本中都不可用。
- 给定 Pet 的存储必须由基于请求的 StorageClass 的动态存储置备器进行置备,或者由管理员预先置备。
- 删除 Pet Set 不会删除任何 Pet 或 Pet 存储。你需要手动删除你的 Pet 及其可能的存储。
- 所有 Pet Set 当前都需要一个“管理服务”,即负责 Pet 网络身份的 Service。用户负责此 Service。
- 更新现有 Pet Set 当前是一个手动过程。你需要部署一个新的 Pet Set,使用新的镜像版本,或者逐个孤立 Pet 并更新它们的镜像,然后它们会重新加入集群。
资源和参考资料
- 演示的源代码可在 GitHub 上获取:(Pet Set 示例将合并到 Kubernetes Cassandra Examples 中)。
- 更多关于 Jobs 的信息
- Pet Set 文档
- 图片来源:Cassandra 图片和 Cyclops 图片