背景
Docker for Macをお使いであれば一度は
ホストとコンテナ間のマウントが遅いと感じたことがあると思います。
Docker やDocker Composeであれば、マウント先のコンテナディレクトリ末尾に:cached
とフラグを立ててあげることでホストディレクトリに対する読み書きのパフォーマンスが改善されます。
参考URL
例えばdockerでは
$ docker run -v /your/project/dir:/mount/dir:cached your_image
Docker Composeでは
version: '3.7'
services:
your-app:
restart: always
image: your_image
volumes:
- ./project/dir:/mount/dir:cached
マウント先のディレクトリ末尾に:cached
をつけるだけなので手軽ですね!
シンプル!
本記事ではこの:cached
を恩恵をk8s環境が得るまでを紹介していきます。
はじめに
Docker for Macのissueでも議論されていますが、
現状(2019/01/22時点)Docker for Macの仕様としての機能提供ではなく、
現状の仕組みを利用したちょっとした小技程度と考えてもらえたらと思います。
今後のアップデートで、よりスマートに実現可能な方法も出てくる可能性があります。
本記事の方法は上記Issueのこちらの方法を参考にしています。
動作環境
- macOS Mojave 10.14.2
- Docker for Mac 2.0.0.2
- Engine : 18.09.1
- Kubernetes: v1.10.11
それではやってみる。
Issueのこちらをざっくり要約すると、
**「一度cachedされたホストディレクトリは、他のコンテナもその恩恵にあずかるよ」**ってことみたいです。
まず、あらかじめcachedしたいホストディレクトリをマウントしたコンテナを
予めバックグラウンドで実行しておきます。
$ docker run --rm -d \
-v /your/host/directory:/tmp/project:cached \
busybox:latest \
watch -n 1 date
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
90a9a40edaa6 busybox:latest "watch -n 1 date" 2 seconds ago Up 2 seconds objective_visvesvaraya
docker ps
で起動中のコンテナを確認すると先程立ち上げたものが確認できます。
続いてdeploymentのマニフェストファイルをk8sにapplyしましょう。
apiVersion: apps/v1
kind: Deployment
metadata:
name: cached-deployment
spec:
replicas: 1
selector:
matchLabels:
app: cached-app
template:
metadata:
labels:
app: cached-app
spec:
containers:
- name: your-container
image: your_image
volumeMounts:
- name: cached-data
mountPath: /your/project/directory
volumes:
- name: cached-data
hostPath:
path: /your/host/directory
type: Directory
$ kubectl apply -f /path/to/manifest/deployment.yml
deployment.apps "cached-deployment" created
以上です!お疲れ様でした!
結果の確認
検証として、バックエンドをDjango, DBをSQLite3で構築したPodをk8s上にデプロイしてみました。
適当なクエリを投げ、ヒットしたレコードを列挙するページで応答速度を計測しています。
SQLiteのファイルサイズは約130MBです。
cached前
cached後
cached前に比べ、約10倍ほど応答速度が上がっているのが確認できました。
ちなみに
先述の方法はLocalタイプのPersistant Volumeについても同様の結果が得られました。
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-cached-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: local-storage
local:
path: /your/host/directory
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- docker-for-desktop
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: local-cached-claim
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-storage
resources:
requests:
storage: 10Gi
上記のマニフェストで作成したPersistant Volumeを使用するために
deployment.yml
のvolume定義部分を書き換えます。
apiVersion: apps/v1
kind: Deployment
metadata:
name: cached-deployment
spec:
replicas: 1
selector:
matchLabels:
app: cached-app
template:
metadata:
labels:
app: cached-app
spec:
containers:
- name: your-container
image: your_image
volumeMounts:
- name: cached-data
mountPath: /your/project/directory
volumes:
- name: cached-data
persistentVolumeClaim:
claimName: local-cached-claim
localタイプのボリュームの詳細は以下のブログが詳しいです。
https://kubernetes.io/blog/2018/04/13/local-persistent-volumes-beta/
終わりに
多少強引な方法ではありましたが、
なんとかk8s上のコンテナに対してcachedオプションの恩恵をあずかることが出来ました。
もし他にもこんな方法あるよー!って方がいらっしゃいましたら教えていただきたいです。。
ありがとうございました!