本文已發布超過一年。較舊的文章可能包含過時的內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

使用 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 組件讓一切變得更加容易。為了大規模測試這項新功能,我們決定舉辦希臘寵物怪獸賽跑!我們讓半人馬和其他古希臘怪獸在跨多個可用區的數十萬場比賽中競賽。

File:Cassandra1.jpeg
如你們許多人所知,Kubernetes 源自古希臘語:κυβερνήτης。這意味著舵手、飛行員、操舵手或船長。因此,為了追蹤比賽結果,我們需要一個資料儲存庫,而我們選擇了 Cassandra。Κασσάνδρα,卡珊德拉,她是特洛伊國王普里阿摩斯和王后赫卡柏的女兒。由於多次提及古希臘語,我們認為讓古希臘怪獸參賽是很恰當的。

從那時起,故事有點偏離主題,因為 Cassandra 實際上也是 Pet。請繼續閱讀,我們將會解釋。

Kubernetes 1.3 中令人興奮的新功能之一是 Pet Set。為了組織 Kubernetes 內部容器的部署,有不同的部署機制可供使用。這些組件的範例包括資源控制器和 Daemon Set。Pet Set 是一項新功能,提供在 Kubernetes 內部以 Pet 形式部署容器的功能。Pet Set 為 pet / pod 部署的各個方面提供身分保證:DNS 名稱、一致的儲存空間和有序的 pod 索引。先前,使用 Deployment 和複製控制器等組件,只會部署具有弱耦合身分識別的應用程式。對於管理微服務等應用程式來說,弱身分識別非常適合,因為在微服務中,服務發現很重要,應用程式是無狀態的,並且個別 Pod 的命名並不重要。許多軟體應用程式確實需要強身分識別,包括許多不同類型的分散式有狀態系統。Cassandra 是需要一致網路身分識別和穩定儲存空間的分散式應用程式的絕佳範例。

Pet Set 提供以下功能

  • 一個穩定的主機名稱,可供 DNS 中的其他服務使用。編號基於 Pet Set 名稱,並從零開始。例如 cassandra-0。
  • Pet 的序數索引。0、1、2、3 等。
  • 穩定的儲存空間,連結到 Pet 的序數和主機名稱。
  • 對等點探索可透過 DNS 進行。對於 Cassandra,對等點的名稱在 Pet 建立之前就已得知。
  • 啟動和關閉順序。哪個編號的 Pet 將會是下一個建立的 Pet 是已知的,以及在縮減 Pet Set 大小時,哪個 Pet 將會被銷毀也是已知的。當縮減叢集大小時,此功能對於從 Pet 排空資料等管理任務非常有用。

如果您的應用程式具有其中一項或多項需求,那麼它可能適合使用 Pet Set。
一個相關的類比是,Pet Set 是由 Pet 狗組成的。如果您有一隻白色、棕色或黑色狗,而棕色狗跑掉了,您可以換成另一隻棕色狗,沒有人會注意到。如果隨著時間推移,您一直用白狗替換您的狗,那麼就會有人注意到。Pet Set 讓您的應用程式能夠維持 Pet 的獨特身分或毛色。

Pet Set 的範例工作負載

  • Cassandra、Zookeeper、etcd 或 Elastic 等叢集軟體需要穩定的成員資格。
  • MySQL 或 PostgreSQL 等資料庫,隨時都需要將單一實例連接到持久卷。

只有在您的應用程式需要其中一些或所有這些屬性時,才使用 Pet Set。將 Pod 作為無狀態副本進行管理要容易得多。

所以回到我們的賽跑!

正如我們所提到的,Cassandra 是透過 Pet Set 部署的完美候選者。Pet Set 非常像 複製控制器,但有一些新的附加功能。以下是一個 YAML 範例清單

無頭服務以提供 DNS 查詢

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 服務的 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

File:Polyphemus.gif由於我們在談論怪獸,我們必須擴大規模。我們將 1,009 個 Minion 節點部署到 Google Compute Engine (GCE),分佈在 4 個區域,執行 Kubernetes 1.3 beta 的自訂版本。由於示範是在 1.3 發布日期之前設定的,因此我們在 beta 程式碼上執行此示範。對於 Minion 節點,選擇了 GCE 虛擬機器 n1-standard-8 機器大小,這是一個具有 8 個虛擬 CPU 和 30GB 記憶體的虛擬機器。這將允許在一個節點上執行單一 Cassandra 實例,這是磁碟 I/O 的建議做法。

然後部署了 Pet!總共一千個,在兩個不同的 Cassandra 資料中心中。Cassandra 分散式架構專為多資料中心部署而設計。通常,多個 Cassandra 資料中心部署在同一個實體或虛擬資料中心內部,以便隔離工作負載。資料會在所有資料中心之間複製,但資料中心之間的工作負載可能不同,因此應用程式調校也可能不同。名為 'DC1-Analytics' 和 'DC1-Data' 的資料中心各部署了 500 個 Pet。比賽資料是由連接到 DC1-Data 的 Python Batch Jobs 建立的,而 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 的儲存空間必須由動態儲存空間佈建器根據請求的儲存類別進行佈建,或由管理員預先佈建。
  • 刪除 Pet Set 不會刪除任何 Pet 或 Pet 儲存空間。您將需要手動刪除您的 Pet 以及可能的儲存空間。
  • 目前所有 Pet Set 都需要一個「管理服務」,或是一個負責 Pet 網路身分識別的服務。使用者負責此服務。
  • 更新現有的 Pet Set 目前是一個手動過程。您需要部署具有新映像版本的全新 Pet Set,或者逐一孤立 Pet 並更新其映像,這會使它們重新加入叢集。

資源與參考資料

  • 示範的原始碼可在 GitHub 上取得:(Pet Set 範例將會合併到 Kubernetes Cassandra 範例中)。
  • 關於 Jobs 的更多資訊
  • Pet Set 的文件
  • 圖片來源:Cassandra 圖片 和 Cyclops 圖片