序章

このチュートリアルでは、コンテナ化された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を設定する方法を参照してください。
  • ADNSレコード。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ブランチをローカルマシンに複製することから始めます。

  1. git clone --single-branch --branch polls-docker https://github.com/do-community/django-polls.git

django-pollsディレクトリに移動します。

  1. cd django-polls

このディレクトリには、DjangoアプリケーションのPythonコード、Dockerがコンテナイメージのビルドに使用するDockerfile、およびコンテナに渡される環境変数のリストを含むenvファイルが含まれています。実行環境。 Dockerfileを調べます。

  1. cat Dockerfile
Output
FROM 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を使用してイメージをビルドします。

  1. docker build -t polls .

-tフラグを使用してイメージにpollsという名前を付け、現在のディレクトリをビルドコンテキストとして渡します。これは、イメージを構築するときに参照するファイルのセットです。

Dockerがイメージをビルドしてタグ付けした後、docker imagesを使用して使用可能なイメージを一覧表示します。

  1. 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またはお気に入りのエディターで開きます。

  1. 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コマンドを使用してデータベーススキーマを作成します。

  1. 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"でオーバーライドします。これにより、アプリコードで定義されたデータベーススキーマが作成されます。

これを初めて実行する場合は、次のように表示されます。

Output
No 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プロジェクトの管理ユーザーを作成します。

  1. docker run -i -t --env-file env polls sh

これにより、実行中のコンテナー内にシェルプロンプトが表示され、Djangoユーザーの作成に使用できます。

  1. python manage.py createsuperuser

ユーザーのユーザー名、メールアドレス、パスワードを入力し、ユーザーを作成したら、CTRL+Dを押してコンテナーを終了して強制終了します。

最後に、アプリの静的ファイルを生成し、collectstaticを使用してDigitalOceanSpaceにアップロードします。 これが完了するまでに少し時間がかかる場合があることに注意してください。

  1. docker run --env-file env polls sh -c "python manage.py collectstatic --noinput"

これらのファイルが生成されてアップロードされると、次の出力が表示されます。

Output
121 static files copied.

これでアプリを実行できます。

  1. 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アプリのインターフェースを確認します。

Polls Apps Interface

管理インターフェースを表示するには、http://localhost/adminにアクセスしてください。 Pollsアプリの管理者認証ウィンドウが表示されます。

Polls Admin Auth Page

createsuperuserコマンドで作成した管理ユーザー名とパスワードを入力します。

認証後、Pollsアプリの管理インターフェースにアクセスできます。

Polls Admin Main Interface

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にログインします。

  1. docker login
Output
Login 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のユーザー名とリポジトリ名でイメージにタグを付け直します。

  1. docker tag polls:latest your_dockerhub_username/your_dockerhub_repo_name:latest

画像をリポジトリにプッシュします。

  1. 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というディレクトリを作成します。 ディレクトリに移動します。

  1. mkdir yaml
  2. cd

nanoまたはお好みのテキストエディタでpolls-configmap.yamlというファイルを開きます。

  1. 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を作成します。

  1. kubectl apply -f polls-configmap.yaml
Output
configmap/polls-config created

ConfigMapを作成したら、次のステップでアプリが使用するシークレットを作成します。

ステップ5—秘密を設定する

シークレット値はbase64エンコードである必要があります。つまり、クラスターでのシークレットオブジェクトの作成は、ConfigMapの作成よりも少し複雑です。 シークレット値を手動でbase64エンコードし、マニフェストファイルに貼り付けることで、前の手順からプロセスを繰り返すことができます。 また、環境変数ファイルkubectl create、および--from-env-fileフラグを使用して作成することもできます。これは、このステップで行います。

ステップ1envファイルをもう一度使用して、ConfigMapに挿入された変数を削除します。 yamlディレクトリにpolls-secretsという名前のenvファイルのコピーを作成します。

  1. cp ../env ./polls-secrets

お好みのエディタでファイルを編集します。

  1. 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を使用して、クラスターにシークレットを作成します。

  1. kubectl create secret generic polls-secret --from-env-file=poll-secrets
Output
secret/polls-secret created

ここでは、polls-secretというシークレットオブジェクトを作成し、作成したシークレットファイルを渡します。

kubectl describeを使用してシークレットを検査できます。

  1. kubectl describe secret polls-secret
Output
Name: 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というファイルを開くことから始めます。

  1. 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つのレプリカを実行することを指定します。

envFromsecretRefおよびconfigMapRefを使用して、polls-secretシークレットおよびpolls-configConfigMapからのすべてのデータを環境変数としてのコンテナ。 ConfigMapキーとSecretキーが環境変数名になります。

