#健康检查 #进程 #负载均衡 #k8s # #替换 #远程

bin+lib launcho

2k行Rust代码的超简化k8s替代品

1个不稳定版本

0.1.0 2023年10月1日

#621 in HTTP服务器

CC0许可证

87KB
2K SLoC

Launcho - 2k行Rust代码的超简化k8s替代品

我对k8s的复杂性感到沮丧,所以我正在编写我能想到的最简单的替代品。这个程序所做的只是

  • 重新启动已死亡的进程
  • 执行健康检查,并重新启动失败的进程
  • 轮询日志,以便远程访问(例如,使用kubectl get logs
  • 允许远程重新配置,包括升级进程
  • 管理负载均衡(包括淘汰正在升级的进程,直到它们通过健康检查才将流量发送到新进程)

这一切都是用大约2k行的Rust编写的。

设置launcho

cargo install launcho

在服务器上执行

sudo apt-get install ipvsadm # Make sure you have ipvsadm installed
sudo launcho server

还可以将launcho server添加到init.d或任何其他位置,以便在启动时运行。

一旦服务器启动,您就可以在服务器上运行launcho print-auth来获取连接所需的认证信息。它看起来可能像

# Paste this into ~/.launcho/launcho-client-auth.yaml on the client machine
host: change-me-to-point-to-the-server.example.com:12888
cert: |
  -----BEGIN CERTIFICATE-----
  MIIBWzCCAQKgAwIBAgIUY2V0NJXiRC+qMdydF42rmIR6TfIwCgYIKoZIzj0EAwIw
  ITEfMB0GA1UEAwwWcmNnZW4gc2VsZiBzaWduZWQgY2VydDAgFw03NTAxMDEwMDAw
  MDBaGA80MDk2MDEwMTAwMDAwMFowITEfMB0GA1UEAwwWcmNnZW4gc2VsZiBzaWdu
  ZWQgY2VydDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBNEBkWsYqN/EDudl0mE
  f2cLr1iWbGMB7YmoxmVy+VMzAZ1WvKO23kenPNKNHZC9vomNLww7HtRHDau4GmXd
  +J6jFjAUMBIGA1UdEQQLMAmCB2xhdW5jaG8wCgYIKoZIzj0EAwIDRwAwRAIgSd8V
  Q7j0xX/zGmyiaAToDXMzo/3pjmZ4WtLUg4ROfTYCIFV1Kjw1lHObS0HPVUkc8UKq
  Kul0XMy4//sfCpqT1SeD
  -----END CERTIFICATE-----
private: null
token: 4d0f71f5d2d69b25b6a1638245386ebb1b3f6f4cc109006907707fa6e30bedd8

然后,您可以将此内容粘贴到客户端机器上的~/.launcho/launcho-client-auth.yaml中,首先将host更改为指向服务器。

最后,您可以控制launcho服务器。您应该能看到类似的内容

$ launcho status
Events:
  Warning { msg: "Auth file not found at \"/root/.launcho/launcho-server-auth.yaml\" -- generating a new one" }

使用launcho

主要思想是launcho有一个“目标”配置,它正在尝试达到。此目标是通过您可以通过版本控制来指定的yaml来指定的。要获取当前目标

launcho target get     # or launcho t get

要设置当前目标

launcho target set FILE     # or launcho t set FILE

默认的目标文件将看起来像

# No orchestration target set, this is an example file.
# Use `launcho target get` and `launcho target set` to edit this.

# Create processes like this:
processes:
  # -
  #   name: "example_proc"
  #   command: ["python", "server.py"]
  #   env:
  #     # Use ${SECRET_NAME} to access secrets defined in the server config.
  #     DATABASE_URL: "${DATABASE_URL}"
  #   # List all services this process should receive traffic from.
  #   # Each service for each process gets allocated a port, which is given
  #   # via a corresponding environment variable, in this case SERVICE_PORT_WEB.
  #   receives:
  #     - "web"
  #   # Define an endpoint to hit to check for health.
  #   health:
  #     service: "web"
  #     path: "/health"
  #   #uid: "whoever"
  #   #gid: "whoever"
  #   #cwd: "/var/wherever"

# Create services like this:
services:
  # -
  #   name: "web"
  #   on: "127.0.0.1:5000"

这里有几个概念

名称 含义
target launcho尝试保持运行的进程和服务配置
process launcho尝试保持运行的单个进程(基本上是一个k8s pod)
service 每个“服务”将流量负载均衡到接收它的某些进程集(基本上是一个k8s服务)
secret launcho维护一个将密钥映射到字符串的键值存储(基本上是一个k8s secret)
resource Launcho 存储数据处理过程中可以访问的数据块(类似于 k8s 容器镜像)

每个服务将被路由到接收它的每个进程。对于每个接收到的服务,每个进程都将获得一个名为 SERVICE_PORT_SERVICE_NAME 的环境变量 -- 您的进程应绑定到 localhost:该服务端口 以接收它们负载均衡的服务请求份额。

您可以使用以下命令列出/上传/下载/删除资源

launcho resource ls          # or launcho r ls
launcho resource up FILE     # ... and so on
launcho resource down RESOURCE_ID OUTPUT_FILE
launcho resource rm RESOURCE_ID RESOURCE_ID...

您可以使用以下命令修改机密信息

launcho secret ls       # or launcho s ls
launcho secret get SECRET_NAME SECRET_NAME... 
launcho secret set SECRET_NAME VALUE
launcho secret rm SECRET_NAME SECRET_NAME...

请注意,修改机密信息将自动启动任何依赖该配置的进程的新版本,一旦新版本运行正常,流量将被迁移。

预期的工作流程

进程可以请求将某些资源放置在其工作目录中,您可以在进程启动之前运行一个命令。这是制作基本“容器镜像”的预期机制。例如,使用以下服务器:

const http = require('http');
const url = require('url');

const server = http.createServer((req, res) => {
  const path = url.parse(req.url).pathname;
  if (path === '/health') {
    res.statusCode = 200;
    res.end('OK');
  } else if (path === '/') {
    res.statusCode = 200;
    res.end('Hello, world!');
  } else {
    res.statusCode = 404;
    res.end('Not Found');
  }
});

const port = process.env.SERVICE_PORT_TRAFFIC;
server.listen(port, () => console.log(`Server running on port ${port}`));

我们可以设置以下目标(使用 launcho target set target.yaml

processes:
  -
    name: "main_server"
    resources:
    -
      id: "${BUNDLE_RESOURCE_ID}"
      file: "bundle.tar.bz2"
    before: |
      tar -xf bundle.tar.bz2
      mv bundle/* .
    command: ["node", "server.js"]
    receives:
      - "traffic"
    health:
      service: "traffic"
      path: "/health"

services:
  -
    name: "traffic"
    on: "127.0.0.1:5000"

然后要部署新版本,您只需做以下操作

# Assuming bundle/server.js contains the above server...
tar -cvvhjf bundle.tar.bz2 bundle/
launcho resource up bundle.tar.bz2 | tee NEW_RESOURCE_ID
launcho secret set BUNDLE_RESOURCE_ID $(cat NEW_RESOURCE_ID)

这将启动服务的新版本。一旦新版本通过健康检查,所有连接到端口 5000 的流量将从旧版本重新路由到新版本,然后旧版本将被杀死。

您可以使用 launcho status 检查服务器状态,并通过 launcho logs PROCESS_RANDOM_NAME 获取其日志。

假设您通常将某种 TLS 处理反向代理指向您的服务(例如,可能将 nginx 指向 127.0.0.1:5000,并将 nginx 保留在 launcho 的管理范围之外,但这不是强制性的)。

依赖关系

~26–45MB
~822K SLoC