istio学习总结

istio学习总结

安装

不使用micro.k8s中的istio插件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#https://istio.io/latest/zh/docs/setup/install/istioctl/
curl -L https://istio.io/downloadIstio | sh -
cd istio-1.11.4
#https://istio.io/latest/zh/docs/setup/getting-started/
vim /etc/profile.d/istio.sh
export PATH="$PATH:/works/istio/istio-1.11.4/bin"

. /etc/profile

istioctl install --set profile=demo -y
kubectl label namespace default istio-injection=enabled

#Example
#https://blog.frognew.com/2021/07/learning-istio-1.10-01.html
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
kubectl get pods -w

kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
kubectl get gateway

istioctl analyze
✔ No validation issues found when analyzing namespace: default.

kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -s productpage:9080/productpage | grep -o "<title>.*</title>"

kubectl get svc istio-ingressgateway -n istio-system

export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].status.hostIP}')
#export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
export INGRESS_PORT=$(kubectl get svc istio-ingressgateway -n istio-system|awk '{print $5}'|sed '1d'|awk -F ',' '{print $2}'|awk -F '/' '{print $1}'|awk -F ':' '{print $2}')

export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
echo "$GATEWAY_URL"
echo "http://$GATEWAY_URL/productpage"

#查看仪表板
kubectl apply -f samples/addons
kubectl rollout status deployment/kiali -n istio-system

istioctl dashboard --address 0.0.0.0 kiali

#istioctl dashboard kiali
http://192.168.95.234:20001/kiali

#Mocking some traffic data:
for i in $(seq 1 100); do curl -s -o /dev/null "http://$GATEWAY_URL/productpage"; done

#jinjecting sidecar with existing namespace
https://istio.io/latest/docs/setup/additional-setup/sidecar-injection/
kubectl label zerofinance-dev istio-injection=enabled
#Injection occurs at pod creation time. Kill the running pod and verify a new pod is created with the injected sidecar. The original pod has 1/1 READY containers, and the pod with injected sidecar has 2/2 READY containers.
kubectl -n zerofinance-dev delete po --all

#Disable injection for the default namespace and verify new pods are created without the sidecar.
kubectl label zerofinance-dev default istio-injection-

卸载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#卸载application
kubectl delete -f samples/addons
istioctl manifest generate --set profile=demo | kubectl delete --ignore-not-found=true -f -
kubectl delete namespace istio-system
kubectl label namespace default istio-injection-
#or https://istio.io/latest/zh/docs/examples/bookinfo/#cleanup
samples/bookinfo/platform/kube/cleanup.sh

kubectl get virtualservices #-- there should be no virtual services
kubectl get destinationrules #-- there should be no destination rules
kubectl get gateway #-- there should be no gateway
kubectl get pods #-- the Bookinfo pods should be deleted
kubectl get se #-- ServerEntity


#卸载istio
#https://istio.io/latest/zh/docs/setup/install/istioctl/#uninstall
#可选的 --purge 参数将删除所有 Istio 资源,包括可能被其他 Istio 控制平面共享的、集群范围的资源。
istioctl x uninstall --purge

bookinfo应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
#https://blog.frognew.com/2021/07/learning-istio-1.10-03.html
kubectl get deploy -l app=reviews
kubectl get pod -l app=reviews

#将请求路由到固定版本的微服务上
kubectl apply -f samples/bookinfo/networking/destination-rule-all-mtls.yaml
#上面reviews微服务的destinationrule的subsets包含v1, v2, v3。

#接下来使用下面的命令创建VirtualService:
kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml
#reviews微服务的VirtualService配置了路由的目标只到v1 subset,其他服务在请求reviews时将只被路由到reviews v1。 istio配置的传播是最终一致性的,等待几秒钟后,多次刷新/prodctpage页,确认书籍评不再不包含评分信息,说明请求一直被路由到v1版本的reviews服务。

#基于用户身份进行请求路由
kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml
#请求头中end-user=jason的路由目标是reviews-v2,其他是reviews-v1。测试以jason登录(密码任意输入),登录后多次刷新/productpage页面,书籍的评论都一直包含黑星评级,而以其他用户名登录或匿名不登录访问时书籍评论都不包含星级评论。 这说明已经成功配置按用户身份的路由控制。

#还原
kubectl delete -f samples/bookinfo/networking/virtual-service-all-v1.yaml

#使用Istio对服务进行流量管理之故障注入
#https://blog.frognew.com/2021/07/learning-istio-1.10-04.html

#流量管理API资源对象VirtualService和DestinationRule
#https://blog.frognew.com/2021/07/learning-istio-1.10-05.html

#使用Istio对服务进行流量管理之流量转移
#https://blog.frognew.com/2021/07/learning-istio-1.10-06.html

