# 在 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` 驗證目標是否**正在被抓取**

3. Alertmanager
```
oc port-forward -n ns1-coo pod/alertmanager-example-coo-monitoring-stack-0 9093
```
4. `http://localhost:9093/#/alerts`,來驗證目標警報是否正在觸發

## 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)