Kong GatewayにはOpenTelemetry Pluginが用意されていて、これを使うとアプリの改変やMeshへの追加なしで以下のようなトレースを取得することが出来る。
これを使うとレイテンシが大きい場合に以下のどこに問題があるかが確認できるようになる。
- クライアント->Kong Gateway
- Kong Gateway内
- Kong Gateway->アプリケーション
この記事はOpenTelemetry Pluginの設定方法を確認した時のメモ。
検証環境
以下の環境で検証した。
- KubernetesはEKS
- Kong Ingress Controller(KIC)は導入済み
- Kong Gatewayは構築済み
- cert-managerは導入済み
KIC、Kong Gateway、cert-managerについてはこちらの記事の内容で構築したものを利用した。
Kong Gatewayの設定変更
Kong Gatewayに設定を加えないとトレースがエンドポイントに転送されないため、最初に設定変更を行う。
OpenTelemetry Pluginのこちらの説明に従い、tracing_instrumentations
とtracing_sampling_rate
をKong Gatewayに設定する。
Helmのvalues.yamlに以下を追加してupgradeする。
env:
tracing_instrumentations: all
tracing_sampling_rate: 1.0
upgradeのコマンドは以下。
helm upgrade -i -f kong-values.yaml kong kong/kong -n kong
設定が反映されているかはKong ManagerにログインしてInfo(右上のi
)をクリックし、Config Details
のView Full Configuration
から確認できる。
Jaegerのインストール
Jaegerの構築方法はいくつかあるが、ここではJaeger Operatorで構築する。
まずJaeger Operatorをインストールする。
helm repo add jaegertracing https://jaegertracing.github.io/helm-charts
helm upgrade -i jaeger-operator jaegertracing/jaeger-operator -n observability --create-namespace --set rbac.clusterRole=true
なお、私の環境ではOperatorが以下のエラーを吐いてJaeger
リソースを作成しようとしても上手く行かなかった。
failed to list *v1.IngressClass: ingressclasses.networking.k8s.io is forbidden: User "system:serviceaccount:observability:jaeger-operator" cannot list resource "ingressclasses" in API group "networking.k8s.io" at the cluster scope
そのため以下のClusterRoleを作成し、Podを再起動した。
cat <<EOF > ./rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: jaeger-operator-ingress-class
rules:
- apiGroups: ["networking.k8s.io"]
resources: ["ingressclasses"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: jaeger-operator-ingress-class-binding
subjects:
- kind: ServiceAccount
name: jaeger-operator
namespace: observability
roleRef:
kind: ClusterRole
name: jaeger-operator-ingress-class
apiGroup: rbac.authorization.k8s.io
EOF
kubectl apply -f ./rbac.yaml
kubectl delete pod --all -n observability
Ingress
を使ったJaegerを作成するために、Issuer
で証明書を作成できるようにする。
MY_EMAIL=hogehoge@hogehoge.com
cat <<EOF > ./issuer.yaml
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
labels:
app: certmanager-issuer
chart: certmanager-issuer-0.1.0
name: jaeger-issuer
namespace: observability
spec:
acme:
email: $MY_EMAIL
privateKeySecretRef:
name: jaeger-acme-key
server: https://acme-v02.api.letsencrypt.org/directory
solvers:
- http01:
ingress:
class: kong
EOF
kubectl apply -f ./issuer.yaml
Jaeger
リソースを作成する。
MYHOST=xxx.hogehoge.com
cat <<EOF > ./jaeger.yaml
apiVersion: jaegertracing.io/v1
kind: Jaeger
metadata:
name: jaeger
namespace: observability
spec:
ingress:
hosts:
- jaeger.$MYHOST
ingressClassName: kong
enabled: true
tls:
- hosts:
- jaeger.$MYHOST
secretName: jaeger-cert
annotations:
kubernetes.io/tls-acme: "true"
cert-manager.io/issuer: "jaeger-issuer"
EOF
kubectl apply -f ./jaeger.yaml
Ingressで設定したホスト名にアクセスするとJaegerのUIが確認できる。
サンプルアプリケーションのデプロイとService/Routeの作成
次にテストに使うサンプルアプリケーション(nginx)をデプロイし、サンプルアプリに到達するためのKong GatewayのService/Routeを作成する。
なお、KICを使ってIngress
を作れば自動的にService/Routeは生成されるため、今回はIngress
の作成=Service/Routeの作成となる。
以下のManifest(Deployment
, Service
, Issuer
, Ingress
)を作成する。
Manifest(クリックして表示)
cat <<EOF > ./nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
type: ClusterIP
selector:
app: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/issuer: nginx-issuer
kubernetes.io/tls-acme: "true"
name: nginx
spec:
ingressClassName: kong
rules:
- host: nginx.eks.$MYHOST
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx
port:
number: 80
tls:
- secretName: nginx-general-tls
hosts:
- nginx.eks.$MYHOST
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: nginx-issuer
spec:
acme:
email: $MY_EMAIL
privateKeySecretRef:
name: nginx-acme-key
server: https://acme-v02.api.letsencrypt.org/directory
solvers:
- http01:
ingress:
class: kong
EOF
デプロイする。
kubectl create ns nginx-sample
kubectl apply -f ./nginx.yaml -n nginx-sample
Ingress
のホスト名にブラウザでアクセスすれば、以下のようにnginxの初期画面が確認できる。
また、Kong ManagerからService/Routeが作成されていることも確認できる。
OpenTelemetry Pluginの導入
Kong GatewayにOpenTelemetry Pluginを導入してトレースを取得・転送する。
ここではKong Managerから設定し、Pluginの対象は先程作ったRouteに限定するものとする。
先程作成されたnginxのRouteを選択し、Plugins
からNew Plugin
を選択する。
Plugin選択の画面に遷移するので、OpenTelemetry Pluginを選択する。
選択すると設定画面に遷移するので、以下の設定を入力してSave
する。
-
Endpoint
:http://jaeger-collector.observability.svc:4318/v1/traces
-
Resource Attributes
:{ "service.name": "nginx" }
Endpoint
については同一クラスタ内で展開しているので直接Service
を参照した。Ingress
のホスト名を使って参照したい場合、今回Jaeger OperatorでデプロイしたJaegerのIngress
ではOTEL用のPort(4318)向けのパスが存在していないので注意。
Resource Attributes
については後ほどJaegerでトレースを絞る際のタグみたいなものとなる。ここではAdd Config.Resource Attributes
をクリックして以下のように入力する。
以上で設定は完了となる。
動作確認
nginxに公開しているIngress
のホスト名でアクセスする。
curl -X GET https://$(kubectl get ing nginx -n nginx-sample -o jsonpath={.spec.rules[].host})
Jaegerを見てみる。
ログインするとSearch
のService
のところにOpenTelemetry Pluginのservice.name
で設定した名前のServiceが確認できる。