GitHub Actions如何通过跳板机自动部署应用

使用 GitHub Actions 通过跳板机部署应用

在某些情况下,目标服务器无法直接通过 GitHub 访问。这时,我们可以使用跳板机(Bastion Host)来实现自动部署。以下是通过 GitHub Actions 配置跳板机部署的步骤:

1. 在本机生成 ed25519 密钥对

1
2
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""
cat ~/.ssh/id_ed25519.pub

为了防止跳板机和目标服务器之间无法通过 SSH 连接,我们需要在本机生成 ed25519 密钥对,并将其公钥添加到跳板机和目标服务器的 authorized_keys 文件中。其实这个秘钥对在跳板机或者目标服务器上生成都可以,只要能互相通信就行。

2. 在跳板机和目标服务器上添加新生成的公钥

在跳板机和目标服务器上,您需要将新生成的公钥添加到 ~/.ssh/authorized_keys 文件中,以便允许通过 SSH 进行无密码登录。以下是具体步骤:

2.1 登录到跳板机:

1
ssh ${BASTION_USER}@${BASTION_HOST}

2.2. 将公钥添加到跳板机的 authorized_keys 文件:

1
2
echo "新生成的公钥内容" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

2.3. 然后,登录到目标服务器:

1
ssh ${TARGET_USER}@${TARGET_HOST}

2.4. 同样地,将公钥添加到目标服务器的 authorized_keys 文件:

1
2
echo "新生成的公钥内容" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
  • BASTION_HOST:跳板机的 IP 地址或主机名
  • BASTION_USER:跳板机的用户名
  • TARGET_HOST:目标服务器的 IP 地址或主机名
  • TARGET_USER:目标服务器的用户名
  • SSH_PRIVATE_KEY:用于 SSH 连接的私钥

这样,您就可以通过跳板机无密码地访问目标服务器了。
注意:使用哪个登录用户创建的秘钥对,就使用哪个登录用户登录跳板机和目标服务器。

3.将本机生成的私钥id_ed25519拷贝到跳板机~/.ssh/目录下,因为目标服务器的公钥也是使用的本机私钥生成的,所以需要将本机私钥拷贝到跳板机。

1
scp ~/.ssh/id_ed25519 ${BASTION_USER}@${BASTION_HOST}:~/.ssh/

4.测试跳板机和目标服务器是否可以无密码通信

1
ssh -i ~/.ssh/id_ed25519 ${TARGET_USER}@${TARGET_HOST}

如果可以无密码通信,则说明跳板机和目标服务器可以无密码通信。
注意:使用哪个登录用户创建的秘钥对,就使用哪个登录用户登录跳板机和目标服务器。

5. 将私钥id_ed25519的内容添加到GitHub仓库的Secrets and variables中,命名为JUMP_SERVER_SSH_KEY。

6. 创建 GitHub Actions 工作流

.github/workflows 目录下创建一个新的工作流文件,例如 deploy.yml,并添加以下内容:

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92


name: Publish To Production

on:
push:
branches: [main]

env:
NODE_VERSION: "16.14.2"
JUMP_SERVER: "xxx.xxx.xxx.xxx" # 替换为跳板机的真实IP
TARGET_SERVER: "yyy.yyy.yyy.yyy" # 替换为目标服务器的真实IP
SERVER_USER: "ubuntu"
REMOTE_PATH: "/var/www/html/myapp/dist"
ALERT_URL: "https://example.com/notify"
PROJECT_NAME: "测试环境"

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Use Node.js ${{ env.NODE_VERSION }}
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Build
run: yarn build

- name: Install SSH Keys
uses: shimataro/ssh-key-action@v2
with:
key: ${{ secrets.JUMP_SERVER_SSH_KEY }}
name: jump_server
known_hosts: unnecessary
if_key_exists: replace

- name: Setup SSH Config
run: |
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "Host jumpserver
HostName ${{ env.JUMP_SERVER }}
User ${{ env.SERVER_USER }}
IdentityFile ~/.ssh/jump_server
StrictHostKeyChecking=no

Host targetserver
HostName ${{ env.TARGET_SERVER }}
User ${{ env.SERVER_USER }}
ProxyCommand ssh -W %h:%p jumpserver
StrictHostKeyChecking=no
IdentityFile ~/.ssh/jump_server" > ~/.ssh/config
chmod 600 ~/.ssh/config

- name: Debug SSH Connection
run: |
ssh -v targetserver "echo 'Connection test'"

- name: Check SSH Setup
run: |
ls -la ~/.ssh/
ssh-keygen -l -f ~/.ssh/jump_server || echo "Key not found"

- name: Deploy with rsync
continue-on-error: true
run: |
ssh targetserver "sudo find ${{ env.REMOTE_DIR }} -not -name '.user.ini' -exec chown ${{ env.SERVER_USER }}:${{ env.SERVER_USER }} {} +"
rsync -avz --delete \
--exclude='.user.ini' \
-e "ssh -o StrictHostKeyChecking=accept-new -i ~/.ssh/jump_server" \
./dist/ \
targetserver:${{ env.REMOTE_DIR }}

- name: Notify Deployment End
if: always()
run: |
if [ ${{ job.status }} == 'success' ]; then
STATUS="success"
else
STATUS="failed"
fi

curl -X POST ${{ env.NOTIFICATION_URL }} \
-H "Content-Type: application/json" \
-d "{\"status\":\"$STATUS\", \"project\":\"${{ env.PROJECT_NAME }}\"}"

补充说明:

  • 本机生成的私钥id_ed25519拷贝到跳板机~/.ssh/目录下,因为目标服务器的公钥也是使用的本机私钥生成的,所以需要将本机私钥拷贝到跳板机。
  • 本机生成的公钥id_ed25519.pub拷贝到目标服务器的~/.ssh/authorized_keys文件中。
  • 本机生成的公钥id_ed25519.pub拷贝到跳板机的~/.ssh/authorized_keys文件中。
  • 本机生成的私钥id_ed25519拷贝到GitHub仓库的Secrets and variables中,命名为JUMP_SERVER_SSH_KEY。

7.目标服务器的访问权限问题

 需要检查目标服务器的用户是否有访问目标目录的权限,否则无法进行rsync操作。如果没有权限,则需要给目标服务器的用户设置目标目录的读写权限。
支付宝打赏 微信打赏

如果文章对你有帮助,欢迎点击上方按钮打赏作者,更多功能请访问博客站



GitHub Actions如何通过跳板机自动部署应用
https://blog.fxcxy.com/2024/11/30/github-actions如何通过跳板机部署应用/
作者
spatacus
发布于
2024年11月30日
许可协议