kWatanabe 記事一覧へ

kWatanabe の 技術帖

某企業でOSや仮想化の研究をやっているインフラ系エンジニア。オンプレとクラウドのコラボレーションなど、興味ある技術を綴る。

ローカルのGitBucketをGitHubに移行する(その2)

  • ローカルサーバのGitBucketで管理していたリポジトリGitHubに移行したい
  • その1では、リポジトリ本体とユーザ情報、タグなどの移行を行った
  • 今回は、データベースで管理されている Issue を GitBacket からダンプする

その1はこちら。

kwatanabe.hatenablog.jp

その3はこちら。

kwatanabe.hatenablog.jp

背景

過去記事参照。

GitBucket から Issue を取り出す

アプリケーショントークンの取得

GitBucket は GitHub REST API v3 のサブセット*1を実装しているので、直接 H2 や PostgreSQL の中身を覗かなくてもある程度はなんとかなる。

REST API なので python なり perl なりでスクリプトでサクッとおわらせたい。そのためにまずはアプリケーショントークンを取得する。

  1. GitBucket にログイン
  2. Account settings を選択
  3. Applications を選択
  4. Generate new token の Token description にテキトーな説明を入れる
  5. Generate token を選択

するとトークンが表示されるのでメモっておく。

f:id:kWatanabe:20201011014344p:plain
アプリケーショントークンの取得

Issue と Pull Request の取得

アプリケーショントークンを使って、http://GITBACKET_SERVER_URL/api/v3/repos/USERNAME/REPONAME/issues に対して、APIをコールしてやれば以下のような JSON で降ってくる。

{
    'number': 2,
    'title': 'Issueのタイトル',
    'user': {
        'login': 'USERNAME',
        'email': 'USERNAME@example.com',
        'type': 'User',
        'site_admin': True,
        'created_at': '2018-08-08T12: 51: 17Z',
        'id': 0,
        'url': 'http://GITBACKET_SERVER_URL/api/v3/users/USERNAME',
        'html_url': 'http://GITBACKET_SERVER_URL/USERNAME',
        'avatar_url': 'http://GITBACKET_SERVER_URL/USERNAME/_avatar'
    }, 
    'assignee': {
        userと同じ key の集まり (valueは異なる)
    },
    'labels': [
        {
            'name': 'enhancement',
            'color': '84b6eb',
            'url': 'http://GITBACKET_SERVER_URL/api/v3/repos/USERNAME/REPONAME/labels/enhancement'
        }
    ],
    'state': 'closed',
    'created_at': '2018-08-13T14:33:25Z',
    'updated_at': '2020-10-10T06:34:36Z',
    'body': 'Issueのメッセージ本文',
    'id': 0,
    'assignees': [
        {
            user や assignee 同じ key の集まり (valueは異なる)
        }
    ],
    'comments_url': 'http://GITBACKET_SERVER_URL/api/v3/repos/USERNAME/REPONAME/issues/2/comments',
    'html_url': 'http://GITBACKET_SERVER_URL/USERNAME/REPONAME/issues/2'
}

さらに、Issue 内のコメントは、降ってきた comments_url に対してAPIをコールしてやれば、これまた JSON で手に入る。

[
    {
        "id": 3,
        "user": {
            "login": "USERNAME",
            "email": "USERNAME@excample.com",
            "type": "User",
            "site_admin": true,
            "created_at": "2018-08-08T12:51:17Z",
            "id": 0,
            "url": "http://GITBACKET_SERVER_URL/api/v3/users/USERNAME",
            "html_url": "http://GITBACKET_SERVER_URL/USERNAME",
            "avatar_url": "http://GITBACKET_SERVER_URL/USERNAME/_avatar"
        },
        "body":"Issueのコメント本文"
    }
]

Pull Request と Issue はAPIのエントリポイントが異なるだけで、全く同じ手順でダンプできる。なので、Issue と Pull Request はメソッドを共通化できる。やっつけだが、概ね以下の通り。

【2020/10/20修正】ちょっとやっつけすぎたので、少しリファクタリング

import os
import requests

GITBUCKET_API_BASEURL='http://gitbucket.example.com/api/v3/repos/USERNAME/REPONAME'
GITBUCKET_APP_TOKEN='XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'

# GitBucket から issue を取得する
def get_issues (base_url, token):
    headers = {'Authorization': 'token ' + token}
    issues = []

    # issue
    for issue_type in ('issues', 'pulls'):
        url = '%s/%s' % (base_url, issue_type)
        for state in ('open', 'closed'):
            for page in range(1, 10000):
                payload = {'state': state, 'page':page}
                response = requests.get(url, headers=headers, params=payload)
                new_issues = response.json()
                if not len(new_issues):
                    break
                issues.extend(new_issues)
    issues.sort(key=lambda x: x['number'])

    # issue comment
    for issue in issues:
        response = requests.get(issue['comments_url'], headers=headers)
        issue['comments'] = response.json()

    return issues

