多ssh key部署同一台server以及ssh-agent的最佳实践


有些时候,我们需要在一台服务器里拉取github的项目,由于安全考虑,github的规定一个deploy key只能用在一个项目里面。 所以多个项目就需要我们用多个ssh key

而我们如果只在一台服务器,除了默认生成的id_rsa,则需要为每个项目加入生成一个独立的ssh key,这样就存在多个秘钥和公钥对,那么我们执行git pull或者git push这样的命令的时候,ssh如何找到正确的key呢?

这个时候需要用到ssh的config以及ssh-agent来解决这个问题,下面我们一步步来说明这个过程。

生成新的密钥对

1
2
ssh-keygen -f ~/.ssh/project1_rsa
ssh-keygen -f ~/.ssh/project2_rsa

上面这个命令,一路回车的话,当然也可以输入密码,如果使用密码,那么在使用的时候则需要输入这个密码(通过ssh-agent这个代理程序可以帮你记住密码,则可以不用每次都输入),这个会在用户的目录下生成2个密码对,生成的内容如下:

1
2
3
4
5
> ls ~/.ssh
project1_rsa # project1 的私钥
project1_rsa.pub # project2 的公钥
project2_rsa
project2_rsa.pub

然后,接下来,为了让ssh知道我们生成的密钥对里面的私钥,需要用ssh-add命令加入

1
ssh-add ~/.ssh/project1_rsa

如果报下面这个错误:

1
Could not open a connection to your authentication agent.

则说明ssh-agent代理程序没有启动,那么再返回来启动这个代理程序,然后再加入

1
2
3
eval `ssh-agent -s` # 启动代理
ssh-add ~/.ssh/project1_rsa
ssh-add ~/.ssh/project2_rsa

这里有个问题,ssh-agent不一定是默认启动的,这个agent在下一个终端会话进来后可能用不了,这个问题我们后面在说。

接下来,为了完成让git pull的时候,自动认得目录,接下来,我们要做两个配置

1. 创建~/.ssh/config

1
touch ~/.ssh/config

把下面内容贴进去

1
2
3
4
5
6
7
8
Host project1
HostName github.com
User git
IdentityFile /home/ubuntu/.ssh/project1_rsa
Host project2
HostName github.com
User git
IdentityFile /home/ubuntu/.ssh/project2_rsa

这个配置的意思是,当ssh碰到要去连接的Host为project1的时候,会把HostName 设置为 github.com,并且使用git用户,私钥使用的是IdentityFile /home/ubuntu/.ssh/project1_rsa

2. 修改git remote

进入你的github项目

1
git remote set-url origin git@project1:<your github name>/project1.git
  • your github name: 是你在github注册的名字

由于这里使用的git ssh协议,那么在你执行git pull这些命令的时候,它会去寻找命令~/.ssh/config里面的配置,然后找到根据git@project1来找到Host project1的配置,然后机会ssh会使用这些配置来执行命令。

ssh-agent自动启动

ssh-agent进程一般来说会自动启动,并会自动加载~/.ssh/id_rsa,它启动的时候,创建一个继承SSH_AUTH_SOCKSSH_AGENT_PID环境变量的进程,那么如果你开的会话并没有这些环境变量,那么你的会话无法正确的链接到ssh-agent,即使你用ps -aux | grep ssh-agent可以看到有这个进程,甚至可能有多个ssh-agent(因为你在多个会话里面执行过多次”eval ssh-agent -s“)也无济于事。

如果没有这些环境变量,你执行ssh-add命令的时候,它连不到已经启动的ssh-agent,所以会报Could not open a connection to your authentication agent.这样的错误。

所以我们确保我们启动会话的时候启动ssh-agent。为了实现这个你可以在~/.bashrc或者~/.bash_profile或者~/.profile这些会话启动的时候会加载shell里面加入启动命令,实现的方法有多种,比如你可以直接加入evalssh-agent -s``. 那么而每次启动,然后同时加入trap 'kill $SSH_AGENT_PID' EXIT,让会话退出的时候kill掉这个启动的经常。 然而这样做,每当你其他一个shell就会创建一个ssh-agent的进程。