#使用Istio Gateway将外部流量接入到服务网格
#https://blog.frognew.com/2021/07/learning-istio-1.10-07.html
#https://www.cnblogs.com/boshen-hzb/p/10679863.html
#https://jonathangazeley.com/2020/12/30/load-balancing-ingress-with-metallb-on-microk8s/
上面istio-ingressgateway的Service的Type是LoadBalancer, 它的EXTERNAL-IP处于pending状态, 这是因为我们目前的环境并没有可用于Istio Ingress Gateway外部的负载均衡器,为了使得可以从外部访问, 通过修改istio-ingressgateway这个Service的externalIps:
kubectl edit service istio-ingressgateway -n istio-system
spec:
externalIPs:
- 192.168.95.234

samples/bookinfo/networking/bookinfo-gateway.yaml


#Istio流量管理之TCP流量转移
#https://blog.frognew.com/2021/07/learning-istio-1.10-08.html
kubectl create namespace istio-io-tcp-traffic-shifting
kubectl label namespace istio-io-tcp-traffic-shifting istio-injection=enabled
kubectl apply -f samples/tcp-echo/tcp-echo-services.yaml -n istio-io-tcp-traffic-shifting
kubectl get svc istio-ingressgateway -n istio-system -o yaml
#test
for i in {1..10}; do \
sh -c "(date; sleep 1) | nc 192.168.95.234 31400"; \
done
10个请求中的输出结果都是one说明请求流量被100%的路由到了v1版本的服务。

接下来通过以下命令,将20%流量从tcp-echo:v1迁移到tcp-echo:v2:
kubectl apply -f samples/tcp-echo/tcp-echo-20-v2.yaml -n istio-io-tcp-traffic-shifting
#test
for i in {1..10}; do \
sh -c "(date; sleep 1) | nc 192.168.95.234 31400"; \
done
10个请求中差不多有20%的请求被路由到了版本v2的服务商。

#Istio流量管理之设置请求超时和熔断
#https://blog.frognew.com/2021/07/learning-istio-1.10-09.html

#Istio流量管理之流量镜像
#https://blog.frognew.com/2021/07/learning-istio-1.10-10.html

#Istio流量管理之访问外部服务的三种方法
#https://blog.frognew.com/2021/07/learning-istio-1.10-11.html
使用ServiceEntry API资源对象将一个可访问的外部服务注册到服务网格中(推荐)
kubectl get istiooperator installed-state -n istio-system -o jsonpath='{.spec.meshConfig.outboundTrafficPolicy.mode}'
如果显示为空,则表示为ALLOW_ANY
选项值为ALLOW_ANY,sidecar将允许调用未知的服务,调整为:REGISTRY_ONLY
istioctl install --set profile=demo -y --set meshConfig.outboundTrafficPolicy.mode=REGISTRY_ONLY
#test namespace可选
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: external-svc
namespace: istio-system
spec:
hosts:
- "baidu.com"
- "www.baidu.com"
ports:
- name: http
number: 80
protocol: HTTP
- name: https
number: 443
protocol: HTTPS
location: MESH_EXTERNAL
EOF

kubectl -n istio-system get se
kubectl run curl --image=radial/busyboxplus:curl -it
#kubectl attach curl -c curl -i -t
kubectl exec -it curl -c curl -- curl http://www.baidu.com
kubectl exec -it curl -c curl -- curl https://www.baidu.com

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: httpbin-ext
spec:
hosts:
- httpbin.org
ports:
- number: 80
name: http
protocol: HTTP
- number: 443
name: https
protocol: HTTPS
resolution: DNS
location: MESH_EXTERNAL
EOF

kubectl run curl --image=radial/busyboxplus:curl -it
#kubectl attach curl -c curl -i -t
kubectl exec -it curl -c curl -- curl http://httpbin.org/headers
kubectl exec -it curl -c curl -- curl -sSI https://httpbin.org/headers

#Istio Egress Gateway及其使用场景
#https://blog.frognew.com/2021/07/learning-istio-1.10-12.html
kubectl exec -it curl -c curl -- curl -sSI https://httpbin.org/headers | grep "HTTP/"
为httpbin.org的443端口创建Egress Gateway。并为指向Egress Gateway的流量创建一个目标规则DestinationRule。
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: istio-egressgateway
spec:
selector:
istio: egressgateway
servers:
- port:
number: 443
name: tls
protocol: TLS
hosts:
- httpbin.org
tls:
mode: PASSTHROUGH
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: egressgateway-for-httpbin-ext
spec:
host: istio-egressgateway.istio-system.svc.cluster.local
subsets:
- name: httpbin-ext
EOF
创建一个虚拟服务VirtualService,将流量从 sidecar 引导至 egress gateway,再从 egress gateway 引导至外部服务:
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: direct-httpbin-ext-through-egress-gateway
spec:
hosts:
- httpbin.org
gateways:
- mesh
- istio-egressgateway
tls:
- match:
- gateways:
- mesh
port: 443
sniHosts:
- httpbin.org
route:
- destination:
host: istio-egressgateway.istio-system.svc.cluster.local
subset: httpbin-ext
port:
number: 443
- match:
- gateways:
- istio-egressgateway
port: 443
sniHosts:
- httpbin.org
route:
- destination:
host: httpbin.org
port:
number: 443
weight: 100
EOF
kubectl exec -it curl -c curl -- curl -sSI https://httpbin.org/headers | grep "HTTP/"
检查istio-egressgateway代理的日志:
kubectl logs -l istio=egressgateway -n istio-system

