前言
在之前的文章中,我們花了大量的篇幅,從記錄後端pod真實ip開始説起,然後引入envoy,再解決了各種各樣的需求:配置自動重載、流量劫持、sidecar自動注入,到envoy的各種能力:熔斷、流控、分流、透明代理、可觀測性等等,已經可以支撐起一個完整的服務治理框架了
而今天介紹的istio,正是前面提到的這些所有功能的集大成者,從本文開始,我們將詳細介紹istio,並且與之前手搓的功能做一個詳細的對比,為大家以後選擇服務治理的某個功能提供參考
istio架構
┌──────────────┐
│ istiod │ ← 控制面
│ (Pilot+CA) │
└──────┬───────┘
│ xDS (gRPC / TLS)
│
┌────────────┐ │ ┌────────────┐
│ Envoy │◄───┼───►│ Envoy │ ← 數據面
│ (Sidecar) │ │ (Sidecar) │
└─────▲──────┘ └─────▲──────┘
│ iptables │
│ │
App Pod App Pod
- 數據面就是之前一直在研究的envoy,包括4/7代理、熔斷、限流、可觀測性等等,envoy就是執行由控制面下發的配置
- 控制面istiod主要的職責:將配置下發到每一個envoy去。由於istio中配置以crd的形式成為了k8s的資源,所以要不斷的監聽k8s apiserver,將資源的變化翻譯成envoy看得懂的配置,並且下發到envoy去
至於其餘istio的資源,我們後面詳細介紹
istio安裝
不説廢話,先把istio安裝上去再説
首先準備好k8s集羣,其次下載istio(這一步有可能需要上網)
curl -L https://istio.io/downloadIstio | sh -
cd istio-*
sudo ln -s $PWD/istioctl /usr/local/bin/istioctl
驗證兼容性
istioctl x precheck
開始安裝
istioctl install --set profile=default -y
由於鏡像倉庫沒法直接使用,所以需要一些特殊的方法,具體可以看這篇文章: 快速拉取docker鏡像
需要的鏡像有:
docker.io/istio/pilot:1.28.2
docker.io/istio/proxyv2:1.28.2
安裝完成:
▶ kubectl -n istio-system get pod
NAME READY STATUS RESTARTS AGE
istio-ingressgateway-865c448856-qs8s2 1/1 Running 0 8s
istiod-86c75775bb-j7qbg 1/1 Running 0 12s
安裝完成,要從哪兒開始呢?
istio的自動注入
kubectl label namespace default istio-injection=enabled
同之前envoy一樣,給namespace打上標籤之後,重啓服務即可
kubectl rollout restart deploy nginx-test
重啓之後sidecar已經注入進去了,我們來觀察一下istio注入到底做了什麼事情
先describe看看events
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 8s default-scheduler Successfully assigned default/nginx-test-6f855b9bb9-9phsv to wilson
Normal Pulled 8s kubelet Container image "docker.io/istio/proxyv2:1.28.2" already present on machine
Normal Created 8s kubelet Created container: istio-init
Normal Started 8s kubelet Started container istio-init
Normal Pulled 8s kubelet Container image "docker.io/istio/proxyv2:1.28.2" already present on machine
Normal Created 8s kubelet Created container: istio-proxy
Normal Started 8s kubelet Started container istio-proxy
Normal Pulled 6s kubelet Container image "registry.cn-beijing.aliyuncs.com/wilsonchai/nginx:latest" already present on machine
Normal Created 6s kubelet Created container: nginx-test
Normal Started 5s kubelet Started container nginx-test
1個initContainer,1個業務container和1個sidecar
其中initContainer:
Init Containers:
istio-init:
Container ID: containerd://2bf56cd37703d82a2a43e94e8c8d683ed66b0afe22bf7148a597d67b89a727a8
Image: docker.io/istio/proxyv2:1.28.2
Image ID: docker.m.daocloud.io/istio/proxyv2@sha256:39065152d6bd3e7fbf6bb04be43c7a8bbd16b5c7181c84e3d78fa164a945ae7f
Port: <none>
Host Port: <none>
Args:
istio-iptables
-p
15001
-z
15006
-u
1337
-m
REDIRECT
-i
*
-x
-b
*
-d
15090,15021,15020
--log_output_level=default:info
...
和之前envoy中劫持流量的做法一樣,istio依然是使用iptables將端口流量導入到代理之中處理
嘗試訪問一下:
▶ curl 10.22.12.178:30785/test
i am backend in backend-6d76f54494-g6srz
成功,再次查看istio-proxy日誌。空的?為了調試方便,將其打開並且輸出至控制枱
kubectl -n istio-system edit cm istio
apiVersion: v1
data:
mesh: |-
accessLogFile: /dev/stdout
...
至此,istio的第一個功能探索完畢,自動注入sidecar container並且完成了流量劫持
Upgrade Required 426 的問題
當前的架構是左圖,現在要前進到右圖

