[Dynatrace] Envoy/Istioを使った Service Mesh アプリをDynatraceでモニタリングする（準備編）

## ＧＷの11連休？が終わった。。。
長かったＧＷも終わり、今日から仕事に復帰される方もおおいのかな？と思います。私はゴールデンウィークの長期連休とは関係なく、カレンダー通り仕事していたので、今日月曜日もいつもどおりで全く苦はないです（笑。でも、大体ゴールデンウィークは通例仕事の負荷が少し減る傾向があるので、この機会を利用して Service mesh についてまとめることにりました。ということで、今回のテーマは「Envoy/Istio Service meshアプリをDynatraceでモニタリングする」です。envoy/isto や service mesh に関する基礎知識は、世の中沢山有益な情報がありますので、ここでは細かくは触れず、直接本題に入りたいと思います。
ちょうど、本家 isitio community では、envoy/istio を使った service mesh サンプルアプリ（bookinfo application）を用意してくれていますので、それを kubernetes 上にdeployし、DynatraceのOneAgentとOpenTelemetryの両方を使ってモニタリングする方法について、まとめようと思います。

## Dynatrace で envoy をトレースしたい場合のこれまでの対応
Envoy には古くから `OpenTracing` モジュールが組み込まれていました。DynatraceではこのOpenTracingモジュールをモニタするための OneAgent code module が envoy proxy に inject されることで enovy ingress/egress トレースを可視化できていました（OneAgent v1.195でサポートされた際の[ブログ](https://www.dynatrace.com/news/blog/automatic-intelligent-observability-into-envoy-proxied-services-of-your-istio-service-mesh/)はこちらからどうぞ）ただ、時は流れ OpenTracing が OpenTelemetry へ統合されることになり、本家 envoy も [v1.30](https://www.envoyproxy.io/docs/envoy/latest/version_history/v1.28/v1.28.0#deprecated) 以降 opentracing モジュールをコードから削除することを決めました。この決定に伴い、Dynatraceの envoy trace module も envoy 1.30 以降使用できなくなりました。そのため、新しい OpenTelemetry trace API を通じて、envoy trace を見る方法が実装されるようになりました。Dynatrace community サイトでも [heads-up](https://community.dynatrace.com/t5/Container-platforms/Heads-Up-Upcoming-changes-in-Istio-Envoy-observability-Envoy-gt/m-p/232535?_gl=1*16a1zx8*_gcl_au*NDMzOTgyNjMuMTc0Njg2NDA0OA..*_ga*OTEyNjM2OTIxLjE3NDY1MTQzMzk.*_ga_1MEMV02JXV*czE3NDcwMDg3ODEkbzIxJGcxJHQxNzQ3MDEyMjgwJGowJGwwJGgw#M2120) でも、この件はアナウンスされています。
という背景もあり、このブログでは新しく実装された OpenTelemetry trace API を通じて、envoy ingress/egress trace をDynatraceへ取り込む方法を紹介します（前置きが長い。。。）

## Kubernetesにbookinfo sample applicationを構築する（準備編）
さっそく、ここからが実装編です。まずは、いつものように自身のlaptop上にKubernetes clusterを立てていきます。もちろん、お世話になるのは [RKE2](https://docs.rke2.io/) です。Dynatraceが[フルサポート](https://docs.dynatrace.com/docs/ingest-from/technology-support#kubernetes)する、Kubernetes distribution です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/afc0c7fb-b332-4c45-877e-53fd0ef209b2.png)

### 1. Kubernetesの構築
私がいつも使用している Canonical の [multipass](https://canonical.com/multipass) を使って、kubernetes 用 vm を立ち上げます。
```
yasuyuki.suzuki@DT-7PW8FY3#
❯ multipass launch --name envoy-qiita --cpus 4 --memory 8G --disk 50G --bridged
Launched: envoy-qiita

yasuyuki.suzuki@DT-7PW8FY3#
❯ multipass info envoy-qiita
Name:           envoy-qiita
State:          Running
Snapshots:      0
IPv4:           172.21.220.50
                192.168.1.18
Release:        Ubuntu 24.04.2 LTS
Image hash:     8e7d1781c14d (Ubuntu 24.04 LTS)
CPU(s):         4
Load:           0.19 0.05 0.02
Disk usage:     1.9GiB out of 48.4GiB
Memory usage:   553.7MiB out of 7.8GiB
Mounts:         --
```
次に RKE2 をこのVM上にインストールしていきます。Kubernetesのバージョンはあまり気にせず、この時点の最新版を使います。
```
ubuntu@envoy-qiita:~$ curl -sfL https://get.rke2.io | sudo sh -
[INFO]  finding release for channel stable
[INFO]  using v1.31.8+rke2r1 as release
[INFO]  downloading checksums at https://github.com/rancher/rke2/releases/download/v1.31.8%2Brke2r1/sha256sum-amd64.txt
[INFO]  downloading tarball at https://github.com/rancher/rke2/releases/download/v1.31.8%2Brke2r1/rke2.linux-amd64.tar.gz
[INFO]  verifying tarball
[INFO]  unpacking tarball file to /usr/local
ubuntu@envoy-qiita:~$ sudo systemctl enable rke2-server.service
Created symlink /etc/systemd/system/multi-user.target.wants/rke2-server.service → /usr/local/lib/systemd/system/rke2-server.service.
ubuntu@envoy-qiita:~$ sudo systemctl start rke2-server.service
ubuntu@envoy-qiita:~$ systemctl status rke2-server
● rke2-server.service - Rancher Kubernetes Engine v2 (server)
     Loaded: loaded (/usr/local/lib/systemd/system/rke2-server.service; enabled; preset: enabled)
     Active: active (running) since Mon 2025-05-12 10:44:23 JST; 11s ago
       Docs: https://github.com/rancher/rke2#readme
    Process: 2264 ExecStartPre=/bin/sh -xc ! /usr/bin/systemctl is-enabled --quiet nm-cloud-setup.service (code=exited, status=0/SUCCESS)
    Process: 2266 ExecStartPre=/sbin/modprobe br_netfilter (code=exited, status=0/SUCCESS)
    Process: 2271 ExecStartPre=/sbin/modprobe overlay (code=exited, status=0/SUCCESS)
   Main PID: 2273 (rke2)
      Tasks: 142
     Memory: 2.1G (peak: 2.1G)
        CPU: 35.737s
     CGroup: /system.slice/rke2-server.service
             ├─2273 "/usr/local/bin/rke2 server"
             ├─2292 containerd -c /var/lib/rancher/rke2/agent/etc/containerd/config.toml
             ├─2315 kubelet --volume-plugin-dir=/var/lib/kubelet/volumeplugins --file-check-frequency=5s --sync-frequency=30s --address=0.0.0.0 --anonymous-auth=false --authenticati>
             ├─2363 /var/lib/rancher/rke2/data/v1.31.8-rke2r1-2b6cfe81cbb5/bin/containerd-shim-runc-v2 -namespace k8s.io -id 346e844689ef21b0905e365ec5aaa976e6b7a6bda56fd249c99d34d3>
             ├─2368 /var/lib/rancher/rke2/data/v1.31.8-rke2r1-2b6cfe81cbb5/bin/containerd-shim-runc-v2 -namespace k8s.io -id 8696b8d0480acb361884fe85440e9b7652a98a921b504b67cdc68459>
             ├─2483 /var/lib/rancher/rke2/data/v1.31.8-rke2r1-2b6cfe81cbb5/bin/containerd-shim-runc-v2 -namespace k8s.io -id 4809311b1f33b9275a8f4cfb8fc39c6cedd45e8909d8c727687ec3eb>
             ├─2610 /var/lib/rancher/rke2/data/v1.31.8-rke2r1-2b6cfe81cbb5/bin/containerd-shim-runc-v2 -namespace k8s.io -id 45ae2b15bb230ff1da01643590a5ebe12b7af86cf81dfcb96cdf2304>
             ├─2628 /var/lib/rancher/rke2/data/v1.31.8-rke2r1-2b6cfe81cbb5/bin/containerd-shim-runc-v2 -namespace k8s.io -id f2336d80c9214256c43d33621551876756bf73746424aad2a6f4f1b1>
             ├─2762 /var/lib/rancher/rke2/data/v1.31.8-rke2r1-2b6cfe81cbb5/bin/containerd-shim-runc-v2 -namespace k8s.io -id bd422b0cfe1304e05154e3cc63b81a0122cb27210e937e07e61b023a>
             ├─3146 /var/lib/rancher/rke2/data/v1.31.8-rke2r1-2b6cfe81cbb5/bin/containerd-shim-runc-v2 -namespace k8s.io -id 0f21c0072cc6be0a91f13d4e0031c5dd814c5e3365fb763ce235e5d5>
             ├─3159 /var/lib/rancher/rke2/data/v1.31.8-rke2r1-2b6cfe81cbb5/bin/containerd-shim-runc-v2 -namespace k8s.io -id 28a13a8394074676db77dc2db252d1c8d5beb910af70bbfe7beefd8f>
             └─3409 /var/lib/rancher/rke2/data/v1.31.8-rke2r1-2b6cfe81cbb5/bin/containerd-shim-runc-v2 -namespace k8s.io -id 8411bb7296c38c3b2f5a60510037c13a2635219e64426bf85e3de8a1>

May 12 10:44:24 envoy-qiita rke2[2273]: time="2025-05-12T10:44:24+09:00" level=info msg="Updating TLS secret for kube-system/rke2-serving (count: 11): map[listener.cattle.io/cn-10.4>
May 12 10:44:25 envoy-qiita rke2[2273]: time="2025-05-12T10:44:25+09:00" level=info msg="Labels and annotations have been set successfully on node: envoy-qiita"
May 12 10:44:26 envoy-qiita rke2[2273]: time="2025-05-12T10:44:26+09:00" level=info msg="Connecting to proxy" url="wss://172.21.220.50:9345/v1-rke2/connect"
May 12 10:44:26 envoy-qiita rke2[2273]: time="2025-05-12T10:44:26+09:00" level=info msg="Started tunnel to 172.21.220.50:9345"
May 12 10:44:26 envoy-qiita rke2[2273]: time="2025-05-12T10:44:26+09:00" level=info msg="Proxy done" err="context canceled" url="wss://127.0.0.1:9345/v1-rke2/connect"
May 12 10:44:26 envoy-qiita rke2[2273]: time="2025-05-12T10:44:26+09:00" level=info msg="Stopped tunnel to 127.0.0.1:9345"
May 12 10:44:26 envoy-qiita rke2[2273]: time="2025-05-12T10:44:26+09:00" level=info msg="error in remotedialer server [400]: websocket: close 1006 (abnormal closure): unexpected EOF"
May 12 10:44:26 envoy-qiita rke2[2273]: time="2025-05-12T10:44:26+09:00" level=info msg="Handling backend connection request [envoy-qiita]"
May 12 10:44:26 envoy-qiita rke2[2273]: time="2025-05-12T10:44:26+09:00" level=info msg="Remotedialer connected to proxy" url="wss://172.21.220.50:9345/v1-rke2/connect"
May 12 10:44:31 envoy-qiita rke2[2273]: time="2025-05-12T10:44:31+09:00" level=info msg="Adding node envoy-qiita-ec75e93f etcd status condition"
```
このように、rke2-server service が `active (running)` となっていれば、OKです。あとはkube configやrke2のbinaryパスを設定していきます。
```
ubuntu@envoy-qiita:~$ mkdir -p .kube
ubuntu@envoy-qiita:~$ cd .kube/
ubuntu@envoy-qiita:~/.kube$ sudo cp /etc/rancher/rke2/rke2.yaml config
ubuntu@envoy-qiita:~/.kube$ sudo chown ubuntu:ubuntu config
ubuntu@envoy-qiita:~/.kube$ ls -la config
-rw------- 1 ubuntu ubuntu 2973 May 12 10:46 config
ubuntu@envoy-qiita:~/.kube$ 
ubuntu@envoy-qiita:~/.kube$ cd
ubuntu@envoy-qiita:~$ ln -s /var/lib/rancher/rke2/bin .
ubuntu@envoy-qiita:~$ source .profile
ubuntu@envoy-qiita:~$ which kubectl
/home/ubuntu/bin/kubectl
ubuntu@envoy-qiita:~$ kubectl version
Client Version: v1.31.8+rke2r1
Kustomize Version: v5.4.2
Server Version: v1.31.8+rke2r1
ubuntu@envoy-qiita:~$ kubectl get nodes -o wide
NAME          STATUS   ROLES                       AGE     VERSION          INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
envoy-qiita   Ready    control-plane,etcd,master   2m55s   v1.31.8+rke2r1   172.21.220.50   <none>        Ubuntu 24.04.2 LTS   6.8.0-59-generic   containerd://2.0.4-k3s2
ubuntu@envoy-qiita:~$ kubectl get pods -n kube-system
NAME                                                    READY   STATUS      RESTARTS     AGE
cloud-controller-manager-envoy-qiita                    1/1     Running     1 (3m ago)   3m1s
etcd-envoy-qiita                                        1/1     Running     0            2m18s
helm-install-rke2-canal-xq842                           0/1     Completed   0            2m57s
helm-install-rke2-coredns-xnvnm                         0/1     Completed   0            2m57s
helm-install-rke2-ingress-nginx-sbr5t                   0/1     Completed   0            2m57s
helm-install-rke2-metrics-server-qtpjl                  0/1     Completed   0            2m57s
helm-install-rke2-runtimeclasses-5wfwt                  0/1     Completed   0            2m57s
helm-install-rke2-snapshot-controller-crd-n4pq6         0/1     Completed   0            2m57s
helm-install-rke2-snapshot-controller-jnnzr             0/1     Completed   2            2m57s
kube-apiserver-envoy-qiita                              1/1     Running     0            3m2s
kube-controller-manager-envoy-qiita                     1/1     Running     0            3m2s
kube-proxy-envoy-qiita                                  1/1     Running     0            2m55s
kube-scheduler-envoy-qiita                              1/1     Running     0            3m2s
rke2-canal-hjdmc                                        2/2     Running     0            2m48s
rke2-coredns-rke2-coredns-869cb5bf57-fktzf              1/1     Running     0            2m49s
rke2-coredns-rke2-coredns-autoscaler-5b89b754bd-48h77   1/1     Running     0            2m49s
rke2-ingress-nginx-controller-n78bt                     1/1     Running     0            2m12s
rke2-metrics-server-58ff89f9c7-fd9dz                    1/1     Running     0            2m21s
rke2-snapshot-controller-58dbcfd956-stmz6               1/1     Running     0            2m8s
ubuntu@envoy-qiita:~$ 
```
と、kube-system namespace で全てのPodが、Running or Completed になっていれば、RKE2 のセットアップは終了です。

### 2. Istio bookinfo application の deploy
次に、Istio community が提供してくれている bookino application を、さきほど構築した kubernetes 上に deploy していきます。ここでは istio side car mode を使って、bookinfo application を deploy するので、こちらの[リンク](https://istio.io/latest/docs/setup/getting-started/)に従い構築します。

* Download istio
まずは最新版のv1.26.0をダウンロードして、$HOME配下にインストールします。その後、PATH環境変数を変更して、istioctl コマンドが直接使えるようにします。`istioctl version`とコマンドを打って、versionが表示されればPATHの設定は正常ですね。
```
ubuntu@envoy-qiita:~$ curl -L https://istio.io/downloadIstio | sh -
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   101  100   101    0     0    354      0 --:--:-- --:--:-- --:--:--   355
100  5124  100  5124    0     0   9065      0 --:--:-- --:--:-- --:--:--  9065

Downloading istio-1.26.0 from https://github.com/istio/istio/releases/download/1.26.0/istio-1.26.0-linux-amd64.tar.gz ...

Istio 1.26.0 download complete!

The Istio release archive has been downloaded to the istio-1.26.0 directory.

To configure the istioctl client tool for your workstation,
add the /home/ubuntu/istio-1.26.0/bin directory to your environment path variable with:
         export PATH="$PATH:/home/ubuntu/istio-1.26.0/bin"

Begin the Istio pre-installation check by running:
         istioctl x precheck

Try Istio in ambient mode
        https://istio.io/latest/docs/ambient/getting-started/
Try Istio in sidecar mode
        https://istio.io/latest/docs/setup/getting-started/
Install guides for ambient mode
        https://istio.io/latest/docs/ambient/install/
Install guides for sidecar mode
        https://istio.io/latest/docs/setup/install/

Need more information? Visit https://istio.io/latest/docs/
ubuntu@envoy-qiita:~$ cd istio-1.26.0/
ubuntu@envoy-qiita:~/istio-1.26.0$ vi $HOME/.profile
ubuntu@envoy-qiita:~/istio-1.26.0$ source !$
source $HOME/.profile
ubuntu@envoy-qiita:~/istio-1.26.0$ istioctl version
Istio is not present in the cluster: no running Istio pods in namespace "istio-system"
client version: 1.26.0
ubuntu@envoy-qiita:~/istio-1.26.0$
```
* Install istio
istio をインストールします。bookinfo application用の profile が予め用意されていますので、それを活用します。なお、Dynatraceでenvoy traceを見る場合は、このprofileで servicemesh の設定を追加する必要がありますが、ここではまずアプリを稼働させることを優先させるため、Dynatraceの監視設定は一旦やりません。
```
ubuntu@envoy-qiita:~/istio-1.26.0$ istioctl install -f samples/bookinfo/demo-profile-no-gateways.yaml -y
        |\          
        | \
        |  \        
        |   \       
      /||    \      
     / ||     \     
    /  ||      \    
   /   ||       \   
  /    ||        \  
 /     ||         \ 
/______||__________\
____________________
  \__       _____/  
     \_____/        

✔ Istio core installed ⛵️                                                                                                                                                             

✔ Istiod installed 🧠
✔ Installation complete
ubuntu@envoy-qiita:~/istio-1.26.0$
```
`Installation complete`と最後表示されれば、正常にインスト－ルは完了しています。次に、side car として envoy/istio が自動的に pod へ inject されるように、bookinfo application 用の namespace にラベルを設定していきます。istio の document では default namespace に当該設定を行っていますが、ここでは bookinfo application 用のnamespaceを作り（bookinfo-app）、そのnamespaceに対して、`istio-injection` label を有効にします。
```
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl get ns
NAME              STATUS   AGE
default           Active   16m
istio-system      Active   101s
kube-node-lease   Active   16m
kube-public       Active   16m
kube-system       Active   16m
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl create ns bookinfo-app
namespace/bookinfo-app created
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl get ns bookinfo-app --show-labels
NAME           STATUS   AGE   LABELS
bookinfo-app   Active   9s    kubernetes.io/metadata.name=bookinfo-app
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl label ns bookinfo-app istio-injection=enabled
namespace/bookinfo-app labeled
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl get ns bookinfo-app -L istio-injection
NAME           STATUS   AGE   ISTIO-INJECTION
bookinfo-app   Active   79s   enabled
ubuntu@envoy-qiita:~/istio-1.26.0$ 
```
最後のコマンドで `ISTIO-INJECTION=enabled`となっていれば、今後このPodにdeployされるアプリへ自動的に envoy/istio containerがinjectionされます。

* Install the Kubernetes Gateway API CRDs
RKE2はデフォルトで kubernetes gateway crd がインストールされないため、istio ドキュメントと同じようにここで kubernets gateway crd をインストールします。
```
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl get crd -A | grep gateway
gateways.networking.istio.io                               2025-05-12T01:59:18Z
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \
{ kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.3.0-rc.1" | kubectl apply -f -; }
customresourcedefinition.apiextensions.k8s.io/gatewayclasses.gateway.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/gateways.gateway.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/grpcroutes.gateway.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/httproutes.gateway.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/referencegrants.gateway.networking.k8s.io created
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl get crd -A | grep gateway
gatewayclasses.gateway.networking.k8s.io                   2025-05-12T02:07:24Z
gateways.gateway.networking.k8s.io                         2025-05-12T02:07:24Z
gateways.networking.istio.io                               2025-05-12T01:59:18Z
grpcroutes.gateway.networking.k8s.io                       2025-05-12T02:07:24Z
httproutes.gateway.networking.k8s.io                       2025-05-12T02:07:24Z
referencegrants.gateway.networking.k8s.io                  2025-05-12T02:07:24Z
ubuntu@envoy-qiita:~/istio-1.26.0$ 
```
最後のコマンドで、`gatway.networking.k8s.io` という crds の一覧が見えれば、kubernetes gateway crds のインスト－ルはOKです。

* Deploy the sample application
さっそく、bookinfo sample application を deploy しましょう。sample application 用の manifest も用意されていますので、それを apply するだけです。ただし、忘れずに namespace bookinfo-app を指定しましょう。
```
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -n bookinfo-app
service/details created
serviceaccount/bookinfo-details created
deployment.apps/details-v1 created
service/ratings created
serviceaccount/bookinfo-ratings created
deployment.apps/ratings-v1 created
service/reviews created
serviceaccount/bookinfo-reviews created
deployment.apps/reviews-v1 created
deployment.apps/reviews-v2 created
deployment.apps/reviews-v3 created
service/productpage created
serviceaccount/bookinfo-productpage created
deployment.apps/productpage-v1 created
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl get pods -n bookinfo-app
NAME                              READY   STATUS            RESTARTS   AGE
details-v1-77b775f46-g8z4r        0/2     PodInitializing   0          7s
productpage-v1-78dfd4688c-th4m2   0/2     Init:0/1          0          7s
ratings-v1-7c4c8d6794-hx2tn       0/2     PodInitializing   0          7s
reviews-v1-849f9bc5d6-9jdxq       0/2     Init:0/1          0          7s
reviews-v2-5c757d5846-l6l6p       0/2     Init:0/1          0          7s
reviews-v3-6d5d98f5c4-skjwj       0/2     Init:0/1          0          7s
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl get pods -n bookinfo-app
NAME                              READY   STATUS    RESTARTS   AGE
details-v1-77b775f46-g8z4r        2/2     Running   0          38s
productpage-v1-78dfd4688c-th4m2   2/2     Running   0          38s
ratings-v1-7c4c8d6794-hx2tn       2/2     Running   0          38s
reviews-v1-849f9bc5d6-9jdxq       2/2     Running   0          38s
reviews-v2-5c757d5846-l6l6p       2/2     Running   0          38s
reviews-v3-6d5d98f5c4-skjwj       2/2     Running   0          38s
ubuntu@envoy-qiita:~/istio-1.26.0$
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl get svc -n bookinfo-app
NAME          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
details       ClusterIP   10.43.146.234   <none>        9080/TCP   63s
productpage   ClusterIP   10.43.130.64    <none>        9080/TCP   63s
ratings       ClusterIP   10.43.246.56    <none>        9080/TCP   63s
reviews       ClusterIP   10.43.153.78    <none>        9080/TCP   63s
ubuntu@envoy-qiita:~/istio-1.26.0$
```
Podを確認した際、`READY 2/2`になっていることをきんと確認しましょう。アプリ用のコンテナとenvoy/isio用のコンテナ2つが動いているかどうを、これは表しているためです。次に、bookinfo applicationが動いているかどうかを確認するために、下記コマンドを実行しましょう（namespaceの指定を忘れずに！！！）
```
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl -n bookinfo-app exec "$(kubectl -n bookinfo-app get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -sS productpage:9080/productpage | grep -o "<title>.*</title>"
<title>Simple Bookstore App</title>
ubuntu@envoy-qiita:~/istio-1.26.0$ 
```
いいですね。Sample applicationのタイトルがちゃんと返ってきました♪

* Open the application to outside traffic
次に、Kubenetes clusterの外から、この bookinfo application にアクセスできるよう、ingress gatewayの設定を追加します。Kubernetes Gateway の manifest がこれも用意されているので、apply するのみです。
```
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl -n bookinfo-app apply -f samples/bookinfo/gateway-api/bookinfo-gateway.yaml
gateway.gateway.networking.k8s.io/bookinfo-gateway created
httproute.gateway.networking.k8s.io/bookinfo created
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl get gw -n bookinfo-app
No resources found in bookinfo-app namespace.
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl get gateway -n bookinfo-app
NAME               CLASS   ADDRESS   PROGRAMMED   AGE
bookinfo-gateway   istio             False        20s
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl get httproute -n bookinfo-app
NAME       HOSTNAMES   AGE
bookinfo               33s
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl get svc -n bookinfo-app
NAME                     TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                        AGE
bookinfo-gateway-istio   LoadBalancer   10.43.177.210   <pending>     15021:32470/TCP,80:31864/TCP   50s
details                  ClusterIP      10.43.146.234   <none>        9080/TCP                       8m57s
productpage              ClusterIP      10.43.130.64    <none>        9080/TCP                       8m57s
ratings                  ClusterIP      10.43.246.56    <none>        9080/TCP                       8m57s
reviews                  ClusterIP      10.43.153.78    <none>        9080/TCP                       8m57s
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl annotate gateway bookinfo-gateway networking.istio.io/service-type=ClusterIP -n bookinfo-app
gateway.gateway.networking.k8s.io/bookinfo-gateway annotated
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl get svc -n bookinfo-app
NAME                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)            AGE
bookinfo-gateway-istio   ClusterIP   10.43.177.210   <none>        15021/TCP,80/TCP   2m15s
details                  ClusterIP   10.43.146.234   <none>        9080/TCP           10m
productpage              ClusterIP   10.43.130.64    <none>        9080/TCP           10m
ratings                  ClusterIP   10.43.246.56    <none>        9080/TCP           10m
reviews                  ClusterIP   10.43.153.78    <none>        9080/TCP           10m
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl get httproute -n bookinfo-app
NAME       HOSTNAMES   AGE
bookinfo               2m23s
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl get gateway -n bookinfo-app
NAME               CLASS   ADDRESS                                                 PROGRAMMED   AGE
bookinfo-gateway   istio   bookinfo-gateway-istio.bookinfo-app.svc.cluster.local   True         2m27s
ubuntu@envoy-qiita:~/istio-1.26.0$ 
```
bookinfo-gateway にアドレスが振られ、`PROGRAMMED=True` になっていれば、受け入れ体制完了です。

* Access the application
自身のlaptop（私の場合、Windows）から、browser を使って bookinfo application にアクセスできるようポートフォワーディングを設定します。ここでの注意点は2つです。
1) bookinfo-app namespaceを指定すること
2) デフォルトだと 127.0.0.1 しかポートフォワーディングしないため、`--address`オプションで全てのIPアドレスをlistenするように指定すること
```
ubuntu@envoy-qiita:~/istio-1.26.0$ ip addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 52:54:00:3d:15:15 brd ff:ff:ff:ff:ff:ff
    inet 172.21.220.50/20 metric 100 brd 172.21.223.255 scope global dynamic eth0
       valid_lft 83654sec preferred_lft 83654sec
    inet6 fe80::5054:ff:fe3d:1515/64 scope link 
       valid_lft forever preferred_lft forever
ubuntu@envoy-qiita:~/istio-1.26.0$ kubectl port-forward svc/bookinfo-gateway-istio 8080:80 --address 0.0.0.0 -n bookinfo-app
Forwarding from 0.0.0.0:8080 -> 80
Handling connection for 8080
Handling connection for 8080
```
予めRKE2 vmが持っているeth0のIPアドレスを調べておき、そのアドレスのポート8080を叩くと、ブラウザ上にbookinfo applicationのページが表示されるはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/efd3c88d-e4fd-425d-a7e6-a16c41e809fd.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/3464650d-2f2f-424c-83b8-08d0275f3696.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/65ba8ed8-f6de-40cb-860a-2d1490d70e1d.png)
何回か、ページをリロードし、Book Reviews のところに、
1) レビューがないもの
2) 黒色の星レビューがあるもの
3) オレンジ色の星レビューがあるもの

