示例:使用 Stateful Sets 部署 Cassandra

    本示例也使用了Kubernetes的一些核心组件:

    准备工作

    本示例假设你已经安装运行了一个 Kubernetes集群(版本 >=1.2),并且还在某个路径下安装了 命令行工具。请查看 getting started guides 获取关于你的平台的安装说明。

    本示例还需要一些代码和配置文件。为了避免手动输入,你可以 git clone Kubernetes 源到你本地。

    Cassandra Docker 镜像

    Pod 使用来自 Google 的 gcr.io/google-samples/cassandra:v12 镜像。这个 docker 镜像基于 debian:jessie 并包含 OpenJDK 8。该镜像包含一个从 Apache Debian 源中安装的标准 Cassandra。你可以通过使用环境变量改变插入到 cassandra.yaml 文件中的参数值。

    快速入门

    如果你希望直接跳到我们使用的命令,以下是全部步骤:

    1. kubectl apply -f https://k8s.io/examples/application/cassandra/cassandra-service.yaml

    application/cassandra/cassandra-statefulset.yaml 示例:使用 Stateful Sets 部署 Cassandra - 图1

    1. apiVersion: apps/v1
    2. kind: StatefulSet
    3. metadata:
    4. name: cassandra
    5. labels:
    6. app: cassandra
    7. spec:
    8. serviceName: cassandra
    9. replicas: 3
    10. selector:
    11. matchLabels:
    12. app: cassandra
    13. template:
    14. metadata:
    15. labels:
    16. app: cassandra
    17. spec:
    18. terminationGracePeriodSeconds: 1800
    19. containers:
    20. - name: cassandra
    21. image: gcr.io/google-samples/cassandra:v13
    22. imagePullPolicy: Always
    23. ports:
    24. - containerPort: 7000
    25. name: intra-node
    26. - containerPort: 7001
    27. name: tls-intra-node
    28. - containerPort: 7199
    29. name: jmx
    30. - containerPort: 9042
    31. name: cql
    32. resources:
    33. limits:
    34. cpu: "500m"
    35. memory: 1Gi
    36. requests:
    37. cpu: "500m"
    38. memory: 1Gi
    39. securityContext:
    40. capabilities:
    41. add:
    42. - IPC_LOCK
    43. lifecycle:
    44. preStop:
    45. exec:
    46. command:
    47. - /bin/sh
    48. - -c
    49. - nodetool drain
    50. env:
    51. - name: MAX_HEAP_SIZE
    52. value: 512M
    53. - name: HEAP_NEWSIZE
    54. value: 100M
    55. - name: CASSANDRA_SEEDS
    56. value: "cassandra-0.cassandra.default.svc.cluster.local"
    57. - name: CASSANDRA_CLUSTER_NAME
    58. value: "K8Demo"
    59. - name: CASSANDRA_DC
    60. value: "DC1-K8Demo"
    61. - name: CASSANDRA_RACK
    62. value: "Rack1-K8Demo"
    63. - name: POD_IP
    64. valueFrom:
    65. fieldRef:
    66. fieldPath: status.podIP
    67. readinessProbe:
    68. exec:
    69. command:
    70. - /bin/bash
    71. - -c
    72. - /ready-probe.sh
    73. initialDelaySeconds: 15
    74. timeoutSeconds: 5
    75. # These volume mounts are persistent. They are like inline claims,
    76. # but not exactly because the names need to match exactly one of
    77. # the stateful pod volumes.
    78. volumeMounts:
    79. - name: cassandra-data
    80. mountPath: /cassandra_data
    81. # These are converted to volume claims by the controller
    82. # and mounted at the paths mentioned above.
    83. # do not use these in production until ssd GCEPersistentDisk or other ssd pd
    84. volumeClaimTemplates:
    85. - metadata:
    86. name: cassandra-data
    87. spec:
    88. accessModes: [ "ReadWriteOnce" ]
    89. storageClassName: fast
    90. resources:
    91. requests:
    92. storage: 1Gi
    93. ---
    94. kind: StorageClass
    95. apiVersion: storage.k8s.io/v1
    96. metadata:
    97. name: fast
    98. provisioner: k8s.io/minikube-hostpath
    99. parameters:
    100. type: pd-ssd
    1. # 创建 statefulset
    2. kubectl apply -f https://k8s.io/examples/application/cassandra/cassandra-statefulset.yaml
    3. # 验证 Cassandra 集群。替换一个 pod 的名称。
    4. kubectl exec -ti cassandra-0 -- nodetool status
    5. # 清理
    6. grace=$(kubectl get po cassandra-0 -o=jsonpath='{.spec.terminationGracePeriodSeconds}') \
    7. && kubectl delete statefulset,po -l app=cassandra \
    8. && echo "Sleeping $grace" \
    9. && sleep $grace \
    10. && kubectl delete pvc -l app=cassandra
    11. #
    12. # 资源控制器示例
    13. #
    14. # 创建一个副本控制器来复制 cassandra 节点
    15. kubectl create -f cassandra/cassandra-controller.yaml
    16. # 验证 Cassandra 集群。替换一个 pod 的名称。
    17. kubectl exec -ti cassandra-xxxxx -- nodetool status
    18. # 扩大 Cassandra 集群
    19. kubectl scale rc cassandra --replicas=4
    20. # 删除副本控制器
    21. kubectl delete rc cassandra
    22. #
    23. # 创建一个 DaemonSet,在每个 kubernetes 节点上放置一个 cassandra 节点
    24. #
    25. kubectl create -f cassandra/cassandra-daemonset.yaml --validate=false
    26. # 资源清理
    27. kubectl delete daemonset cassandra

    Kubernetes 描述一组执行同样任务的 Pod。在 Kubernetes 中,一个应用的原子调度单位是一个 Pod:一个或多个_必须_调度到相同主机上的容器。

    这个 Service 用于在 Kubernetes 集群内部进行 Cassandra 客户端和 Cassandra Pod 之间的 DNS 查找。

    以下为这个 service 的描述:

    1. apiVersion: v1
    2. kind: Service
    3. metadata:
    4. labels:
    5. app: cassandra
    6. name: cassandra
    7. spec:
    8. clusterIP: None
    9. ports:
    10. - port: 9042
    11. selector:
    12. app: cassandra

    Download and cassandra-statefulset.yaml

    为 StatefulSet 创建 service

    1. kubectl apply -f https://k8s.io/examples/application/cassandra/cassandra-service.yaml

    以下命令显示了 service 是否被成功创建。

    1. $ kubectl get svc cassandra

    命令的响应应该像这样:

    1. NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    2. cassandra None <none> 9042/TCP 45s

    如果返回错误则表示 service 创建失败。

    步骤 2:使用 StatefulSet 创建 Cassandra Ring环

    StatefulSets(以前叫做 PetSets)特性在 Kubernetes 1.5 中升级为一个 Beta 组件。在集群环境中部署类似于 Cassandra 的有状态分布式应用是一项具有挑战性的工作。我们实现了 StatefulSet,极大的简化了这个过程。本示例使用了 StatefulSet 的多个特性,但其本身超出了本文的范围。。

    以下是 StatefulSet 的清单文件,用于创建一个由三个 pod 组成的 Cassandra ring 环。

    本示例使用了 GCE Storage Class,请根据你运行的云平台做适当的修改。

    1. apiVersion: "apps/v1beta1"
    2. kind: StatefulSet
    3. metadata:
    4. name: cassandra
    5. spec:
    6. serviceName: cassandra
    7. replicas: 3
    8. template:
    9. labels:
    10. app: cassandra
    11. spec:
    12. containers:
    13. - name: cassandra
    14. image: gcr.io/google-samples/cassandra:v12
    15. imagePullPolicy: Always
    16. ports:
    17. - containerPort: 7000
    18. name: intra-node
    19. - containerPort: 7001
    20. name: tls-intra-node
    21. - containerPort: 7199
    22. name: jmx
    23. - containerPort: 9042
    24. name: cql
    25. resources:
    26. limits:
    27. cpu: "500m"
    28. memory: 1Gi
    29. requests:
    30. cpu: "500m"
    31. memory: 1Gi
    32. securityContext:
    33. capabilities:
    34. add:
    35. - IPC_LOCK
    36. lifecycle:
    37. preStop:
    38. exec:
    39. command: ["/bin/sh", "-c", "PID=$(pidof java) && kill $PID && while ps -p $PID > /dev/null; do sleep 1; done"]
    40. env:
    41. - name: MAX_HEAP_SIZE
    42. value: 512M
    43. - name: HEAP_NEWSIZE
    44. value: 100M
    45. - name: CASSANDRA_SEEDS
    46. value: "cassandra-0.cassandra.default.svc.cluster.local"
    47. - name: CASSANDRA_CLUSTER_NAME
    48. value: "K8Demo"
    49. - name: CASSANDRA_DC
    50. value: "DC1-K8Demo"
    51. - name: CASSANDRA_RACK
    52. value: "Rack1-K8Demo"
    53. - name: CASSANDRA_AUTO_BOOTSTRAP
    54. value: "false"
    55. - name: POD_IP
    56. valueFrom:
    57. fieldRef:
    58. fieldPath: status.podIP
    59. readinessProbe:
    60. exec:
    61. command:
    62. - /bin/bash
    63. - -c
    64. - /ready-probe.sh
    65. initialDelaySeconds: 15
    66. timeoutSeconds: 5
    67. # These volume mounts are persistent. They are like inline claims,
    68. # but not exactly because the names need to match exactly one of
    69. # the stateful pod volumes.
    70. volumeMounts:
    71. - name: cassandra-data
    72. mountPath: /cassandra_data
    73. # These are converted to volume claims by the controller
    74. # and mounted at the paths mentioned above.
    75. # do not use these in production until ssd GCEPersistentDisk or other ssd pd
    76. volumeClaimTemplates:
    77. - metadata:
    78. name: cassandra-data
    79. annotations:
    80. volume.beta.kubernetes.io/storage-class: fast
    81. spec:
    82. accessModes: [ "ReadWriteOnce" ]
    83. resources:
    84. requests:
    85. storage: 1Gi
    86. ---
    87. kind: StorageClass
    88. apiVersion: storage.k8s.io/v1beta1
    89. metadata:
    90. name: fast
    91. provisioner: kubernetes.io/gce-pd
    92. parameters:
    93. type: pd-ssd

    创建 Cassandra StatefulSet 如下:

    1. kubectl apply -f https://k8s.io/examples/application/cassandra/cassandra-statefulset.yaml

    步骤 3:验证和修改 Cassandra StatefulSet

    这个 StatefulSet 的部署展示了 StatefulSets 提供的两个新特性:

    1. Pod 的名称已知
    2. Pod 以递增顺序部署

    首先,运行下面的 kubectl 命令,验证 StatefulSet 已经被成功部署。

    1. $ kubectl get statefulset cassandra

    这个命令的响应应该像这样:

    1. NAME DESIRED CURRENT AGE
    2. cassandra 3 3 13s

    接下来观察 Cassandra pod 以一个接一个的形式部署。StatefulSet 资源按照数字序号的模式部署 pod:1, 2, 3 等。如果在 pod 部署前执行下面的命令,你就能够看到这种顺序的创建过程。

    1. $ kubectl get pods -l="app=cassandra"
    2. NAME READY STATUS RESTARTS AGE
    3. cassandra-0 1/1 Running 0 1m
    4. cassandra-1 0/1 ContainerCreating 0 8s

    运行 Cassandra 工具 nodetool 将显示 ring 环的状态。

    1. $ kubectl exec cassandra-0 -- nodetool status
    2. Datacenter: DC1-K8Demo
    3. ======================
    4. Status=Up/Down
    5. |/ State=Normal/Leaving/Joining/Moving
    6. -- Address Load Tokens Owns (effective) Host ID Rack
    7. UN 10.4.2.4 65.26 KiB 32 63.7% a9d27f81-6783-461d-8583-87de2589133e Rack1-K8Demo
    8. UN 10.4.0.4 102.04 KiB 32 66.7% 5559a58c-8b03-47ad-bc32-c621708dc2e4 Rack1-K8Demo
    9. UN 10.4.1.4 83.06 KiB 32 69.6% 9dce943c-581d-4c0e-9543-f519969cc805 Rack1-K8Demo

    你也可以运行 cqlsh 来显示集群的 keyspaces。

    1. $ kubectl exec cassandra-0 -- cqlsh -e 'desc keyspaces'
    2. system_traces system_schema system_auth system system_distributed

    你需要使用 kubectl edit 来增加或减小 Cassandra StatefulSet 的大小。你可以在文档 中找到更多关于 edit 命令的信息。

    使用以下命令编辑 StatefulSet。

    1. $ kubectl edit statefulset cassandra

    这会在你的命令行中创建一个编辑器。你需要修改的行是 replicas。这个例子没有包含终端窗口的所有内容,下面示例中的最后一行就是你希望改变的 replicas 行。

    1. # Please edit the object below. Lines beginning with a '#' will be ignored,
    2. # and an empty file will abort the edit. If an error occurs while saving this file will be
    3. # reopened with the relevant failures.
    4. #
    5. apiVersion: apps/v1beta1
    6. kind: StatefulSet
    7. metadata:
    8. creationTimestamp: 2016-08-13T18:40:58Z
    9. generation: 1
    10. labels:
    11. app: cassandra
    12. name: cassandra
    13. namespace: default
    14. resourceVersion: "323"
    15. uid: 7a219483-6185-11e6-a910-42010a8a0fc0
    16. spec:
    17. replicas: 3

    按下面的示例修改清单文件并保存。

    1. spec:
    2. replicas: 4

    这个 StatefulSet 现在将包含四个 pod。

    1. $ kubectl get statefulset cassandra

    这个command的响应应该像这样:

    1. NAME DESIRED CURRENT AGE
    2. cassandra 4 4 36m

    对于 Kubernetes 1.5 发布版,beta StatefulSet 资源没有像 Deployment, ReplicaSet, Replication Controller 或者 Job 一样,包含 kubectl scale 功能,

    步骤 4:删除 Cassandra StatefulSet

    删除或者缩容 StatefulSet 时不会删除与之关联的 volumes。这样做是为了优先保证安全。你的数据比其它会被自动清除的 StatefulSet 关联资源更宝贵。删除 Persistent Volume Claims 可能会导致关联的 volumes 被删除,这种行为依赖 storage class 和 reclaim policy。永远不要期望能在 claim 删除后访问一个 volume。

    使用如下命令删除 StatefulSet。

    1. $ grace=$(kubectl get po cassandra-0 -o=jsonpath='{.spec.terminationGracePeriodSeconds}') \
    2. && kubectl delete statefulset -l app=cassandra \
    3. && echo "Sleeping $grace" \
    4. && sleep $grace \
    5. && kubectl delete pvc -l app=cassandra

    Kubernetes 负责复制一个完全相同的 pod 集合。像 Service 一样,它具有一个 selector query,用来识别它的集合成员。和 Service 不一样的是,它还具有一个期望的副本数,并且会通过创建或删除 Pod 来保证 Pod 的数量满足它期望的状态。

    和我们刚才定义的 Service 一起,Replication Controller 能够让我们轻松的构建一个复制的、可扩展的 Cassandra 集群。

    让我们创建一个具有两个初始副本的 replication controller。

    1. apiVersion: v1
    2. kind: ReplicationController
    3. metadata:
    4. name: cassandra
    5. # The labels will be applied automatically
    6. # from the labels in the pod template, if not set
    7. # labels:
    8. # app: cassandra
    9. spec:
    10. # The selector will be applied automatically
    11. # from the labels in the pod template, if not set.
    12. # selector:
    13. # app: cassandra
    14. template:
    15. metadata:
    16. labels:
    17. app: cassandra
    18. spec:
    19. containers:
    20. - command:
    21. - /run.sh
    22. resources:
    23. limits:
    24. cpu: 0.5
    25. env:
    26. - name: MAX_HEAP_SIZE
    27. value: 512M
    28. - name: HEAP_NEWSIZE
    29. value: 100M
    30. - name: CASSANDRA_SEED_PROVIDER
    31. value: "io.k8s.cassandra.KubernetesSeedProvider"
    32. - name: POD_NAMESPACE
    33. fieldRef:
    34. fieldPath: metadata.namespace
    35. - name: POD_IP
    36. valueFrom:
    37. fieldRef:
    38. fieldPath: status.podIP
    39. image: gcr.io/google-samples/cassandra:v12
    40. name: cassandra
    41. ports:
    42. - containerPort: 7000
    43. name: intra-node
    44. - containerPort: 7001
    45. name: tls-intra-node
    46. - containerPort: 7199
    47. name: jmx
    48. - containerPort: 9042
    49. name: cql
    50. volumeMounts:
    51. - mountPath: /cassandra_data
    52. name: data
    53. volumes:
    54. - name: data
    55. emptyDir: {}

    下载示例

    在这个描述中需要注意几件事情。

    selector 属性包含了控制器的 selector query。它能够被显式指定,或者在没有设置时,像此处一样从 pod 模板中的 labels 中自动应用。

    Pod 模板的标签 app:cassandra 匹配步骤1中的 Service selector。这就是 Service 如何选择 replication controller 创建的 pod 的原理。

    replicas 属性指明了期望的副本数量,在本例中最开始为 2。我们很快将要扩容更多数量。

    创建 Replication Controller:

    1. $ kubectl create -f cassandra/cassandra-controller.yaml

    你可以列出新建的 controller:

    1. $ kubectl get rc -o wide
    2. NAME DESIRED CURRENT AGE CONTAINER(S) IMAGE(S) SELECTOR
    3. cassandra 2 2 11s cassandra gcr.io/google-samples/cassandra:v12 app=cassandra

    现在,如果你列出集群中的 pod,并且使用 app=cassandra 标签过滤,你应该能够看到两个 Cassandra pod。(wide 参数使你能够看到 pod 被调度到了哪个 Kubernetes 节点上)

    1. $ kubectl get pods -l="app=cassandra" -o wide
    2. NAME READY STATUS RESTARTS AGE NODE
    3. cassandra-21qyy 1/1 Running 0 1m kubernetes-minion-b286
    4. cassandra-q6sz7 1/1 Running 0 1m kubernetes-minion-9ye5

    因为这些 pod 拥有 app=cassandra 标签,它们被映射给了我们在步骤 1 中创建的 service。

    为了显示 SeedProvider 逻辑是按设想在运行,你可以使用 nodetool 命令来检查 Cassandra 集群的状态。为此,请使用 kubectl exec 命令,这样你就能在一个 Cassandra pod 上运行 nodetool。同样的,请替换 cassandra-xxxxx 为任意一个 pods的真实名字。

    1. $ kubectl exec -ti cassandra-xxxxx -- nodetool status
    2. Datacenter: datacenter1
    3. =======================
    4. Status=Up/Down
    5. |/ State=Normal/Leaving/Joining/Moving
    6. -- Address Load Tokens Owns (effective) Host ID Rack
    7. UN 10.244.0.5 74.09 KB 256 100.0% 86feda0f-f070-4a5b-bda1-2eeb0ad08b77 rack1
    8. UN 10.244.3.3 51.28 KB 256 100.0% dafe3154-1d67-42e1-ac1d-78e7e80dce2b rack1

    步骤 6:Cassandra 集群扩容

    现在,让我们把 Cassandra 集群扩展到 4 个 pod。我们通过告诉 Replication Controller 现在我们需要 4 个副本来完成。

    1. $ kubectl scale rc cassandra --replicas=4

    你可以看到列出了新的 pod:

    1. $ kubectl get pods -l="app=cassandra" -o wide
    2. NAME READY STATUS RESTARTS AGE NODE
    3. cassandra-21qyy 1/1 Running 0 6m kubernetes-minion-b286
    4. cassandra-81m2l 1/1 Running 0 47s kubernetes-minion-b286
    5. cassandra-8qoyp 1/1 Running 0 47s kubernetes-minion-9ye5
    6. cassandra-q6sz7 1/1 Running 0 6m kubernetes-minion-9ye5

    一会儿你就能再次检查 Cassandra 集群的状态,你可以看到新的 pod 已经被自定义的 SeedProvider 检测到:

    1. $ kubectl exec -ti cassandra-xxxxx -- nodetool status
    2. Datacenter: datacenter1
    3. =======================
    4. Status=Up/Down
    5. |/ State=Normal/Leaving/Joining/Moving
    6. -- Address Load Tokens Owns (effective) Host ID Rack
    7. UN 10.244.0.6 51.67 KB 256 48.9% d07b23a5-56a1-4b0b-952d-68ab95869163 rack1
    8. UN 10.244.1.5 84.71 KB 256 50.7% e060df1f-faa2-470c-923d-ca049b0f3f38 rack1
    9. UN 10.244.1.6 84.71 KB 256 47.0% 83ca1580-4f3c-4ec5-9b38-75036b7a297f rack1
    10. UN 10.244.0.5 68.2 KB 256 53.4% 72ca27e2-c72c-402a-9313-1e4b61c2f839 rack1

    步骤 7:删除 Replication Controller

    在你开始步骤 5 之前, __删除__你在上面创建的 replication controller

    1. $ kubectl delete rc cassandra

    步骤 8:使用 DaemonSet 替换 Replication Controller

    在 Kubernetes中, 能够将 pod 一对一的分布到 Kubernetes 节点上。和 ReplicationController 相同的是它也有一个用于识别它的集合成员的 selector query。但和 ReplicationController 不同的是,它拥有一个节点 selector,用于限制基于模板的 pod 可以调度的节点。并且 pod 的复制不是基于一个设置的数量,而是为每一个节点分配一个 pod。

    示范用例:当部署到云平台时,预期情况是实例是短暂的并且随时可能终止。Cassandra 被搭建成为在各个节点间复制数据以便于实现数据冗余。这样的话,即使一个实例终止了,存储在它上面的数据却没有,并且集群会通过重新复制数据到其它运行节点来作为响应。

    DaemonSet 设计为在 Kubernetes 集群中的每个节点上放置一个 pod。那样就会给我们带来数据冗余度。让我们创建一个 DaemonSet 来启动我们的存储集群:

    1. apiVersion: extensions/v1beta1
    2. kind: DaemonSet
    3. metadata:
    4. labels:
    5. name: cassandra
    6. name: cassandra
    7. spec:
    8. template:
    9. metadata:
    10. labels:
    11. app: cassandra
    12. spec:
    13. # Filter to specific nodes:
    14. # nodeSelector:
    15. # app: cassandra
    16. containers:
    17. - command:
    18. - /run.sh
    19. env:
    20. - name: MAX_HEAP_SIZE
    21. value: 512M
    22. - name: HEAP_NEWSIZE
    23. value: 100M
    24. - name: CASSANDRA_SEED_PROVIDER
    25. value: "io.k8s.cassandra.KubernetesSeedProvider"
    26. - name: POD_NAMESPACE
    27. valueFrom:
    28. fieldRef:
    29. fieldPath: metadata.namespace
    30. - name: POD_IP
    31. valueFrom:
    32. fieldRef:
    33. fieldPath: status.podIP
    34. image: gcr.io/google-samples/cassandra:v12
    35. name: cassandra
    36. ports:
    37. - containerPort: 7000
    38. name: intra-node
    39. - containerPort: 7001
    40. name: tls-intra-node
    41. - containerPort: 7199
    42. name: jmx
    43. - containerPort: 9042
    44. name: cql
    45. # If you need it, it will go away in C* 4.0.
    46. #- containerPort: 9160
    47. # name: thrift
    48. resources:
    49. requests:
    50. cpu: 0.5
    51. volumeMounts:
    52. - mountPath: /cassandra_data
    53. name: data
    54. volumes:
    55. - name: data
    56. emptyDir: {}

    下载示例

    这个 DaemonSet 绝大部分的定义和上面的 ReplicationController 完全相同;它只是简单的给 daemonset 一个创建新的 Cassandra pod 的方法,并且以集群中所有的 Cassandra 节点为目标。

    不同之处在于 nodeSelector 属性,它允许 DaemonSet 以全部节点的一个子集为目标(你可以向其他资源一样标记节点),并且没有 replicas 属性,因为它使用1对1的 node-pod 关系。

    创建这个 DaemonSet:

    1. $ kubectl create -f cassandra/cassandra-daemonset.yaml

    你可能需要禁用配置文件检查,像这样:

    1. $ kubectl create -f cassandra/cassandra-daemonset.yaml --validate=false

    你可以看到 DaemonSet 已经在运行:

    1. $ kubectl get daemonset
    2. NAME DESIRED CURRENT NODE-SELECTOR
    3. cassandra 3 3 <none>

    现在,如果你列出集群中的 pods,并且使用 app=cassandra 标签过滤,你应该能够看到你的网络中的每一个节点上都有一个(且只有一个)新的 cassandra pod。

    1. $ kubectl get pods -l="app=cassandra" -o wide
    2. NAME READY STATUS RESTARTS AGE NODE
    3. cassandra-ico4r 1/1 Running 0 4s kubernetes-minion-rpo1
    4. cassandra-kitfh 1/1 Running 0 1s kubernetes-minion-9ye5
    5. cassandra-tzw89 1/1 Running 0 2s kubernetes-minion-b286

    为了证明这是按设想的在工作,你可以再次使用 nodetool 命令来检查集群的状态。为此,请使用 kubectl exec 命令在任何一个新建的 cassandra pod 上运行 nodetool

    1. $ kubectl exec -ti cassandra-xxxxx -- nodetool status
    2. Datacenter: datacenter1
    3. =======================
    4. Status=Up/Down
    5. |/ State=Normal/Leaving/Joining/Moving
    6. -- Address Load Tokens Owns (effective) Host ID Rack
    7. UN 10.244.0.5 74.09 KB 256 100.0% 86feda0f-f070-4a5b-bda1-2eeb0ad08b77 rack1
    8. UN 10.244.4.2 32.45 KB 256 100.0% 0b1be71a-6ffb-4895-ac3e-b9791299c141 rack1
    9. UN 10.244.3.3 51.28 KB 256 100.0% dafe3154-1d67-42e1-ac1d-78e7e80dce2b rack1

    注意:这个示例让你在创建 DaemonSet 前删除了 cassandra 的 Replication Controller。这是因为为了保持示例的简单,RC 和 DaemonSet 使用了相同的 app=cassandra 标签(如此它们的 pod 映射到了我们创建的 service,这样 SeedProvider 就能识别它们)。

    如果我们没有预先删除 RC,这两个资源在需要运行多少 pod 上将会发生冲突。如果希望的话,我们可以使用额外的标签和 selectors 来支持同时运行它们。

    当你准备删除你的资源时,按以下执行:

    1. $ kubectl delete service -l app=cassandra

    我们使用了一个自定义的 来在 Kubernetes 之上运行 Cassandra。仅当你通过 replication control 或者 daemonset 部署 Cassandra 时才需要使用自定义的 seed provider。在 Cassandra 中,SeedProvider 引导 Cassandra 使用 gossip 协议来查找其它 Cassandra 节点。Seed 地址是被视为连接端点的主机。Cassandra 实例使用 seed 列表来查找彼此并学习 ring 环拓扑。KubernetesSeedProvider 通过 Kubernetes API 发现 Cassandra seeds IP 地址,那些 Cassandra 实例在 Cassandra Service 中定义。

    请查阅自定义 seed provider 的 文档,获取 KubernetesSeedProvider 进阶配置。对于本示例来说,你应该不需要自定义 Seed Provider 的配置。

    查看本示例的 image 目录,了解如何构建容器的 docker 镜像及其内容。

    你可能还注意到我们设置了一些 Cassandra 参数(MAX_HEAP_SIZEHEAP_NEWSIZE),并且增加了关于 的信息。我们还告诉 Kubernetes 容器暴露了 和 Thrift API 端口。最后,我们告诉集群管理器我们需要 0.1 cpu(0.1 核)。