Quantcast
Channel: hachi8833の記事一覧|TechRacho by BPS株式会社
Viewing all articles
Browse latest Browse all 1759

mrsk gem README: 37signalsの多機能コンテナデプロイツール(翻訳)

$
0
0

概要

MITライセンスに基づいて翻訳・公開いたします。

mrsked/mrsk - GitHub

本記事公開時点のバージョン: Release v0.10.1 · mrsked/mrsk

mrsk gem README: 37signalsの多機能コンテナデプロイツール(翻訳)

MRSKは、Dockerを利用してWebアプリケーションをベアメタルからクラウドVMまでダウンタイムゼロでデプロイできます。新しいアプリケーションコンテナが起動してから古いコンテナが停止されるまでの間、動的リバースプロキシであるTraefikを利用してリクエストを保持します。複数のホストに対してシームレスに動作し、SSHKitを利用してコマンドを実行します。当初Railsアプリケーション向けに構築されましたが、Dockerでコンテナ化可能なあらゆる種類のWebアプリケーションで動作します。

以下のScreencastもどうぞ。Discordにもぜひご参加ください。

🔗 インストール方法

Rubyが使える環境であれば、以下を実行してMRSKをグローバルにインストールできます。

gem install mrsk

または、Docker化バージョンのMRSKをエイリアス経由で実行することも可能です(以下を自分の${SHELL}rcファイルに追加しておくと再利用がシンプルになります)。

alias mrsk='docker run --rm -it -v $HOME/.ssh:/root/.ssh -v /var/run/docker.sock:/var/run/docker.sock -v ${PWD}/:/workdir  ghcr.io/mrsked/mrsk'

次に、アプリケーションディレクトリでmrsk initを実行します(Railsアプリでbin/mrsk binstubを使いたい場合はmrsk init --bundleを実行します)。
終わったら新しいconfig/deploy.ymlファイルを編集します。このファイルは以下のようにシンプルです。

service: hey
image: 37s/hey
servers:
  - 192.168.0.1
  - 192.168.0.2
registry:
  username: registry-user-name
  password:
    - MRSK_REGISTRY_PASSWORD
env:
  secret:
    - RAILS_MASTER_KEY

次に.envファイルを編集して、自分が使うレジストリのパスワードをMRSK_REGISTRY_PASSWORD環境変数に追加します(Railsアプリをproduction環境で動かすためにRAILS_MASTER_KEYも追加します)。

以上で、サーバーにデプロイする準備が整います。

mrsk deploy

これにより、以下が行われます。

  1. SSH経由でサーバーに接続する(デフォルトではrootを利用し、sshキーで認証される)
  2. DockerがなさそうなサーバーではDockerをインストールする(apt-getを利用): これを行うにはssh経由でのrootアクセスが必要です
  3. レジストリにローカルとリモートの両方でログインする
  4. アプリケーションのルートディレクトリにある標準のDockerfileでイメージをビルドする
  5. イメージをレジストリにpushする
  6. レジストリにあるイメージをサーバーにpullする
  7. Traefikが実行中で、トラフィックをポート80で受信することを確認する
  8. アプリがGET /up200 OKを返すことを確認する
  9. 現在のgitバージョンハッシュと一致するアプリのバージョンで、新しいコンテナを起動する
  10. 以前のバージョンで実行されていた古いコンテナを停止する
  11. 未使用のイメージを削除してコンテナを停止し、サーバーがあふれないようにする

できました!これで、すべてのサーバーがポート80でアプリを配信するようになります。実行するサーバーが1個だけの場合は、これでOKです。実行するサーバーが複数の場合は、ロードバランサーをサーバーの手前に配置する必要があります。

🔗 ビジョン

Webアプリを手軽にデプロイする商用サービスは、この何十年の間に爆発的に増加しています。その先駆けとなったHerokuの素晴らしさは、永遠に競合他社の先を行くかと思われるほどでした。近年はFly.ioやRenderなどの優れた競合サービスも登場していますし、ホスト型KubernetesによってAWSやGCPやDigital Oceanなどあらゆる場所での作業が楽になりつつあります。しかしこれらはすべて、クラウド上のコンピュータを有料でレンタルする形になります。自社内にあるハードウェア上で実行したい場合は、たとえ将来の移行パスが明確であったとしても、そうした商用プラットフォームにどの程度ロックインされるかを慎重に見極める必要があります。できれば、ビジネスが請求書の山に飲み込まれる前に!

