2
Help us understand the problem. What are the problem?

remote.it を使ってAKS(Azure Kubernetes Service)上のサービスに接続してみた!

はじめに

本記事は QiitaEngineerFesta 2022 「remote.it を使って○○に接続してみた!」 の参加記事です。

本キャンペーンで初めて remote.it というサービスを知りました。
公式サイトや既存のQiitaの記事などを見るに、インターネットからのインバウンドが開いてない環境に対しセキュアにアクセス経路を確立するためのサービスのようです。

使い道を考えたときに、普段よく触ってる Kubernetes と組み合わせて活用できないかと思いつきました。

Azure上のAKS(Azure Kubernetes Service)で起動したアプリに対し、安全な経路で接続できると便利だなー、と…。
remoteit.drawio.png

いろいろ触ってみたところなんとか実現できそうだったので、その手順を紹介します。

おことわり

Kubernetes上でのremote.itの起動を試すにあたり、Kubernetesのお作法からするとあまり推奨できない手法を取っています。
大事な環境ではこの記事の内容を真似しないようご注意ください。

環境

AKSのKubernetesバージョン 1.22.6 で試しています。
CNIの違いは今回の試した内容ではあまり関係ないと思いますが kubenet を選択しました。

remote.it アカウント作成

何はともあれ remote.it のアカウント作成が必要です。
remote.it の右上の はじめる からアカウント作成画面に入ります。
image.png

メールアドレスとパスワードを入力してアカウント作成します。
CREATE ACCOUNT ボタンを押すと入力したメールアドレス宛に確認のメールが送信されます。メール内のリンクをクリックすると登録が完了します。
image.png

登録が完了しログインすると。以下のような画面が表示されます。
image.png

サンプルアプリケーションの準備

AKS上でサンプルアプリケーションを起動しておきます。サンプルにはnginxのPodを利用しました。

sample.yaml
---
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を選択し、右側に表示されるインストールコマンドを確認します。
image.png

R3_REGISTRATION_CODE=~ の箇所の値をコピーします。上記スクリーンショットの白塗り部分です。

Registration Codeが準備できたら、PodをAKS上へデプロイしましょう。
マニフェストは以下のとおり。remoteit というNamespace配下にPodをデプロイします。
マニフェスト内の "{{ REGISTRATION_CODE }}" の箇所を上記で取得した値に置き換えてください。

remoteit.yaml
---
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/配下の設定ファイルを読み込んで起動するようです。
上記マニフェストでは、

  1. ConfigMapにinitContainerで実行するスクリプトを格納
  2. initContainerでConfigMapに格納したスクリプトを実行し、環境変数の値を利用し /etc/remoteit/ 配下に設定ファイルを生成
  3. initContainerで生成した設定ファイルを利用し、ビルドしたイメージを起動

という流れでremote.itを起動しています。
イメージビルドの項でも触れましたが、remote.itデーモンはsystemdで起動します。
Pod上でsystemdを起動するため、privileged: true を追加し特権でコンテナを実行しています。
セキュリティ上問題を生む可能性もあるので、利用には十分注意しましょう。

remote.itの設定

Podが起動して少しすると、remote.itの Devices メニューに remoteit というデバイスが追加されます。
image.png

remoteit をクリックし、次の画面でServiceの追加(+ボタン)をクリック、右のメニューに以下のように入力していきます。

  • SERVICE TYPE: HTTP
  • SERVICE NAME: sampleapp HTTP
  • SERIVCE PORT: 80
  • SERVICE HOST ADDRESS: samplesvc.sample
  • Enable Service: チェックを付ける

入力が終わったら SAVE ボタンをクリックし保存しましょう。
image.png

Kubernetesクラスター内からは、
<Service名>.<Namespace名>
という名前で他のアプリケーションにアクセスすることができます。
上記で入力した samplesvc.sample は、
sample Namespaceの samplesvc Serviceを示します。

以上で設定は完了です。次の項でremote.itを利用してサンプルアプリにアクセスしてみましょう。

remote.itでアクセス経路の開通

先ほど保存したsampleapp HTTPサービスの CONNECT + LAUNCH ボタンをクリックします。

image.png

クリック後少し待つと、remote.itから発行されたランダムな文字列のサブドメイン付きURLが表示されます。
LAUNCH をクリックしてみましょう。
image.png

AKS上のnginxにアクセスできました!
image.png

図にすると以下のようなイメージです。
remoteit.drawio (1).png

なお、この発行されたURLはパブリックに公開されますURLを知っていれば誰でもアクセスできてしまう ので注意しましょう。

Serviceの設定をHTTPではなく TCP・ポート80 として公開すれば、最初にアクセスした人のアクセス元IP以外からは受け付けない という状態になります。
ただ、アクセス先ポート番号が80番ではなくなってしまうため、アクセス元の環境によっては支障が出るかもしれません。自身の環境によって使い分けるのが良いでしょう。
image.png

おわりに

remote.it、初めて使ってみましたが便利そうなサービスです。

コンテナ上で動かすことはおそらく標準の使い方ではないと思いますが、
一般的なLinuxディストリビューションのマシンがあればスクリプトを実行するだけで導入でき、お手軽に利用開始できます。(Arch LinuxやOpenWRTのパッケージまで公開してるのは珍しい)

個人利用であれば無料のプランもあります。

これからの季節、お盆の帰省の際などに自宅の機器にアクセスするといった用途で導入するのもいいかもしれませんね。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
2
Help us understand the problem. What are the problem?