跳转至

特性说明

使用介绍

服务端口自动纳管

懒加载支持自动监听集群内服务端口信息,并为所有端口启用懒加载,这样就无需手动指定服务端口列表。

在SlimeBoot中配置懒加载相关参数:

general.autoPort:true,启动端口自动纳管,等于false或者不指定,则手动管理。兼容之前版本

general.wormholePort中手动指定的端口也会被懒加载纳管。

为了安全,自动纳管时,端口**只会自动增加**。如果需要缩减端口范围,请切换到手动模式,或自动模式下重启懒加载。懒加载遵循Istio对端口协议的判断逻辑(端口名以“HTTP, HTTP2, GRPC, GRPCWeb”开头),只感知HTTP协议的端口变化。

样例:

kind: SlimeBoot
metadata:
  name: lazyload
  namespace: mesh-operator
spec:
  # ...
  module:
    - name: lazyload
      kind: lazyload
      enable: true
      general:
        autoPort: true # 自动纳管服务端口
 # ...

具体原理可参考 autoport

基于Accesslog开启懒加载

指定SlimeBoot CR资源 spec.module.global.misc.metricSourceType:accesslog,使用Accesslog获取服务调用关系

或者设置spec.module.global.misc.metricSourceType:prometheus,使用Prometheus获取服务间调用关系。

使用Accesslog获取服务调用关系的大概过程:

  • slime-boot在创建global-sidecar时,发现metricSourceType: accesslog,额外生成一个configmap,内容是包含lazyload controller处理accesslog的地址信息的static_resources。再通过一个envoyfilter,将static_resources加入global-sidecar配置中,使得global-sidecar的accesslog会发送到lazyload controller
  • global-sidecar完成兜底转发时会生成accesslog,包含了调用方和被调用方服务信息。global-sidecar将信息发送给lazyload controller
  • lazyload controller分析accesslog,获取到新的服务调用关系

随后的过程,就是修改servicefence和sidecar,和处理prometheus metric的过程一致。

样例

spec:
  module:
    - name: lazyload # custom value
      kind: lazyload # should be "lazyload"
      enable: true
      general: # replace previous "fence" field
        wormholePort: # replace to your application svc ports
          - "9080"
      global:
        misc:
          metricSourceType: accesslog

手动或自动为服务启用懒加载

支持通过autoFence参数,指定启用懒加载是手动模式、自动模式。这里的启用懒加载,指的是创建serviceFence资源,从而生成Sidecar CR。

支持通过defaultFence参数,指定自动模式下,是否全局启用懒加载。

配置方式如下

---
apiVersion: config.netease.com/v1alpha1
kind: SlimeBoot
metadata:
  name: lazyload
  namespace: mesh-operator
spec:
  module:
    - name: lazyload
      kind: lazyload
      enable: true
      general:
        autoFence: true # true为自动模式,false 为手动模式,默认为手动模式
        defaultFence: true # 自动模式下的默认行为,true时,什么都不指定也会生成servicefence,false时只有打上注解的才会开启
  # ...

自动模式

autoFence: true时,进入自动模式。自动模式下,启用懒加载的服务范围,通过三个维度调整。

Service级别 - label slime.io/serviceFenced

  • false: 不自动启用
  • true: 自动启用

  • 其他值或缺省: 使用Namespace级别配置

Namespace级别 - label slime.io/serviceFenced

  • false: 该namespace下的所有服务都不自动启用
  • true:该namespace下的所有服务都自动启用
  • 其他值或缺省: 使用全局级别配置

全局级别 - lazyload的defaultFence参数

  • false: 全局不自动启用
  • true:全局自动启用

优先级:Service级别 > Namespace级别 > 全局级别

注:对于自动生成的ServiceFence资源 ,会通过标准Label app.kubernetes.io/created-by=fence-controller来记录,实现了状态关联变更。 而不匹配该Label的ServiceFence资源,视为手动配置,不受以上Label影响。

举例

Namespace testns下有三个服务: svc1, svc2, svc3

  • autoFencetruedefaultFencetrue时,自动生成以上三个服务的ServiceFence
  • 给Namespace testns加上Label slime.io/serviceFenced: "false", 所有testns下的ServiceFence消失
  • svc1打上 slime.io/serviceFenced: "true" label: 服务svc1的ServiceFence创建
  • 删掉Namespace和Service上的label:恢复三个ServiceFence

配置样例

apiVersion: v1
kind: Namespace
metadata:
  labels:
    istio-injection: enabled
    slime.io/serviceFenced: "false"
  name: testns