MRSKは、これら商用サービスが切り開いてきた先進的なエルゴノミクスを取り入れて、Webサービスをあらゆる場所にデプロイ可能にすることを目指しています。デプロイ先がマネージドサービスなし・価格上乗せなしの低価格サービス(Digital Ocean、Hetzner、OVHなど)であろうと、自社内に設置されているベアメタルマシンであろうと、まったく変わりません。SSHキーを追加した以外に何も準備していない素のUbuntuサーバーのIPアドレスリストを設定ファイルに記入すれば、文字通り数分で実行できるようになるのです。

この手法によって移植性が大幅に高まります。Webアプリを複数のクラウドにデプロイするのも同じように手軽にできます。普段は独自ハードウェアで運用し、アクセスが集中する時期が近づいたらクラウドにデプロイして可用性を高めることも可能です。ツール周りが単一プロバイダにロックインされていなければ、多くの魅力的なオプションが利用できます。

MRSKが最終的に目指すのは、商用サービスに縛られていないオープンソースのツールを用いて、本番運用までの複雑さを軽減することです(ゼロではありません、念のため)。LinuxやDockerの基本的な操作がまだ難しいのであれば、これまでどおりフルマネージドサービスに乗る方がおそらくよいでしょう。しかしそうした概念に慣れてくれば、MRSKを使う準備はすぐにでも整います。

🔗 Capistrano/Kubernetes/Docker Swarmでいいのでは?

MRSKは基本的に「コンテナ用Capistrano」です。事前にサーバーを注意深くセットアップする必要もありませんし、サーバーで適切なバージョンのRubyやその他の依存関係を事前に準備しておく必要もありません。必要なものはすべてDockerイメージの中で動きます。真新しいUbuntuサーバー(でも何でも)を起動してMRSKのサーバーリストに追加すれば、Dockerで自動プロビジョニングされて即座に実行されます。Dockerレイヤキャッシュ機能によってデプロイも高速化され、サーバーに煩わされることも減ります。さらに、MRSKでビルドしたイメージは、後でCIや内部調査にも転用できます。

Kubernetesは猛獣です。独自ハードウェア上での運用は気の小さい人には向いていません。他の誰かのプラットフォーム上で動かすのであれば(Renderがやっているような透過的運用か、AWSやGCP上で明示的に運用するか)、Kubernetesは良いオプションですが、クラウドと独自ハードウェアの間を自由に移動したり両者を混在させたりするなら、MRSKの方がずっとシンプルです。MRSKでは基本的なDockerコマンドが呼び出されているだけです。

Docker SwarmはKubernetesよりずっとシンプルですが、それでもステートのreconciliation(調整)を利用する宣言的モデル上に構築される点は同じです。MRSKはあえてCapistranoと同様の命令的コマンド中心の設計を採用しています。

最終的にWebアプリのデプロイ方法はいくらでも存在しますが、MRSKは、私たち37signalsが現代のコンテナ化ツールのメリットを失わずにHEYクラウドから自社に取り戻すのに使っているツールキットなのです。

🔗 MRSKをDockerから実行する

MRSKは、rails/dockedと同様にDockerコンテナでパッケージ化されています。これにより、Docker以外の依存関係をインストールせずに、(アプリケーションのディレクトリから)MRSKを実行可能になります。
コンテナ作業をさらに便利にするために、以下のエイリアスをbashのプロファイル設定に追加してください。

alias mrsk="docker run -it --rm -v '${PWD}:/workdir' -v '${SSH_AUTH_SOCK}:/ssh-agent' -v /var/run/docker.sock:/var/run/docker.sock -e 'SSH_AUTH_SOCK=/ssh-agent' ghcr.io/mrsked/mrsk:latest"

MRSKはリモート接続をsshで確立するので、sshエージェントにアクセス可能になっている必要があります。上のコマンドは、ボリュームマウントを用いてコンテナ内でボリュームを利用可能にし、コンテナ内部のsshエージェントがそれを利用できるように設定します。

🔗 設定

🔗 必要な環境変数を.envファイルで読み込む

