18.4. PTP イベントコンシューマーアプリケーションの開発
ベアメタルクラスターノードで Precision Time Protocol (PTP) イベントを使用するコンシューマーアプリケーションを開発する場合は、コンシューマーアプリケーションと cloud-event-proxy
コンテナーを別のアプリケーション Pod にデプロイする必要があります。cloud-event-proxy
コンテナーは、PTP Operator Pod からイベントを受信し、これをコンシューマーアプリケーションに渡します。コンシューマーアプリケーションは、REST API を使用して cloud-event-proxy
コンテナーで投稿されたイベントにサブスクライブします。
PTP イベントアプリケーションのデプロイに関する詳細は、PTP 高速イベント通知フレームワークについて を参照してください。
以下の情報は、PTP イベントを使用するコンシューマーアプリケーションを開発するための一般的なガイダンスです。完全なイベントコンシューマーアプリケーションの例は、この情報の範囲外です。
18.4.1. PTP イベントコンシューマーアプリケーションのリファレンス
PTP イベントコンシューマーアプリケーションには次の機能が必要です。
-
POST
ハンドラーで実行され、クラウドネイティブ PTP イベントの JSON ペイロードを受信する Web サービス -
PTP イベントプロデューサーをサブスクライブするための
createSubscription
関数 -
PTP イベントプロデューサーの現在の状態をポーリングする
getCurrentState
関数
次の Go スニペットの例は、これらの要件を示しています。
Go での PTP イベントコンシューマーサーバー関数の例
func server() { http.HandleFunc("/event", getEvent) http.ListenAndServe("localhost:8989", nil) } func getEvent(w http.ResponseWriter, req *http.Request) { defer req.Body.Close() bodyBytes, err := io.ReadAll(req.Body) if err != nil { log.Errorf("error reading event %v", err) } e := string(bodyBytes) if e != "" { processEvent(bodyBytes) log.Infof("received event %s", string(bodyBytes)) } else { w.WriteHeader(http.StatusNoContent) } }
PTP イベントの例 Go の createSubscription 関数
import (
"github.com/redhat-cne/sdk-go/pkg/pubsub"
"github.com/redhat-cne/sdk-go/pkg/types"
v1pubsub "github.com/redhat-cne/sdk-go/v1/pubsub"
)
// Subscribe to PTP events using REST API
s1,_:=createsubscription("/cluster/node/<node_name>/sync/sync-status/os-clock-sync-state") 1
s2,_:=createsubscription("/cluster/node/<node_name>/sync/ptp-status/ptp-clock-class-change")
s3,_:=createsubscription("/cluster/node/<node_name>/sync/ptp-status/lock-state")
// Create PTP event subscriptions POST
func createSubscription(resourceAddress string) (sub pubsub.PubSub, err error) {
var status int
apiPath:= "/api/ocloudNotifications/v1/"
localAPIAddr:=localhost:8989 // vDU service API address
apiAddr:= "localhost:8089" // event framework API address
subURL := &types.URI{URL: url.URL{Scheme: "http",
Host: apiAddr
Path: fmt.Sprintf("%s%s", apiPath, "subscriptions")}}
endpointURL := &types.URI{URL: url.URL{Scheme: "http",
Host: localAPIAddr,
Path: "event"}}
sub = v1pubsub.NewPubSub(endpointURL, resourceAddress)
var subB []byte
if subB, err = json.Marshal(&sub); err == nil {
rc := restclient.New()
if status, subB = rc.PostWithReturn(subURL, subB); status != http.StatusCreated {
err = fmt.Errorf("error in subscription creation api at %s, returned status %d", subURL, status)
} else {
err = json.Unmarshal(subB, &sub)
}
} else {
err = fmt.Errorf("failed to marshal subscription for %s", resourceAddress)
}
return
}
- 1
<node_name>
を、PTP イベントを生成しているノードの FQDN に置き換えます。compute-1.example.com
はその例です。
Go の PTP イベントコンシューマー getCurrentState 関数の例
//Get PTP event state for the resource func getCurrentState(resource string) { //Create publisher url := &types.URI{URL: url.URL{Scheme: "http", Host: localhost:8989, Path: fmt.SPrintf("/api/ocloudNotifications/v1/%s/CurrentState",resource}} rc := restclient.New() status, event := rc.Get(url) if status != http.StatusOK { log.Errorf("CurrentState:error %d from url %s, %s", status, url.String(), event) } else { log.Debugf("Got CurrentState: %s ", event) } }
18.4.2. cloud-event-proxy のデプロイメントとサービス CR を参照する
PTP イベントコンシューマーアプリケーションをデプロイするときは、次の cloud-event-proxy
デプロイメントとサブスクライバサービス CR の例を参考として使用してください。
HTTP トランスポートは、PTP およびベアメタルイベントのデフォルトのトランスポートです。可能な場合、PTP およびベアメタルイベントには AMQP ではなく HTTP トランスポートを使用してください。AMQ Interconnect は、2024 年 6 月 30 日で EOL になります。AMQ Interconnect の延長ライフサイクルサポート (ELS) は 2029 年 11 月 29 日に終了します。詳細は、Red Hat AMQ Interconnect のサポートステータス を参照してください。
HTTP トランスポートを使用した cloud-event-proxy デプロイメントの参照
apiVersion: apps/v1 kind: Deployment metadata: name: event-consumer-deployment namespace: <namespace> labels: app: consumer spec: replicas: 1 selector: matchLabels: app: consumer template: metadata: labels: app: consumer spec: serviceAccountName: sidecar-consumer-sa containers: - name: event-subscriber image: event-subscriber-app - name: cloud-event-proxy-as-sidecar image: openshift4/ose-cloud-event-proxy args: - "--metrics-addr=127.0.0.1:9091" - "--store-path=/store" - "--transport-host=consumer-events-subscription-service.cloud-events.svc.cluster.local:9043" - "--http-event-publishers=ptp-event-publisher-service-NODE_NAME.openshift-ptp.svc.cluster.local:9043" - "--api-port=8089" env: - name: NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName - name: NODE_IP valueFrom: fieldRef: fieldPath: status.hostIP volumeMounts: - name: pubsubstore mountPath: /store ports: - name: metrics-port containerPort: 9091 - name: sub-port containerPort: 9043 volumes: - name: pubsubstore emptyDir: {}
AMQ トランスポートを使用した cloud-event-proxy デプロイメントの参照
apiVersion: apps/v1 kind: Deployment metadata: name: cloud-event-proxy-sidecar namespace: cloud-events labels: app: cloud-event-proxy spec: selector: matchLabels: app: cloud-event-proxy template: metadata: labels: app: cloud-event-proxy spec: nodeSelector: node-role.kubernetes.io/worker: "" containers: - name: cloud-event-sidecar image: openshift4/ose-cloud-event-proxy args: - "--metrics-addr=127.0.0.1:9091" - "--store-path=/store" - "--transport-host=amqp://router.router.svc.cluster.local" - "--api-port=8089" env: - name: <node_name> valueFrom: fieldRef: fieldPath: spec.nodeName - name: <node_ip> valueFrom: fieldRef: fieldPath: status.hostIP volumeMounts: - name: pubsubstore mountPath: /store ports: - name: metrics-port containerPort: 9091 - name: sub-port containerPort: 9043 volumes: - name: pubsubstore emptyDir: {}
cloud-event-proxy サブスクライバーサービスの参照
apiVersion: v1 kind: Service metadata: annotations: prometheus.io/scrape: "true" service.alpha.openshift.io/serving-cert-secret-name: sidecar-consumer-secret name: consumer-events-subscription-service namespace: cloud-events labels: app: consumer-service spec: ports: - name: sub-port port: 9043 selector: app: consumer clusterIP: None sessionAffinity: None type: ClusterIP
18.4.3. cloud-event-proxy サイドカー REST API から利用可能な PTP イベント
PTP イベントコンシューマーアプリケーションは、以下の PTP タイミングイベントの PTP イベントプロデューサーをポーリングできます。
リソース URI | 説明 |
---|---|
|
現在の PTP 機器のロック状態を説明します。 |
|
ホストオペレーティングシステムのクロック同期状態を説明します。 |
| PTP クロッククラスの現在の状態を説明します。 |
18.4.4. コンシューマーアプリケーションを PTP イベントにサブスクライブする
PTP イベントコンシューマーアプリケーションがイベントをポーリングできるようにするには、アプリケーションをイベントプロデューサーにサブスクライブする必要があります。
18.4.4.1. PTP lock-state イベントのサブスクライブ
PTP lock-state
イベントのサブスクリプションを作成するには、次のペイロードを使用して、http://localhost:8081/api/ocloudNotifications/v1/subscriptions
のクラウドイベント API に POST
アクションを送信します。
{ "endpointUri": "http://localhost:8989/event", "resource": "/cluster/node/<node_name>/sync/ptp-status/lock-state", }
応答の例
{ "id": "e23473d9-ba18-4f78-946e-401a0caeff90", "endpointUri": "http://localhost:8989/event", "uriLocation": "http://localhost:8089/api/ocloudNotifications/v1/subscriptions/e23473d9-ba18-4f78-946e-401a0caeff90", "resource": "/cluster/node/<node_name>/sync/ptp-status/lock-state", }
18.4.4.2. PTP os-lock-sync-state イベントのサブスクライブ
PTP os-clock-sync-state
イベントのサブスクリプションを作成するには、次のペイロードを使用して、http://localhost:8081/api/ocloudNotifications/v1/subscriptions
のクラウドイベント API に POST
アクションを送信します。
{ "endpointUri": "http://localhost:8989/event", "resource": "/cluster/node/<node_name>/sync/sync-status/os-clock-sync-state", }
応答の例
{ "id": "e23473d9-ba18-4f78-946e-401a0caeff90", "endpointUri": "http://localhost:8989/event", "uriLocation": "http://localhost:8089/api/ocloudNotifications/v1/subscriptions/e23473d9-ba18-4f78-946e-401a0caeff90", "resource": "/cluster/node/<node_name>/sync/sync-status/os-clock-sync-state", }
18.4.4.3. PTP ptp-lock-class-change イベントのサブスクライブ
PTP ptp-clock-class-change
イベントのサブスクリプションを作成するには、次のペイロードを使用して、http://localhost:8081/api/ocloudNotifications/v1/subscriptions
のクラウドイベント API に POST
アクションを送信します。
{ "endpointUri": "http://localhost:8989/event", "resource": "/cluster/node/<node_name>/sync/ptp-status/ptp-clock-class-change", }
応答の例
{ "id": "e23473d9-ba18-4f78-946e-401a0caeff90", "endpointUri": "http://localhost:8989/event", "uriLocation": "http://localhost:8089/api/ocloudNotifications/v1/subscriptions/e23473d9-ba18-4f78-946e-401a0caeff90", "resource": "/cluster/node/<node_name>/sync/ptp-status/ptp-clock-class-change", }
18.4.5. 現在の PTP クロックステータスの取得
ノードの現在の PTP ステータスを取得するには、GET
アクションを以下のイベント REST API のいずれかに送信します。
-
http://localhost:8081/api/ocloudNotifications/v1/cluster/node/<node_name>/sync/ptp-status/lock-state/CurrentState
-
http://localhost:8081/api/ocloudNotifications/v1/cluster/node/<node_name>/sync/sync-status/os-clock-sync-state/CurrentState
-
http://localhost:8081/api/ocloudNotifications/v1/cluster/node/<node_name>/sync/ptp-status/ptp-clock-class-change/CurrentState
応答はクラウドネイティブイベント JSON オブジェクトです。以下に例を示します。
ロック状態 API レスポンスの例
{ "id": "c1ac3aa5-1195-4786-84f8-da0ea4462921", "type": "event.sync.ptp-status.ptp-state-change", "source": "/cluster/node/compute-1.example.com/sync/ptp-status/lock-state", "dataContentType": "application/json", "time": "2023-01-10T02:41:57.094981478Z", "data": { "version": "v1", "values": [ { "resource": "/cluster/node/compute-1.example.com/ens5fx/master", "dataType": "notification", "valueType": "enumeration", "value": "LOCKED" }, { "resource": "/cluster/node/compute-1.example.com/ens5fx/master", "dataType": "metric", "valueType": "decimal64.3", "value": "29" } ] } }
18.4.6. PTP イベントコンシューマーアプリケーションがイベントを受信していることの確認
アプリケーション Pod の cloud-event-proxy
コンテナーが PTP イベントを受信していることを確認します。
前提条件
-
OpenShift CLI (
oc
) がインストールされている。 -
cluster-admin
権限を持つユーザーとしてログインしている。 - PTP Operator をインストールして設定している。
手順
アクティブな
linuxptp-daemon
Pod の一覧を取得します。以下のコマンドを実行します。$ oc get pods -n openshift-ptp
出力例
NAME READY STATUS RESTARTS AGE linuxptp-daemon-2t78p 3/3 Running 0 8h linuxptp-daemon-k8n88 3/3 Running 0 8h
次のコマンドを実行して、必要なコンシューマー側
cloud-event-proxy
コンテナーのメトリックにアクセスします。$ oc exec -it <linuxptp-daemon> -n openshift-ptp -c cloud-event-proxy -- curl 127.0.0.1:9091/metrics
ここでは、以下のようになります。
- <linuxptp-daemon>
問い合わせる Pod を指定します (例:
linuxptp-daemon-2t78p
)。出力例
# HELP cne_transport_connections_resets Metric to get number of connection resets # TYPE cne_transport_connections_resets gauge cne_transport_connection_reset 1 # HELP cne_transport_receiver Metric to get number of receiver created # TYPE cne_transport_receiver gauge cne_transport_receiver{address="/cluster/node/compute-1.example.com/ptp",status="active"} 2 cne_transport_receiver{address="/cluster/node/compute-1.example.com/redfish/event",status="active"} 2 # HELP cne_transport_sender Metric to get number of sender created # TYPE cne_transport_sender gauge cne_transport_sender{address="/cluster/node/compute-1.example.com/ptp",status="active"} 1 cne_transport_sender{address="/cluster/node/compute-1.example.com/redfish/event",status="active"} 1 # HELP cne_events_ack Metric to get number of events produced # TYPE cne_events_ack gauge cne_events_ack{status="success",type="/cluster/node/compute-1.example.com/ptp"} 18 cne_events_ack{status="success",type="/cluster/node/compute-1.example.com/redfish/event"} 18 # HELP cne_events_transport_published Metric to get number of events published by the transport # TYPE cne_events_transport_published gauge cne_events_transport_published{address="/cluster/node/compute-1.example.com/ptp",status="failed"} 1 cne_events_transport_published{address="/cluster/node/compute-1.example.com/ptp",status="success"} 18 cne_events_transport_published{address="/cluster/node/compute-1.example.com/redfish/event",status="failed"} 1 cne_events_transport_published{address="/cluster/node/compute-1.example.com/redfish/event",status="success"} 18 # HELP cne_events_transport_received Metric to get number of events received by the transport # TYPE cne_events_transport_received gauge cne_events_transport_received{address="/cluster/node/compute-1.example.com/ptp",status="success"} 18 cne_events_transport_received{address="/cluster/node/compute-1.example.com/redfish/event",status="success"} 18 # HELP cne_events_api_published Metric to get number of events published by the rest api # TYPE cne_events_api_published gauge cne_events_api_published{address="/cluster/node/compute-1.example.com/ptp",status="success"} 19 cne_events_api_published{address="/cluster/node/compute-1.example.com/redfish/event",status="success"} 19 # HELP cne_events_received Metric to get number of events received # TYPE cne_events_received gauge cne_events_received{status="success",type="/cluster/node/compute-1.example.com/ptp"} 18 cne_events_received{status="success",type="/cluster/node/compute-1.example.com/redfish/event"} 18 # HELP promhttp_metric_handler_requests_in_flight Current number of scrapes being served. # TYPE promhttp_metric_handler_requests_in_flight gauge promhttp_metric_handler_requests_in_flight 1 # HELP promhttp_metric_handler_requests_total Total number of scrapes by HTTP status code. # TYPE promhttp_metric_handler_requests_total counter promhttp_metric_handler_requests_total{code="200"} 4 promhttp_metric_handler_requests_total{code="500"} 0 promhttp_metric_handler_requests_total{code="503"} 0