此篇博文istio相關介紹和測試用例來源於網絡,這裏結合本身配置加以整理。node
官方中文參考文檔nginx
官方英文參考文檔git
服務網格(Service Mesh)這個術語一般用於描述構成這些應用程序的微服務網絡以及應用之間的交互。隨着規模和複雜性的增加,服務網格愈來愈難以理解和管理。它的需求包括服務發現、負載均衡、故障恢復、指標收集和監控以及一般更加複雜的運維需求,例如 A/B 測試、金絲雀發佈、限流、訪問控制和端到端認證等。github
Istio 提供了一個完整的解決方案,經過爲整個服務網格提供行爲洞察和操做控制來知足微服務應用程序的多樣化需求。web
Istio 提供一種簡單的方式來爲已部署的服務創建網絡,該網絡具備負載均衡、服務間認證、監控等功能,只須要對服務的代碼進行一點或不須要作任何改動。想要讓服務支持 Istio,只須要在您的環境中部署一個特殊的 sidecar 代理,使用 Istio 控制平面功能配置和管理代理,攔截微服務之間的全部網絡通訊:json
HTTP、gRPC、WebSocket 和 TCP 流量的自動負載均衡。bootstrap
經過豐富的路由規則、重試、故障轉移和故障注入,能夠對流量行爲進行細粒度控制。api
可插入的策略層和配置 API,支持訪問控制、速率限制和配額。瀏覽器
對出入集羣入口和出口中全部流量的自動度量指標、日誌記錄和跟蹤。安全
Istio 旨在實現可擴展性,知足各類部署需求。
流量管理: 經過簡單的規則配置和流量路由,您能夠控制服務之間的流量和 API 調用。
通訊安全: Istio 的安全功能使開發人員能夠專一於應用程序級別的安全性。Istio 提供底層安全通訊信道,並大規模管理服務通訊的認證、受權和加密。
監控功能: 經過 Istio 的監控功能,能夠真正瞭解服務性能如何影響上游和下游的功能,而其自定義儀表板能夠提供對全部服務性能的可視性,並讓您瞭解該性能如何影響您的其餘進程。
跨平臺: Istio 是獨立於平臺的,旨在運行在各類環境中,包括跨雲、內部部署、Kubernetes、Mesos 等。
集成和定製: 策略執行組件能夠擴展和定製,以便與現有的 ACL、日誌、監控、配額、審計等方案集成。
Istio 服務網格邏輯上分爲數據平面和控制平面。
數據平面由一組以 sidecar 方式部署的智能代理(Envoy)組成。這些代理能夠調節和控制微服務及 Mixer 之間全部的網絡通訊。
Istio 使用 Envoy 代理的擴展版本,Envoy 是以 C++ 開發的高性能代理,用於調解服務網格中全部服務的全部入站和出站流量。Envoy 的許多內置功能被 istio 發揚光大,例如:
Envoy 被部署爲 sidecar,和對應服務在同一個 Kubernetes pod 中。
Mixer 是一個獨立於平臺的組件,負責在服務網格上執行訪問控制和使用策略,並從 Envoy 代理和其餘服務收集遙測數據。代理提取請求級屬性,發送到 Mixer 進行評估。
Pilot 爲 Envoy sidecar 提供服務發現功能,爲智能路由(例如 A/B 測試、金絲雀部署等)和彈性(超時、重試、熔斷器等)提供流量管理功能。它將控制流量行爲的高級路由規則轉換爲特定於 Envoy 的配置,並在運行時將它們傳播到 sidecar。
Citadel 經過內置身份和憑證管理能夠提供強大的服務間和最終用戶身份驗證。可用於升級服務網格中未加密的流量,併爲運維人員提供基於服務標識而不是網絡控制的強制執行策略的能力。從 0.5 版本開始,Istio 支持基於角色的訪問控制,以控制誰能夠訪問您的服務。
Galley 表明其餘的 Istio 控制平面組件,用來驗證用戶編寫的 Istio API 配置。隨着時間的推移,Galley 將接管 Istio 獲取配置、 處理和分配組件的頂級責任。它將負責將其餘的 Istio 組件與從底層平臺(例如 Kubernetes)獲取用戶配置的細節中隔離開來。
提示:在Minikube中運行須要至少8G內存和4核CPU。
參考文檔:https://thenewstack.io/tutorial-blue-green-deployments-with-kubernetes-and-istio
若是要成功部署istio,須要給kube-apiserver添加MutatingAdmissionWebhook
,ValidatingAdmissionWebhook
的參數,成功運行istio的kube-apiserver配置以下:
[Unit] Description=Kubernetes API Server Documentation=https://github.com/GoogleCloudPlatform/kubernetes After=network.target [Service] ExecStart=/opt/kubernetes/bin/kube-apiserver \ --enable-admission-plugins=MutatingAdmissionWebhook,ValidatingAdmissionWebhook,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota,NodeRestriction \ --bind-address=192.168.20.31 \ --insecure-bind-address=127.0.0.1 \ --authorization-mode=Node,RBAC \ --runtime-config=rbac.authorization.k8s.io/v1 \ --kubelet-https=true \ --anonymous-auth=false \ --basic-auth-file=/opt/kubernetes/ssl/basic-auth.csv \ --enable-bootstrap-token-auth \ --token-auth-file=/opt/kubernetes/ssl/bootstrap-token.csv \ --service-cluster-ip-range=10.1.0.0/16 \ --service-node-port-range=20000-40000 \ --tls-cert-file=/opt/kubernetes/ssl/kubernetes.pem \ --tls-private-key-file=/opt/kubernetes/ssl/kubernetes-key.pem \ --client-ca-file=/opt/kubernetes/ssl/ca.pem \ --service-account-key-file=/opt/kubernetes/ssl/ca-key.pem \ --requestheader-client-ca-file=/opt/kubernetes/ssl/ca.pem \ --requestheader-allowed-names= \ --requestheader-extra-headers-prefix="X-Remote-Extra-" \ --requestheader-group-headers=X-Remote-Group \ --requestheader-username-headers=X-Remote-User \ --proxy-client-cert-file=/opt/kubernetes/ssl/metrics-server.pem \ --proxy-client-key-file=/opt/kubernetes/ssl/metrics-server-key.pem \ --enable-aggregator-routing=true \ --runtime-config=api/all=true \ --etcd-servers=http://192.168.20.31:2379,http://192.168.20.32:2379,http://192.168.20.33:2379 \ --enable-swagger-ui=true \ --allow-privileged=true \ --audit-log-maxage=30 \ --audit-log-maxbackup=3 \ --audit-log-maxsize=100 \ --audit-log-path=/opt/kubernetes/log/api-audit.log \ --event-ttl=1h \ --v=2 \ --logtostderr=false \ --log-dir=/opt/kubernetes/log Restart=on-failure RestartSec=5 Type=notify LimitNOFILE=65536 [Install] WantedBy=multi-user.target
確認Metrics Server成功安裝,並正常運行:
# kubectl get apiservices |grep metrics-server v1beta1.metrics.k8s.io kube-system/metrics-server True 5d # kubectl get apiservices v1beta1.metrics.k8s.io -o yaml apiVersion: apiregistration.k8s.io/v1 kind: APIService metadata: creationTimestamp: 2018-11-07T06:23:17Z name: v1beta1.metrics.k8s.io resourceVersion: "747856" selfLink: /apis/apiregistration.k8s.io/v1/apiservices/v1beta1.metrics.k8s.io uid: 9d638462-e255-11e8-a817-000c29550ccc spec: group: metrics.k8s.io groupPriorityMinimum: 100 insecureSkipTLSVerify: true service: name: metrics-server namespace: kube-system version: v1beta1 versionPriority: 100 status: conditions: - lastTransitionTime: 2018-11-12T09:21:46Z message: all checks passed reason: Passed status: "True" type: Available # kubectl top node # k8s 1.12版本默認會使用metrics api NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% 192.168.20.32 580m 28% 2263Mi 61% 192.168.20.33 381m 19% 2317Mi 63%
執行以下命令,會下載安裝包並自動解壓縮:
curl -L https://git.io/getLatestIstio | sh -
進入 Istio 包目錄。例如,假設這個包是 istio-1.1.0.0:
cd istio-1.1.0
安裝目錄中包含:
添加bin目錄到系統的環境變量,或者將bin/istioctl文件拷貝到/usr/bin
,這樣在使用istioctl命令時就更加方便了:
export PATH=$PWD/bin:$PATH
安裝istio的自定義資源(CRD):
kubectl apply -f install/kubernetes/helm/istio/templates/crds.yaml
因爲是在沒有Rancher和雲供應商的環境中安裝istio,沒有LoadBalancer的支持,因此咱們須要將istio-1.0.3/install/kubernetes/istio-demo.yam 中的LoadBalancer
關鍵字修改成 NodePort
:
apiVersion: v1 kind: Service metadata: name: istio-ingressgateway namespace: istio-system annotations: labels: chart: gateways-1.0.3 release: istio heritage: Tiller app: istio-ingressgateway istio: ingressgateway spec: type: LoadBalancer # 將此處的LoadBalancer 修改成 NodePort selector: app: istio-ingressgateway istio: ingressgateway ports: - name: http2 nodePort: 31380 port: 80 targetPort: 80 - name: https nodePort: 31390 port: 443
用以下命令安裝不啓用 Sidecar 間雙向 TLS 認證的 Istio:
kubectl apply -f install/kubernetes/istio-demo.yaml
執行這個文件以後,咱們會發現已經安裝了多個服務和pod,而且建立了istio-system的命名空間:
[root@k8s-node-1 ~]# kubectl get pod -n istio-system NAME READY STATUS RESTARTS AGE grafana-546d9997bb-2z8nj 1/1 Running 0 4h4m istio-citadel-6955bc9cb7-b4jm4 1/1 Running 0 4h4m istio-cleanup-secrets-9rm4c 0/1 Completed 0 4h4m istio-egressgateway-7dc5cbbc56-gccmr 1/1 Running 0 4h4m istio-galley-545b6b8f5b-pwckj 1/1 Running 0 3h8m istio-grafana-post-install-stm7q 0/1 Completed 0 4h4m istio-ingressgateway-7958d776b5-kf4xf 1/1 Running 0 4h4m istio-pilot-567dd97ddc-mnmhg 2/2 Running 0 4h4m istio-policy-5c689f446f-82lbn 2/2 Running 0 4h4m istio-policy-5c689f446f-jl4lh 2/2 Running 1 102m istio-policy-5c689f446f-s4924 2/2 Running 0 3m14s istio-security-post-install-cgqtr 0/1 Completed 0 4h4m istio-sidecar-injector-99b476b7b-4twb2 1/1 Running 0 4h4m istio-telemetry-55d68b5dfb-ftlbl 2/2 Running 0 4h4m istio-telemetry-55d68b5dfb-l8xk6 2/2 Running 0 3h7m istio-telemetry-55d68b5dfb-t5kdz 2/2 Running 1 3h8m istio-telemetry-55d68b5dfb-zgljm 2/2 Running 0 3h8m istio-telemetry-55d68b5dfb-zxg7q 2/2 Running 1 3h8m istio-tracing-6445d6dbbf-92876 1/1 Running 0 4h4m prometheus-65d6f6b6c-bpk8q 1/1 Running 1 4h4m servicegraph-57c8cbc56f-f92rs 1/1 Running 17 4h4m [root@k8s-node-1 ~]# kubectl get svc -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE grafana NodePort 10.1.157.231 <none> 3000:28271/TCP 4h6m istio-citadel ClusterIP 10.1.103.109 <none> 8060/TCP,9093/TCP 4h6m istio-egressgateway ClusterIP 10.1.171.122 <none> 80/TCP,443/TCP 4h6m istio-galley ClusterIP 10.1.60.32 <none> 443/TCP,9093/TCP 4h6m istio-ingressgateway NodePort 10.1.105.144 <none> 80:31380/TCP,443:31390/TCP,31400:31400/TCP,15011:39182/TCP,8060:21878/TCP,853:35905/TCP,15030:22762/TCP,15031:20989/TCP 4h6m istio-pilot ClusterIP 10.1.28.6 <none> 15010/TCP,15011/TCP,8080/TCP,9093/TCP 4h6m istio-policy ClusterIP 10.1.208.196 <none> 9091/TCP,15004/TCP,9093/TCP 4h6m istio-sidecar-injector ClusterIP 10.1.31.204 <none> 443/TCP 4h6m istio-telemetry ClusterIP 10.1.178.158 <none> 9091/TCP,15004/TCP,9093/TCP,42422/TCP 4h6m jaeger-agent ClusterIP None <none> 5775/UDP,6831/UDP,6832/UDP 4h6m jaeger-collector ClusterIP 10.1.63.111 <none> 14267/TCP,14268/TCP 4h6m jaeger-query ClusterIP 10.1.235.64 <none> 16686/TCP 4h6m prometheus NodePort 10.1.235.55 <none> 9090:28729/TCP 4h6m servicegraph ClusterIP 10.1.30.255 <none> 8088/TCP 4h6m tracing ClusterIP 10.1.114.120 <none> 80/TCP 4h6m zipkin ClusterIP 10.1.212.242 <none> 9411/TCP 4h6m
爲了對k8s中的各個命名空間進行監控和流量處理,須要對每一個命名空間進行 Envoy 容器注入(確認Istio-sidecar-injector正常啓動):
kubectl label namespace <namespace> istio-injection=enabled EG: kubectl label namespace default istio-injection=enabled
若是要取消標記,使用以下命令:
kubectl label namespace default istio-injection-
理解原理:
istio提供了缺省的配置,會在帶有istio-injection=enabled標籤的命名空間中選擇pod,添加一個istio-proxy的容器,使用以下命令能夠編輯目標命名空間的範圍:
kubectl edit mutatingwebhookconfiguration istio-sidecar-injector
istio-system 命名空間中的 ConfigMap istio-sidecar-injector 中包含了缺省的注入策略以及 Sidecar 的注入模板。
有兩種注入策略:
disabled: Sidecar 注入器缺省不會向 Pod 進行注入。在 Pod 模板中加入 sidecar.istio.io/inject 註解並賦值爲 true 才能啓用注入。
enabled: Sidecar 注入器缺省會對 Pod 進行注入。在 Pod 模板中加入 sidecar.istio.io/inject 註解並賦值爲 false 就會阻止對這一 Pod 的注入
這裏使用jsonpath工具查看istio-ingressgateway的外部服務端口:
kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}'
查看grafana的外部映射端口,此端口上的服務展現了當前集羣的監控數據:
kubectl -n istio-system get service grafana -o jsonpath='{.spec.ports[?(@.name=="http")].nodePort}'
查看prometheus服務的端口:
kubectl -n istio-system get service prometheus -o yaml|grep nodePort
全部有UI界面的外部端口均可以經過瀏覽器採用 ip:端口 的方式正常訪問。
若是在默認的grafana模板中,沒有正常的展現出數據,能夠查看各個節點的時鐘是否同步,經過在查看網頁URL的請求在prometheus執行,看是否能獲得數據。
能夠按照官方提供的bookinfo示例對istio進行測試:https://istio.io/docs/examples/bookinfo/
這裏使用一個示例文件,部署兩個不一樣版本的nginx服務,對這兩個版本分流。建立myapp.yaml:
apiVersion: v1 kind: Service metadata: name: myapp labels: app: myapp spec: type: ClusterIP ports: - port: 80 name: http selector: app: myapp --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: myapp-v1 spec: replicas: 1 template: metadata: labels: app: myapp version: v1 spec: containers: - name: myapp image: janakiramm/myapp:v1 imagePullPolicy: IfNotPresent ports: - containerPort: 80 --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: myapp-v2 spec: replicas: 1 template: metadata: labels: app: myapp version: v2 spec: containers: - name: myapp image: janakiramm/myapp:v2 imagePullPolicy: IfNotPresent ports: - containerPort: 80
這個文件中,構建了簡單的基於Nginx的Docker鏡像來做爲應用案例:janakiramm/myapp:v1和janakiramm/myapp:v2。部署完成以後,這兩個版本的Nginx會分別顯示藍色或者綠色背景的靜態頁面。
執行:
kubectl apply -f myapp.yaml
成功建立後,使用port-forward
命令映射出本地端口,測試是否能成功訪問:
kubectl port-forward deployment/myapp-v1 8081:80 curl 127.0.0.1:8081
這裏分別建立了網關(Gateway)、目的地規則(DestinationRule)、虛擬服務(VirtualService)到app-gateway.yaml文件中:
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: app-gateway spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "*" --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: myapp spec: host: myapp subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2 --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: myapp spec: hosts: - "*" gateways: - app-gateway http: - route: - destination: host: myapp subset: v1 weight: 50 - destination: host: myapp subset: v2 weight: 50 ---
執行:
kubectl apply -f app-gateway.yaml
能夠經過istio-ingressgateway的端口來查看此服務:
kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}'
經過訪問此端口能夠直接訪問到應用服務,能夠發現當咱們不斷請求時,會根據以前設置的權重對v1和v2進行輪詢。