云溪的 blog
  • Archive
  • Media
  • Search
  • Tags
  • About
Home

Posts

手把手教你用 GitLab CI/CD 部署项目

如果你用 GitLab 来做项目管理,我非常建议你了解一下 GitLab 的 CI/CD 的功能,它可以自动帮你完成项目的打包、部署、上线。 免去了上线过程中的复杂操作,对于标准化流程机器向来比人做的好。也能减少很多不必要的 Human Error 。 本文以 Python 项目部署为例,讲一下 CI/CD 中的一些部署思路,给你一个引子,引出你对 CI/CD 更多的探索。 概括来讲,CI/CD 包含两个关键步骤:配置和执行,只要你的项目根目录里有 .gitlab-ci.yml 配置文件,GitLab 就会读取,然后按照配置去执行计划。 配置: 是通过 GitLab CI 配置文件 (.gitlab-ci.yml )来告诉,执行者(Runner)要做哪些事情 执行: 执行的动作是由 Runner 来做的, Runner 是一个可执行程序,可以在任意一台服务器上。项目可以配置一个或多个 Runner。 关于配置 以下是 .gitlab-ci.yml 的一个模板,可以复制到你项目中改改就可以完成你项目的自动部署功能。 stages: # 定义步骤 - deploy deploy_test: # job 名称 image: instrumentisto/rsync-ssh:latest # 指定 docker 镜像 stage: deploy # 所属的步骤 script: # 执行的脚本 - mkdir -p ~/.ssh - echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config - echo "$TEST_SSH_PRIVATE_KEY" >> ~/.ssh/id_rsa # 将 GitLab 里设置的的私钥环境变量输出到 ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa - ssh -p 22 -i ~/.ssh/id_rsa root@"$TEST_SERVER" "cd $TEST_PROJECT_PATH && git pull && source .venv/bin/activate && pip install -r requirements.txt && python test.py " retry: 2 # 如果任务执行失败,会进行 2 次的重试 only: refs: - test # 仅当代码被推送到 test 分支时才会触发该步骤 deploy_prod: image: instrumentisto/rsync-ssh:latest # 指定镜像 stage: deploy script: - mkdir -p ~/.ssh - echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config - echo "$PROD_SSH_PRIVATE_KEY" >> ~/.ssh/id_rsa # 将 GitLab 里设置的的私钥环境变量输出到 ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa - ssh -p 22 -i ~/.ssh/id_rsa root@"$PROD_SERVER" "cd $PROD_PROJECT_PATH && git pull && source .venv/bin/activate && pip install -r requirements.txt && supervisorctl restart server" retry: 2 only: refs: - master 配置文件包含 stages 和 Job 两个概念。stages 根据项目上线一共有多少个环节来定义,如你可以能有「构建」(build)->「测试」(test)->「部署」(deploy)。我这里为了演示方便只配置了一个 deploy, stage 名称可以随意取,但是尽可能的语义化一些,这样在仓库看日志会比较清晰。 ...

February 15, 2025 · 2 min · 云溪

我开始用 Neovim 来开发了

一直以来,我都感觉传统编辑器鼠标和键盘的频繁切换的体验让我无法接受,它让编程这件事情拆分成了两个系统:输入和移动。我一直有将他们统一的冲动,但又受限于 vim 学习成本过高的固有认知一直没有行动。它像一根若有若无的刺一直刺痛着我,直到有一天我接触到了 lazyvim,我想也许是时候改变了。 lazyvim 可以极大程度降低了配置难度,可以在不进行任何配置的情况下拥有一个轻量级的代码编辑器。 我切换 Neovim 除了 lazyvim 降低了配置成本还有另一个原因:我认为自己还会有相当长的时间开发相关的活动,一个高度可定制的编辑器,可以让我随心所欲的打造一个称手的工具。 关于配置我使用的是 https://github.com/craftzdog/dotfiles-public 并在此基础上扩充了 PHP 开发相关的配置。在文章底部我会贴出自己的 dotfile 仓库,目前我的配置可以用于 VUE、PHP、GO 的开发,如果需要可以自取。 在开发之前我们还是需要对 Neovim 基础操作有一定的了解,这里介绍一下我的学习方式。 我是通过 https://lazyvim-ambitious-devs.phillips.codes/ 一书建立的最初的基本只是,后续又看了一些视频加深我对 Neovim 的理解。 在视频学习的过程中,可以很好的学习资深的 vimer 是如何进行 vim 操作的,拿来主义可以省去很多自己探索的精力。最开始只需要模仿就可以了,等你对 vim 使用熟练后你会有自己的想法,那时自然而然的会形成自己独有的操作方式。 视频的学习我参考了 craftzdog 比较多,在 B 站上也学习了其他人的一些操作技巧。 Neovim 的学习成本也没有想象中那个高,正常下来,一周你就可以比较得心应手的进行开 发了。 得益于 LSP 的技术,让 Neovim 对开发语言的支持和 Vs code 并没什么本质的差别。 Vs code 对语言的支持也是通过 LSP 来实现的。 Neovim 带来了什么?它确实能使我整个开发的工作流完全脱离了鼠标,所有开发的工作包括但不限于代码编写、函数跳转、以及 git 的提交等全部都可以脱离鼠标完成,双手不需要离开键盘区域就可以完成编程所需要的操作。 此外像文件操作:打开、删除、重命名等操作,Neovim 也可以很方便的操作。它确实让我更专注了,所有的操作都没有任何的打断,我不需要频繁的把手离开键盘做一些额外的鼠标操作。 上文说到,Neovim 可定制化程度更更高,理论上你能按照你的习惯去配置 Neovim 来使它与你配合的更默契。 Neovim 会不会对开发效率带来一定的提升?从我目前的使用程度来看,它并不能带来明显的开发效率的提升,Neovim 在一些操作上的确更有优势,但是也有一些操作没有 GUI 更加的高效。总的看来我觉得它的开发效率和 Vs code 差不多。 ...

