1个不稳定版本
0.1.0 | 2023年10月1日 |
---|
#621 in HTTP服务器
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