极客时间-Service Mesh实战(概念部分)

时间:Feb. 16, 2021 分类:

目录:

极客时间-Service Mesh实战

01 课程介绍

微服务在带来便利的时候也会存在缺点,其中核心的问题就是服务间的网络通信,随着规模变大就会越来越突出,Service Mesh就是为了解决这个问题而生的,可以让开发从通信问题中解脱出来,省去了开发和维护控制逻辑的工作,让开发人员只关注业务。

Service Mesh被称为第二代微服务也并无道理。云原生是未来软件架构的方向,kubernetes(操作系统)和Service Mesh(应用层网络),serviceless(不用关注机器与实例),Service Mesh让服务与通讯解耦,只关注业务,而不用在业务逻辑中夹杂大量超时重试的控制逻辑,也不用集成各种流量控制的类库工具包,代码中只有业务本身。

Service Mesh经历了

  • 16年概念的提出
  • 17年几个重量级产品的发布

时至今日才经历了4年的时间

02 内容综述

03 Service Mesh的起源:为什么出现Service Mesh技术?

微服务的特性

围绕业务构建团队

期初开发的团队根据职能划分为了不同的团队,开发的团队根据功能划分为了不同的团队。

后者是

  • 团队层面:内聚,独立开发业务,没有依赖
  • 产品层面:服务彼此独立,没有依赖,可以根据服务的请求量决定服务的部署数量

康威理论里也讲,一个团队的结构会决定开发产品的结构

去中心化的数据管理

数据库和业务会绑定在一起

微服务也会带来缺点,就是服务间网络通信问题的排查

网络通信会成为痛点,主要就是因为分布式的8个谬论

  • 网络是可靠的
  • 网络延迟是0
  • 网络带宽是无限的
  • 网络是安全的
  • 网络拓扑是不变的
  • 只有一个管理员
  • 传输成本为0
  • 网络是同构的

开发业务系统的时候,潜意识会忽略这个网络的问题,会导致这8个谬论的产生

在分布式系统中,微服务架构服务会越来越多,变的更离散,交互也会越来越多,就会造成这个网络的痛点,所以才引入了管理和控制服务间的通信

在管理过程中

  • 服务注册和发现
  • 路由,流量转移
  • 弹性能力(熔断,超时,重试)
  • 安全
  • 可观测性

04 Service Mesh发展:Service Mesh技术是如何演进的?

第一阶段:控制逻辑和业务逻辑耦合

第二阶段:公共库(把控制逻辑集中在一起,会有人力的学习成本和维护成本,语言绑定和侵入性的问题)

第三阶段:代理模式(配置简陋)

第四阶段:Sidecar(边车模式,通过Sidecar来接收和转发请求)

第五阶段:Service Mesh

05 微服务通信的救市良方:什么是Service Mesh?它能帮助你做什么?

Service Mesh是一个基础设施层,用于处理服务与服务的通信,它主要的功能是在云原生应用这种复杂的服务拓扑进行请求分发,一般是一组轻量化的网络代理,部署在应用代码旁边,和应用是完全透明的

06 列王的纷争:史上有那些主流的Service Mesh

Service Mesh产品的发展史

2016年

  • Linkerd
  • 9月Envoy1.0版本发布

2017年

  • Linkerd加入cncf
  • 4月Linkerd 1.0发布
  • 9月Istio 0.1发布
  • 9月Envoy加入cncf
  • 12月Conduit发布

2018年

  • 7月Istio 1.0发布
  • Envoy稳定发布
  • Conduit并入了Linkerd2.0
  • 国内大厂参与

2019年

  • 3月Istio 1.1发布
  • 4月AWS App Mesh GA
  • 5月Google Taffic Director beta发布
  • 9月Kong发布Kuma
  • 蚂蚁金服Mosh支持双十一

2020年

  • 3月Istio 1.5发布

详细的介绍

Linkerd作为一个数据平面

  1. 对比Envoy没有优势
  2. 选择了Rust的小种语言,得不到社区支持
  3. 产品独立,没有云厂商支持

Envoy

  1. 性能稳定可靠
  2. Istio的默认数据平面
  3. xDS协议是数据平面的标准

Istio

  1. 收编Envoy,直接有高水准的数据平面

07 王者的诞生:为什么Istio有如此高的呼声

