V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
seakingii
V2EX  ›  程序员

寻找方便的在线更新 service 程序的方案

  •  
  •   seakingii · 2022-03-05 12:32:52 +08:00 · 2500 次点击
    这是一个创建于 998 天前的主题,其中的信息可能已经有所发展或是发生改变。

    说下需求:

    我的服务器上运行着十几个 service,是用 c#和 GO 写的可执行文件,当前用 supervisor 来管理,目前更新 service 我是先在 supervisor 里停止它,然后用 FTP 上传新的可执行文件,上传完成后在 supervisor 里启动它.

    如果偶尔更新,这样操作问题不大,现在的问题是经常要更新多个 service,感觉这样效率太低.

    有没有这种方案: 1 上传新的可执行文件时不需要在 supervisor 先停止 service 2 上传完成后 service 会自动重启 3 不太需要优雅的"不中断服务更新",短时间停止一下问题不大.

    如果能用 supervisor 实现最好,其它的也可以考虑.

    不熟悉 linux 运营这块,请指点...

    22 条回复    2022-03-06 17:49:09 +08:00
    FrankAdler
        1
    FrankAdler  
       2022-03-05 12:52:41 +08:00
    用 systemd 代理 supervisor ,语法更简单,ftp 建议换成脚本
    go build xxx
    scp xx [email protected]:/xxx
    ssh [email protected] "
    tar ...
    mv ...
    rm ...
    systemctl restart xxx
    ....
    "
    echo "手工"
    brader
        2
    brader  
       2022-03-05 15:17:58 +08:00
    简单搞得话很容易,你可以使用 git 仓库来存储代码,然后你在服务器起一个定时任务,写个 shell ,1 分钟拉取一次 git 代码,判断 git 代码有更新,就执行 build 和重启命令。
    liuhan907
        3
    liuhan907  
       2022-03-05 15:46:19 +08:00
    如果你不抗拒新东西的话,弄个单节点 k8s ,比方说 k3s 这种轻量发行版,然后每次发版本打个新镜像往 k8s 一丢就了事了。
    ch2
        4
    ch2  
       2022-03-05 15:57:04 +08:00
    这是一个示例脚本:
    CGO_ENABLED=0 go build -o my_service -a -ldflags '-extldflags "-static"' .
    scp service [email protected]:/root/my_service
    ssh [email protected] "bash /root/update_service.sh"
    其中在部署机器上的 /root/update_service.sh 内容为:
    systemctl stop my_service
    rm -rf /usr/local/bin/my_service
    cp my_service /usr/local/bin
    chmod +x /usr/local/bin/my_service
    systemctl start my_service
    此外需要在编译的机器上添加待部署机器上的 ssh 私钥,以及在待部署机器上写 systemctl 的 my_service.service 文件
    gesse
        5
    gesse  
       2022-03-05 17:37:07 +08:00
    [program:bin]
    command=/opt/bin

    $ mv /opt/bin /tmp/
    $ mv ~/newbin /opt/bin

    $ supervisorctl restart bin


    linux 文件占用是用的 inode ,而非路径,所以可以把正在执行的文件 move 到其他目录,然后把新版本的执行文件 mv 到正确目录,然后 restart
    gesse
        6
    gesse  
       2022-03-05 17:39:22 +08:00
    如果是十多个 supervisor 服务, 完全可以把执行文件放到一个目录里, 然后替换目录

    再一次性
    $ supervisorctl reload
    codehz
        7
    codehz  
       2022-03-05 17:40:16 +08:00 via Android
    虽然 linux 不允许覆盖正在运行的程序,但是你可以先删除了再上传同名文件(
    crackhopper
        8
    crackhopper  
       2022-03-05 18:06:23 +08:00
    显然用 k8s 更容易搞定。搞很多脚本,脚本维护也是问题。后续系统继续扩展也是问题。
    ClericPy
        9
    ClericPy  
       2022-03-05 18:15:27 +08:00
    以为挺常见的场景, 结果楼上给的都不是我常见的...

    gunicorn gracefully restart - Google 搜索 - https://www.google.com/search?q=gunicorn+gracefully+restart&oq=gunicorn+gracefully+restart&aqs=chrome..69i57.7670j0j7&sourceid=chrome&ie=UTF-8

    搜索关键词主要就是 gracefully restart, 可以参考上面 gunicorn 通过 HUP 信号做的那种

    以前也见过 nginx 切换流量的做法, 反代指向的本地服务多个版本是多个进程实例和端口的, 这种也是不宕机直接切换流量的路子

    如果其他的云原生那边的就不提了, 饿了吃饭去了
    EminemW
        10
    EminemW  
       2022-03-05 18:29:01 +08:00
    jenkins 写脚本
    hongzx
        11
    hongzx  
       2022-03-05 18:56:49 +08:00 via iPhone
    用 docker 来运行
    Git+Drone 自动化部署
    vvhhaaattt
        12
    vvhhaaattt  
       2022-03-05 19:07:12 +08:00 via Android
    ansible 没人提么?我们之前 supervisor 管理 python 跟 golang ,都用 supervisor 发布。
    vvhhaaattt
        13
    vvhhaaattt  
       2022-03-05 19:07:35 +08:00 via Android
    @vvhhaaattt ansible 发布……
    ragnaroks
        14
    ragnaroks  
       2022-03-05 21:00:58 +08:00
    docker
    cosmtrek
        15
    cosmtrek  
       2022-03-05 21:26:30 +08:00
    k8s +1
    kirile
        16
    kirile  
       2022-03-05 21:53:09 +08:00
    我是自己用 go 写了个程序, 负责服务停止, 替换, 服务启动, 监听一个 rpc 服务用来接收需要替换的文件压缩包, 把多个服务的路径什么的维护起来. 然后配合 WinForm 客户端, 更新服务的时候就基本上两步就行, 选择服务->点击部署. 另外 WinSCP 可以支持即使 systemd 服务运行着也照样替换 golang 可执行文件, 这个的话也挺方便, 找到目录->拖拽覆盖->重启服务
    xuanbg
        17
    xuanbg  
       2022-03-06 08:20:52 +08:00
    Jenkins 装一个,每个 service 配一个 job 。哪个有更新点一下哪个 job 的构建就完事。
    Dogtler
        18
    Dogtler  
       2022-03-06 09:26:50 +08:00 via iPhone
    K8s 滚动更新
    shoaly
        19
    shoaly  
       2022-03-06 10:47:31 +08:00
    如果是我来做这个方案的话:
    1 做一个 http 的中心化软件下载地址
    2 做一个脚本 , 通过 cron 定期从中心化节点下载文件(假设为 xxx), 并且命名为 xxx.update (这一步通过 cron 做更稳定无脑)
    3 另一个脚本检查 xxx.update 和 本地 xxx md5 是否一致, 如果不一致就删除 xxx , 然后将 xxx.update 修改为 xxx, 并且运行重启脚本: pkill xxx && chmod+x xxx && nohup ./xxx &
    4 如果 md5 一致, 就删除 xxx.update
    sampeng
        20
    sampeng  
       2022-03-06 14:20:01 +08:00
    = =!这不就是 docker-composer 干的事么。。。
    sampeng
        21
    sampeng  
       2022-03-06 14:22:29 +08:00
    公司有一些这种很简单,没必要 k8s 的。。。
    平常升级就是 docker-compose up --force-recreate ,简单可依赖
    initd
        22
    initd  
       2022-03-06 17:49:09 +08:00
    运行环境是 虚拟机
    brew 自定义 tap
    egoist/bget 下载 github rel

    转换成 容器
    可以用 dokku 的 Paas 持续部署


    运行环境是 容器
    docker-compose
    https://docs.docker.com/compose/
    短链 dc.moz.one

    k8s
    https://kubernetes.io/docs/reference/kubectl/docker-cli-to-kubectl
    短链: dtk.moz.one
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3735 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 04:23 · PVG 12:23 · LAX 20:23 · JFK 23:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.