文章目录
目的: 根据不同的引擎版本,可以把请求发送到指定的引擎上。可以实现版本降级。
原理
Istio通过VirtualService和DestinationRule两个资源对象来实现流量管理,其中VirtualService用于定义流量路由规则,而DestinationRule用于定义服务的负载均衡策略和TLS设置
- VirtualService: 实现服务请求路由规则的动能
- DestinationRule: 实现⽬标服务的负载均衡、服务发现、故障处理和故障注⼊的功能
- Gateway: 让服务⽹格内的服务,可以被全世界看到
- ServiceEntry: 让服务⽹格内的服务,可以看到外⾯的世界
实现
Deployment
shell
{{- $revisionHistoryLimit := .Values.revisionHistoryLimit -}}
{{- $replicaCount := .Values.replicaCount -}}
{{- $autoscaling := .Values.autoscaling.enabled -}}
{{- $podAnnotations := .Values.podAnnotations -}}
{{- $imagePullSecrets := .Values.imagePullSecrets -}}
{{- $podSecurityContext := .Values.podSecurityContext -}}
{{- $securityContext := .Values.securityContext -}}
{{- $pullPolicy := .Values.pullPolicy -}}
{{- $port := .Values.service.port -}}
{{- $resources := .Values.resources -}}
{{- $nodeSelector := .Values.nodeSelector -}}
{{- $repository := .Values.image.repository -}}
{{- $affinity := .Values.affinity -}}
{{- $tolerations := .Values.tolerations -}}
{{- range $num,$tag := .Values.image.tag -}}
{{- $version := add $num 1 -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "grpc-manifest.fullname" $ }}-v{{ $version }}
labels:
{{- include "grpc-manifest.labels" $ | nindent 4 }}
app.kubernetes.io/tag: v{{ $version }}
app.kubernetes.io/type: grpc
spec:
revisionHistoryLimit: {{ $revisionHistoryLimit | default 5 }}
{{- if not $autoscaling }}
replicas: {{ $replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "grpc-manifest.selectorLabels" $ | nindent 6 }}
app.kubernetes.io/tag: v{{ $version }}
app.kubernetes.io/type: grpc
...
{{end }}
作用:可以根据版本生成对应的服务
VirtualService
yaml
{{- define "grpc-manifest.gateway" -}}
{{- $port := .Values.services.port }}
{{- range $num,$image := .Values.image.tag }}
{{- $version := add $num 1 }}
- match:
- headers:
grpcsvc:
exact: v{{ $version }}
route:
- destination:
host: {{ include "grpc-manifest.fullname" $ }}
port:
number: {{ $port }}
subset: v{{ $version }}
{{- end }}
{{- end }}
例子中,虚拟服务将流量分发服务的两个子集:v$version
。也可设置权重默认是 100
,表示 携带 header为grpcsvc: v$version
的流量将全量被路由到 v$version
DestinationRule
目标规则定义了如何将请求路由到实际的服务实例。每个目标规则关联到一个虚拟服务的子集
yaml
{{- define "grpc-manifest.route" -}}
{{- range $num,$image := .Values.image.tag }}
{{- $version := add $num 1 }}
- name: v{{ $version }}
labels:
app.kubernetes.io/instance: {{ include "grpc-manifest.fullname" $ }}
app.kubernetes.io/tag: v{{ $version }}
{{- end }}
{{- end }}
例子中,目标规则将子集 v$version
分别映射到具有相应标签的实际服务实例。
需要多个版本同时部署时,会根据镜像自动更新资源配置
yaml
[root@ycloud grpc-manifest]# cat env/devel/image_tag.yaml
image:
tag:
- v1.0.1
- v1.0.2
- v1.0.3
- v1.0.4
约束
根据定义好的行为实现
访问通过添加metadata
的方式来选择指定的版本,并且如果访问中 metadata
指定有误要做降级策略,给默认且可正常运行的版本
eg: (案例仅限测试,生产根据实际需求更新)
yaml
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: {{ include "grpc-manifest.fullname" . }}
spec:
workloadSelector:
labels:
app: istio-ingressgateway
configPatches:
- applyTo: HTTP_FILTER
match:
context: GATEWAY
listener:
filterChain:
filter:
name: "envoy.filters.network.http_connection_manager"
subFilter:
name: "envoy.filters.http.router"
patch:
operation: INSERT_BEFORE
value:
name: envoy.filters.http.lua
typed_config:
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
inlineCode: |
function envoy_on_request(request_handle)
local contentType = request_handle:headers():get("content-type")
if contentType and string.find(contentType, "grpc") then
local grpcSvcHeader = request_handle:headers():get("grpcsvc")
local allowedVersions = {"v1", "v2", "v3", "v4"}
local isInAllowedVersions = false
for _, allowedVersion in ipairs(allowedVersions) do
if grpcSvcHeader == allowedVersion then
isInAllowedVersions = true
break
end
end
if not isInAllowedVersions then
request_handle:headers():replace("grpcsvc", "v1")
end
end
end
部署
待实现 自动部署和之前服务有出入,需要针对这个服务做调整,主要判断,通过版本引擎来自动更新旧版本
具体 Helm 案例届时会更新到
GitHub