逃脱只会部署集群系列 —— Istio服务部署以及传统流量调度

目录

一、Service Mesh 服务网格

1、服务网格

2、开源实现

二、Istio服务部署

1、安装Istio

2、安装istio组件

三、传统模式的流量走向

1、场景一

2、资源清单

3、操作实现

四、剖析下默认流量调度机制

1、集群流量调度规则详解

2、总结下


一、Service Mesh 服务网格

1、服务网格

        目的是解决系统架构微服务化后的服务间通信和治理问题。提供一种通用的服务治理方案。

        Sidecar 在软件系统架构中特指边车模式。这个模式的灵感来源于我们生活中的边三轮:即在两轮摩托车的旁边添加一个边车的方式扩展现有的服务和功能。

        

        这个模式的精髓在于实现了数据面(业务逻辑)和控制面的解耦:原来两轮摩托车的驾驶者集中注意力跑赛道,边车上的领航员专注周围信息和地图,专注导航。

         Service Mesh 这个服务网络专注于处理服务和服务间的通讯。其主要负责构造一个稳定可靠的服务通讯的基础设施,并让整个架构更为的先进和 Cloud Native。在工程中,Service Mesh 基本来说是一组轻量级的与应用逻辑服务部署在一起的服务代理,并且对于应用服务是透明的。

2、开源实现

第一代服务网格 Linkerd和Envoy

Linkerd 使用Scala编写,是业界第一个开源的service mesh方案。作者 William Morgan 是 service mesh 的布道师和践行者。Envoy 基于C++ 11编写,无论是理论上还是实际上,后者性能都比 Linkderd 更好。这两个开源实现都是以 sidecar 为核心,绝大部分关注点都是如何做好proxy,并完成一些通用控制面的功能。 但是,当你在容器中大量部署 sidecar 以后,如何管理和控制这些 sidecar 本身就是一个不小的挑战。于是,第二代 Service Mesh 应运而生。

第二代服务网格 Istio

Istio 是 Google 和 IBM 两位巨人联合 Lyft 的合作开源项目。是当前最主流的service mesh方案,也是事实上的第二代 service mesh 标准。

二、Istio服务部署

1、安装Istio

https://istio.io/latest/docs/setup/getting-started/

下载 Istio

下载内容将包含:安装文件、示例和 istioctl 命令行工具。

  1. 访问 Istio release 页面下载与您操作系统对应的安装文件。在 macOS 或 Linux 系统中,也可以通过以下命令下载最新版本的 Istio:

    $ wget https://github.com/istio/istio/releases/download/1.7.3/istio-1.7.3-linux-amd64.tar.gz
  2. 解压并切换到 Istio 包所在目录下。例如:Istio 包名为 istio-1.7.3,则:

    $ tar zxf istio-1.7.3-linux-amd64.tar.gz
    $ ll istio-1.7.3
    drwxr-x---  2 root root    22 Sep 27 08:33 bin
    -rw-r--r--  1 root root 11348 Sep 27 08:33 LICENSE
    drwxr-xr-x  6 root root    66 Sep 27 08:33 manifests
    -rw-r-----  1 root root   756 Sep 27 08:33 manifest.yaml
    -rw-r--r--  1 root root  5756 Sep 27 08:33 README.md
    drwxr-xr-x 20 root root   330 Sep 27 08:33 samples
    drwxr-x---  3 root root   133 Sep 27 08:33 tools
  3. istioctl 客户端拷贝到 path 环境变量中

    $ cp bin/istioctl /bin/
  4. 配置命令自动补全

    istioctl 自动补全的文件位于 tools 目录。通过复制 istioctl.bash 文件到您的 home 目录,然后添加下行内容到您的 .bashrc 文件执行 istioctl tab 补全文件:

    $ cp tools/istioctl.bash ~
    $ source ~/istioctl.bash

2、安装istio组件

https://istio.io/latest/zh/docs/setup/install/istioctl/#display-the-configuration-of-a-profile

使用istioctl直接安装:

$ istioctl install --set profile=demo
✔ Istio core installed
✔ Istiod installed
✔ Egress gateways installed
✔ Ingress gateways installed
✔ Installation complete
​
$ kubectl -n istio-system get po
NAME                                    READY   STATUS    RESTARTS   AGE
istio-egressgateway-7bf76dd59-n9t5l     1/1     Running   0          77s
istio-ingressgateway-586dbbc45d-xphjb   1/1     Running   0          77s
istiod-6cc5758d8c-pz28m                 1/1     Running   0          84s

