石师傅 發表於 2022-2-23 21:51:00

DevOps 前端开发和 Spug

<h2 id="devops-前端开发和-spug">DevOps 前端开发和 Spug</h2>
<p>朋友新工作是进行 DevOps 前端开发,涉及 Spug。</p>
<h3 id="devops-是什么">DevOps 是什么</h3>
<p>DevOps 是一种思想。用于促进开发和运维之间的沟通、协作或整合。</p>
<p><em>Tip</em>:DevOps 是 Development 和 Operations 的组合词,即开发和运维。运维工程师 最基本职责是保证服务(产品)的稳定性。</p>
<h4 id="devops-也是沟通协作的秩序化">DevOps 也是沟通协作的秩序化</h4>
<p><strong>假如</strong>软件开发由两个部门组成:开发部门(dev)和运维部门(ops)</p>
<ul>
<li>dev 负责设计产品以及将产品做出来。</li>
<li>ops 负责将 dev 做出的产品进行发布部署、并反馈问题给 dev</li>
</ul>
<p><em>Tip</em>:测试工程师(it行业也叫 QA)在哪里?那就放在开发部门。因为产品得没有问题才能交付给运维。</p>
<p>上面提到 DevOps 是为了:”促进开发和运维的沟通“,既然是”<strong>促进沟通</strong>“,那么两个部门之前需要做的事情还是得做,只是何时做?由谁做?</p>
<p>请看 DevOps 生命周期图:</p>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/665957/galleries/2104361/o_220221065553_devops.png"></p>
<p>DevOps 是一个无穷大符号,表明是一个不断提升效率和持续的<strong>过程</strong>。</p>
<p>从 plan 开始,依次转到 code、build 阶段,测试(test)没有问题则说明可以发布(release),于是运维可以部署(deploy),接着对产品进行操作(operate),一旦监控(monitor)发现问题,则将反馈到计划阶段(plan),如此不断<strong>循环</strong>。</p>
<ol>
<li><code>plan</code>,计划阶段。开发团队根据需求制定计划,一旦计划制定,编码就开始了</li>
<li><code>code</code>,编码。工具有 git</li>
<li><code>build</code>,使代码可执行(例如前端需打包成 dist)。例如 java 中的 maven</li>
<li><code>test</code>,测试代码是否有缺陷。自动化测试工具有 Selenium</li>
<li><code>release</code>,发布。经过几次手动或自动化测试,我们认为它已准备好发布并被送往运维团队</li>
<li><code>deploy</code>,部署。运维现在将代码部署到环境中。自动化部署有 kubernetes</li>
<li><code>operate</code>,操作。部署好了,就使用产品。自己人或用户使用</li>
<li><code>monitor</code>,监控。工具有 nagios</li>
<li><code>monitor -&gt; plan</code>。监控中收到的问题,直接反馈给 plan(计划阶段)。即<strong>集成阶段</strong></li>
<li>编码修复问题,测试通过,则继续发布,称之为持续集成。持续集成的工具有 Jenkins</li>
</ol>
<h3 id="使用-jenkens-落实-devops">使用 jenkens 落实 DevOps</h3>
<p>DevOps 是一种思想,使得软件开发能持续的提升效率。</p>
<p>落实 DevOps 思想需要使用一些工具。尽可能的让其<strong>自动化</strong>。</p>
<p>先来做一个题,请匹配下列工具与 devops 阶段:</p>
<div class="mermaid">flowchart TB
    subgraph b
    code
    build
    test
    deploy
    end

    subgraph a[工具]
    gradle
   
    git
    selenium
    puppet
    end

    click git "https://baike.baidu.com/item/GIT" _blank
   
