Spring Cloud Kubernetes 構成ウォッチャー

ただし、アプリケーションを再起動しない限り、Spring Boot はこれらの変更を自動的にリフレッシュしません。Spring Cloud は、アクチュエーターエンドポイント /refresh をヒットするか、Spring Cloud Bus を使用して RefreshRemoteApplicationEvent をパブリッシュすることにより、アプリケーションを再起動せずにアプリケーションコンテキストをリフレッシュする機能を提供します。

Kubernetes 上で実行されている Spring Cloud アプリの構成をリフレッシュするには、Spring Cloud Kubernetes Configuration Watcher コントローラーを Kubernetes クラスターにデプロイします。

GitHub のソースコード (英語) から Docker イメージを構築し、それを使用して Kubernetes にデプロイできます。

これを設定するもう 1 つのオプションは、構成ウォッチャーをデプロイするために使用される デプロイ .yaml にいくつかの環境変数を提供することです。重要なものをいくつか示します。

env:
  - name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_CONFIGURATION_WATCHER
    value: DEBUG
  - name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_CLIENT_CONFIG_RELOAD
    value: DEBUG
  - name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_COMMONS_CONFIG_RELOAD
    value: DEBUG

これらは、構成ウォッチャーでのデバッグログ記録を有効にし、潜在的な構成ミスを診断できるようにするために、初期セットアップで特に役立ちます。

env:
  - name: SPRING_CLOUD_KUBERNETES_RELOAD_NAMESPACES_0
    value: "namespace-a"

これにより、ウォッチャーはシークレットと構成マップを検索する場所を認識できます。ここでは、選択的な名前空間 (上記の設定) と名前空間の解決によって選択された名前空間 (これがデフォルトのオプション) の 2 つのオプションがあります。これらすべてのオプションには適切な RBAC ルールが必要であることに注意してください。

デフォルトでは、Configuration Watcher は、ラベルが ConfigMaps のみを監視します。

spring.cloud.kubernetes.config: "true"

デフォルトでは、シークレットは監視されません。シークレットの監視を有効にするには、以下を設定してください。

env:
  - name: SPRING_CLOUD_KUBERNETES_SECRETS_ENABLED
    value: "TRUE"

有効化すると、ラベルが " spring.cloud.kubernetes.secret: "true" " のシークレットのみが監視対象となります。

これらのラベルセレクターは、Configuration Watcher アプリケーション自体でカスタマイズできます。

spring:
  cloud:
    kubernetes:
      reload:
        config-maps-labels:
          my-configmap-label: "my-configmap-value"
        secrets-labels:
          my-secret-label: "my-secret-value"

または、ウォッチャーデプロイの環境変数経由:

env:
  - name: SPRING_CLOUD_KUBERNETES_RELOAD_CONFIG_MAPS_LABELS_MY_CONFIGMAP_LABEL
    value: "my-configmap-value"
  - name: SPRING_CLOUD_KUBERNETES_RELOAD_SECRETS_LABELS_MY_SECRET_LABEL
    value: "my-secret-value"

特にボリュームとしてマウントされる configmaps とシークレット (spring.config.import 経由) の場合、もう 1 つの重要な構成は次のとおりです。

- name: SPRING_CLOUD_KUBERNETES_CONFIGURATION_WATCHER_REFRESHDELAY
  value: "10000"

これは、構成ウォッチャーからイベントを発行する前に何ミリ秒待つ必要があるかを示します。Kubernetes のドキュメントには次のように記載されているため、これは重要です。

ボリュームで現在使用されている ConfigMap が更新されると、投影されたキーも最終的に更新されます。

この最終部分をクラスター上のミリ秒単位の値に「一致」させる必要があります。

Spring Cloud Kubernetes Configuration Watcher は、2 つの方法でリフレッシュ通知をアプリケーションに送信できます。

  1. HTTP 経由の場合、通知を受けるアプリケーションは、/refresh アクチュエーターエンドポイントを公開し、クラスタ内からアクセスできるようにする必要があります。

  2. Spring Cloud Bus を使用する場合、アプリケーションが使用するメッセージブローカーをクラスターにデプロイする必要があります。

デプロイ YAML

以下は、Kubernetes Configuration Watcher を Kubernetes にデプロイするために使用できるサンプルデプロイ YAML です。

---
apiVersion: v1
kind: List
items:
  - apiVersion: v1
    kind: Service
    metadata:
      labels:
        app: spring-cloud-kubernetes-configuration-watcher
      name: spring-cloud-kubernetes-configuration-watcher
    spec:
      ports:
        - name: http
          port: 8888
          targetPort: 8888
      selector:
        app: spring-cloud-kubernetes-configuration-watcher
      type: ClusterIP
  - apiVersion: v1
    kind: ServiceAccount
    metadata:
      labels:
        app: spring-cloud-kubernetes-configuration-watcher
      name: spring-cloud-kubernetes-configuration-watcher
  - apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      labels:
        app: spring-cloud-kubernetes-configuration-watcher
      name: spring-cloud-kubernetes-configuration-watcher:view
    roleRef:
      kind: Role
      apiGroup: rbac.authorization.k8s.io
      name: namespace-reader
    subjects:
      - kind: ServiceAccount
        name: spring-cloud-kubernetes-configuration-watcher
  - apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      namespace: default
      name: namespace-reader
    rules:
      - apiGroups: ["", "extensions", "apps"]
        resources: ["configmaps", "pods", "services", "endpoints", "secrets"]
        verbs: ["get", "list", "watch"]
  - apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: spring-cloud-kubernetes-configuration-watcher-deployment
    spec:
      selector:
        matchLabels:
          app: spring-cloud-kubernetes-configuration-watcher
      template:
        metadata:
          labels:
            app: spring-cloud-kubernetes-configuration-watcher
        spec:
          serviceAccount: spring-cloud-kubernetes-configuration-watcher
          containers:
          - name: spring-cloud-kubernetes-configuration-watcher
            image: springcloud/spring-cloud-kubernetes-configuration-watcher:5.0.2
            imagePullPolicy: IfNotPresent
            readinessProbe:
              httpGet:
                port: 8888
                path: /actuator/health/readiness
            livenessProbe:
              httpGet:
                port: 8888
                path: /actuator/health/liveness
            ports:
            - containerPort: 8888

