总体步骤

类似把大象关进冰箱分为3步:

  1. 把冰箱门打开
  2. 把大象放到冰箱里
  3. 把冰箱门关上

将物理机迁移至ESXi 7.0虚拟机也需要3步:

  1. VMware vCenter Converter Standalone Client将物理机打包成VMware Workstation兼容的vmdk文件;
  2. 将vmdk文件上传至ESXi系统存储,并通过vmkfstools转换其为ESXi7.0兼容的格式;
  3. 用上一步转换而来的虚拟硬盘文件创建虚拟机。

1 打包物理机

  1. WMware官网下载VMware vCenter Converter Standalone Client,可能需要注册一个账号
  2. 在需要打包的物理机上安装并运行VMware vCenter Converter Standalone Client
  3. 点击Convert machine,弹窗中选择source typeThis local machine进入下一步:
    WX20220106-103415-1.png
  4. 在目标系统中按照以下界面选择,建议存储位置这里可以通过插入一个移动硬盘并选择这个盘,以方便后续上传到ESXi:
    WX20220106-103534-2.png
  5. 在选项/Options步骤,编辑Data copy type,只选择需要的打包的分区,比如引导分区、系统盘等
    WX20220106-104151-3.png
  6. 继续点击Next/Finish直到完成转换,稍候片刻,即可获得导出的VMware Workstation兼容的vmdk文件

2 上传vmdk,使用vmkfstools转换格式

由于打包的vmdk是兼容VMware Workstation的版本,是不兼容ESXi的。如果不转换格式的话,会出现类似报错:

无法打开磁盘 scsi0:m: 磁盘类型 n 不受支持或无效。请确保磁盘已导入。
  1. 进入ESXi Web终端,通过存储 -> 数据存储浏览器进入并打开/创建相关文件夹,并上传上一步打包出来的vmdk文件:
    迁移1.png
  2. 找到数据存储所在位置:
    迁移2.png
  3. 主机 -> 管理 -> 服务 中打开SSH服务,详见启用对 ESXi Shell 的访问
  4. 通过终端SSH连接到ESXi服务器
  5. cd到第2步存储所在的文件夹,再进一步cd到上传的vmdk文件所在的文件夹
  6. 执行vmkfstools转换格式命令,记得最后要使用-d thin来使用精简置备模式,以节省空间

    # 进入导入vmdk文件所在的文件夹
    cd /vmfs/volumes/xxxxx248-xxxx75d-07eb-xxxxd6c0/xxxx
    # 转换格式,假定原文件名为orginal.vmdk,转换后的文件名为dest.vmdk
    vmkfstools -i orginal.vmdk dest.vmdk -d thin
  7. 等待片刻,即可享用转换出来的vmdk文件

3 创建虚拟机