MRSKはdotenvを用いて、アプリケーションのルートディレクトリに置かれている.envファイルの環境変数を自動的に読み込みます。この.envファイルは、MRSK_REGISTRY_PASSWORDやデータベースパスワードなどの変数を設定するのに利用できます。ただし、この理由によって、.envファイルは決してGitにチェックインしたりDockerfileに取り込んだりしてはいけません。形式は以下のようなキーバリューになります。

MRSK_REGISTRY_PASSWORD=pw
DB_PASSWORD=secret123

🔗 生成された.envファイルを利用する

🔗 1Passwordを秘密情報ストアとして利用する

秘密情報ストアを1Passwordなどに集約している場合は、秘密情報を取得する.env.erbテンプレートを作成できます。以下は.env.erbファイルの例です。

<% if (session_token = `op signin --account my-one-password-account --raw`.strip) != "" %># Generated by mrsk envify
GITHUB_TOKEN=<%= `gh config get -h github.com oauth_token`.strip %>
MRSK_REGISTRY_PASSWORD=<%= `op read "op://Vault/Docker Hub/password" -n --session  #{session_token}` %>
RAILS_MASTER_KEY=<%= `op read "op://Vault/My App/RAILS_MASTER_SECRET" -n --session #{session_token}` %>
MYSQL_ROOT_PASSWORD=<%= `op read "op://Vault/My App/MYSQL_ROOT_PASSWORD" -n --session #{session_token}` %>
<% else raise ArgumentError, "Session token missing" end %>

このテンプレートファイルはGitにチェックインしても安全です。アプリをデプロイできるユーザーなら誰でもmrsk envifyを実行して、アプリを最初にセットアップしたり、パスワードを変更して正しい.envファイルを取得したりできます。

デプロイ先ごとに環境変数を使い分ける必要がある場合は、.env.destination.erbテンプレートで設定できます。mrsk envify -d stagingを実行すると.env.stagingファイルが生成されます。

🔗 Bitwardenを秘密情報ストアとして利用する

Bitwardenなどのオープンソースの秘密情報ストアを使う場合は、以下のような.env.erbテンプレートで秘密情報を探索できます。

SOME_SECRETはbitwardenの保管庫(vault)の秘密メモに保存できます。

$ bw list items --search SOME_SECRET | jq
? Master password: [hidden]

[
  {
    "object": "item",
    "id": "123123123-1232-4224-222f-234234234234",
    "organizationId": null,
    "folderId": null,
    "type": 2,
    "reprompt": 0,
    "name": "SOME_SECRET",
    "notes": "yyy",
    "favorite": false,
    "secureNote": {
      "type": 0
    },
    "collectionIds": [],
    "revisionDate": "2023-02-28T23:54:47.868Z",
    "creationDate": "2022-11-07T03:16:05.828Z",
    "deletedDate": null
  }
]

上のjsonから SOME_SECRETidを抽出して、以下の.erbで利用します。

.env.erbサンプルファイル:

<% if (session_token=`bw unlock --raw`.strip) != "" %># Generated by mrsk envify
SOME_SECRET=<%= `bw get notes 123123123-1232-4224-222f-234234234234 --session #{session_token}` %>
<% else raise ArgumentError, "session_token token missing" end %>

これで、アプリをデプロイできるユーザーなら誰でもmrsk envifyを実行して.envを生成できます。

🔗 Docker Hub以外のレジストリを使用する

デフォルトのレジストリはDocker Hubですが、registry/serverで変更可能です。

registry:
  server: registry.digitalocean.com
  username:
    - DOCKER_REGISTRY_TOKEN
  password:
    - DOCKER_REGISTRY_TOKEN

秘密情報DOCKER_REGISTRY_TOKENへの参照は、MRSKを実行中のマシン上のENV["DOCKER_REGISTRY_TOKEN"]を探索します。

🔗 root以外のSSHユーザーを使う

デフォルトのSSHユーザーはrootですが、ssh/userで変更可能です。

ssh:
  user: app

🔗 SSHプロキシホストを使う

プロキシホスト経由で接続する必要がある場合は、ssh/proxyで指定できます。

ssh:
  proxy: "192.168.0.1" # デフォルトユーザーはroot

ユーザーも指定できます。

ssh:
  proxy: "app@192.168.0.1"

🔗 環境変数を使う

以下を使うと、アプリのコンテナにenvの環境変数を注入できます。

