企业内项目接入istio流程
企业内接入istio常见有两种情况:
- 需要注入istio sidecar进行流量管理(东西流量)
- 不需要sidecar,只需要使用ingressGateway作为网关把服务发布出去(只需要南北流量管理)
针对第一种情况,在建立服务时,最好配置version标签;第二种情况不需要特殊处理,但是也推荐打上version标签,方便后期用sidecar管理。
同时也要考虑项目是否已经部署在集群内了:
- 新项目还未部署:按照istio的规范创建deployment和service,以及istio的核心资源
- 已经部署在集群中的:需要修改Deployment、Service,按需转换为ingressGateway对外提供服务
项目接入istio实战
测试项目架构
有一个测试项目demo,架构如下:

- 前端有个UI服务,域名根路径指向前端服务
- 两个后端服务通过/order和/receiveapi暴露访问:
- Receive Service(转发请求到Handler Service,返回一个随机密码)
- Order Service(查询订单,连接Mysql)
- Handler Service不暴露对外访问。
我们把这个项目改造为istio服务网格管理。
部署测试项目
kubectl create ns demo
mysql组件
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
namespace: demo
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
volumes:
- name: data
persistentVolumeClaim:
claimName: mysql-data
containers:
- name: mysql
image: registry.cn-beijing.aliyuncs.com/dotbalo/mysql:8.0.20
imagePullPolicy: IfNotPresent
env:
- name: MYSQL_ROOT_PASSWORD
value: password
volumeMounts:
- name: data
mountPath: /var/lib/mysql
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-data
namespace: demo
spec:
volumeMode: Filesystem
storageClassName: sc-nfs
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Mi
---
apiVersion: v1
kind: Service
metadata:
name: mysql
namespace: demo
spec:
type: NodePort
selector:
app: mysql
ports:
- nodePort: 32541
port: 3306
protocol: TCP
targetPort: 3306
# 部署好进入mysql配置数据库
mysql -uroot -p
create database orders;
CREATE USER 'order'@'%' IDENTIFIED BY 'password';
GRANT ALL ON orders.* TO 'order'@'%';
order服务
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-order
namespace: demo
spec:
replicas: 1
selector:
matchLabels:
app: demo-order
template:
metadata:
labels:
app: demo-order
version: v1 # istio改造,需要加上版本标签
spec:
containers:
- name: demo-order
image: registry.cn-beijing.aliyuncs.com/dotbalo/demo-order:v1
imagePullPolicy: IfNotPresent
env:
- name: MYSQL_HOST
value: mysql
- name: MYSQL_PORT
value: "3306"
- name: MYSQL_USER
value: order
- name: MYSQL_PASSWORD
value: password
- name: MYSQL_DB
value: orders
livenessProbe:
failureThreshold: 2
initialDelaySeconds: 30
periodSeconds: 5
successThreshold: 1
tcpSocket:
port: 8080
timeoutSeconds: 2
readinessProbe:
failureThreshold: 2
initialDelaySeconds: 30
periodSeconds: 5
successThreshold: 1
tcpSocket:
port: 8080
timeoutSeconds: 2
---
apiVersion: v1
kind: Service
metadata:
name: order
namespace: demo
spec:
selector:
app: demo-order
ports:
# istio中端口命名的要求:如果是http端口就叫http-80或者http-web;如果是TCP的就叫tcp-3306之类的
- name: http-web
port: 80
protocol: TCP
targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo-order
namespace: demo
spec:
ingressClassName: nginx
rules:
- host: demo.test.com
http:
paths:
- backend:
service:
name: order
port:
number: 80
path: /orders
pathType: ImplementationSpecific
handler服务
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-handler
namespace: demo
spec:
replicas: 1
selector:
matchLabels:
app: demo-handler
template:
metadata:
labels:
app: demo-handler
version: v1 # istio改造,加上版本标签
spec:
containers:
- name: demo-handler
env:
- name: SPRING_PROFILES_ACTIVE
value: k8supgrade
- name: SERVER_PORT
value: "8080"
image: registry.cn-beijing.aliyuncs.com/dotbalo/demo-handler:v0.0.1-upgrade
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 2
initialDelaySeconds: 30
periodSeconds: 5
successThreshold: 1
tcpSocket:
port: 8080
timeoutSeconds: 2
readinessProbe:
failureThreshold: 2
initialDelaySeconds: 30
periodSeconds: 5
successThreshold: 1
tcpSocket:
port: 8080
timeoutSeconds: 2
---
apiVersion: v1
kind: Service
metadata:
name: handler
namespace: demo
spec:
selector:
app: demo-handler
ports:
- name: http-web
port: 80
protocol: TCP
targetPort: 8080
receive服务
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-receive
namespace: demo
spec:
replicas: 1
selector:
matchLabels:
app: demo-receive
template:
metadata:
labels:
app: demo-receive
version: v1 # istio改造,加上版本标签
spec:
containers:
- name: demo-receive
image: registry.cn-beijing.aliyuncs.com/dotbalo/demo-receive:v0.0.1-upgrade
imagePullPolicy: Always
env:
- name: SPRING_PROFILES_ACTIVE
value: k8supgrade
- name: SERVER_PORT
value: "8080"
livenessProbe:
failureThreshold: 2
initialDelaySeconds: 30
periodSeconds: 5
successThreshold: 1
tcpSocket:
port: 8080
timeoutSeconds: 2
readinessProbe:
failureThreshold: 2
initialDelaySeconds: 30
periodSeconds: 5
successThreshold: 1
tcpSocket:
port: 8080
timeoutSeconds: 2
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
# 将用户请求路径重写为第二个捕获组 (.*) 的内容,去掉 /receiveapi 前缀,转发给后端demo-receive服务
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: demo-receive
namespace: demo
spec:
ingressClassName: nginx-default
rules:
- host: demo.test.com
http:
paths:
- backend:
service:
name: demo-receive
port:
number: 8080
path: /receiveapi(/|$)(.*)
pathType: ImplementationSpecific
---
apiVersion: v1
kind: Service
metadata:
name: demo-receive
namespace: demo
spec:
selector:
app: demo-receive
ports:
- name: http-web
port: 8080
protocol: TCP
targetPort: 8080
前端UI
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-ui
namespace: demo
spec:
replicas: 1
selector:
matchLabels:
app: demo-ui
template:
metadata:
labels:
app: demo-ui
version: v1 # istio项目改造,加上版本标签
spec:
containers:
- name: demo-ui
image: registry.cn-beijing.aliyuncs.com/dotbalo/demo-ui:sw
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 2
initialDelaySeconds: 10
periodSeconds: 5
successThreshold: 1
tcpSocket:
port: 80
timeoutSeconds: 2
readinessProbe:
failureThreshold: 2
initialDelaySeconds: 10
periodSeconds: 5
successThreshold: 1
tcpSocket:
port: 80
timeoutSeconds: 2
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo-ui
namespace: demo
spec:
ingressClassName: nginx-default
rules:
- host: demo.test.com
http:
paths:
- backend:
service:
name: demo-ui
port:
number: 80
path: /
pathType: ImplementationSpecific
---
apiVersion: v1
kind: Service
metadata:
labels:
app: demo-ui
name: demo-ui
namespace: demo
spec:
selector:
app: demo-ui
ports:
- name: http-web
port: 80
protocol: TCP
targetPort: 80
访问项目
宿主机添加host,通过前端UI的ingress访问:demo.test.com
接入istio南北流量改造
如果想要使用Istio管理南北流量,建议服务的入口使用IngressGateway进行管理,也就是需要把之前由其他控制器管理的Ingress改造为由Istio Gateway管理(新项目直接创建即可,无需改造)。
确认待改造ingress
首先确认当前项目的ingress配置有哪些:
kubectl get ingress -n demo
NAME CLASS HOSTS
demo-order nginx-default demo.test.com
demo-receive nginx-default demo.test.com
demo-ui nginx-default demo.test.com
建议先改造后端再改造前端
为项目创建Gateway
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: demo-gateway
namespace: demo
spec:
selector:
istio: ingressgateway # 使用默认的istio ingress gateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "demo.test.com" # 发布域名
创建VirtualService
接下来需要创建VirtualService和Gateway绑定
order服务
看demo-order的ingress定义,把/orders路径转发到order svc,端口号是80。创建同样规则的VirtualService:
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: demo-order
namespace: demo
spec:
hosts:
- "demo.test.com"
gateways:
- demo-gateway
http:
- match:
- uri:
prefix: /orders
route:
- destination:
host: order.demo.svc.cluster.local
port:
number: 80
vs创建完成后就可以通过域名+ingressGateway端口号访问到服务了:demo.test.com:30080/orders
receive服务
看receive服务的ingress定义,里面有路径重写,将用户请求路径重写为第二个捕获组 (.*) 的内容,去掉 /receiveapi 前缀,转发给后端demo-receive服务的8080端口。
创建同样规则的VirtualService:
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: demo-receive
namespace: demo
spec:
hosts:
- "demo.test.com"
gateways:
- demo-gateway
http:
- match:
- uri:
prefix: /receiveapi/ # 注意rewtire时前端路径要把最后的/写上,全部rewrite成/。这样后端服务就不会多一个/了
rewrite:
uri: /
route:
- destination:
host: demo-receive.demo.svc.cluster.local
port:
number: 8080
前端ui服务
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: demo-ui
namespace: demo
spec:
hosts:
- "demo.test.com"
gateways:
- demo-gateway
http:
- match:
- uri:
prefix: /
route:
- destination:
host: demo-ui
port:
number: 80
创建完成后,访问根路径demo.test.com:30080/验证。
删除ingress
验证VirtualService和Gateway可以访问到发布的域名之后,就可以删掉现存的ingress了。
接入istio东西流量改造
如果需要istio管理东西流量,需要istio的sidecar注入,然后再通过DR和VS控制内部流量。
ns添加istio注入标签
首先向demo命名空间添加istio标签:
kubectl label ns demo istio-injection=enabled
重建pod
rollout restart所有deployment和sts,滚动更新之后,istio sidecar会加到pod里面。
创建dr和vs
之后给需要管理东西流量的Service创建VirtualService和DestinationRule,方便更细力度控制流量。
比如handler服务是对内暴露的,可以进行东西流量改造。对handler服务创建VirtualService和DestinationRule:
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: handler
namespace: demo
spec:
host: handler.demo.svc.cluster.local
subsets:
- name: v1
labels:
version: v1
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: handler
namespace: demo
spec:
hosts:
- handler.demo.svc.cluster.local
http:
- route:
- destination:
host: handler.demo.svc.cluster.local
port:
number: 80
subset: v1 # 流量指向v1
改造完成后可以在kiali界面查看流量图:http://192.168.40.180:31096/kiali/console/graph/