submarine icon indicating copy to clipboard operation
submarine copied to clipboard

[DESIGN] Submarine can provide the function of notebook startup and shutdown

Open cdmikechen opened this issue 3 years ago • 3 comments

由于篇幅问题,考虑到英文可能不一定能表达清楚很多执行的细节,暂时以中文进行描述。

目前的 Submarine 每次创建一个新的 NoteBook 都会在 K8s 的CRD资源上创建一个新的实例。基于 notebook-controller 的服务发现的机制,会创建一个 Jupyter 的 Statefuleset 资源和 Service 资源。这是一个正常的处理流程,用户在 NoteBook 启动后可在 Submarine 上点击名称访问这个实例。 但是每一个实例在不同的使用者创建并使用后并不是一直在运行代码的,很多情况下在执行了一个idea或者验证了一些预想的情景和数据后,这个 NoteBook 实例就会被搁置。虽然用户稍后退出了 Submarine,但是这个实例仍然存在,这对于集群来讲就是一个被占用的无用的 Pod。

我目前的考虑是希望 Submarine 能提供一个针对 NoteBook 启动和停止的功能,这个功能会分为2个部分来实现。

  1. 在目前 NoteBook 功能的列表操作部分添加 启动/停止 按钮。用户在确认不使用该 NoteBook 时候可关闭 Pod,但是相关的 workspace 等资源不进行回收;再次启用后可继承原来的资源重启服务。
  2. 确认一种自动停止的机制,在用户指定时间不操作后,Submarine 自动停止该实例。在用户再次需要时可再启动 NoteBook。

针对 1 方案,可如描述中提到的添加 启动/停止 按钮,让用户自行控制。 针对 2 方案,目前已知的条件下,可基于 Jupyter 的 metric 指标利用 Promethues 进行采集,然后 Submarine 服务会轮询指标情况,针对指定时长(假定为30分钟)没有过执行的 Pod 做资源回收。我在自己的测试环境下针对既有的 Jupyter 服务做了如下的测试和方案验证:

Jupyter 容器基于 notebook-controller 做定制化资源注册,但是 Service 缺少 lables,暂无法使用 Promethues OperatorServiceMonitor 做服务发现,故使用 PodMonitor做验证。在这里,我创建了一个名称为 test 的 NoteBook 实例。PodMonitor 的描述文件如下:

apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
  name: notebook-test
  namespace: submarine
  labels:
    k8s-app-pod: 'true'
spec: 
  podMetricsEndpoints:
    - path: /notebook/submarine/test/metrics
      port: notebook-port
  namespaceSelector:
    matchNames:
      - submarine
  selector:
    matchLabels:
      statefulset: test

Xnip2021-12-30_20-32-16

如图可以看到,采集的指标内,kernel_currently_running_total{type="python3"} 资源可以作为系统运行时的一个判断。 同时,我们也可以添加独立的 Service 做到相同的效果:

kind: Service
apiVersion: v1
metadata:
  name: notebook-test-metric
  namespace: submarine
  labels:
    statefulset: test
spec:
  ports:
    - name: http-test
      protocol: TCP
      port: 8888
      targetPort: 8888
  selector:
    statefulset: test
  type: ClusterIP
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: notebook-test
  namespace: submarine
  labels:
    k8s-app-service: 'true'
spec:
  endpoints:
    - path: /notebook/submarine/test/metrics
      port: http-test
  namespaceSelector:
    matchNames:
      - submarine
  selector:
    matchLabels:
      statefulset: test

基于服务发现后的 Promethues 指标如下如所示: Xnip2021-12-30_20-33-44

cdmikechen avatar Dec 30 '21 12:12 cdmikechen

提供启停的 Rest 服务,具体处理逻辑:

  • 在表 notebook 中新增字段,代表是否启动,默认为 1 启动。
ALTER TABLE submarine.notebook ADD started TINYINT(1) DEFAULT 1;
  • 提供 启动/停止 的 Rest 接口。

关闭接口会将 started 设置为 0。同时,删除指定的 notebooks.kubeflow.org 资源,相关其他资源(例如pvc、configmap、ingress等)不删除。 启动接口会将 started 设置为 1。重新创建 notebooks.kubeflow.org 资源。

  • 新增 NoteBook 的 Status:stopped

cdmikechen avatar Dec 31 '21 00:12 cdmikechen

如何实现自动启停

  1. 配置相关参数 submarine.notebook.prometheus.enable

    是否可支持采集 NoteBook 的 Prometheus 指标。如果开启,在 submitter 为 k8s 的时候,会自动注册 PodMonitor

  2. 配置相关参数 submarine.notebook.prometheus.labels

    配置扫描的标签,默认为空,可支持的描述方式为:k8s-app-pod:true,k8s-app-pod2:true,用逗号隔开

  3. 配置相关参数 submarine.server.tasks.autostop.enable

    是否支持 NoteBook 自动关闭,默认为关闭。该参数需要在 submarine.notebook.prometheus.enable 启动后才可实现此服务。

  4. 配置相关参数 submarine.server.tasks.autostop.duration

    自动任务扫描不活跃的持续事件,默认为分钟级别,默认为 30 分钟。该参数需要在 submarine.notebook.prometheus.enable 启动后才可实现此服务。

  5. server 端新增可轮训的调度任务,基于分钟间隔进行调度任务。

    按照 NoteBook 资源去扫描不活跃的事件,当超过当前不活跃的时间,系统调用关闭接口关闭该 NoteBook

cdmikechen avatar Jan 04 '22 09:01 cdmikechen

hi, @cdmikechen good job! The program is very carefully designed.

xunliu avatar Mar 22 '22 07:03 xunliu