env:
  DATABASE_URL: mysql2://db1/hey_production/
  REDIS_URL: redis://redis1:6379/1

🔗 機密の環境変数を使う

機密にしておくべき環境変数がある場合は、envファイルでclearブロックとsecretブロックを使い分けることが可能です。

env:
  clear:
    DATABASE_URL: mysql2://db1/hey_production/
    REDIS_URL: redis://redis1:6379/1
  secret:
    - DATABASE_PASSWORD
    - REDIS_PASSWORD

secretブロックの環境変数リストは、実行時にローカル環境から展開されます。つまり、DATABASE_PASSWORDの秘密情報への参照は、MRSKを実行している環境でENV["DATABASE_PASSWORD"]を探索します。これは、ビルド用の秘密情報の場合と同じ要領です。

参照されたsecretの環境変数が見つからない場合は、KeyError例外で設定を中止します。

注: secretの環境変数は、MRSKの出力では値が伏せ字(redacts)になります。clearの環境変数は、実行時に平文でコンテナに注入されます。

🔗 ボリュームを使う

volumesでカスタムボリュームをアプリのコンテナに追加できます。

volumes:
  - "/local/path:/container/path"

🔗 MRSKの環境変数

コンテナを実行すると、以下の環境変数が設定されます。

  • MRSK_CONTAINER_NAME: ここには現在のコンテナ名とバージョンが含まれます

🔗 さまざまな役割のサーバーを使い分ける

デフォルトのWeb以外に、ジョブ実行など別のロール用に別ホストを使う場合は、新しいエンドポイントコマンドでこれらのホストを以下のように指定できます。

servers:
  web:
    - 192.168.0.1
    - 192.168.0.2
  job:
    hosts:
      - 192.168.0.3
      - 192.168.0.4
    cmd: bin/jobs

注: Traefikは、デフォルトではwebロールにのみ(ロールが指定されていない場合すべてのサーバーに)インストールおよび実行されます。Traefikをweb以外のロールでホストする必要がある場合は、traefik: trueを追加します。

servers:
  web:
    - 192.168.0.1
    - 192.168.0.2
  web2:
    traefik: true
    hosts:
      - 192.168.0.3
      - 192.168.0.4

🔗 コンテナにラベルを付ける

起動されるコンテナにラベルを設定することで、デフォルトのTraefikルールをカスタマイズできます。

labels:
  traefik.http.routers.hey.rule: Host(`app.hey.com`)

注意: バッククオートは、ルールを正しく渡し、bashでコマンド置換として扱われないようにするために必要です。

これにより、同じTraefikインスタンスとポートを共有する同一サーバーで複数のアプリケーションを実行できるようになります。利用可能なルーティングルールの完全なリストは https://doc.traefik.io/traefik/routing/routers/#ruleにあります。

ラベルはロールごとにも適用可能です。

servers:
  web:
    - 192.168.0.1
    - 192.168.0.2
  job:
    hosts:
      - 192.168.0.3
      - 192.168.0.4
    cmd: bin/jobs
    labels:
      my-label: "50"

🔗 コンテナオプションを利用する

コンテナの起動に使うオプションは、options定義で特殊化できます。

servers:
  web:
    - 192.168.0.1
    - 192.168.0.2
  job:
    hosts:
      - 192.168.0.3
      - 192.168.0.4
    cmd: bin/jobs
    options:
      cap-add: true
      cpu-count: 4

これで、jonコンテナがdocker run ... --cap-add --cpu-count 4 ...で起動します。

🔗 ログを設定する

Dockerに渡すログ出力ドライバやオプションは、loggingで設定できます。

logging:
  driver: awslogs
  options:
    awslogs-region: "eu-central-2"
    awslogs-group: "my-app"

何も設定しない場合は、すべてのコンテナでデフォルトオプションmax-size=10mが使われます。Dockerのデフォルトのログ出力ドライバはjson-fileです。

🔗 stop_wait_timeを変更する

新規デプロイ時には、実行中の古い各コンテナはSIGTERMで”graceful”にシャットダウンされ、10秒の猶予期間を経てからSIGKILLを送信します。
この値はstop_wait_timeオプションで設定できます。

stop_wait_time: 30

🔗 ネイティブのマルチアーキテクチャ向けのリモートビルダーを使う