Istio数据平面的基础上,增加了控制平面

  1. 出击及时:17年发布狙击Linkerd
  2. 光环加持:Google,IBM和Lyft
  3. 第二代Service Mesh
  4. Envoy加入
  5. 功能强大

为什么要使用Istio

  1. 可以很轻松构建服务网格
  2. 应用代码无需修改

功能分四个方面

  • 流量控制:路由,流量转移,弹性(超时,重试,熔断),测试(故障注入,流量镜像)
  • 安全:授权,认证
  • 可观测性:指标,日志,可追踪
  • 策略:限流,黑白名单

在1.5版本,去掉了策略相关,是因为去掉了Mixer模块,将功能转移到Envoy中

Istio版本迭代历程

  • 17.05 发布了v0.1
  • 18.07 发布了v1.0,可应用于生产
  • 19.03 发布了v1.1 架构重构,企业级可用
  • 19.06 发布了v1.2
  • 19.09 发布了v1.3
  • 19.11 发布了v1.4
  • 20.03 发布了v1.5 架构再次重构

云原生的战略

  • 微服务Istio
  • 通讯gRPC
  • 容器kubernetes

08 Istio的自我救赎:为什么Istio发生了两次重大的架构变更

架构1.0版本

数据平面

  • envoy

控制平面

  • pilot 配置管理和分发
  • citadel 安全相关
  • mixer 收集数据指标,设置策略

mixer带来的问题

  1. 需要和数据平面进行两次通讯,降低了效率
  2. 在进行扩展修改的时候,需要重新部署

架构1.1版本

  • Adapter 提供了mixer的扩展功能
  • Galley 配置验证,提取处理和分发的组件,pilot进行了解耦

但是造成了mixer的性能更差了,解耦本身并没有错误

架构1.5版本

重建了控制平面

  • 整合为istiod
  • 废弃mixer

09 核心功能之流量控制:Istio是如何实现流量控制

核心资源CRD包括

虚拟服务(Virtual Service)

  • 将流量路由到给定的目标地址
  • 将请求地址和真实工作负载解耦
  • 包含一组路由规则
  • 和目标规则经常是成对出现

目标规则

  • 目标地址的子集
  • 设置负载均衡策略

网关

管理进出网格的流量

服务入口

将外部服务注册到网格内

功能

  • 为外部目标转发请求
  • 添加超时重试等策略
  • 扩展网格

sidecar

对流量进行一个全局的控制

功能

  • 调整envoy代理的端口和协议
  • 限制envoy代理可以访问的服务

10 服务可观察性:如何理解服务可视化的重要性

指标

  • 代理级别:sidecar代理的数据
  • 服务级别:有延迟,流量,饱和和错误等
  • 控制平面级别:自身组件行为监控和网格健康状况

日志

服务可视化

11 保卫你的网格:Istio是如何设计安全架构的?

Istio的安全架构

  • 网格外服务通过JWT方式调用网格内服务
  • 网格内部可以通过双向TLS认证

认证提供了兼容模式,可以支持加密和不加密方式同时进行请求传输

认证包括两种

  • 对等认证 用于服务间认证,Mutual TLS
  • 请求认证 用于终端用户身份认证,Json Web Token

授权包括

  • 范围设置:metadata/namespace, selector,
  • 值匹配:rule/from和to,可以配置为空
  • 允许和拒绝:action
  • 自定义条件:when

12 安装与部署:如何部署Istio?他都支持那些环境和部署方式

安装istioctl

curl -L https://istio.io/downloadIstio | sh -

使用istioctl安装istio

  • 默认安装 istio manifest apply
  • 选择profile istio manifest apply --set profile=demo
  • 自定义安装选项 istio manifest apply --set addonComponents.grafana.enabled=true
  • 自定义安装清单 istio manifest apply --set installPackagePath=<发布路径>/install/kubernetes/operator/charts

查看crd资源

kubectl get crd | grep istio
kubectl api-resources | grep istio

可以通过生成清单的方式安装

istioctl manifest generate > $HOME/generated-manifest.yaml
kubectl apply -f $HOME/generated-manifest.yaml

验证安装

istioctl verify-install -f $HOME/generated-manifest.yaml

启动dashboard

istioctl dashboard kiali

