前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Istio流量管理快速入门

Istio流量管理快速入门

作者头像
王先森sec
发布2023-04-24 17:35:04
发布2023-04-24 17:35:04
32500
代码可运行
举报
文章被收录于专栏:王先森王先森
运行总次数:0
代码可运行

Istio使用场景

在业务更新迭代快速发展时代,更新版本只靠Kubernetes实现简单的更新发布是不行的,如果想要实现对业务流量访问限制还需要借用Istio的能力,比如升级到v2版本,将v2版本接入流量占比要到10%,Kubernetes是无法实现。下面就是整个实现过程。

快速入门

环境准备

主机名

IP

角色

k8s-master

eth0:10.1.1.100、docker:172.17.100.0/24

K8S-master

k8s-node1

eth0:10.1.1.120、docker:172.17.120.0/24

K8S-node

k8s-node2

eth0:10.1.1.130、docker:172.17.130.0/24

K8S-node

场景一

模型图

创建资源配置清单

  • Front-tomcat
  • Bill-service-V1
  • Service
代码语言:javascript
代码运行次数:0
运行
复制
cat > front-tomcat-dpl-v1.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: front-tomcat
    version: v1
  name: front-tomcat-v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: front-tomcat
      version: v1
  template:
    metadata:
      labels:
        app: front-tomcat
        version: v1
    spec:
      containers:
      - image: tomcat:9.0-jdk11
        name: front-tomcat
        command: ["/bin/sh", "-c", "echo '你好, 这是(王先森)账单v1服务中心'>/usr/share/nginx/html/index.html;nginx -g 'daemon off;'"]
EOF
代码语言:javascript
代码运行次数:0
运行
复制
cat > bill-service-dpl-v1.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    service: bill-service
    version: v1
  name: bill-service-v1
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 '你好, 这是(王先森)账单v1服务中心'>/usr/share/nginx/html/index.html;nginx -g 'daemon off;'"]
EOF
代码语言:javascript
代码运行次数:0
运行
复制
cat > bill-service-svc.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
  labels:
    service: bill-service
  name: bill-service
spec:
  ports:
  - name: http
    port: 9999
    protocol: TCP
    targetPort: 80
  selector:
    service: bill-service
  type: ClusterIP
EOF

应用资源配置清单

代码语言:javascript
代码运行次数:0
运行
复制
$ kubectl apply -f front-tomcat-dpl-v1.yaml
$ kubectl apply -f bill-service-dpl-v1.yaml
$ kubectl apply -f bill-service-svc.yaml

$ kubectl exec front-tomcat-v1-548b46d488-r7wv8 -- curl -s bill-service:9999
你好, 这是(王先森)账单v1服务中心

场景二

后台账单服务更新v2版本,前期规划90%的流量访问v1版本,接入10%的流量到v2版本

模型图

创建资源配置清单

新增bill-service-dpl-v2.yaml

代码语言:javascript
代码运行次数:0
运行
复制
cat > bill-service-dpl-v2.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    service: bill-service
    version: v2
  name: bill-service-v2
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 '你好, 这是(王先森)账单v2服务中心'>/usr/share/nginx/html/index.html;nginx -g 'daemon off;'"]
EOF

此时,访问规则会按照v1和v2的pod各50%的流量分配。

代码语言:javascript
代码运行次数:0
运行
复制
$ kubectl apply -f bill-service-dpl-v2.yaml
$ kubectl exec front-tomcat-v1-5fdcb465f6-2j86p -- curl -s bill-service:9999
你好, 这是(王先森)账单v2服务中心
你好, 这是(王先森)账单v2服务中心
你好, 这是(王先森)账单v1服务中心
你好, 这是(王先森)账单v1服务中心

K8S默认流量调度机制

集群流量调度规则详解

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

curl bill-service:9999相当于请求k8s中SVCip:9999—>查找本地路由通过route -n没有符合进入0.0.0.0转到172.7.100.1网桥到10.1.1.100宿主机上面,然后宿主机看kube-proxy组件通过iptables-save | grep svcip找到链路—>iptables-save | grep 链路—>就可以找到对应pod两个地址的random各自50%的规则。

流量分析详细过程

执行curl -s bill-service:9999操作时,因为容器内默认dns解析,实际上是在curl后端服务svc地址

代码语言:javascript
代码运行次数:0
运行
复制
[root@k8s-master1 bill]# kubectl exec -ti bill-service-v1-59b4f4ccc7-qvhw6 -c bill-server -- sh
/ # nslookup bill-service
Server:         192.168.0.2
Address:        192.168.0.2:53

Name:   bill-service.default.svc.cluster.local
Address: 192.168.18.251
[root@k8s-master1 bill]# kubectl get svc
NAME           TYPE        CLUSTER-IP        EXTERNAL-IP   PORT(S)    AGE
bill-service   ClusterIP   192.168.18.251    <none>        9999/TCP   2d23h
kubernetes     ClusterIP   192.168.0.1       <none>        443/TCP    217d

通过默认路由(0.0.0.0)规则转到172.17.100.1网桥

代码语言:javascript
代码运行次数:0
运行
复制
[root@k8s-master1 bill]# kubectl exec -ti bill-service-v1-59b4f4ccc7-qvhw6 -c bill-server -- sh
/ # route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         172.7.100.1     0.0.0.0         UG    0      0        0 eth0
172.7.100.0     *               255.255.255.0   U     0      0        0 eth0

# 没有找到192.168.18.251 规则,就通过默认路由(0.0.0.0)转到172.17.100.1的网关上。

宿主机并没有维护规则,流量而是跳转到iptables查看规则