为了解决这个问题,可以用封装成下面的命令,加入到~/.bashrc(~/.bash_profile或者~/.profile)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

SSH_ENV="$HOME/.ssh/agent-environment"

function addAdditionSSHKey {
/usr/bin/ssh-add $HOME/.ssh/project1_rsa;
/usr/bin/ssh-add $HOME/.ssh/project2_rsa;
}

function start_agent {
echo "Initialising new SSH agent..."
/usr/bin/ssh-agent | sed 's/^echo/#echo/' > "${SSH_ENV}"
echo succeeded
chmod 600 "${SSH_ENV}"
. "${SSH_ENV}" > /dev/null
/usr/bin/ssh-add; # add default id
addAdditionSSHKey; # add addition ids
}

# Source SSH settings, if applicable

if [ -f "${SSH_ENV}" ]; then
. "${SSH_ENV}" > /dev/null
#ps ${SSH_AGENT_PID} doesn't work under cywgin
ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
start_agent;
}
else
start_agent;
fi

其中addAdditionSSHKey可以配置你要加入的私钥,每次你加入新的私钥的后,都可以直接在新的会话窗口直接执行addAdditionSSHKey帮助你加入新的key

这个段shell会先判断~/.ssh目录下面存储的agent-environment环境变量信息是否存在,如果存在,说明之前已经启动了一个ssh-agent进程,只需要把它的变量export到当前的会话即可,如果没有,则启动一个新的ssh-agent,并把相关环境变量保存下来

这个agent-environment环境变量存储的信息大约如下,

1
2
3
SSH_AUTH_SOCK=/tmp/ssh-qyakUB3GkFmc/agent.9914; export SSH_AUTH_SOCK;
SSH_AGENT_PID=9916; export SSH_AGENT_PID;
#echo Agent pid 9916;

. "${SSH_ENV}" > /dev/null则个语句就是执行命令,把已经保存的环境变量export到当前的会话。

reference:

在linux云服务器上部署新项目

新建用户

假设我们要跑自己的博客,则考虑新建一个用户叫做blog来专门运行blog的相关程序

1
2
3
4
5
6
7
8
# 新建用户
useradd -d /home/blog -m blog
# 设置密码
passwd blog
# 新建.ssh
mkdir /home/blog/.ssh
# 把root可以的所有可以控制机器的key复制给新用户,这样可以通过blog@x.x.x.x 来直接访问用户
chown blog:blog /home/blog/.ssh/authorized_keys

默认这个用户是不在sudoer里面的,也即是不能通过sudo来安装全局的程序
如果需要安装需要root运行的程序,需要用root用户进去安装后,给这个用户用,也就是如果你开一个用户给某个独立项目,可以让他们随意折腾,但是需要root权限的时候,需要他们来找你

ssh-keygen && git

一般来说,你还需要去git服务器上拉代码,那么可以就需要把blog这个用户给创建一个密钥对,然后把公钥交给git托管服务器作为deploy key使用

1
ssh-keygen

是否设置密码随你自己需要

设置好后,登录这个用户ssh blog@x.x.x.x的终端后,就可以直接执行

1
git clone ...

通过certbot来自动申请证书

1
2
3
4
5
6
sudo add-apt-repository ppa:certbot/certbot
sudo apt install certbot
certbot --version # 查看安装的certbot version
sudo apt-get install python-certbot-nginx # 安装nginx插件
certbot plugins # 查看plugin安装结果
certbot --nginx -d blog.domain.com # 申请blog.domain.com这个域名的证书

自有短地址服务yourls最简单的部署方式

介绍

有时候,我们需要对不同的流量来源做精准的统计,比如我们群发短信,希望对群发效果做a/b test,可以在短信里面的带的landing page做区分,然后需要有精准的统计工具,这个时候我们可以用短地址系统来做统计,也就是在不同的短信里面使用不同的短地址,然后对短地址系统来做数据采集和分析。