---
apiVersion: v1
kind: Service
metadata:
  annotations: {}
  labels:
    app: svc1
    service: svc1
    slime.io/serviceFenced: "true"
  name: svc1
  namespace: testns

手动模式

autoFence参数为false时,启用懒加载为手动模式,需要用户手动创建ServiceFence资源, 手动模块下只支持Service级别。

自定义兜底流量分派

lazyload/fence默认会将envoy无法匹配路由(缺省)的流量兜底发送到global sidecar,应对短暂服务数据缺失的问题,这是“懒加载”所必然面对的。 该方案因为技术细节上的局限性,对于目标(如域名)是集群外的流量,无法正常处理,详见 [Configuration Lazy Loading]: Failed to access external service #3

基于这个背景,设计了本特性,同时也能用于更灵活的业务场景。 大致思路是通过域名匹配的方式将不同的缺省流量分派到不同的目标做正确处理。

配置样例:

module:
  - name: lazyload
    kind: lazyload
    enable: true
    general:
      wormholePort:
      - "80"
      - "8080"
      dispatches:  # new field
      - name: 163
        domains:
        - "www.163.com"
        cluster: "outbound|80||egress1.testns.svc.cluster.local"  # standard istio cluster format: <direction>|<svcPort>|<subset>|<svcFullName>, normally direction is outbound and subset is empty      
      - name: baidu
        domains:
        - "*.baidu.com"
        - "baidu.*"
        cluster: "{{ (print .Values.foo \".\" .Values.namespace ) }}"  # you can use template to construct cluster dynamically
      - name: sohu
        domains:
        - "*.sohu.com"
        - "sodu.*"
        cluster: "_GLOBAL_SIDECAR"  # a special name which will be replaced with actual global sidecar cluster
      - name: default
        domains:
        - "*"
        cluster: "PassthroughCluster"  # a special istio cluster which will passthrough the traffic according to orgDest info. It's the default behavior of native istio.

在本例中,我们把一部分流量分派给了指定的cluster; 另一部分让它走global sidecar; 然后对其余的流量,让它保持原生istio的行为: passthrough

注意

  • 自定义分派场景,如果希望保持原有逻辑 “其他所有未定义流量走global sidecar” 的话,需要显式配置如上的倒数第二条

添加静态服务依赖关系

懒加载除了从slime metric(accesslog/prometheus metric)处根据动态指标更新服务依赖关系,还支持通过serviceFence.spec添加静态服务依赖关系。支持三种细分场景:依赖某个服务、依赖某个namespace所有服务、依赖具有某个label的所有服务。

依赖某个服务

适用于启用懒加载的服务静态依赖另外一个或多个服务的场景,可以在初始化时直接将配置加入sidecar crd。

下面的样例中,为启用懒加载的服务添加对reviews.default服务的静态依赖关系。

# servicefence
spec:
  enable: true
  host:
    reviews.default.svc.cluster.local: # static dependenct of reviews.default service
      stable: {}