代码语言:javascript
代码运行次数:0
运行
复制
[root@k8s-master1 bill]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.1.1.2        0.0.0.0         UG    0      0        0 eth0
10.1.1.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 eth0
172.7.100.0     0.0.0.0         255.255.255.0   U     0      0        0 docker0
172.7.120.0     10.1.1.120      255.255.255.0   UG    0      0        0 eth0
172.7.130.0     10.1.1.130      255.255.255.0   UG    0      0        0 eth0
# 实际上宿主机部署kube-proxy组件,kube-proxy维护了iptables规则,流量虽然没有直接的宿主机route规则,但是流量访问时已经被iptables拦截,我们看下iptable有没有配置相关规则
[root@k8s-master1 bill]# iptables-save | grep  192.168.18.251
-A KUBE-SERVICES -d 192.168.18.251/32 -p tcp -m comment --comment "default/bill-service:http cluster IP" -m tcp --dport 9999 -j KUBE-SVC-BY6GMFMEZFXQ2BDP
-A KUBE-SVC-BY6GMFMEZFXQ2BDP ! -s 172.7.0.0/16 -d 192.168.18.251/32 -p tcp -m comment --comment "default/bill-service:http cluster IP" -m tcp --dport 9999 -j KUBE-MARK-MASQ

Istio注入资源配置清单

Istio注入方法1
代码语言:javascript
代码运行次数:0
运行
复制
istioctl kube-inject -f bill-service-dpl-v1.yaml|kubectl apply -f -
istioctl kube-inject -f bill-service-dpl-v2.yaml|kubectl apply -f -
istioctl kube-inject -f front-tomcat-dpl-v1.yaml|kubectl apply -f -
# 或
kuubectl apply -f <(istioctl kube-inject -f bill-service-dpl-v1.yaml)
kuubectl apply -f <(istioctl kube-inject -f bill-service-dpl-v2.yaml)
kuubectl apply -f <(istioctl kube-inject -f front-tomcat-dpl-v1.yaml)
Istio注入方法2

通过向名称空间加入自动注入标签

代码语言:javascript
代码运行次数:0
运行
复制
kubectl label namespace bookinfo istio-injection=enabled

创建流量调度资源配置清单

若想实现上述需求,需要解决如下两个问题:

  • 让访问账单服务的流量按照我们期望的比例,其实是一条路由规则,如何定义这个规则
  • 如何区分两个版本的服务

这里需要创建两个新的资源类型:VirtualServiceDestinationRule

VirtualService是一个虚拟的service,描述的是满足什么条件的流量被那个后端处理。类似于根据路径去匹配方法,是更开放的match条件。

DestinationRule描述的是这个请求到达某个后端后怎么去处理,是方法内的处理逻辑。 所以负载均衡和熔断策略是定义在DestinationRule中的,还可以配置连接池大小、异常实例驱逐规则等功能。

  • DestinationRule
  • VirtualService
代码语言:javascript
代码运行次数:0
运行
复制
cat > bill-service-destnation-rule.yaml <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: dest-bill-service
spec:
  host: bill-service # 标识规则的适用对象,取值是Service资源名称,可以是网格内或以serviceEntry方式注册的网格外的服务
  subsets:   # 定义的服务子集,经常用来定义一个服务版本。
  - name: v1
    labels:      # 标签选择器
      version: v1
  - name: v2
    labels:
      version: v2
EOF
代码语言:javascript
代码运行次数:0
运行
复制
cat > bill-service-virtualservice.yaml <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: vs-bill-service
spec:
  hosts: # 列出VirtualService的hosts,可以是IP、DNS名称、FQDN或*
  - bill-service
  http: # 指定符合规则的流量到那些Destination,支持HTTP/1.1、HTTP2,及gRPC等协议
  - name: bill-service-route
    route:
    - destination: # 满足条件会把流量打入具体的Destination
        host: bill-service
        subset: v1      # 选择服务版本
      weight: 90        # 权重
    - destination:
        host: bill-service
        subset: v2
      weight: 10
EOF

使用client验证流量分配是否生效。

代码语言:javascript
代码运行次数:0
运行
复制
$ kubectl apply -f bill-service-virtualservice.yaml
$ kubectl apply -f bill-service-destnation-rule.yaml
$ kubectl exec front-tomcat-v1-598964b695-868vf -c front-tomcat -- curl -s bill-service:9999
你好, 这是(王先森)账单v1服务中心
你好, 这是(王先森)账单v1服务中心
你好, 这是(王先森)账单v1服务中心
你好, 这是(王先森)账单v1服务中心
你好, 这是(王先森)账单v2服务中心
你好, 这是(王先森)账单v1服务中心
你好, 这是(王先森)账单v1服务中心
你好, 这是(王先森)账单v1服务中心

这里就会发现规划90%的流量访问v1版本、接入10%的流量到v2版本,就已经实现了。

Istio注入报错

代码语言:javascript
代码运行次数:0
运行
复制
[root@k8s-master1 ~]# istioctl version
2023-02-23T07:44:24.585408Z     error   klog    an error occurred forwarding 42999 -> 15014: error forwarding port 15014 to pod b56d93be9c44a8f9e668503d735bed98386b5bda9fdadc761b814b0582ef6e14, uid : unable to do port forwarding: socat not found

需要安装socat:yum -y install socat

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-02-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Istio使用场景
  • 快速入门
    • 环境准备
    • 场景一
      • 模型图
      • 创建资源配置清单
      • 应用资源配置清单
    • 场景二
      • 模型图
      • 创建资源配置清单
      • K8S默认流量调度机制
      • Istio注入资源配置清单
      • 创建流量调度资源配置清单
  • Istio注入报错
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档