yourls是一个基于php+mysql开发开源的短地址服务系统,除了基础的跳转外,还提供丰富的统计和插件。

安装

我们知道使用php的包安装工具composer有时候是件非常痛苦的事情,还有yourls系统需要apache或者nginx配合,把服务器搞得很乱,因此,最好的办法就是把yourls封装到docker里面,打包交给docker-composeswarm 或者 k8s 来管理。

如何正确的给hexo、hugo等静态博客做dns解析?

问题

之前我搭建hexo的时候,觉得github.io的速度比较快,所以默认的dns通过cname解析到了github.io,然后搜索引擎解析到coding的pages。这样个人访问飞快,搜索引擎又可以抓取, 多好啊。

但是,告诉大家,这样个方案是不靠谱的,因为github.io这个域名已经大面积被污染

我怎么知道的?刚好昨天用helm add一个repo,刚好这个repo又是部署*.github.io的静态网站,安装失败后,用curl看这个请求这个地址的细节,发现请求的地址是127.0.0.1。怪不得前两天我的博客突然访问不了,还纳闷qiang怎么会封我一个小小的博客呢,不至于吧。

优雅的将hexo部署到github和coding

1. 前言

上次写了篇文章 使用github action同时部署hexo到github和coding最优雅的方式(支持多github账号),从实现原理的角度做了介绍,由于实现的目标比较多,所以看起来比较复杂,这次我们不讲原理,仅仅按实现目标来介绍如何配置。

1.1 目标

先说我们要实现的目标,然后再按目标来介绍方法

  1. hexo的source存放在独立私有库jiuhao
  2. 生成的静态文件存放在github和coding独立的库
  3. 本地可以通过 hexo d -g一个命令一次性部署到github和coding
  4. 可以通过git push推送到github的surce仓库后,由action触发部署到github和coding的静态仓库
  5. 同时实现3和4,只需要配置一次_config.yml。而不需要在action里面写死目标静态仓库的地址,方便维护
  6. 支持多个github账号,同时也支持多个coding账号

说明:

  • 目标 1 把 source 放在独立的私有库是安全性考虑
  • 目标 3 和 4 是方便可以使用两种方法都能达到部署的目标, 3 是手工部署, 4 是通过git push触发,比如 github 的 action 可能某些原因失败了,暂时又没时间去维护,那么我可以直接在本地hexo d -g部署就行
  • 目标5是实现3和4的时候,两种方法的目标仓库(publish repo)地址配置只需要一处维护,不需要分散在 _config.yml 和 github action
  • 目标 6 是可选目标。 如果不需要区分工作和私人用的github 账号,可以不需要理会这个目标。

deepin + virtual box 安装增强扩展失败的问题修复

问题

在ubuntu desktop里面用virutalbox来安装deepin,然后如果希望宿主机和虚拟机之间可以进行内容的copy/paste,需要安装扩展。

一般来说,如果在windows下,直接在virtualbox里面执行安装功能,virtualbox会直接下载然后完成安装,但是ubuntu下安装deepin如果直接执行操作,virtualbox也会去下载扩展的安装包,但是下载完后,安装的时候,会报找不到扩展的安装包。而且之后重启你会发现不能正常进入deepin系统。

使用github action同时部署hexo到github和coding最优雅的方式(支持多github账号)

目标

我们知道使用github action 可以很简单的部署hexo的静态文件到github pages,但是如果在国内我们希望部署到github pages同时也部署到coding,然后通过dns双线路由,另外,我们可能有多个账号,比如公司的和个人的博客或者网站,也是同时部署到coding和github,那就这个github action解决不了,下面我们改造一下,使其达到这个目标:

  1. hexo的source存放在独立库
  2. 生成的静态文件存在独立的库
  3. 提交markdown文件后,自动生成静态文件
  4. 自动部署到github pages
  5. 自动部署到coding
  6. 同一份hexo source库,只需要配置一次hexo的_config.yml,就可以直接通过hexo deploy -g 或者git push来触发部署
  7. 支持多个github账号,同时也支持多个coding账号

