Istio Compression == ## 前置作業 * 確認 ServiceMesh 所需的四個 Operator 存在 | Operator 名稱 | Namespace | 用途 | | ---------------------- | ----------------------------- | ------- | | Elasticsearch Operator | openshift-operators-redhat | 日誌索引 | | Jaeger Operator | openshift-distributed-tracing | 分散追蹤 | | Kiali Operator | openshift-distributed-tracing | 可視化流量監控 | | Service Mesh Operator | openshift-operators | 主體控制元件 | ```shell= oc get operators | egrep 'servicemesh|kiali|elasticsearch|jaeger' elasticsearch-operator.openshift-operators-redhat 2y123d jaeger-product.openshift-distributed-tracing 2y123d kiali-ossm.kiali 74d kiali-ossm.olm-test 74d kiali-ossm.openshift-operators 2y123d servicemeshoperator.olm-test 74d servicemeshoperator.openshift-operators 2y123d servicemeshoperator3.openshift-operators 74d ``` ## 安裝 Istio ### 建立 SMCP / SMMR ### SMCP ```yaml= apiVersion: maistra.io/v2 kind: ServiceMeshControlPlane metadata: name: basic namespace: servicemesh spec: version: v2.5 tracing: type: Jaeger addons: kiali: enabled: true security: controlPlane: mtls: true gateways: ingress: enabled: true runtime: container: resources: requests: cpu: 100m memory: 128Mi deployment: autoScaling: enabled: false service: type: ClusterIP ``` ### SMMR #### 【SMMR】 - 透過 Namespace 選擇 ```yaml= apiVersion: maistra.io/v1 kind: ServiceMeshMemberRoll metadata: name: default namespace: servicemesh # ← 必須與 SMCP 同命名空間 spec: members: - alex-test-1 # 這種做法是透過 member selector 直接選 namespace ``` #### 【SMMR】 - 透過 Label 選擇 ```yaml= apiVersion: maistra.io/v1 kind: ServiceMeshMemberRoll metadata: name: default namespace: servicemesh # ← 必須與 SMCP 同命名空間 spec: memberSelectors: - matchLabels: istio-injection: "enabled" ``` ### 確認 Istio 狀態 * 看 ServiceMesh Control Planes 建立狀態 * 確認在 `servicemesh` 中建立出 control planes ```shell= oc get servicemeshcontrolplanes -n servicemesh NAME READY STATUS PROFILES VERSION AGE basic 9/9 ComponentsReady ["default"] 2.5.2 2d20h ``` * 看 ServiceMesh Member Roll ```shell= oc get smmr -n servicemesh NAME READY STATUS AGE default 4/4 Configured 24h ``` ### 建立被監控 Workload * 建立新的 project * 切換指令預設 ns * 將 ns 標上 `istio-injection=enabled` ```shell= oc new-project alex-test-1 oc project alex-test-1 oc label namespace alex-test-1 istio-injection=enabled --overwrite oc ``` ### 建立 nginx server / `nginx-deployment.yaml` * 在剛建立的 project 中,建立 Nginx ```yaml= apiVersion: apps/v1 kind: Deployment metadata: name: nginx-dep namespace: alex-test-1 spec: replicas: 1 selector: matchLabels: app: nginx-dep template: metadata: labels: app: nginx-dep spec: containers: - name: nginx-dep image: quay.kyndryl.tw/alex/nginx-unprivileged:1.25.3 ports: - containerPort: 8080 resources: requests: cpu: 50m memory: 64Mi limits: cpu: 200m memory: 128Mi --- apiVersion: v1 kind: Service metadata: name: nginx-service-2 namespace: alex-test-1 spec: type: ClusterIP ports: - port: 80 targetPort: 8080 protocol: TCP name: http selector: app: nginx-dep --- apiVersion: route.openshift.io/v1 kind: Route metadata: name: nginx-route-2 spec: to: kind: Service name: nginx-service-2 weight: 100 port: targetPort: http tls: insecureEdgeTerminationPolicy: Redirect termination: edge wildcardPolicy: None ``` ## 建立 Istio 入口 ### VitualService / Gateway * 建立 gateway 並引導流量 * 用 `oc get pods --show-labels` ```yaml= oc get pod -n servicemesh --show-labels | grep ingress; ``` * Label 也可以用指令確認 ```shell= oc get deployment -n servicemesh istio-ingressgateway -o jsonpath='{.spec.template.metadata.labels}{"\n"}' # 輸出結果 {"app":"istio-ingressgateway","istio":"ingressgateway","istio.io/rev":"basic","maistra-control-plane":"servicemesh","maistra.io/gateway":"istio-ingressgateway.servicemesh","service.istio.io/canonical-name":"istio-ingressgateway","service.istio.io/canonical-revision":"basic","sidecar.istio.io/inject":"false"} ``` ```yaml= apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: nginx-gateway # 幫 gateway 取名字 namespace: alex-test-1 # 放置的 ns spec: selector: istio: ingressgateway # 要跟 istio 的 ingressgateway Pod label 一致 servers: - port: number: 80 name: http protocol: HTTP hosts: - alex-nginx-istio.apps.thsr.kyndryl.tw # 綁定你的外部域名 --- apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: nginx namespace: alex-test-1 # 要跟 GW 放在一起 spec: hosts: - alex-nginx-istio.apps.thsr.kyndryl.tw # 與 Gateway 一致 gateways: - nginx-gateway http: - route: - destination: host: nginx-service.alex-test-1.svc.cluster.local # 寫「K8s Service 名稱」-> svc名稱.ns名稱.svc.cluster.local port: number: 80 ``` ## Check Point 1 * 先確認服務可以分別從下方兩路進行連線 * 不透過 Istio 進入 * https://nginx-route-2-alex-test-1.apps.thsr.kyndryl.tw/ * 透過 Istio 的入口連入 * http://alex-nginx-istio.apps.thsr.kyndryl.tw/ ### 如果沒有成功注入... * 在 Deployment 加入下列 annotation ```shell= oc patch deploy nginx-dep -n alex-test-1 \ -p '{ "spec": { "template": { "metadata": { "annotations": { "sidecar.istio.io/inject": "true" } } } } }' deployment.apps/nginx-dep patched ``` > 如果一開始沒有使用 Sidecar 且初次啟用 Sidecar,則必定會重啟 Pods > 若需避免服務中斷,則需透過 > `oc rollout restart deployment nginx-dep -n alex-test-1` > Pods 會以 Rollout 方式重啟 / 服務不中斷但會觸發告警 ## 啟用 Gzip ### EnvoyFilter 的設定 ```yaml= # EnvoyFilter: 對應 alex-test-1/nginx-gateway listener 啟用 gzip 壓縮 apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: name: enable-gzip-nginx namespace: servicemesh spec: workloadSelector: labels: app: istio-ingressgateway configPatches: - applyTo: HTTP_FILTER match: context: GATEWAY listener: filterChain: filter: name: envoy.filters.network.http_connection_manager subFilter: name: envoy.filters.http.router listenerFilterChain: filter: name: "envoy.filters.network.http_connection_manager" patch: operation: INSERT_BEFORE value: name: envoy.filters.http.compressor typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.compressor.v3.Compressor compressor_library: name: gzip typed_config: "@type": type.googleapis.com/envoy.extensions.compression.gzip.compressor.v3.Gzip memory_level: 9 compression_level: BEST_COMPRESSION compression_strategy: DEFAULT_STRATEGY response_direction_config: common_config: min_content_length: 100 # 壓縮太小的,省不了傳輸量,還耗費 CPU 意義不大 content_type: - text/html - text/plain - text/css - application/javascript - application/json ``` ### 確認修改 EnvoyFilter 不會重啟 Pod ```shell= ❯ oc get pods NAME READY STATUS RESTARTS AGE nginx-689dd8dfb9-j52x6 2/2 Running 0 74m nginx-dep-6dc797957-skpv9 2/2 Running 0 56m ``` ### 驗證壓縮功能 * GET `envoyfilter` ```shell= ❯ oc get envoyfilter -n servicemesh NAME AGE enable-gzip-nginx 20s metadata-exchange-1.6-basic 7d10h stats-filter-1.6-basic 7d10h tcp-metadata-exchange-1.6-basic 7d10h tcp-stats-filter-1.6-basic 7d10h ``` * curl 請求,發現 `vary: Accept-Encoding` ```shell= # 測試指令 HOST=alex-nginx-istio.apps.thsr.kyndryl.tw curl -sS -D - -o /dev/null -H 'Accept-Encoding: gzip' "http://$HOST/" # 結果如下 HTTP/1.1 200 OK server: istio-envoy date: Tue, 25 Nov 2025 17:17:21 GMT content-type: text/html last-modified: Tue, 24 Oct 2023 13:46:47 GMT accept-ranges: bytes x-envoy-upstream-service-time: 2 content-encoding: gzip vary: Accept-Encoding transfer-encoding: chunked set-cookie: 8163d0087b0b21765b4a8ecc72ffb1ac=3e288abbac618d5602454d79f23c0816; path=/; HttpOnly cache-control: private ``` * 預期結果如果有 `content-encoding: gzip` 表示傳輸有被壓縮 * `envoy.filters.http.compressor` 預設只壓縮超過 min_content_length 的 Content-Type * min_content_length 先前給了 100,上述 `content-length: 615`, 615 > 100 所以會觸發壓縮  ## 測試 * 找出入口 ... 在 `alex-nginx-istio.apps.thsr.kyndryl.tw` ```shell= oc get routes -n servicemesh NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD alex-test-1-nginx-gateway-4897fe2ae11e0c79 alex-nginx-istio.apps.thsr.kyndryl.tw istio-ingressgateway http2 None grafana grafana-servicemesh.apps.thsr.kyndryl.tw grafana <all> reencrypt/Redirect None istio-ingressgateway istio-ingressgateway-servicemesh.apps.thsr.kyndryl.tw istio-ingressgateway 8080 None jaeger jaeger-servicemesh.apps.thsr.kyndryl.tw jaeger-query https-query reencrypt None kiali kiali-servicemesh.apps.thsr.kyndryl.tw kiali 20001 reencrypt/Redirect None prometheus prometheus-servicemesh.apps.thsr.kyndryl.tw prometheus <all> reencrypt/Redirect None ``` * 每秒 100 次請求為例 ```shell= #!/usr/bin/env bash HOST=alex-nginx-istio.apps.thsr.kyndryl.tw echo "Target Host: $HOST" echo "Press Ctrl+C to stop." while true; do for i in {1..100}; do curl -s -o /dev/null -H 'Accept-Encoding: gzip' "http://$HOST/" & done wait sleep 1 done ``` * 在 Kalia 觀測  ## 效能檢查 * 在 Kiali/Prometheus 觀察 istio-proxy 的 CPU、延遲。壓縮會增加 CPU。 * 用 envoy admin(localhost:15000/config_dump)確認 filter 已插入(在 router 之前)。 ## Ref * https://imroc.cc/istio/usage/enable-gzip * https://access.redhat.com/articles/6972785
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up