1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

KongAdvent Calendar 2024

Day 21

KonnectのDataPlaneをPrometheus/Grafanaで監視する

Last updated at Posted at 2024-12-20

本記事は「Kong Advent Calendar 2024」の21日目のエントリとして、KonnectのDataPlaneをPrometheus/Grafanaで監視する方法について解説する。

基本的には以下のための手順を整理したメモとなる。

  • KonnectのDataPlaneのメトリクス取得
  • DataPlaneがProxyする通信のメトリクス取得

メトリクス取得にはPrometheusを利用し、可視化はGrafanaを利用する。
今回はKonnect向けに書いているが設定はKong Gatewayにも流用可能なので、Kong Gatewayでも同じようなことをしたい人には参考になると思う。

前提

以下の前提で構築および検証を実施する。

  • DataPlaneとPrometheusの展開先にEKSを利用
  • cert-managerは導入済み
  • Prometheus/Grafanaの構築にはPrometheus Operatorを利用
  • Prometheus/Grafanaの公開に使うIngress ControllerはContourを使用
  • KonnectのControlPlaneは作成済み

Ingress Controllerは当初Kong Ingress Controller(KIC)を利用しようと考えていたが、Konnectでの利用はUIがRead-Onlyになるなど少し制約が面倒だったので今回はContourにした。(参考:Kong Ingress Controller for Kubernetes Association

構築

Ingress Controller(Contour)の構築

この辺の手順に従ってインストールする。
Helmのリポジトリを追加する。

helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

インストールする。環境にもよるが大体1分くらいで完了する。

helm upgrade -i contour bitnami/contour -n projectcontour --create-namespace --wait 

設定値を変更したい人はこちらからvalues.yamlの値が参照できる。

インストールすると以下のIngressClassが確認できる。

$ kubectl get ingressclass contour
NAME      CONTROLLER                                         PARAMETERS   AGE
contour   projectcontour.io/projectcontour/contour-contour   <none>       5m56s

今後はこれを使ってIngressを作成する。

Prometheus/Grafanaの構築

PrometheusとGrafanaはPrometheus Operatorを使って構築する。
構築方法はHelmのリポジトリに記載があるのでこれを参考にインストールする。

リポジトリを追加する。

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

values.yamlを作成する前に、Ingressで利用するドメインを環境変数に設定する。

DOMAIN=eks.hogehoge.info

values.yamlを作成する。

cat <<EOF > ./prometheus-stack-values.yaml
alertmanager:
  ingress:
    enabled: true
    ingressClassName: contour
    annotations:
      cert-manager.io/issuer: prometheus-stack-kube-prom-self-signed-issuer
    hosts:
    - alertmanager.$DOMAIN
    tls:
    - secretName: alertmanager-general-tls
      hosts:
      - alertmanager.$DOMAIN
grafana:
  adminPassword: admin
  ingress:
    enabled: true
    ingressClassName: contour
    annotations:
      cert-manager.io/issuer: prometheus-stack-kube-prom-self-signed-issuer
    hosts:
    - grafana.$DOMAIN
    tls:
    - secretName: grafana-general-tls
      hosts:
      - grafana.$DOMAIN
  persistence:
    enabled: true
    type: statefulset
    accessModes:
    - ReadWriteOnce
    size: 20Gi
    finalizers:
    - kubernetes.io/pvc-protection
prometheusOperator:
  admissionWebhooks:
    certManager:
      enabled: true
prometheus:
  prometheusSpec:
    storageSpec:
      volumeClaimTemplate:
        spec:
          accessModes: ["ReadWriteOnce"]
          resources:
            requests:
              storage: 20Gi
  ingress:
    enabled: true
    ingressClassName: contour
    annotations:
      cert-manager.io/issuer: prometheus-stack-kube-prom-self-signed-issuer
    hosts:
    - prometheus.$DOMAIN
    tls:
    - secretName: prometheus-general-tls
      hosts:
      - prometheus.$DOMAIN
EOF

何となく分かると思うので詳細な説明は割愛するが、基本的にはcert-manager向けの設定とドメインの設定、ストレージ容量の指定をしているくらいである。
cert-managerのためのIssuerCertificateなどは自動生成されるので用意する必要はない。

インストールする。

helm upgrade -i -f prometheus-stack-values.yaml prometheus-stack prometheus-community/kube-prometheus-stack -n prometheus-stack --create-namespace --wait

指定したホスト名がIngressのADDRESSに表示されるアドレスを向くようDNSサーバ側で名前解決の設定を入れる。
設定後、PrometheusとGrafanaにアクセスするとそれぞれ画面が確認できる。
20241121161746.png

20241121161759.png

Grafanaの初期ログインユーザ名とパスワードは<helm release名>-grafanaに格納されている。
今回はvalues.yamlでパスワードにadminを設定しており、初期ユーザはadminになるので、両方adminを指定すればログイン出来る。

DataPlaneの構築

Konnectと繋ぐためのDataPlaneをデプロイする。
ブラウザからKonnectにログインし、Data Plane Nodes->New Data Plane Nodeを選択し、作成画面のPlatformKubernetesを選択する。
選択すると以下のように進行手順が表示されるので、これに従ってDataPlaneをデプロイする。
20241121163729.png

リポジトリを追加する。

kubectl create namespace kong
helm repo add kong https://charts.konghq.com
helm repo update

証明書を生成し、tls.crttls.keyという名前で保存する。
保存後にSecretを作成し、DataPlaneが証明書を参照できるようにする。

kubectl create secret tls kong-cluster-cert -n kong --cert=./tls.crt --key=./tls.key

Secretの作成が終わったら、表示されているDataPlaneのvalues.yamlを一旦ファイルに保存する。

DataPlaneのIngress設定

ここから一工夫加える。
せっかくIngressがあるので、ProxyをIngressで公開するよう設定を追加する。
通信はIngressでTLS終端してKong GatewayにはHTTPを渡すようにする(ContourだとContourのCRDであるkind: HTTPProxyを使わないとTLSのパススルーが出来ないっぽい)。
IngressでTLS終端するために自己署名証明書発行のためのIssuerCertificateを作成しapplyする。

cat <<EOF > ./proxy-cert.yaml
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: kong-konnect-dp-issuer-root
spec:
  selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: kong-konnect-dp-ca
spec:
  commonName: kong-konnect-dp-ca
  secretName: kong-konnect-dp-ca
  isCA: true
  issuerRef:
    group: cert-manager.io
    kind: Issuer
    name: kong-konnect-dp-issuer-root
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: kong-konnect-dp-issuer
spec:
  ca:
    secretName: kong-konnect-dp-ca
EOF
kubectl apply -f ./proxy-cert.yaml

このIssuerを使って自己署名証明書を作成し、Ingressリソースも作成するためにvalues.yamlに対してproxyブロックを追記する。

cat <<EOF >> ./values.yaml
proxy:
  enabled: true
  type: ClusterIP
  http:
    enabled: true
  ingress:
    enabled: true
    ingressClassName: contour
    hostname: "proxy.$DOMAIN"
    tls:
    - hosts:
      - proxy.$DOMAIN
      secretName: kong-konnect-dp-general-tls
    annotations:
      cert-manager.io/issuer: kong-konnect-dp-issuer
  tls:
    enabled: false
EOF

TLSはIngressでは使うのでproxy.ingress.tlsは設定するが、IngressでTLSを終端させた後はHTTPでProxyにアクセスするため、proxy.http.enabledtrueで、proxy.tls.enabledfalseとなる

DataPlaneの監視設定

もう少しvalues.yamlに追加設定する。
次はDataPlaneを監視するためにServiceMonitorの設定を入れる。
ServiceMonitorはPrometheus Operatorが提供するカスタムリソースであり、このリソース内で指定した条件に合致するkind: Serviceで提供されるリソースを自動的にスクレイピングしてくれるものである。
ServiceMonitorは幸いなことにvalues.yamlで値を指定すれば自動生成されるので、その設定も追加する。

cat <<EOF >> ./values.yaml
serviceMonitor:
  enabled: true
  namespace: prometheus-stack
  labels:
    release: prometheus-stack
EOF

namespaceにPrometheusがいるNamespaceを指定し、Prometheus側に検出してもらうためにラベルを設定している。
なぜこのラベルなのかは「Prometheus OperatorのServiceMonitor / PodMonitor検出ルール」という内容で以前触れているのでそちらを参照して欲しい。

DataPlaneのデプロイ

このvalues.yamlを使ってDataPlaneをデプロイする。

helm upgrade -i kong-konnect-dp kong/kong -n kong -f ./values.yaml

デプロイが完了すると以下のようにDataPlaneが見つかった旨が表示される。
20241121164522.png

作成したIngress経由でProxyにアクセスできることを確認する。

$ curl https://proxy.$DOMAIN -k
{
  "message":"no Route matched with those values",
  "request_id":"8767816cf10a442aa25ba93f36a83904"
}

Prometheus側を見ると、TargetにDataPlaneがいることが分かる。
20241122124933.png

PrometheusのExpression BrowserからKongに関連するメトリクスが取れていることも分かる。
20241122130254.png

なお、何度か試していた時に、たまにTargetにDataPlaneが出てこないことがあった。
確認するとServiceMonitorに指定したラベルが反映されていなかった(原因は不明)。
その場合はkubectl edit servicemonitor -n prometheus-stack kong-konnect-dp-kong
みたいな感じでServiceMonitorを修正し、metadata.labelsrelease: prometheus-stackを追加してあげるとよい。

Grafanaのダッシュボードの作成

メトリクスが取れていることが確認できたので、ダッシュボードを作成する。
Kong GatewayのダッシュボードはGrafanaLabsで公開されているので、新規に作成せずにここで公開されているものを使ってダッシュボードを作成する。
20241122130454.png
(図:Grafana Labsで"kong"でダッシュボードを検索した結果)

Grafanaにログインし、左サイドバーのDashboardsからNew->New dashboardをクリックする。
次にImport dashboard->Discardをクリックし、以下の新規にダッシュボードをインポートする設定に移る。
20241122130837.png

Kong Officialのダッシュボードはこちらにあり、このIDは7424なので、このIDを入力してLoadをクリックし、データソースにPrometheusを選択してImportをクリックする。
20241122131100.png

Importが完了するとダッシュボードが表示される。
ただし、今は通信を行っておらず、かつPrometheus Pluginも入れていないので見れるメトリクスは限定的であり、ほとんどがNo dataと表示される。
20241122131337.png

なお、nginxのような通信とは関係ない部分は確認可能。
20241122131420.png

なお、Proxy Podの負荷状態に関するパネルはKongのダッシュボードには用意されていない。
これに関してはPrometheus OperatorでデプロイしたGrafanaに標準でついているダッシュボード(kubernetes-mixin)を使うとCPU・メモリ利用率、帯域使用量などが確認できるので、それで代用するとよい。

image.png

DataPlaneがProxyする通信のメトリクス取得

適当に通信を行って、Proxyした通信のメトリクスが見れるかを確認する。
ServiceとRouteをAPIで作成するために、最初にKonnectのトークン、ControlPlaneのID、KonnectのAPIエンドポイントをそれぞれ環境変数に設定する。

KONNECT_TOKEN=kpat_ER1WQxxxx
CP_ID=788397a0-b6f4-4dc8-a2f8-63cc6f0c62bb
KONNECT_API=https://us.api.konghq.com/v2

curlでAPIを発行してService、Routeを作成する。なお叩いているAPIの使用はこの辺を参考にした。
最初にServiceを作成する。

curl -s -X POST \
  "${KONNECT_API}/control-planes/${CP_ID}/core-entities/services" \
  -H "Authorization: Bearer $KONNECT_TOKEN" \
  -d name=httpbin-service \
  -d url=https://httpbin.konghq.com

作成時に表示されるServiceのIDを環境変数に設定する。

SERVICE_ID=306ed63f-2022-447b-90be-2425cdafa661

Routeを作成する。

curl -s -X POST \
  "${KONNECT_API}/control-planes/${CP_ID}/core-entities/routes" \
  -H "Authorization: Bearer ${KONNECT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "httpbin-route",
    "paths": ["/httpbin"],
    "service": {
      "id": "'"${SERVICE_ID}"'"
    }
  }'

