drone.io v0.5以降のキャッシュ戦術

drone v0.4までは標準でビルドを高速化するための機能としてキャッシュを利用することができました。これはビルド終了時に保存したファイルを次回のビルドで再利用することができるものです。 nodejsであればnode_modules, rubyであればbundle gemsをキャッシュしておくとビルド時間を節約できます。

drone v0.5からは標準のキャッシュ機構はなくなりプラグインを利用することになりました*1が、これは少々厄介な問題を生むことになりました。 ここでは代替となる方法をご紹介します。

Volume Cache Plugin

今までと同じような挙動を期待するのであれば volume-cache plugin が利用可能です。

Volume Cache | Plugins | Drone

このプラグインはagentが動いているホストの任意の場所にキャッシュを保存することができます。

設定するには以下のように、ビルドの前後に、キャッシュの復元(restore)と、保存(rebuild)のステップをはさみこみます。

pipeline:
  restore-cache:
    image: drillster/drone-volume-cache
    restore: true
    mount:
      - ./node_modules
    volumes:
      - /tmp/cache:/cache

  build:
    image: node
    commands:
      - npm install

  rebuild-cache:
    image: drillster/drone-volume-cache
    rebuild: true
    mount:
      - ./node_modules
    volumes:
      - /tmp/cache:/cache

このプラグインの難しいところは管理者しか設定できない Trusted flag が必要になるところです。

f:id:ashphy22:20171014160052p:plain

この設定は管理者しか変更できませんので、多数の利用者がいると大変面倒です。 またTrusted flagはdocker.sockをプラグインに開放してしまうので、volumesにはホスト上のどの場所でも設定できてしまい、管理上問題になります。

利用者が少ない場合は設定するものが少なく良い選択肢になります。

S3 Cache Plugin

キャッシュ置き場としてAWS S3を利用する s3-cache plugin を利用することができます

Amazon S3 Cache | Plugins | Drone

droneをAWSにデプロイしている場合はそのままS3を利用できるので便利ですが、そうでない場合はS3互換ストレージも利用できます。オンプレで上げている場合などは minio を使うと便利でしょう。

minio.io

minioはdockerで上げればすぐ利用可能になりますのでdroneとの相性も良いです。 docker-composeでは以下のような設定になります。

minio:
  image: minio/minio
  ports:
    - "9000:9000"
  volumes:
    - /var/lib/minio/data:/data
    - /var/lib/minio/config:/root/.minio
  command: server /data
  environment:
    - "MINIO_ACCESS_KEY=DRONE"
    - "MINIO_SECRET_KEY=DRONEDRONE"

minioは9000番ポートがデフォルトですが、drone v0.8からはgRPCを利用するようになり9000番ポートをデフォルトで利用するようになったため*2、drone serverとは別に上げるか80番で上げるように変更したほうがよいです。

minioは複数ユーザを設定することができないシンプルなストレージです。 そのためアクセスキーは全員で使いまわすことになりますが、キャッシュ用途であればほとんどの場合問題にはなりません。

設定例は以下のようになりますが、AWS S3以外のストレージを指定するオプションは公式のドキュメントでは url オプションになっているところを endpoint とする必要があります。

pipeline:
  restore-cache:
    image: plugins/s3-cache:1
    pull: true
    endpoint: http://minio:9000
    access_key: DRONE
    secret_key: DRONEDRONE
    restore: true
 
  build:
    image: node
    commands:
      - npm install
 
  rebuild-cache:
    image: plugins/s3-cache:1
    pull: true
    endpoint: http://minio:9000
    access_key: DRONE
    secret_key: DRONEDRONE
    rebuild: true
    mount:
      - node_modules
 
  flush_cache:
    image: plugins/s3-cache:1
    pull: true
    endpoint: http://minio:9000
    access_key: DRONE
    secret_key: DRONEDRONE
    flush: true
    flush_age: 14

キャッシュの保存場所はデフォルトで /<owner>/<repo>/<branch> になります。 つまりブランチごとにキャッシュが生成されるため、Github Flowなどで都度ブランチを作るようなワークフローの場合は都度キャッシュがなくなってしまい効果が薄れてしまいます。以下のように path オプションを固定値で指定すれば毎回同じキャッシュを利用できます。

restore-cache:
  image: plugins/s3-cache:1
  pull: true
  endpoint: http://minio:9000
  access_key: DRONE
  secret_key: DRONEDRONE
  restore: true
  path: '/org-name/repo-name/'
 
rebuild-cache:
  image: plugins/s3-cache:1
  pull: true
  endpoint: http://minio:9000
  access_key: DRONE
  secret_key: DRONEDRONE
  rebuild: true
  path: '/org-name/repo-name/'
  mount:
    - node_modules

organization nameが3文字以下の場合

githubと連携している場合でorganization nameが3文字に満たない場合、bucket名が3文字以上というバリデーションルールに反してしまい、rebuild-cacheに失敗します。(なぜかデッドロックして死にます) この場合もpathオプションで回避してください。

flush

古いキャッシュを消す機能が flush です。 minioはホスト側から見れば通常のファイルシステムとして見えるのでtmpwatchの対象としてしまえば、利用者がflush_cacheを明示的に書く必要がなくなります。

さいごに

v0.5から標準機能ではなくなってしまったキャッシュ機能ですが、pluginになったことで腐ったキャッシュをユーザが自由に削除できるようになりました。もっとdroneを使いこなしてみてください。