阿里云618活动升级成拼团了

刚刚收到阿里云发的短信,说618活动升级,点进去一看是拼团活动,拼团的价格比之前还要低,之前2核4G是320/年,现在开始是301/年,3年从960跌到了904. 之前我已经对比过,阿里在这次活动里优惠力度比另外两家还有大,现在竟然还继续降价。虽然还是“但见新人笑那闻旧人哭”系列,但是阿里对于拉新可以说非常上心。

于是,赶紧弄了个拼团链接分享给大家

阿里云、腾讯云和华为云618活动细节对比

上次写文章的时候,腾讯云在618搞活动,阿里云华为云没有跟进,刚刚发现阿里云和华为云也上架了618活动了. 下面我们直观的看看三者的差异.

活动对比结论

先说结论, 具体大家再去看下面的内容.

阿里云,,区分了个人新用户和企业新用户的专区, 腾讯云则只有针对企业的新用户的专区,没有专门针对个人新用户的专区,但是它的标有新用户的产品则是不区分企业还是个人的.

阿里云有提供给企业和个人开发者的免费体验的产品,性能还不错的.体验期为14天到3个月不等. 个人的短企业的长. 腾讯云则没有这种免费的体验, 这点明显阿里云更灵活,先用好了再给钱.

腾讯云,每天提供5场的秒杀活动,价格一如既往的优惠,而且性能都是100%,而阿里的低端ecs则是突发性能的多, 这点看,腾讯云比较给力.

华为云,有自己研发硬件的能力,性能非常不错(当然可能也和它的云的使用饱和度有关系),也都是性能100%,而且对于新人,有很多套餐价格比腾讯云还要划算.

总的来看两家的活动符合他们一贯的风格, 阿里云优惠种类多,比较灵活,腾讯云和华为云主打性价比,总体而言.大家各有优势.

如何管理linux设备上的bridge(网桥)和docker bridge

什么是bridge(网桥)?

bridge是一种技术,可以把一个linux设备上的两块网卡桥接在一起,如何对外表现为一个大的网卡接口,这样做有很多用途

比如你有两台设备,但是又没有路由器,那么把他们桥接在一起,可以共享其中一台的网络,这样两台都可以上网,这两台设备也可以是vm,不一定是物理设备

还有一种用途,就是监控两个设备的网络流量,比如用wireshark来监控他们间的流量

总的来讲,桥接就是将一台计算机插入到已经与较大网络(例如Internet)建立连接的另一台计算机上,然后让这台桥接上去的计算机可以使用联网计算机的连接。

哪些软件使用了桥接技术

bridge在vm(virtual machine)的领域非常有用,比如docker, k8s, multipass等。

docker可以帮忙创建很多独立的虚拟容器,那这些容器怎么上网,相互之间怎么通信呢,docker提供多种途径,其中一种就是bridge。

查看设备上有哪些bridge,可以用brctl命令,如果你的没有这个命令,可用apt或者yum安装** sudo apt install bridge-utils**

按资源需求来选择合适的云服务器

之前写过一篇文章,介绍个人拥有服务器能用来干啥好玩的, 里面列了一些个人云主机能用来做的一些场景, 但是,实际上不同场景对于服务器配置的需求也各不一样,无论个人还是企业都有必要在选择云主机的时候有清晰的思路. 否则等买了才发现不合用(不一定是用不了,就是不能很好的满足需求),而有失去了新人(无论个人还是企业)优惠,就很不划算了.

在我们去分析具体的场景应该怎么选择之前,我们先看看影响我们选择的几个主要因素,也就是服务器资源的4个重要组成部分:

  • CPU
  • 内存
  • 硬盘
  • 网络

这4样东西,可以说是一个服务器它生命里面最重要的东西了,那么我们简要(否则又变成长文了,大家都不喜欢看长文…)的来说一说这4个家伙.

阿里云、腾讯云、华为云多角度对比

