背景
Istio是一个开源服务网格,随着微服务架构的复杂性不断增长,它应运而生。它旨在提供一种统一的方式来连接、保护、管理和观察微服务。Istio允许开发人员简单地部署云原生应用,同时让运维人员能够高效地管理流量、安全性和策略。
若你希望快速上手Istio,本文将提供一个简洁的入门指南。我们将介绍如何安装Istio、利用Istio的流量管理功能来控制服务的入口流量。
传统微服务、K8s、Istio关系
- 传统微服务例如dubbo,Springcloud都需要有自己的注册中心、网关等组件,例如Euraka、Zuul
-
像SpringCloud之类微服务的能力,如:服务发现、服务注册、负载均衡、动态水平扩展之类的能力,K8S组件其实都已经原生支持了
- K8s有流量调度和流量治理能力,但是能力弱。(例如金丝雀发布,其实用原生ingress也可以实现,但较为麻烦,不够灵活)
- --》所以Istio可以简单理解为对K8s流量治理的能力增强
Istio架构
- 划分成两大部分
- Control plane:控制平面,由Pilot、Citadel、Galley组成(istio1.5之前这三个组件独立为3个pod部署,1.5之后融合成istiod),负责服务发现、配置、认证,是配置进行统一的管理然后分发给不通的数据平面。
- Data plance:数据平面
安装Istio
下载Istio
下载命令请参考官方文档
下载后将Istio的bin目录加入到PATH里
[root@localhost ~]# ll
total 93360
-rw-------. 1 root root 1260 Nov 25 2023 anaconda-ks.cfg
drwxr-x---. 6 root root 115 Aug 12 21:16 istio-1.23.0
-rw-r--r--. 1 root root 95595640 Sep 2 23:53 minikube-linux-amd64
[root@localhost ~]# cd istio-1.23.0/
[root@localhost istio-1.23.0]# ll
total 28
drwxr-x---. 2 root root 22 Aug 12 21:16 bin
-rw-r--r--. 1 root root 11357 Aug 12 21:16 LICENSE
drwxr-xr-x. 4 root root 36 Aug 12 21:16 manifests
-rw-r-----. 1 root root 979 Aug 12 21:16 manifest.yaml
-rw-r--r--. 1 root root 6759 Aug 12 21:16 README.md
drwxr-xr-x. 26 root root 4096 Aug 12 21:16 samples
drwxr-xr-x. 3 root root 57 Aug 12 21:16 tools
[root@localhost istio-1.23.0]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost istio-1.23.0]# export PATH=$PWD/bin:$PATH
[root@localhost istio-1.23.0]# echo $PATH
/root/istio-1.23.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost istio-1.23.0]# istioctl version
Istio is not present in the cluster: no running Istio pods in namespace "istio-system"
client version: 1.23.0
安装Istio
Install Istio using the demo
profile, without any gateways:
[root@localhost istio-1.23.0]# istioctl install -f samples/bookinfo/demo-profile-no-gateways.yaml -y
|\
| \
| \
| \
/|| \
/ || \
/ || \
/ || \
/ || \
/ || \
/______||__________\
____________________
\__ _____/
\_____/
✔ Istio core installed ⛵️
✔ Istiod installed 🧠
✔ Installation complete Made this installation the default for cluster-wide operations.
[root@localhost istio-1.23.0]# minikube kubectl -- get pods -n istio-system
NAME READY STATUS RESTARTS AGE
istiod-868d9947bb-2hqjs 1/1 Running 0 5m19s
[root@localhost istio-1.23.0]# minikube kubectl -- get services -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istiod ClusterIP 10.96.157.245 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 5m29s
增加一个命名空间label,通过该label自动注入sidecar代理:
如下:把default这个namespace打上了istio-injection=enabled标签
[root@localhost istio-1.23.0]# minikube kubectl -- label namespace default istio-injection=enabled
namespace/default labeled
安装Kubernetes Gateway API CRDs
[root@localhost istio-1.23.0]# kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || { kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.1.0" | kubectl apply -f -; }
customresourcedefinition.apiextensions.k8s.io/gatewayclasses.gateway.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/gateways.gateway.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/grpcroutes.gateway.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/httproutes.gateway.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/referencegrants.gateway.networking.k8s.io created
安装demo应用
[root@localhost istio-1.23.0]# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
service/details created
serviceaccount/bookinfo-details created
deployment.apps/details-v1 created
service/ratings created
serviceaccount/bookinfo-ratings created
deployment.apps/ratings-v1 created
service/reviews created
serviceaccount/bookinfo-reviews created
deployment.apps/reviews-v1 created
deployment.apps/reviews-v2 created
deployment.apps/reviews-v3 created
service/productpage created
serviceaccount/bookinfo-productpage created
deployment.apps/productpage-v1 created
[root@localhost istio-1.23.0]#
[root@localhost istio-1.23.0]#
[root@localhost istio-1.23.0]#
[root@localhost istio-1.23.0]# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
details ClusterIP 10.105.16.81 <none> 9080/TCP 21s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 58m
productpage ClusterIP 10.97.209.169 <none> 9080/TCP 21s
ratings ClusterIP 10.108.206.100 <none> 9080/TCP 21s
reviews ClusterIP 10.96.139.19 <none> 9080/TCP 21s
[root@localhost istio-1.23.0]#
[root@localhost istio-1.23.0]#
[root@localhost istio-1.23.0]# kubectl get pods
NAME READY STATUS RESTARTS AGE
details-v1-857849f66-hpst9 0/2 Init:0/1 0 29s
productpage-v1-c5b7f7dbc-9fwtl 0/2 Init:0/1 0 29s
ratings-v1-68d5f5486b-z7wjj 0/2 Init:0/1 0 29s
reviews-v1-7dc5fc4b46-h7w6f 0/2 Init:0/1 0 29s
reviews-v2-6cf45d556b-hgktf 0/2 Init:0/1 0 29s
reviews-v3-86cb7d97f8-2mlm8 0/2 Init:0/1 0 29s
[root@localhost istio-1.23.0]#
[root@localhost istio-1.23.0]#
启动时间较久,可以用-w查看变化
[root@localhost istio-1.23.0]# kubectl get pods -w
NAME READY STATUS RESTARTS AGE
details-v1-857849f66-hpst9 0/2 Init:0/1 0 38s
productpage-v1-c5b7f7dbc-9fwtl 0/2 Init:0/1 0 38s
ratings-v1-68d5f5486b-z7wjj 0/2 PodInitializing 0 38s
reviews-v1-7dc5fc4b46-h7w6f 0/2 PodInitializing 0 38s
reviews-v2-6cf45d556b-hgktf 0/2 Init:0/1 0 38s
reviews-v3-86cb7d97f8-2mlm8 0/2 Init:0/1 0 38s
reviews-v2-6cf45d556b-hgktf 0/2 PodInitializing 0 42s
reviews-v3-86cb7d97f8-2mlm8 0/2 PodInitializing 0 47s
details-v1-857849f66-hpst9 0/2 PodInitializing 0 53s
productpage-v1-c5b7f7dbc-9fwtl 0/2 PodInitializing 0 58s
reviews-v1-7dc5fc4b46-h7w6f 1/2 Running 0 2m16s
reviews-v1-7dc5fc4b46-h7w6f 1/2 Running 0 2m17s
reviews-v1-7dc5fc4b46-h7w6f 2/2 Running 0 2m18s
ratings-v1-68d5f5486b-z7wjj 1/2 Running 0 3m16s
ratings-v1-68d5f5486b-z7wjj 1/2 Running 0 3m16s
ratings-v1-68d5f5486b-z7wjj 2/2 Running 0 3m17s
reviews-v2-6cf45d556b-hgktf 1/2 Running 0 3m27s
reviews-v2-6cf45d556b-hgktf 1/2 Running 0 3m27s
reviews-v2-6cf45d556b-hgktf 2/2 Running 0 3m28s
reviews-v3-86cb7d97f8-2mlm8 1/2 Running 0 3m39s
reviews-v3-86cb7d97f8-2mlm8 1/2 Running 0 3m40s
reviews-v3-86cb7d97f8-2mlm8 2/2 Running 0 3m41s
[root@localhost istio-1.23.0]# kubectl get pods
NAME READY STATUS RESTARTS AGE
details-v1-857849f66-hpst9 2/2 Running 0 5m29s
productpage-v1-c5b7f7dbc-9fwtl 2/2 Running 0 5m29s
ratings-v1-68d5f5486b-z7wjj 2/2 Running 0 5m29s
reviews-v1-7dc5fc4b46-h7w6f 2/2 Running 0 5m29s
reviews-v2-6cf45d556b-hgktf 2/2 Running 0 5m29s
reviews-v3-86cb7d97f8-2mlm8 2/2 Running 0 5m29s
等所有的pod启动成功后
验证应用
[root@localhost istio-1.23.0]# kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -sS productpage:9080/productpage | grep -o "<title>.*</title>"
<title>Simple Bookstore App</title>
外部访问demo应用
[root@localhost istio-1.23.0]# kubectl apply -f samples/bookinfo/gateway-api/bookinfo-gateway.yaml
gateway.gateway.networking.k8s.io/bookinfo-gateway created
httproute.gateway.networking.k8s.io/bookinfo created
[root@localhost istio-1.23.0]# kubectl annotate gateway bookinfo-gateway networking.istio.io/service-type=ClusterIP --namespace=default
gateway.gateway.networking.k8s.io/bookinfo-gateway annotated
[root@192 test-ingress]# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
bookinfo-gateway-istio ClusterIP 10.100.243.223 <none> 15021/TCP,80/TCP 4d
details ClusterIP 10.105.16.81 <none> 9080/TCP 4d
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d1h
productpage ClusterIP 10.97.209.169 <none> 9080/TCP 4d
ratings ClusterIP 10.108.206.100 <none> 9080/TCP 4d
reviews ClusterIP 10.96.139.19 <none> 9080/TCP
[root@localhost istio-1.23.0]# kubectl get gateway
NAME CLASS ADDRESS PROGRAMMED AGE
bookinfo-gateway istio bookinfo-gateway-istio.default.svc.cluster.local True 75s
验证外部访问
- 从Kubernetes节点转发到clusterip的service
[root@localhost istio-1.23.0]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
bookinfo-gateway-istio ClusterIP 10.100.243.223 <none> 15021/TCP,80/TCP 2m19s
details ClusterIP 10.105.16.81 <none> 9080/TCP 9m41s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 67m
productpage ClusterIP 10.97.209.169 <none> 9080/TCP 9m41s
ratings ClusterIP 10.108.206.100 <none> 9080/TCP 9m41s
reviews ClusterIP 10.96.139.19 <none> 9080/TCP 9m41s
[root@localhost istio-1.23.0]#
[root@localhost istio-1.23.0]#
[root@localhost istio-1.23.0]# kubectl port-forward svc/bookinfo-gateway-istio 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
kubectl的port-forward工具,可以将本机端口转发到k8s集群里的service或者pod,用来方便测试
配置请求路由
- 背景
reviews
的三个不同版本已经部署并同时运行。在浏览器中访问 Bookinfo 应用程序的/productpage
并刷新几次。会注意到,有时书评的输出包含星级评分,有时则不包含。这是因为没有明确的默认服务版本可路由, Istio 将以循环方式将请求路由到所有可用版本。
1. Virtual Service 来定义路由规则。
- 作用:定义Virtual Service 将所有流量路由到每个微服务的 v1 版本
- 使用方法:
kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml
- 重点属性说明:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews 主机名,一般网关用,根据判断http请求的host来转发,备注:当productpage发送一个HTTP请求到`reviews`主机名时,这个请求会被Istio Ingress网关接收。
http:
- route:
- destination:
host: reviews 与虚拟服务的 hosts
不同,destination 的 host 必须是存在于 Istio 服务注册中心的实际目标地址,否则 Envoy 不知道该将请求发送到哪里。 可以是一个有代理的服务网格,或者是一个通过服务入口(service entry)被添加进来的非网格服务。 本示例运行在 Kubernetes 环境中,host 名为一个 Kubernetes 服务名:
subset: v1
2. 定义Destination Rules
- 作用:定义有哪些转发的目标(通常用来定义一个服务有哪些版本,vs转发到这些版本上去)
- 使用方法:
kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml
- 重点属性说明:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews 对应k8s的service名
subsets:
- name: v1
labels:
version: v1 对应reviews这个service的所有pod里,再筛选出有label为version=v1的pod
- name: v2
labels:
version: v2 对应reviews这个service的所有pod里,再筛选出有label为version=v2的pod
- name: v3
labels:
version: v3 对应reviews这个service的所有pod里,再筛选出有label为version=v3的pod
3. 验证
您可以通过再次刷新 Bookinfo 应用程序的 /productpage
轻松测试新配置。
无论您刷新多少次,页面的评论部分都不会显示评级星标。这是因为您将 Istio 配置为将评论服务的所有流量路由到版本 reviews:v1
,而此版本的服务不访问星级评分服务。