最後に、containerPort 8000を公開し、gunicornという名前を付けます。

Kubernetesデプロイメントの設定の詳細については、KubernetesドキュメントのDeploymentsを参照してください。

ファイルの編集が完了したら、ファイルを保存して閉じます。

kubectl apply -fを使用して、クラスターにデプロイメントを作成します。

  1. kubectl apply -f polls-deployment.yaml
  1. deployment.apps/polls-app created

kubectl getを使用して、展開が正しく展開されたことを確認します。

  1. kubectl get deploy polls-app
Output
NAME READY UP-TO-DATE AVAILABLE AGE polls-app 2/2 2 2 6m38s

エラーが発生した場合、または何かがうまく機能していない場合は、kubectl describeを使用して、失敗したデプロイメントを検査できます。

  1. kubectl describe deploy

kubectl get podを使用して2つのポッドを検査できます。

  1. kubectl get pod
Output
NAME 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というファイルを作成することから始めます。

  1. nano polls-svc.yaml

次のサービスマニフェストに貼り付けます。

投票-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を使用してサービスを展開します。

  1. kubectl apply -f polls-svc.yaml
Output
service/polls created

kubectl get svcを使用してサービスが作成されたことを確認します。

  1. kubectl get svc polls
Output
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE polls NodePort 10.245.197.189 <none> 8000:32654/TCP 59s

この出力は、サービスのクラスター内部IPとNodePort(32654)を示しています。 サービスに接続するには、クラスターノードの外部IPアドレスが必要です。

  1. kubectl get node -o wide
Output
NAME 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アプリのインターフェースが表示されます。

Polls Apps Interface

/adminルートhttp://203.0.113.1:32654/adminを使用して同じテストを繰り返すことができます。 以前と同じ管理インターフェースが表示されます。

Polls Admin Auth Page

この段階で、Deploymentを使用してDjangoPollsアプリコンテナーの2つのレプリカをロールアウトしました。 また、これら2つのレプリカの安定したネットワークエンドポイントを作成し、NodePortサービスを使用して外部からアクセスできるようにしました。

このチュートリアルの最後のステップは、HTTPSを使用してアプリへの外部トラフィックを保護することです。 これを行うには、前提条件にインストールされているingress-nginx Ingress Controllerを使用し、Ingressオブジェクトを作成して外部トラフィックをpollsKubernetesサービスにルーティングします。

ステップ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入力を削除する必要があります。

  1. 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というファイルを開きます。

  1. 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ホストのトラフィックをポート8000pollsサービスにルーティングするルールを定義します。

ファイルの編集が完了したら、ファイルを保存して閉じます。

kubectl applyを使用して、クラスターに入力を作成します。

  1. kubectl apply -f polls-ingress.yaml
Output
ingress.networking.k8s.io/polls-ingress created

kubectl describeを使用して、作成したばかりのイングレスの状態を追跡できます。

  1. kubectl describe ingress polls-ingress
Output
Name: 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を実行して、作成が成功したことをさらに確認することもできます。

  1. 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を使用します。

  1. 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フラグを使用して、証明書の検証をバイパスします。

  1. 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を開いて、もう一度編集します。

  1. 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を使用して入力を更新します。

  1. kubectl apply -f polls-ingress.yaml
Output
ingress.networking.k8s.io/polls-ingress configured

kubectl describe certificate polls-tlsおよびkubectl describe ingress polls-ingressを使用して、証明書の発行ステータスを追跡できます。

  1. 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アプリのインターフェースが表示されます。

Polls Apps Interface

WebブラウザでHTTPS暗号化がアクティブになっていることを確認します。 Google Chromeを使用している場合、エラーなしで上記のページにアクセスすると、すべてが正しく機能していることが確認されます。 さらに、URLバーに南京錠が表示されます。 南京錠をクリックすると、Let’sEncrypt証明書の詳細を調べることができます。

最後のクリーンアップタスクとして、オプションでpollsサービスタイプをNodePortから内部専用のClusterIPタイプに切り替えることができます。

エディタを使用してpolls-svc.yamlを変更します。

  1. nano polls-svc.yaml

typeNodePortからClusterIPに変更します。

投票-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を使用して変更をロールアウトします。

  1. kubectl apply -f polls-svc.yaml --force
Output
service/polls configured

kubectl get svcを使用してサービスが変更されたことを確認します。

  1. kubectl get svc polls
Output
NAME 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シリーズページにアクセスしてください。