# 在 Openshift 中設定 Cluster Observability Operator 監控一個服務 ## 0. 本篇文章 Openshift 環境資訊 - Openshift version: `4.18.22` - Cluster Observability Operator version : `1.2.2` - [安裝 Cluster Observability Operator 文件](https://hackmd.io/8tQR4UDWTB-cG20AnmWGAg?view#32-%E9%96%8B%E5%A7%8B%E5%AE%89%E8%A3%9D-Cluster-Observability-Operator) ## 1. Preface 可以透過設定由Cluster Observability Operator 所管理的監控堆疊 (monitoring stacks),來監控服務的指標 (metrics)。 若要測試監控服務,請遵循以下步驟: * 部署一個定義了 service endpoint 的範例服務。 * 建立一個 `ServiceMonitor` 物件,用以指定 COO 應如何監控該服務。 * 建立一個 `MonitoringStack` 物件來探索 (discover) 前述的 `ServiceMonitor` 物件。 ## 2. 為 Cluster Observability Operator 部署範例服務 此設定檔會在使用者自訂的 `ns1-coo` 專案中,部署一個名為 `prometheus-coo-example-app` 的範例服務。該服務會公開 (expose) 自訂的 `version` 指標。 ### 2.1. **先決條件** 您能以具備 `cluster-admin` 叢集角色的使用者身分,或是以具 `namespace` 管理權限的使用者身分存取叢集。 ### 2.2. 開始部署與設定 1. 建立並切換專案目錄 ``` mkdir sample; cd sample ``` 2. 建立一個名為 `prometheus-coo-example-app.yaml` 的 YAML 檔案,其中包含以下用於 `namespace`、`deployment` 和 `service` 的設定細節: ``` cat <<EOF > prometheus-coo-example-app.yaml apiVersion: v1 kind: Namespace metadata: name: ns1-coo --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: prometheus-coo-example-app name: prometheus-coo-example-app namespace: ns1-coo spec: replicas: 1 selector: matchLabels: app: prometheus-coo-example-app template: metadata: labels: app: prometheus-coo-example-app spec: containers: - image: ghcr.io/rhobs/prometheus-example-app:0.4.2 imagePullPolicy: IfNotPresent name: prometheus-coo-example-app --- apiVersion: v1 kind: Service metadata: labels: app: prometheus-coo-example-app name: prometheus-coo-example-app namespace: ns1-coo spec: ports: - port: 8080 protocol: TCP targetPort: 8080 name: web selector: app: prometheus-coo-example-app type: ClusterIP EOF ``` 3. 建立範例應用 ``` oc apply -f prometheus-coo-example-app.yaml ``` 4. 確認 pod 狀態是 `running` ``` oc -n ns1-coo get pods ``` 正確執行結果: ``` NAME READY STATUS RESTARTS AGE prometheus-coo-example-app-57b7fcf6c6-w7b2b 1/1 Running 0 8s ``` 好的,這段技術文件的繁體中文翻譯如下: ## 3. 指定服務如何由 Cluster Observability Operator 監控 要使用您在「為 Cluster Observability Operator 部署範例服務」一節中所建立的範例服務公開的**指標 (metrics)**,您必須設定監控元件以從 `/metrics` **端點 (endpoint)** 抓取指標。 您可以透過建立一個 `ServiceMonitor` 物件來指定如何監控服務,或建立一個 `PodMonitor` 物件來指定如何監控 Pod,以完成此設定。`ServiceMonitor` 物件需要一個 `Service` 物件,而 `PodMonitor` 物件則不需要,這讓 `MonitoringStack` 物件能夠直接從 Pod 公開的指標端點抓取指標。 此程序展示如何為 `ns1-coo` namespace 中一個名為 `prometheus-coo-example-app` 的範例服務建立 `ServiceMonitor` 物件。 ### 3.1. 先決條件 * 您需以具有 `cluster-admin` **叢集角色 (cluster role)** 的使用者身分,或具有該命名空間管理權限的使用者身分存取叢集。 * 您已安裝 Cluster Observability Operator。 * 您已在 `ns1-coo` 命名空間中部署 `prometheus-coo-example-app` 範例服務。 ### 3.2. 開始部署與設定 建立一個名為 `example-coo-app-service-monitor.yaml` 的 YAML 檔案,其中包含以下 `ServiceMonitor` 物件的設定詳細資訊: 1. 定義一個 `ServiceMonitor` 物件 > `MonitoringStack` 物件將會引用它,以抓取 (scrape) 由 `prometheus-coo-example-app` 範例服務所暴露 (exposed) 的指標資料 ``` cat <<EOF > example-coo-app-service-monitor.yaml apiVersion: monitoring.rhobs/v1 kind: ServiceMonitor metadata: labels: k8s-app: prometheus-coo-example-monitor name: prometheus-coo-example-monitor namespace: ns1-coo spec: endpoints: - interval: 30s port: web scheme: http selector: matchLabels: app: prometheus-coo-example-app EOF ``` 2. 透過執行以下指令,將此設定應用至叢集: ``` oc apply -f example-coo-app-service-monitor.yaml ``` 3. 透過執行以下指令並觀察輸出結果,來驗證 `ServiceMonitor` 資源是否已成功建立: ``` oc -n ns1-coo get servicemonitors.monitoring.rhobs ``` 執行結果: ``` NAME AGE prometheus-coo-example-monitor 77s ``` ## 4. 為 Cluster Observability Operator 建立一個 `MonitoringStack` 物件 若要抓取由目標 `prometheus-coo-example-app` 服務所暴露的指標資料,您需要建立一個 `MonitoringStack` 物件,該物件需引用您在「為 Cluster Observability Operator 指定服務的監控方式」一節中所建立的 `ServiceMonitor` 物件。接著,這個 `MonitoringStack` 物件便能發現該服務,並從中抓取其暴露的指標資料。 ### 4.1. 先決條件 * 您需以具有 `cluster-admin` 叢集角色的使用者身分,或是在該命名空間中具有管理權限的使用者身分存取叢集。 * 您已安裝叢集可觀察性 Operator (Cluster Observability Operator)。 * 您已在 `ns1-coo` 命名空間中部署了 `prometheus-coo-example-app` 範例服務。 * 您已在 `ns1-coo` 命名空間中建立了一個名為 `prometheus-coo-example-monitor` 的 `ServiceMonitor` 物件。 ### 4.2. 開始部署與設定 1. 為 `MonitoringStack` 物件的設定建立一個 YAML 檔案。在此範例中,將檔案命名為 `example-coo-monitoring-stack.yaml`。 ``` cat <<EOF > example-coo-monitoring-stack.yaml apiVersion: monitoring.rhobs/v1alpha1 kind: MonitoringStack metadata: name: example-coo-monitoring-stack namespace: ns1-coo spec: logLevel: debug retention: 1d resourceSelector: matchLabels: k8s-app: prometheus-coo-example-monitor EOF ``` 2. 加入以下 `MonitoringStack` 物件的設定詳細資訊: ``` oc apply -f example-coo-monitoring-stack.yaml ``` 3. 執行以下指令並檢視輸出,以驗證 **MonitoringStack** 物件是否可用: ``` oc -n ns1-coo get monitoringstack ``` 執行結果: ``` NAME AGE example-coo-monitoring-stack 9s ``` 4. 執行以下指令,從 Prometheus 擷取作用中目標 (active targets) 的資訊,並篩選輸出,僅列出標籤為 `app=prometheus-coo-example-app` 的目標。此舉可以驗證帶有此特定標籤的目標,確實已被 Prometheus **發現**並正在**主動監控**。 ``` oc -n ns1-coo exec -c prometheus prometheus-example-coo-monitoring-stack-0 -- curl -s 'http://localhost:9090/api/v1/targets' | jq '.data.activeTargets[].discoveredLabels | select(.__meta_kubernetes_endpoints_label_app=="prometheus-coo-example-app")' ``` 正確執行結果: ``` { "__address__": "10.247.0.35:8080", "__meta_kubernetes_endpoint_address_target_kind": "Pod", "__meta_kubernetes_endpoint_address_target_name": "prometheus-coo-example-app-57b7fcf6c6-w7b2b", "__meta_kubernetes_endpoint_node_name": "worker-3", "__meta_kubernetes_endpoint_port_name": "web", "__meta_kubernetes_endpoint_port_protocol": "TCP", "__meta_kubernetes_endpoint_ready": "true", "__meta_kubernetes_endpoints_annotation_endpoints_kubernetes_io_last_change_trigger_time": "2025-09-18T06:21:52Z", "__meta_kubernetes_endpoints_annotationpresent_endpoints_kubernetes_io_last_change_trigger_time": "true", "__meta_kubernetes_endpoints_label_app": "prometheus-coo-example-app", "__meta_kubernetes_endpoints_labelpresent_app": "true", "__meta_kubernetes_endpoints_name": "prometheus-coo-example-app", "__meta_kubernetes_namespace": "ns1-coo", "__meta_kubernetes_pod_annotation_k8s_ovn_org_pod_networks": "{\"default\":{\"ip_addresses\":[\"10.247.0.35/23\"],\"mac_address\":\"0a:58:0a:f7:00:23\",\"gateway_ips\":[\"10.247.0.1\"],\"routes\":[{\"dest\":\"10.244.0.0/14\",\"nextHop\":\"10.247.0.1\"},{\"dest\":\"10.98.0.0/16\",\"nextHop\":\"10.247.0.1\"},{\"dest\":\"169.254.0.5/32\",\"nextHop\":\"10.247.0.1\"},{\"dest\":\"100.64.0.0/16\",\"nextHop\":\"10.247.0.1\"}],\"ip_address\":\"10.247.0.35/23\",\"gateway_ip\":\"10.247.0.1\",\"role\":\"primary\"}}", "__meta_kubernetes_pod_annotation_k8s_v1_cni_cncf_io_network_status": "[{\n \"name\": \"ovn-kubernetes\",\n \"interface\": \"eth0\",\n \"ips\": [\n \"10.247.0.35\"\n ],\n \"mac\": \"0a:58:0a:f7:00:23\",\n \"default\": true,\n \"dns\": {}\n}]", "__meta_kubernetes_pod_annotation_openshift_io_scc": "restricted-v2", "__meta_kubernetes_pod_annotation_seccomp_security_alpha_kubernetes_io_pod": "runtime/default", "__meta_kubernetes_pod_annotationpresent_k8s_ovn_org_pod_networks": "true", "__meta_kubernetes_pod_annotationpresent_k8s_v1_cni_cncf_io_network_status": "true", "__meta_kubernetes_pod_annotationpresent_openshift_io_scc": "true", "__meta_kubernetes_pod_annotationpresent_seccomp_security_alpha_kubernetes_io_pod": "true", "__meta_kubernetes_pod_controller_kind": "ReplicaSet", "__meta_kubernetes_pod_controller_name": "prometheus-coo-example-app-57b7fcf6c6", "__meta_kubernetes_pod_host_ip": "10.10.7.18", "__meta_kubernetes_pod_ip": "10.247.0.35", "__meta_kubernetes_pod_label_app": "prometheus-coo-example-app", "__meta_kubernetes_pod_label_pod_template_hash": "57b7fcf6c6", "__meta_kubernetes_pod_labelpresent_app": "true", "__meta_kubernetes_pod_labelpresent_pod_template_hash": "true", "__meta_kubernetes_pod_name": "prometheus-coo-example-app-57b7fcf6c6-w7b2b", "__meta_kubernetes_pod_node_name": "worker-3", "__meta_kubernetes_pod_phase": "Running", "__meta_kubernetes_pod_ready": "true", "__meta_kubernetes_pod_uid": "275239d6-4353-4f0d-8887-4b0046efd0df", "__meta_kubernetes_service_label_app": "prometheus-coo-example-app", "__meta_kubernetes_service_labelpresent_app": "true", "__meta_kubernetes_service_name": "prometheus-coo-example-app", "__metrics_path__": "/metrics", "__scheme__": "http", "__scrape_interval__": "30s", "__scrape_timeout__": "10s", "job": "serviceMonitor/ns1-coo/prometheus-coo-example-monitor/0" } ``` ## 5. Validating the monitoring stack 若要驗證 monitoring stack 是否正常運作,請存取範例服務,然後檢視收集到的指標資料。 ### 5.1. 先決條件 * 您需以具有 `cluster-admin` 叢集角色的使用者身分,或是在該命名空間中具有管理權限的使用者身分存取叢集。 * 您已安裝叢集可觀察性 Operator (Cluster Observability Operator)。 * 您已在 `ns1-coo` 命名空間中部署了 `prometheus-coo-example-app` 範例服務。 * 您已在 `ns1-coo` 命名空間中建立了一個名為 `prometheus-coo-example-monitor` 的 `ServiceMonitor` 物件。 * 您已在 `ns1-coo` 命名空間中建立了一個名為 `example-coo-monitoring-stack` 的 `MonitoringStack` 物件。 ### 5.2. 開始驗證 1. 建立一個路由 (Route) 以暴露 (expose) `prometheus-coo-example-app` 範例服務。請在您的終端機中執行以下指令: ``` oc expose svc prometheus-coo-example-app -n ns1-coo ``` 2. 檢視 route 物件 ``` oc -n ns1-coo get route ``` 執行結果: ``` NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD prometheus-coo-example-app prometheus-coo-example-app-ns1-coo.apps.topgun.example.com prometheus-coo-example-app web None ``` 2. 透過您的瀏覽器或命令列存取此路由,以產生指標資料 ``` curl http://prometheus-coo-example-app-ns1-coo.apps.topgun.example.com; echo ``` 執行結果: ``` Hello from example application. ``` 3. 在 Prometheus Pod 上執行查詢,以回傳 HTTP 請求總數 (total HTTP requests) 的指標: ``` oc -n ns1-coo exec -c prometheus prometheus-example-coo-monitoring-stack-0 -- curl -s 'http://localhost:9090/api/v1/query?query=http_requests_total' | jq ``` 執行結果: ``` { "status": "success", "data": { "resultType": "vector", "result": [ { "metric": { "__name__": "http_requests_total", "code": "200", "endpoint": "web", "instance": "10.247.0.35:8080", "job": "prometheus-coo-example-app", "method": "get", "namespace": "ns1-coo", "pod": "prometheus-coo-example-app-57b7fcf6c6-w7b2b", "service": "prometheus-coo-example-app" }, "value": [ 1758178540.022, "5" ] }, { "metric": { "__name__": "http_requests_total", "code": "404", "endpoint": "web", "instance": "10.247.0.35:8080", "job": "prometheus-coo-example-app", "method": "get", "namespace": "ns1-coo", "pod": "prometheus-coo-example-app-57b7fcf6c6-w7b2b", "service": "prometheus-coo-example-app" }, "value": [ 1758178540.022, "0" ] } ] } } ``` ## 6. 抓取多個 namespace 中的目標 若要抓取多個命名空間中的目標,請在 `MonitoringStack` 物件中設定 namespace 與 resource selector 。 ### 6.1. 先決條件 * 您需要以具有 **`cluster-admin`** 叢集角色的使用者,或具有該 namespace **管理權限**的使用者身分存取叢集。 * 您已安裝 Cluster Observability Operator。 ### 6.2. 開始部署與設定 1. 部署以下的 namespace 與 `MonitoringStack` YAML 檔案: ``` cat <<EOF > example-coo-monitoring-stack-v2.yaml apiVersion: v1 kind: Namespace metadata: name: ns1-coo labels: monitoring.rhobs/stack: multi-ns --- apiVersion: monitoring.rhobs/v1alpha1 kind: MonitoringStack metadata: name: example-coo-monitoring-stack namespace: ns1-coo spec: logLevel: debug retention: 1d resourceSelector: matchLabels: k8s-app: prometheus-coo-example-monitor namespaceSelector: matchLabels: monitoring.rhobs/stack: multi-ns EOF ``` 2. 建立 `MonitoringStack` ``` oc apply -f example-coo-monitoring-stack-v2.yaml ``` 3. 在 `ns1-coo` 命名空間中部署一個範例應用程式,該應用程式帶有一個**持續觸發的警報**: ``` cat <<EOF > prometheus-coo-example-app-v2.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app: prometheus-coo-example-app name: prometheus-coo-example-app namespace: ns1-coo spec: replicas: 1 selector: matchLabels: app: prometheus-coo-example-app template: metadata: labels: app: prometheus-coo-example-app spec: containers: - image: ghcr.io/rhobs/prometheus-example-app:0.4.2 imagePullPolicy: IfNotPresent name: prometheus-coo-example-app --- apiVersion: v1 kind: Service metadata: labels: app: prometheus-coo-example-app name: prometheus-coo-example-app namespace: ns1-coo spec: ports: - port: 8080 protocol: TCP targetPort: 8080 name: web selector: app: prometheus-coo-example-app type: ClusterIP --- apiVersion: monitoring.rhobs/v1 kind: ServiceMonitor metadata: labels: k8s-app: prometheus-coo-example-monitor name: prometheus-coo-example-monitor namespace: ns1-coo spec: endpoints: - interval: 30s port: web scheme: http selector: matchLabels: app: prometheus-coo-example-app --- apiVersion: monitoring.rhobs/v1 kind: PrometheusRule metadata: name: example-alert namespace: ns1-coo labels: k8s-app: prometheus-coo-example-monitor spec: groups: - name: example rules: - alert: VersionAlert for: 1m expr: version{job="prometheus-coo-example-app"} > 0 labels: severity: warning EOF ``` 4. 重新部署範例應用 ``` oc apply -f prometheus-coo-example-app-v2.yaml ``` 5. 在另一個標記為 `monitoring.rhobs/stack: multi-ns` 的 namespace 中部署相同的範例應用程式: ``` cat <<EOF > prometheus-coo-example-app-ns2.yaml apiVersion: v1 kind: Namespace metadata: name: ns2-coo labels: monitoring.rhobs/stack: multi-ns --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: prometheus-coo-example-app name: prometheus-coo-example-app namespace: ns2-coo spec: replicas: 1 selector: matchLabels: app: prometheus-coo-example-app template: metadata: labels: app: prometheus-coo-example-app spec: containers: - image: ghcr.io/rhobs/prometheus-example-app:0.4.2 imagePullPolicy: IfNotPresent name: prometheus-coo-example-app --- apiVersion: v1 kind: Service metadata: labels: app: prometheus-coo-example-app name: prometheus-coo-example-app namespace: ns2-coo spec: ports: - port: 8080 protocol: TCP targetPort: 8080 name: web selector: app: prometheus-coo-example-app type: ClusterIP --- apiVersion: monitoring.rhobs/v1 kind: ServiceMonitor metadata: labels: k8s-app: prometheus-coo-example-monitor name: prometheus-coo-example-monitor namespace: ns2-coo spec: endpoints: - interval: 30s port: web scheme: http selector: matchLabels: app: prometheus-coo-example-app EOF ``` 6. 部署新的範例應用 ``` oc apply -f prometheus-coo-example-app-ns2.yaml ``` #### 4.5.3. 驗證 請驗證 **`Prometheus`** 實例已新增目標,且警報正在觸發。您可以使用**連接埠轉發 (port-forward)** 指令,來公開由 `MonitoringStack` 實例所部署的 `Prometheus` 或 `Alertmanager` 使用者介面。 1. Prometheus ``` oc port-forward -n ns1-coo pod/prometheus-example-coo-monitoring-stack-0 9090 ``` 2. 打開瀏覽器連接至 `http://localhost:9090/targets` 驗證目標是否**正在被抓取** ![image](https://hackmd.io/_uploads/S16TE4Yjge.png) 3. Alertmanager ``` oc port-forward -n ns1-coo pod/alertmanager-example-coo-monitoring-stack-0 9093 ``` 4. `http://localhost:9093/#/alerts`,來驗證目標警報是否正在觸發 ![image](https://hackmd.io/_uploads/r1tX4EKogx.png) ## 7. 參考資料 - [Configuring the Cluster Observability Operator to monitor a service - Red Hat Docs](https://docs.redhat.com/en/documentation/openshift_container_platform/4.18/html-single/cluster_observability_operator/index#configuring-the-cluster-observability-operator-to-monitor-a-service)