の3パターンが表示されれば、Review-v1/v2/v3 pod にそれぞれリクエストが飛んでいる証拠です。

envoy側のログを見たい場合は、`kubectl logs <pod> -c istio-proxy -n bookinfo-app -f` で tail 出力を見て下さい。ブラウザからのアクセスが envoy proxy を通じてサービスへrouteされていることが分かると思います。
```
[2025-05-12T02:38:21.894Z] "GET /details/0 HTTP/1.1" 200 - via_upstream - "-" 0 178 2 2 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0" "1f210ef0-14e0-9116-a5f6-9bd427965bfe" "details:9080" "10.42.0.21:9080" outbound|9080||details.bookinfo-app.svc.cluster.local 10.42.0.26:44198 10.43.146.234:9080 10.42.0.26:50938 - default
[2025-05-12T02:38:21.900Z] "GET /reviews/0 HTTP/1.1" 200 - via_upstream - "-" 0 442 62 62 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0" "1f210ef0-14e0-9116-a5f6-9bd427965bfe" "reviews:9080" "10.42.0.24:9080" outbound|9080||reviews.bookinfo-app.svc.cluster.local 10.42.0.26:56448 10.43.153.78:9080 10.42.0.26:38654 - default
[2025-05-12T02:38:21.889Z] "GET /productpage HTTP/1.1" 200 - via_upstream - "-" 0 15072 75 74 "10.42.0.28" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0" "1f210ef0-14e0-9116-a5f6-9bd427965bfe" "172.21.220.50:8080" "10.42.0.26:9080" inbound|9080|| 127.0.0.6:39823 10.42.0.26:9080 10.42.0.28:0 outbound_.9080_._.productpage.bookinfo-app.svc.cluster.local default
[2025-05-12T02:38:22.004Z] "GET /static/tailwind/tailwind.css HTTP/1.1" 304 - via_upstream - "-" 0 0 4 3 "10.42.0.28" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0" "9beebb93-9c2e-9363-a805-3cdbab0cb309" "172.21.220.50:8080" "10.42.0.26:9080" inbound|9080|| 127.0.0.6:39823 10.42.0.26:9080 10.42.0.28:0 outbound_.9080_._.productpage.bookinfo-app.svc.cluster.local default
[2025-05-12T02:38:22.010Z] "GET /static/img/izzy.png HTTP/1.1" 304 - via_upstream - "-" 0 0 2 2 "10.42.0.28" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0" "1f4f9639-01ea-9c06-b4df-10bb1e828ff9" "172.21.220.50:8080" "10.42.0.26:9080" inbound|9080|| 127.0.0.6:39823 10.42.0.26:9080 10.42.0.28:0 outbound_.9080_._.productpage.bookinfo-app.svc.cluster.local default
```

## まとめ
いかがだったでしょうか？Service meshアプリを自分で作るとなると大変ですが、community側でこういったsample applicationが用意されていると本当にありがたいです。今回のように、ちょっとしたデモをするときとかも簡単にspin upできます。ただ、今回のブログのゴールはこの bookinfo application の trace 情報を envoy 含めて可視化することなので、次回の記事をしばしお待ちください。

まだ、Dynatraceを触ったことがない方、このブログを見てやってみたいと思われた方は、下記フリートライアルにてお試し下さい。↓↓↓

Dynatraceフリートライアル → https://www.dynatrace.com/ja/trial/