因为公司的工作,我们用到阿里云,腾讯云,华为云,甚至电信云,其他还有一些小的服务商也测试过.

根据我们的经验,如果从多个角度对比: 价格,性能,稳定性,安全性

(以下对比仅仅是从过往的我们使用和压测对比,做的历史经验总结)

总体来说:

  • 价格: 腾讯云>阿里云
  • 性能: 腾讯云>阿里云
  • 稳定性: 阿里云>腾讯云
  • 安全性: 阿里云>腾讯云

熟悉软件工程的人一看就知道,这个东西其实也符合软件工程的规律,性能和安全性(稳定性)往往难以兼得.

另外,根据我们测试,华为云作为后起之秀,性能比腾讯云还要好,这点出乎我们的意料之外(我想可能更华为有硬件研发能力有关系),这点可供大家参考.

新手如何选择云服务器

最近在个人小项目需要购买一些服务器,花了一些时间,对市面上主要的云服务提供商做了一些简单的对比,记录下来备忘,同时,也给希望可以给同样需要的人提供一些思路,节省时间.

主要考虑因素

云服务器商的各种套餐让人眼花缭乱,原因是因为各自的资源性能不一样。

虽然有一些标准可以对比,根据个人的使用经验,但是实际性和云服务商的平台架构和技术实力还是差别蛮大,比如不同平台,物理隔离的技术的差异,可能你的服务器会因为隔壁大户老吴抢资源太厉害,而遭遇性能问题。

从不了解到知道再到熟悉,有一个过程。所以对于新手来讲,先入门体验一下是最重要的,而搞清楚服务商之间的种种差别反而不太重要,所以,初次体验,我建议成本怎么低怎么来。

集线器 (hubs),交换机(switch) 和网桥(bridge)的区别

image

集线器(hub)

  • hub工作在OSI的第一层,发给 hub 的数据包会广播给所有的端口
  • hub的是直接的物理连接到每一台设备的网卡,所有有较低的连接丢失风险,因为hub是所有设备共享带宽的一个设备,所以它是半-双工的,所以他会存在冲突,同时发给hub的入站和出站包会存在冲突,需要算法解决冲突,因此hub的性能相对会差一些
  • hub本质上是一个多端口中继器,它不管包的内容,只是简单的把某个端口收到的包,再广播给其他所有的端口,所以,一台主机发给另外一台主机的内容会被其他无关的主机监听到。有安全问题

网桥(bridge)

image

Dqlite,基于sqlite 高可用(HA)数据库

k3s之前的multi-master的支持 Mysql, PostgreSql, etcd 这3个方案,现在正在实验一个内嵌的multi-master方案,使用一个sqlite的HA版本-dqlitedqlite-顾名思义,distibution sqlite,以后稳定的话,可能会成为官方推荐的HA方案。

Dqlite用主要做了几个事情:

  1. 提供一个基于raft的解决方案,基于一个叫 c-raft 的 raft轻量级实现,

  2. 把sqlite封装起来,给它存储层注册一个定制driver来操作数据

  3. CAP理论里,和绝大多分布式数据库一样,dqlite选择了(CP without A), 就是选择了Consistency(一致性)、Partition tolerance(分区容错性),而不保证 Availability(可用性),也即是:

  4. 保证了数据一致性

  5. 保持强一致性,用户请求需要在服务器中所有的分区里面完成了一致性才返回

  6. 但是,不保证每个请求都能得到没有报错的响应

瑞士军刀NC

nc是网络调试的一款强大的工具,是用于处理TCP或UDP数据的通用实用程序,是黑客界的瑞士军刀

看看的常规用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
> tldr nc
Netcat is a versatile utility for working with TCP or UDP data.
More information:
https://nmap.org/ncat

- Listen on a specified port and print any data received:
nc -l {{port}}

- Connect to a certain port (you can then write to this port):
nc {{ip_address}} {{port}}

- Set a timeout:
nc -w {{timeout_in_seconds}} {{ipaddress}} {{port}}

- Serve a file:
nc -l {{port}} < {{file}}

