Kubernetes と GitOps を使用する Apache Kafka® 用 DevOps

streaming-ops プロジェクト は本稼働環境のシミュレーションであり、Confluent Cloud 上の Apache Kafka® をターゲットとするストリーミングアプリケーションを実行しています。アプリケーションとリソースは、宣言型インフラストラクチャである Kubernetes および オペレーターパターン を使用して GitOps によって管理されます。このドキュメントには、使用方法の説明とプロジェクトのハイライトが含まれます。

"streaming-ops" のその他の詳細については、ブログの投稿記事「DevOps for Apache Kafka® with Kubernetes and GitOps」を参照してください。

Kubernetes 上でのイベントストリーミングアプリケーションの管理に関するドキュメント、コードおよび戦略を参照するだけでも、このプロジェクトが役立つことがわかるでしょう。さらに、独自のバージョンのプロジェクトを運用する場合は、次の使用方法の説明に従ってください。

使用方法

セットアップ

  1. このプロジェクトでは、Kubernetes 上でマイクロサービスを運用するための GitOps ワークフローを重点的に紹介しています。GitOps を使用するには、FluxCD アプリケーションに、リポジトリへの読み取りおよび書き込みアクセス許可があることが必要です。独自のローカルバージョンの場合は、このリポジトリのフォークを作成し、そのクローンをローカルで作成する必要があります。作成しない場合は、GitOps 自動化に、レポジトリに対する読み取りおよび書き込みが許可されません。

    ../../_images/streaming-ops-fork.png
  2. リポジトリのフォークとクローンを作成した後、次の 2 つのシェル変数をエクスポートします。これで、プロジェクトのインストールが、適切な GitHub リポジトリと GitHub アカウント向けに構成されます。

    • REPO_URL 変数をエクスポートして、フォークを作成したリポジトリの git URL をポイントします。
    export REPO_URL=git@github.com:your-fork/streaming-ops
    
    • 自分の GitHub ユーザー ID で GHUSER 変数をエクスポートします。
    export GHUSER="Your GitHub User ID"
    

前提条件

Confluent Cloud

このプロジェクトでは、Kafka と Schema Registry のために Confluent Cloud を使用します。streaming-ops プロジェクトのコピーを実行するには、Confluent Cloud アカウントが必要になります。新しいアカウントにサインアップするときは、プロモーションコード DEVOPS200 を使用すると、$200 分を無料で使用できます(詳細)。

警告

このプロジェクトに組み込まれた自動化により、実際の Confluent Cloud リソースが作成され、管理されます。Confluent Cloud 環境、クラスター、トピック、ACL、サービスアカウントが作成され、課金対象となる他の Confluent Cloud リソースが作成される場合もあります。想定外の課金を避けるために、デモを起動する前に、慎重にリソースのコストを見積もってください。また、デモが終了したら、すべての Confluent Cloud リソースが破棄されたことを手作業で確認してください。

開発ツール

このプロジェクトでは、さまざまなツールがローカル開発マシンにインストールされている必要があります。以下に、ツールのインストール用のリンクなど、これらの要件のリストを示します。これらのツールを手作業でインストールすることもできますが、macOS を使用している場合は、提供されている make ターゲットを使用して依存関係をインストールできます。この make ターゲットは、 Homebrew および /usr/local/bin へのバイナリのダウンロードとコピーを組み合わせて使用します。

別のオペレーティングシステムを使用している場合や、依存関係を手作業でインストールする場合は、この手順をスキップし、以下の個々のツールのインストール手順に従ってください。

警告

この make コマンドを使用する場合は、 /usr/local/bin にファイルをインストールするために管理パスワードの入力が求められます。

make install-deps

ローカル開発ツールを入手したら、以下にある次のセクションに進みます。

