Istio 基础概念学习整理

Istio 基础概念学习整理

流量管理

为了在网格中导流,Istio 需要知道所有的 endpoint 在哪以及它们属于哪些服务。 为了定位到 service registry(服务注册中心), Istio 会连接到一个服务发现系统(Istio不提供服务发现系统)。例如,如果您在 Kubernetes 集群上安装了 Istio, 那么它将自动检测该集群中的服务和 endpoint。

虚拟服务(Virtual Service)目标规则(Destination Rule) 是 Istio 流量路由功能的核心构建模块。每个虚拟服务包含一组按顺序评估的路由规则,通过这些规则,Istio 将每个到虚拟服务的给定请求匹配到特定的、真实的目标地址。

使用 Istio实现金丝雀发布

Kubernetes中使用istio流量路由和副本部署是两个完全独立的功能,可以轻松实现细粒度控制流量百分比(例如路由 1% 的流量而不需要 100 个 Pod)。

定义svc,Istio是基于svc来实现服务注册的

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
name: helloworld
labels:
  app: helloworld
spec:
  selector:
    app: helloworld
  ...

添加 2 个 Deployment,包含相同的标签app=helloworld,版本分别为 v1v2

yaml 复制代码
kind: Deployment
metadata:
  name: helloworld-v1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: helloworld
        version: v1
    spec:
      containers:
      - image: helloworld-v1
        ...
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: helloworld-v2
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: helloworld
        version: v2
    spec:
      containers:
      - image: helloworld-v2
        ...

使用普通 Kubernetes 进行金丝雀部署需要调整每个 Deployment 的副本数目。例如,将 10% 的流量发送到金丝雀版本(v2),v1 和 v2 的副本可以分别设置为 9 和 1。

使用istio我们可以通过设置路由规则来控制流量分配:

yaml 复制代码
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: helloworld
spec:
  hosts:
    - helloworld
  http:
  - route:
    - destination:
        host: helloworld
        subset: v1
        weight: 90 # 90%的流量给v1
    - destination:
        host: helloworld
        subset: v2
        weight: 10
    timeout: 10s # 默认15秒
    retries:
      attempts: 3 # 默认重试2次
      perTryTimeout: 2s # 每次重试都有 2 秒的超时
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: helloworld
spec:
  host: helloworld
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
EOF

我们基于流量来控制后,我们就可以放心的使用hpa了

shell 复制代码
$ kubectl autoscale deployment helloworld-v1 --cpu-percent=50 --min=1 --max=10
$ kubectl autoscale deployment helloworld-v2 --cpu-percent=50 --min=1 --max=10

我们还可以通过匹配headers来实现将特定用户的流量引入到金丝雀版本中

yaml 复制代码
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: helloworld
spec:
  hosts:
    - helloworld
  http:
  - match:
    - headers:
        cookie:
          regex: "^(.*?;)?(email=[^;]*@some-company-name.com)(;.*)?$"
    route:
    - destination:
        host: helloworld
        subset: v1
        weight: 50
    - destination:
        host: helloworld
        subset: v2
        weight: 50
  - route:
    - destination:
        host: helloworld
        subset: v1
EOF

Istio网关

Istio 的网关资源可以来管理网格的入站和出站流量,可以配置 4-6 层的负载均衡属性,如对外暴露的端口、TLS 设置等。网关主要用于管理进入的流量。

示例:让 HTTPS 流量从 ext-host.example.com 通过 443 端口流入网格

yaml 复制代码
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: ext-host-gwy
spec:
  selector:
    app: my-gateway-controller
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    hosts:
    - ext-host.example.com
    tls:
      mode: SIMPLE
      credentialName: ext-host-cert
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: virtual-svc
spec:
  hosts:
  - ext-host.example.com
  gateways:
    - ext-host-gwy

服务入口

配置服务入口允许您管理运行在网格外的服务的流量

示例:添加一个外部dns到服务中心

yaml 复制代码
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: svc-entry
spec:
  hosts:
  - ext-svc.example.com
  ports:
  - number: 443
    name: https
    protocol: HTTPS
  location: MESH_EXTERNAL
  resolution: DNS
---
# 接下来就可以把其添加为DestinationRule了
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: ext-res-dr
spec:
  host: ext-svc.example.com
  trafficPolicy:
    connectionPool:
      tcp:
        connectTimeout: 1s

Sidecar

默认情况下,Istio 让每个 Envoy 代理都可以访问来自和它关联的工作负载的所有端口的请求,在大集群中会因此占用大量内存,所以sidecar支持特定namespace的访问

