はじめてのHashiCorp Consul (第2回 Connect機能)

Consulのチュートリアル(Consul Curriculum)をやってみました。
2019.03.27

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

おはようございます、加藤です。Consul チュートリアルをやってみたの第2回です。Connect機能を触って見ました。

はじめてのHashiCorp Consul (第1回 インストール〜起動)

Connect機能の説明

Connect機能はサービス間をTLS暗号化と認証を行う機能です。 サイドカープロキシとして動作し、例えばサービスA→サービスBへ通信を行う際に異なるホストで動作していたとしても、サービスA, Bどちらもlocalhostへの通信(Consul Connectへの通信)を行う事でサービス間通信を行えます。

やってみる内容

socatncを使って、TCPでメッセージを送るとオウム返しされる環境をConsul Connect経由で行ってみます。

今回やってみる内容は学習の為のものです。本番利用に耐えうる物では無いので、その際は下記を確認してください。 Connect in Production - Consul by HashiCorp

Consulへサービスを登録

サービス定義ファイルを作成します。

host

cat <<EOF | tee ./consul.d/socat.json
{
  "service": {
    "name": "socat",
    "port": 8181,
    "connect": { "sidecar_service": {} }
  }
}
EOF
cat <<EOF | tee ./consul.d/web.json
{
  "service": {
    "name": "web",
    "port": 8080,
    "connect": {
      "sidecar_service": {
        "proxy": {
          "upstreams": [{
             "destination_name": "socat",
             "local_bind_port": 9191
          }]
        }
      }
    }
  }
}
EOF

コンテナ起動

操作はコンテナ上で行います。作成したサービス定義をマウントして、コンテナを起動し中に入ります。

host

docker run --rm --name consul_getting_started -v $(pwd)/consul.d/:/consul/config -d consul
docker exec -it consul_getting_started sh

サービスとConnectの起動

socatをバックグラウンドで立ち上げます。ログを後で見れるようにファイルに書き出しておきます。/consul/log/は、ホストだと.consul.d/log/に該当します。

container

apk add socat
mkdir -p /consul/log
socat -v tcp-l:8181,fork exec:"/bin/cat" > /consul/log/socat.txt 2>&1 &

Consul Connectをそれぞれバックグラウンドで立ち上げます。

container

consul connect proxy -sidecar-for socat > /consul/log/connect_socat.txt 2>&1 &
consul connect proxy -sidecar-for web > /consul/log/connect_web.txt 2>&1 &

動作確認と説明

ncを使って通信を開始します。テキストを入力してEnterを押すとオウム返しされることを確認してください。 確認が終わったらCtrl + Cで終了してください。

container

nc 127.0.0.1 9191

お気づきでしょうか?socat8181待機しているのに、nc9191へ通信を行っています。 サービス定義ファイルを確認しながら簡単に説明して行きます。

socat.jsonはサービス名がsocatでポートが8181である事が定義されています。

socat.json

{
  "service": {
    "name": "socat",
    "port": 8181,
    "connect": { "sidecar_service": {} }
  }
}

web.jsonはサービス名がwebでポートが8080である事が定義されています...がこちらは関係はありません。 sidecar_serviceの部分が重要です。ここでは、プロキシのルールが書かれておりlocalhost:9191へ通信するとsocatサービスへ転送する内容になっています。

web.json

{
  "service": {
    "name": "web",
    "port": 8080,
    "connect": {
      "sidecar_service": {
        "proxy": {
          "upstreams": [{
             "destination_name": "socat",
             "local_bind_port": 9191
          }]
        }
      }
    }
  }
}

アクセス制御

Consul Connectの機能には認証もあります。今はncの通信が出来ていますが、これを遮断してみましょう。

container

consul intention create -deny web socat
# Created: web => socat (deny)

通信できるか確認してみると、意図したとおり失敗しました。

container

nc -v 127.0.0.1 9191
127.0.0.1 (127.0.0.1:9191) open
nc: too many output retries

アクセスを開放します。

container

consul intention delete web socat
Intention deleted.

この機能によって、IDベースでの認証が可能になります。(IDはConsulサービス定義で指定した名前を指しています。)

あとがき

前回と合わせて、Consulの出来ること・良さが少しずつ見えてきた気がします。早く一通りやり切って本番運用に耐えうる環境を作ってみたいです。