見出し画像

オンプレサーバにGitHubActions SelfHosted Runnerを立ててAnsibleをlocalhostに向けて構成管理する方法が便利そうでした

こんにちはvaru3です。

noteに技術系の記事が増えてほしいので、久しぶりに技術の検証記事を書きます!

TL;DR

・外からアクセスできないオンプレのサーバをGitHub Actions SelfHostedRunnerを利用してCI/CDで構成管理できるようにした

・SelfHostedRunnerのプロセスを立ち上げ、GitHub上からworkflowをkickするとlocalhostに向けてAnsibleを実行する、という仕組み

・Ansibleを実行するための発射台が不要だし、秘匿情報はSecretsに保存して環境変数で渡せるし、Webhook経由で気軽にAnsibleを実行できるので大変便利でした


前置き

・お手伝いしているプロジェクトの一つでオンプレサーバを構築することがあったのですが、2021年にコマンドぽちぽちでサーバ構築をやりたくなかったのでAnsibleで構成管理をすることにしました

・とはいえ、そのサーバは外部からは接続ができないローカルエリアネットワーク内にあったのでAnsibleを使うにもSSHできないなと困っていたところ、そういえばlocalhostに向けて実行する方法があったなと思い出しました

・GitHub Actionsのセルフホストランナーはactionsというプロセスが立ち上がって、そのプロセスがある名前空間上でworkflowが実行される(特にコンテナとかが立ち上がるわけではない)ということを思い出して、ここで上記のようにAnsible Playbookを実行できれば構成管理できるじゃん!と思いついたので早速やってみました

構成

・そんな大した構成ではないですが、図にするとこんな感じです

画像1

・今回はオンプレサーバとなっていますが、もちろんクラウド上のインスタンスでも構わないですし、自宅にあるようなRhasberry Piでもいいですし、Macbookなどでも同様のことができるかと思います

・またSelfHosted Runnerは複数台、リポジトリに紐づけることが可能です。1つのリポジトリでworkflowを分ければ複数台のサーバを構成管理することが可能となります

1.オンプレサーバにGitHub Actions Selfhosted Runner をインストールする

・この辺りは公式のドキュメントが充実しているので、そちらを参照すると良いです

・公式のドキュメントはこちら

・ここで注意しなければいけないのは、actionsが起動しているユーザーがAnsibleの実行ユーザーとなる、という点です。actionsが起動しているユーザーは sudo で rootになれるようパスワードをユーザーに設定しておく必要があります

$ passwd
New password: <sudoパスワードを設定する>

・対象のOSやアーキテクチャが幅広いので、(Ansible Playbookさえ書ければ)これらのサーバであれば実行可能となります。

画像2

・こんな感じでリポジトリの Settings -> Actions -> Runners を確認してRunnerが追加できていればOKです

2. Ansible Playbookを書く

・Ansibleのディレクトリ構成とかは様々な流派があるのでここでは割愛しますが、トップレベルのプレイブックとしてはこんな感じの設定を入れておくと良いです

- hosts: localhost
  connection: local
  become: yes
  roles:
...

・hostsをlocalhostにして become: yesとしてrootになれるように設定しておきます

3. GitHub上から実行してみる

・肝心の.github/workflows/xxx.ymlですが以下のように設定します

name: Run ansible-playbook
on:
 workflow_dispatch:
jobs:
 varu3-server:
   runs-on: [self-hosted, varu3-server]
   steps:
     - uses: actions/checkout@v2
     - name: Run playbook
       run: |
         ansible-playbook tasks/varu3-server.yml --extra-vars "ansible_become_pass=${VARU3_SERVER_SUDO_PASSWORD}"
       working-directory: ansible
       env:
         VARU3_SERVER_SUDO_PASSWORD: ${{ secrets.VARU3_SERVER_SUDO_PASSWORD }}
         COMMON_VARU3_PRIVATE_KEY: ${{ secrets.VARU3_PRIVATE_KEY }}


on.workflow_dispatch: としておくことで、任意のタイミングでこのワークフローを実行することができます。今回は特にPushやPR作成を契機としないのでこのように設定しています

runs-on: [self-hosted, <hostname>] を設定しておくことで、このタスクを実行するランナーを指定しています。ここでは構成管理したいサーバのhostname(Runnerのタグ)を指定します

・ansible-playbookに --extra-vars "ansible_become_pass=XXXX" を渡しています。これは先ほど設定した sudo パスワードですが、ここでは以下のようにGitHub Repositoryに設定できるSecretsにおいてそれを環境変数として渡すようにしています

画像3

・上記のように設定したところで workflow_dipatchでAnsibleを実行します。Actions -> workflows -> 特定のworkflow -> Run workflowから任意のブランチを選択します

画像4

・しばらくすると上記のようにAnsibleが実行されてワークフローが完了するはず

便利なところ

さて、こんな感じでさくっと使ってみたわけですがどんなところが便利かというのをいくつか挙げてみます。

Ansibleの発射台が不要

・よくあるAnsibleの実行環境の構築だとAnsibleの実行環境を用意してそこから各サーバにSSHで入って…みたいなのを作る必要がありますが、この手法だと、実行環境自体も用意する必要がありませんし、向き先が localhost なのでSSHの設定も不要です

秘匿情報をGitHub上で管理することができる

・ansibleで秘匿情報を扱う際には ansible-vaultなどで暗号化・復号するのが一般的ですが、そういった手順が若干面倒くさくもあるわけです。この手法であれば、秘匿情報はGitHubのSecretsに保存して、環境変数経由で渡せば安全に管理することができます

・ちなみにAnsibleで秘密鍵をファイルに書き出す場合はこのように書いておけば良いです

- name: Put private key from environment vars
   copy:
   dest: /home/varu3/.ssh/id_ed25519
   content: "{{ lookup('env', 'VARU3_PRIVATE_KEY') }}"

actionsとansibleさえ入れてしまえば、あとは自由に構築できる

・構成管理に必要なものはactions と ansibleです。 actionsは公式ドキュメントであるように、多くのOS,プラットフォームに対応していますし、ansibleもpythonが動く環境であれば動作します。気軽に yum や apt でもインストールすることができます

Webhook経由で実行できる

・GitHub Actionsの機能で、リポジトリのAPIトークンさえあればWebhook経由でworkflowを実行することができます。他のworkflowと組み合わせたり、AWS lambdaなどに仕込んでおけば別のイベントを契機にworkflowを実行できます。拡張性が高く使うことができるのではないでしょうか

終わりに

・何気なく思いついてやってみた手法ではありますが、上記のようなメリットがあり良い解決策になったのではないかと思っています。オンプレのサーバを構築する機会も多くはなくなってきましたが、自宅のRhasberry Piで使えそうだったりと利便性は高そうでした。

・コンテナが主流の昨今で、Ansibleも若干枯れた技術になりつつありますがAnsibleの辛い部分をActions側でうまい具合に補完してくれるような構成になったのではないかと思います

・GitHub Actionsはまだまだ便利な使い方がありそうなので模索してみたいですね。

以上!

この記事が気に入ったらサポートをしてみませんか?