ツール 情報 インストール手順
ccloud ccloud CLI を使用して Confluent Cloud リソースを管理します。 Confluent Cloud CLI をインストールします。
kubectl Kubernetes クラスターとの連携や、シークレットの作成などに必要です。 https://kubernetes.io/ja/docs/tasks/tools/
helm Kubernetes クラスターに FluxCD をインストールするために使用します。 https://helm.sh/ja/docs/intro/install/
fluxctl Kubernetes クラスター内の FluxCD コントローラーと連携するために必要です。 https://docs.fluxcd.io/en/1.18.0/references/fluxctl.html
k3d (省略可)ローカルの Docker ベースの Kubernetes クラスター上でプロジェクトを実行するために使用します。 https://github.com/rancher/k3d#get
Kustomize Kustomize スタイルのオーバーレイを使用して環境(dev、stg、prd など)が作成されます。 https://kubernetes-sigs.github.io/kustomize/installation/
kubeseal Sealed Secrets と kubeseal を使用してシークレットが暗号化され、その後、Git リポジトリにコミットされます。 https://github.com/bitnami-labs/sealed-secrets
jq JSON の処理に使用します。 https://stedolan.github.io/jq/
yq YAML の処理に使用します。 https://github.com/mikefarah/yq

Kubernetes クラスター

  1. プロジェクトでは、Kubernetes を使用して、Confluent Cloud Kafka および Schema Registry に接続されたアプリケーションをホストします。既存の Kubernetes クラスターを使用する場合に必要なのは、必ず kubectl コマンドを構成して、そのクラスターが適切に管理されるようにすることです。k3d を使用して Docker 上にローカルテスト Kubernetes クラスターを作成する場合は、提供されている以下の make ターゲットを使用します。

    make cluster
    

    kubectl が適切に構成され、クラスターで準備が整っていることを確認します。

    kubectl get nodes
    
    NAME                        STATUS   ROLES    AGE   VERSION
    k3d-streaming-ops-server-0   Ready    master   24s   v1.18.4+k3s1
    k3d-streaming-ops-server-1   Ready    master   15s   v1.18.4+k3s1
    k3d-streaming-ops-server-2   Ready    master   12s   v1.18.4+k3s1
    k3d-streaming-ops-server-3   Ready    master   10s   v1.18.4+k3s1
    