注入sidecar

kubectl label namespace dafault istio-injection=enabled -overwrite=true

工作的原理是利用了admission controller,结合webhook进行注入,会改写创建的pod

部署demo应用

demo应用架构

  • productpage 主页
  • reviews 评论内容(reviews有三个不同的版本)
  • details 详细内容
  • ratings 评分服务
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml

启动的pod内会有istio-proxy的容器

创建ingress网关

kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml

通过访问对应的/productpage验证是否部署成功

13 动态路由:用Virtula Service和Destination Rule设置路由策略

kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml
kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml

VirtualService

  • hosts
  • gateways 对于外部访问需要,内部服务就直接省略
  • http
  • tcp
  • tls
  • exportTo 可见性,可以在本ns或者所有ns

http对应的HTTPRoute

  • match 对应HTTPMatchRequest,有uri、scheme、method、headers和post等
  • route 对应HTTPRouteDestination,有destination(包括host和subset)、weight和headers
  • retries
  • timeout
  • rewrite

destination对应的DestinationRule

  • host 目标地址
  • subsets 子集,一般对应多个版本
  • trafficPolicy 对应TrafficPolicy,有loadBalancer、connectionPool、tls、outtilerDetection和portLevelSettings
  • exportTo

Virtula Service和Destination Rule使用场景

  • 按照服务版本路由
  • 按照比例切分流量
  • 根据路由规则进行路由
  • 定义负载均衡和连接池等策略

14 网关:用Gateway管理进入网格的流量

什么是Gateway?

  • 一个运行在网格边缘的负载均衡器
  • 接收外部请求,转发给网格内的服务
  • 配置对外的端口、协议与内部服务的映射关系

设置网关

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: test-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: test-gateway
spec:
  hosts:
  - "*"
  gateways:
  - test-gateway
  http:
  - match:
    - uri:
        prefix: /details
    - uri:
        exact: /health
    route:
    - destination:
        host: details
        port:
          number: 9080

请求url为/details/0/health进行验证

Gateway的应用场景

  • 暴露网格内服务给外界
  • 访问安全(对外使用https协议内部使用http)
  • 统一应用入口,API聚合

15 服务入口:用Service Entry扩展你的网格服务

服务入口的作用是

  • 添加外部服务到网格内部
  • 管理到外部服务的请求

安装用于测试的client

kubectl apply -f samples/sleep/sleep.yaml

关闭出流量访问权限

kubectl get configmap istio -n istio-system -o yaml | sed 's/mode: ALLOW_ANY/mode: REGISTRY_ONLY/g' | kubectl replace -n istio-system -f -

定义服务入口

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: httpbin-ext
spec:
  hosts:
  - httpbin.org
  ports:
  - number: 80
    name: http
    protocol: HTTP
  resolution: DNS
  location: MESH_EXTERNAL
EOF

使用httpbin.org/headers来测试服务

16 流量转移:灰度发布是如何实现

有蓝绿发布,金丝雀发布等

kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml

通过对VirtualService的route指向两个不同的destination,权重分别为50

17 Ingress: 控制进入网格的请求

Istio的Ingress和kubernetes的Ingress的区别

  • Istio针对L4~L6,只定义接入点,复用的Virtual Server的L7路由协议
  • kubernetes针对L7,可以定义路由规则

添加服务

kubectl apply -f samples/httpbin/httpbin.yaml

创建ingress

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: httpbin-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "httpbin.example.com"

创建路由规则

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin
spec:
  hosts:
  - "httpbin.example.com"
  gateways:
  - httpbin-gateway
  http:
  - match:
    - uri:
        prefix: /status
    - uri:
        prefix: /delay
    route:
    - destination:
        port:
          number: 8000
        host: httpbin

测试接口

  • /status/200
  • /delay/2

18 Egress: 用Egress实现访问外部服务

istio访问外部的方式

  • 使用ServiceEntry
  • 配置sidecar跳过代理默认
  • Egress

创建ServiceEntry,用于指向外部服务

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: httpbin
spec:
  hosts:
  - httpbin.org
  ports:
  - number: 80
    name: http-port
    protocol: HTTP
  resolution: DNS

这样是直接可以访问外部服务的

创建gateway,使用Egress来处理流量

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: istio-egressgateway
spec:
  selector:
    istio: egressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - httpbin.org