#使用认证策略设置双向TLS和基本的终端用户认证
#https://blog.frognew.com/2021/07/learning-istio-1.10-13.html
kubectl create ns foo
kubectl label namespace foo istio-injection=enabled
kubectl create ns bar
kubectl label namespace bar istio-injection=enabled

kubectl apply -f samples/httpbin/httpbin.yaml -n foo
kubectl run curl --image=radial/busyboxplus:curl -it -n foo
kubectl apply -f samples/httpbin/httpbin.yaml -n bar
kubectl run curl --image=radial/busyboxplus:curl -it -n bar

kubectl create ns legacy
kubectl apply -f samples/httpbin/httpbin.yaml -n legacy
kubectl run curl --image=radial/busyboxplus:curl -it -n legacy

#Test
for from in "foo" "bar" "legacy"; do for to in "foo" "bar" "legacy"; do kubectl exec curl -c curl -n ${from} -- curl -s "http://httpbin.${to}:8000/ip" -s -o /dev/null -w "curl.${from} to httpbin.${to}: %{http_code}\n"; done; done

kubectl get peerauthentication --all-namespaces
No resources found

#配置全局严格模式启用istio双向TLS
#前面学习了具有sidecar代理的工作负载之间将自动启用双向TLS认证,但工作负载仍然可以接收plain-text流量。可以通过将整个服务网格的对等认证策略(PeerAuthentication)设置为STRICT模式,以阻止整个网格的服务以非双向TLS通信。 如下所示,全局的对等认证策略是没有selector的,且它必须位于安装istio的根命名空间内(如istio-system)。
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: "default"
namespace: "istio-system"
spec:
mtls:
mode: STRICT
EOF

#Test
for from in "foo" "bar" "legacy"; do for to in "foo" "bar" "legacy"; do kubectl exec curl -c curl -n ${from} -- curl -s "http://httpbin.${to}:8000/ip" -s -o /dev/null -w "curl.${from} to httpbin.${to}: %{http_code}\n"; done; done
会发现没有sidecar代理的curl.legacy到有sidecar代理的httpbin.foo和httpbin.bar的请求将会失败,因为全局的对等认证策略是严格模式,要求客户端与httpbin.foo和httpbin.bar之间的流量必须是双向TLS的。

#终端用户认证
kubectl -n foo exec -it curl -- curl http://httpbin.foo.svc.cluster.local:8000/headers
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: httpbin-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "httpbin.example.com"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- "httpbin.example.com"
gateways:
- httpbin-gateway
http:
- route:
- destination:
host: httpbin.foo.svc.cluster.local
port:
number: 8000
EOF

配置要求必须提供有效的token,这样没有token的请求也会被拒绝:
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: "frontend-ingress"
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
action: DENY
rules:
- from:
- source:
notRequestPrincipals: ["*"]
to:
- operation:
hosts: ["httpbin.example.com"]
EOF

curl http://httpbin.example.com/headers -s -o /dev/null -w "%{http_code}\n"
403

TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.10/security/tools/jwt/samples/demo.jwt -s)
curl --header "Authorization: Bearer $TOKEN" http://httpbin.example.com/headers -s -o /dev/null -w "%{http_code}\n"
200

配置按路由提供有效token,路径指host、path、或者method:
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: "frontend-ingress"
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
action: DENY
rules:
- from:
- source:
notRequestPrincipals: ["*"]
to:
- operation:
paths: ["/headers"]
hosts: ["httpbin.example.com"]
EOF

不提供token访问https://httpbin.example.com/headers将被拒绝,但可以访问其他路径:
curl http://httpbin.example.com/headers -s -o /dev/null -w "%{http_code}\n"
403
curl http://httpbin.example.com/ip -s -o /dev/null -w "%{http_code}\n"
200
curl --header "Authorization: Bearer $TOKEN" http://httpbin.example.com/headers -s -o /dev/null -w "%{http_code}\n"
200

使用