if __name__ == '__main__':
    issues = get_issues(GITBUCKET_API_BASEURL, GITBUCKET_APP_TOKEN)
    print(issues)

ハマりポイントとしては2点。

  • GitBucket の issues APIGitHub では使える state=all が使えないので、state=openとstate=closedを使って結果を結合しないとダメ。
  • またper_page=N も使えず、25個ずつしか取ってこれないので、page=N を順繰りに増やし、空配列しか降ってこなくなるまで取得し続けないとダメ。

これで、issue と Pull Request を一通りぶっこ抜けるようになったので、今度はこれを同じく GitHub API を使って GitHub に突っ込んでいく。

次回予告

  • GitBucket からぶっこ抜いた Issue と Issue comment を GitHub に入れていきます。

*1:サブセットなので、いろいろと実装が足りなくてハマりポイント多数。ちゃんとしたドキュメントが欲しい

ローカルのGitBucketをGitHubに移行する(その1)

  • ローカルサーバのGitBucketで管理していたリポジトリGitHubに移行したい
  • リポジトリ本体は clone して push すれば事が済むが、ユーザ名やメールアドレスが同じとは限らない
  • また、データベースで管理されている Issue などはそう簡単にはいかない
  • あんまり頑張りすぎずに、できる範囲で移行した際の作業記録(その1)

その2とその3はこちら。

kwatanabe.hatenablog.jp

kwatanabe.hatenablog.jp

背景

とある事情にて、ローカルのGitBucketをGitHubのプライベートリポジトリに移行することになった

GitHubリポジトリの移行機能を持っていたり、極端な話 clone して push したら済むので、そう難しくない。でも、PostgreSQL に入っている Issue とか、 pull request とかはどうすりゃいいか分からん。

移行ツールとか無いか、いろいろ漁ってみたもののコレといったものが出てこない。なんとかならんものか。

最低限守りたいモノ

とりあえず、あんまり頑張りたくないので、最低限守りたいものを整理する。

プルリクは、たまたまオープンのものが無かったので、特に意識はしていない。

【2020/10/11訂正】 Issue だけだと、Issue 番号がずれてしまうので、プルリクも入れてやらないとダメだった。

リポジトリ

フルミラーの取得

リポジトリの完全なミラーを取得する。

まずは単純に clone して。

$ git clone <リポジトリのURL>

ブランチを確認して。

$ cd <cloneしたディレクトリ>
$ git branch -r | grep -v "\->" | grep -v master
  origin/issue103

見つけたブランチも引っ張ってくる。

$ git branch --track issue103 origin/issue103
$ git branch
  issue103
* master

多分大丈夫だと思うけど、fetch と pull もしておく。

$ git fetch --all
$ git pull --all

おっけー。

ユーザ情報を GitHub のものに移行

ユーザ情報(AuthorとCommitter)が、ローカルとGitHubアカウントで齟齬があるので、コレを修正する。

齟齬とはいったものの、実態としてローカルのリポジトリでは、好き勝手にでっち上げたユーザ名とメールアドレスを使ってコミットしていたのでもうグチャグチャ。まずは、こいつを GitHub のそれに合わせて整える。

現状を確認する。

$ git log --pretty=full
…(略)…
Author:  XXXX <XXXX@XXXX.com>
Commit: XXXX <XXXX@XXXX.com>
…(略)…

もし、GitHubのユーザ名が kwatanabe、 メールアドレスが kwatanabe@example.com だとすると、こうする。

$ git filter-branch -f --env-filter "GIT_AUTHOR_NAME='kwatanabe'; GIT_AUTHOR_EMAIL='kwatanabe@example.com'; GIT_COMMITTER_NAME='kwatanabe'; GIT_COMMITTER_EMAIL='kwatanabe@example.com';" HEAD 
Ref 'refs/heads/master' was rewritten

もし、ブランチがあるならそれぞれで同じ事をやっておく。

$ git checkout BRANCH
Switched to branch 'BRANCH'
Your branch is up to date with 'origin/BRANCH'.

$ git filter-branch -f … (省略)

修正されたことを確認。

$ git log --pretty=full
…(略)…
Author:  kwatanabe <kwatanabe@example.com>
Commit: kwatanabe <kwatanabe@example.com>
…(略)…

試しに push してみる

とりあえずこれでリポジトリは整った。試しにGitHubにプッシュしてみる。

