• 基于阿里云 ASK 的 Istio 微服务应用部署初探


    作者:王飞龙(不物)

    目前 Kubernetes 已经成为业界容器编排系统的事实标准,基于 Kubernetes 的云原生应用生态(Helm, Istio, Knative, Kubeflow, Spark on Kubernetes 等)更是让 Kubernetes 成为云操作系统。在这样的背景下,Serverless 容器成为现有 Container as a Service 的进化方向之一,一方面通过 Serverless 方式根本性解决了 Kubernetes 自身的管理复杂性,让用户无需受困于 Kubernetes 集群容量规划、安全维护、故障诊断;另一方面也进一步释放了云计算的能力,将安全、可用性、可伸缩性等需求由基础设施实现。

    ASK 作为阿里云 Serverless Kubernetes 平台 [ 1] ,不仅有免运维、秒级弹性、超大 Pod 容量、弹性预测等重磅能力,更重要的是它依然是一个标准 Kubernetes 平台。

    本文会通过在 ASK 上试用 Istio 部署微服务应用的方式,来验证 ASK 对标准 Kubernetes 的兼容性。Istio 作为 Service Mesh(服务网格)的领导解决方案,一方面本身足够复杂具有代表性,另一方面它也代表了云原生时代微服务架构的趋势具有参考意义。

    现在就让我们开始吧!

    创建集群

    试用 Istio 前,需要准备一个 ASK 集群。登录阿里云控制台,选择产品与服务 > 容器服务 Kubernetes 版,在左侧边栏选择集群进入集群列表页面。点击右上角创建集群开始创建集群,配置集群参数如下:

    • 集群名称:hello-istio
    • 集群规格:Pro 版
    • 地域:美国(硅谷)
    • 付费类型:按量付费
    • Kubernetes 版本:1.20.11-aliyun.1
    • 专有网络:自动创建
    • Service CIDR:172.21.0.0/20
    • API Server 访问:标准型I(slb.s2.small)
    • 使用 EIP 暴露 API Server:是
    • 时区:Aisa/Shanghai(UTC+08:00)
    • 服务发现:CoreDNS
    • 使用日志服务:创建新 Project

    确认配置后点击创建集群进入等待集群创建完成。Istio 依赖 DNS 服务,这里选择创建集群时默认安装 CoreDNS 组件。

    1.png

    集群创建完成后,进入集群列表 > hello-istio > 详情 > 集群信息 > 连接信息页面,复制公网访问内容到本地/tmp/kube/config 文件,并通过如下命令配置好 kubelet:

    $ export KUBECONFIG=/tmp/kube/config
    

    试用 Istio

    kubectl 配置好后就可以开始在集群安装和试用 Istio。

    下载 Istio

    进入 Istio 发布页面 [ 2] 下载针对操作系统的安装文件,也可以通过如下命令下载并提取最新版本:

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

    因为我本机~/bin 目录已加入 PATH,这里我将提取的 Istio 目录复制~/bin 目录,并建好软链接。

    $ cp istio-1.13.3 ~/bin
    $ cd ~/bin
    $ ln -s istio-1.13.3/bin/istioctl
    $ ls -al ~/bin/
    total 28
    drwxr-xr-x   5 feilong.wfl staff   160  5  4 22:40 ./
    drwxr-xr-x+ 95 feilong.wfl staff  3040  5  8 22:30 ../
    drwxr-x---   9 feilong.wfl staff   288  4 15 00:48 istio-1.13.3/
    lrwxr-xr-x   1 feilong.wfl staff    25  5  4 22:40 istioctl -> istio-1.13.3/bin/istioctl*
    

    如果 istioctl --help 命令输出正常,则 istioctl 已正确配置。

    安装 Istio

    1. 本次安装采用 demo profile [ 3] ,它包含了一组专为测试准备的功能集合,另外还有用户生产或性能测试的配置组合。
    $ istioctl install --set profile=demo -y
    ✔ Istio core installed
    ✔ Istiod installed
    ✔ Egress gateways installed
    ✔ Ingress gateways installed
    ✔ Installation complete
    
    1. 给命名空间添加标签,指示 Istio 在部署应用的时候,自动注入 Envoy 边车代理:
    $ kubectl label namespace default istio-injection=enabled
    namespace/default labeled
    

    部署示例应用

    1. 部署 Bookinfo 示例应用 [ 4]
    $ kubectl apply -f ~/bin/istio-1.13.3/samples/bookinfo/platform/kube/bookinfo.yaml
    service/details created
    serviceaccount/bookinfo-details created
    deployment.apps/details-v1 created
    service/ratings created
    serviceaccount/bookinfo-ratings created
    deployment.apps/ratings-v1 created
    service/reviews created
    serviceaccount/bookinfo-reviews created
    deployment.apps/reviews-v1 created
    deployment.apps/reviews-v2 created
    deployment.apps/reviews-v3 created
    service/productpage created
    serviceaccount/bookinfo-productpage created
    deployment.apps/productpage-v1 created
    
    1. 检查 Pod 已就绪:
    $ kubectl get pods
    NAME                              READY   STATUS    RESTARTS   AGE
    details-v1-79f774bdb9-t2jhq       2/2     Running   0          2m54s
    productpage-v1-6b746f74dc-qc9lg   2/2     Running   0          2m46s
    ratings-v1-b6994bb9-tmbh6         2/2     Running   0          2m51s
    reviews-v1-545db77b95-xdhp4       2/2     Running   0          2m49s
    reviews-v2-7bf8c9648f-4gn6f       2/2     Running   0          2m48s
    reviews-v3-84779c7bbc-jfndj       2/2     Running   0          2m48s
    

    要等待并确保所有的 Pod 达到此状态:就绪状态(READY)的值为 2/2 、状态(STATUS)的值为 Running。基于平台的不同,这个操作过程可能会花费几分钟的时间。

    1. 检查 Service 已就绪:
    $ kubectl get services
    NAME          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
    details       ClusterIP   172.21.11.168   <none>        9080/TCP   59s
    kubernetes    ClusterIP   172.21.0.1      <none>        443/TCP    33m
    productpage   ClusterIP   172.21.0.124    <none>        9080/TCP   51s
    ratings       ClusterIP   172.21.9.7      <none>        9080/TCP   57s
    reviews       ClusterIP   172.21.13.223   <none>        9080/TCP   55s
    
    1. 确保网页服务正常。如果命令返回页面标题,则应用已在集群中运行。
    $ kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -s productpage:9080/productpage | grep -o "<title>.*</title>"
    <title>Simple Bookstore App</title>
    

    对外开放服务

    现在,BookInfo 应用已经部署,但还不能被外界访问。 要开放访问,需要创建 Istio 入站网关(Ingress Gateway), 它会把一个路径路由到网格内的服务。

    1. 把应用关联到 Istio 网关:
    $ kubectl apply -f ~/bin/istio-1.13.3/samples/bookinfo/networking/bookinfo-gateway.yaml
    gateway.networking.istio.io/bookinfo-gateway created
    virtualservice.networking.istio.io/bookinfo created
    
    1. 确保配置文件没有问题:
    $ istioctl analyze
    ✔ No validation issues found when analyzing namespace: default.
    

    确定入站 IP 和端口

    使用如下命令为访问网关设置 INGRESS_HOST 和 INGRESS_PORT 两个变量:

    $ 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=="http2")].port}')
    $ export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].port}')
    

    设置变量 GATEWAY_URL,并确保 IP 地址和端口均成功的赋值给了该变量:

    $ export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
    $ echo "$GATEWAY_URL"
    47.88.21.82:80
    

    验证外部访问

    运行下面命令,获取 Bookinfo 应用的外部访问地址:

    $ echo "http://$GATEWAY_URL/productpage"
    http://47.88.21.82:80/productpage
    

    复制上面命令的输出地址到浏览器并访问,确认 Bookinfo 已经实现了外部访问。刷新页面,发现 Book Reviews 的显示样式会不断变化。

    2.png

    查看仪表盘

    仪表盘能帮助了解服务网格的结构、展示网络的拓扑结构、分析网格的健康状态。

    1. 首先安装 Kiali 和其他插件,等待部署完成。
    $ kubectl apply -f ~/bin/istio-1.13.3/samples/addons
    $ kubectl rollout status deployment/kiali -n istio-system
    Waiting for deployment "kiali" rollout to finish: 0 of 1 updated replicas are available...
    deployment "kiali" successfully rolled out
    
    1. 访问 Kiali 仪表板。
    $ istioctl dashboard kiali
    
    1. 在左侧的导航菜单,选择 Graph,然后在 Namespace 下拉列表中,选择 default

    Kiali 仪表板展示了网格的概览、以及 Bookinfo 示例应用的各个服务之间的关系。 它还提供过滤器来可视化流量的流动。

    3.png

    添加默认目标规则

    使用 Istio 控制 Bookinfo 版本路由前,需要先在目标规则 [ 5] 中定义好可用的版本。运行以下命令为 Bookinfo 服务创建默认的目标规则:

    $ kubectl apply -f ~/bin/istio-1.13.3/samples/bookinfo/networking/destination-rule-all.yaml
    destinationrule.networking.istio.io/productpage created
    destinationrule.networking.istio.io/reviews created
    destinationrule.networking.istio.io/ratings created
    destinationrule.networking.istio.io/details created
    

    等待几秒钟,目标规则生效。您可以使用如下命令查看目标规则:

    $ kubectl get destinationrules
    NAME          HOST          AGE
    details       details       30s
    productpage   productpage   32s
    ratings       ratings       31s
    reviews       reviews       32s
    

    路由所有流量到 v1 版本

    运行以下命令创建 Virtual Service 将所有流量路由到微服务的 v1 版本:

    $ kubectl apply -f ~/bin/istio-1.13.3/samples/bookinfo/networking/virtual-service-all-v1.yaml
    virtualservice.networking.istio.io/productpage created
    virtualservice.networking.istio.io/reviews created
    virtualservice.networking.istio.io/ratings created
    virtualservice.networking.istio.io/details created
    

    您可以通过再次刷新 Bookinfo 应用程序的/productpage 页面测试新配置。请注意,无论您刷新多少次,页面的评论部分都不会显示评级星标。这是因为当前已将 Istio 配置为评论服务的所有流量路由到版本 reviews:v1,而此版本的服务不访问星级评分服务。

    基于用户身份的路由

    接下来将更改路由配置,实现将来自特定用户的所有流量路由到特定的服务版本。示例中来自名为 Jason 用户的所有流量将被路由到服务 review:v2。

    Istio 对用户身份没有任何特殊的内置机制。本例中,productpage 服务在所有到 reviews 服务的 HTTP 请求中都增加了一个自定义的 end-user 请求头,从而达到效果。

    1. 运行以下命令以启用基于用户的路由:
    $ kubectl apply -f ~/bin/istio-1.13.3/samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml
    virtualservice.networking.istio.io/reviews created
    
    1. 确保规则已创建:
    $ kubectl get virtualservice reviews -o yaml
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      annotations:
        kubectl.kubernetes.io/last-applied-configuration: |
          {"apiVersion":"networking.istio.io/v1alpha3","kind":"VirtualService","metadata":{"annotations":{},"name":"reviews","namespace":"default"},"spec":{"hosts":["reviews"],"http":[{"match":[{"headers":{"end-user":{"exact":"jason"}}}],"route":[{"destination":{"host":"reviews","subset":"v2"}}]},{"route":[{"destination":{"host":"reviews","subset":"v1"}}]}]}}
      creationTimestamp: "2022-05-15T16:05:55Z"
      generation: 1
      name: reviews
      namespace: default
      resourceVersion: "1984849"
      uid: f3bd3dcb-d83c-4a75-9511-1fc9308ca05b
    spec:
      hosts:
      - reviews
      http:
      - match:
        - headers:
            end-user:
              exact: jason
        route:
        - destination:
            host: reviews
            subset: v2
      - route:
        - destination:
            host: reviews
            subset: v1
    
    1. 在 Bookinfo 应用程序的/productpage 上,以用户 jason 身份登录。刷新浏览器,看到每个评论旁边显示星级评分。

    4.png

    1. 以其他用户身份登录,刷新浏览器。发现星级评分消失了。

    原理和限制

    数据平面,Istio 通过向 Pod 注入的 Sidecar 代理(istio-proxy)来负责协调和控制微服务之前的所有网络通信。为了让 Sidecar 代理(istio-proxy)劫持业务容器流量,Istio 需要向 Pod 所在网络下发 iptables 规则。常规安装模式下,iptables 规则下发是由 Istio 向 Pod 注入的初始化容器 istio-init 完成。向 Pod 网络下发 iptables 规则需要容器可以使用 NET_ADMIN 和 NET_RAW 两个高权限的能力(Capabilities)。ASK 集群中这两个高权限能力受 ASK Pod Security Policy [ 6] 和 ECI Container Security Policy [ 7] 的影响。

    ASK Pod Security Policy 的 CAPS 为 *,表示没有限制。

    $ kubectl get psp
    NAME             PRIV   CAPS   SELINUX    RUNASUSER   FSGROUP    SUPGROUP   READONLYROOTFS   VOLUMES
    ack.privileged   true   *      RunAsAny   RunAsAny    RunAsAny   RunAsAny   false            *
    

    ECI Container Security Policy 允许通过容器安全上下文配置即可。Istio 中 Pod 注入模板文件~/bin/istio-1.13.3/manifests/charts/istio-control/istio-discovery/files/injection-template.yaml 包含如下代码:不启用 Istio CNI 插件 [ 8] 将添加 NET_ADMIN 和 NET_RAW 两个高权限能力:

    securityContext:
      allowPrivilegeEscalation: {{ .Values.global.proxy.privileged }}
      privileged: {{ .Values.global.proxy.privileged }}
      capabilities:
    {{- if not .Values.istio_cni.enabled }}
        add:
        - NET_ADMIN
        - NET_RAW
    {{- end }}
        drop:
        - ALL
    

    所以从原理上分析当前 ASK 集群使用 Istio 没有兼容性问题。

    总结

    本次在 ASK 上试用 Istio 这类高复杂度的软件,未发现兼容性问题。又从原理上正面分析论证了产生兼容性问题的可能性较低。因此,ASK 对原生 Kubernetes 还是有着极好的兼容性。后续将在 ASK 集群上深入探索 Istio 其他功能,以进一步验证 ASK 对原生 Kubernetes 的兼容性。

    参考链接:

    [1] 阿里云 Serverless Kubernetes

    https://help.aliyun.com/document_detail/127525.html

    [2] Istio 发布页面

    https://github.com/istio/istio/releases/tag/1.13.3

    [3] demo profile**

    https://istio.io/latest/docs/setup/additional-setup/config-profiles/

    [4] Bookinfo 示例应用

    https://istio.io/latest/zh/docs/examples/bookinfo/

    [5] 目标规则

    https://istio.io/latest/docs/concepts/traffic-management/#destination-rules)中定义好可用的版本中定义好可用的版本)

    [6] ASK Pod Security Policy

    https://help.aliyun.com/document_detail/165047.html

    [7] ECI Container Security Policy

    https://help.aliyun.com/document_detail/163023.html

    [8] Istio CNI 插件

    https://istio.io/latest/docs/setup/additional-setup/cni/

    点击此处,了解阿里云 ASK 更多详情和最佳实践

  • 相关阅读:
    C#中虚方法与抽象方法的区别
    关于计算同一个用户购买日期间隔查询语句
    pandas 讲数据分组之后保留前N行方法
    关于Mysql隐式转化及注意事项与cast函数运用
    Mysql 去重
    记一个pandas 分组之后.head()返回的数据问题
    Failed to introspect Class xxxx
    golang 推荐学习记录
    Java内存区域
    Struts2中采用Json返回List对象数据为空解决方案
  • 原文地址:https://www.cnblogs.com/alisystemsoftware/p/16326206.html
Copyright © 2020-2023  润新知