创建虚拟服务

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: vs-for-egressgateway
spec:
  hosts:
  - httpbin.org
  gateways:
  - istio-egressgateway
  - mesh
  http:
  - match:
    - gateways:
      - mesh
      port: 80
    route:
    - destination:
        host: istio-egressgateway.istio-system.svc.cluster.local
        subset: httpbin
        port:
          number: 80
      weight: 100
  - match:
    - gateways:
      - istio-egressgateway
      port: 80
    route:
    - destination:
        host: httpbin.org
        port:
          number: 80
      weight: 100
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: dr-for-egressgateway
spec:
  host: istio-egressgateway.istio-system.svc.cluster.local
  subsets:
  - name: httpbin

这里针对mesh内部的,转发到egress,而egress才会转发到目标地址

19 超时重试:提升系统的健壮性和可用性

  • 超时主要是为了控制故障的范围,避免扩散
  • 重试主要是为了解决网络抖动时,通信失败的问题

添加服务的延迟时间

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - fault:
      delay:
        percent: 100
        fixedDelay: 2s
    route:
    - destination:
        host: ratings
        subset: v1

服务指向

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v2

再加一个reviews添加超时设置

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v2
    timeout: 1s

这时候请求就会获取不到数据了

再设置一下ratings的重试策略

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - fault:
      delay:
        percent: 100
        fixedDelay: 5s
    route:
    - destination:
        host: ratings
        subset: v1
    retries:
      attempts: 2
      perTryTimeout: 1s

20 熔断:秒杀场景下的过载保护如何实现

熔断是一种过载的保护手段,目的是避免服务级联失败

demo通过httpbin作为server端,client为一个压力测试工具

添加策略

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: httpbin
spec:
  host: httpbin
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 1
      http:
        http1MaxPendingRequests: 1
        maxRequestsPerConnection: 1
    outlierDetection:
      consecutiveErrors: 1
      interval: 1s
      baseEjectionTime: 3m
      maxEjectionPercent: 100

配置的trafficPolicy有两个部分

  • maxRequestsPerConnection为http每个连接的最大请求数为1
  • outlierDetection触发熔断的次数为1
  • interval为熔断的间隔时间为1s
  • baseEjectionTime最大可驱逐时间
  • maxEjectionPercent最大可驱逐比例

tcp还有connectTimeout和tcpKeepalive配置项

部署压力测试工具

kubectl apply -f samples/httpbin/sample-client/fortio-deploy.yaml

进行压力测试

kubectl exec -it $FORTIO_POD -c fortio /usr/bin/fortio -- load -c 2 -qps 0 -n 20 -loglevel Warning http://localhost:5000/get 

可以看到存在503的熔断请求

kubectl exec -it $FORTIO_POD -c istio-proxy -- pilot-agent request GET stats | grep httpbin.default | grep pending

upstream_rq_pending_overflow就是被熔断的请求

21 故障注入:在Istio实现一个"Chaos Monkey"

故障注入由Netflix提出ChaosMonkey,以及后来的混沌工程

kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml
kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml
kubectl apply -f samples/bookinfo/networking/virtual-service-ratings-test-delay.yaml

除了延迟故障delay,还有终止故障abort,有httpStatus和percentage配置项

22 流量镜像:解决线上问题排查难题

流量镜像的目录有

  • 线上问题排查
  • 生产环境的压力测试
  • 复制请求用于分析

部署v1和v2两个版本

apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin-v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
      version: v1
  template:
    metadata:
      labels:
        app: httpbin
        version: v1
    spec:
      containers:
      - image: docker.io/kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        command: ["gunicorn", "--access-logfile", "-", "-b", "0.0.0.0:80", "httpbin:app"]
        ports:
        - containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
      version: v2
  template:
    metadata:
      labels:
        app: httpbin
        version: v2
    spec:
      containers:
      - image: docker.io/kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        command: ["gunicorn", "--access-logfile", "-", "-b", "0.0.0.0:80", "httpbin:app"]
        ports:
        - containerPort: 80

创建虚拟主机的目标规则

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin
spec:
  hosts:
    - httpbin
  http:
  - route:
    - destination:
        host: httpbin
        subset: v1
      weight: 100
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: httpbin
spec:
  host: httpbin
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2