- Receive a file:
nc {{ip_address}} {{port}} > {{file}}

- Server stay up after client detach:
nc -k -l {{port}}

- Client stay up after EOF:
nc -q {{timeout}} {{ip_address}}

- Scan the open ports of a specified host:
nc -v -z {{ip_address}} {{port}}

- Act as proxy and forward data from a local TCP port to the given remote host:
nc -l {{local_port}} | nc {{hostname}} {{remote_port}}

nc对于网络的操作可以分为接受发送这两种操作

区别是参数 -l, -l 是监听端口的参数,有这个参数,说明启动的是一个服务端

其他没有-l的操作,则是向其他网络端发起网络操作,是一个客户端

个人拥有云服务器能用来干啥好玩的?

偶尔还是能看到,有人问个人买云服务器能用来怎么玩好,下面我根据个人经验做一点分享。

总的来讲,买服务器可以分为3种目的:

  • 学习:学习各种计算机相关技术
  • 分享:个人博客等
  • 试验:个人有应用的一些想法,想快速试验一下

下面是具体的用法(某一个项目可能包含上面说的多个目的在一起,就不具体划分了):

理解k8s的Flannel网络

此文始发于我的简书博客: k8s的Flannel网络,特此声明

引: 之前写过一篇文章介绍如何管理linux设备上的bridge(网桥)和docker bridge, 今天我们来看看k8s的网络模型。

我们先来看图示例,下面则个是k8s的网络模型图。

k8s的网络模型

我们知道,在k8s里面最小的管理单元是pod,一个主机可以跑多个pod,一个pod里面可以跑多个容器。

如上面所示,一个pod里面所有的容器共享一个网络命名空间(network namespace),所以,pod里面的容器之间通信,可以直接通过localhost来完成,pod里面的容器之间通过localhost+端口的方式来通信(这和应用程序在宿主机的通信方式是一样的)。

什么是子网掩码?

“子网”掩码,顾名思义,它就是拿来划分子网的,更准确的说,划分子网的同时,还能通过它知道主机在子网里面的具体ip的具体地址。

用途

那么划分这个子网有什么用呢?

  1. 方便管理,不同的子网可以相互隔离
  2. 我们知道,IPv4的ip地址资源比较紧张,实际上整个互联网就是一个巨大的局域网,ip地址有限,那么通过划分子网,如何再在子网里面分配ip地址给子网的主机,这个时候同一一个ip就可以给一整个子网所共用,就解决了互联网ip不够的问题

原理

既然要划分子网,要有一个规则,告诉路由器,IP的哪一部分是表示子网,哪一部分表示我在这个子网里面具体的地址

所以,实际上IP细来讲又分为三部分:网络部分(network)子网段部分(subnetwork)和主机部分(host)

一般大家喜欢把网络部分和子网部分合并成为网络地址(网络号),把子网看做是网络的一部分,主机部分称为主机地址(主机号)

NAT探珠

概要

NAT的全称是 Network Address Translation, 其实看英文名,就知道它的大概意思:网络地址转换。

严格来说,

  • 这个Address,包括了IP地址和端口。
  • 而这个Translation,则包括来来源地址和目的地址,以及来源端口和目的端口这4者之间的转换

那么NAT规则其实定义的就是这4者的映射关系,告诉路由器应该怎么去转换(Translation)

那么什么时候会用到NAT技术呢,答案是,从一个网络到另外一个网络,有一些文章在写NAT的时候,常讲的是外网(互联网)到私网(私域子网)的通信的时候,其实这只是其中一种场景,实际上,只要是两个网络间需要通信,都可以用NAT来做。

下面这个图讲的就是互联网和私网这个场景的NAT

1
2
3
4
5
6
7
8
9
10
 \ | /                  .                               /
+---------------+ WAN . +-----------------+/
|Regional Router|----------------------|Stub Router w/NAT|---
+---------------+ . +-----------------+\
. | \
. | LAN
. ---------------
Stub border

Figure 1: A typical NAT operation scenario