GitHubでプラベートリポジトリを作る。このとき、「Add a README file」と「Add .gitignore」のチェックを外しておく。

f:id:kWatanabe:20201010180849p:plain
プライベートリポジトリの作成

リポジトリのPUSH先URLを変更する。

$ git remote set-url origin https://github.com/<ユーザ名>/<リポジトリ>

あと、GitHubのデフォルトブランチ名は master ではなく main に変わった*1ので、メインブランチ名を変更する。

$ git branch -M main
$ git branch
  issue103
* main

PUSHする。

$ git push --all origin
$ git push --tags

GitHubのコンソールに入って、リポジトリのブランチとタグがきちんと反映されてることを確認しておく。

f:id:kWatanabe:20201010184333p:plain
ブランチ

あと、きちんとコミットとユーザが紐付き、いわゆる"草原"に反映されていることを確認する。

f:id:kWatanabe:20201010183038p:plain
いわゆる”草原”を確認する

次回予告

単なるリポジトリの移行だけであれば、コレで完了。

Issue やら Release やらをコピーしたい場合は、GitBucket から どうにかしてぶっこ抜く必要がある。

これは以下の記事参照です。

kwatanabe.hatenablog.jp

*1:完全なる独り言なんですが、blacklistとwhitelistとか、masterとslaveとか、言いたいことは分かるのですが、専門用語ってお互いに誤解を生まないように作られているものなので、そう簡単に変えちゃイカンと思うのです…。

LXCの非特権コンテナにホストのGPUをパススルーする

  • 2020/11/08 一部のtypoを修正

大要

  • Proxmox VEのLXCの非特権コンテナにGPUをパススルーし、CUDAを使う
  • KVMVGAパススルーと違って、ホストに搭載するGPUは1つでよい
  • GPUは(性能を考慮しないなら)そのままホストでも利用できる
  • (たぶん、)生のLXCでも同等の手順で実現できる

背景

  • 我が家では Ryzen マシンに Proxmox VE を入れて、IaaS モドキを運用している(以前は CloudStack + XenServer だったが、XenServer 無料版 の制限強化の際にやめた)
  • RyzenGPUを持たないので、コンソール用に GeForce GTX 1050Ti を挿しているが、非常時以外は使わないので勿体ない
  • LXCの非特権コンテナ上で 1050Ti を使って CUDA ができれば、追加費用なしで手軽にGPUインスタンスが手に入るのではと思った

ターゲット環境

手順

大まかな手順は以下の通り。

  1. ホストでGPUのドライバをビルド
  2. ホストでGPUのデバイスファイルを有効化
  3. ゲストにGPUのデバイスファイルをリマップ
  4. ゲストでGPUのドライバをビルド
  5. ゲストでCUDAのライブラリをインストール(割愛)

ホストでGPUドライバをビルド

サブスクリプションを持たない人向けの Proxmox リポジトリを有効にする。もちろん、サブスクリプションをお持ちの場合は不要。

# vim /etc/apt/sources.list
deb http://download.proxmox.com/debian/pve buster pve-no-subscription

Proxmox VE のリポジトリには nvidia-driver がないので、Proxmox VE 6.x のベースである Debian 10 のリポジトリを有効にする。なお、stable リポジトリnvidia-driver は古いので、backports リポジトリを用いる。

# vim /etc/apt/sources.list
deb http://deb.debian.org/debian buster-backports main contrib non-free
deb-src http://deb.debian.org/debian buster-backports main contrib non-free

nvidia-driver を導入する。nvidia-driver はバイナリで提供されていないので、DKMS*1 でその場でビルドされる。そのため、カーネルヘッダやビルドツールも一式必要になる。

# apt update
# apt upgrade
# apt install pve-headers build-essentials
# apt install -t buster-backports nvidia-driver nvidia-smi

ホストでGPUバイスファイルを有効化

DKMSでビルドされたドライバモジュールを有効にする。

# vim /etc/modules-load.d/nvidia-gpu.conf
nvidia-drm
nvidia
nvidia_uvm

udevルールを作成して、ドライバがロードされた時に非特権コンテナからでもデバイスファイルを扱えるように、アクセス権が変更されるようにする。(特権コンテナの場合は不要)

余談だが、非特権コンテナから扱えるようにアクセス権を緩めると、ホストの一般ユーザ(Proxmox VEに一般ユーザはないが)からでもデバイスファイルが叩けるようになってしまう。でも、コンテナを特権コンテナにするよりはまだマシか…?

