Skip to main content

OpenShift

Description​

This connector monitors Red Hat OpenShift Container Platform and OKD 4.x clusters through the API server REST API (cluster version and updates, cluster operators, operators installed by OLM with their updates, nodes with their CPU and memory usage, Deployments and StatefulSets with their desired, available, ready, current and updated pods, DaemonSets with their scheduled, misscheduled and ready nodes, HorizontalPodAutoscalers with their minimum, maximum, current and desired pods, PersistentVolumeClaims with their phase, requested and provisioned storage, PersistentVolumes with their phase and capacity, namespaces (projects) with their phase, Jobs with their active, failed and succeeded pods (by default the Jobs without succeeded pod, see the jobFieldSelector variable), CronJobs with their running Jobs, Services with their ready, serving and terminating endpoints and their load balancer ingress points, pods with their phase and CPU and memory usage (by default the pods not Succeeded, see the podFieldSelector and podLabelSelector variables) and their containers with their state, restarts, readiness, resources and CPU utilization, machine config pools, CPU, memory, storage and object count quotas of cluster resource quotas and project resource quotas). The bearer token of a ServiceAccount bound to the cluster-reader ClusterRole must be provided as the HTTP password.

container kubernetes linux openshift

Enterprise Connector

This connector requires the Enterprise edition of MetricsHub.

Target​

Typical platforms: Red Hat OpenShift, OKD

Operating systems: Linux, other

This connector is not available for the local host (it is applicable to remote hosts only).

Prerequisites​

Leverages: OpenShift API server REST API

Technology and protocols: HTTP

Variables:

  • podFieldSelector: Field selector of the pods monitored by openshift_pod and openshift_container (Kubernetes field selector syntax, for example status.phase!=Succeeded,metadata.namespace!=openshift-monitoring). The default leaves out the pods that completed successfully (the pods of finished Jobs); set it empty to monitor every pod. (default: status.phase!=Succeeded)
  • podLabelSelector: Label selector of the pods monitored by openshift_pod and openshift_container, also applied to their resource metrics (Kubernetes label selector syntax, for example app.kubernetes.io/part-of=shop; the value goes into the request URL as it is, so write a space as +, for example environment+in+(production,qa)). Empty by default (every pod selected by podFieldSelector).
  • jobFieldSelector: Field selector of the Jobs monitored by openshift_job (Kubernetes field selector syntax; the API only supports status.successful, metadata.name and metadata.namespace on Jobs). The default keeps the Jobs that have no succeeded pod (running, failed or not started), leaving out the completed Jobs that every CronJob run creates; set it empty to monitor every Job. (default: status.successful=0)

Examples​

CLI​

metricshub HOSTNAME -t linux -c +OpenShift --https --http-port 443 -u USERNAME

metricshub.yaml​

resourceGroups:
<RESOURCE_GROUP>:
resources:
<HOSTNAME-ID>:
attributes:
host.name: <HOSTNAME> # Change with actual host name
host.type: linux
connectors: [ +OpenShift ] # Optional, to load only this connector
protocols:
http:
https: true
port: 443 # or probably something else
username: <USERNAME> # Change with actual credentials
password: <PASSWORD> # Encrypted using metricshub-encrypt
additionalConnectors:
OpenShift: # Unique ID. Use 'uses' if different from the original connector ID
uses: OpenShift # Optional - Original ID if not in key
force: true # Optional (default: true); false for auto-detection only
variables:
podFieldSelector: <VALUE> # Replace with desired value.
podLabelSelector: <VALUE> # Replace with desired value.
jobFieldSelector: <VALUE> # Replace with desired value.

Connector Activation Criteria​

The OpenShift connector will be automatically activated, and its status will be reported as OK if all the below criteria are met:

  • The HTTP Request below to the managed host succeeds:
    • get /version
    • The response body contains: gitVersion (regex)
  • The HTTP Request below to the managed host succeeds:
    • get /apis/config.openshift.io/v1/clusterversions/version
    • Request Header: ${file::httpHeader.txt}
    • The entire response (header + body) contains: 200 (regex)

