はじめに
本記事は QiitaEngineerFesta 2022 「remote.it を使って○○に接続してみた!」 の参加記事です。
本キャンペーンで初めて remote.it というサービスを知りました。
公式サイトや既存のQiitaの記事などを見るに、インターネットからのインバウンドが開いてない環境に対しセキュアにアクセス経路を確立するためのサービスのようです。
使い道を考えたときに、普段よく触ってる Kubernetes と組み合わせて活用できないかと思いつきました。
Azure上のAKS(Azure Kubernetes Service)で起動したアプリに対し、安全な経路で接続できると便利だなー、と…。
いろいろ触ってみたところなんとか実現できそうだったので、その手順を紹介します。
おことわり
Kubernetes上でのremote.itの起動を試すにあたり、Kubernetesのお作法からするとあまり推奨できない手法を取っています。
大事な環境ではこの記事の内容を真似しないようご注意ください。
環境
AKSのKubernetesバージョン 1.22.6 で試しています。
CNIの違いは今回の試した内容ではあまり関係ないと思いますが kubenet を選択しました。
remote.it アカウント作成
何はともあれ remote.it のアカウント作成が必要です。
remote.it の右上の はじめる
からアカウント作成画面に入ります。
メールアドレスとパスワードを入力してアカウント作成します。
CREATE ACCOUNT
ボタンを押すと入力したメールアドレス宛に確認のメールが送信されます。メール内のリンクをクリックすると登録が完了します。
登録が完了しログインすると。以下のような画面が表示されます。
サンプルアプリケーションの準備
AKS上でサンプルアプリケーションを起動しておきます。サンプルにはnginxのPodを利用しました。
---
apiVersion: v1
kind: Namespace
metadata:
name: sample
---
apiVersion: v1
kind: Service
metadata:
name: samplesvc
namespace: sample
spec:
selector:
app: sampleapp
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sampleapp
namespace: sample
labels:
app: sampleapp
spec:
replicas: 1
selector:
matchLabels:
app: sampleapp
template:
metadata:
labels:
app: sampleapp
spec:
containers:
- name: sampleapp
image: nginx:latest
ports:
- containerPort: 80
kubectl apply -f sample.yaml
sample
という名前のNamespaceを作成し、その配下にServiceとDeploymentを作成しています。
kubectl get pod,svc -n sample
NAME READY STATUS RESTARTS AGE
pod/sampleapp-64c4fc65fb-q4wh6 1/1 Running 0 3m3s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/samplesvc ClusterIP 10.0.19.155 <none> 80/TCP 3m3s
Serviceのタイプは ClusterIP
となっており、AKSクラスタ外に公開していない 状態です。
remote.it 用コンテナイメージのビルド
AKS上でremote.itを実行するため、コンテナイメージをビルドします。
Dockerfileは以下のとおりです。(手抜き…)
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y init sudo iproute2 curl
RUN sh -c "$(curl -L https://downloads.remote.it/remoteit/install_agent.sh)"
CMD ["/sbin/init"]
Ubuntu(Debian)用のremote.itはsystemdで起動します。
コンテナ上でsystemdを実行するため、init
パッケージをインストールし CMDで /sbin/init
を指定しています。
その他必要なパッケージと、remote.itのエージェントをインストールしています。
これをビルドし、AKSからPullできる適当なコンテナレジストリーに格納しておきます。
docker build -t <hogeregistry.example.com>/remoteit:latest .
docker push <hogeregistry.example.com>/remoteit:latest
remote.it コンテナ起動
AKS上に前項でビルドしたremote.itコンテナをデプロイします。
まずはremote.itの Registration Code を取得する必要があります。
remote.itにログインした画面の左メニュー上部の +
ボタンをクリック、Linux & Raspberry Pi
を選択し、右側に表示されるインストールコマンドを確認します。
R3_REGISTRATION_CODE=~
の箇所の値をコピーします。上記スクリーンショットの白塗り部分です。
Registration Codeが準備できたら、PodをAKS上へデプロイしましょう。
マニフェストは以下のとおり。remoteit
というNamespace配下にPodをデプロイします。
マニフェスト内の "{{ REGISTRATION_CODE }}"
の箇所を上記で取得した値に置き換えてください。
---
apiVersion: v1
kind: Namespace
metadata:
name: remoteit
---
apiVersion: v1
kind: ConfigMap
metadata:
name: entrypoint
namespace: remoteit
data:
entrypoint.sh: |-
#!/bin/bash
apt-get update && apt-get -y install curl
sh -c "$(curl -L https://downloads.remote.it/remoteit/install_agent.sh)"
---
apiVersion: v1
kind: Pod
metadata:
name: remoteit
namespace: remoteit
spec:
initContainers:
- name: init
image: ubuntu:20.04
command:
- /bin/entrypoint.sh
env:
- name: R3_REGISTRATION_CODE
value: "{{ REGISTRATION_CODE }}"
volumeMounts:
- mountPath: /bin/entrypoint.sh
name: entrypoint
readOnly: true
subPath: entrypoint.sh
- mountPath: /etc/remoteit
name: remoteit-config
containers:
- name: remoteit
image: <hogeregistry.example.com>/remoteit/remoteit:latest
imagePullPolicy: Always
volumeMounts:
- mountPath: /etc/remoteit
name: remoteit-config
securityContext:
privileged: true
volumes:
- name: entrypoint
configMap:
defaultMode: 0700
name: entrypoint
- name: remoteit-config
emptyDir: {}
kubectl apply -f remoteit.yaml
remote.itのデーモンは、/etc/remoteit/
配下の設定ファイルを読み込んで起動するようです。
上記マニフェストでは、
- ConfigMapにinitContainerで実行するスクリプトを格納
- initContainerでConfigMapに格納したスクリプトを実行し、環境変数の値を利用し /etc/remoteit/ 配下に設定ファイルを生成
- initContainerで生成した設定ファイルを利用し、ビルドしたイメージを起動
という流れでremote.itを起動しています。
イメージビルドの項でも触れましたが、remote.itデーモンはsystemdで起動します。
Pod上でsystemdを起動するため、privileged: true
を追加し特権でコンテナを実行しています。
セキュリティ上問題を生む可能性もあるので、利用には十分注意しましょう。
remote.itの設定
Podが起動して少しすると、remote.itの Devices
メニューに remoteit というデバイスが追加されます。
remoteit をクリックし、次の画面でServiceの追加(+
ボタン)をクリック、右のメニューに以下のように入力していきます。
- SERVICE TYPE: HTTP
- SERVICE NAME: sampleapp HTTP
- SERIVCE PORT: 80
- SERVICE HOST ADDRESS: samplesvc.sample
- Enable Service: チェックを付ける
入力が終わったら SAVE ボタンをクリックし保存しましょう。
Kubernetesクラスター内からは、
<Service名>.<Namespace名>
という名前で他のアプリケーションにアクセスすることができます。
上記で入力した samplesvc.sample
は、
sample
Namespaceの samplesvc
Serviceを示します。
以上で設定は完了です。次の項でremote.itを利用してサンプルアプリにアクセスしてみましょう。
remote.itでアクセス経路の開通
先ほど保存したsampleapp HTTP
サービスの CONNECT + LAUNCH ボタンをクリックします。
クリック後少し待つと、remote.itから発行されたランダムな文字列のサブドメイン付きURLが表示されます。
LAUNCH をクリックしてみましょう。
なお、この発行されたURLはパブリックに公開されます。URLを知っていれば誰でもアクセスできてしまう ので注意しましょう。
Serviceの設定をHTTPではなく TCP・ポート80
として公開すれば、最初にアクセスした人のアクセス元IP以外からは受け付けない という状態になります。
ただ、アクセス先ポート番号が80番ではなくなってしまうため、アクセス元の環境によっては支障が出るかもしれません。自身の環境によって使い分けるのが良いでしょう。
おわりに
remote.it、初めて使ってみましたが便利そうなサービスです。
コンテナ上で動かすことはおそらく標準の使い方ではないと思いますが、
一般的なLinuxディストリビューションのマシンがあればスクリプトを実行するだけで導入でき、お手軽に利用開始できます。(Arch LinuxやOpenWRTのパッケージまで公開してるのは珍しい)
個人利用であれば無料のプランもあります。
これからの季節、お盆の帰省の際などに自宅の機器にアクセスするといった用途で導入するのもいいかもしれませんね。