# vim /etc/udev/rules.d/70-nvidia-gpu.rules
KERNEL=="nvidia", RUN+="/bin/bash -c '/usr/bin/nvidia-smi -L && /bin/chmod 666 /dev/nvidia*'"
KERNEL=="nvidia_uvm", RUN+="/bin/bash -c '/usr/bin/nvidia-modprobe -c0 -u && /bin/chmod 0666 /dev/nvidia-uvm*'"

ホストを一度再起動する。

# reboot

起動したら、GPUが正しくホストで認識されているか確認する。

# nvidia-smi
Sun Oct  4 15:42:59 2020       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 440.100      Driver Version: 440.100      CUDA Version: N/A      |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 105...  On   | 00000000:0A:00.0 Off |                  N/A |
| 29%   29C    P8    N/A /  75W |      1MiB /  4040MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

ゲストにGPUバイスファイルをリマップ

コンテナの設定ファイルを開いて、GPUのデバイスファイルをリマップする。

例えば、対象のコンテナの vmid が 101 だった場合は、以下の通り。

# vim /etc/pve/lxc/101.conf 
lxc.cgroup.devices.allow: c 195:* rwm
lxc.cgroup.devices.allow: c 236:* rwm
lxc.cgroup.devices.allow: c 226:* rwm

lxc.mount.entry: /dev/nvidia0 dev/nvidia0 none bind,optional,create=file
lxc.mount.entry: /dev/nvidiactl dev/nvidiactl none bind,optional,create=file
lxc.mount.entry: /dev/nvidia-uvm dev/nvidia-uvm none bind,optional,create=file
lxc.mount.entry: /dev/nvidia-modeset dev/nvidia-modeset none bind,optional,create=file
lxc.mount.entry: /dev/nvidia-uvm-tools dev/nvidia-uvm-tools none bind,optional,create=file
lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir

コンテナを起動して、コンテナの中からもデバイスファイルが見えている事を確認する。