istio针对不同的环境,提供了几种不同的初始化部署的profile

# 查看提供的profile类型
$ istioctl profile list
我们用的是demo模式,也就是都安装
​
# 获取kubernetes的yaml:
$ istioctl manifest generate --set profile=demo > istio-kubernetes-manifest.yaml

卸载

$ istioctl manifest generate --set profile=demo | kubectl delete -f -

三、传统模式的流量走向

1、场景一

通过前端服务front-tomcat访问bill-service访问默认会50%随机调度至后端的服务bill-service-dp1和bill-service-dp2。

2、资源清单

front-tomcat-dpl-v1.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: front-tomcat
    version: v1
  name: front-tomcat-v1
  namespace: istio-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: front-tomcat
      version: v1
  template:
    metadata:
      labels:
        app: front-tomcat
        version: v1
    spec:
      containers:
      - image: consol/tomcat-7.0:latest
        name: front-tomcat

bill-service-dpl-v1.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    service: bill-service
    version: v1
  name: bill-service-v1
  namespace: istio-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      service: bill-service
      version: v1
  template:
    metadata:
      labels:
        service: bill-service
        version: v1
    spec:
      containers:
      - image: nginx:alpine
        name: bill-service
        command: ["/bin/sh", "-c", "echo 'this is bill-service-v1'>/usr/share/nginx/html/index.html;nginx -g 'daemon off;'"]

 bill-service-dpl-v2.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    service: bill-service
    version: v2
  name: bill-service-v2
  namespace: istio-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      service: bill-service
      version: v2
  template:
    metadata:
      labels:
        service: bill-service
        version: v2
    spec:
      containers:
      - image: nginx:alpine
        name: bill-service
        command: ["/bin/sh", "-c", "echo 'hello, this is bill-service-v2'>/usr/share/nginx/html/index.html;nginx -g 'daemon off;'"]

bill-service-svc.yaml

apiVersion: v1
kind: Service
metadata:
  labels:
    service: bill-service
  name: bill-service
  namespace: istio-demo
spec:
  ports:
  - name: http
    port: 9999
    protocol: TCP
    targetPort: 80
  selector:
    service: bill-service
  type: ClusterIP

3、操作实现

$ kubectl create namespace istio-demo
$ kubectl apply -f front-tomcat-dpl-v1.yaml
$ kubectl apply -f bill-service-dpl-v1.yaml
$ kubectl apply -f bill-service-dpl-v2.yaml
$ kubectl apply -f bill-service-svc.yaml
​
[root@k8s-master demo]# kubectl -n istio-demo exec front-tomcat-v1-7f8c94c6c8-lfz5m --  curl -s bill-service:9999
this is bill-service-v1
[root@k8s-master demo]# kubectl -n istio-demo exec front-tomcat-v1-7f8c94c6c8-lfz5m --  curl -s bill-service:9999
hello, this is bill-service-v2

四、剖析下默认流量调度机制

1、集群流量调度规则详解

        我们都知道默认访问规则会按照v1和v2的pod各50%的流量分配,那k8s默认的调度机制是怎么实现的呢,现在从网络层面解释下。

 curl bill-service:9999-->curl svcip:9999-->查找本地route -n-->没有符合进入0.0.0.0转到10.244.1.1网桥-->10.244.2.1是宿主机上面-->宿主机看kubeproxy组件-->iptables-save | grep svcip找到链路-->iptables-save | grep 链路-->就可以找到对应pod两个地址的random各自50%的规则

1、执行<kubectl -n istio-demo exec front-tomcat-v1-7f8c94c6c8-lfz5m --  curl -s bill-service:9999>操作时,因为容器内默认dns解析,实际上是在curl后端服务svc地址。

# bill自带域名解析
[root@k8s-master demo]# kubectl -n istio-demo exec -it bill-service-v1-765cb46975-hmtmd sh
/ # nslookup bill-service
Server:		10.1.0.10
...
Address: 10.1.122.241

[root@k8s-master demo]# kubectl get svc -n istio-demo 
NAME           TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
bill-service   ClusterIP   10.1.122.241   <none>        9999/TCP   66m

curl -s bill-service:9999 等同于 curl -s 10.1.122.241:9999

2、路由通过0.0.0.0规则转到10.244.1.1网桥

[root@k8s-master demo]# kubectl -n istio-demo exec -it bill-service-v1-765cb46975-hmtmd sh
/ # route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         10.244.1.1      0.0.0.0         UG    0      0        0 eth0
10.244.0.0      10.244.1.1      255.255.0.0     UG    0      0        0 eth0
10.244.1.0      *               255.255.255.0   U     0      0        0 eth0