開発をARM64(Apple Siliconなど)で行っているがAMD64(x86 64ビット)にデプロイしたい場合は、マルチアーキテクチャのイメージを利用できます。デフォルトのMRSKは、QEMUエミュレーション経由でビルドを行うローカルbuildx設定をセットアップします。ただし、特に最初のビルドはかなり遅くなる可能性があります。

ビルダーのオプションを使えば、ローカルではイメージのAMD64部分をネイティブリリースし、リモートではAMD64ホストを利用してイメージのAMD64部分をネイティブビルドする形で高速化できるようになります。

builder:
  local:
    arch: arm64
    host: unix:///Users/<%= `whoami`.strip %>/.docker/run/docker.sock
  remote:
    arch: amd64
    host: ssh://root@192.168.0.1

注意: これを行うには、ビルダーとして使われるリモートホストでDockerが動作していなければなりません。このインスタンスの共有範囲は、同一のレジストリとcredentialを用いるビルドに限定すべきです。

🔗 単一アーキテクチャ向けのリモートビルダーを利用する

開発をARM64(Apple Siliconなど)で行っていてAMD64(x86 64ビット)にデプロイしたいが、ローカルで(または他のARM64ホストで)イメージを実行する必要がない場合は、AMD64のみを対象とするリモートビルダーを構成できます。ローカルでのビルドが不要なので、マルチアーキテクチャのビルドよりも少し速くなります。

builder:
  remote:
    arch: amd64
    host: ssh://root@192.168.0.1

🔗 マルチアーキテクチャが不要な場合にネイティブビルダーを使う

デプロイしているアーキテクチャと同一のアーキテクチャで開発している場合は、マルチアーキテクチャとリモートビルドの両方をやめることでビルドを高速化できます。

builder:
  multiarch: false

これは、デプロイ先サーバーとアーキテクチャを共有しているCIサーバーでMRSKを実行している場合にも適しています。

🔗 ビルド時に別のDockerfileやコンテキストを使う

ビルドコマンドに別のDockerfileやコンテキストを渡す必要がある場合は(例: monorepoを使っている場合や別のDockerfileがある場合)、以下のようにbuilderオプションで変更可能です。

# 別のDockerfileを使う
builder:
  dockerfile: Dockerfile.xyz
# コンテキストを設定する
builder:
  context: ".."
# Dockerfileとコンテキストを両方指定する
builder:
  dockerfile: "../Dockerfile.xyz"
  context: ".."

🔗 新しいイメージでビルド用秘密情報を使う

イメージによっては、ビルド時に秘密情報を渡す必要が生じることがあります(private gemリポジトリにアクセスするGITHUB_TOKENなど)。これは、環境変数に秘密情報を設定してビルダーのコンフィグで参照することで可能になります。

builder:
  secrets:
    - GITHUB_TOKEN

このビルド用秘密情報はDockerfileで参照できます。

# Gemfilesをコピーする
COPY Gemfile Gemfile.lock ./

# 依存関係をインストールする
# (アクセストークン経由でアクセスするprivateリポジトリなど)
# (終了後、GITHUB_TOKENを含むバンドルキャッシュは削除する)
RUN --mount=type=secret,id=GITHUB_TOKEN \
  BUNDLE_GITHUB__COM=x-access-token:$(cat /run/secrets/GITHUB_TOKEN) \
  bundle install && \
  rm -rf /usr/local/bundle/cache

🔗 Traefikのコマンド引数を使う

以下のようにtraefikコマンドをカスタマイズできます。

traefik:
  args:
    accesslog: true
    accesslog.format: json

これで、traefikコンテナが--accesslog=true accesslog.format=jsonで起動します。

🔗 Traefikのホスト-ポートバインディング

デフォルトのTraefikは、ホストマシンのポート80にバインドします。これは以下のように別のポートを設定可能です。

traefik:
  host_port: 8080

🔗 traefik向けのDockerオプションを設定する

traefikには以下の方法でDockerオプションを追加で渡せます。

traefik:
  options:
    publish:
    - 8080:8080
    volumes:
    - /tmp/example.json:/tmp/example.json
    memory: 512m

これで、docker run ... --volume /tmp/example.json:/tmp/example.json --publish 8080:8080のようなコマンドでtraefikコンテナが起動します。

🔗 traefikに別のエンドポイントを設定する

traefikには、以下のように複数のエンドポイントを設定できます。