October 26, 2024 · 1 min · 云溪

谈谈规范

在多年的开发经历中,我发现不重视编程规范是普遍存在的一个问题。很多开发人员对规范的态度都是很抵触的,认为规范的条条框框是枷锁,会降低开发效率。 不仅仅是普通员工,很多公司的管理人员对于规范的重视程度也是不够的,甚至就没有制定规范的想法。 为什么会出现这种现象呢,我想每个人都会有自己的角度,大多数原因可能是因为项目周期紧张,没有时间制定规范,或是单纯的认为规范会影响开发效率。 上面的原因是客观存在的,所以大家对于不制定规范也没有太大的心智负担。今天我想就这个现象谈谈我对规范的认识。 规范一般有两种,一种是项目规范一种是编程规范。 关于项目规范 我在刚开始入行的时候,公司虽然也没有自己的规范,但是带我的前辈,给了我一份谷歌的开发规范,让我学习,代码的书写格式是怎么样的,什么时候应该换行,应该怎么避免写嵌套 if… 这让我对代码规范有了一个最基本的认识。 代码需要书写的简洁,易读。代码规范有点像写文章时的字体工整程度,越遵守代码规范,字体就越工整。你可以想象就算同样的一篇文章,字体工整和字体潦草给阅读人的感受是完全不同的。 后来我在一家公司做管理,刚到公司时也没有自己的规范,每个人的代码风格,变量命名,项目组织的习惯各有不同,导致项目的风格多样,这给我们带来了一些问题。 维护成本高 当我们维护其他同事写的代码的话,需要从头开始阅读一遍代码,才能了解问题具体出在哪。如果我们有规范就不需要通读所有代码,仅需依据规范出问题代码的大体位置。 代码复用差 当我们有一些通用业务需要封装时,如果没有规范,就需要考虑所有的代码风格,甚至要做一些额外的兼容才能把组件封装完成,有了规范我们完全就可以避免这类问题。 项目对接慢 由于没有规范,每次公司来了新同事,我们并没有很完善的文档给到他。导致新同事上手项目比较困难,中间还要不断地去询问老同事,才能对代码有一个相对比较完善的理解。 这无疑增加了很多的摩擦成本,且团队越大,这种摩擦成本就会越高。就像我们都说中文,又各自有自己的方言,大家需要了解每个人的方言体系,才能更好的深入交流。 我们需要“普通话”这样一个统一的说话规范,来降低我们团队内部的摩擦成本。 建立规范 为了解决上述问题,我们结合自身团队的特点,参考了他人的规范制定出了我们自己规范的初版。 初版规范经过内部评审和修改后,我们形成了自己的规范文档。 后续我们在实践的过程中遇到了一些规范上的不足,也进一步对规范做了补充,使规范在原有的基础上不断的迭代和优化。 这样一套规范建立后,使我们每一步都是在之前的基础之上,而不是每一次都是从 0 开始。这让我们可以不断的阶梯向上。 如何让规范落地 规范的制定后就需要考虑规范落地问题,如何让团队更好的遵守规范。 首先需要让团队认识到规范对我们团队合作是有益的。做好心理建设,消除心理的抵制情绪。 把规范塑造成开发文档,让团队养成经常查阅的习惯,对规范有疑惑就去规范文档找答案。 利用工具降低规范的执行难度,像一些代码风格的问题可以通过 IDE 代码格式化解决,不用团队开发者额外注意。 使用静态代码分析工具检测代码是否符合规范,如果使用 CI/CD 可以把这一步集成到 CI/CD 中,让不符合规范的代码,无法提交到线上环境。 关于编程规范 编程规范包括:设计模式,设计原则,编程范式,最佳实践等等。这类规范一般是行业发展多年,一些经验丰富的前辈总结的一些开发工作的规范。 因为这类规范通常是前辈们在长期实践中总结出来的。遵守这类规范能让我们更容易开发出稳定的程序,少走弯路。 这类规范一般都具有普遍性,对语言没有任何的限制,因此一旦你熟练的掌握,你用任何语言开发的程序都会有更好的稳定性,更少 Bug 、更容易维护和扩展。 我发现有些同学会遇到一些奇奇怪怪的问题,或者一段时间后,程序出现了运行瓶颈。有不少是因为没有遵守某些编程规范引发的问题。 有时他们不遵守编程规范,并非不愿意,而是因为他们不了解某些规范。因此对于编程规范,要像探寻宝藏一般,时常去探索一下。不断地完善和补充自己对编程规范的理解。 总结 规范短期看可能会觉得有点浪费时间,影响开发效率,从长期看,却未必如此,那些减少的 Bug, 复用的代码,以及与同事之间协作效率的提升,足以弥补开发时的损耗。 牛顿说:我之所以比现别人看的远,是因为我站在巨人的肩上。 运用前人的智慧和经验,能让我们做事情更加的顺利。要站在前人的肩膀上,哪怕你觉得这个人不够高,也比自己站在平地上看的更远。

