GKE Dataplane V2 observability が Preview になりました
はじめに
こんにちは。クラウドエース株式会社で SRE をしている間瀬です。
今回は 2023 年 7 月 12 日に Preview となった GKE Dataplane V2 observability について紹介させていただきます。
GKE Dataplane V2 observability について
本機能は Google Kubernetes Engine (以下、GKE) のネットワーキングオブションの一つとなる GKE Dataplane V2 上で動作する機能となっています。
GKE Dataplane V2 は Cilium によって実装されており、従来よりも効率的なネットワーキングやモニタリング、セキュリティに関する機能が提供されています。
GKE Dataplane V2 observability は GKE Dataplane V2 によって収集可能な指標を公開して Cloud Monitoring や Google Cloud Managed Service for Prometheus(以下、GMP) 、Hubble、セルフマネージドな Prometheus によって観測できる機能になります。
本機能のリリース前は GKE Dataplane V2 によって提供される機能は Cilium が持つほとんどの機能が制限されていましたが、本機能ではその一部がマネージドサービスとして利用できるようになっています。
尚、Cilium について詳しく知りたい方は 2023年 7 月 18 日に開催された Cloud Native Days Fukuoka 2023 プレイベントにて登壇してきましたので、こちらの動画を参照ください。
対象のセッションは動作の 35:40 からとなります。
以下より本機能の特徴を記載させていただきます。
Hubble UI
まずは個人的に本機能で最も特徴的となる Hubble UI について紹介させていただきます。
Hubble は Cilium をベースとしているモニタリングツールになります。GKE Dataplane V2 が有効化されているクラスタに対して GKE Dataplane V2 observability tool を有効化することで 下記のような UI を参照することが可能です。
Hubble UI のサービスマップによって L4 での Pod 間トラフィックを可視化することができます。以下の画像では画面上部がサービスマップで、下部にはトラフィック毎の情報が一覧表示されます。
尚、マネージドではない Hubble では Pod へアノテーションを追加することで L7 の可視化も可能ですが、本機能については現時点では対応していないようでした。
Hubble CLI
上記と同じ利用条件で CLI によるトラフィックの確認が可能です。
CLI によって L4 トラフィックの確認が可能です。CLI にはフィルタ機能があり、namespace や Pod などでフィルタすることが可能です。
kubectl exec -it -n kube-system deployment/hubble-relay -c hubble-cli -- hubble observe --from-namespace default
Jul 25 04:48:03.162: default/productpage-v1-75ddfff844-t644j:54096 (ID:16854) -> kube-system/kube-dns-fc686db9b-28vs4:53 (ID:39068) to-endpoint FORWARDED (UDP)
Jul 25 04:48:03.166: default/productpage-v1-75ddfff844-t644j:56764 (ID:16854) -> default/reviews-v3-645ffdc889-2nw67:9080 (ID:45829) to-stack FORWARDED (TCP Flags: SYN)
Jul 25 04:48:03.166: default/productpage-v1-75ddfff844-t644j:56764 (ID:16854) -> default/reviews-v3-645ffdc889-2nw67:9080 (ID:45829) to-endpoint FORWARDED (TCP Flags: SYN)
Jul 25 04:48:03.166: default/productpage-v1-75ddfff844-t644j:56764 (ID:16854) <- default/reviews-v3-645ffdc889-2nw67:9080 (ID:45829) to-stack FORWARDED (TCP Flags: SYN, ACK)
Jul 25 04:48:03.166: default/productpage-v1-75ddfff844-t644j:56764 (ID:16854) <- default/reviews-v3-645ffdc889-2nw67:9080 (ID:45829) to-endpoint FORWARDED (TCP Flags: SYN, ACK)
Jul 25 04:48:03.166: default/productpage-v1-75ddfff844-t644j:56764 (ID:16854) -> default/reviews-v3-645ffdc889-2nw67:9080 (ID:45829) to-stack FORWARDED (TCP Flags: ACK)
Jul 25 04:48:03.166: default/productpage-v1-75ddfff844-t644j:56764 (ID:16854) -> default/reviews-v3-645ffdc889-2nw67:9080 (ID:45829) to-endpoint FORWARDED (TCP Flags: ACK)
Jul 25 04:48:03.166: default/productpage-v1-75ddfff844-t644j:56764 (ID:16854) -> default/reviews-v3-645ffdc889-2nw67:9080 (ID:45829) to-stack FORWARDED (TCP Flags: ACK, PSH)
Jul 25 04:48:03.166: default/productpage-v1-75ddfff844-t644j:56764 (ID:16854) -> default/reviews-v3-645ffdc889-2nw67:9080 (ID:45829) to-endpoint FORWARDED (TCP Flags: ACK, PSH)
Jul 25 04:48:03.171: default/productpage-v1-75ddfff844-t644j:56764 (ID:16854) <- default/reviews-v3-645ffdc889-2nw67:9080 (ID:45829) to-stack FORWARDED (TCP Flags: ACK, PSH)
Jul 25 04:48:03.171: default/productpage-v1-75ddfff844-t644j:56764 (ID:16854) <- default/reviews-v3-645ffdc889-2nw67:9080 (ID:45829) to-endpoint FORWARDED (TCP Flags: ACK, PSH)
Jul 25 04:48:03.175: default/productpage-v1-75ddfff844-t644j:56764 (ID:16854) -> default/reviews-v3-645ffdc889-2nw67:9080 (ID:45829) to-stack FORWARDED (TCP Flags: ACK, FIN)
Jul 25 04:48:03.175: default/productpage-v1-75ddfff844-t644j:56764 (ID:16854) -> default/reviews-v3-645ffdc889-2nw67:9080 (ID:45829) to-endpoint FORWARDED (TCP Flags: ACK, FIN)
Jul 25 04:48:03.177: default/productpage-v1-75ddfff844-t644j:56764 (ID:16854) <- default/reviews-v3-645ffdc889-2nw67:9080 (ID:45829) to-stack FORWARDED (TCP Flags: ACK, FIN)
Jul 25 04:48:03.177: default/productpage-v1-75ddfff844-t644j:56764 (ID:16854) <- default/reviews-v3-645ffdc889-2nw67:9080 (ID:45829) to-endpoint FORWARDED (TCP Flags: ACK, FIN)
Jul 25 04:48:03.177: default/productpage-v1-75ddfff844-t644j:56764 (ID:16854) -> default/reviews-v3-645ffdc889-2nw67:9080 (ID:45829) to-stack FORWARDED (TCP Flags: ACK)
Jul 25 04:48:03.177: default/productpage-v1-75ddfff844-t644j:56764 (ID:16854) -> default/reviews-v3-645ffdc889-2nw67:9080 (ID:45829) to-endpoint FORWARDED (TCP Flags: ACK)
GKE Dataplane V2 メトリクスの取得
GKE Dataplane V2 が有効化されているクラスタに対して GKE Dataplane V2 metrics を有効化することで、指標が公開されます。
主要なメトリクスは以下となり、Pod 別の通信フロー数になります。クラスタにて GMP が有効になっていると、自動的に収集され Metrics Explorer から参照可能です。
- prometheus.googleapis.com/pod_flow_egress_flows_count/counter : Podからのフロー合計数
- prometheus.googleapis.com/pod_flow_ingress_flows_count/counter: Podへのフロー合計数
その他の指標について Hubble や Cilium に関する様々な指標が公開されているようです。比較できていないですが、現時点ではマネージドではない Cilium, Hubble より公開されている指標が少ない印象を受けました。
Cilium が動作する Pod のメトリクス用のエンドポイントにアクセスすることで公開されている指標が確認できるので興味ある方は確認してみてください。
本機能が解決する課題、メリット
現時点でメリットと感じたのは、Anthos Service Mesh や Istio のようなサービスメッシュを導入しなくてもサービスマップによって Pod 間の依存関係を可視化、検査できるところだと思います。
サービスメッシュを導入する場合、サービスメッシュ自体の管理が必要となる点や Pod にサイドカーコンテナがデプロイされることにより Pod の構成が複雑になる課題が挙げられますが、本機能を代わりに利用することでそれらを解決できます。
一方で、本機能ではサービスメッシュが提供するようなプロキシによるマイクロサービス毎のトラフィック管理のようなことはできないので、これら機能を利用しないケースや、必要な場合はメリットは薄れますがサービスメッシュと併用して利用する必要があります。
本機能の利用における注意点
GKE Dataplane V2 を既に利用されている方は本機能を有効化するだけで利用可能となりますが、GKE Dataplane V2 は作成済みのクラスタへ適用できないため、GKE Dataplane V2 を利用されていない方はクラスタの再作成が必要となります。
利用にかかるコスト
上記で説明したGKE Dataplane V2 observability tool、GKE Dataplane V2 metrics それぞれにコストがかかります。現時点においてコストについて記載されているページはこちらになります。
-
GKE Dataplane V2 observability tool
Preview 段階では無料となっており、課金情報は現時点では公開されていませんが、一般提供後は Pod 別に時間で課金されるようです。 -
GKE Dataplane V2 metrics
GMP によってメトリクスを収集する場合のみ GMP の課金体系に沿って課金されます。
GKE Dataplane V2 metrics の有効化による公開だけでは課金されないようです。
利用方法
ほとんど公式docの内容と同じですが、本機能の利用方法について以下に紹介させていただきます。
クラスタの作成、機能の有効化
前提として、今回はスタンダードモードのクラスタを新規に作成してメトリクスの収集はGMPにて行うものとします。
以下のコマンドで GKE クラスタを作成します。
gcloud container clusters create gke-cluster \
--enable-dataplane-v2 \
--enable-managed-prometheus \
--enable-dataplane-v2-metrics \
--dataplane-v2-observability-mode=INTERNAL_VPC_LB \
--region asia-northeast1
Hubble UI のデプロイ
以下の内容で yaml ファイルを作成します。
apiVersion: v1
kind: ServiceAccount
metadata:
name: hubble-ui
namespace: kube-system
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: hubble-ui
labels:
app.kubernetes.io/part-of: cilium
rules:
- apiGroups:
- networking.k8s.io
resources:
- networkpolicies
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- componentstatuses
- endpoints
- namespaces
- nodes
- pods
- services
verbs:
- get
- list
- watch
- apiGroups:
- apiextensions.k8s.io
resources:
- customresourcedefinitions
verbs:
- get
- list
- watch
- apiGroups:
- cilium.io
resources:
- "*"
verbs:
- get
- list
- watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: hubble-ui
labels:
app.kubernetes.io/part-of: cilium
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: hubble-ui
subjects:
- kind: ServiceAccount
name: hubble-ui
namespace: kube-system
---
apiVersion: v1
kind: ConfigMap
metadata:
name: hubble-ui-nginx
namespace: kube-system
data:
nginx.conf: |
server {
listen 8081;
# uncomment for IPv6
# listen [::]:8081;
server_name localhost;
root /app;
index index.html;
client_max_body_size 1G;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# CORS
add_header Access-Control-Allow-Methods "GET, POST, PUT, HEAD, DELETE, OPTIONS";
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Max-Age 1728000;
add_header Access-Control-Expose-Headers content-length,grpc-status,grpc-message;
add_header Access-Control-Allow-Headers range,keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout;
if ($request_method = OPTIONS) {
return 204;
}
# /CORS
location /api {
proxy_http_version 1.1;
proxy_pass_request_headers on;
proxy_hide_header Access-Control-Allow-Origin;
proxy_pass http://127.0.0.1:8090;
}
location / {
# double `/index.html` is required here
try_files $uri $uri/ /index.html /index.html;
}
}
}
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: hubble-ui
namespace: kube-system
labels:
k8s-app: hubble-ui
app.kubernetes.io/name: hubble-ui
app.kubernetes.io/part-of: cilium
spec:
replicas: 1
selector:
matchLabels:
k8s-app: hubble-ui
template:
metadata:
labels:
k8s-app: hubble-ui
app.kubernetes.io/name: hubble-ui
app.kubernetes.io/part-of: cilium
spec:
securityContext:
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
serviceAccount: hubble-ui
serviceAccountName: hubble-ui
containers:
- name: frontend
image: quay.io/cilium/hubble-ui:v0.11.0
ports:
- name: http
containerPort: 8081
volumeMounts:
- name: hubble-ui-nginx-conf
mountPath: /etc/nginx/conf.d/default.conf
subPath: nginx.conf
- name: tmp-dir
mountPath: /tmp
terminationMessagePolicy: FallbackToLogsOnError
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsUser: 1000
runAsGroup: 1000
capabilities:
drop:
- all
- name: backend
image: quay.io/cilium/hubble-ui-backend:v0.11.0
env:
- name: EVENTS_SERVER_PORT
value: "8090"
- name: FLOWS_API_ADDR
value: "hubble-relay.kube-system.svc:443"
- name: TLS_TO_RELAY_ENABLED
value: "true"
- name: TLS_RELAY_SERVER_NAME
value: relay.kube-system.svc.cluster.local
- name: TLS_RELAY_CA_CERT_FILES
value: /var/lib/hubble-ui/certs/hubble-relay-ca.crt
- name: TLS_RELAY_CLIENT_CERT_FILE
value: /var/lib/hubble-ui/certs/client.crt
- name: TLS_RELAY_CLIENT_KEY_FILE
value: /var/lib/hubble-ui/certs/client.key
ports:
- name: grpc
containerPort: 8090
volumeMounts:
- name: hubble-ui-client-certs
mountPath: /var/lib/hubble-ui/certs
readOnly: true
terminationMessagePolicy: FallbackToLogsOnError
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsUser: 1000
runAsGroup: 1000
capabilities:
drop:
- all
volumes:
- configMap:
defaultMode: 420
name: hubble-ui-nginx
name: hubble-ui-nginx-conf
- emptyDir: {}
name: tmp-dir
- name: hubble-ui-client-certs
projected:
# note: the leading zero means this number is in octal representation: do not remove it
defaultMode: 0400
sources:
- secret:
name: hubble-relay-client-certs
items:
- key: ca.crt
path: hubble-relay-ca.crt
- key: tls.crt
path: client.crt
- key: tls.key
path: client.key
---
kind: Service
apiVersion: v1
metadata:
name: hubble-ui
namespace: kube-system
labels:
k8s-app: hubble-ui
app.kubernetes.io/name: hubble-ui
app.kubernetes.io/part-of: cilium
spec:
type: ClusterIP
selector:
k8s-app: hubble-ui
ports:
- name: http
port: 80
targetPort: 8081
yaml ファイル作成後に以下のコマンドでクラスタへデプロイします。
※ yaml ファイル名は hubble-ui-std.yaml
kubectl apply -f hubble-ui-std.yaml
ここまでで、構築手順としては完了ですが、以降の手順を実施する前にご自身でサンプルAP等をデプロイしてください。
私はよく Istio のチュートリアルで使われている bookinfo アプリケーションを利用しています。
コチラを参考に Istio はインストールせずにアプリケーションのみデプロイしてください。
Hubble UI へのアクセス
以下のコマンドで port-forward します。
kubectl -n kube-system port-forward service/hubble-ui 16100:80 --address='0.0.0.0'
その後、自身のブラウザにて localhost:16100 へアクセスすることで Hubble UI へのアクセスが可能です。
Hubble CLI によるトラフィックの確認
以下のコマンドでトラフィックの確認が可能です。コマンドの末尾を hubble -h とすることでフィルタ等のオプションが参照できます。
kubectl exec -it -n kube-system deployment/hubble-relay -c hubble-cli -- hubble observe
メトリクスの確認
公式docの手順を参考にコンソール上の Metrics Explorer から prometheus/pod_flow_egress_flows_count または prometheus/pod_flow_ingress_flows_count の指標を選択することで参照が可能です。
まとめ
本機能の登場によって容易にサービスマップのモニタリングが可能になるので今後は GKE Dataplane V2 をあえて採用したいケースが増えてくるのではないかと感じました。
また、本機能のベースとなっている Cilium や eBPF は活発に開発が続いているので今後もマネージドサービスとしての更なるアップデートも期待できると個人的には考えています。
記事内で利用条件として触れた通り、一度クラスタを作成すると GKE Dataplane V2 を使用するにはクラスタの再作成が必要になるので、これからクラスタを構築される方は今後追加されるかもしれない拡張機能を利用しやすくするために GKE Dataplane V2 を有効化しておいてもいいのかなと思います。
今後も本機能はじめ GKE Dataplane V2 には注目して更なるアップデートが公開された際には記事を書きたいと思います。
Discussion