service: myservice
labels:
  traefik.tcp.routers.other.rule: 'HostSNI(`*`)'
  traefik.tcp.routers.other.entrypoints: otherentrypoint
  traefik.tcp.services.other.loadbalancer.server.port: 9000
  traefik.http.routers.myservice.entrypoints: web
  traefik.http.services.myservice.loadbalancer.server.port: 8080
traefik:
  options:
    publish:
      - 9000:9000
  args:
    entrypoints.web.address: ':80'
    entrypoints.otherentrypoint.address: ':9000'

🔗 新規イメージのビルド引数を設定する

秘密情報以外のビルド引数も設定可能です。

builder:
  args:
    RUBY_VERSION: 3.2.0

このビルド引数はDockerfileで参照可能です。

ARG RUBY_VERSION
FROM ruby:$RUBY_VERSION-slim as base

🔗 DB/キャッシュ/検索サービスを使う

アクセサリサービス(追加サービス)もMRSK経由で管理できます。アクセサリとは、アプリが依存する長時間実行サービスのことです。アクセサリサービスはデプロイ時には自動的に更新されません。

accessories:
  mysql:
    image: mysql:5.7
    host: 1.1.1.3
    port: 3306
    env:
      clear:
        MYSQL_ROOT_HOST: '%'
      secret:
        - MYSQL_ROOT_PASSWORD
    volumes:
      - /var/lib/mysql:/var/lib/mysql
    options:
      cpus: 4
      memory: "2GB"
  redis:
    image: redis:latest
    role:
      - web
    port: "36379:6379"
    volumes:
      - /var/lib/redis:/data
  internal-example:
    image: registry.digitalocean.com/user/otherservice:latest
    host: 1.1.1.5
    port: 44444

アクセサリーサービスが実行されるホストは、ホストまたはロールで指定できます。

  # 単一ホスト
  mysql:
    host: 1.1.1.1
  # 複数ホスト
  redis:
    hosts:
      - 1.1.1.1
      - 1.1.1.2
  # ロール指定
  monitoring:
    roles:
      - web
      - jobs

これでmrsk accessory start mysqlを実行して1.1.1.3のホストでMySQLサーバーを起動します。mrsk accessoryで利用可能な全コマンドを表示できます。

アクセサリのイメージは、publicなイメージか、自分たちのprivateレジストリでタグ付けされていなければなりません。

🔗 cronを使う

cronジョブ実行用のコンテナを利用できます。

servers:
  cron:
    hosts:
      - 192.168.0.1
    cmd:
      bash -c "cat config/crontab | crontab - && cron -f"

上はcron設定がconfig/crontabに保存されていることが前提です。

🔗 監査ブロードキャストを使う

デプロイやロールバックなどの監査をチャットルームなどにブロードキャストしたい場合は、監査のコード行に渡されるバイナリへのパスをaudit_broadcast_cmdの第1引数に設定することでできます。

audit_broadcast_cmd:
  bin/audit_broadcast

ブロードキャストコマンドは以下のようになります。

#!/usr/bin/env bash
curl -q -d content="[My App] ${1}" https://3.basecamp.com/XXXXX/integrations/XXXXX/buckets/XXXXX/chats/XXXXX/lines

これで、以下のような行がBasecampの事前設定済みチャットボットに投稿されます。

[My App] [dhh] Rolled back to version d264c4e92470ad1bd18590f04466787262f605de

🔗 パスやポートのカスタムヘルスチェック

MRSKはデフォルトでアプリケーションのポート3000の/upに再度ヘルスチェックを行います。ポートやパスはhealthcheck設定でカスタマイズできます。

healthcheck:
  path: /healthz
  port: 4000

これにより、/healthzパスへのヘルスチェック用のtraefikラベル付きでアプリケーションが構成され、MRSKが実行するデプロイ前ヘルスチェックがポート4000の同じパスに対して実行されるようになります。

🔗 コマンド

🔗 サーバーでコマンドを実行する

以下の単発コマンドを実行できます。

# すべてのサーバーでコマンドを実行する
mrsk app exec 'ruby -v'
App Host: 192.168.0.1
ruby 3.1.3p185 (2022-11-24 revision 1a6b16756e) [x86_64-linux]