创建一个新的虚拟机,添加上一步转换出来的vmdk文件为新的硬盘

  1. 进入ESXi终端,通过虚拟机 -> 新建虚拟机 -> 创建新虚拟机
    迁移3.png
  2. 自定义设置,硬盘选择那里添加一个现有硬盘,选择刚才创建的vmdk文件(dest.vmdk
    迁移4.png
  3. 安装常规步骤创建好虚拟机
  4. 理论上你可以运行你的虚拟机了

参考

LEDE的vmdk在esxi下提示scsi0:0的磁盘类型不受支持或无效_Jian Sun_的博客-程序员宝宝
WorkStation 虚拟机迁移到 ESXi的后续处理. 转载

目录

  1. 安装和配置Jenkins
  2. 构建和发布Docker镜像

安装和配置Jenkins

  1. 准备一个操作系统,并安装Docker,具体可以参考Docker文档

    • 若是Linux操作系统,应增加docker用户组并将当前作业用户添加进组,否则必须使用sudo升权执行

      sudo groupadd docker
      sudo usermod -aG docker ${USER}

      退出登陆或重启系统后即可直接运行docker

  2. 拉取Jenkins相关Docker镜像并运行

    • 拉取并运行blueocean版本的Jenkins镜像:

      docker run -p 8080:8080 -p 50000:50000 -v jenkins_data:/var/jenkins_home jenkinsci/blueocean
    • 为了支持SSH操作,拉取并运行jenkins/ssh-agent镜像:

      cat pub.key | docker run jenkins/ssh-agent

      * pub.key配置相关证书密钥中Jenkins容器的公钥

  3. 配置Jenkins:

    • 浏览器打开Jenkins镜像宿主机IP地址所在8080端口,如:http://localhost:8080
    • 使用上一步启动Jenkins获得的初始密码进入系统并创建用户
    • 进入Manage Jenkins -> Manage Plugins添加Maven Integration pluginGitLab PluginSSH pluginDocker Pipeline这些插件
    • 进入Manage Jenkins -> Global Tool Configuration配置JDK、Git、Maven、Docker
      jenkins-jdk.png
      Jenkins- Git.png
      Jenkins- Maven.png
      Jenkins-Docker.png
  4. 配置相关证书密钥和用户名密码,为连接GitHub、Gitlab,Docker私服、远程服务器做准备:

    • 配置Jenkins自身的证书:进入Jenkins所在容器,创建SSH密钥/证书,并添加进Jenkins系统中(用来从Github/Gitlab下载源码)

      # 进入jenkins容器,假设容器ID为abc
      docker exec -it abc /bin/bash
      # 生成证书,默认在/var/jenkins_home/.ssh/下有id_rsa和id_rsa.pub两个密钥和公钥
      ssh-keygen -t rsa
    • 将公钥作为Deploy Key添加进对应的Github或者Gitlab项目中
    • Manage Jenkins -> Credentials中添加此密钥(Jenkins自身密钥)
    • 继续添加Docker私服的用户名密码
    • 继续添加远程服务器SSH登陆的用户名密码
  5. 创建Jenkins构建脚本

    • 若是Maven项目,可以选择Maven项目构建;若是纯Docker构建,直接选择Freestyle
    • 配置source为Git,输入repo地址(git@开头),并选择Jenkins自身密钥作为凭证(Credentials)
    • 添加构建步骤,选择Docker构建和发布,输入Dockerfile所在文件夹,若就在根目录则不必输入
    • 选择使用Docker构建,设置镜像名称为Docker私服地址/用户/镜像名,勾选发布镜像,并选择Docker私服的凭证
    • 在触发条件出选择push event,将对应的Webhook填写到GitHub/Gitlab对应项目的Webhook设置中去
  6. 测试构建脚本(略)
  7. 在远程服务器上线
    通过布置一个脚本,进行远程登录+拉取并运行docker镜像,即可实现在远程服务器上上线的操作。

参考

  1. 高效部署Springboot的三种方式,知乎

Nginx settings:

/etc/nginx/sites-available/domain.name.com

include        /etc/nginx/proxy.conf;
limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s;
server_tokens  off;

upstream corshapi {
        server localhost:5001;
}

add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;


limit_req  zone=one burst=10 nodelay;

location /api {
        proxy_pass         http://localhost:5001;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection keep-alive;
        proxy_set_header   Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
}

Reference

  1. Publishing to local IIS failed to include JS files for Pages when using 'abp-script' Tag
  2. Configure IdentityServer4 behind nginx reverse-proxy
  3. Enforce HTTPS in ASP.NET Core
  4. Host ASP.NET Core on Linux with Nginx
  5. Depoloyment Problem: invalid_request
  6. ABP Framework to Azure! - Part 10
  7. Sign-in - IdentityServer 4
  8. Authorization in Angular UI

What is frp?

rp is a fast reverse proxy to help you expose a local server behind a NAT or firewall to the Internet. As of now, it supports TCP and UDP, as well as HTTP and HTTPS protocols, where requests can be forwarded to internal services by domain name.
frp also has a P2P connect mode.

github.com:frp

架构

FRP分为服务端frps和客户端frpc。架构如下:

设置服务端systemd service, /etc/systemd/system/frps.service:

[Unit]
Description=Frp Server Service
After=network.target

[Service]
Type=simple
User=nobody
Restart=on-failure
RestartSec=5s
ExecStart=/usr/bin/frps -c /etc/frp/frps.ini
LimitNOFILE=1048576

[Install]
WantedBy=multi-user.target

服务端设置好后:

Congratulations, frps install completed!
==============================================
You Server IP   : 123.123.123.123
Bind port       : 7020
Dashboard port  : 7500
vhost http port : 7080
vhost https port: 7443
Privilege token : tokenxxxxx!
Max Pool count  : 50
Log level       : info
Log max days    : 3
Log file        : enable

客户端 frpc.ini:

[common]
server_addr = 123.123.123.123
server_port = 7020

[web]
type = http
local_port = 80
custom_domains = frp.domain.com

nginx 代理:
server {

# 监听nginx 80端口
listen 80;
# 域名配置 记得一定要加上*.frp.xxx.com +  frp.xxx.com这个,只加frp.xxx.com是不行的,无法支持泛域名做sub模式
server_name *.frp.xxx.com frp.xxx.com;
location / {
    proxy_pass http: //127.0.0.1:7001;
    # 这个Host的header一定要加,不然转发后frp拿不到通过哪个域名访问的,导致转发失败
    proxy_set_header   Host             $host;
    proxy_set_header   X-Real-IP        $remote_addr;
    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
}

}

参考

  1. FRP内网穿透与Nginx结合,实现多子域名转发服务(四级子域名)

《架构整洁之道》是Uncle Bob|Bob大叔【美】Robert C. Martin(罗伯特 C. 马丁)在2017年写的介绍软件架构的书。本书从最细节的编程范式,再讲到SOLID设计原则,然后依次介绍高阶的组件、软件架构。后面强调了数据库、框架、Web等是实现细节而非架构。最后则是其他人写的拾遗和半工作经历自传。整本书有点像搭建房子时介绍建筑架构,先从砖和钢筋混凝土到房价再到房子等由小到大介绍开了,很有趣。

作者总结了3种编程范式:

  1. 结构化编程:最传统的,程序是欧几里得公理系统;对函数控制权的直接转移进行了限制和规范;
  2. 面向对象编程:通过封装、继承和多态,对程序控制权的间接转移进行了限制和规范;
  3. 函数式编程:通过变量不可变(函数无状态)、对可变进行隔离,对程序中的赋值进行了限制和规范。

作者总结的架构精髓:SOLID原则,可以有效指导我们如何构建每一个程序模块。

S代表Single Responsibility Principle,即单一责任原则:每个模块都只有一个需要被改变的理由。据说与Conway Law直接相关。

O代表Open Close Principle,即开闭原则:允许新增代码来改变系统的行为,而不允许通过改变老代码来改变系统行为。Software entities (classes, modules, functions) should be open for extension but closed for modification

L代表Liskov Substitution Principle,李氏替换原则:组件之间必须满足设计约束才可以相互替换;派生类(子类)对象可以在程序中代替其基类(超类)对象。

I代表Interface Segregation Principle,接口隔离原则:客户(client)不应被迫使用对其而言无用的方法或功能。Clients should not be forced to depend upon interfaces that they don't use。接口隔离,避免不必要的依赖。

D代表Dependency Inversion Principle,依赖反转原则:高层次的策略性代码不应该依赖于底层的实现性代码,依赖关系应该反过来。例如业务逻辑不应该依赖UI或者数据库。High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions。

作者继续阐明组件构建原则。

组件定义:组件是程序部署的最小单元,即可执行文件和库,比如jar文件。

组件的聚合要满足以下三个原则:

  1. REP 复用/发布等同原则:软件复用的最小粒度应该等同与发布的最小粒度。这样任何变更不会导致过多的发布,或者过度的源代码修改。
  2. CCP 共同闭包原则:把那些会同时修改,并且为相同目的而修改的软件模块(类)放到同一个组件中去,即共同闭包。这实际是SRP在组件级别的重述,因为可维护性的重要性远大于可复用性。我们可以通过组件张力图,去计量共同闭包。
  3. CRP 共同复用原则:不要强迫一个组件的用户依赖他们不需要的东西。

组件的耦合应该满足下面三个原则:

  1. 无循环依赖原则:组件依赖关系中不应该出现环状结构。如果有,可以通过DIP解决。
  2. 稳定依赖原则:依赖关系必须指向更稳定的方向。被依赖的最多的组件应该是最稳定的,因为它难以被修改。计量关系:I = Fan-out/(Fan-in + Fan-out)。接口最稳定。
  3. 稳定抽象原则:一个组件的抽象化程度应该与其稳定性保持一致。

讲完组件,作者开始阐述软件架构。

主要是把策略和细节分离,在整个软件中,合理的划分边界,同时合理的规划好边界之间的依赖关系。同时做好策略与层次的设计:低层次的组件应该去依赖高层次的组件。

业务逻辑作为程序中最核心的用来挣钱/省钱的逻辑,应该位于层次同心圆最中间。而实现细节,或者I/O(UI、数据库等),则应位于最外面。依赖关系则是,最外面依赖最里面。
the clean artchitecture.jpeg

个人感觉,软件架构计时做好合理的分层,这里包括水平和垂直分层两个部分。水平只的是从UI、业务逻辑、持久化等数据流去分层;垂直分层则是从业务模块和领域的角度去分层,例如订单模块、CRM模块等。一个合理的软件架构,应该同时考虑这两种分层,并选择与之相应较好的侧重点。Salesforce是典型的侧重水平分层的平台,有明确的UI层(Visualforce Page、aura、lwc)、逻辑层(Apex)、数据层(SOQL、DML)。而目前流行的微服务架构,则更侧重垂直分层。

这两种分层的取舍,作者并没有过多解释,只是强调了策略与细节、分层与边界、分层与依赖等更加基础的内容。为什么?我猜是因为在架构上去侧重某种分层,结果就是出现框接,而作者认为框架是细节,并非架构。

作者还强调很多看起来像框架的东西,其实是实现细节

比如数据库、Web、应用程序框架,他们都是实现细节。

作者还对一个视频销售网站的架构设计,进行了精彩的讨论。

在另外一个人写的拾遗部分,主要讨论了作者的理论和自己的理解。

最后,作者回顾了从20世纪60年代到90年代,作者的软件工作生涯。可以从中看到作者不断总结教训经验,慢慢得出本书的这套理论。

参考

  1. douban 架构整洁之道
  2. wiki 开闭原则
  3. wiki 里氏替换原则
  4. wiki 接口隔离原则
  5. wiki SOLID
  6. zhihu 小话设计模式原则之:依赖倒置原则DIP
  7. The Clean Architecture