配置镜像

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin
spec:
  hosts:
    - httpbin
  http:
  - route:
    - destination:
        host: httpbin
        subset: v1
      weight: 100
    mirror:
      host: httpbin
      subset: v2
    mirror_percentage: 
      value: 100

23 洞察你的服务:使用kiali观察你的微服务应用

微服务可视化的重要性

  • 痛点:服务依赖复杂,问题排查困难
  • 优点:梳理服务的交互关系,了解应用的行为与状态

kiali是一个Istio的可观测性控制台,通过服务拓扑的方式理解服务网格的架构,提供网格健康状态视图,具有服务网格配置功能

功能有

  • 服务拓扑
  • 健康检查
  • 指标查看
  • 配置验证

kiali架构

主要分前端和后端两部分,后端通过与Istio交互获取必要的数据,并且有两个扩展,prometheus和cluster的API

istioctl已经集成了dashboard

istioctl dashboard kiali 

24 指标:使用prometheus收集指标

istio在1.5的遥测指标

  • 请求数 istio_requests_total
  • 请求时长 istio_request_duration_milliseconds
  • 请求大小 istio_request_bytes
  • 响应大小 istio_response_bytes
  • tcp发送字节数 istio_tcp_send_bytes_total
  • tcp响应字节数 istio_tcp_received_bytes_total
  • tcp连接打开数 istio_tcp_connections_opened_total
  • tcp连接关闭数 istio_tcp_connections_closed_total

在老的版本是通过mixter来提供metrics接口

而新版本,prometheus直接与envoy进行交互

envoy使用了STATS和METADATA EXCHANGE插件来完成mixer的功能,但是扩展性很差了

后续最好的就是使用WebAssembly(字节码的方式),在1.5已经可以支持了

可以解决静态化编译的问题,优势在于

  • 无需修改Envoy
  • 避免远程调用
  • 隔离性/安全/多样性
  • 可移植/可维护

25 监控:使用Grafana查看系统的整体状态

Istio有默认的两种dashboard

Mesh

  • 网格数据总览
  • 服务视图
  • 工作负载

Performance

  • Istio系统总览
  • 各组件负载

26 日志:如何获取envoy日志并进行调试

配置在istio的ns中名为istio的configmap,日志路径为accessLogFile字段,日志格式为accessLogEncoding字段

在istio中,sidecar都是使用的istio-proxy的容器名称

会有outbound和inbound的日志

Envoy的流量也包括五元组

对于有问题,也有对应的字段RESPONSE_FLAGS

27 分布式追踪:使用Jaeger对应用进行分布式追踪

Jaeger的概念

  • Span逻辑单元,有父子关系
  • Trace是Span的组合

Jaeger架构

  • agent需要从应用获取到span信息发送给collector
  • collector为收集器,用于发送到存储
  • query支持查询
  • ingester配合kafka使用,调入到存储中

添加jaeger

--set values.tracing.enabled=true
--set values.global.tracer.zipkin.address=<jaeger-collector-service>.<jaeger-collector-namespace>:9411 

28 守卫网络:配置TLS安全网关

1.5版本的Istio有那些更新

  • SDS服务发现趋于稳定
  • 对等认证和请求认证配置的分离

SDS安全发现服务架构(istio-agent为pilot-agent)

hhttp://image.whysdomain.com/jksj/istio22.png https://image.whysdomain.com/jksj/istio01.png

  1. istiod提供了grpc的服务,接收CSR证书签名请求
  2. envoy会通过SDS的API来发送CSR证书和密钥的请求
  3. istio-agnet会创建私钥和CSR发送给istiod索要签名
  4. ca校验签发证书,通过istio-agent将证书和密钥发送给envoy

功能

  • 身份和证书管理
  • 实现安全配置自动化
  • 中心化的SDS Server

优点

  • 无需挂载secret
  • 动态更新证书
  • 可监视多个证书密钥对

确认一下curl的编译参数

curl --version | grep LibreSSl

生成根证书

# 为服务创建根证书和私钥:
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example.com.key -out example.com.crt

# 为httpbin.example.com创建证书和私钥:
openssl req -out httpbin.example.com.csr -newkey rsa:2048 -nodes -keyout httpbin.example.com.key -subj "/CN=httpbin.example.com/O=httpbin organization"
openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in httpbin.example.com.csr -out httpbin.example.com.crt

