Istio Gateway与Kubernetes Ingress Controller对比

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 在Kubernetes环境中,Kubernetes Ingress用于配置需要在集群外部公开的服务。但是在Istio服务网格中,更好的方法是使用新的配置模型,即Istio Gateway。Gateway允许将Istio流量管理的功能应用于进入集群的流量。

在Kubernetes环境中,Kubernetes Ingress用于配置需要在集群外部公开的服务。但是在Istio服务网格中,更好的方法是使用新的配置模型,即Istio Gateway。Gateway允许将Istio流量管理的功能应用于进入集群的流量。

二者在支持的功能上的对比,如下表所示

Istio Gateway 阿里云Ingress Controller NGINX Ingress Controller
根据HTTP Header选择路由规则 支持 仅支持单个Header,不支持多个Header组合 不支持
Header规则支持正则表达式 支持 支持 不支持
服务之间设置权重拆分流量 支持 支持 不支持
Header和权重规则组合使用 支持 支持 不支持
路由规则检查 支持 不支持 不支持
路由规则粒度 service下的不同pod service service
支持的协议 HTTP1.1/HTTP2/gRPC/TCP/Websockets/MongoDB HTTP1.1/HTTP2/gRPC/TCP/Websockets HTTP1.1/HTTP2/gRPC/TCP/Websockets

下面我们看下使用Istio Gateway实现灰度发布时,与Ingress在使用上的差异

Istio Gateway实现灰度发布

环境准备

创建Kubernetes集群

阿里云容器服务Kubernetes 1.10.4目前已经上线,可以通过容器服务管理控制台非常方便地快速创建 Kubernetes 集群。具体过程可以参考这里

部署istio

阿里云容器服务在应用目录目前支持istio快速部署,具体过程可以参考这里

部署用于灰度发布的两个服务

old service

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: old-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      run: old-nginx
  template:
    metadata:
      labels:
        run: old-nginx
    spec:
      containers:
      - image: registry.cn-hangzhou.aliyuncs.com/xianlu/old-nginx
        imagePullPolicy: Always
        name: old-nginx
        ports:
        - containerPort: 80
          protocol: TCP
      restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
  name: old-nginx
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    run: old-nginx
  sessionAffinity: None
  type: NodePort

new service

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: new-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      run: new-nginx
  template:
    metadata:
      labels:
        run: new-nginx
    spec:
      containers:
      - image: registry.cn-hangzhou.aliyuncs.com/xianlu/new-nginx
        imagePullPolicy: Always
        name: new-nginx
        ports:
        - containerPort: 80
          protocol: TCP
      restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
  name: new-nginx
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    run: new-nginx
  sessionAffinity: None
  type: NodePort

部署后效果如下图

$ kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   172.19.0.1      <none>        443/TCP        9h
new-nginx    NodePort    172.19.8.168    <none>        80:31904/TCP   4h
old-nginx    NodePort    172.19.12.148   <none>        80:31545/TCP   4h

测试两个服务

$ kubectl run -it --rm bash --image=appropriate/curl --restart=Never curl 172.19.8.168
new
$ kubectl run -it --rm bash --image=appropriate/curl --restart=Never curl 172.19.12.148
old

创建Gateway对象

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: helloworld-gateway
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"

确定Istio入口IP和port

$ kubectl get svc istio-ingressgateway -n istio-system
NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)                                      AGE
istio-ingressgateway   LoadBalancer   172.19.14.182   47.1x6.xx.41   80:31380/TCP,443:31390/TCP,31400:31400/...   10h

确认EXTERNAL-IP设置了值

export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http")].port}')
export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].port}')

发布场景

满足特定规则的客户端才能访问new service

例如,我们希望请求头中带有user且值为new的客户端请求才能访问new service

我们可以创建一个对应的VirtualService为通过Gateway进入的流量配置路由

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: helloworld
spec:
  gateways:
  - helloworld-gateway
  hosts:
  - '*'
  http:
  - match:
    - headers:
        user:
          exact: new
    route:
    - destination:
        host: new-nginx
        port:
          number: 80
  - route:
    - destination:
        host: old-nginx
        port:
          number: 80

客户端测试

$ curl -H "user: new" http://$INGRESS_HOST:$INGRESS_PORT
new
$ curl -H "user: new" http://$INGRESS_HOST:$INGRESS_PORT
new
$ curl -H "user: new" http://$INGRESS_HOST:$INGRESS_PORT
new
$ curl http://$INGRESS_HOST:$INGRESS_PORT
old
$ curl http://$INGRESS_HOST:$INGRESS_PORT
old
$ curl http://$INGRESS_HOST:$INGRESS_PORT
old

在满足特定规则的客户端请求中会有一定比例访问到new service

例如,我们希望请求头中带有user且值为new的客户端请求有50%的比例访问new service,那么我们可以创建一个这样的VirtualService

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: helloworld
spec:
  gateways:
  - helloworld-gateway
  hosts:
  - '*'
  http:
  - match:
    - headers:
        user:
          exact: new
    route:
    - destination:
        host: new-nginx
        port:
          number: 80
      weight: 50
    - destination:
        host: old-nginx
        port:
          number: 80
      weight: 50
  - route:
    - destination:
        host: old-nginx
        port:
          number: 80

客户端测试