没有找到10.1.122.241规则,就通过0.0.0.0转到10.244.1.1的Gateway

3、宿主机没有维护规则,流量跳转到iptables查看规则

# 这个10.244.1.1实际上是宿主机的地址,也就是说容器此时网络规则,容器内部-->宿主机
[root@k8s-node2 ~]# ip a | grep -e 10.244.1.1
    inet 10.244.1.1/24 brd 10.244.1.255 scope global cni0

# 此时宿主机也没有发现相关规则

# 实际上宿主机部署kube-proxy组件,kube-proxy维护了iptables规则,流量虽然没有直接的宿主机route规则,但是流量访问时已经被iptables拦截,我们看下iptable有没有配置相关规则
[root@k8s-node2 ~]# iptables-save | grep 10.1.122.241
-A KUBE-SERVICES ! -s 10.244.0.0/16 -d 10.1.122.241/32 -p tcp -m comment --comment "istio-demo/bill-service:http cluster IP" -m tcp --dport 9999 -j KUBE-MARK-MASQ
-A KUBE-SERVICES -d 10.1.122.241/32 -p tcp -m comment --comment "istio-demo/bill-service:http cluster IP" -m tcp --dport 9999 -j KUBE-SVC-PK4BNTKC2JYVE7B2

 4、iptables规则链路成功查找到0.5权重的后端地址

# 根据svc地址规则跳转至KUBE-SVC-PK4BNTKC2JYVE7B2链
[root@k8s-node2 ~]# iptables-save | grep 10.1.122.241
-A KUBE-SERVICES -d 10.1.122.241/32 -p tcp -m comment --comment "istio-demo/bill-service:http cluster IP" -m tcp --dport 9999 -j KUBE-SVC-PK4BNTKC2JYVE7B2

# 可以看到0.5权重转发到KUBE-SEP-OIO7GYZLNGRLZLYD,剩下的权重转发到KUBE-SEP-OXS2CP2Q2RMPFLD5链路。我们看下分别对应到后端哪里了
[root@k8s-node2 ~]# iptables-save | grep KUBE-SVC-PK4BNTKC2JYVE7B2
-A KUBE-SVC-PK4BNTKC2JYVE7B2 -m comment --comment "istio-demo/bill-service:http" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-OIO7GYZLNGRLZLYD
-A KUBE-SVC-PK4BNTKC2JYVE7B2 -m comment --comment "istio-demo/bill-service:http" -j KUBE-SEP-OXS2CP2Q2RMPFLD5

# 查看KUBE-SEP-OIO7GYZLNGRLZLYD对应的IP
[root@k8s-node2 ~]# iptables-save | grep KUBE-SEP-OIO7GYZLNGRLZLYD
-A KUBE-SEP-OIO7GYZLNGRLZLYD -s 10.244.1.168/32 -m comment --comment "istio-demo/bill-service:http" -j KUBE-MARK-MASQ

# 查看KUBE-SEP-OXS2CP2Q2RMPFLD5对应的IP
[root@k8s-node2 ~]# iptables-save | grep KUBE-SEP-OXS2CP2Q2RMPFLD5
-A KUBE-SEP-OXS2CP2Q2RMPFLD5 -s 10.244.2.74/32 -m comment --comment "istio-demo/bill-service:http" -j KUBE-MARK-MASQ

# 可以发现,两条链路对应的就是bill-service的两个pod地址
[root@k8s-node2 ~]# kubectl get po -n istio-demo  -owide
NAME                               READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
bill-service-v1-765cb46975-hmtmd   1/1     Running   0          89m   10.244.1.168   k8s-node2   <none>           <none>
bill-service-v2-6854775ffc-9n6jv   1/1     Running   0          87m   10.244.2.74    k8s-node1   <none>           <none>
front-tomcat-v1-7f8c94c6c8-lfz5m   1/1     Running   0          89m   10.244.1.169   k8s-node2   <none>           <none>

2、总结下

front容器执行curl bill-service:9999操作时,根据域名解析规则,实际是在执行curl -s 10.1.122.241:9999,容器根据本地route -n规则进入0.0.0.0转到10.244.1.1网桥,这个网桥地址位于宿主机上面但是也没有配置相应的route规则;于是我们思考k8s集群网络是由kubeproxy组件配置iptables规则调度的,于是通过iptables-save一步步找到svcip-->0.5-->bill-service-ip的过程。

猜你喜欢

转载自blog.csdn.net/weixin_39855998/article/details/122515422