App Host: 192.168.0.2
ruby 3.1.3p185 (2022-11-24 revision 1a6b16756e) [x86_64-linux]
# primaryサーバーでコマンドを実行する
mrsk app exec --primary 'cat .ruby-version'
App Host: 192.168.0.1
3.1.3
# すべてのサーバーでコマンドを実行する
mrsk app exec 'bin/rails about'
App Host: 192.168.0.1
About your application's environment
Rails version             7.1.0.alpha
Ruby version              ruby 3.1.3p185 (2022-11-24 revision 1a6b16756e) [x86_64-linux]
RubyGems version          3.3.26
Rack version              2.2.5
Middleware                ActionDispatch::HostAuthorization, Rack::Sendfile, ActionDispatch::Static, ActionDispatch::Executor, Rack::Runtime, Rack::MethodOverride, ActionDispatch::RequestId, ActionDispatch::RemoteIp, Rails::Rack::Logger, ActionDispatch::ShowExceptions, ActionDispatch::DebugExceptions, ActionDispatch::Callbacks, ActionDispatch::Cookies, ActionDispatch::Session::CookieStore, ActionDispatch::Flash, ActionDispatch::ContentSecurityPolicy::Middleware, ActionDispatch::PermissionsPolicy::Middleware, Rack::Head, Rack::ConditionalGet, Rack::ETag, Rack::TempfileReaper
Application root          /rails
Environment               production
Database adapter          sqlite3
Database schema version   20221231233303

App Host: 192.168.0.2
About your application's environment
Rails version             7.1.0.alpha
Ruby version              ruby 3.1.3p185 (2022-11-24 revision 1a6b16756e) [x86_64-linux]
RubyGems version          3.3.26
Rack version              2.2.5
Middleware                ActionDispatch::HostAuthorization, Rack::Sendfile, ActionDispatch::Static, ActionDispatch::Executor, Rack::Runtime, Rack::MethodOverride, ActionDispatch::RequestId, ActionDispatch::RemoteIp, Rails::Rack::Logger, ActionDispatch::ShowExceptions, ActionDispatch::DebugExceptions, ActionDispatch::Callbacks, ActionDispatch::Cookies, ActionDispatch::Session::CookieStore, ActionDispatch::Flash, ActionDispatch::ContentSecurityPolicy::Middleware, ActionDispatch::PermissionsPolicy::Middleware, Rack::Head, Rack::ConditionalGet, Rack::ETag, Rack::TempfileReaper
Application root          /rails
Environment               production
Database adapter          sqlite3
Database schema version   20221231233303
# primaryサーバーでコマンドを実行する
mrsk app exec -p 'bin/rails runner "puts Rails.application.config.time_zone"'
UTC

🔗 SSH経由でインタラクティブにコマンドを実行する

サーバー上で、Railsコンソールやbashセッションなどの対話型コマンドを実行できます (デフォルトはprimary: 別のサーバーに接続するには--hostsを使います)。

# アプリの直近のイメージから作った新規コンテナで
# 新しいbashセッションを開始する
mrsk app exec -i bash
# アプリが現在実行中のコンテナでbashセッションを開始する
mrsk app exec -i --reuse bash
# アプリの直近のイメージから作った新規コンテナで
# Railsコンソールを開始する
mrsk app exec -i 'bin/rails console'

🔗 コンテナの詳細な実行状態を表示する

mrsk detailsを実行するとサーバーの状態を表示できます。

Traefik Host: 192.168.0.1
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                               NAMES
6195b2a28c81   traefik   "/entrypoint.sh --pr…"   30 minutes ago   Up 19 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp   traefik

Traefik Host: 192.168.0.2
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                               NAMES
de14a335d152   traefik   "/entrypoint.sh --pr…"   30 minutes ago   Up 19 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp   traefik

App Host: 192.168.0.1
CONTAINER ID   IMAGE                                                                         COMMAND                  CREATED          STATUS          PORTS      NAMES
badb1aa51db3   registry.digitalocean.com/user/app:6ef8a6a84c525b123c5245345a8483f86d05a123   "/rails/bin/docker-e…"   13 minutes ago   Up 13 minutes   3000/tcp   chat-6ef8a6a84c525b123c5245345a8483f86d05a123