</div><p><em>Tip</em>:例如 <code>git</code> 匹配 <code>code</code>。</p>
<p>笔者将使用 jenkins 将 code、build、test、release、deploy 这几个阶段自动化。最终达到的目的就是,一旦代码修改并提交,jenkins 就会给我打包、部署。</p>
<h4 id="安装-jenkins">安装 jenkins</h4>
<p>进入 jenkins 官网,提到“简易安装——Jenkins 是一个基于 Java 的独立程序,可以立即运行,包含 Windows、Mac OS X 和其他类 Unix 操作系统”。</p>
<p>点击“下载”进入 download 页面,下载稳定版(LTS)的 war 包(<code>Generic Java package(.war)</code>)。点击确提示“您的连接不是私密连接”,从中文版切换成英文版在试,即可下载。</p>
<p><em>Tip</em>:.war 可以通过 java 命令运行;另一种是 .msi,放入 tomcat 中运行,而 tomcat 的运行也依赖于 jdk/jre。</p>
<p>下载后通过 <code>java -jar</code> 运行 jenkins,报错(<code>java</code>),所以我们得安装 java 的 jdk。</p>
<pre><code class="language-javascript">jenkins&gt; java -jar '.\jenkins .war'
</code></pre>
<p>来到官网(Java Downloads)下载 windows 版本。</p>
<p><em>Tip</em>:下载速度太慢,于是笔者百度,从某人的网盘随便下载了一个jdk,一直 next 安装即可。</p>
<p><code>java</code> 命令正常执行,说明安装成功:</p>
<pre><code class="language-javascript">PS C:\Users\75394&gt; java -version
java version "1.8.0_271"
Java(TM) SE Runtime Environment (build 1.8.0_271-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.271-b09, mixed mode)
</code></pre>
<p><em>Tip</em>:笔者未做环境变量(例如 JAVA_HOME、Path)的设置,但发现环境变量中的 Path 自动给设置上了。</p>
<p>再次运行 jenkins:</p>
<pre><code class="language-javascript">jenkins&gt; java -jar '.\jenkins .war'
Running from: devops-test\jenkins\jenkins .war
webroot: $user.home/.jenkins

...

2022-02-09 12:18:48.127+0000     INFO    jenkins.install.SetupWizard#init:

*************************************************************

Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:

// 用于“解锁 Jenkins”
d6f001fb9d324847965fcc3e881b43e8

This may also be found at: C:\Users\75394\.jenkins\secrets\initialAdminPassword

*************************************************************

2022-02-09 12:21:33.350+0000     INFO    h.m.DownloadService$Downloadable#load: Obtained the updated data file for hudson.tasks.Maven.MavenInstaller
2022-02-09 12:21:40.330+0000     INFO    hudson.util.Retrier#start: Performed the action check updates server successfully at the attempt #1
2022-02-09 12:21:40.337+0000     INFO    hudson.model.AsyncPeriodicWork#lambda$doRun$1: Finished Download metadata. 172,577 ms
2022-02-09 12:21:44.829+0000     INFO    jenkins.InitReactorRunner$1#onAttained: Completed initialization
2022-02-09 12:21:44.844+0000     INFO    hudson.WebAppMain$3#run: Jenkins is fully up and running
</code></pre>
<p>终端输出的“d6f001fb9d324847965fcc3e881b43e8”(即密码),用于下面的<strong>解锁</strong> Jenkins。</p>
<p><em>Tip</em>:默认情况下,您的 Jenkins 在 <code>https://localhost:8080/</code> 上运行。 这可以通过编辑 jenkins.xml 来更改,它位于您的安装目录中。 该文件也是更改其他引导配置参数的地方,例如 JVM 选项、HTTPS 设置等 —— 官网</p>
<p>浏览器访问 jenkins:<code>https://localhost:8080/</code>,页面显示“Jenkins 正在准备工作,请稍候...”:</p>
<pre><code class="language-javascript">// Jenkins 正在准备工作,请稍候...
Please wait while Jenkins is getting ready to work ...
// 当 Jenkins 准备就绪时,您的浏览器将自动重新加载。
Your browser will reload automatically when Jenkins is ready.
</code></pre>
<p>约5分钟,提示“解锁 Jenkins”,内容如下:</p>
<pre><code class="language-javascript">解锁 Jenkins
为了确保管理员安全地安装 Jenkins,密码已写入到日志中(不知道在哪里?)该文件在服务器上:

C:\Users\75394\.jenkins\secrets\initialAdminPassword

请从本地复制密码并粘贴到下面。

管理员密码

// 待输入:d6f001fb9d324847965fcc3e881b43e8

</code></pre>
<p>输入密码后,进入“自定义Jenkins”:</p>
<pre><code class="language-javascript">自定义Jenkins
插件通过附加特性来扩展Jenkins以满足不同的需求。

[安装推荐的插件]            [自定义安装插件]
</code></pre>
<p>笔者点击“自定义安装插件”,但没有安装任何插件,于是进入“jenkins 就绪”:</p>
<p><em>Tip</em>:初次使用,没有经验,建议还是选择“安装推荐的插件”</p>
<pre><code class="language-javascript">Jenkins已就绪!
你已跳过创建admin用户的步骤。要登录请使用用户名:'admin' 及用于访问安装向导的管理员密码。
您已经跳过了 Jenkins URL的配置。