シークレットの作成

  1. このプロジェクトでは、Bitnami Sealed Secrets を使用してシークレットの値(パスワードや API キーなど)を管理します。使用する Kubernetes クラスター用に kubectl クライアントを構成しているため、次のコマンドで、Sealed Secrets コントローラーを Kubernetes 内にインストールします。

    make install-bitnami-secret-controller
    

    戻り値が null から 1 に変わるまで、このコマンドを繰り返して、Sealed Secrets コントローラーの準備が整うまで待機します。

    kubectl get -n kube-system deployment/sealed-secrets-controller -o json | jq '.status.availableReplicas'
    
  2. シ-クレットコントローラーのパブリックキーを取得し、これを使用してシークレットをシーリング(暗号化)します。Sealed Secrets が Git リポジトリにコミットされ、その後、GitOps プロセスによって Kubernetes クラスター内にインストールされます。パブリック/プライベートキーペアを生成したシ-クレットコントローラーのみが、Kubernetes クラスター内の Sealed Secrets を復号化できます。

    クラスターにパブリックノードがある(この手順のローカル dev クラスターセットアップのように)場合は、次のコマンドを使用してパブリックキーを取得し、保存することができます。

    make get-public-key-dev
    

    プライベート(ネットワークポリシーで許可されないため、kubeseal がシ-クレットコントローラーにアクセスできません)である既存のクラスターを使用している場合は、シ-クレットコントローラーのログファイルから、ローカルに保管されているキーファイルにキーをコピーする必要があります。kubectl を含むクラスターへの管理者アクセス許可がある場合は、次のコマンドを実行してログを取得できる可能性があります。

    kubectl logs -n kube-system deployment/sealed-secrets-controller
    

    パブリックキーを取得したら、secrets/keys/dev.crt にあるファイルにそれを保管します。このファイルをリポジトリにチェックインする必要はありませんが、これはシークレット情報ではありません。セットアップスクリプトの残りの部分は、シークレットを暗号化するために、secrets/keys/dev.crt の場所でパブリックキーを探します。

    注釈

    シークレットの長期的管理とプライベートクラスターの詳細については Bitnami のドキュメント を参照してください。

    以下を実行して、secrets/key/dev.crt ファイルの内容を検証します。

    cat secrets/keys/dev.crt
    

    次のような結果が得られるので、確認します。

    -----BEGIN CERTIFICATE-----
    MIIErTCCApWgAwIBAgIQH5QEHe0tYPRHi2fPNkCZITANBgkqhkiG9w0BAQsFADAA
    MB4XDTIwMDkwMjE0MDcwOFoXDTMwMDgzMTE0MDcwOFowADCCAiIwDQYJKoZIhvcN
    AQEBBQADggIPADCCAgoCggIBAKoUaCGavOp4Aqz9b3eTDibdytlq46jsBpBGfF7R
    ...
    pzdWVMSumzZnWE/bu9+OQ4TX0d2p6ka/paOXuOObGOlJclex3lEc3Hw06iL9TnJJ
    K4qei3kT6H/QlcjslyWaJtPO5liZLbjBBitXjONM3A8vLfKXA+3IVHG4QAr39jtv
    2Q==
    -----END CERTIFICATE-----
    
  3. シークレットのシーリングプロセスは、次のパターンに従って進みます(この説明の後にサンプルコマンドがあります)。

    • シーリングするシークレットを含むローカルテキストファイルを作成します。このファイルには、未加工のシークレットデータが含まれているため、他のシークレットと同様に保護する必要があります。
    • kubectl create secret file コマンドを使用してローカル Kubernetes シークレットマニフェストファイルを作成し、ステージングエリアに配置します。このファイルには、base64 エンコーディングの未加工のシークレットデータが含まれているため、他のシークレットと同様に保護する必要があります。
    • kubeseal コマンドは、シークレットコントローラーのパブリックキーと、前の手順で作成した Kubernetes シークレットファイルで実行されます。これにより、Sealed Secrets Kubernetes マニフェストファイルが暗号化され、作成されます。このファイルは、暗号化されたシークレットを含んでおり、安全に git リポジトリ(パブリックリポジトリを含む)にコミットできます。これは、シ-クレットコントローラーのみが内部プライベートキーでシークレットを復号化できるためです。
    • この Sealed Secrets ファイルをリポジトリにコミットし、プッシュします。
    • FluxCD により Sealed Secrets が Kubernetes クラスターに同期されます。
    • Kubernetes クラスター内の Sealed Secrets コントローラーは、新しいシーリングされたシークレットを見つけ、Opaque Secrets としてクラスター内にインストールしてシーリングを解除します。

    以下の手順で、このプロセスをわかりやすく説明します。

    注釈

    以下のコマンドでは、名前空間、シークレット名、および汎用シークレットファイル名が固有であり、以降のコマンドにリンクされています。scripts/seal-secrets.sh スクリプトを理解していない場合は、これらの値を変更しないでください。

    このプロジェクトを使用するために必要な固有のシークレットが 2 つあります。

    • Confluent Cloud リソースを管理するには、ccloud CLI ログイン認証情報を使用します。以下を含むファイルを作成します。

      CCLOUD_EMAIL=your-ccloud-email
      CCLOUD_PASSWORD=your-ccloud-password
      

      このファイルは、リポジトリにコミットしたり、他のシークレットと同様に保護したりしないでください。次の kubectl create secret コマンドを実行して、作成したばかりの ccloud 認証情報ファイルへのパスを --from-env-file 引数で渡します。

      kubectl create secret generic cc.ccloud-secrets --namespace=default --from-env-file=<path-to-your-file> --dry-run=client -o yaml > secrets/local-toseal/dev/default-cc.ccloud-secrets.yaml
      
    • プロジェクトに含まれるマイクロサービスは、MySQL データベースを使用して、Connect と変更データキャプチャーのデモを示します。データベース用の認証情報は、Kubernetes クラスター内にシークレットとして作成する必要があります。サンプル secrets/example-connect-operator-secrets.props には、このファイルのレイアウトの例があります。データベースの認証情報ファイルの個人用コピーを作成する必要はありません。サービス全体が Kubernetes クラスターの内部で実行されており、一般には公開されないためです。したがって、提供されたサンプルファイルを使用できます。

      kubectl create secret generic connect-operator-secrets --namespace=default --from-env-file=./secrets/example-connect-operator-secrets.props --dry-run=client -o yaml > secrets/local-toseal/dev/default-connect-operator-secrets.yaml
      

    上記のコマンドにより、プレーンテキストのシークレットファイルから汎用 Kubernetes シークレットマニフェストが作成され、ステージングエリア(secrets/local-toseal/dev)に配置されます。このシークレットを、次の make ターゲットでシーリングします。このターゲットが scripts/seal-secrets.sh スクリプトを使用します。このコマンドにより、シーリングされたシークレットが secrets/sealed/dev に配置され、これらのファイルは安全に Git リポジトリにコミットできます。さらにこのコマンドにより、シーリングが解除されたシークレットファイルがステージングエリア(secrets/local-toseal/dev)から削除されます。

    make seal-secrets-dev
    

    次のように表示されます。

    Sealing-secrets-----------------------------------
    ➜ ./scripts/seal-secrets.sh dev
    INFO - Successfully sealed secrets/local-toseal/dev/default-cc.ccloud-secrets.yaml
    INFO - Successfully sealed secrets/local-toseal/dev/default-connect-operator-secrets.yaml
    

    これで、シーリングされたシークレットをリポジトリにコミットでき、Flux がそれを Kubernetes クラスターに同期できるようになります。

    git add secrets/sealed/dev/.
    git commit -m 'New secrets!'
    git push origin main # (or to the appropriate branch if you are doing GitOps by PR already!)
    