$ ls /dev/nvidia* /dev/dri/*
/dev/nvidia0
/dev/nvidiactl
/dev/nvidia-modeset
/dev/nvidia-uvm
/dev/nvidia-uvm-tools
/dev/dri/card0
…(省略)…

ゲストでGPUドライバをビルド

ホストと同様にコンテナでGPUのドライバをビルドする。今回は Proxmox VE のベースである Debian 10 のコンテナなので、カーネルヘッダが異なる以外は同じ。

まずは、backports リポジトリを有効にして…。

$ sudo vim /etc/apt/sources.list
deb http://deb.debian.org/debian buster-backports main contrib non-free
deb-src http://deb.debian.org/debian buster-backports main contrib non-free

次に、DKMS でドライバをビルドする。

$ sudo apt update
$ sudo apt upgrade
$ sudo apt install build-essential
$ sudo apt install -t buster-backports nvidia-driver nvidia-smi

コンテナの内部からGPUにアクセスできるか確認する。

$ nvidia-smi
…(省略)…

あとは、実機でCUDAを使うときと同様に、コンテナにCUDAドライバをインストールする。ここでは割愛する。

備考

  • ホストとゲストのドライバは同じバージョンが望ましい。
  • Debian 10 以外のコンテナにパススルーする場合は、ディストリビューションのドライバのバージョンを確認して、少しでも違ったら公式ドライバでバージョン合わせをするのが無難
  • Proxmox VE 固有の手順は殆どないので、多分、生のLXCでも同じ手順で使えると思う

まとめ

  • Proxmox VE 6.2 上に構築した、LXCの非特権コンテナに GeForce GTX 1050Ti をパススルーして、お手軽GPUインスタンスを作った
  • ホストでも引き続きGPUを使えるので、RyzenLinuxなをお持ちの方は、とりあえずGPUを握ったコンテナを用意しておくと何かと捗るかもしれない

*1:Dynamic Kernel Module Support。ライセンスがポリシに合わなかったり、そもそもフリーじゃなかったりの理由で、Linuxカーネルのソースツリーの外にソースが存在するカーネルモジュールを、利用者の責任の下でその場でビルドさせる仕組み。

AWS・Azure・自宅にてマルチでハイブリッドなクラウドを作ってみた(その2)

大要

  • 自学自習のため、マルチでハイブリッドなクラウドを作ってみた
  • ゴールは、各リソースをパブリックな通信なしで利用できるようにすること
  • 前回はL3レベルでのサイト間VPNで、IaaS層のハイブリッド化行った
  • 今回は AWS と Azure の PaaS を各拠点のネットワークで相互に繋いで PaaS層のハイブリッド化を行う

前回はこちら kwatanabe.hatenablog.jp

背景

  • 前回記事参照

PaaSのハイブリッド化

  • 前回の作業でAmazon VPC、Azure VNet、自宅のLANが相互に接続されている
  • PaaSをこれらVPCやVNetに所属させることができれば、PaaSのハイブリッド化も実現できる
  • Azure PaaS と AWS PaaS では設計思想の違いから必要なアプローチが異なる

AWS PaaS

  • AWS PaaS は VPC に対してプラガブルな設計となっているので、多くのメニューでそのまま VPC のサブネットに繋げることができる
  • 例えば、Amazon RDS だと作成時にVPCとサブネットグループを指定できる
  • RDSのマルチAZ対応するには適切なルーティング設定が VPC に必要

f:id:kWatanabe:20200926121949p:plain
Amazon RDS での 接続先VPC の設定

Azure PaaS

  • VNet は IaaS のための仕組みであり、PaaS の接続は考慮されていない
  • Azure PaaS は各リソースがパブリックな世界で孤立している
  • VNet に繋ぐには、そのための機能が PaaS に備わっている必要がある
  • 例えば、Azure App Service では以下の機能が提供されている
    • VNet Integration
      • Gateway-required VNet Integration
      • Region VNet Integration
    • Hybrid Connections
    • プライベートエンドポイント (Preview)

docs.microsoft.com docs.microsoft.com docs.microsoft.com

具体例

f:id:kWatanabe:20200926124232g:plain
デモ環境のイメージ

  • Azure App Service と Amazon RDS を繋いで簡単なWebシステムを作る
  • RDS のパブリックアクセシビリティを無効にして、マルチクラウドが実現できている事を確認する
  • App Serivce を VNet に接続する手段は Region VNet Integration を用いる

Amazon RDS

インスタンスを作成する。作成に特別な手順は必要ない。以下のパラメータ以外は好きに選んでかまわない。

  • エンジン:MySQL (MySQL Community 8.0.20)
  • マルチAZ配置:なし
  • 接続VPC:Hybrid-VPC (前回記事参照)
  • サブネットグループ:新規
  • パブリックアクセス:なし
  • VPCセキュリティグループ:3306/TCPを許可
  • アベイラビリティゾーン:Hybird-Subnetと同じところ
  • データベースポート:3306
  • 認証:パスワード認証
  • 最初のデータベース名:wordpress

インスタンスがデプロイされたら、コンソールからエンドポイント名を確認したうえで、同じサブネットに属するEC2からプライベートIPアドレスを調べておく。

f:id:kWatanabe:20200926125304p:plain
RDSのエンドポイントの確認

$ nslookup XXXXXXXXXXXXXXXXXXXXX.ap-northeast-1.rds.amazonaws.com
Server:         192.168.20.2
Address:        192.168.20.2#53

Non-authoritative answer:
Name:   XXXXXXXXXXXXXXXXXXXXX.ap-northeast-1.rds.amazonaws.com
Address: 192.168.20.225

以上でRDSの構築は完了。

Azure App Service

インスタンスを作成する。まずは通常の手順でデプロイする。

ネットワーク⇒VNet統合から、以下の設定を行う。

  • 仮想ネットワーク:前回作成した Azure VNet
  • サブネット:Hybrid_Subnet_Dammy

構成⇒アプリケーションの設定から、以下の設定を行う。

  • パラメータ:WEBSITE_VNET_ROUTE_ALL
  • 値:1

プロイセンター⇒FTPから接続情報を取得して、FTPクライアントで任意のディレクトリに Wordpressアーカイブを展開する。

  • なお、5.5系はPHP7.4以降を推奨としているため、5.4系を用いる

一旦、App Serivceを「停止」⇒「起動」でコールドブートした後に、WordPress をデプロイした URL にブラウザで繋ぎ、初期設定を行う。

  • データーベースのホスト名は、RDS をデプロイしたときに調べたプライベートIPアドレスを指定する。

f:id:kWatanabe:20200926130633p:plain
Wordpressの初期設定

以上でApp Serivceの構築は完了。

まとめ

f:id:kWatanabe:20200926131504p:plain
最終構成

  • 本記事の手順を実施した時点で上記の環境が完成する。
  • App Serivce にアクセスすればWordpressが稼働しており、その後にRDSを停止させれば「データベース接続エラー」となるはず。
    • Region VNet Integration は IaaS ⇒ PaaS 方向の通信をフォワードしない
    • App Service の前段に自宅やAWSで動くリバースプロキシを挟みたい場合などは他の方法が必要になる
  • Azure PaaS のハイブリッド化はなかなかの鬼門のようだ

AWS・Azure・自宅にてマルチでハイブリッドなクラウドを作ってみた(その1)

大要

  • 自学自習のため、マルチでハイブリッドなクラウドを作ってみた
  • AWS、Azure、自宅の各拠点をプライベートなネットワークで結ぶ
  • ゴールは、各リソースをパブリックな通信なしで利用できるようにすること
  • まずは、Softether VPNでサイト間VPNを構築した

次回は PaaS を VPN に繋げる話。 kwatanabe.hatenablog.jp

背景

  • 浦島太郎なkWatanabeにとって、クラウドといえばOpenNebula、OpenStack、CloudStackであって、パブリックなクラウドは馴染みがない
  • コレはイカんと思い、会社の勉強会*1にかこつけて、何かパブリッククラウドで遊んでみようと思った
  • システムを知るにはまずは足回りからがモットーなので、まずは生の計算機とネットワークが見えそうな、マルチでハイブリッドなクラウドに挑戦した

マルチでハイブリッドなクラウド

f:id:kWatanabe:20200925222427g:plain
マルチでハイブリッドなクラウド

サイト間VPN

f:id:kWatanabe:20200925234646g:plain
サイト間VPNのイメージ

  • まず、各拠点をプライベートなネットワークで結ぶためにサイト間VPNを作る
  • 各事業者でVPNのPaaSを提供
  • 今回は1つの仕組みで完結させる為、Softether VPNを採用
  • 注意点としては、AWSもAzureも仮想ネットワークはL3レベルでフィルタされているので、L2ではなくL3でサイト間VPNをはる必要がある

ネットワークの整備

自宅

  • 192.168.1.0/24 が整備されている
  • VPNサーバ以外の各端末のルーティングテーブルを設定する
    • 192.168.20.0/24 via 192.168.1.249 (VPNサーバの仮想L3スイッチの内向きアドレス)
    • 192.168.21.0/24 via 192.168.1.249 (同上)
    • 192.168.30.0/24 via 192.168.1.249 (同上)
    • 192.168.31.0/24 via 192.168.1.249 (同上)
    • 192.168.10.0/24 via 192.168.1.249 (同上)

Amazon VPC

  • CIDRの範囲:192.168.20.0/24 と 192.168.21.0/24
  • サブネット「Hybrid-Subnet」
    • CIDR:192.168.20.0/24
    • ルートテーブル
      • 192.168.1.0/24 via 192.168.20.1 (VPNブリッジのEC2インスタンス)
      • 192.168.30.0/24 via 192.168.20.1 (同上)
      • 192.168.31.0/24 via 192.168.20.1 (同上)
    • アベイラビリティゾーン:Hybrid-Subnet-Dammy と異なるところ
  • サブネット「Hybrid-Subnet-Dammy」
    • CIDR:192.168.21.0/24
    • アベイラビリティゾーン:Hybrid-Subnetと異なるところ
    • ルートテーブルなし

Azure VNet

  • IPv4 アドレス空間:192.168.30.0/24 と 192.168.31.0/24
    • サブネット「Hybrid_Subnet」
      • CIDR:192.168.30.0/24
      • ルートテーブル
        • 192.168.1.0/24 via 192.168.30.100 (VPNブリッジのVirtualMachine)
        • 192.168.20.0/24 via 192.168.30.100 (同上)
        • 192.168.21.0/24 via 192.168.30.100 (同上)
    • サブネット「Hybrid_Subnet_Dammy」
      • CIDR:192.168.31.0/24
      • ルートテーブルはHybrid_Subnetと同じ
    • BastionHost:無効化
    • DDoS Protection Standard:無効化
    • ファイアウォール:無効化

Softether VPN のインストール

自宅(VPNサーバ)

  • 環境は、LXCで構築した Debian 10 のシステムコンテナ
  • ネットワークインタフェースは2つ
    • eth0:VPN通信を受け付けるNIC
      • veth (仮想NICをホストのNICにブリッジ接続)
      • ルータから 5555/TCP ポートがフォーワードされる
      • IPアドレスは 192.168.1.0/24 のどこか(なんでもいい)
    • eth1:パケットをローカルに流すためのNIC
      • phys (物理NICをパススルー)
      • プロミスキャスモードにする
      • IPアドレスは未割り当て

SoftEther の サイトから Linux 64bit 用のバイナリを入手してリンクする

$ sudo apt install wget gcc make
$ cd /opt
$ wget https://jp.softether-download.com/files/softether/v4.34-9745-rtm-2020.04.05-tree/Linux/SoftEther_VPN_Server/64bit_-_Intel_x64_or_AMD64/softether-vpnserver-v4.34-9745-rtm-2020.04.05-linux-x64-64bit.tar.gz -O - | sudo tar xzf -
$ cd /opt/vpnserver
$ sudo make

systemdのユニットファイルを作成して、自動起動を有効化する

$ cat << EOF | sudo tee /etc/systemd/system/softether-vpnserver.service
[Unit]
Description=Softether VPN Server Service
After=network.target

[Service]
Type=forking
User=root
ExecStart=/opt/vpnserver/vpnserver start
ExecStop=/opt/vpnserver/vpnserver stop
Restart=on-abort
WorkingDirectory=/opt/vpnserver

[Install]
WantedBy=multi-user.target
EOF
$ sudo chmod +x /etc/systemd/system/softether-vpnserver.service
$ sudo systemctl daemon-reload
$ sudo systemctl start softether-vpnserver
$ sudo systemctl enable softether-vpnserver

適当な端末から eth0 に向かって、SoftEther VPN Managerで接続して、以下の設定を施す。

  • 仮想HUB「DEFAULT」の設定
    • ユーザ名:テキトー
    • 認証方法:パスワード認証
    • SecureNATは無効
    • ローカルブリッジ:eth1
  • 仮想HUB「HYBRID」の設定
    • ユーザ名:テキトー
    • 認証方法:パスワード認証
    • SecureNATは無効
  • 待受ポート:5555/TCP (SE-VPN) のみ
  • 仮想L3スイッチの設定
    • インターフェース
      • 192.168.1.249 ⇒ 接続先HUB「DEFAULT」に接続
      • 192.168.10.1 ⇒ 接続先HUB「HYBRID」に接続
    • ルーティングテーブル
      • 192.168.20.0 ⇒ 192.168.10.2 (AWS用)
      • 192.168.30.0 ⇒ 192.168.10.3 (Azure用その1)
      • 192.168.31.0 ⇒ 192.168.10.3 (Azure用その2)

以上で設定完了。

AWS および Azure(VPNブリッジ)

  • Amazon EC2 と Azure VirtualMachine で Debian10 のインスタンスを作成
    • NICはそれぞれ自身の VPC なり VNet なりに属するインタフェース1個
    • パブリックIPあり
    • プライベートIPは手動指定
      • AWS:192.168.20.100/24
      • Azure:192.168.30.100/24
    • モニタモードに相当する機能を有効化
      • AWS:送信元/送信先チェックを無効にする
      • Azure:Enable IP forwardingを有効にする
    • セキュリティグループ
      • 自分のサブネット内のパケットすべて許可
      • 5555/TCP (SE-VPN) を許可

SoftEther の サイトから Linux 64bit 用のバイナリを入手してリンクする。

$ sudo apt install wget gcc make
$ cd /opt
$ wget https://jp.softether-download.com/files/softether/v4.34-9745-rtm-2020.04.05-tree/Linux/SoftEther_VPN_Bridge/64bit_-_Intel_x64_or_AMD64/softether-vpnbridge-v4.34-9745-rtm-2020.04.05-linux-x64-64bit.tar.gz -O - | sudo tar xzf -
$ cd /opt/vpnbridge
$ sudo make

ユニットファイルを作成して、自動起動を有効化する

$ cat << EOF | sudo tee /etc/systemd/system/softether-vpnbridge.service
[Unit]
Description=Softether VPN Bridge Service
After=network.target

[Service]
Type=forking
User=root
ExecStart=/opt/vpnbridge/vpnbridge start
ExecStop=/opt/vpnbridge/vpnbridge stop
Restart=on-abort
WorkingDirectory=/opt/vpnbridge

[Install]
WantedBy=multi-user.target
EOF
$ sudo systemctl daemon-reload
$ sudo systemctl start softether-vpnbridge
$ sudo systemctl enable softether-vpnbridge

VPNブリッジは自力でアドレス変換しないとダメなのでポートフォワードを有効化

$ sudo vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
$ sudo sysctl -p

適当な端末から、SoftEther VPN Managerで接続して、以下の設定を施す。

  • 仮想HUB「BRIDGE」
    • ポート:5555/TCP
    • ローカルブリッジ:新しいtapデバイス ( vpntap )
    • カスケード接続:仮想HUB「HYBRID」
      • ブリッジ名:HYBRID
      • 接続先:自宅のVPNサーバ
      • 状態:オフライン
    • ユーザ名とパスワード:仮想HUB「HYBRID」に設定したもの

SoftEther VPN の設定後に、tapデバイスに ip addr でIPアドレスを設定

  • AWS:192.168.10.2
  • Azure:192.168.10.3

SoftEther VPNの設定後に、ip route でローカルのルーティングテーブルを編集

  • AWS
    • 192.168.1.0/24 via 192.168.10.1 dev tap_vpntap
    • 192.168.30.0/24 via 192.168.10.1 dev tap_vpntap
    • 192.168.31.0/24 via 192.168.10.1 dev tap_vpntap
  • Azure
    • 192.168.1.0/24 via 192.168.10.1 dev tap_vpntap
    • 192.168.20.0/24 via 192.168.10.1 dev tap_vpntap

改めて、SoftEther VPN Managerで接続して、以下の設定を施す。

  • 仮想HUB「BRIDGE」
    • カスケード接続:仮想HUB「HYBRID」
      • 状態:オンライン

以上で設定は完了。

まとめ

f:id:kWatanabe:20200926004223g:plain
本記事の手順完了時点の状況

  • 本記事の手順を実施した時点で上記の環境が構築できている
  • IaaS レベルのハイブリッドクラウドであれば、これで構築完了
  • 各拠点間の端末から ping を送りあうと疎通ができるはず
  • 次回は各拠点に PaaS をデプロイして、疎通できるようにする

次回に続く kwatanabe.hatenablog.jp

*1:会社の勉強会だけど、作業は資料作成のふくめて4連休のオフの時間にしたし、機材も自費でクラウドを契約したので会社のカネは1円も使ってない。趣味でやったことを会社の勉強会で喋っただけ。

クラウド課金で死なないための予算管理

大要

  • パブリッククラウドは使った分だけ課金される
  • リソース解放漏れにより、思わぬ請求が来ることを防止したい
  • 予算に基づいたアラートを設定した
  • 思わぬ課金に気づけるようになった

パブリッククラウドは使えば使うだけ課金される

浦島太郎なkWatanabeは、計算機リソースに対する課金といえばリース代や電気代、あるいはVPSなどの固定額モデルしか馴染みがない。

これらは無茶な使い方をしても、性能が出ない・機能が足らないなど、クールダウンできるタイミングがあったけど、パブリッククラウドではそうはいかない。 リソースは足りなければ足されるし、請求額も膨れていく。

自制できずに課金されるなら自業自得だが、解放漏れによる課金はいただけない。

予算を管理する

リソースを監視する仕組みを入れてもいいけども、個別に対応して漏れると本末転倒なので、まずは水際対策として課金状況に応じたアラートを設定する。

Microsoft Azure の場合

docs.microsoft.com

Azure Portalの「サブスクリプション」>「予算」から、予算額とアラートを出す閾値を設定できる。

スコープはサブスクリプションでもいいし、リソースグループでもいい。 解放漏れなどイレギュラーな課金への対策はサブスクリプションに設定して、実際の予算はリソースグループにしておくと、管理が楽かもしれない。

f:id:kWatanabe:20200913160433p:plain
Azureでの予算設定の例

使ったつもりもないのに課金されている場合に備えて1000円。自己牽制として4000円。 額は、とりあえず適当に入れた。これで閾値をまたいだ際に、約1時間以内にアラートが届くようになるらしい。

AWSの場合

docs.aws.amazon.com

AWS Management Consoleの「マイアカウント」>「Budgets」から、予算額とアラートを出す閾値を設定できる。

AWSの場合、課金単位は全てUSDなので、予算もUSDで指定する。 これは、請求額をJPYにしても同じ。

アラートを出す閾値は「実際に掛かった額」または「予測額」で設定できるので、組み合わせて使えばリソースの解放漏れを事前に察知できるかもしれない。

f:id:kWatanabe:20200920135255j:plain
AWSでの予算設定の例

こちらも、同様に使ったつもりが無い場合と自己牽制のために2つのアラートを設定。額はとりあえず適当に入れた。

まとめ

  • 従量課金生活に慣れていないので、AzureとAWSに予算の設定を行った。
  • 使ったつもりが無いのに課金されている場合に備えた少額のアラートと、自己牽制のためのそれなりの額のアラートを設定した。
  • ガラケー時代に味わったパケ死の再来とならないよう注意したい。

はじめまして kWatanabeです

意気込み

はじめまして。kWatanaeです。

2010年頃には、iTRONやRT-LinuxXenKVM などを活用したリアルタイムシステムの研究。

2015年頃には、OpenStack、CloudStack などのプライベートクラウド や Pacemaker、ZooKeeper、ZeroMQ などを活用したHAクラスタの開発をやってました。

その後、炎上プロジェクトにドナドナされ、2020年頃に戻ってきたのはいいものの、世の中はパブリッククラウド一色。それもPaaS/SaaS/FaaSの全盛期。

浦島太郎からイマドキのエンジニアなるため、頑張ります。

これから

パグリッククラウド一色の世の中とはいえ、誰かはオンプレやネットワークもちゃんと見ないといけません。オンプレとクラウドのコラボレーションをテーマとして、Low-Level も High-Level も何でもキャッチアップしていきます。

今後ともよしなに。