# related sidecar
spec:
  egress:
  - hosts:
    - '*/reviews.default.svc.cluster.local'
    - istio-system/*
    - mesh-operator/*

依赖某个namespace所有服务

适用于启用懒加载的服务静态依赖另外一个或多个namespace中所有服务的场景,可以在初始化时直接将配置加入sidecar crd。

下面的样例中,为启用懒加载的服务添加对test命名空间中所有服务的静态依赖关系。

# servicefence
spec:
  enable: true
  host:
    test/*: {} # static dependency of all services in test namespace

# related sidecar
spec:
  egress:
  - hosts:
    - test/*
    - istio-system/*
    - mesh-operator/*

依赖具有某个label的所有服务

适用于启用懒加载的服务静态依赖具有某个label或多个label的所有服务的场景,可以在初始化时直接将配置加入sidecar crd。

下面的样例中,为启用懒加载的服务添加拥有app=details的所有服务,以及拥有app=reviews, group=default的所有服务的静态依赖关系。

# servicefence
spec:
  enable: true
  labelSelector: # Match service label, multiple selectors are 'or' relationship
    - selector:
        app: details
    - selector: # labels in one selector are 'and' relationship
        app: reviews
        group: default

# related sidecar
spec:
  egress:
  - hosts:
    - '*/details.default.svc.cluster.local' # with label "app=details"
    - '*/details.test.svc.cluster.local' # with label "app=details"
    - '*/reviews.default.svc.cluster.local' # with label "app=details" and "group=default"
    - istio-system/*
    - mesh-operator/*

自定义服务依赖别名

在某些场景,我们希望懒加载根据已知的服务依赖,添加一些额外的服务依赖进去。

用户可以通过配置general.domainAliases,提供自定义的转换关系,实现需求。general.domainAliases包含多个domainAlias,每个domainAlias由匹配规则pattern和转换规则templates组成。pattern只包含一个匹配规则,templates则可以包含多个转换规则。

举个例子,我们希望添加<svc>.<ns>.svc.cluster.local时,额外添加<ns>.<svc>.mailsaas的服务依赖,则可以这么配置

apiVersion: config.netease.com/v1alpha1
kind: SlimeBoot
metadata:
  name: lazyload
  namespace: mesh-operator
spec:
  module:
    - name: lazyload-test
      kind: lazyload
      enable: true
      general:
        wormholePort: # replace to your application service ports, and extend the list in case of multi ports
          - "9080"
        domainAliases: 
          - pattern: '(?P<service>[^\.]+)\.(?P<namespace>[^\.]+)\.svc\.cluster\.local$'
            templates:
              - "$namespace.$service.mailsaas"
  #...

对应的servicefence会这样

apiVersion: microservice.slime.io/v1alpha1
kind: ServiceFence
metadata:
  name: ratings
  namespace: default
spec:
  enable: true
  host:
    details.default.svc.cluster.local: # static dependent service
      stable: {}
status:
  domains:
    default.details.mailsaas: # static dependent service converted result
      hosts:
      - default.details.mailsaas
    default.productpage.mailsaas: # dynamic dependent service converted result
      hosts:
      - default.productpage.mailsaas
    details.default.svc.cluster.local:
      hosts:
      - details.default.svc.cluster.local
    productpage.default.svc.cluster.local:
      hosts:
      - productpage.default.svc.cluster.local
  metricStatus:
    '{destination_service="productpage.default.svc.cluster.local"}': "1" # dynamic dependent service

sidecar则是这样

apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
  name: ratings
  namespace: default
spec:
  egress:
  - hosts:
    - '*/default.details.mailsaas' # static dependent service converted result
    - '*/default.productpage.mailsaas' # dynamic dependent service converted result
    - '*/details.default.svc.cluster.local'
    - '*/productpage.default.svc.cluster.local'
    - istio-system/*
    - mesh-operator/*
  workloadSelector:
    labels:
      app: ratings

日志输出到本地并轮转

slime的日志默认输出到标准输出,指定SlimeBoot CR资源中spec.module.global.log.logRotate等于true会将日志输出到本地并启动日志轮转,不再输出到标准输出。

轮转配置也是可调整的,默认的配置如下,可以通过显示指定logRotateConfig中的各个值进行覆盖。

spec:
  module:
    - name: lazyload # custom value
      kind: lazyload # should be "lazyload"
      enable: true
      general: # replace previous "fence" field
        wormholePort: # replace to your application svc ports
          - "9080"
      global:
        log:
          logRotate: true
          logRotateConfig:
            filePath: "/tmp/log/slime.log"
            maxSizeMB: 100
            maxBackups: 10
            maxAgeDay: 10
            compress: true

通常需要配合存储卷使用,在存储卷准备完毕后,指定SlimeBoot CR资源中的spec.volumesspec.containers.slime.volumeMounts来显示将存储卷挂载到日志本地文件所在的路径。

以下是基于minikube kubernetes场景下的完整demo

创建存储卷

基于/mnt/data路径创建hostpath类型的存储卷

# hostPath pv for minikube demo
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: lazyload-claim
  namespace: mesh-operator
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: lazyload-volumn
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"

在SlimeBoot中声明挂载信息

在SlimeBoot CR资源中指定了存储卷会挂载到pod的"/tmp/log"路径,这样slime的日志会持久化到/mnt/data路径下,并且会自动轮转。

---
apiVersion: config.netease.com/v1alpha1
kind: SlimeBoot
metadata:
  name: lazyload
  namespace: mesh-operator
spec:
  image:
    pullPolicy: Always
    repository: docker.io/slimeio/slime-lazyload
    tag: v0.7.1
  module:
    - name: lazyload # custom value
      kind: lazyload # should be "lazyload"
      enable: true
      general: # replace previous "fence" field
        wormholePort:
          - "9080"
      global:
        log:
          logRotate: true
          logRotateConfig:
            filePath: "/tmp/log/slime.log"
            maxSizeMB: 100
            maxBackups: 10
            maxAgeDay: 10
            compress: true
#... skip
  volumes:
    - name: lazyload-storage
      persistentVolumeClaim:
        claimName: lazyload-claim
  containers:
    slime:
      volumeMounts:
        - mountPath: "/tmp/log"
          name: lazyload-storage

完整样例

Back to top