September 20, 2024 · 1 min · 云溪

零停机升级服务

在项目迭代的过程中,我们经常会进行更新线上代码的操作,而更新的操作我们会希望影响的用户越少越好,最好是能做到零停机更新。 在目前云原生的大背景下,K8s 的滚动更新策略会更为人知一些,但是一些中小型项目的部署建立一套 K8s 服务从成本和收益的角度来看是有些得不偿失的。 本文介绍用 Docker 和 Traefik 如何实现零停机升级服务。关于 Traefik 在 更靠近云原生的反向代理神器-Traefik 一文中有更详细的介绍。 整个服务部署流程如下 本方案通过 gitlab CI/CD 来进行部署,开发人员仅需在对应的分支提交代码,服务器会自动完成 构建 -> 部署 -> 通知 等操作。 在 部署 阶段通过蓝绿发布的方式来进行零停机升级的。 蓝绿发布是通 shell 脚本进行操作的,由于 Traefik 的 docker provider 不支持动态的增删服务,本方案采取了 file provider,shell 会启动新服务的时候修改Traefik 的 file provider 来把新服务加入到负载均衡的集群,并在新服务启动完成后,把老服务从负载均衡迁出并停用老服务。 得益于 Traefik 对动态配置的支持,所有对配置文件的修改是无需重启 Traefik,它会自动发现配置文件的变动,把最新的配置加载到程序内部。 整个 部署 流程中始终都会有容器在线提供服务,我们也就实现了零停机升级系统的目标。 本文最后会附上一份完整的 demo 链接,感兴趣的可以下载之后运行一下了解整个操作机制。 本方案还存在一些局限,如蓝绿发布其实是 blue 和 green 交替提供服务,如果你本身是一个服务集群,这个方案并不能很好的适应。 如果你面临上述问题可以考虑 docker swarm 来解决问题,或者部署 K8s,其间的选择主要是看你服务的规模。 本文到此基本结束,如果你更好的想法,欢迎留言讨论。 示例代码:https://github.com/yunxi177/zero-downtime References zero-downtime deploys with Docker Compose and Traefik:https://github.com/maxcountryman/aquamarine ...

September 18, 2024 · 1 min · 云溪

更靠近云原生的反向代理神器-Traefik

Traefik 是一个用于反向代理的软件,如果你没有听说过,可以把它看作 Nignx 也是可以的。 Traefik 相比与 Nginx 更适合容器化部署: 只需要配置下容器的标签,Traefik 就可以自动发现新服务的加入,并根据标签绑定对应的域名 支持 TLS 证书自动申请(Let’s Encrypt) 支持 TCP/UDP 协议的转发 支持动态配置,可以在服务运行的状态下进行 Service、Router、Middleware 的增/删/改 Traefik 在项目最初部署阶段,会让整个部署更聚焦。以前用 Nginx 部署,你除了需要把容器启动起来,还需要配置 Nignx 将对应服务的域名反向代理到容器导出的端口上。 Traefik 将这个绑定域名的步骤放在了 docker compose 编写的阶段只需给容器加一个标签即可。项目上线时启动容器,Traefik 根据标签的配置把域名绑定到对应的容器上。 Traefik 可以通过 docker network 容器进行通讯,这意味着容器服务的端口无须再导出到物理机,Traefik 通过 docker network 就可以找到对应的容器处理请求。 Traefik 整个流程如下(中间件非必须,可有可无): 入口点(Entrypoints) -> 路由(Routers) -> [中间件(Middleware)] -> 服务(Service) -> Server Traefik 的配置分为两个:程序配置和路由配置。程序配置通过 traefik.yml 文件进行配置。traefik.yml 提供了路由配置的解析引擎(Providers)。 traefik.yml 配置示例如下: log: level: INFO accessLog: {} api: dashboard: true insecure: true entryPoints: # 入口点配置 web: address: ":80" providers: docker: # 通过 docker label 的方式进行路由配置 endpoint: "unix:///var/run/docker.sock" exposedByDefault: false watch: true network: traefik_webgateway // docker network 用于 traefik 与容器进行通讯 接下来说说 Traefik 一些核心概念: ...

September 2, 2024 · 2 min · 云溪
« Prev  Next  »
© 2025 云溪的 blog