yaml 复制代码
apiVersion: networking.istio.io/v1alpha3
kind: Sidecar
metadata:
  name: default
  namespace: bookinfo
spec:
  egress:
  - hosts:
    - "./*" # 当前ns的服务
    - "istio-system/*" # istio-system ns下的服务

故障注入

故障注入是一种将错误引入系统以确保系统能够承受并从错误条件中恢复的测试方法。

示例:千分之一的访问 5 秒延迟

yaml 复制代码
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - fault:
      delay:
        percentage:
          value: 0.1
        fixedDelay: 5s
    route:
    - destination:
        host: ratings
        subset: v1

Kubernetes Gateway API

Kubernetes Gateway API负责南北流量,集群对外访问的流量。Istio关注的是服务之间的流量,包括集群内的东西向流量和南北向流量。

与 Ingress 不同,Kubernetes Gateway 不包含对目标服务的任何引用。使用 Gateway API 后,服务路由被定义在单独的配置资源中, 这些配置资源会附加到 Gateway 中,用于将流量子集定向到特定服务,例如我们示例中的 helloworld。这种分离允许我们在不同的命名空间中定义 Gateway 和路由, 并可以由不同的团队进行管理。

定义helloworld测试服务

shell 复制代码
$ kubectl create ns sample
$ kubectl apply -f samples/helloworld/helloworld.yaml -n sample

定义网关资源

shell 复制代码
$ kubectl create namespace sample-ingress
$ kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: sample-gateway
  namespace: sample-ingress
spec:
  gatewayClassName: istio # 名为 istio 的gw
  listeners:
  - name: http
    hostname: "*.sample.com"
    port: 80
    protocol: HTTP
    allowedRoutes:
      namespaces:
        from: All # 所有ns
EOF

上面我们作为集群管理人员,在 sample-ingress 命名空间中应用了 Gateway,因为 Gateway 资源的所有权归于集群操作员,它可以很好地用于为多个团队的服务提供入口。

接下来,我们将代表开发人员为 sample-ingress/sample-gateway 添加路由。

shell 复制代码
kubectl apply -n sample -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: helloworld
spec:
  parentRefs: # 将 HTTPRoute 附加到 sample-gateway
  - name: sample-gateway
    namespace: sample-ingress
  hostnames: ["helloworld.sample.com"] # 子域名
  rules:
  - matches:
    - path:
        type: Exact
        value: /hello # 路径
    backendRefs:
    - name: helloworld # svc/helloworld
      port: 5000
EOF

基于权重的路由选择,创建v1、v2的svc

shell 复制代码
$ kubectl apply -n sample -f samples/helloworld/gateway-api/helloworld-versions.yaml

将流量 90% 转到 v1,10% 到 v2

shell 复制代码
$ kubectl apply -n sample -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: helloworld
spec:
  parentRefs:
  - name: sample-gateway
    namespace: sample-ingress
  hostnames: ["helloworld.sample.com"]
  rules:
  - matches:
    - path:
        type: Exact
        value: /hello
    backendRefs:
    - name: helloworld-v1
      port: 5000
      weight: 90
    - name: helloworld-v2
      port: 5000
      weight: 10
EOF
相关推荐
敲上瘾17 小时前
【探索实战】:Kurator分布式统一应用分发平台的全面解析与实践指南
分布式·容器·kubernetes·serverless
Connie14511 天前
记一次K8s故障告警排查(Grafna告警排查)
云原生·容器·kubernetes·grafana
谷隐凡二2 天前
Kubernetes主从架构简单解析:基于Python的模拟实现
python·架构·kubernetes
陈陈CHENCHEN2 天前
SuperMap iManager for K8s 离线环境镜像仓库 Containerd 部署
kubernetes
会飞的小蛮猪2 天前
Ubuntu24.04 基于Containerd部署K8s1.34(私服部署)
docker·云原生·kubernetes
间彧2 天前
Kubernetes滚动发布详解
kubernetes
间彧2 天前
在实际生产环境中,Kubernetes声明式API如何实现蓝绿部署、金丝雀发布等高级部署策略?
kubernetes
间彧2 天前
Kubernetes声明式API相比传统命令式API在故障恢复场景下的具体优势有哪些?
kubernetes·github
间彧2 天前
为什么说Kubernetes的API设计是其成功的关键因素之一?
kubernetes
间彧2 天前
Kubernetes Deployment 配置简化实战:从复杂到高效
kubernetes