Istio是一個用於鏈接、管理以及安全化微服務的開放平臺, 提供了一種簡單的方式用於建立微服務網絡,並提供負載均衡/服務間認證/監控等能力,關鍵的是並不須要修改服務自己. 主要提供如下功能:html
Envoy 是一個面向服務架構的L7代理和通訊總線而設計的,這個項目誕生是出於如下目標:nginx
Envoy將做爲一個獨立的sidecar與相關微服務部署在同一個Kubernetes的pod上,並提供一系列的屬性給Mixer。Mixer以此做爲依據執行策略,併發送到監控系統.json
這種sidecar代理模型不須要改變任何服務自己的邏輯,並能增長一系列的功能.後端
後端的基礎設施經常被設計用於提供創建服務支持的功能,包括訪問控制系統、遙測數據捕獲系統、配額執行系統以及計費系統等。傳統服務會直接和這些後端系統打交道,和後端緊密耦合,並集成其中的個性化語義以及用法。安全
Mixer的設計目的是改變層次之間的邊界,以此來下降整體的複雜性。從服務代碼中剔除策略邏輯,改由運維人員進行控制。
這些機制的應用是基於一組 屬性 的,每一個請求都會將這些屬性呈現給Mixer。在Istio中,這些屬性來自於Sidecar代理(Envoy)的每一次請求。
request.path: xyz/abc
request.size: 234
request.time: 12:34:56.789 04/17/2017
source.ip: 192.168.0.1
target.service: example複製代碼
這裏的例子配置了一個類型爲 listchecker 的適配器。listchecker適配器使用一個列表來檢查輸入。若是配置的是白名單模式且輸入值存在於列表之中,就會返回成功的結果。
apiVersion: config.istio.io/v1alpha2
kind: listchecker
metadata:
name: staticversion
namespace: istio-system
spec:
providerUrl: http://white_list_registry/
blacklist: false複製代碼
配置實例將請求中的屬性映射成爲適配器的輸入, 注意Handler配置中須要的全部維度都定義在這一映射之中。
apiVersion: config.istio.io/v1alpha2
kind: metric
metadata:
name: requestduration
namespace: istio-system
spec:
value: response.duration | "0ms"
dimensions:
destination_service: destination.service | "unknown"
destination_version: destination.labels["version"] | "unknown"
response_code: response.code | 200
monitored_resource_type: '"UNSPECIFIED"'複製代碼
apiVersion: config.istio.io/v1alpha2
kind: rule
metadata:
name: promhttp
namespace: istio-system
spec:
match: destination.service == "service1.ns.svc.cluster.local" && request.headers["xuser"] == "user1"
actions:
- handler: handler.prometheus
instances:
- requestduration.metric.istio-system複製代碼
例如,k8s中,一個服務foo就會有一個域名foo.default.svc.cluster.local hostname,虛擬IP10.0.1.1以及可能的監聽端口。
Istio的規則配置提供了一個基於pb的模式定義。這些規則內容存儲在一個KVstore中,pilot訂閱了這些配置信息的變化,以便更新istio其餘組件的配置內容。
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
name: reviews-default
spec:
destination:
name: reviews
route:
- labels:
version: v1
weight: 100複製代碼
GET /v1/registration/(string: service_name)
請求發現服務返回指定service_name的全部主機, 返回如下JSON格式的響應:
{
"hosts": []
}
const std::string Json::Schema::SDS_SCHEMA(R"EOF( { "$schema": "http://json-schema.org/schema#",
"definitions" : {
"host" : {
"type" : "object",
"properties" : {
"ip_address" : {"type" : "string"},
"port" : {"type" : "integer"},
"tags" : {
"type" : "object",
"properties" : {
"az" : {"type" : "string"},
"canary" : {"type" : "boolean"},
"load_balancing_weight": {
"type" : "integer",
"minimum" : 1,
"maximum" : 100
}
}
}
},
"required" : ["ip_address", "port"]
}
},
"type" : "object",
"properties" : {
"hosts" : {
"type" : "array",
"items" : {"$ref" : "#/definitions/host"}
}
},
"required" : ["hosts"]
}
)EOF");複製代碼
這兒不得不提的是pilot的 proxy injection 能力,你可能已經想到了它是基於iptable規則來實現的。這樣全部的服務交互都會被pilot捕獲並從新轉發。
提供服務間以及用戶之間的認證,確保不須要修改服務code的前提下加強服務之間的安全性. 主要包括如下3個組件:
Istio的分佈式跟蹤是基於Twitter開源的zipkin分佈式跟蹤系統,理論模型來自於Google Dapper 論文.
安裝Istio時會啓動zipkin addon,固然也可使用以下命令啓動:
kubectl apply -f install/kubernetes/addons/zipkin.yaml複製代碼
訪問zipkin dashboard: http://localhost:9411
kubectl port-forward $(kubectl get pod -l app=zipkin -o jsonpath='{.items[0].metadata.name}') 9411:9411複製代碼
服務自己實現須要作必定的改動,即從最初始的HTTP請求中獲取如下header並傳遞給其餘的請求:
x-request-id
x-b3-traceid
x-b3-spanid
x-b3-parentspanid
x-b3-sampled
x-b3-flags
x-ot-span-context複製代碼
在Kubernetes環境下, Istio使用了內置的Ingress來暴露服務,目前支持HTTP和HTTPS兩種方式. 具體的Ingress,參見Kubernetes Ingress.
cat <<EOF | kubectl create -f -
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: simple-ingress
annotations:
kubernetes.io/ingress.class: istio
spec:
rules:
- http:
paths:
- path: /headers
backend:
serviceName: httpbin
servicePort: 8000
- path: /delay/.*
backend:
serviceName: httpbin
servicePort: 8000
EOF複製代碼
cat <<EOF | kubectl create -f -
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: secured-ingress
annotations:
kubernetes.io/ingress.class: istio
spec:
tls:
- secretName: ingress-secret
rules:
- http:
paths:
- path: /ip
backend:
serviceName: httpbin
servicePort: 8000
EOF複製代碼
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Service
metadata:
name: externalbin
spec:
type: ExternalName
externalName: httpbin.org
ports:
- port: 80
# important to set protocol name
name: http
EOF複製代碼
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Service
metadata:
name: securegoogle
spec:
type: ExternalName
externalName: www.google.com
ports:
- port: 443
# important to set protocol name
name: https
EOF複製代碼
其中, metadata.name 就是內部服務所須要訪問的外部服務的名稱, spec.externalName則是外部服務的DNS名稱.
export SOURCE_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
kubectl exec -it $SOURCE_POD -c sleep bash
curl http://externalbin/headers
curl http://securegoogle:443複製代碼
kubectl apply -f <(istioctl kube-inject -f samples/apps/sleep/sleep.yaml --includeIPRanges=10.0.0.1/24)複製代碼
默認配置下,Istio會將全部的請求路由到同一個服務的全部版本上.此外,Istio提供了根據請求內容的路由規則,以下規則描述了全部的請求都會指向服務的版本v1:
type: route-rule
name: ratings-default
namespace: default
spec:
destination: ratings.default.svc.cluster.local
precedence: 1
route:
- tags:
version: v1
weight: 100
---
type: route-rule
name: reviews-default
namespace: default
spec:
destination: reviews.default.svc.cluster.local
precedence: 1
route:
- tags:
version: v1
weight: 100
---
type: route-rule
name: details-default
namespace: default
spec:
destination: details.default.svc.cluster.local
precedence: 1
route:
- tags:
version: v1
weight: 100
---
type: route-rule
name: productpage-default
namespace: default
spec:
destination: productpage.default.svc.cluster.local
precedence: 1
route:
- tags:
version: v1
weight: 100
---複製代碼
若是須要將某些請求指向其餘版本的服務,如根據請求的cookie進行路由:
destination: reviews.default.svc.cluster.local
match:
httpHeaders:
cookie:
regex: ^(.*?;)?(user=jason)(;.*)?$
precedence: 2
route:
- tags:
version: v2複製代碼
其餘具體的規則,參見: https://istio.io/docs/reference/config/traffic-rules/routing-rules.html#routerule
destination: ratings.default.svc.cluster.local
httpFault:
delay:
fixedDelay: 7s
percent: 100
match:
httpHeaders:
cookie:
regex: "^(.*?;)?(user=jason)(;.*)?$"
precedence: 2
route:
- tags:
version: v1複製代碼
HTTP請求超時能夠經過在路由規則中設置字段httpReqTimeout實現.
具體例子以下:
cat <<EOF | istioctl replace
type: route-rule
name: reviews-default
spec:
destination: reviews.default.svc.cluster.local
route:
- tags:
version: v2
httpReqTimeout:
simpleTimeout:
timeout: 1s
EOF複製代碼
在Istio的mixer中配置限流規則,以下ratelimit.yaml:
rules:
- selector: source.labels["app"]=="reviews" && source.labels["version"] == "v3"
- aspects:
- kind: quotas
params:
quotas:
- descriptorName: RequestCount
maxAmount: 5000
expiration: 5s
labels:
label1: target.service複製代碼
若是target.service=rating, 那麼計數器的key則爲:
$aspect_id;RequestCount;maxAmount=5000;expiration=5s;label1=ratings複製代碼
執行以下命令可使得rating服務的請求控制在每5秒5000次(限定在reviews v3服務在調用時生效):
istioctl mixer rule create global ratings.default.svc.cluster.local -f ratelimit.yaml複製代碼
rules:
- aspects:
- kind: denials
selector: source.labels["app"]=="reviews" && source.labels["version"] == "v3"複製代碼
執行以下命令可使rating服務拒絕來自reviews v3服務的任何請求.
- name: versionList
impl: genericListChecker
params:
listEntries: ["v1", "v2"]複製代碼
啓用白名單時blacklist設置爲false,反之爲true.
rules:
aspects:
- kind: lists
adapter: versionList
params:
blacklist: false
checkExpression: source.labels["version"]複製代碼