部署httpbin

apiVersion: v1
kind: Service
metadata:
  name: httpbin
  labels:
    app: httpbin
spec:
  ports:
  - name: http
    port: 8000
  selector:
    app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
      version: v1
  template:
    metadata:
      labels:
        app: httpbin
        version: v1
    spec:
      containers:
      - image: docker.io/citizenstig/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        ports:
        - containerPort: 8000

提交证书

kubectl create -n istio-system secret tls httpbin-credential --key=httpbin.example.com.key --cert=httpbin.example.com.crt

创建入口网关

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: mygateway
spec:
  selector:
    istio: ingressgateway 
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: httpbin-credential
    hosts:
    - httpbin.example.com

这里SIMPLE为单向(标准)认证

请求验证,可以加一下-v的方式查看握手方式

curl -HHost:httpbin.example.com \
--resolve httpbin.example.com:443:127.0.0.1 \
--cacert example.com.crt "https://httpbin.example.com:443/status/418"

29 双重保障:为应用设置不同级别的双向TLS

认证策略的分类

  • 对等认证
  • 请求认证

认证策略范围(优先级最窄原则)

  • 网格
  • 命名空间
  • 特性服务

mTLS是需要client和server都进行证书认证

demo介绍

  • client为sleep
  • server为httpbin

先设置兼容模式,测试功能

# 兼容模式
kubectl apply -f - <<EOF
apiVersion: "security.istio.io/v1beta1"
kind: "PeerAuthentication"
metadata:
  name: "default"
  namespace: "default"
spec:
  mtls:
    mode: PERMISSIVE
EOF

调整为严格模式,就不能通过了

# 严格模式
kubectl apply -f - <<EOF
apiVersion: "security.istio.io/v1beta1"
kind: "PeerAuthentication"
metadata:
  name: "default"
  namespace: "default"
spec:
  mtls:
    mode: STRICT
EOF

进行服务注入

kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml) -n testauth

如果需要全局进行限制

kubectl apply -f - <<EOF
apiVersion: "security.istio.io/v1beta1"
kind: "PeerAuthentication"
metadata:
  name: "default"
spec:
  mtls:
    mode: STRICT
EOF

也可以限制服务级别

30 授权策略:如何实现JWT身份认证与授权

JWT在Encode的时候就是一段字符串,而在Decode之后分三个部分

  • Header 使用的加密算法
  • Payload 传输的信息
  • Signature 将以上数据根据约定的密钥进行签名

创建请求认证

kubectl apply -f - <<EOF
apiVersion: "security.istio.io/v1beta1"
kind: "RequestAuthentication"
metadata:
  name: "jwt-example"
  namespace: testjwt
spec:
  selector:
    matchLabels:
      app: httpbin
  jwtRules:
  - issuer: "testing@secure.istio.io"
    jwksUri: "https://raw.githubusercontent.com/malphi/geektime-servicemesh/master/c3-19/jwks.json"
EOF

测试访问

#测试不合法的jwt访问
kubectl exec $(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name}) -c sleep -n testjwt -- curl "http://httpbin.testjwt:8000/headers" -H "Authorization: Bearer invalidToken"

#测试没有授权策略时,都可以访问
kubectl exec $(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name}) -c sleep -n testjwt -- curl "http://httpbin.testjwt:8000/headers" -s -o /dev/null -w "%{http_code}\n"

创建授权策略

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: require-jwt
  namespace: testjwt
spec:
  selector:
    matchLabels:
      app: httpbin
  action: ALLOW
  rules:
  - from:
    - source:
       requestPrincipals: ["testing@secure.istio.io/testing@secure.istio.io"]
EOF

使用授权访问

#解析token
TOKEN=$(curl https://raw.githubusercontent.com/malphi/geektime-servicemesh/master/c3-19/demo.jwt -s) && echo $TOKEN | cut -d '.' -f2 - | base64 --decode -
#测试带token的请求
kubectl exec $(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name}) -c sleep -n testjwt -- curl "http://httpbin.foo:8000/headers" -s -o /dev/null -H "Authorization: Bearer $TOKEN" -w "%{http_code}\n"