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例子
istio要求调用方同样位于istio环境的容器中,nginx-master.yaml用于调用测试
# 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配置
# 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
- 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'
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