美文网首页每天进步一点点
Istio1.6访问VM工作负载三种方式(新的WorkloadE

Istio1.6访问VM工作负载三种方式(新的WorkloadE

作者: 桢桢claire | 来源:发表于2020-06-23 23:12 被阅读0次

    上次说到,Istio 1.6新版本引入了Workload Entry来增强对于非K8S(虚拟机和裸机)工作负载的支持。在理论上,网格内的服务彼此之间可以通过服务名互相调用,但是对于网格外的服务,有哪些访问方式呢?本宝宝专门花了很大的功夫做了实验,今天就一起来看看。

    先来看一些理论

    目前,Istio对于外部服务的支持有三种:

    1. 通过istioctl register <external-service> <IP> <PORT>注册一个Service和一个Endpoint;
    2. 通过ServiceEntry定义;
    3. 通过WorkloadEntry + ServiceEntry 组合定义。

    第一种方式 istioctl register

    在这种方式下,你需要将每个网格外服务都通过istioctl register进行注册,这个命令将自动创建并部署对应的serviceendpoint。注册进来的服务将被分配网格内部的域名,使用mTLS,并且直接受Istio管理。VM需要安装Istio各个组件(Envoy proxy、node-agent、istio-agent),并且保证可被istio控制平面访问。

    第二种方式 ServiceEntry

    什么是ServiceEntry?

    先来看官网对ServiceEntry的定义:

    ServiceEntry enables adding additional entries into Istio’s internal service registry, so that auto-discovered services in the mesh can access/route to these manually specified services.

    也就是说,他是将其他非网格内服务加入Istio的服务发现,像网格内的服务一样进行管理。这里没有直接使用“外部服务”,是因为ServiceEntry适用的主体不仅仅包括网格外的服务(比如Web API),还包括一些处于网格内部但却不存在于平台的服务注册表中的服务(例如需要和 Kubernetes 服务沟通的一组虚拟机服务)。在这种方式下,该服务所处VM不需要安装Istio组件,只需要保证Istio能访问该服务即可。

    ServiceEntry怎么定义外部服务?

    对于外部服务,你需要按照下面的规则来配置:

    • hosts :指定外部服务对应的主机名或DNS域名。对于HTTP流量,就是HTTP Header的Host;对于HTTPS/TLS的流量,就是SNI。
    • location :指定为MESH_EXTERNAL,表示它是在网格外部,需要通过API来访问的接口。
    • ports :外部服务的端口。
    • resolution :表示服务发现的模式
      • 如果是一个明确IP,配置为NONE
      • 如果使用了endpoints,配置为STATIC
      • 如果使用了DNS域名,配置为DNS

    比如,如果想将外部网页服务注册到istio中,可以这样配置:

    apiVersion: networking.istio.io/v1alpha3
    kind: ServiceEntry
    metadata:
      name: external-svc-https
    spec:
      hosts:
      - api.dropboxapi.com
      - www.googleapis.com
      - api.facebook.com
      location: MESH_EXTERNAL
      ports:
      - number: 443
        name: https
        protocol: TLS
      resolution: DNS
    ---
    
    ServiceEntry怎么定义内部服务?

    在定义内部服务时,ServiceEntry需要和DestinationRule配合使用,也就是说,通过ServiceEntry定义服务,通过DestionationRule初始化到istio到服务的mTLS连接。

    在这种方式下,你需要将每个网格外服务的地址都显式定义在ServiceEntry的endpoints字段中,但你不需要在VM或裸机上安装Istio。

    第三种方式 WorkloadEntry

    什么是WorkloadEntry?

    WorkloadEntry的出现就是为了将ServiceEntry中的endpoints定义与ServiceEntry本身进行分离,使ServiceEntry专注定义非网格内部服务,而WorkloadEntry定义该服务来源(VM或裸机)的信息。引用官网的介绍,

    WorkloadEntry enables operators to describe the properties of a single non-Kubernetes workload such as a VM or a bare metal server as it is are onboarded into the mesh. A WorkloadEntry must be accompanied by an Istio ServiceEntry that selects the workload through the appropriate labels and provides the service definition for a MESH_INTERNAL service (hostnames, port properties, etc.).

    也就是说,WorkloadEntry也是与ServiceEntry配套使用的,那么由于ServiceEntry是和DestinationRule配套使用的,因此他们三个要一起使用。

    在这种方式下,你可以用WorkloadEntry定义VM,再用ServiceEntry定义非网格内服务,并且可以选择一个或多个运行在K8S和非K8S上的服务,实现了最大程度的灵活性。

    实验做什么

    下面,我们就分别用这三种方式尝试将虚拟机上的服务注册到istio中进行管理。实验基于Istio提供的示例应用Bookinfo,增加Ratings服务的新版本,使其调用运行在VM上的mysql作为后端。应用架构图如下:


    实验架构

    环境说明

    为了做实验,专门用了一台阿里云和一台华为云,配置了安全组,使其相互能访问。其中,阿里云上跑Istio,华为云作为VM跑mysql服务:

    • 阿里云ECS:4核8G、CentOS 8.0、Docker(v18.06.1)、kubectl(v1.15.0)、minikube(v1.2.0阿里社区版)、istio(1.6.2)

    • 华为云云耀云:2核4G、Ubuntu 18.04、Docker(v19.03.11)、kubectl(v1.15.0)、minikube(v1.1.0阿里社区版)、mysql(v10.1.44-MariaDB)

    (由于目前sidecar安装只提供了deb版本,对于CentOS需要手动make编译安装,因此VM直接选用Ubuntu。)

    实验怎么做

    在本宝宝看了大量文档连蒙带猜后,终于理出了头绪,因此专门分开介绍在VM和Istio两端分别需要做怎样的配置。

    首先说VM端

    VM起一个Mysql服务,里面放评分数据,并作为ratings服务的后端。

    1. 安装Envoy sidecar
    curl -L https://storage.googleapis.com/istio-release/releases/1.6.3/deb/istio-sidecar.deb
    sudo dpkg -i istio-sidecar.deb 
    
    1. 配置Mysql
      Mysql默认只允许本地访问,于是先要配置使其允许远程访问。详细步骤请参考《填坑指南 1.如何开启Mysql远程访问》。

    2. 将评分数据加入Mysql

    curl -q https://raw.githubusercontent.com/istio/istio/release-1.6/samples/bookinfo/src/mysql/mysqldb-init.sql | mysql -u root -ppassword
    

    示例使用名为test的数据库,可以查询并自定义评分数据。

    MariaDB [(none)]> use test
    Reading table information for completion of table and column names
    You can turn off this feature to get a quicker startup with -A
    
    Database changed
    MariaDB [test]> select * from ratings;
    +----------+--------+
    | ReviewID | Rating |
    +----------+--------+
    |        1 |      3 |
    |        2 |      2 |
    +----------+--------+
    2 rows in set (0.01 sec)
    

    至此,VM需要配置的内容就结束了。下面来看Istio端。

    再说istio端

    Istio端需要将VM上的Mysql加入网格中,并配置服务调用策略,使Ratings服务调用VM上的Mysql服务查询评分数据。

    1. 启用Istio meshExpansion。
      在安装Istio的时需要开启meshExpansion功能。
      istioctl install --set profile=demo --set values.global.meshExpansion.enabled=true

    2(*). 开启Kiali
    Kiali是为Istio提供图形化界面Dashboard的开源项目,可以通过它监控网格内服务的实时状态,以及网格配置。为了能够监测流量流向,我们开启Kiali,详细步骤请参考《填坑指南->2. 如何开启Kaili进行流量监控?》。

    1. 部署并应用v2-mysql版本的ratings服务。
      查看了应用源码,发现在ratings服务的源码中,是从环境变量中取值初始化DB连接。
    image.png image.png

    因此,在ratings服务的Deployment中,也需要将后端DB连接信息传入环境变量。
    部署并应用v2-mysql版本ratings,MYSQL_DB_HOST使用服务名mysqldb,istio会自动寻找注册过的名为mysqldb的Service或ServiceEntry。

    1. 部署并应用应用新版本VirtualService。
      使用virtual-service-ratings-mysql.yaml,使流量应用v3版本的reviews服务和v2-mysql版本的ratings服务。

    2. 在Istio中注册”mysqldb“。

    上文介绍到有三种方式配置非K8S服务,下面就分别试一下。

    方式一:使用istioctl register

    1. 注册mysqldb服务。
      它会默认创建出来同名的Service和endpoints。
    [root@node2 kube]# istioctl register mysqldb 124.**.65.221 3306
    2020-06-23T06:58:15.842443Z warn    Got 'services "mysqldb" not found' looking up svc 'mysqldb' in namespace 'default', attempting to create it
    2020-06-23T06:58:15.852592Z warn    Got 'endpoints "mysqldb" not found' looking up endpoints for 'mysqldb' in namespace 'default', attempting to create them
    
    1. 确认service和endpoint状态。
    [root@node2 kube]# kubectl get svc
    NAME           TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
    details        ClusterIP      10.101.253.166   <none>        9080/TCP         50m
    frontend       NodePort       10.102.61.100    <none>        80:30004/TCP     16d
    kubernetes     ClusterIP      10.96.0.1        <none>        443/TCP          17d
    mongodb        ClusterIP      10.100.95.126    <none>        27017/TCP        14d
    mysqldb        ClusterIP      10.97.255.81     <none>        3306/TCP         114s
    productpage    ClusterIP      10.109.248.58    <none>        9080/TCP         50m
    ratings        ClusterIP      10.99.19.120     <none>        9080/TCP         50m
    reviews        ClusterIP      10.100.95.201    <none>        9080/TCP         50m
    
    [root@node2 kube]# kubectl get endpoints
    NAME           ENDPOINTS                                            AGE
    details        172.17.0.21:9080,172.17.0.7:9080                     48m
    kubernetes     172.26.205.16:8443                                   17d
    mongodb        172.17.0.24:27017                                    14d
    mysqldb        124.**.65.221:3306                                   35s
    productpage    172.17.0.9:9080                                      48m
    ratings        172.17.0.14:9080,172.17.0.26:9080                    48m
    reviews        172.17.0.10:9080,172.17.0.11:9080,172.17.0.25:9080   48m
    
    1. 访问bookinfo应用。
      先在华为云上将评分数据更新为五星,五星,之后调用productpage。可以看到评分已经发生变化。


      image.png

    使用Kiali查看调用路径,可以看到v2-mysql版本的ratings调用了mysqldb服务。


    image.png

    方式二:使用ServiceEntry

    1. 定义并部署ServiceEntry
    • hosts :对于非HTTP的流量,该字段不生效,它将后面通过address或endpoint定义的服务映射为网格内部的一个虚拟服务,以hosts标识,并遵循istio内部的服务名定义格式 。
    • endpoints :表示与网格服务相关的网络地址,可以是IP或主机名,也可以用多个address组成一个vip组。

    按照上述规则,在hosts里填mysqldb,在endpoints里填VM的IP。

    apiVersion: networking.istio.io/v1alpha3
    kind: ServiceEntry
    metadata:
      name: mysqldb-se
    spec:
      hosts:
      - mysqldb
      location: MESH_INTERNAL
      ports:
      - number: 3306
        name: mysql
        protocol: mysql
      resolution: STATIC
      endpoints:
      - address: 124.**.65.221
    ---
    
    1. 定义并部署DestinationRule
    • hosts :表示规则适用的对象,这里指定以ServiceEntry方式注册的网格外服务名称。
    • trafficPolicy :规则内容的定义,这里只规定了tls的模式,在ISTIO_MUTUAL 模式下,Istio 会依据内部实现机制自动设置密钥和证书的路径,不需要手动指定clientCertificate、 privateKey和 caCertificates的位置。

    按照上述规则,在host里填mysqldb

    apiVersion: networking.istio.io/v1alpha3
    kind: DestinationRule
    metadata:
      name: mtls-mysqldb
    spec:
      host: mysqldb
      trafficPolicy:
        tls:
          mode: ISTIO_MUTUAL
    ---
    
    1. 访问bookinfo应用。
      先在华为云上将评分数据更新为三星和五星,之后调用productpage。可以看到评分已经发生变化。


      image.png

    使用Kiali查看调用路径,可以看到v2-mysql版本的ratings调用了ServiceEntry类型的mysqldb-se,同时出现了PassthroughtCluster。想了解PassthroughCluster,请参考《填坑指南->3. PassthroughCluster是什么鬼?》

    image.png

    方式三:使用WorkloadEntry

    1. 定义并部署WorkloadEntry
    • address : 表示与网格服务相关的网络地址,可以是IP或主机名。

    按照上述规则,在adddress中配置VM的IP,并添加标签”mysqlvm“。

    apiVersion: networking.istio.io/v1alpha3
    kind: WorkloadEntry
    metadata:
      name: mysqldb-we
    spec:
      address: 124.**.65.221
      labels:
        app: mysqlvm
        instance-id: ubuntu-vm-mariadb
        class: vm
    ---
    
    1. 定义并部署ServiceEntry
    • workloadSelector :通过label来选择K8S上有这个标签的Pod,或通过WorkloadEntry定义的VM上的工作负载。也就是说,通过这种方式,就不需要关心工作负载是跑在哪里的了,只需要指定应用的标签,istio会自动选择有相应标签的工作负载。

    按照上述规则,在hosts里填mysqldb,在workloadSelector通过标签”mysqlvm“定义相应的WorkloadEntry。

    apiVersion: networking.istio.io/v1alpha3
    kind: ServiceEntry
    metadata:
      name: mysqldb-vm-se
    spec:
      hosts:
      - mysqldb
      location: MESH_INTERNAL
      ports:
      - number: 3306
        name: mysql
        protocol: mysql
      resolution: STATIC
      workloadSelector:
        labels:
          app: mysqlvm
    ---
    
    1. 定义并部署DestinationRule
      在DestinationRule中配置使用ISTIO_MUTUAL连接mysqldb
    apiVersion: networking.istio.io/v1alpha3
    kind: DestinationRule
    metadata:
      name: mtls-mysqldb-vm
    spec:
      host: mysqldb
      trafficPolicy:
        tls:
          mode: ISTIO_MUTUAL
    ---
    
    1. 访问bookinfo应用。
      先在华为云上将评分数据更新为一星和一星,之后调用productpage。可以看到评分已经发生变化。


      image.png

    使用Kiali查看调用路径,可以看到v2-mysql版本的ratings调用了ServiceEntry类型的mysqldb-vm-se

    image.png

    吐槽加总结一下

    这次做实验本来是为了尝试了新版本的WorkloadEntry,但是由于Istio的文档实在是太乱,网上的经验帖又太少,看了不下几十个链接,最终只能连蒙带猜,根据属性说明尝试配置,算是成功了,但总觉得Istio乱花渐欲的配置实在是太迷,还有很多不是理解不够深刻的地方。

    走了很多弯路,特意总结出这三种访问外部服务的方式,附带填坑指南供大家参考。
    喜欢本宝宝就请多多关注哦。

    填坑指南

    1. 如何开启Mysql远程访问?

    1)注释掉bing-address。
    Mariadb的配置文件位置和普通Mysql有所不同,bind-address在/etc/mysql/mariadb.conf.d/50-server.cnf这里。

    vi /etc/mysql/mariadb.conf.d/50-server.cnf
    
    # Instead of skip-networking the default is now to listen only on
    # localhost which is more compatible and is not less secure.
    #bind-address           = 127.0.0.1
    

    2) 使用GRANT命令增加允许远程访问的host。

    GRANT ALL ON *.* to root@'39.**.145.34' IDENTIFIED BY 'password';
    FLUSH PRIVILEGES;  
    
    MariaDB [mysql]> select host, user from user;
    +---------------+------+
    | host          | user |
    +---------------+------+
    | %             | root |
    | 39.**.145.34 | root |
    | localhost     | root |
    +---------------+------+
    3 rows in set (0.00 sec)
    

    2. 如何开启Kiali进行流量监控?

    1)查看Kiali服务状态。

    [root@node2 ~]# kubectl get svc -n istio-system
    NAME                        TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                                                                                                                                   AGE
    ...
    kiali                       ClusterIP      10.103.7.219     <none>        20001/TCP                                                                                                                                 3d5h
    ...
    

    2)启用port-forward,将20001端口直接暴露出来。

    kubectl -n istio-system port-forward --address 0.0.0.0 $(kubectl -n istio-system get pod -l app=kiali -o jsonpath='{.items[0].metadata.name}') 20001:20001 &
    

    3)打开浏览器,使用<ip>:20001直接访问Kiali Dashboard,默认用户名和密码都为admin。

    3. PassthroughCluster是什么鬼?

    参考官网说明,监控被阻止的和透传的外部服务流量

    为了更好的监控外部流量,Istio 控制平面使用了预定义集群BlackHoleClusterPassthrough来配置 sidecar 代理,它们的作用分别是阻止和通过所有流量。当将global.outboundTrafficPolicy.mode设置为 ALLOW_ANY时, PassthroughCluster 是在 Envoy 配置中创建的虚拟集群。在此模式下,允许流向外部服务的所有流量。

    为了实现此目的,将使用 SO_ORIGINAL_DST 且监听 0.0.0.0:15001 的默认虚拟出站监听器设置为 TCP 代理,并将 PassthroughCluster 作为静态集群。 对于每个基于端口/协议的监听器,虚拟路由配置都会添加 PassthroughCluster 以作为默认路由,发向PassthroughCluster的请求会被直接发送到其请求中要求的原始目地的,Envoy不会对请求进行重新路由。

    相关文章

      网友评论

        本文标题:Istio1.6访问VM工作负载三种方式(新的WorkloadE

        本文链接:https://www.haomeiwen.com/subject/pndzxktx.html