App Host: 192.168.0.2
CONTAINER ID   IMAGE                                                                         COMMAND                  CREATED          STATUS          PORTS      NAMES
1d3c91ed1f55   registry.digitalocean.com/user/app:6ef8a6a84c525b123c5245345a8483f86d05a123   "/rails/bin/docker-e…"   13 minutes ago   Up 13 minutes   3000/tcp   chat-6ef8a6a84c525b123c5245345a8483f86d05a123

mrsk app detailsでアプリコンテナの情報だけを表示したり、mrsk traefik detailsでTraefikの情報だけを表示したりすることも可能です。

🔗 不適切なデプロイをロールバックで修正する

不適切なデプロイに気づいたら、一時停止している古いコンテナイメージを再度アクティベートすることで即座にロールバックできます。

mrsk app containersを実行すると、ロールバックできる古いコンテナを確認できます。
表示内容はmrsk app detailsに似ていますが、古いコンテナもすべて含まれます。出力は以下のようになります。

App Host: 192.168.0.1
CONTAINER ID   IMAGE                                                                         COMMAND                  CREATED          STATUS                      PORTS      NAMES
1d3c91ed1f51   registry.digitalocean.com/user/app:6ef8a6a84c525b123c5245345a8483f86d05a123   "/rails/bin/docker-e…"   19 minutes ago   Up 19 minutes               3000/tcp   chat-6ef8a6a84c525b123c5245345a8483f86d05a123
539f26b28369   registry.digitalocean.com/user/app:e5d9d7c2b898289dfbc5f7f1334140d984eedae4   "/rails/bin/docker-e…"   31 minutes ago   Exited (1) 27 minutes ago              chat-e5d9d7c2b898289dfbc5f7f1334140d984eedae4

App Host: 192.168.0.2
CONTAINER ID   IMAGE                                                                         COMMAND                  CREATED          STATUS                      PORTS      NAMES
badb1aa51db4   registry.digitalocean.com/user/app:6ef8a6a84c525b123c5245345a8483f86d05a123   "/rails/bin/docker-e…"   19 minutes ago   Up 19 minutes               3000/tcp   chat-6ef8a6a84c525b123c5245345a8483f86d05a123
6f170d1172ae   registry.digitalocean.com/user/app:e5d9d7c2b898289dfbc5f7f1334140d984eedae4   "/rails/bin/docker-e…"   31 minutes ago   Exited (1) 27 minutes ago              chat-e5d9d7c2b898289dfbc5f7f1334140d984eedae4

上の例ではe5d9d7c2b898289dfbc5f7f1334140d984eedae4が直近のバージョンであることがわかるので、ここにロールバック可能です。

mrsk rollback e5d9d7c2b898289dfbc5f7f1334140d984eedae4を実行してロールバックすると、6ef8a6a84c525b123c5245345a8483f86d05a123が停止してe5d9d7c2b898289dfbc5f7f1334140d984eedae4が起動します。古いコンテナも利用可能な状態になっているので、非常に迅速に行われます。レジストリからのダウンロードは発生しません。

mrsk deployを実行すると、デフォルトでは3日後に古いコンテナが削除されるのでご注意ください。

🔗 削除を実行してサーバーをクリーンアップする

Traefik、コンテナ、イメージ、レジストリセッションを含むアプリケーション全体を削除する場合はmrsk removeを実行します。これにより、サーバーをクリーンにできます。

🔗 ロック

コンカレントな実行が安全でないコマンドは、実行中にデプロイロックを取得します。このロックは、primaryサーバー上のmrsk_lockディレクトリです。

ロックの状態は以下で確認できます。

mrsk lock status
Locked by: AN Other at 2023-03-24 09:49:03 UTC
Version: 77f45c0686811c68989d6576748475a60bf53fc2
Message: Automatic deploy lock

以下のようにロックを手動で取得・解除することも可能です。

mrsk lock acquire -m "Doing maintanence"
mrsk lock release

🔗 MRSKの開発状況

これはベータ版ソフトウェアです。コマンドは今後変更される可能性があります。ただし37signalsでは本番運用しています。

🔗 ライセンス

MRSK is released under the MIT License.

関連記事

クジラに乗ったRuby: Evil Martians流Docker+Ruby/Rails開発環境構築(更新翻訳)

The post mrsk gem README: 37signalsの多機能コンテナデプロイツール(翻訳) first appeared on TechRacho.


Viewing all articles
Browse latest Browse all 1759

Trending Articles