其實就是在backend注入istio-proxy,直接重啓就好
▶ kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
backend-5d4d7b598c-f7852 2/2 Running 0 13s 10.244.0.49 wilson <none> <none>
nginx-test-6f855b9bb9-9phsv 2/2 Running 0 58m 10.244.0.48 wilson <none> <none>
注入完成,測試一下
▶ curl 10.22.12.178:30785/test
Upgrade Required
▶ kubectl logs -f -l app=nginx-test -c istio-proxy
[2026-01-26T07:54:42.977Z] "GET /test HTTP/1.1" 426 - upstream=10.244.0.48:80 duration=6ms route=default
[2026-01-26T07:54:42.978Z] "- - -" 0 - upstream=10.105.148.194:10000 duration=9ms route=-
在nginx注入istio-proxy,backend沒有注入的時候並沒有報錯。而一旦nginx與backend都注入的時候就會出現Upgrade Required (426)錯誤,Nginx Sidecar 發現目標(Backend)是一個純文本服務,它會回退到“透明代理”模式,簡單地把 Nginx 發出的流量透傳出去
Nginx Sidecar 發現目標也有 Sidecar,它會嘗試建立一個高度優化的、基於 mTLS 的隧道(關於mTLS後面會詳細介紹)。如果此時 Nginx 發出的請求頭(比如缺少 Host 字段,或者使用了 HTTP/1.0)不符合 Envoy 對這種隧道
協議的預期,Envoy 可能會向 Nginx 發送一個特殊的響應,或者 Nginx 在嘗試通過這種隧道通信時,因為某些 Header 衝突(如 Connection: close)自發產生了 426 錯誤
想要解決這個問題有兩種方法
改造nginx中加入標記
location /test {
proxy_http_version 1.1; # 必須添加這一行
proxy_set_header Host $host; # 這一行也是必須的
proxy_pass http://backend_ups;
}
Nginx 的 proxy_pass 默認使用 HTTP/1.0。在 Istio 環境中,HTTP/1.0 不支持長連接(Keep-Alive)以及一些現代的協議協商,這與 Istio Sidecar(Envoy)默認的 L7 代理行為衝突,Istio 需要 HTTP/1.1 來支持複雜連接管理問題
改造backend service
如果nginx改造有難度,那也可以嘗試改造backend-service
apiVersion: v1
kind: Service
metadata:
name: backend-service
namespace: default
spec:
ports:
- name: tcp-80 # 原為 http-80 改為 tcp-80
port: 10000
protocol: TCP
targetPort: 10000
selector:
app: backend
Istio 只有在識別到流量是 HTTP 時才會進行深度的協議檢查和轉換。如果你把這個服務聲明為 TCP,Istio 就會將其視為原始字節流進行透傳,不再關心它是 HTTP/1.0 還是 1.1。優點就是徹底解決 426 問題,無需改 Nginx。
缺點則是你會失去 Istio 針對該服務的 HTTP 監控指標(如請求數、4xx/5xx 統計)、分佈式追蹤以及基於路徑的路由功能
http 1.0 與 http 1.1
這裏再簡單介紹一下兩個協議版本的區別
-
連接管理(最顯著的區別)
- HTTP 1.0:短連接 (Short-lived),默認情況下,客户端每發起一個請求,都要與服務器建立一次 TCP 三次握手。請求結束並收到響應後,TCP 連接立即關閉。如果頁面有 10 張圖片,瀏覽器就要建立 10 次 TCP 連接。這帶來了極高的延遲和資源開銷。
- HTTP 1.1:持久連接 (Persistent Connection / Keep-Alive)。默認開啓 Connection: keep-alive。一個 TCP 連接可以被多個請求複用。只有在明確聲明 Connection: close 或連接超時後才會關閉。
- 在 Istio 中: Envoy 極度依賴持久連接來維持高性能的 Sidecar 間隧道。HTTP 1.0 的頻繁斷開會讓 Envoy 感到“壓力山大”,甚至認為這是一種非標準的協議行為。
-
Host Header
- HTTP 1.0:人們認為一個 IP 對應一個網站,所以請求頭裏不需要帶域名信息。
- HTTP 1.1:隨着虛擬主機(一個 IP 跑多個網站)的流行,HTTP 1.1 規定請求頭必須包含 Host 字段。
- 在 K8s/Istio 中: Istio 的路由決策、Service 的匹配完全依賴 Host 頭。這也是為什麼 Nginx 使用 HTTP 1.0 轉發時,如果不手動補全 Host 頭,後端往往會返回 404 或協議錯誤。
以上是istio必須要求HTTP 1.1最主要的兩個因素,當然還有其他非常重要的區別
| 特性 | HTTP 1.0 | HTTP 1.1 |
|---|---|---|
| 連接模型 | 默認短連接,每次請求新開 TCP | 默認持久連接 (Keep-Alive),複用 TCP |
| Host 頭部 | 可選 (導致無法支持虛擬主機) | 必須 (支持一 IP 多域名) |
| 流水線 (Pipelining) | 不支持 | 支持 (但在實際應用中受限) |
| 斷點續傳 | 不支持 | 支持 (通過 Range 頭部) |
| 緩存控制 | 簡單 (Expires) | 複雜且強大 (Cache-Control, ETag) |
| 默認協議版本 | 許多舊軟件(如 Nginx proxy)的默認值 | 現代 Web 應用的基石標準 |
小結
本章內容算是一個開胃小菜,成功安裝了istio,並且解決了一個非常常見的426問題,至於怎麼把之前在envoy的那些最佳實踐搬遷到istio,那就是後面的內容了,敬請期待
後記
如果整個namespace都已經有了注入標籤istio-injection=enabled,但是某個deployment不想讓istio注入
kubectl patch deployment nginx -p '{"spec":{"template":{"metadata":{"annotations":{"sidecar.istio.io/inject":"false"}}}}}'
聯繫我
- 聯繫我,做深入的交流

至此,本文結束
在下才疏學淺,有撒湯漏水的,請各位不吝賜教...