此篇博文istio相关介绍和测试用例来源于网络,这里结合自己配置加以整理。
成都创新互联公司-成都网站建设公司,专注成都网站建设、成都做网站、网站营销推广,域名注册,虚拟主机,绵阳服务器托管有关企业网站制作方案、改版、费用等问题,请联系成都创新互联公司。
官方中文参考文档
官方英文参考文档
服务网格(Service Mesh)这个术语通常用于描述构成这些应用程序的微服务网络以及应用之间的交互。随着规模和复杂性的增长,服务网格越来越难以理解和管理。它的需求包括服务发现、负载均衡、故障恢复、指标收集和监控以及通常更加复杂的运维需求,例如 A/B 测试、金丝雀发布、限流、访问控制和端到端认证等。
Istio 提供了一个完整的解决方案,通过为整个服务网格提供行为洞察和操作控制来满足微服务应用程序的多样化需求。
Istio 提供一种简单的方式来为已部署的服务建立网络,该网络具有负载均衡、服务间认证、监控等功能,只需要对服务的代码进行一点或不需要做任何改动。想要让服务支持 Istio,只需要在您的环境中部署一个特殊的 sidecar 代理,使用 Istio 控制平面功能配置和管理代理,拦截微服务之间的所有网络通信:
HTTP、gRPC、WebSocket 和 TCP 流量的自动负载均衡。
通过丰富的路由规则、重试、故障转移和故障注入,可以对流量行为进行细粒度控制。
可插入的策略层和配置 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 4h5m
istio-citadel-6955bc9cb7-b4jm4 1/1 Running 0 4h5m
istio-cleanup-secrets-9rm4c 0/1 Completed 0 4h5m
istio-egressgateway-7dc5cbbc56-gccmr 1/1 Running 0 4h5m
istio-galley-545b6b8f5b-pwckj 1/1 Running 0 3h8m
istio-grafana-post-install-stm7q 0/1 Completed 0 4h5m
istio-ingressgateway-7958d776b5-kf4xf 1/1 Running 0 4h5m
istio-pilot-567dd97ddc-mnmhg 2/2 Running 0 4h5m
istio-policy-5c689f446f-82lbn 2/2 Running 0 4h5m
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 4h5m
istio-sidecar-injector-99b476b7b-4twb2 1/1 Running 0 4h5m
istio-telemetry-55d68b5dfb-ftlbl 2/2 Running 0 4h5m
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 4h5m
prometheus-65d6f6b6c-bpk8q 1/1 Running 1 4h5m
servicegraph-57c8cbc56f-f92rs 1/1 Running 17 4h5m
[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 3000:28271/TCP 4h7m
istio-citadel ClusterIP 10.1.103.109 8060/TCP,9093/TCP 4h7m
istio-egressgateway ClusterIP 10.1.171.122 80/TCP,443/TCP 4h7m
istio-galley ClusterIP 10.1.60.32 443/TCP,9093/TCP 4h7m
istio-ingressgateway NodePort 10.1.105.144 80:31380/TCP,443:31390/TCP,31400:31400/TCP,15011:39182/TCP,8060:21878/TCP,853:35905/TCP,15030:22762/TCP,15031:20989/TCP 4h7m
istio-pilot ClusterIP 10.1.28.6 15010/TCP,15011/TCP,8080/TCP,9093/TCP 4h7m
istio-policy ClusterIP 10.1.208.196 9091/TCP,15004/TCP,9093/TCP 4h7m
istio-sidecar-injector ClusterIP 10.1.31.204 443/TCP 4h7m
istio-telemetry ClusterIP 10.1.178.158 9091/TCP,15004/TCP,9093/TCP,42422/TCP 4h7m
jaeger-agent ClusterIP None 5775/UDP,6831/UDP,6832/UDP 4h7m
jaeger-collector ClusterIP 10.1.63.111 14267/TCP,14268/TCP 4h7m
jaeger-query ClusterIP 10.1.235.64 16686/TCP 4h7m
prometheus NodePort 10.1.235.55 9090:28729/TCP 4h7m
servicegraph ClusterIP 10.1.30.255 8088/TCP 4h7m
tracing ClusterIP 10.1.114.120 80/TCP 4h7m
zipkin ClusterIP 10.1.212.242 9411/TCP 4h7m
为了对k8s中的各个命名空间进行监控和流量处理,需要对每个命名空间进行 Envoy 容器注入(确认Istio-sidecar-injector正常启动):
kubectl label 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进行轮询。