FluxCD のインストール

  1. シークレットをシーリングし、リポジトリにコミットしたので、FluxCD を Kubernetes クラスター内にインストールします。

    make install-flux-dev
    

    この make ターゲットは、scripts/flux-init.sh スクリプトを使用して FluxCD をクラスター内にインストールします。GitOps ベースの継続的なデリバリーが円滑に行われるよう、FluxCD が Git リポジトリにアクセス可能である必要があります。インストール後に FluxCD は、構成済みの GitHub リポジトリに正常に接続できるまで待機しています。スクリプトにより、FluxCD が生成したデプロイキーが出力されます。このデプロイキーを、Settings->Deploy キーの下のフォークされた GitHub リポジトリに追加して、キーがリポジトリに書き込みアクセスを実行できるようにします。

    注釈

    Flux が同期済み状態を制御するタグを管理するには、書き込みアクセス権が必要です。詳細については、Flux のドキュメント を参照してください。

    FluxCD と GitHub リポジトリの間の同期が適切にセットアップされている場合は、デプロイキー構成後に、 make install-flux-dev コマンドからの出力が、次のように表示されます。

    >>> Github deploy key is ready
    >>> Cluster bootstrap done!
    
  2. FluxCD が、Kubernetes リソースのデプロイを開始します。使用している Kubernetes クラスターとネットワーク帯域幅に応じて、FluxCD がこの作業を完了するまでに最大で 10 分かかります。このスタートアップ期間の後に、以下のコマンドでアプリケーションがデプロイされたことを検証します。これにより、default 名前空間にデプロイされたさまざまな Kubernetes リソースが表示されます。

    kubectl get all
    

    実行すると、次のように表示されます。

    NAME                                                  READY   STATUS      RESTARTS   AGE
    pod/add-inventory-1599062700-x98dd                    0/1     Completed   0          3m29s
    pod/ccloud-operator                                   1/1     Running     0          44h
    pod/connect-operator                                  1/1     Running     0          46h
    pod/connect-service-66b8988b6d-j2fgq                  1/1     Running     0          47h
    pod/email-service-7457445bcb-vqzbv                    1/1     Running     0          26h
    pod/fraud-service-7dbdb87689-hzhpk                    1/1     Running     0          27h
    pod/inventory-service-6c85b9769-j489p                 1/1     Running     1          27h
    pod/mysql-5f97b96f84-xp6gs                            1/1     Running     0          4d18h
    pod/order-details-service-68fb4bd656-whwff            1/1     Running     0          27h
    pod/orders-and-payments-simulator-fb9ccbc75-6bsww     1/1     Running     1          26h
    pod/orders-service-754d77d5c5-szksg                   1/1     Running     0          43h
    pod/validations-aggregator-service-6f8f5ddb9d-cjss2   1/1     Running     3          26h
    
    NAME                     TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
    service/connect          ClusterIP   10.66.4.37   <none>        80/TCP     4d18h
    service/kubernetes       ClusterIP   10.66.0.1    <none>        443/TCP    5d1h
    service/mysql            ClusterIP   None         <none>        3306/TCP   4d18h
    service/orders-service   ClusterIP   10.66.6.78   <none>        80/TCP     46h
    
    NAME                                             READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/connect-service                  1/1     1            1           4d18h
    deployment.apps/email-service                    1/1     1            1           26h
    deployment.apps/fraud-service                    1/1     1            1           27h
    deployment.apps/inventory-service                1/1     1            1           27h
    deployment.apps/mysql                            1/1     1            1           4d18h
    deployment.apps/order-details-service            1/1     1            1           27h
    deployment.apps/orders-and-payments-simulator    1/1     1            1           26h
    deployment.apps/orders-service                   1/1     1            1           46h
    deployment.apps/validations-aggregator-service   1/1     1            1           26h
    
    NAME                                                        DESIRED   CURRENT   READY   AGE
    replicaset.apps/connect-service-66b8988b6d                  1         1         1       4d18h
    replicaset.apps/email-service-7457445bcb                    1         1         1       26h
    ...
    replicaset.apps/validations-aggregator-service-6f8f5ddb9d   1         1         1       26h
    replicaset.apps/validations-aggregator-service-7557d6cc48   0         0         0       26h
    
    NAME                                 COMPLETIONS   DURATION   AGE
    job.batch/add-inventory-1599062700   1/1           5s         3m29s
    
    NAME                          SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
    cronjob.batch/add-inventory   */5 * * * *   False     0        3m38s           43h
    

    セットアッププロセスで問題が発生した場合は、「トラブルシューティング」セクションを参照してください。

