istio
简介
Istio:是一个开源的服务网格(Service Mesh)平台,主要用于连接、管理微服务。无需修改应用代码为分布式应用提供了流量管理、安全、可观测性等功能。
服务网格(Service Mesh):是一种基础设施层,用于处理服务间的通信、监控、安全等,与业务逻辑解耦。
Sidecar模式:Istio通过在每个Pod旁边注入一个Proxy(通常是 Envoy),拦截和管理所有进出该Pod的流量(多为HTTP,也支持TCP和UDP)。
组件
Envoy:代理,负责数据面流量的拦截、转发、加密、限流等。
Pilot:控制面,负责服务发现、流量管理策略的下发。
Citadel:提供服务间的身份认证和密钥管理(安全)。
istiod:Istio 1.5+ 的统一控制面,整合了 Pilot、Citadel、Galley 等功能。
Ingress/Egress Gateway:负责集群流量的统一入口和出口。
istio安装
mkdir -r /k8s/istio && cd /k8s/istio
curl -L https://istio.io/downloadIstio | sh -
echo 'export PATH="$PATH:/k8s/istio/istio-1.28.0/bin"' >> ~/.bashrc && source ~/.bashrc
istioctl x precheck
cd istio-1.28.0
istioctl install
kubectl label namespace default istio-injection=enabled
kubectl set resources deployment/istiod -n istio-system --containers=discovery --requests=cpu=100m,memory=500Mi --limits=cpu=400m,memory=1Gi
kubectl set resources deployment/istio-ingressgateway -n istio-system --containers=istio-proxy --requests=cpu=100m,memory=256Mi --limits=cpu=500m,memory=512Mi
istio-nginx例子
nginx-master.yaml
istio要求调用方同样位于istio环境的容器中,nginx-master.yaml用于调用测试
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment-master
spec:
replicas: 1
selector:
matchLabels:
app: nginx-master
template:
metadata:
labels:
app: nginx-master
spec:
containers:
- name: nginx-container-master
image: nginx:latest
ports:
- containerPort: 80
nginx-online表示正式环境
# nginx-online.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
isCanary: 'false'
template:
metadata:
labels:
app: nginx
isCanary: 'false'
spec:
containers:
- name: nginx-container
image: nginx:latest
ports:
- containerPort: 80
lifecycle:
postStart:
exec:
command:
- /bin/sh
- -c
- sed -i "s/Welcome to nginx\!/Welcome to ${HOSTNAME}\!/g" /usr/share/nginx/html/index.html
nginx-canary-1表示金丝雀1
# nginx-canary-1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment-canary-1
spec:
replicas: 1
selector:
matchLabels:
app: nginx
isCanary: 'true'
canaryId: '1'
template:
metadata:
labels:
app: nginx
isCanary: 'true'
canaryId: '1'
spec:
containers:
- name: nginx-container-canary-1
image: nginx:latest
ports:
- containerPort: 80
lifecycle:
postStart:
exec:
command:
- /bin/sh
- -c
- sed -i "s/Welcome to nginx!/Welcome to ${HOSTNAME}!/g" /usr/share/nginx/html/index.html
nginx-canary-2表示金丝雀2
# nginx-canary-2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment-canary-2
spec:
replicas: 1
selector:
matchLabels:
app: nginx
isCanary: 'true'
canaryId: '2'
template:
metadata:
labels:
app: nginx
isCanary: 'true'
canaryId: '2'
spec:
containers:
- name: nginx-container-canary-2
image: nginx:latest
ports:
- containerPort: 80
lifecycle:
postStart:
exec:
command:
- /bin/sh
- -c
- sed -i "s/Welcome to nginx!/Welcome to ${HOSTNAME}!/g" /usr/share/nginx/html/index.html
nginx的Service,通配nginx匹配
# nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
selector:
app: nginx
ports:
- name: web
protocol: TCP
port: 5000
targetPort: 80
type: ClusterIP
istio配置
VirtualService负责拦截请求并根据匹配的规则路由到不同的host和subset。
DestinationRule负责定义host的不同subset,并通过标签(labels)将流量映射到具体的服务实例。
VS中优先级同时符合多个条目时,靠上方的优先级更高。
多个不同name的VS文件配置同一个hosts,后应用的VS会覆盖先应用的相同的 VS规则。
# nginx-vs.yaml
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: nginx
spec:
hosts:
- nginx.default.svc.cluster.local
http:
- match:
- headers:
canary_id:
exact: '1'
route:
- destination:
host: nginx.default.svc.cluster.local
subset: canary-1
weight: 50 # 配置分流
- destination:
host: nginx.default.svc.cluster.local
subset: canary-11
weight: 50
- match:
- headers:
canary_id:
exact: '2'
route:
- destination:
host: nginx.default.svc.cluster.local
subset: canary-2
- route:
- destination:
host: nginx.default.svc.cluster.local
subset: online
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: nginx
spec:
host: nginx.default.svc.cluster.local
subsets:
- name: online
labels:
isCanary: 'false'
- name: canary-1
labels:
isCanary: 'true'
canaryId: '1'
- name: canary-2
labels:
isCanary: 'true'
canaryId: '2'
- name: canary-11
labels:
isCanary: 'true'
canaryId: '11'
exportTo: # 所有命名空间生效,分命名空间怎么用?
- '*'
istio-nginx测试
kubectl exec -it nginx-deployment-master-d9dfb9976-x28s5 -- bash
curl -s nginx:5000 -H "canary_id: 1" | grep "Welcome to"
<title>Welcome to nginx-deployment-canary-1-d4d4f9577-9dlvp!</title>
<h1>Welcome to nginx-deployment-canary-1-d4d4f9577-9dlvp!</h1>
curl -s nginx:5000 -H "canary_id: 2" | grep "Welcome to"
<title>Welcome to nginx-deployment-canary-2-558b489475-d6ppx!</title>
<h1>Welcome to nginx-deployment-canary-2-558b489475-d6ppx!</h1>
curl -s nginx:5000 -H "canary_id: 3" | grep "Welcome to"
<title>Welcome to nginx-deployment-748c545c49-mnsnq!</title>
<h1>Welcome to nginx-deployment-748c545c49-mnsnq!</h1>
curl -s nginx:5000 | grep "Welcome to"
<title>Welcome to nginx-deployment-748c545c49-mnsnq!</title>
<h1>Welcome to nginx-deployment-748c545c49-mnsnq!</h1>
配置的1和2都前往了对应的分组,未配置的3和空则走了默认的分组。
原理
- 创建一个Service,得到一个域名nginx.default.svc.cluster.local
- POD客户端(这个客户端也必须被注入了Istio)访问这个域名
- 流量被转发到POD客户端的istio-proxy(Envoy),访问nginx.default.svc.cluster.local不再是直达经过标签选择的pod,而是被转发到Envoy
- Envoy查询VS,使用hosts比对得到上面的VS规则,按断http协议的请求是否存在canary_id这个header,都是则继续查找nginx.default.svc.cluster.local的canary这个subset
- Envoy查询DestinationRule,判断nginx.default.svc.cluster.local的canary这个subset的规则,得到规则为存在canaryId: ‘1’这个标签
- 最终转发到存在canaryId: ‘1’标签的nginx-deployment-canary-1
Istio+Envoy的组合只会拦截TCP和UDP流量,不会拦截ping的ICMP流量
注册和配置收集
- pod被注入istio-proxy后,Envoy进程会自动启动
- Envoy尝试连接Istio控制面,报告自己的身份
- Istio控制面收集VS,DR等配置,计算这个Envoy的相关配置
- 默认情况下本命名空间的服务都被认为相关
- 所有被注入了Envoy的服务
- Istio控制面根据身份信息推送对应的Envoy配置
kiali安装
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.28/samples/addons/kiali.yaml
kubectl -n istio-system get svc kiali
kubectl -n istio-system port-forward svc/kiali 20001:20001 --address="0.0.0.0"
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/addons/prometheus.yaml
kubectl -n istio-system get pod,svc | grep -i prometheus
kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \
kubectl apply --server-side -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/experimental-install.yaml
get vs和get virtualservice和get virtualservice.networking.istio.io
virtualservice.networking.istio.io是CRD的全名
vs一般是默认的注册短名