ServiceとRouteの作成が済んだらPrometheus Pluginを設定する。
ここではServiceに対して適用する。

curl -s -X POST \
  "${KONNECT_API}/control-planes/${CP_ID}/core-entities/services/${SERVICE_ID}/plugins" \
  -H "Authorization: Bearer $KONNECT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "prometheus",
    "config": {
      "status_code_metrics": true,
      "latency_metrics": true,
      "bandwidth_metrics": true,
      "upstream_health_metrics": true
     }
   }'

動作確認する。
以下のような感じで一定時間Proxyに対してアクセスする。

watch curl -s -k https://proxy.$DOMAIN/httpbin/user-agent

少し時間が経ったらPrometheusがスクレイピングしてメトリクスが見れるはずだ。
Prometheus側でメトリクスが取れることを確認する。
ここでは一例として、リクエスト数を確認してみる。
20241122164951.png

exported_service="httpbin-service"に対してのアクセスがcode="200"を返した回数が15回であることが確認できた。
Grafanaのダッシュボードの方も確認する。

20241122165242.png

今度はNo dataとならずRPSやレイテンシがグラフィカルに表示されることが確認できた。

まとめ

KonnectのDataPlaneの監視方法については公式ドキュメントには特に記載がなかったが、Helmのvalues.yamlを読み解くことでServiceMonitorを使って簡単にPrometheusの監視下に置くことが確認できた。
また公式のダッシュボードにはDataPlaneのパネルはないものの、Prometheus Operator標準のパネルで監視できることも確認できた。
今回アラートは特に設定しなかったが、必要なメトリクスが取れていることも分かったので、DataPlaneの障害時には通知を飛ばすのは難しくなさそうだ。
また、DataPlaneがProxyする通信のメトリクスも可視化できたので、こちらもアラート対象にする見込みを得ることが出来た。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?