DjangoをlocalのKubernetesで動かす
この記事ではDjangoをlocal環境のKubernetesで動かす方法について書いていきます。
Djangoであれば以下のようにpipenvできちんと環境分離ができますがdockerやdocker-composeも開発で使うことでしょう。 さらに、DjangoをGKEなどのKubernetesで問題なく動くかとうかをlocalでテストしたいという需要があります。
pipenv install
pipenv run python manage.py migrate
pipenv run python manage.py runserver
localでKubernetes clustersを動かす場合について次のような候補があるでしょう。
1はVM上にminikubeをインストールするので重いです。 2もVMですが、VirtualBoxよりKVMのほうが軽いので少しましになりますがまだ重いのは否めません。 minikubeでDjangoを立ち上げただけでロードアベレージが2を超えるので、Thinkpad X1 Carbon(Core i5)が熱くなります。 この状況ではラップトップで開発しようという気力はなくなるでしょう。 3のkind (Kubernetes IN Docker)を使って構築してみたところkindのKubernetesでDjangoを起動してロードアベレージ0.5くらいで収まったので、 実用的なlocalのKubernetes clustersだと思います。
kind (Kubernetes IN Docker)
まずkindをインストールしましょう。
GO111MODULE="on" go get sigs.k8s.io/kind@v0.7.0
以下でkindのコマンドがzshで補完できるようになります。
sudo sh -c "kind completion zsh > /usr/share/zsh/site-functions/_kind"
インストールが終わったらいよいよlocal Kubernetes clusterを作ります。
kind create cluster
export KUBECONFIG="$(kind get kubeconfig-path --name="kind")"
kubectl cluster-info
あとはkubectlコマンドでGKEでやるのとほぼ同じようにできるのですが、 GKE(本番環境)とkind(テスト環境)とpipenv(開発環境)の3つの環境が存在するので環境変数で3つの環境に対応できるようにしなければいけません。 環境ごとに違う設定が必要なものについては環境変数から読むように変更します。
setting.py
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')
DATABASES = {
'default': {
'ENGINE': os.environ.get('DJANGO_ENGINE'),
'HOST': os.environ.get('DJANGO_HOST'),
'PORT': os.environ.get('DJANGO_PORT'),
'NAME': os.environ.get('DJANGO_DBNAME'),
'USER': os.environ.get('DJANGO_DBUSER'),
'PASSWORD': os.environ.get('DJANGO_DBPASSWORD'),
}
}
EMAIL_HOST_USER = os.environ.get('DJANGO_EMAIL_USER')
EMAIL_HOST_PASSWORD = os.environ.get('DJANGO_EMAIL_PASSWORD')
pipenvは.envファイルがあると環境変数として考慮してくれるので以下のようなDockerfileを用意してENVを投げ入れるようにしておくと GKE(本番環境)とkind(テスト環境)とpipenv(開発環境)の3つの環境に対応できます。
Dockerfile
FROM python:3.7
ARG ENV
RUN mkdir /code/
WORKDIR /code/
COPY ./ /code/
RUN pip install --upgrade pip && \
pip install pipenv && \
pipenv --python /usr/local/bin/python && \
pipenv install
COPY $ENV /code/.env
CMD pipenv run python manage.py collectstatic
CMD pipenv run gunicorn yourproject.wsgi:application --bind 0.0.0.0:8000
静的コンテンツはdjango-storagesを利用するとpipenv run python manage.py collectstaticするだけでGoogle cloud storageに反映されます。 テスト環境と本番環境でバケット名を分けたほうがよいので.envkindと.envgkeで設定します。 毎回面倒になるのでkindでKubernetes clusterを作るコマンドをaliasでkindstartにまとめます。 ついでに終了するkindstopも.bashrcか.zshrcに追加しておきます。
alias kindstart='kind create cluster; export KUBECONFIG="$(kind get kubeconfig-path --name="kind")"; kubectl cluster-info'
alias kindstop='unset KUBECONFIG; kind delete cluster'
local kubernetes clusterを作ります。
kindstart
ビルドする。このとき.envkindというファイルから環境変数をkind用のDockerfileに投げ入れます。
docker build -t myapp/django:v1 --build-arg ENV=".envkind" .
.envkind(.env .envgkeも同様に設定する)
export DJANGO_SECRET_KEY='djangoのシークレットキー'
export DJANGO_ENGINE='django.db.backends.postgresql'
export DJANGO_DBPASSWORD='テスト環境のパスワード'
export DJANGO_HOST='テスト環境のDBサーバー'
export DJANGO_PORT='5432'
export DJANGO_DBNAME='awesomedb'
export DJANGO_DBUSER='awesomeapp'
export DJANGO_EMAIL_USER='yourtestgmail@gmail.com'
export DJANGO_EMAIL_PASSWORD='gmailのimapパスワード'
export GS_BUCKET_NAME='Google cloud storageテスト環境のバケット名'
export DEBUG=False
.env .envkind .envgkeなどの環境変数は機密情報を扱うのでgit-cryptで暗号化しておきます。 まずGnuPGで鍵を生成します。GnuPGで鍵を作る方法はこちらの記事を参考にしてください。 Djangoのプロジェクトディレクトリで以下のコマンドを実行します。
git-crypt init
.gitattributesファイルを作り暗号化したいファイルを定義する。
.env filter=git-crypt diff=git-crypt
.envkind filter=git-crypt diff=git-crypt
.envgke filter=git-crypt diff=git-crypt
.gitattributesをgitにコミットする。
git add .gitattributes
git commit -m 'Add encrypted file config'
復号化できるユーザーのGPGキーを指定する。
git-crypt add-gpg-user YOUR_GNUPG_ID
これで.env .envkind .envgkeは暗号化されるので気兼ねなくGitHubにコミットできるようになります。
git-crypt unlock
許可されたユーザーだけがgit cloneした後にこのコマンドで暗号化されたファイルを復号化できます。 いったんunlockされると復号化できるユーザーは何もしなくても復号化されたファイルが見えるようになります。
開発環境の環境変数は.envなのでそのままpipenvが読み込んでくれます。 GKEの環境変数は.envgkeにしてGKEのビルド時に同じようにDockerfileのENVに投げ込むようなMakefileを書いておきます。 テスト環境のデータベースはKubernetesに置いてもうまみがないので適当なサーバーに投げておきます。 開発環境のデータベースは色々できるようにlocalのPostgreSQLを使うように.envに書いておきます。
django.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: django
spec:
replicas: 1
selector:
matchLabels:
app: django
template:
metadata:
labels:
app: django
spec:
containers:
- name: django
image: "myapp/django:v1"
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8000
name: django
テスト用なのでレプリカは1にしています。
kind load docker-image myapp/django:v1
ビルドしたイメージをkindに取り込みます。
kubectl apply -f django.yaml
kubectl port-forward deployment/django 8000:8000
ブラウザでlocalhost:8000で動いていればlocalのKubernetesでDjangoが動いていることになります。
kindでmigrationする場合は以下のようにすればできるでしょう。
kubectl exec deployment/django -- bash -c 'pipenv run python manage.py migrate'
ついでにCircleCIも仕込んでおきましょう。
.circleci/config.yml
version: 2
jobs:
test:
docker:
- image: circleci/python:3.7
- image: circleci/postgres:11-alpine
environment:
POSTGRES_DB: awesomedb
POSTGRES_USER: awesome
POSTGRES_PASSWORD: "ok"
working_directory: ~/repo
steps:
- checkout
- run: sudo chown -R circleci:circleci /usr/local/bin
- run: sudo chown -R circleci:circleci /usr/local/lib/python3.7/site-packages
- run:
name: install dependencies
command: |
pip install --upgrade pip
pip install pipenv
pipenv --python /usr/local/bin/python
pipenv install
- run:
name: run tests
command: |
rm .env
pipenv run python manage.py test
environment:
DJANGO_SECRET_KEY: 'ok'
DJANGO_ENGINE: 'django.db.backends.postgresql'
DJANGO_DBPASSWORD: 'ok'
DJANGO_HOST: 'localhost'
DJANGO_PORT: ''
DJANGO_DBNAME: 'awesomedb'
DJANGO_DBUSER: 'awesome'
DEBUG: True
workflows:
version: 2
test:
jobs:
- test
ブログ記事を投稿したらTwitterでお知らせいたします。ブログを気に入っていただけた方はお気軽にフォローしてください。
— Solist Work (@SolistWork) 2018年11月27日
関連記事
最新記事
タグ一覧
-
ansible (2)
application (8)
chrome (1)
command (14)
django (1)
docker (3)
document (1)
emacs (14)
git (2)
google (1)
hugo (1)
kubernetes (1)
linux (20)
makefile (6)
mariadb (2)
melpa (1)
postgresql (2)
python (1)
security (2)
terminal (11)
thinkpad (2)
work (6)
zsh (10)