サービスアカウントと関連するロールバインディングは、Spring Cloud Kubernetes 構成が適切に動作するために重要です。コントローラーは、Kubernetes クラスター内の ConfigMaps、Pods、サービス、エンドポイント、シークレットに関するデータを読み取るためにアクセスする必要があります。

ConfigMaps と秘密の監視

有効なラベルを持つ ConfigMap または Secret に変更が加えられた場合 (上記で詳述)、Spring Cloud Kubernetes 構成ウォッチャーは ConfigMap または Secret の名前を取得し、その名前でアプリケーションに通知を送信します。ただし、これはユースケースには十分ではない可能性があります。たとえば、次のことが必要になる場合があります。

  • 構成マップを複数のアプリケーションにバインドして、単一の構成マップ内の変更が多くのサービスのリフレッシュをトリガーするようにします。

  • プロファイルベースのソースがアプリケーションのイベントをトリガーするようにする

そのため、指定できる追加のアノテーションがあります。

spring.cloud.kubernetes.configmap.apps または spring.cloud.kubernetes.secret.apps。これは、コンマで区切られたアプリの文字列を受け取り、このシークレット / 構成マップで変更が発生したときに通知を受け取るアプリケーションの名前を指定します。

例:

kind: ConfigMap
apiVersion: v1
metadata:
  name: example-configmap
  labels:
    spring.cloud.kubernetes.config: "true"
  annotations:
    spring.cloud.kubernetes.configmap.apps: "app-a, app-b"

HTTP の実装

デフォルトでは、HTTP 実装が使用されます。この実装が使用されている場合、Spring Cloud Kubernetes 構成ウォッチャーと ConfigMap またはシークレットの変更が発生すると、HTTP 実装は Spring Cloud Kubernetes 検出クライアントを使用して、ConfigMap またはシークレットの名前に一致するアプリケーションのすべてのインスタンスを取得し、アプリケーションのアクチュエーター /refresh エンドポイントに HTTP POST リクエストを送信します。デフォルトでは、検出クライアントに登録されているポートを使用して、POST リクエストを /actuator/refresh に送信します。

インスタンスの shutdown アクチュエーターエンドポイントを呼び出すように構成ウォッチャーを構成することもできます。これを行うには、spring.cloud.kubernetes.configuration.watcher.refresh-strategy=shutdown を設定します。

デフォルト以外の管理ポートとアクチュエーターのパス

アプリケーションがデフォルト以外のアクチュエーターパスを使用している場合、または管理エンドポイントに別のポートを使用している場合、アプリケーションの Kubernetes サービスは boot.spring.io/actuator というアノテーションを追加し、その値をアプリケーションが使用するパスとポートに設定できます。たとえば

apiVersion: v1
kind: Service
metadata:
  labels:
    app: config-map-demo
  name: config-map-demo
  annotations:
    boot.spring.io/actuator: http://:9090/myactuator/home
spec:
  ports:
    - name: http
      port: 8080
      targetPort: 8080
  selector:
    app: config-map-demo

アクチュエーターパスや管理ポートの設定を選択できるもう 1 つの方法は、spring.cloud.kubernetes.configuration.watcher.actuatorPath および spring.cloud.kubernetes.configuration.watcher.actuatorPort を設定することです。

メッセージングの実装

メッセージング実装は、Spring Cloud Kubernetes 構成ウォッチャーアプリケーションが Kubernetes にデプロイされているときに、プロファイルを bus-amqp (RabbitMQ) または bus-kafka (Kafka) に設定することで有効にできます。デフォルトでは、メッセージング実装を使用すると、構成ウォッチャーは Spring Cloud Bus を使用して RefreshRemoteApplicationEvent をすべてのアプリケーションインスタンスに送信します。これにより、アプリケーションインスタンスはインスタンスを再起動せずにアプリケーションの構成プロパティをリフレッシュします。

アプリケーションの構成プロパティをリフレッシュするために、アプリケーションインスタンスをシャットダウンするように構成することもできます。アプリケーションがシャットダウンすると、Kubernetes はアプリケーションインスタンスを再起動し、新しい構成プロパティが読み込まれます。この戦略を使用するには、spring.cloud.kubernetes.configuration.watcher.refresh-strategy=shutdown を設定します。

RabbitMQ の構成

bus-amqp プロファイルが有効になっている場合は、使用する RabbitMQ インスタンスの場所と認証に必要な資格情報を指すように Spring RabbitMQ を構成する必要があります。これは、標準の Spring RabbitMQ プロパティを設定することで実行できます。たとえば

spring:
  rabbitmq:
    username: user
    password: password
    host: rabbitmq

Kafka の設定

bus-kafka プロファイルが有効になっている場合は、使用する Kafka ブローカーインスタンスの場所を指すように Spring Kafka を構成する必要があります。これは、標準の Spring Kafka プロパティを設定することで実行できます。たとえば

spring:
  kafka:
    producer:
      bootstrap-servers: localhost:9092