前面演示了 Ingress 在 Kubernetes 中的應用,這章介紹下 Istio Gateway 入站網關沮焕。
下載 Istio
curl -L https://istio.io/downloadIstio | sh -
cd istio-1.9.0
cat >> /etc/profile <<EOF
export PATH=/opt/istio/istio-1.9.0/bin:$PATH
EOF
source /etc/profile
安裝 Istio
# istioctl install -f /opt/cloud/istio-operator.yml -y
istioctl install --set profile=demo -y
kubectl label namespace cloud istio-injection=enabled
輸出信息:
? Istio core installed
? Istiod installed
? Egress gateways installed
? Ingress gateways installed
? Installation complete
Istio 控制器運行起來后吨岭,可以通過編輯 IstioOperator
對象來改變 Istio 的配置÷褪鳎控制器會檢測到改變辣辫,繼而用相應配置更新 Istio 的安裝內容。istio-operator.yml
這個文件我也放在了項目的根目錄下魁巩。
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
name: cloud-istio-operator
namespace: istio-system
spec:
profile: demo
meshConfig:
accessLogFile: /dev/stdout
accessLogEncoding: TEXT
安裝完成后急灭,即可在 Dashboard 界面看到 istio-system 命名空間下的 Workloads、Discovery and Load Balancing 信息谷遂。
在 istio-1.9.0/samples/addons 下有一些監(jiān)控葬馋、追蹤的插件 Prometheus、 Grafana埋凯、Jaeger点楼,安裝很容易,下面一條命令即可白对,你可以去部署了解一下掠廓。
# 在 istio-1.9.0 文件夾下
kubectl apply -f samples/addons
下圖是 Istio 可視化工具 Kiali 的界面:
上面在安裝 Istio 的時候,執(zhí)行了這一句:kubectl label namespace cloud istio-injection=enabled
它會給我們微服務所在的 cloud 命名空間添加 istio-injection=enabled
標簽甩恼,這樣在部署應用的時候蟀瞧,Istio 會自動的將 sidecar 容器注入到 Pod 中 沉颂,查看命名空間標簽信息:
[root@k8s002 ~]# kubectl get namespaces --show-labels
NAME STATUS AGE LABELS
cloud Active 4d istio-injection=enabled
default Active 4d istio-injection=enabled
ingress-nginx Active 3d1h app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
istio-system Active 34h istio-injection=disabled
Istio 的流量管理模型源于和服務一起部署的 Envoy 代理,網格內服務發(fā)送和接收的所有流量都經由 Envoy 代理悦污,這讓控制網格內的流量變得非常簡單铸屉,而且不需要對服務做任何的更改,它是一種與語言徹底解偶的服務治理方案切端。
上一節(jié)彻坛,我們已經將幾個微服務部署到了 Kubernetes 平臺,現在為了給我們的服務添加 Istio 支持踏枣,通過下面的命令將 cloud 命名空間下的所有 Pod 都刪除昌屉,然后 Deployment、ReplicaSet 控制器模式會重建所有 Pod茵瀑,這時 Istio 會自動為我們的服務注入 sidecar 容器间驮。
kubectl delete --all pods --namespace=cloud
這時候再去看下新的 Pod 信息,已經被自動注入了下面兩個容器:istio-proxy马昨、istio-init竞帽。(或者通過命令 kubectl describe pod {name} -n cloud
查看 Pod 信息)
sidecar 注入其實就是在 Pod 的 YML 模板中添加額外的容器配置,這個模板在名稱為 istio-sidecar-injector 的 Config Maps 對象中鸿捧。
-
istio-init
它的作用是配置 iptables 規(guī)則屹篓,將入站、出站流量交由 istio-proxy 代理匙奴,init 容器會在應用容器啟動之前運行抱虐,并且執(zhí)行完成后就退出了,通常用來完成一些初始化任務饥脑。
-
istio-proxy
真正的 sidecar 代理恳邀,基于 Envoy 實現。
istio-proxy 是如何獲取應用容器的入站和出站流量灶轰?答案就在 istio-init 這個容器中谣沸。
initContainers:
- name: istio-init
image: docker.io/istio/proxyv2:1.9.0
args:
- istio-iptables
- '-p'
- '15001'
- '-z'
- '15006'
- '-u'
- '1337'
- '-m'
- REDIRECT
- '-i'
- '*'
- '-x'
- ''
- '-b'
- '*'
- '-d'
- 15090,15021,15020
-
-p 15001
表示出站流量被 iptable 重定向到 Envoy 的 15001 端口 -
-z 15006
表示入站流量被 iptable 重定向到 Envoy 的 15006 端口 -
-u 1337
用于排除用戶 ID 為 1337 即 istio-proxy 自身的流量
[root@k8s002 ~]# docker ps -a | grep istio-init
a06bf54904f9 istio/proxyv2 "/usr/local/bin/pilo…" 5 hours ago Exited (0) 5 hours ago k8s_istio-init_user-server-9b9656cbb-7vsx2_cloud_2809324e-6fc6-4f32-8fec-c7dfa95f0497_0
ab76b4bfb6f1 istio/proxyv2 "/usr/local/bin/pilo…" 5 hours ago Exited (0) 5 hours ago k8s_istio-init_order-server-d5f799765-9w7vn_cloud_98772936-423f-4796-b6d4-fdf170b8bb2a_0
35149e8f46b1 istio/proxyv2 "/usr/local/bin/pilo…" 5 hours ago Exited (0) 5 hours ago k8s_istio-init_actuator-admin-7c595b74d9-kn6wk_cloud_3ce9994b-0b52-4b81-b93d-978134bbbeb7_0
通過 docker logs a06bf54904f9 查看一個 istio-init 容器的日志翠霍,會輸出 istio-init 所配置的 iptables 規(guī)則废亭。
*nat
......
-A PREROUTING -p tcp -j ISTIO_INBOUND
-A OUTPUT -p tcp -j ISTIO_OUTPUT
......
-A ISTIO_INBOUND -p tcp -j ISTIO_IN_REDIRECT
-A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-ports 15006
......
-A ISTIO_OUTPUT -j ISTIO_REDIRECT
-A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001
COMMIT
-
PREROUTING
所有到達 Pod 的入站流量被重定向到端口 15006 -
OUTPUT
所有出站流量被重定向到端口 15001鸽捻,這些都是 istio-proxy 正在監(jiān)聽的端口盔腔。
[root@k8s002 ~]# docker exec -it b5e4c3488480 netstat -tnlp
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:15006 0.0.0.0:* LISTEN 13/envoy
tcp 0 0 0.0.0.0:9097 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:15021 0.0.0.0:* LISTEN 13/envoy
tcp 0 0 0.0.0.0:15090 0.0.0.0:* LISTEN 13/envoy
tcp 0 0 127.0.0.1:15000 0.0.0.0:* LISTEN 13/envoy
tcp 0 0 0.0.0.0:15001 0.0.0.0:* LISTEN 13/envoy
tcp6 0 0 :::15020 :::* LISTEN 1/pilot-agent
在 Kubernetes 中,代理被注入到 Pod 中外邓,通過配置 iptables 規(guī)則來捕獲流量袋马,一旦 sidecar 代理被注入戳护,Istio 就可以通過 sidecar 代理來協(xié)調所有的流量非凌。
下面是 order-server 中 sidecar 代理的部分日志举农,會看到所有 inbound 和 outbound 的請求信息,下面一個是 actuator-admin 服務探測客戶端是否在線的請求敞嗡,另一個是 eureka 客戶端的續(xù)約請求颁糟。查看 istio-proxy 日志命令:kubectl logs -f -l app=order-server -c istio-proxy -n cloud
- -l 指定標簽信息
- -c 指定容器名稱
- -n 指定命名空間
[2021-02-24] "GET /actuator/health HTTP/1.1" 200 - via_upstream - "-" 0 15 2 1 "-" "ReactorNetty/0.8.15.RELEASE" "8bcd13fa-2e95-90c6-8fa3-a579c36facf2" "10.244.1.70:9099" "127.0.0.1:9099" inbound|9099|| 127.0.0.1:38332 10.244.1.70:9099 10.244.1.69:34062 - default
[2021-02-24] "PUT /eureka/apps/ORDER-SERVER/10.244.1.70:9099?status=UP&lastDirtyTimestamp=1614156772911 HTTP/1.1" 200 - via_upstream - "-" 0 0 1 1 "-" "Java-EurekaClient/v1.9.8" "6b711a7c-1d72-9f0b-a825-1fafdb9da462" "eureka-server:18761" "10.244.0.16:18761" outbound|18761||eureka-server.cloud.svc.cluster.local 10.244.1.70:53380 10.97.40.48:18761 10.244.1.70:45068 - default
[2021-02-24] "GET /eureka/apps/delta HTTP/1.1" 200 - via_upstream - "-" 0 87 1 1 "-" "Java-EurekaClient/v1.9.8" "179d11d3-5591-92c7-871b-05bfd71e98fd" "eureka-server:18761" "10.244.0.16:18761" outbound|18761||eureka-server.cloud.svc.cluster.local 10.244.1.70:53380 10.97.40.48:18761 10.244.1.70:45068 - default
下面演示如何通過 Istio Ingress Gateway 來轉發(fā)外部請求航背。
在 Kubernetes 環(huán)境中,使用 Ingress 對象來指定需要暴露到集群外的服務棱貌,但是 Ingress 本身是不支持 TCP 協(xié)議的玖媚,只能用于 HTTP 流量。在 Istio 服務網格中婚脱,使用了一種新的配置模型 Istio Gateway 將服務暴露至服務網格之外今魔,它通過將 L4 配置與 L7 配置分離的方式克服了 Ingress 不支持 TCP 路由的問題。
- Gateway
- VirtualService
Istio Gateway 是運行在網格邊界的獨立 Envoy 代理障贸,而不是工作負載的 sidecar 代理涡贱,Istio 為我們提供了一些預先配置好的網關代理部署 istio-ingressgateway 和 istio-egressgateway,下面要創(chuàng)建的 cloud-gateway 就是基于 istio-ingressgateway 實現的 selector:istio:ingressgateway
惹想。
cloud-gateway 網關配置讓 HTTP 流量從 47.103.80.230 通過 80 端口流入網格,這里沒有為請求指定任何的路由規(guī)則督函,要為網關指定路由嘀粱,需要把網關綁定到虛擬服務 VirtualService 上。
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: cloud-gateway
spec:
selector:
istio: ingressgateway # use Istio default gateway implementation
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- 47.103.80.230
VirtualService
在 VirtualService 中使用路由規(guī)則辰狡,告訴 istio-ingressgateway 將請求路由到哪個服務锋叨,路由目標地址可以是同一服務的不同版本,也可以是完全不同的服務(DestinationRule)宛篇,未匹配任何路由規(guī)則的請求均會被拒絕并返回 404 響應娃磺。
VirtualService 中的路由規(guī)則要比 Ingress 強大很多,它可以配置請求超時時間叫倍、失敗重試次數偷卧、熔斷器,可以進行故障注入測試吆倦,而且它提供的匹配規(guī)則非常豐富听诸,可以在端口、header 字段蚕泽、URI 晌梨、queryParams 查詢參數等內容上設置匹配條件,還可以對請求進行重定向 HTTPRedirect
须妻、重寫 HTTPRewrite
仔蝌,這些功能在項目中均提供了示例。
spec:hosts
虛擬服務主機名可以是 IP 地址荒吏,或者是完全限定域名 FQDN敛惊,也可以使用通配符 "*" 前綴,匹配所有服務的路由規(guī)則绰更。
destination:host
必須是存在于 Istio 服務注冊中心的實際目標地址豆混,否則 Envoy 代理不知道將請求發(fā)送到哪里篓像。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: user
spec:
hosts:
- "*"
gateways:
- cloud-gateway
http:
- match:
- uri:
prefix: /user
route:
- destination:
port:
number: 9097
host: user-server.cloud.svc.cluster.local
timeout: 10s
retries:
attempts: 3
perTryTimeout: 2s
...... 完整配置,請 clone 項目后查看
我們 cloud 微服務演示項目提供的 Istio 網關路由配置文件在項目的根目錄下皿伺,名稱為 istio-gateway.yml员辩。
部署命令 kubectl apply -f /opt/cloud/istio-gateway.yml,部署成功后即可進行下面的測試鸵鸥。
Ingress Gateway 使用了 Loadbalancer 的方式暴露奠滑,通過 kubectl get svc -n istio-system
命令查看到 istio-ingressgateway 暴露到了 31963 端口,下面通過幾個微服務的接口來測試下(注意暴露端口需要添加 ECS 安全組規(guī)則)妒穴。
[root@k8s001 ~]# kubectl get svc -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-egressgateway ClusterIP 10.109.231.239 <none> 80/TCP,443/TCP,15443/TCP 165m
istio-ingressgateway LoadBalancer 10.99.186.2 <pending> 15021:31872/TCP,80:31963/TCP,443:31474/TCP,31400:30316/TCP,15443:32160/TCP 165m
istiod ClusterIP 10.109.254.235 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 165m
下面是每個微服務中提供的一些接口宋税,可以訪問測試下連通性:
接口地址 | 調用服務 |
---|---|
http://IP:31963/order/init | order-server |
http://IP:31963/auth/init | auth-server |
http://IP:31963/order/user/list | order-server -> user-server -> auth-server |
http://IP:31963/user/init | user-server |
訪問后,可以查看 istio-ingressgateway 的日志讼油,會輸出一次請求的具體信息杰赛。
查看日志命令為:kubectl logs -f -l istio=ingressgateway -c istio-proxy -n istio-system
[2021-02-24T06:30:07.775Z] "GET /order/init HTTP/1.1" 200 - via_upstream - "-" 0 86 9 8 "10.244.1.1" "PostmanRuntime/7.26.10" "e304f605-0047-93b8-b201-10da3ce764fe" "47.103.80.230:31963" "10.244.1.66:9099" outbound|9099||order-server.cloud.svc.cluster.local 10.244.1.57:58992 10.244.1.57:8080 10.244.1.1:24551 - -
[2021-02-24T06:30:12.370Z] "GET /auth/init HTTP/1.1" 200 - via_upstream - "-" 0 85 6 6 "10.244.1.1" "PostmanRuntime/7.26.10" "d1afb272-413c-987b-92c4-d6dc5514823b" "47.103.80.230:31963" "10.244.1.63:9096" outbound|9096||auth-server.cloud.svc.cluster.local 10.244.1.57:60132 10.244.1.57:8080 10.244.1.1:24551 - -
[2021-02-24T06:30:21.660Z] "GET /order/user/list HTTP/1.1" 200 - via_upstream - "-" 0 204 22 22 "10.244.1.1" "PostmanRuntime/7.26.10" "b7ba1167-4507-9f9a-8ef9-2a2b5dc09c51" "47.103.80.230:31963" "10.244.1.66:9099" outbound|9099||order-server.cloud.svc.cluster.local 10.244.1.57:58992 10.244.1.57:8080 10.244.1.1:24551 - -
[2021-02-24T06:31:24.201Z] "GET /user/init HTTP/1.1" 200 - via_upstream - "-" 0 85 3 2 "10.244.1.1" "PostmanRuntime/7.26.10" "d880d400-ff95-9958-b004-e39eca0cafc8" "47.103.80.230:31963" "10.244.1.67:9097" outbound|9097||user-server.cloud.svc.cluster.local 10.244.1.57:44756 10.244.1.57:8080 10.244.1.1:24551 - -
為了在網格中導流,Istio 需要知道所有的 endpoint 在哪并且屬于哪個服務矮台,Istio 自身并不提供服務發(fā)現功能乏屯,它會連接到一個服務發(fā)現系統(tǒng),我們這里是在 Kubernetes 平臺中部署 Istio瘦赫,它會自動檢測該集群中的服務和 endpoint辰晕。
Istiod
在 Istio 1.5 之后,控制平面進行了簡化确虱,將 Pilot含友、Galley、Citadel 和 sidecar 注入器執(zhí)行的功能都合并成了單一的 istiod 服務校辩,只需啟動單個 Pod窘问,就可以啟用一個包含了所有功能的 Istio 控制平面。
istio-proxy@istiod-6f984b7878-8zxjc:/$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
istio-p+ 1 0.2 1.0 784732 79848 ? Ssl 09:15 0:33 /usr/local/bin/pilot-discovery discovery --monitoringAddr=:15014 --log_output_level=default:info --domain cluster.local --keepalive
istio-p+ 53 0.0 0.0 18504 2072 pts/0 Ss 12:52 0:00 bash
istio-proxy@istiod-6f984b7878-8zxjc:/$ netstat -tnlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:9876 0.0.0.0:* LISTEN 1/pilot-discovery
tcp6 0 0 :::15010 :::* LISTEN 1/pilot-discovery
tcp6 0 0 :::15012 :::* LISTEN 1/pilot-discovery
tcp6 0 0 :::15014 :::* LISTEN 1/pilot-discovery
tcp6 0 0 :::15017 :::* LISTEN 1/pilot-discovery
tcp6 0 0 :::8080 :::* LISTEN 1/pilot-discovery
Istio 提供的幾個分析宜咒、診斷命令:
- istioctl analyze 可以檢測 Istio 配置的潛在問題
[root@k8s002 istio-1.9.0]# istioctl analyze -n cloud
Info [IST0118] (Service actuator-admin.cloud) Port name (port: 5000, targetPort: 5000) doesn't follow the naming convention of Istio port.
Info [IST0118] (Service api-gateway.cloud) Port name (port: 4000, targetPort: 4000) doesn't follow the naming convention of Istio port.
......
上面診斷我們微服務示例命名空間 cloud南缓,提示 Service 對象沒有遵循 Istio 的端口命名規(guī)則。參看官方說明
# 正確寫法如下
spec:
ports:
- name: tcp
port: 5000
protocol: TCP
targetPort: 5000
nodePort: 32700
- istioctl describe 驗證 Pod 網絡
[root@k8s002 istio-1.9.0]# istioctl experimental describe pod user-server-9b9656cbb-t8dx6 -n cloud
Pod: user-server-9b9656cbb-t8dx6
Pod Ports: 9097 (user-server), 15090 (istio-proxy)
Suggestion: add 'app' label to pod for Istio telemetry.
Suggestion: add 'version' label to pod for Istio telemetry.
--------------------
Service: user-server
Port: 9097/auto-detect targets pod port 9097
Exposed on Ingress Gateway http://172.24.251.203
VirtualService: user.default
/user*
2 additional destination(s) that will not reach this pod
Pod 內的服務容器的端口 9097荧呐,Pod 內的 istio-proxy 容器的端口 15090汉形,通過 Ingress Gateway 暴露的 virtual service 規(guī)則。
- istioctl proxy-config endpoints 查看當前可用的 endpoint
[root@k8s002 ~]# istioctl proxy-config endpoints order-server-5676b7dcd6-85xrn.cloud | grep cloud
10.244.0.39:4000 HEALTHY OK outbound|4000||api-gateway.cloud.svc.cluster.local
10.244.0.40:9099 HEALTHY OK outbound|9099||order-server.cloud.svc.cluster.local
10.244.0.41:9097 HEALTHY OK outbound|9097||user-server.cloud.svc.cluster.local
10.244.1.134:5000 HEALTHY OK outbound|5000||actuator-admin.cloud.svc.cluster.local
10.244.1.135:18761 HEALTHY OK outbound|18761||eureka-server.cloud.svc.cluster.local
10.244.1.136:9096 HEALTHY OK outbound|9096||auth-server.cloud.svc.cluster.local
卸載 Istio 命令:
istioctl x uninstall --purge
kubectl delete namespace istio-system
~ 終 ~