$ curl -H "user: new" http://$INGRESS_HOST:$INGRESS_PORT
new
$ curl -H "user: new" http://$INGRESS_HOST:$INGRESS_PORT
old
$ curl -H "user: new" http://$INGRESS_HOST:$INGRESS_PORT
new
$ curl -H "user: new" http://$INGRESS_HOST:$INGRESS_PORT
new
$ curl -H "user: new" http://$INGRESS_HOST:$INGRESS_PORT
old
$ curl -H "user: new" http://$INGRESS_HOST:$INGRESS_PORT
new
$ curl -H "user: new" http://$INGRESS_HOST:$INGRESS_PORT
old
$ curl http://$INGRESS_HOST:$INGRESS_PORT
old
$ curl http://$INGRESS_HOST:$INGRESS_PORT
old
$ curl http://$INGRESS_HOST:$INGRESS_PORT
old

客户端请求中随机会有一定比例访问到new service

例如,我们仅仅希望20%的客户端请求访问new service,那么我们可以创建一个这样的VirtualService

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: helloworld
spec:
  gateways:
  - helloworld-gateway
  hosts:
  - '*'
  http:
  - route:
    - destination:
        host: new-nginx
        port:
          number: 80
      weight: 20
    - destination:
        host: old-nginx
        port:
          number: 80
      weight: 80

客户端测试

$ curl http://$INGRESS_HOST:$INGRESS_PORT
old
$ curl http://$INGRESS_HOST:$INGRESS_PORT
old
$ curl http://$INGRESS_HOST:$INGRESS_PORT
old
$ curl http://$INGRESS_HOST:$INGRESS_PORT
old
$ curl http://$INGRESS_HOST:$INGRESS_PORT
new

与阿里云容器服务Kubernetes Ingress Controller使用上的对比

阿里云容器服务Kubernetes Ingress Controller提供的灰度发布功能参考这里

因为受限于Kubernetes对Ingress资源的描述,Ingress Controller只能通过各种annotation表达式来支持http路由特性

但是Istio Gateway是通过Custom Resource Definition(CRD)的方式定义一种新的资源,相比之下具有更多优势:

  • 语义规则清晰,更有约束,与Ingress的annotation纯文本定义相比更容易检查错误
  • 各种规则可以自由组合,比如,第一种灰度场景,如果我们希望客户端请求header中同时有user=new和foo=bar才可以访问new service时,我们可以将VirtualService修改如下:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: helloworld
spec:
  gateways:
  - helloworld-gateway
  hosts:
  - '*'
  http:
  - match:
    - headers:
        user:
          exact: new
        foo:
          exact: bar
    route:
    - destination:
        host: new-nginx
        port:
          number: 80
      weight: 50
    - destination:
        host: old-nginx
        port:
          number: 80
      weight: 50
  - route:
    - destination:
        host: old-nginx
        port:
          number: 80

这种场景,目前Ingress就无法支持

总结

我们可以利用阿里云Kubernetes容器服务,快速搭建一套用于连接、管理以及安全化微服务的开放平台Istio,为应用引入和配置多个相关服务。本文通过几个灰度发布的场景来体验Istio Gateway带来的Ingress功能,并同Kubernetes Ingress做了功能上的对比。
欢迎大家使用阿里云上的容器服务,快速搭建微服务的开放治理平台Istio,比较简单地集成到自己项目的微服务开发中。

感谢师兄在本文写作过程中给予的指导:)

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务&nbsp;ACK 容器服务&nbsp;Kubernetes&nbsp;版(简称&nbsp;ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
目录
相关文章
|
29天前
|
缓存 Kubernetes Docker
容器服务ACK常见问题之容器服务ACK ingress websocket配置失败如何解决
容器服务ACK(阿里云容器服务 Kubernetes 版)是阿里云提供的一种托管式Kubernetes服务,帮助用户轻松使用Kubernetes进行应用部署、管理和扩展。本汇总收集了容器服务ACK使用中的常见问题及答案,包括集群管理、应用部署、服务访问、网络配置、存储使用、安全保障等方面,旨在帮助用户快速解决使用过程中遇到的难题,提升容器管理和运维效率。
|
3月前
|
Kubernetes 负载均衡 应用服务中间件
kubernetes—Ingress详解
kubernetes—Ingress详解
69 0
|
3月前
|
Kubernetes 应用服务中间件 nginx
|
4月前
|
Kubernetes 应用服务中间件 nginx
k8s ingress不生效的bug 解决了。
k8s ingress不生效的bug 解决了。
|
4月前
|
Kubernetes 负载均衡 应用服务中间件
k8s学习-Ingress(安装、模板、创建、删除)
k8s学习-Ingress(安装、模板、创建、删除)
89 0
|
5月前
|
Kubernetes 应用服务中间件 API
5 分钟了解 Kubernetes Ingress 和 Gateway API
5 分钟了解 Kubernetes Ingress 和 Gateway API
110 0
|
17天前
|
运维 Kubernetes 容灾
kubernetes核心技术之Controller控制器知识总结
kubernetes核心技术之Controller控制器知识总结
13 1
|
1月前
|
负载均衡 安全 网络协议
如何通过计算巢在ACK集群上使用Istio服务网格
本文主要介绍怎么通过计算巢部署Isito服务网格,并介绍了使用示例。
31 0
|
1月前
|
容器
在容器服务ACK中,如果你想更改ALB Ingress的域名和端口
【2月更文挑战第15天】在容器服务ACK中,如果你想更改ALB Ingress的域名和端口
13 3
|
3月前
|
消息中间件 Kubernetes 监控
kubernetes—Controller详解(二)
kubernetes—Controller详解(二)
50 0

相关产品

  • 容器服务Kubernetes版