使用事例

streaming-ops プロジェクトは、さまざまなユースケースのリファレンスとして使用できます。以下の使用事例では、Confluent Cloud をターゲットとする場合に、ユーザー独自の本稼働環境で実行する必要がある一般的な DevOps タスクを調べます。

ヒント

  • FluxCD は、1 分間に一度、Git リポジトリと同期するように構成されています。リポジトリに変更を加えた場合は、コマンドで強制的に同期することができます。

    make sync
    
  • make ターゲット prompt を使用して、開発ツールが事前に搭載されたユーティリティポッド上の Kubernetes クラスター内のターミナルを開くことができます。これは、クラスターの内部から、サービスやリソースと対話する場合に役立つことがあります。たとえば、デプロイした Kafka コネクターのステータスを表示することができます。

    make prompt
    
    bash-5.0# curl -s http://connect/connectors/jdbc-customers/status | jq
    {
      "name": "jdbc-customers",
      "connector": {
        "state": "RUNNING",
        "worker_id": "10.0.2.8:8083"
      },
      "tasks": [
        {
          "id": 0,
          "state": "RUNNING",
          "worker_id": "10.0.2.8:8083"
        }
      ],
      "type": "source"
    }
    

トラブルシューティング

  • k3d ローカル Kubernetes クラスターの使用時に、使用説明の make cluster 手順でエラーが発生する場合があります。これらのエラーは、多くの場合、ホストマシン上で Docker イメージに割り当てられたスペースが不十分であるために発生しています。この手順でエラーが発生した場合は、Docker がインストールされたマシンに十分な空きスペースがあることを確認した後、make cluster コマンドを再度実行してください。