Kubernetesを使用してスケーラブルで安全なDjangoアプリケーションをデプロイする方法
序章
このチュートリアルでは、コンテナ化されたDjangoポーリングアプリケーションをKubernetesクラスターにデプロイします。
Django は、Pythonアプリケーションをすばやく立ち上げるのに役立つ強力なWebフレームワークです。 これには、オブジェクトリレーショナルマッパー、ユーザー認証、アプリケーション用のカスタマイズ可能な管理インターフェイスなど、いくつかの便利な機能が含まれています。 また、キャッシングフレームワークが含まれており、URLディスパッチャーおよびテンプレートシステムを通じてクリーンなアプリの設計を促進します。
Docker を使用してDjangoおよびGunicornアプリケーションを構築する方法では、 Django Tutorial Pollsアプリケーションが、スケーラブルなクラウドを構築するためのTwelve-Factor方法論に従って変更されました。ネイティブWebアプリ。 このコンテナ化されたセットアップは、 Docker、Nginx、およびLet's Encrypt を使用してDjangoアプリケーションをスケーリングおよび保護する方法で、NginxリバースプロキシおよびLet'sEncryptで署名されたTLS証明書を使用してスケーリングおよび保護されました。 コンテナからDjangoを使用したKubernetesへシリーズのこの最後のチュートリアルでは、最新のDjangoポーリングアプリケーションがKubernetesクラスターにデプロイされます。
Kubernetes は、コンテナー化されたアプリケーションのデプロイ、スケーリング、管理を自動化する強力なオープンソースのコンテナーオーケストレーターです。 ConfigMapsやSecretsなどのKubernetesオブジェクトを使用すると、構成を一元化してコンテナから切り離すことができます。一方、Deploymentsなどのコントローラは、失敗したコンテナを自動的に再起動し、コンテナレプリカの迅速なスケーリングを可能にします。 TLS暗号化は、Ingressオブジェクトとingress-nginxオープンソースのIngressコントローラーで有効になります。 cert-manager Kubernetesアドオンは、無料の Let'sEncrypt認証局を使用して証明書を更新および発行します。
前提条件
このチュートリアルに従うには、次のものが必要です。
- ロールベースのアクセス制御(RBAC)が有効になっているKubernetes1.15+クラスター。 このセットアップではDigitalOceanKubernetes クラスターを使用しますが、別の方法を使用してクラスターを自由に作成できます。
kubectl
コマンドラインツールがローカルマシンにインストールされ、クラスターに接続するように構成されています。kubectl
のインストールについて詳しくは、公式ドキュメントをご覧ください。 DigitalOcean Kubernetesクラスターを使用している場合は、 DigitalOcean Kubernetesクラスターへの接続方法を参照して、kubectl
を使用してクラスターに接続する方法を確認してください。- 登録されたドメイン名。 このチュートリアルでは、全体を通して
your_domain.com
を使用します。 Freenom で無料で入手するか、選択したドメインレジストラを使用できます。 - ingress-nginx IngressControllerとcert-manager TLS証明書マネージャーがクラスターにインストールされ、TLS証明書を発行するように構成されています。 cert-managerを使用してIngressをインストールおよび構成する方法については、 DigitalOceanKubernetesでCert-Managerを使用してNginxIngressを設定する方法を参照してください。
A
DNSレコード。your_domain.com
はIngressロードバランサーのパブリックIPアドレスを指しています。 DigitalOceanを使用してドメインのDNSレコードを管理している場合は、 DNSレコードの管理方法を参照して、A
レコードの作成方法を確認してください。- DigitalOcean Space などのS3オブジェクトストレージバケット。Djangoプロジェクトの静的ファイルと、このスペースのアクセスキーのセットを保存します。 スペースの作成方法については、スペースの作成方法の製品ドキュメントを参照してください。 スペースのアクセスキーを作成する方法については、アクセスキーを使用したスペースへのアクセスの共有を参照してください。 マイナーな変更により、django-storagesプラグインがサポートする任意のオブジェクトストレージサービスを使用できます。
- DjangoアプリのPostgreSQLサーバーインスタンス、データベース、およびユーザー。 小さな変更を加えるだけで、Djangoがサポートするのデータベースを使用できます。 PostgreSQLデータベースはpolls(または以下の構成ファイルに入力する別の覚えやすい名前)と呼ばれる必要があり、このチュートリアルでは、Djangoデータベースユーザーの名前はsammyになります。 これらを作成するためのガイダンスについては、Dockerを使用してDjangoおよびGunicornアプリケーションを構築する方法のステップ1に従ってください。 これらの手順は、ローカルマシンから実行する必要があります。 このチュートリアルでは、DigitalOceanマネージドPostgreSQLクラスターを使用します。 クラスタの作成方法については、DigitalOceanManagedDatabasesの製品ドキュメントを参照してください。 独自のPostgreSQLインスタンスをインストールして実行することもできます。 UbuntuサーバーにPostgreSQLをインストールして管理するためのガイダンスについては、Ubuntu18.04にPostgreSQLをインストールして使用する方法を参照してください。
- DockerHubアカウントとパブリックリポジトリ。 これらの作成の詳細については、Dockerドキュメントのリポジトリを参照してください。
- ローカルマシンにインストールされているDockerエンジン。 詳細については、 Ubuntu18.04にDockerをインストールして使用する方法を参照してください。
これらのコンポーネントを設定したら、このガイドを開始する準備が整います。
ステップ1—アプリケーションのクローン作成と構成
このステップでは、GitHubからアプリケーションコードを複製し、データベースのクレデンシャルやオブジェクトストレージキーなどの設定を構成します。
アプリケーションコードとDockerfileは、Django Tutorial Polls AppGitHubリポジトリのpolls-docker
ブランチにあります。 このリポジトリには、Djangoドキュメントのサンプルポーリングアプリケーションのコードが含まれています。このコードは、ポーリングアプリケーションを最初から作成する方法を示しています。
polls-docker
ブランチには、このPollsアプリのDocker化バージョンが含まれています。 コンテナ化された環境で効果的に機能するようにPollsアプリがどのように変更されたかについては、Dockerを使用してDjangoおよびGunicornアプリケーションを構築する方法を参照してください。
git
を使用して、Django Tutorial Polls AppGitHubリポジトリのpolls-docker
ブランチをローカルマシンに複製することから始めます。
git clone --single-branch --branch polls-docker https://github.com/do-community/django-polls.git
django-polls
ディレクトリに移動します。
cd django-polls
このディレクトリには、DjangoアプリケーションのPythonコード、Dockerがコンテナイメージのビルドに使用するDockerfile
、およびコンテナに渡される環境変数のリストを含むenv
ファイルが含まれています。実行環境。 Dockerfile
を調べます。
cat Dockerfile
OutputFROM python:3.7.4-alpine3.10 ADD django-polls/requirements.txt /app/requirements.txt RUN set -ex \ && apk add --no-cache --virtual .build-deps postgresql-dev build-base \ && python -m venv /env \ && /env/bin/pip install --upgrade pip \ && /env/bin/pip install --no-cache-dir -r /app/requirements.txt \ && runDeps="$(scanelf --needed --nobanner --recursive /env \ | awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \ | sort -u \ | xargs -r apk info --installed \ | sort -u)" \ && apk add --virtual rundeps $runDeps \ && apk del .build-deps ADD django-polls /app WORKDIR /app ENV VIRTUAL_ENV /env ENV PATH /env/bin:$PATH EXPOSE 8000 CMD ["gunicorn", "--bind", ":8000", "--workers", "3", "mysite.wsgi"]
このDockerfileは、公式のPython 3.7.4 Docker image をベースとして使用し、django-polls/requirements.txt
ファイルで定義されているDjangoおよびGunicornのPythonパッケージ要件をインストールします。 次に、不要なビルドファイルをいくつか削除し、アプリケーションコードをイメージにコピーして、実行を設定しますPATH
。 最後に、ポート8000
を使用して着信コンテナー接続を受け入れることを宣言し、ポート8000
でリッスンする3人のワーカーでgunicorn
を実行します。
このDockerfileの各ステップの詳細については、Dockerを使用してDjangoおよびGunicornアプリケーションを構築する方法のステップ6を参照してください。
次に、docker build
を使用してイメージをビルドします。
docker build -t polls .
-t
フラグを使用してイメージにpolls
という名前を付け、現在のディレクトリをビルドコンテキストとして渡します。これは、イメージを構築するときに参照するファイルのセットです。
Dockerがイメージをビルドしてタグ付けした後、docker images
を使用して使用可能なイメージを一覧表示します。
docker images
polls
の画像が表示されます。
OutputREPOSITORY TAG IMAGE ID CREATED SIZE polls latest 80ec4f33aae1 2 weeks ago 197MB python 3.7.4-alpine3.10 f309434dea3a 8 months ago 98.7MB
Djangoコンテナを実行する前に、現在のディレクトリにあるenv
ファイルを使用して実行環境を構成する必要があります。 このファイルは、コンテナーの実行に使用されるdocker run
コマンドに渡され、Dockerは構成された環境変数をコンテナーの実行環境に挿入します。
env
ファイルをnano
またはお気に入りのエディターで開きます。
nano env
django-polls / env
DJANGO_SECRET_KEY= DEBUG=True DJANGO_ALLOWED_HOSTS= DATABASE_ENGINE=postgresql_psycopg2 DATABASE_NAME=polls DATABASE_USERNAME= DATABASE_PASSWORD= DATABASE_HOST= DATABASE_PORT= STATIC_ACCESS_KEY_ID= STATIC_SECRET_KEY= STATIC_BUCKET_NAME= STATIC_ENDPOINT_URL= DJANGO_LOGLEVEL=info
次のキーの不足している値を入力します。
DJANGO_SECRET_KEY
: Django docs で詳しく説明されているように、これを一意の予測できない値に設定します。 このキーを生成する1つの方法は、 Scalable DjangoAppチュートリアルのAppSettingsの調整にあります。DJANGO_ALLOWED_HOSTS
:この変数はアプリを保護し、HTTPホストヘッダー攻撃を防ぎます。 テストのために、これを*
に設定します。これは、すべてのホストに一致するワイルドカードです。 本番環境では、これをyour_domain.com
に設定する必要があります。 このDjango設定の詳細については、Djangoドキュメントのコア設定を参照してください。DATABASE_USERNAME
:前提条件の手順で作成したPostgreSQLデータベースユーザーに設定します。DATABASE_NAME
:これをpolls
または前提条件の手順で作成したPostgreSQLデータベースの名前に設定します。DATABASE_PASSWORD
:これを前提条件の手順で作成したPostgreSQLユーザーパスワードに設定します。DATABASE_HOST
:これをデータベースのホスト名に設定します。DATABASE_PORT
:これをデータベースのポートに設定します。STATIC_ACCESS_KEY_ID
:これをスペースまたはオブジェクトストレージのアクセスキーに設定します。STATIC_SECRET_KEY
:これをスペースまたはオブジェクトストレージのアクセスキーシークレットに設定します。STATIC_BUCKET_NAME
:これをスペース名またはオブジェクトストレージバケットに設定します。STATIC_ENDPOINT_URL
:これを適切なスペースまたはオブジェクトストレージエンドポイントURLに設定します。たとえば、スペースがnyc3
リージョンにある場合は、https://your_space_name.nyc3.digitaloceanspaces.com
に設定します。
編集が終了したら、ファイルを保存して閉じます。
次のステップでは、構成されたコンテナーをローカルで実行し、データベーススキーマを作成します。 また、スタイルシートや画像などの静的アセットをオブジェクトストレージにアップロードします。
ステップ2—データベーススキーマの作成とオブジェクトストレージへのアセットのアップロード
コンテナを構築および構成したら、docker run
を使用してDockerfileに設定されているCMD
をオーバーライドし、manage.py makemigrations
およびmanage.py migrate
コマンドを使用してデータベーススキーマを作成します。
docker run --env-file env polls sh -c "python manage.py makemigrations && python manage.py migrate"
polls:latest
コンテナイメージを実行し、変更したばかりの環境変数ファイルを渡し、Dockerfileコマンドをsh -c "python manage.py makemigrations && python manage.py migrate"
でオーバーライドします。これにより、アプリコードで定義されたデータベーススキーマが作成されます。
これを初めて実行する場合は、次のように表示されます。
OutputNo changes detected Operations to perform: Apply all migrations: admin, auth, contenttypes, polls, sessions Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying admin.0003_logentry_add_action_flag_choices... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying auth.0010_alter_group_name_max_length... OK Applying auth.0011_update_proxy_permissions... OK Applying polls.0001_initial... OK Applying sessions.0001_initial... OK
これは、データベーススキーマが正常に作成されたことを示します。
後でmigrate
を実行している場合、データベーススキーマが変更されていない限り、Djangoはno-opを実行します。
次に、アプリコンテナーの別のインスタンスを実行し、その中のインタラクティブシェルを使用して、Djangoプロジェクトの管理ユーザーを作成します。
docker run -i -t --env-file env polls sh
これにより、実行中のコンテナ内にシェルプロンプトが表示され、Djangoユーザーの作成に使用できます。
python manage.py createsuperuser
ユーザーのユーザー名、メールアドレス、パスワードを入力し、ユーザーを作成したら、CTRL+D
を押してコンテナーを終了して強制終了します。
最後に、アプリの静的ファイルを生成し、collectstatic
を使用してDigitalOceanSpaceにアップロードします。 これが完了するまでに少し時間がかかる場合があることに注意してください。
docker run --env-file env polls sh -c "python manage.py collectstatic --noinput"
これらのファイルが生成およびアップロードされると、次の出力が表示されます。
Output121 static files copied.
これでアプリを実行できます。
docker run --env-file env -p 80:8000 polls
Output[2019-10-17 21:23:36 +0000] [1] [INFO] Starting gunicorn 19.9.0 [2019-10-17 21:23:36 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1) [2019-10-17 21:23:36 +0000] [1] [INFO] Using worker: sync [2019-10-17 21:23:36 +0000] [7] [INFO] Booting worker with pid: 7 [2019-10-17 21:23:36 +0000] [8] [INFO] Booting worker with pid: 8 [2019-10-17 21:23:36 +0000] [9] [INFO] Booting worker with pid: 9
ここでは、Dockerfileで定義されているデフォルトのコマンドgunicorn --bind :8000 --workers 3 mysite.wsgi:application
を実行し、コンテナポート8000
を公開して、ローカルマシンのポート80
がポート[にマップされるようにします。 polls
コンテナのX176X]。
これで、URLバーにhttp://localhost
と入力して、Webブラウザーを使用してpolls
アプリに移動できるようになります。 /
パスにルートが定義されていないため、404 Page Not Found
エラーが発生する可能性があります。これは予想どおりです。
http://localhost/polls
に移動して、Pollsアプリのインターフェイスを確認します。
管理インターフェースを表示するには、http://localhost/admin
にアクセスしてください。 Pollsアプリの管理者認証ウィンドウが表示されます。
createsuperuser
コマンドで作成した管理者のユーザー名とパスワードを入力します。
認証後、Pollsアプリの管理インターフェースにアクセスできます。
admin
およびpolls
アプリの静的アセットは、オブジェクトストレージから直接配信されていることに注意してください。 これを確認するには、テストスペースの静的ファイル配信を参照してください。
探索が終了したら、Dockerコンテナを実行しているターミナルウィンドウでCTRL+C
を押して、コンテナを強制終了します。
DjangoアプリのDockerイメージをテストし、静的アセットをオブジェクトストレージにアップロードし、データベーススキーマを構成してアプリで使用できるようになったら、DjangoアプリのイメージをDockerHubなどのイメージレジストリにアップロードする準備が整います。
ステップ3—DjangoアプリイメージをDockerHubにプッシュする
Kubernetesでアプリをロールアウトするには、アプリの画像を DockerHubなどのレジストリにアップロードする必要があります。 Kubernetesは、リポジトリからアプリイメージをプルしてから、クラスターにデプロイします。
DigitalOcean Container Registry のようなプライベートDockerレジストリを使用できます。これは、現在早期アクセスで無料です。または、DockerHubのようなパブリックDockerレジストリを使用できます。 Docker Hubでは、プライベートDockerリポジトリを作成することもできます。 パブリックリポジトリを使用すると、誰でもコンテナイメージを表示およびプルできますが、プライベートリポジトリを使用すると、自分とチームメンバーへのアクセスを制限できます。
このチュートリアルでは、前提条件で作成されたパブリックDockerHubリポジトリにDjangoイメージをプッシュします。 イメージをプライベートリポジトリにプッシュすることもできますが、プライベートリポジトリからイメージをプルすることはこの記事の範囲を超えています。 Docker Hubを使用したKubernetesの認証とプライベートイメージのプルについて詳しくは、Kubernetesドキュメントのプライベートレジストリからイメージをプルするをご覧ください。
まず、ローカルマシンのDockerHubにログインします。
docker login
OutputLogin with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. Username:
DockerHubのユーザー名とパスワードを入力してログインします。
Djangoイメージには、現在polls:latest
タグが付いています。 Docker Hubリポジトリにプッシュするには、DockerHubのユーザー名とリポジトリ名でイメージにタグを付け直します。
docker tag polls:latest your_dockerhub_username/your_dockerhub_repo_name:latest
画像をリポジトリにプッシュします。
docker push sammy/sammy-django:latest
このチュートリアルでは、DockerHubのユーザー名はsammy で、リポジトリ名はsammy-djangoです。 これらの値を独自のDockerHubユーザー名とリポジトリ名に置き換える必要があります。
画像レイヤーがDockerHubにプッシュされると更新される出力が表示されます。
これで、Docker Hub上のKubernetesでイメージを利用できるようになったので、クラスターでイメージのロールアウトを開始できます。
ステップ4—ConfigMapを設定する
Djangoコンテナーをローカルで実行するときに、env
ファイルをdocker run
に渡して、構成変数をランタイム環境に挿入しました。 Kubernetesでは、ConfigMapsおよびSecretsを使用して構成変数を挿入できます。
ConfigMapsは、アプリ設定などの機密でない構成情報を格納するために使用する必要があり、Secretsは、APIキーやデータベースクレデンシャルなどの機密情報に使用する必要があります。 どちらも同様の方法でコンテナに挿入されますが、シークレットには、保存時の暗号化などの追加のアクセス制御とセキュリティ機能があります。 シークレットはbase64にもデータを保存しますが、ConfigMapsはデータをプレーンテキストで保存します。
まず、Kubernetesマニフェストを保存するyaml
というディレクトリを作成します。 ディレクトリに移動します。
mkdir yaml cd
nano
またはお好みのテキストエディタでpolls-configmap.yaml
というファイルを開きます。
nano polls-configmap.yaml
次のConfigMapマニフェストに貼り付けます。
polls-configmap.yaml
apiVersion: v1 kind: ConfigMap metadata: name: polls-config data: DJANGO_ALLOWED_HOSTS: "*" STATIC_ENDPOINT_URL: "https://your_space_name.space_region.digitaloceanspaces.com" STATIC_BUCKET_NAME: "your_space_name" DJANGO_LOGLEVEL: "info" DEBUG: "True" DATABASE_ENGINE: "postgresql_psycopg2"
ステップ1で変更されたenv
ファイルから機密性の低い構成を抽出し、ConfigMapマニフェストに貼り付けました。 ConfigMapオブジェクトはpolls-config
と呼ばれます。 前の手順でenv
ファイルに入力したのと同じ値をコピーします。
テストのために、DJANGO_ALLOWED_HOSTS
を*
のままにして、ホストヘッダーベースのフィルタリングを無効にします。 本番環境では、これをアプリのドメインに設定する必要があります。
ファイルの編集が完了したら、ファイルを保存して閉じます。
kubectl apply
を使用して、クラスターにConfigMapを作成します。
kubectl apply -f polls-configmap.yaml
Outputconfigmap/polls-config created
ConfigMapを作成したら、次のステップでアプリが使用するシークレットを作成します。
ステップ5—秘密を設定する
シークレット値はbase64エンコードである必要があります。つまり、クラスターでのシークレットオブジェクトの作成は、ConfigMapの作成よりも少し複雑です。 シークレット値を手動でbase64エンコードし、マニフェストファイルに貼り付けることで、前の手順からプロセスを繰り返すことができます。 また、環境変数ファイルkubectl create
、および--from-env-file
フラグを使用して作成することもできます。これは、このステップで行います。
ステップ1のenv
ファイルをもう一度使用して、ConfigMapに挿入された変数を削除します。 yaml
ディレクトリにpolls-secrets
という名前のenv
ファイルのコピーを作成します。
cp ../env ./polls-secrets
お好みのエディタでファイルを編集します。
nano polls-secrets
世論調査-秘密
DJANGO_SECRET_KEY= DEBUG=True DJANGO_ALLOWED_HOSTS= DATABASE_ENGINE=postgresql_psycopg2 DATABASE_NAME=polls DATABASE_USERNAME= DATABASE_PASSWORD= DATABASE_HOST= DATABASE_PORT= STATIC_ACCESS_KEY_ID= STATIC_SECRET_KEY= STATIC_BUCKET_NAME= STATIC_ENDPOINT_URL= DJANGO_LOGLEVEL=info
ConfigMapマニフェストに挿入されたすべての変数を削除します。 完了すると、次のようになります。
世論調査-秘密
DJANGO_SECRET_KEY=your_secret_key DATABASE_NAME=polls DATABASE_USERNAME=your_django_db_user DATABASE_PASSWORD=your_django_db_user_password DATABASE_HOST=your_db_host DATABASE_PORT=your_db_port STATIC_ACCESS_KEY_ID=your_space_access_key STATIC_SECRET_KEY=your_space_access_key_secret
ステップ1で使用したのと同じ値を使用してください。 完了したら、ファイルを保存して閉じます。
kubectl create secret
を使用して、クラスターにシークレットを作成します。
kubectl create secret generic polls-secret --from-env-file=poll-secrets
Outputsecret/polls-secret created
ここでは、polls-secret
というシークレットオブジェクトを作成し、作成したシークレットファイルを渡します。
kubectl describe
を使用してシークレットを検査できます。
kubectl describe secret polls-secret
OutputName: polls-secret Namespace: default Labels: <none> Annotations: <none> Type: Opaque Data ==== DATABASE_PASSWORD: 8 bytes DATABASE_PORT: 5 bytes DATABASE_USERNAME: 5 bytes DJANGO_SECRET_KEY: 14 bytes STATIC_ACCESS_KEY_ID: 20 bytes STATIC_SECRET_KEY: 43 bytes DATABASE_HOST: 47 bytes DATABASE_NAME: 5 bytes
この時点で、SecretオブジェクトタイプとConfigMapオブジェクトタイプを使用して、アプリの構成をKubernetesクラスターに保存しました。 これで、アプリをクラスターにデプロイする準備が整いました。
ステップ6—デプロイメントを使用してDjangoアプリをロールアウトする
このステップでは、Djangoアプリのデプロイを作成します。 Kubernetes Deploymentは、クラスター内のステートレスアプリケーションを管理するために使用できるコントローラーです。 コントローラは、ワークロードをスケールアップまたはスケールダウンすることによってワークロードを調整する制御ループです。 コントローラも再起動し、障害が発生したコンテナをクリアします。
デプロイは、Kubernetesクラスター内のデプロイ可能な最小ユニットである1つ以上のポッドを制御します。 ポッドは1つ以上のコンテナを囲みます。 起動できるさまざまなタイプのワークロードの詳細については、Kubernetesの概要をご覧ください。
お気に入りのエディターでpolls-deployment.yaml
というファイルを開くことから始めます。
nano polls-deployment.yaml
次のデプロイメントマニフェストに貼り付けます。
polls-deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: polls-app labels: app: polls spec: replicas: 2 selector: matchLabels: app: polls template: metadata: labels: app: polls spec: containers: - image: your_dockerhub_username/app_repo_name:latest name: polls envFrom: - secretRef: name: polls-secret - configMapRef: name: polls-config ports: - containerPort: 8000 name: gunicorn
ステップ2でDockerHubにプッシュしたDjangoPollsイメージを参照して、適切なコンテナーイメージ名を入力します。
ここでは、polls-app
というKubernetesデプロイメントを定義し、キーと値のペアapp: polls
でラベルを付けます。 template
フィールドの下に定義されたポッドの2つのレプリカを実行することを指定します。
envFrom
とsecretRef
およびconfigMapRef
を使用して、polls-secret
シークレットおよびpolls-config
ConfigMapからのすべてのデータを環境変数としてのコンテナ。 ConfigMapキーとSecretキーが環境変数名になります。
最後に、containerPort
8000
を公開し、gunicorn
という名前を付けます。
Kubernetesデプロイの設定の詳細については、Kubernetesドキュメントのデプロイを参照してください。
ファイルの編集が完了したら、ファイルを保存して閉じます。
kubectl apply -f
を使用して、クラスターにデプロイメントを作成します。
kubectl apply -f polls-deployment.yaml
deployment.apps/polls-app created
kubectl get
を使用して、展開が正しく展開されたことを確認します。
kubectl get deploy polls-app
OutputNAME READY UP-TO-DATE AVAILABLE AGE polls-app 2/2 2 2 6m38s
エラーが発生した場合、または何かがうまく機能していない場合は、kubectl describe
を使用して、失敗したデプロイメントを検査できます。
kubectl describe deploy
kubectl get pod
を使用して2つのポッドを検査できます。
kubectl get pod
OutputNAME READY STATUS RESTARTS AGE polls-app-847f8ccbf4-2stf7 1/1 Running 0 6m42s polls-app-847f8ccbf4-tqpwm 1/1 Running 0 6m57s
これで、Djangoアプリの2つのレプリカがクラスターで稼働しています。 アプリにアクセスするには、Kubernetesサービスを作成する必要があります。これを次に行います。
ステップ7—サービスを使用した外部アクセスの許可
このステップでは、Djangoアプリのサービスを作成します。 Kubernetesサービスは、実行中のポッドのセットをネットワークサービスとして公開できるようにする抽象化です。 サービスを使用すると、ポッドが停止して再作成されても変更されない、アプリの安定したエンドポイントを作成できます。
クラスター内部IPでサービスを公開するClusterIPサービス、NodePortと呼ばれる静的ポートで各ノードのサービスを公開するNodePortサービス、クラウドロードバランサーをプロビジョニングするLoadBalancerサービスなど、複数のサービスタイプがあります。外部トラフィックをクラスター内のポッドに転送します(NodePortsを介して自動的に作成されます)。 これらの詳細については、Kubernetesドキュメントのサービスをご覧ください。
最終的なセットアップでは、このガイドの前提条件でセットアップされたIngressとIngressControllerを使用して公開されるClusterIPサービスを使用します。 今のところ、すべてが正しく機能していることをテストするために、Djangoアプリにアクセスするための一時的なNodePortサービスを作成します。
お気に入りのエディターを使用して、polls-svc.yaml
というファイルを作成することから始めます。
nano polls-svc.yaml
次のサービスマニフェストに貼り付けます。
polls-svc.yaml
apiVersion: v1 kind: Service metadata: name: polls labels: app: polls spec: type: NodePort selector: app: polls ports: - port: 8000 targetPort: 8000
ここでは、polls
というNodePortサービスを作成し、それにapp: polls
ラベルを付けます。 次に、app: polls
ラベルの付いたバックエンドポッドを選択し、それらの8000
ポートをターゲットにします。
ファイルの編集が完了したら、ファイルを保存して閉じます。
kubectl apply
を使用してサービスを展開します。
kubectl apply -f polls-svc.yaml
Outputservice/polls created
kubectl get svc
を使用してサービスが作成されたことを確認します。
kubectl get svc polls
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE polls NodePort 10.245.197.189 <none> 8000:32654/TCP 59s
この出力は、サービスのクラスター内部IPおよびNodePort(32654
)を示しています。 サービスに接続するには、クラスターノードの外部IPアドレスが必要です。
kubectl get node -o wide
OutputNAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME pool-7no0qd9e0-364fd Ready <none> 27h v1.18.8 10.118.0.5 203.0.113.1 Debian GNU/Linux 10 (buster) 4.19.0-10-cloud-amd64 docker://18.9.9 pool-7no0qd9e0-364fi Ready <none> 27h v1.18.8 10.118.0.4 203.0.113.2 Debian GNU/Linux 10 (buster) 4.19.0-10-cloud-amd64 docker://18.9.9 pool-7no0qd9e0-364fv Ready <none> 27h v1.18.8 10.118.0.3 203.0.113.3 Debian GNU/Linux 10 (buster) 4.19.0-10-cloud-amd64 docker://18.9.9
Webブラウザーで、任意のノードの外部IPアドレスとNodePortを使用してPollsアプリにアクセスします。 上記の出力を考えると、アプリのURLはhttp://203.0.113.1:32654/polls
になります。
手順1でローカルにアクセスしたものと同じPollsアプリのインターフェースが表示されます。
/admin
ルートhttp://203.0.113.1:32654/admin
を使用して同じテストを繰り返すことができます。 以前と同じ管理インターフェースが表示されます。
この段階で、Deploymentを使用してDjangoPollsアプリコンテナーの2つのレプリカをロールアウトしました。 また、これら2つのレプリカ用の安定したネットワークエンドポイントを作成し、NodePortサービスを使用して外部からアクセスできるようにしました。
このチュートリアルの最後のステップは、HTTPSを使用してアプリへの外部トラフィックを保護することです。 これを行うには、前提条件にインストールされているingress-nginx
Ingress Controllerを使用し、Ingressオブジェクトを作成して外部トラフィックをpolls
Kubernetesサービスにルーティングします。
ステップ8—NginxIngressとcert-managerを使用したHTTPSの構成
Kubernetes Ingresses を使用すると、Kubernetesクラスターの外部からクラスター内のサービスにトラフィックを柔軟にルーティングできます。 これは、HTTPおよびHTTPSトラフィックをKubernetesサービスにルーティングするためのルールを定義するIngressオブジェクトと、トラフィックを負荷分散して適切なバックエンドサービスにルーティングすることでルールを実装するIngress Controllersを使用して実現されます。
前提条件で、 ingress-nginx IngressControllerとcert-managerTLS証明書自動化アドオンをインストールしました。 また、Let's Encrypt認証局を使用して、ドメインのステージングおよび本番ClusterIssuersを設定し、2つのダミーバックエンドサービスへの証明書発行とTLS暗号化をテストするためのIngressを作成しました。 この手順を続行する前に、前提条件のチュートリアルで作成されたecho-ingress
入力を削除する必要があります。
kubectl delete ingress echo-ingress
必要に応じて、kubectl delete svc
およびkubectl delete deploy
を使用してダミーのサービスとデプロイメントを削除することもできますが、これはこのチュートリアルを完了するために必須ではありません。
また、IngressLoadBalancerのパブリックIPアドレスを指すyour_domain.com
を使用してDNSA
レコードを作成する必要があります。 DigitalOceanロードバランサーを使用している場合、このIPアドレスはコントロールパネルのロードバランサーセクションにあります。 DigitalOceanを使用してドメインのDNSレコードも管理している場合は、 DNSレコードの管理方法を参照して、A
レコードの作成方法を確認してください。
DigitalOcean Kubernetesを使用している場合は、 DigitalOceanKubernetesでCert-Managerを使用してNginxIngressを設定する方法のステップ5で説明されている回避策を実装していることも確認してください。
Ingress Controller LoadBalancerを指すA
レコードを取得したら、your_domain.com
およびpolls
サービスのIngressを作成できます。
お気に入りのエディタを使用して、polls-ingress.yaml
というファイルを開きます。
nano polls-ingress.yaml
次のIngressマニフェストに貼り付けます。
[polls-ingress.yaml] apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: polls-ingress annotations: kubernetes.io/ingress.class: "nginx" cert-manager.io/cluster-issuer: "letsencrypt-staging" spec: tls: - hosts: - your_domain.com secretName: polls-tls rules: - host: your_domain.com http: paths: - backend: serviceName: polls servicePort: 8000
polls-ingress
というIngressオブジェクトを作成し、それに注釈を付けて、コントロールプレーンにingress-nginxIngressControllerとステージングClusterIssuerを使用するように指示します。 また、your_domain.com
のTLSを有効にし、証明書と秘密鍵をpolls-tls
という秘密に保存します。 最後に、your_domain.com
ホストのトラフィックをポート8000
のpolls
サービスにルーティングするルールを定義します。
ファイルの編集が完了したら、ファイルを保存して閉じます。
kubectl apply
を使用して、クラスターに入力を作成します。
kubectl apply -f polls-ingress.yaml
Outputingress.networking.k8s.io/polls-ingress created
kubectl describe
を使用して、作成したばかりのイングレスの状態を追跡できます。
kubectl describe ingress polls-ingress
OutputName: polls-ingress Namespace: default Address: workaround.your_domain.com Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>) TLS: polls-tls terminates your_domain.com Rules: Host Path Backends ---- ---- -------- your_domain.com polls:8000 (10.244.0.207:8000,10.244.0.53:8000) Annotations: cert-manager.io/cluster-issuer: letsencrypt-staging kubernetes.io/ingress.class: nginx Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal CREATE 51s nginx-ingress-controller Ingress default/polls-ingress Normal CreateCertificate 51s cert-manager Successfully created Certificate "polls-tls" Normal UPDATE 25s nginx-ingress-controller Ingress default/polls-ingress
polls-tls
証明書でdescribe
を実行して、作成が成功したことをさらに確認することもできます。
kubectl describe certificate polls-tls
Output. . . Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Issuing 3m33s cert-manager Issuing certificate as Secret does not exist Normal Generated 3m32s cert-manager Stored new private key in temporary Secret resource "polls-tls-v9lv9" Normal Requested 3m32s cert-manager Created new CertificateRequest resource "polls-tls-drx9c" Normal Issuing 2m58s cert-manager The certificate has been successfully issued
これにより、TLS証明書が正常に発行され、your_domain.com
に対してHTTPS暗号化がアクティブになったことを確認できます。
ステージングClusterIssuerを使用した場合、ほとんどのWebブラウザーは、発行した偽のLet's Encrypt証明書を信頼しないため、your_domain.com
に移動するとエラーページが表示されます。
テストリクエストを送信するには、コマンドラインからwget
を使用します。
wget -O - http://your_domain.com/polls
Output. . . ERROR: cannot verify your_domain.com's certificate, issued by ‘CN=Fake LE Intermediate X1’: Unable to locally verify the issuer's authority. To connect to your_domain.com insecurely, use `--no-check-certificate'.
提案された--no-check-certificate
フラグを使用して、証明書の検証をバイパスします。
wget --no-check-certificate -q -O - http://your_domain.com/polls
Output <link rel="stylesheet" type="text/css" href="https://your_space.nyc3.digitaloceanspaces.com/django-polls/static/polls/style.css"> <p>No polls are available.</p>
この出力には、/polls
インターフェイスページのHTMLが表示され、スタイルシートがオブジェクトストレージから提供されていることも確認されます。
ステージングClusterIssuerを使用して証明書の発行を正常にテストしたので、本番ClusterIssuerを使用するようにIngressを変更できます。
polls-ingress.yaml
を開いて、もう一度編集します。
nano polls-ingress.yaml
cluster-issuer
注釈を変更します。
[polls-ingress.yaml] apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: polls-ingress annotations: kubernetes.io/ingress.class: "nginx" cert-manager.io/cluster-issuer: "letsencrypt-prod" spec: tls: - hosts: - your_domain.com secretName: polls-tls rules: - host: your_domain.com http: paths: - backend: serviceName: polls servicePort: 8000
完了したら、ファイルを保存して閉じます。 kubectl apply
を使用して入力を更新します。
kubectl apply -f polls-ingress.yaml
Outputingress.networking.k8s.io/polls-ingress configured
kubectl describe certificate polls-tls
およびkubectl describe ingress polls-ingress
を使用して、証明書の発行ステータスを追跡できます。
kubectl describe ingress polls-ingress
Output. . . Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal CREATE 23m nginx-ingress-controller Ingress default/polls-ingress Normal CreateCertificate 23m cert-manager Successfully created Certificate "polls-tls" Normal UPDATE 76s (x2 over 22m) nginx-ingress-controller Ingress default/polls-ingress Normal UpdateCertificate 76s cert-manager Successfully updated Certificate "polls-tls"
上記の出力は、新しい本番証明書が正常に発行され、polls-tls
シークレットに保存されたことを確認します。
Webブラウザでyour_domain.com/polls
に移動して、HTTPS暗号化が有効になっていて、すべてが期待どおりに機能していることを確認します。 Pollsアプリのインターフェースが表示されます。
WebブラウザでHTTPS暗号化がアクティブになっていることを確認します。 Google Chromeを使用している場合、エラーなしで上記のページにアクセスすると、すべてが正しく機能していることが確認されます。 さらに、URLバーに南京錠が表示されます。 南京錠をクリックすると、Let'sEncrypt証明書の詳細を調べることができます。
最後のクリーンアップタスクとして、オプションでpolls
サービスタイプをNodePortから内部専用のClusterIPタイプに切り替えることができます。
エディタを使用してpolls-svc.yaml
を変更します。
nano polls-svc.yaml
type
をNodePort
からClusterIP
に変更します。
polls-svc.yaml
apiVersion: v1 kind: Service metadata: name: polls labels: app: polls spec: type: ClusterIP selector: app: polls ports: - port: 8000 targetPort: 8000
ファイルの編集が完了したら、ファイルを保存して閉じます。
kubectl apply
を使用して変更をロールアウトします。
kubectl apply -f polls-svc.yaml --force
Outputservice/polls configured
kubectl get svc
を使用してサービスが変更されたことを確認します。
kubectl get svc polls
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE polls ClusterIP 10.245.203.186 <none> 8000/TCP 22s
この出力は、サービスタイプがClusterIPになったことを示しています。 アクセスする唯一の方法は、ドメインとこのステップで作成したIngressを経由することです。
結論
このチュートリアルでは、HTTPSで保護されたスケーラブルなDjangoアプリをKubernetesクラスターにデプロイしました。 静的コンテンツはオブジェクトストレージから直接提供され、実行中のポッドの数は、polls-app
デプロイメントマニフェストのreplicas
フィールドを使用してすばやくスケールアップまたはスケールダウンできます。
DigitalOcean Spaceを使用している場合は、コンテンツ配信ネットワークを介した静的アセットの配信を有効にして、Spaceのカスタムサブドメインを作成することもできます。 詳細については、 DigitalOceanマネージドデータベースとスペースを使用してスケーラブルなDjangoアプリをセットアップする方法から、CDNを有効にするを参照してください。
シリーズの残りの部分を確認するには、コンテナからKuberneteswithDjangoシリーズページにアクセスしてください。