要配置 Jenkins URL的话,到“Jenkins管理”页面。
Jenkins安装已完成。
</code></pre>
<p>点击“开始使用 jenkins”,进入主页。</p>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/665957/galleries/2104361/o_220223015705_jenkins-0.png"></p>
<p>下次启动 jenkins 还是运行 <code>java -jar '.\jenkins .war'</code>,用户名是 admin,密码是 d6f001fb9d324847965fcc3e881b43e8。</p>
<p><em>Tip</em>:默认是英文,可以安装汉化插件(插件搜索 chinese)。</p>
<h4 id="效果展示">效果展示</h4>
<p><em>注</em>:整个实验在只涉及一台个人笔记本(Windows 10 家庭中文版),相关软件有 jenkins、jdk、nginx、github</p>
<ul>
<li>本地 nginx 服务器里面有一个 vue 项目,初次访问显示<code>...App1234</code></li>
</ul>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/665957/galleries/2104361/o_220223014934_jenkins-1.png"></p>
<ul>
<li>直接在 github 中修改源码,保存时间是 <code>23:28</code></li>
</ul>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/665957/galleries/2104361/o_220223015058_jenkins-2.png"></p>
<ul>
<li>github 保存后1分钟,jenkins <strong>自动构建</strong>该项目。构建时间为 <code>23:29</code></li>
</ul>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/665957/galleries/2104361/o_220223015104_jenkins-3.png"></p>
<ul>
<li>jenkins 构建成功,再次访问项目,变为 <code>...App12345</code><br>
<img src="https://images.cnblogs.com/cnblogs_com/blogs/665957/galleries/2104361/o_220223015109_jenkins-4.png"></li>
</ul>
<h4 id="jenkins-相关配置">jenkins 相关配置</h4>
<p><em>注</em>:由于整个实验过程有些曲折,遇到许多问题,不太好描述,所以这里仅仅罗列一些核心点。</p>
<p>jenkins 创建项目 jenkins-vue-demo,并进行相关配置</p>
<ul>
<li>
<p>配置 Github 项目的 URL<br>
<img src="https://images.cnblogs.com/cnblogs_com/blogs/665957/galleries/2104361/o_220223015115_jenkins-5.png"></p>
</li>
<li>
<p>源码管理配置 Git,指定到 github 仓库的 Url<br>
<img src="https://images.cnblogs.com/cnblogs_com/blogs/665957/galleries/2104361/o_220223015119_jenkins-6.png"></p>
</li>
<li>
<p>选择构建触发器。笔者使用每分钟去轮询的方式触发<br>
<img src="https://images.cnblogs.com/cnblogs_com/blogs/665957/galleries/2104361/o_220223015126_jenkins-7.png"></p>
</li>
<li>
<p>构建脚本。首先进入 nginx 的 html 目录(即 <code>web服务器的根目录</code>),然后清空该目录的文件和文件夹;接着将 jenkins 工作空间的 jenkins-vue-demo 项目目拷贝到 nginx 的 html 目录;最后就通过 npm 初始化项目,以及构建生成 dist。<br>
<img src="https://images.cnblogs.com/cnblogs_com/blogs/665957/galleries/2104361/o_220223015131_jenkins-8.png"></p>
</li>
<li>
<p>构建脚本执行完毕,目录结构如下:<br>
<img src="https://images.cnblogs.com/cnblogs_com/blogs/665957/galleries/2104361/o_220223015153_jenkins-11.png"></p>
</li>
<li>
<p>配置 jenkins 到 Github 的凭据<br>
<img src="https://images.cnblogs.com/cnblogs_com/blogs/665957/galleries/2104361/o_220223015139_jenkins-9.png"></p>
</li>
<li>
<p>配置 Git<br>
<img src="https://images.cnblogs.com/cnblogs_com/blogs/665957/galleries/2104361/o_220223015148_jenkins-10.png"></p>
</li>
</ul>
<pre><code class="language-javascript">// cmd 执行 where
C:\Users\79344&gt;where git
D:\software-dir\Git\cmd\git.exe
</code></pre>
<h3 id="netflix与devops">netflix与devops</h3>
<p>需多科技巨头和组织都选择了 DevOps 方法,例如 amazon、facebook、netflix。</p>
<p>netflix 在2007 年推出了在线流媒体服务。</p>
<p>2014年估计,每停机1小时,将损失 20w美元,现在 netflix 可以应付这些问题了。</p>
<p>他们以一种神奇的方式选择了 devops。netflix 开发了一款 Simian Army 的工具,可以在不影响用户的情况下不断地在环境中制造 bug,这种混乱促进开发人员构建了一个在任何此类事件发生时都不会崩溃的系统</p>
<h3 id="cicd">CI/CD</h3>
<p>CI/CD 是一种通过在应用开发阶段引入自动化来频繁向客户交付应用的<strong>方法</strong>。</p>
<p>CI/CD 的<strong>核心</strong>概念是持续集成、持续交付和持续部署。</p>
<p>具体而言,CI/CD 可让持续自动化和持续监控贯穿于应用的整个生命周期(从集成和测试阶段,到交付和部署)</p>
<p>CI/CD 既可能仅指持续集成和持续交付构成的关联环节,也可以指持续集成、持续交付和持续部署这三项构成的关联环节。更为复杂的是,有时"持续交付"也包含了持续部署流程。</p>
<p>我们没必要纠结于这些语义,只需记得 CI/CD 其实就是一个<strong>流程</strong>(通常形象地表述为管道),用于实现应用开发中的高度持续自动化和持续监控。</p>
<p>许多企业最开始先添加 CI,然后逐步实现交付和部署的自动化。</p>
<h4 id="ci-持续集成continuous-integration">CI 持续集成(Continuous Integration)</h4>
<p>CI/CD 中的"CI"始终指持续集成,它属于开发人员的自动化流程。</p>
<p>成功的 CI 意味着应用代码的更改会定期构建、测试并合并到共享存储库中。</p>
<p><em>Note</em>:构建、测试通过后,再合并?</p>
<p>一旦开发人员对应用所做的更改被合并,系统就会通过自动构建应用并运行不同级别的自动化测试(通常是单元测试和集成测试)来验证这些更改,确保这些更改没有对应用造成破坏</p>
<h4 id="cd-持续交付continuous-delivery">CD 持续交付(Continuous Delivery)</h4>
<p>完成 CI 中构建及单元测试和集成测试的自动化流程后,持续交付可自动将已验证的代码发布到存储库</p>
<p>持续交付的目标是拥有一个可随时部署到生产环境的代码库</p>
<p>在持续交付中,每个阶段(从代码更改的合并,到生产就绪型构建版本的交付)都涉及测试自动化和代码发布自动化。在流程结束时,运维团队可以快速、轻松地将应用部署到生产环境中。</p>
<h4 id="cd-持续部署continuous-deployment">CD 持续部署(Continuous Deployment)</h4>
<p>对于一个成熟的 CI/CD 管道来说,最后的阶段是持续部署。作为持续交付——自动将生产就绪型构建版本发布到代码存储库——的延伸,持续部署可以自动将应用发布到生产环境。</p>
<p>持续部署意味着开发人员对应用的更改在编写后的几分钟内就能生效(假设它通过了自动化测试)</p>
<p>总而言之,所有这些 CI/CD 的关联步骤都有助于降低应用的部署风险,因此更便于以小件的方式(而非一次性)发布对应用的更改。</p>
<p>不过,由于还需要编写自动化测试以适应 CI/CD 管道中的各种测试和发布阶段,因此前期投资还是会很大。</p>
<h3 id="spug">spug</h3>
<p>灵活、强大、功能全面的开源<strong>运维平台</strong> —— spug官网</p>
<ul>
<li>开源免费,前后端完全开源,方便二次开发</li>
<li>轻松部署,无 Agent 设计,部署方便快捷</li>
</ul>
<p><em>Tip</em>:腾讯蓝鲸是腾讯对外开放的一套支持私有化部署、永久免费的运维解决方案</p>
<p>spug 面向中小型企业设计的轻量级无 Agent 的自动化运维平台,整合了主机管理、主机批量执行、主机在线终端、文件在线上传下载、应用发布部署、在线任务计划、配置中心、监控、报警等一系列功能。</p>
<p><strong>特性</strong>:</p>
<ul>
<li>批量执行: 主机命令在线批量执行</li>
<li>在线终端: 主机支持浏览器在线终端登录</li>
<li>文件管理: 主机文件在线上传下载</li>
<li>任务计划: 灵活的在线任务计划</li>
<li>发布部署: 支持自定义发布部署流程</li>
<li>配置中心: 支持 KV、文本、json 等格式的配置</li>
<li>监控中心: 支持站点、端口、进程、自定义等监控</li>
<li>报警中心: 支持短信、邮件、钉钉、微信等报警方式</li>
<li>优雅美观: 基于 <strong>Ant Design</strong> 的 UI 界面</li>
<li>开源免费: 前后端代码完全开源</li>
</ul>
<p>管理员登录界面:</p>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/665957/galleries/2104361/o_220314005344_about-spug.png"></p>
<h4 id="docker安装-spug">Docker安装 spug</h4>
<p><em>Tip</em>:默认已安装 docker。初次接触 docker 请看 这里。</p>
<ul>
<li>拉取镜像</li>
</ul>
<pre><code class="language-javascript">C:\Users\75394&gt; docker pull registry.aliyuncs.com/openspug/spug
Using default tag: latest
latest: Pulling from openspug/spug
9b4ebb48de8d: Pull complete
29382e5eb331: Pull complete
4d5237b679ae: Pull complete
6e6a89bf863e: Pull complete
ac331224f129: Pull complete
7be9fe47e7d8: Pull complete
e728e4a0c191: Pull complete
5917c661446c: Pull complete
d3c7d151176c: Pull complete
819a366f7741: Pull complete
6c2f968c028e: Pull complete
dacd1907e067: Pull complete
7918f2774cc6: Pull complete
a871dc4790c0: Pull complete
Digest: sha256:f81eabfd5bbd56c3b7d7fff043262914b21db5ebbe0102f4aa40345bba9c1704
Status: Downloaded newer image for registry.aliyuncs.com/openspug/spug:latest
registry.aliyuncs.com/openspug/spug:latest
</code></pre>
<p>镜像已下载:</p>
<pre><code class="language-javascript">C:\Users\75394&gt; docker image ls
REPOSITORY                            TAG       IMAGE ID       CREATED       SIZE
registry.aliyuncs.com/openspug/spug   latest    b79726b9911b   8 weeks ago   691MB
</code></pre>
<ul>
<li>持久化存储启动</li>
</ul>
<pre><code class="language-javascript">//D:\pjl\blogv2\exercise\spug 指的是映射本地的磁盘路径,也可以是其他目录,/data是容器内代码和数据初始化存储的路径
C:\Users\75394&gt; docker run -d --restart=always --name=spug -p 80:80 -v D:\pjl\blogv2\exercise\spug:/data registry.aliyuncs.com/openspug/spug
a2b18844c8d138573540dba184c9cf236f21dc88397ddfb4d48466e502191523
</code></pre>
<p>容器已成功启动:</p>
<pre><code class="language-javascript">C:\Users\75394&gt; docker ps
CONTAINER ID   IMAGE                                 COMMAND            CREATED         STATUS         PORTS                NAMES
a2b18844c8d1   registry.aliyuncs.com/openspug/spug   "/entrypoint.sh"   7 seconds ago   Up 5 seconds   0.0.0.0:80-&gt;80/tcp   spug
</code></pre>
<ul>
<li>初始化。创建一个用户名为 admin 密码为 spug.dev 的管理员账户</li>
</ul>
<pre><code class="language-javascript">// docker exec 在正在运行的容器中运行命令
C:\Users\75394&gt; docker exec spug init_spug admin spug.dev
Migrations for 'account':
data/spug/spug_api/apps/account/migrations/0001_initial.py
    - Create model Role
    - Create model User
    - Add field created_by to role
    - Create model History
...
初始化/更新成功
创建用户成功
</code></pre>
<p>初始化完毕后需要重启容器</p>
<pre><code class="language-javascript">C:\Users\75394&gt; docker restart spug
spug
</code></pre>
<ul>
<li>访问测试</li>
</ul>
<p>在浏览器中输入 <code>http://localhost:80</code>,输入用户名(admin)和密码(spug.dev),点击登录即可进入系统。</p>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/665957/galleries/2104361/o_220312023035_spug1.png"></p>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/665957/galleries/2104361/o_220223133209_spug2.png"></p>


</div>
<div id="MySignature" role="contentinfo">
    <section class="m-reprintStatement" style="white-space:normal;/* 防止break-all与nowrap矛盾 */word-break:break-all;">
    作者:彭加李<br>
    出处:https://www.cnblogs.com/pengjiali/p/15929337.html<br>
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
</section><br><br>
来源:https://www.cnblogs.com/pengjiali/p/15929337.html
頁: [1]
查看完整版本: DevOps 前端开发和 Spug