これは、なにをしたくて書いたもの?
以前、PrometheusをOKD(Kubernetes)にデプロイしてみました。
OKD/Minishift上に、Prometheusをデプロイしてみる - CLOVER🍀
こちらは、とにかくPrometheusをOKD(Kubernetes)上で動かすことだけを目標にしていましたが、今回は特定のPodといった
対象を絞り込んでのメトリクス収集にフォーカスしたいと思います。
NodeやKubernetes自体の情報ではなく、その上で自分でデプロイして動かしているリソースにフォーカスしてみようかなと。
環境
今回の環境は、こちらです。
$ minishift version minishift v1.33.0+ba29431 $ oc version oc v3.11.0+0cbc58b kubernetes v1.11.0+d4cacc0 features: Basic-Auth GSSAPI Kerberos SPNEGO Server https://192.168.42.27:8443 kubernetes v1.11.0+d4cacc0
こちらに、簡単なサンプルアプリケーションを作成してデプロイし、そのPodに絞ってメトリクスを収集することを考えたいと
思います。もちろん、Prometheusもデプロイします。
サンプルアプリケーション
では、まずはサンプルアプリケーションを作成します。Node.jsで作成することにしましょう。
Node.js用のPrometheusクライアントライブラリ、Expressを利用。
$ npm i prom-client express
バージョン。
"dependencies": { "express": "^4.16.4", "prom-client": "^11.3.0" }
エンドポイントは、メトリクスを返すものと、ホスト名を返すものの2つを用意します。簡単に。
server.js
const os = require('os'); const prometheusClient = require("prom-client"); const collectDefaultMetrics = prometheusClient.collectDefaultMetrics; collectDefaultMetrics({ timeout: 5000 }); const exporess = require("express"); const app = exporess(); app.get("/metrics", (req, res) => { res.set("Content-Type", "text/plain"); res.send(prometheusClient.register.metrics()); }); app.get("/node", (req, res) => { res.send(`this server name = ${os.hostname()}`); }); app.listen(8080, () => console.log(`[${new Date()}] server startup.`));
package.jsonでの指定。
"scripts": { "start": "node server.js", "test": "echo \"Error: no test specified\" && exit 1" },
こちらを適当なGitリポジトリに登録して、OKDにデプロイ。
$ oc new-app --name pod-discovery [GitリポジトリのURL] $ oc expose svc pod-discovery $ oc get all NAME READY STATUS RESTARTS AGE pod/pod-discovery-1-build 0/1 Completed 0 1m pod/pod-discovery-1-hshmv 1/1 Running 0 20s NAME DESIRED CURRENT READY AGE replicationcontroller/pod-discovery-1 1 1 1 22s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/pod-discovery ClusterIP 172.30.8.236 <none> 8080/TCP 1m NAME REVISION DESIRED CURRENT TRIGGERED BY deploymentconfig.apps.openshift.io/pod-discovery 1 1 1 config,image(pod-discovery:latest) NAME TYPE FROM LATEST buildconfig.build.openshift.io/pod-discovery Source Git 1 NAME TYPE FROM STATUS STARTED DURATION build.build.openshift.io/pod-discovery-1 Source Git@baa3367 Complete About a minute ago 39s NAME DOCKER REPO TAGS UPDATED imagestream.image.openshift.io/pod-discovery 172.30.1.1:5000/myproject/pod-discovery latest 23 seconds ago NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD route.route.openshift.io/pod-discovery pod-discovery-myproject.192.168.42.27.nip.io pod-discovery 8080-tcp None
確認。
$ curl pod-discovery-myproject.192.168.42.27.nip.io/node this server name = pod-discovery-1-hshmv $ curl pod-discovery-myproject.192.168.42.27.nip.io/metrics # HELP process_cpu_user_seconds_total Total user CPU time spent in seconds. # TYPE process_cpu_user_seconds_total counter process_cpu_user_seconds_total 0.093472 1554361868786 # HELP process_cpu_system_seconds_total Total system CPU time spent in seconds. # TYPE process_cpu_system_seconds_total counter process_cpu_system_seconds_total 0.021420999999999996 1554361868786 # HELP process_cpu_seconds_total Total user and system CPU time spent in seconds. # TYPE process_cpu_seconds_total counter process_cpu_seconds_total 0.11489300000000001 1554361868786 # HELP process_start_time_seconds Start time of the process since unix epoch in seconds. # TYPE process_start_time_seconds gauge process_start_time_seconds 1554361794 # HELP process_resident_memory_bytes Resident memory size in bytes. # TYPE process_resident_memory_bytes gauge process_resident_memory_bytes 27590656 1554361868787 〜省略〜
これで、アプリケーションの準備はおしまいです。
Prometheusをデプロイする
続いて、PrometheusをOKDにデプロイします。
Service Account、ClusterRole、ClusterRoleBindingを作成。今回は、先ほど作成したPodのみにアクセスするため、ClusterRoleで
扱うリソースは絞っています。
rbac.yml
--- ## ServiceAccount apiVersion: v1 kind: ServiceAccount metadata: name: prometheus-sa namespace: myproject --- ## ClusterRole apiVersion: v1 kind: ClusterRole metadata: name: prometheus-cr rules: - apiGroups: [""] resources: - pods verbs: ["get", "list", "watch"] - nonResourceURLs: ["/metrics"] verbs: ["get"] --- ## ClusterRoleBinding apiVersion: v1 kind: ClusterRoleBinding metadata: name: prometheus roleRef: kind: ClusterRole name: prometheus-cr subjects: - kind: ServiceAccount name: prometheus-sa namespace: myproject
Prometheusに関するリソース定義。
resources.yml
--- ## ImageStream apiVersion: v1 kind: ImageStream metadata: labels: app: prometheus name: prometheus spec: lookupPolicy: local: false tags: - from: kind: DockerImage name: prom/prometheus:v2.8.1 importPolicy: {} name: v2.8.1 referencePolicy: type: Source --- ## DeploymentConfig apiVersion: v1 kind: DeploymentConfig metadata: labels: app: prometheus name: prometheus spec: replicas: 1 selector: app: prometheus deploymentconfig: prometheus strategy: type: Rolling template: metadata: labels: app: prometheus deploymentconfig: prometheus spec: serviceAccountName: prometheus-sa containers: - image: prom/prometheus:v2.8.1 imagePullPolicy: IfNotPresent name: prometheus ports: - containerPort: 9090 protocol: TCP resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - name: config-volume mountPath: /etc/prometheus - name: prometheus-volume-1 mountPath: /prometheus restartPolicy: Always securityContext: {} terminationGracePeriodSeconds: 30 volumes: - name: config-volume configMap: name: prometheus-config - emptyDir: {} name: prometheus-volume-1 triggers: - type: ConfigChange - imageChangeParams: automatic: true containerNames: - prometheus from: kind: ImageStreamTag name: prometheus:v2.8.1 type: ImageChange --- ## ConfigMap apiVersion: v1 kind: ConfigMap metadata: labels: app: prometheus name: prometheus-config data: prometheus.yml: | global: scrape_interval: 10s evaluation_interval: 10s scrape_configs: # pod - job_name: 'kubernetes-pods' kubernetes_sd_configs: - role: pod relabel_configs: # 「__meta_kubernetes_pod_label_」以降をlabelとして追加する - action: labelmap regex: __meta_kubernetes_pod_label_(.+) # 「__meta_kubernetes_namespace」の値をlabel「kubernetes_namespace」として追加する - source_labels: [__meta_kubernetes_namespace] action: replace target_label: kubernetes_namespace # 「__meta_kubernetes_pod_name」の値をlabel「kubernetes_pod_name」として追加する - source_labels: [__meta_kubernetes_pod_name] action: replace target_label: kubernetes_pod_name --- ## Service apiVersion: v1 kind: Service metadata: labels: app: prometheus name: prometheus spec: ports: - name: 9090-tcp port: 9090 protocol: TCP targetPort: 9090 selector: app: prometheus deploymentconfig: prometheus sessionAffinity: None type: ClusterIP --- ## Route apiVersion: v1 kind: Route metadata: labels: app: prometheus name: prometheus spec: port: targetPort: 9090-tcp to: kind: Service name: prometheus weight: 100 wildcardPolicy: None
設定は、ConfigMapで行います。Scrapeするのは、Podだけにしています。
scrape_configs: # pod - job_name: 'kubernetes-pods' kubernetes_sd_configs: - role: pod relabel_configs: # 「__meta_kubernetes_pod_label_」以降をlabelとして追加する - action: labelmap regex: __meta_kubernetes_pod_label_(.+) # 「__meta_kubernetes_namespace」の値をlabel「kubernetes_namespace」として追加する - source_labels: [__meta_kubernetes_namespace] action: replace target_label: kubernetes_namespace # 「__meta_kubernetes_pod_name」の値をlabel「kubernetes_pod_name」として追加する - source_labels: [__meta_kubernetes_pod_name] action: replace target_label: kubernetes_pod_name
これらを適用していきます。RBAC関連のみ、adminで作成します。
$ oc apply -f rbac.yml --as system:admin $ oc apply -f resources.yml
Routeも作っているので、PrometheusのWeb UIを見ることができます。
試しに、upメトリクスを見てみましょう。
Podが大量に並びます。
ではここで、先ほど作成したアプリケーションのみを対象とするようにrelabel_configsを設定してみます。
scrape_configs: # pod - job_name: 'kubernetes-pods' kubernetes_sd_configs: - role: pod relabel_configs: # 「__meta_kubernetes_pod_label_」以降をlabelとして追加する - action: labelmap regex: __meta_kubernetes_pod_label_(.+) # 「__meta_kubernetes_namespace」の値をlabel「kubernetes_namespace」として追加する - source_labels: [__meta_kubernetes_namespace] action: replace target_label: kubernetes_namespace # 「__meta_kubernetes_pod_name」の値をlabel「kubernetes_pod_name」として追加する - source_labels: [__meta_kubernetes_pod_name] action: replace target_label: kubernetes_pod_name # 「__meta_kubernetes_pod_label_app」labelがregexで指定されたもののみ残す # 前述のlabelmapでlabelを変換しているので、「app」でも可 - source_labels: [__meta_kubernetes_pod_label_app] # - source_labels: [app] action: keep regex: pod-discovery
この部分ですね。「app」Label、もしくは「__meta_kubernetes_pod_label_app」Labelが「pod-discovery」のもののみ残します。
# 「__meta_kubernetes_pod_label_app」labelがregexで指定されたもののみ残す # 前述のlabelmapでlabelを変換しているので、「app」でも可 - source_labels: [__meta_kubernetes_pod_label_app] # - source_labels: [app] action: keep regex: pod-discovery
適用して、Prometheusをrollout。
$ oc get all $ oc rollout latest dc/prometheus
すると、対象のPodが絞られます。
relabel_configsで絞り込むことに成功したようです。
では、Podをスケールアウトさせてみましょう。
$ oc scale dc pod-discovery --replicas=3
しばらくすると、Prometheus側でも増えたPodのメトリクスを確認することができます。
Labelで絞り込んだPodが増えても、追従してくれることが確認できました、と。
今回はOKDで「new-app」で作成する時にデフォルトで設定されるLabel「app」を使って絞り込みましたが、relabel_configsを
使って対象を柔軟に絞り込んでモニタリングしていく感じになるんでしょうね。
見る人と、利用する環境でどこまで見る?という話かな…。
とりあえず、思ったとおりの絞り込みは確認できたので、良しとしょうましょう。