Metrics​

TypeCollected MetricsSpecific Attributes
openshift_appliedclusterresourcequotaopenshift.appliedclusterquota.cpu.limit.hard
openshift.appliedclusterquota.cpu.limit.used
openshift.appliedclusterquota.cpu.request.hard
openshift.appliedclusterquota.cpu.request.used
openshift.appliedclusterquota.ephemeral_storage.limit.hard
openshift.appliedclusterquota.ephemeral_storage.limit.used
openshift.appliedclusterquota.ephemeral_storage.request.hard
openshift.appliedclusterquota.ephemeral_storage.request.used
openshift.appliedclusterquota.memory.limit.hard
openshift.appliedclusterquota.memory.limit.used
openshift.appliedclusterquota.memory.request.hard
openshift.appliedclusterquota.memory.request.used
openshift.appliedclusterquota.object_count.hard{k8s.resourcequota.resource_name="configmaps"}
openshift.appliedclusterquota.object_count.hard{k8s.resourcequota.resource_name="count/pods"}
openshift.appliedclusterquota.object_count.hard{k8s.resourcequota.resource_name="pods"}
openshift.appliedclusterquota.object_count.hard{k8s.resourcequota.resource_name="replicationcontrollers"}
openshift.appliedclusterquota.object_count.hard{k8s.resourcequota.resource_name="resourcequotas"}
openshift.appliedclusterquota.object_count.hard{k8s.resourcequota.resource_name="secrets"}
openshift.appliedclusterquota.object_count.hard{k8s.resourcequota.resource_name="services"}
openshift.appliedclusterquota.object_count.hard{k8s.resourcequota.resource_name="services.loadbalancers"}
openshift.appliedclusterquota.object_count.hard{k8s.resourcequota.resource_name="services.nodeports"}
openshift.appliedclusterquota.object_count.used{k8s.resourcequota.resource_name="configmaps"}
openshift.appliedclusterquota.object_count.used{k8s.resourcequota.resource_name="count/pods"}
openshift.appliedclusterquota.object_count.used{k8s.resourcequota.resource_name="pods"}
openshift.appliedclusterquota.object_count.used{k8s.resourcequota.resource_name="replicationcontrollers"}
openshift.appliedclusterquota.object_count.used{k8s.resourcequota.resource_name="resourcequotas"}
openshift.appliedclusterquota.object_count.used{k8s.resourcequota.resource_name="secrets"}
openshift.appliedclusterquota.object_count.used{k8s.resourcequota.resource_name="services"}
openshift.appliedclusterquota.object_count.used{k8s.resourcequota.resource_name="services.loadbalancers"}
openshift.appliedclusterquota.object_count.used{k8s.resourcequota.resource_name="services.nodeports"}
openshift.appliedclusterquota.persistentvolumeclaim_count.hard
openshift.appliedclusterquota.persistentvolumeclaim_count.used
openshift.appliedclusterquota.storage.request.hard
openshift.appliedclusterquota.storage.request.used
id
k8s.namespace.name
name
openshift.clusterquota.name
openshift.clusterquota.uid
openshift_clusteropenshift.clusterversion.status{state="degraded|failed|ok"}
openshift.clusterversion.update.available
channel
control_plane_topology
desired_version
id
k8s.cluster.name
k8s.cluster.uid
name
platform
version
openshift_clusteroperatoropenshift.clusteroperator.status{state="degraded|failed|ok"}id
name
version
openshift_clusterresourcequotaopenshift.clusterquota.cpu.limit.hard
openshift.clusterquota.cpu.limit.used
openshift.clusterquota.cpu.request.hard
openshift.clusterquota.cpu.request.used
openshift.clusterquota.ephemeral_storage.limit.hard
openshift.clusterquota.ephemeral_storage.limit.used
openshift.clusterquota.ephemeral_storage.request.hard
openshift.clusterquota.ephemeral_storage.request.used
openshift.clusterquota.memory.limit.hard
openshift.clusterquota.memory.limit.used
openshift.clusterquota.memory.request.hard
openshift.clusterquota.memory.request.used
openshift.clusterquota.object_count.hard{k8s.resourcequota.resource_name="configmaps"}
openshift.clusterquota.object_count.hard{k8s.resourcequota.resource_name="count/pods"}
openshift.clusterquota.object_count.hard{k8s.resourcequota.resource_name="pods"}
openshift.clusterquota.object_count.hard{k8s.resourcequota.resource_name="replicationcontrollers"}
openshift.clusterquota.object_count.hard{k8s.resourcequota.resource_name="resourcequotas"}
openshift.clusterquota.object_count.hard{k8s.resourcequota.resource_name="secrets"}
openshift.clusterquota.object_count.hard{k8s.resourcequota.resource_name="services"}
openshift.clusterquota.object_count.hard{k8s.resourcequota.resource_name="services.loadbalancers"}
openshift.clusterquota.object_count.hard{k8s.resourcequota.resource_name="services.nodeports"}
openshift.clusterquota.object_count.used{k8s.resourcequota.resource_name="configmaps"}
openshift.clusterquota.object_count.used{k8s.resourcequota.resource_name="count/pods"}
openshift.clusterquota.object_count.used{k8s.resourcequota.resource_name="pods"}
openshift.clusterquota.object_count.used{k8s.resourcequota.resource_name="replicationcontrollers"}
openshift.clusterquota.object_count.used{k8s.resourcequota.resource_name="resourcequotas"}
openshift.clusterquota.object_count.used{k8s.resourcequota.resource_name="secrets"}
openshift.clusterquota.object_count.used{k8s.resourcequota.resource_name="services"}
openshift.clusterquota.object_count.used{k8s.resourcequota.resource_name="services.loadbalancers"}
openshift.clusterquota.object_count.used{k8s.resourcequota.resource_name="services.nodeports"}
openshift.clusterquota.persistentvolumeclaim_count.hard
openshift.clusterquota.persistentvolumeclaim_count.used
openshift.clusterquota.storage.request.hard
openshift.clusterquota.storage.request.used
id
name
openshift.clusterquota.name
openshift.clusterquota.uid
openshift_containerk8s.container.cpu.limit.desired
k8s.container.cpu.limit.utilization
k8s.container.cpu.request.desired
k8s.container.cpu.request.utilization
k8s.container.memory.limit.desired
k8s.container.memory.request.desired
k8s.container.ready
k8s.container.restart.count
k8s.container.status.reason{state="Completed|ContainerCannotRun|ContainerCreating|CrashLoopBackOff|CreateContainerConfigError|ErrImagePull|Error|ImagePullBackOff|OOMKilled"}
k8s.container.status.state{state="running|terminated|waiting"}
id
k8s.container.name
k8s.container.status.last_terminated_reason
k8s.namespace.name
k8s.pod.name
k8s.pod.uid
name
openshift_cronjobk8s.cronjob.job.activeid
k8s.cronjob.name
k8s.cronjob.uid
k8s.namespace.name
name
openshift_daemonsetk8s.daemonset.node.current_scheduled
k8s.daemonset.node.desired_scheduled
k8s.daemonset.node.misscheduled
k8s.daemonset.node.ready
id
k8s.daemonset.name
k8s.daemonset.uid
k8s.namespace.name
name
openshift_deploymentk8s.deployment.pod.available
k8s.deployment.pod.desired
id
k8s.deployment.name
k8s.deployment.uid
k8s.namespace.name
name
openshift_hpak8s.hpa.pod.current
k8s.hpa.pod.desired
k8s.hpa.pod.max
k8s.hpa.pod.min
id
k8s.hpa.name
k8s.hpa.scaletargetref.api_version
k8s.hpa.scaletargetref.kind
k8s.hpa.scaletargetref.name
k8s.hpa.uid
k8s.namespace.name
name
openshift_jobk8s.job.pod.active
k8s.job.pod.desired_successful
k8s.job.pod.failed
k8s.job.pod.max_parallel
k8s.job.pod.successful
id
k8s.job.name
k8s.job.uid
k8s.namespace.name
name
openshift_machineconfigpoolopenshift.machineconfigpool.machine.count
openshift.machineconfigpool.machine.degraded
openshift.machineconfigpool.machine.ready
openshift.machineconfigpool.machine.unavailable
openshift.machineconfigpool.machine.updated
openshift.machineconfigpool.status{state="degraded|failed|ok"}
id
name
openshift_namespacek8s.namespace.phase{state="active|terminating"}id
k8s.namespace.name
k8s.namespace.uid
name
openshift_nodek8s.node.condition.status{k8s.node.condition.type="DiskPressure", k8s.node.condition.status="false"}
k8s.node.condition.status{k8s.node.condition.type="DiskPressure", k8s.node.condition.status="true"}
k8s.node.condition.status{k8s.node.condition.type="DiskPressure", k8s.node.condition.status="unknown"}
k8s.node.condition.status{k8s.node.condition.type="MemoryPressure", k8s.node.condition.status="false"}
k8s.node.condition.status{k8s.node.condition.type="MemoryPressure", k8s.node.condition.status="true"}
k8s.node.condition.status{k8s.node.condition.type="MemoryPressure", k8s.node.condition.status="unknown"}
k8s.node.condition.status{k8s.node.condition.type="NetworkUnavailable", k8s.node.condition.status="false"}
k8s.node.condition.status{k8s.node.condition.type="NetworkUnavailable", k8s.node.condition.status="true"}
k8s.node.condition.status{k8s.node.condition.type="NetworkUnavailable", k8s.node.condition.status="unknown"}
k8s.node.condition.status{k8s.node.condition.type="PIDPressure", k8s.node.condition.status="false"}
k8s.node.condition.status{k8s.node.condition.type="PIDPressure", k8s.node.condition.status="true"}
k8s.node.condition.status{k8s.node.condition.type="PIDPressure", k8s.node.condition.status="unknown"}
k8s.node.condition.status{k8s.node.condition.type="Ready", k8s.node.condition.status="false"}
k8s.node.condition.status{k8s.node.condition.type="Ready", k8s.node.condition.status="true"}
k8s.node.condition.status{k8s.node.condition.type="Ready", k8s.node.condition.status="unknown"}
k8s.node.cpu.allocatable
k8s.node.cpu.usage
k8s.node.ephemeral_storage.allocatable
k8s.node.memory.allocatable
k8s.node.memory.working_set
k8s.node.pod.allocatable
metricshub.host.observed
container.runtime.description
host.arch
host.name
id
k8s.cluster.name
k8s.node.name
k8s.node.uid
kernel_version
kubelet_version
name
os.description
roles
openshift_operatoropenshift.operator.status{state="degraded|failed|ok"}
openshift.operator.update.available
id
k8s.namespace.name
managed_namespaces
name
provider
version
openshift_persistentvolumek8s.persistentvolume.status.phase{state="Available|Bound|Failed|Pending|Released"}
k8s.persistentvolume.storage.capacity
id
k8s.persistentvolume.name
k8s.persistentvolume.uid
k8s.storageclass.name
name
openshift_persistentvolumeclaimk8s.persistentvolumeclaim.status.phase{state="Bound|Lost|Pending"}
k8s.persistentvolumeclaim.storage.capacity
k8s.persistentvolumeclaim.storage.request
id
k8s.namespace.name
k8s.persistentvolumeclaim.name
k8s.persistentvolumeclaim.uid
k8s.storageclass.name
name
openshift_podk8s.pod.cpu.usage
k8s.pod.memory.working_set
k8s.pod.status.phase{state="Failed|Pending|Running|Succeeded|Unknown"}
k8s.pod.status.reason{state="Evicted|NodeAffinity|NodeLost|Shutdown|UnexpectedAdmissionError"}
id
k8s.namespace.name
k8s.node.name
k8s.pod.name
k8s.pod.uid
name
openshift_resourcequotak8s.resourcequota.cpu.limit.hard
k8s.resourcequota.cpu.limit.used
k8s.resourcequota.cpu.request.hard
k8s.resourcequota.cpu.request.used
k8s.resourcequota.ephemeral_storage.limit.hard
k8s.resourcequota.ephemeral_storage.limit.used
k8s.resourcequota.ephemeral_storage.request.hard
k8s.resourcequota.ephemeral_storage.request.used
k8s.resourcequota.memory.limit.hard
k8s.resourcequota.memory.limit.used
k8s.resourcequota.memory.request.hard
k8s.resourcequota.memory.request.used
k8s.resourcequota.object_count.hard{k8s.resourcequota.resource_name="configmaps"}
k8s.resourcequota.object_count.hard{k8s.resourcequota.resource_name="count/pods"}
k8s.resourcequota.object_count.hard{k8s.resourcequota.resource_name="pods"}
k8s.resourcequota.object_count.hard{k8s.resourcequota.resource_name="replicationcontrollers"}
k8s.resourcequota.object_count.hard{k8s.resourcequota.resource_name="resourcequotas"}
k8s.resourcequota.object_count.hard{k8s.resourcequota.resource_name="secrets"}
k8s.resourcequota.object_count.hard{k8s.resourcequota.resource_name="services"}
k8s.resourcequota.object_count.hard{k8s.resourcequota.resource_name="services.loadbalancers"}
k8s.resourcequota.object_count.hard{k8s.resourcequota.resource_name="services.nodeports"}
k8s.resourcequota.object_count.used{k8s.resourcequota.resource_name="configmaps"}
k8s.resourcequota.object_count.used{k8s.resourcequota.resource_name="count/pods"}
k8s.resourcequota.object_count.used{k8s.resourcequota.resource_name="pods"}
k8s.resourcequota.object_count.used{k8s.resourcequota.resource_name="replicationcontrollers"}
k8s.resourcequota.object_count.used{k8s.resourcequota.resource_name="resourcequotas"}
k8s.resourcequota.object_count.used{k8s.resourcequota.resource_name="secrets"}
k8s.resourcequota.object_count.used{k8s.resourcequota.resource_name="services"}
k8s.resourcequota.object_count.used{k8s.resourcequota.resource_name="services.loadbalancers"}
k8s.resourcequota.object_count.used{k8s.resourcequota.resource_name="services.nodeports"}
k8s.resourcequota.persistentvolumeclaim_count.hard
k8s.resourcequota.persistentvolumeclaim_count.used
k8s.resourcequota.storage.request.hard
k8s.resourcequota.storage.request.used
id
k8s.namespace.name
k8s.resourcequota.name
k8s.resourcequota.uid
name
openshift_servicek8s.service.endpoint.count{k8s.service.endpoint.condition="ready", k8s.service.endpoint.address_type="FQDN"}
k8s.service.endpoint.count{k8s.service.endpoint.condition="ready", k8s.service.endpoint.address_type="IPv4"}
k8s.service.endpoint.count{k8s.service.endpoint.condition="ready", k8s.service.endpoint.address_type="IPv6"}
k8s.service.endpoint.count{k8s.service.endpoint.condition="serving", k8s.service.endpoint.address_type="FQDN"}
k8s.service.endpoint.count{k8s.service.endpoint.condition="serving", k8s.service.endpoint.address_type="IPv4"}
k8s.service.endpoint.count{k8s.service.endpoint.condition="serving", k8s.service.endpoint.address_type="IPv6"}
k8s.service.endpoint.count{k8s.service.endpoint.condition="terminating", k8s.service.endpoint.address_type="FQDN"}
k8s.service.endpoint.count{k8s.service.endpoint.condition="terminating", k8s.service.endpoint.address_type="IPv4"}
k8s.service.endpoint.count{k8s.service.endpoint.condition="terminating", k8s.service.endpoint.address_type="IPv6"}
k8s.service.load_balancer.ingress.count
id
k8s.namespace.name
k8s.service.name
k8s.service.type
k8s.service.uid
name
openshift_statefulsetk8s.statefulset.pod.current
k8s.statefulset.pod.desired
k8s.statefulset.pod.ready
k8s.statefulset.pod.updated
id
k8s.namespace.name
k8s.statefulset.name
k8s.statefulset.uid
name