Google Kubernetes Engine での Django の実行

Google Kubernetes Engine(GKE)で動作する Django アプリは、Google のすべてのプロダクトに共通のインフラストラクチャで実行されるため、良好にスケールします。

このチュートリアルは、Django ウェブ開発の知識があることを前提としています。Django 開発を初めて使用する場合は、続行する前に最初の Django アプリを作成するを実施することをおすすめします。このチュートリアルでは、アプリのモデルは質問からなるアンケートで、Django 管理コンソールを使用してモデルを操作できます。

このチュートリアルには Python 2.7 または 3.4 以降が必要です。 また、Docker もインストールする必要があります。

準備

  1. Google アカウントにログインします。

    Google アカウントをまだお持ちでない場合は、新しいアカウントを登録します。

  2. Cloud Console のプロジェクト セレクタページで、Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタのページに移動

  3. Google Cloud プロジェクトに対して課金が有効になっていることを確認します。プロジェクトに対して課金が有効になっていることを確認する方法を学習する

  4. Cloud SQL, and Compute Engine API を有効にします。

    API を有効にする

  5. Cloud SDK をインストールして初期化します。

アプリをダウンロードし、実行する

事前準備が完了したら、Django サンプルアプリをダウンロードして実行します。以降のセクションでは、アプリの構成、実行、デプロイの手順を順番に説明します。

Django アプリのクローンを作成する

Django サンプルアプリのコードは、GitHub の GoogleCloudPlatform/python-docs-samples リポジトリにあります。

  1. 次のコマンドを使用して、zip ファイルとしてサンプルをダウンロードして展開するか、ローカルマシンにリポジトリのクローンを作成します。

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
    
  2. サンプルコードが入っているディレクトリに移動します。

    cd python-docs-samples/kubernetes_engine/django_tutorial
    

ローカル環境の設定

デプロイされたアプリは、App Engine 環境に組み込まれている Cloud SQL Proxy を使用して Cloud SQL インスタンスと通信します。ただし、アプリをローカルでテストするには、プロキシのローカルコピーを開発環境にインストールして使用する必要があります。

詳しくは Cloud SQL Proxy をご覧ください。

Cloud SQL インスタンスに対する基本的な管理タスクを行うには、PostgreSQL クライアントを使用します。

Cloud SQL Admin API の有効化

Cloud SQL を使用する前に、Cloud SQL Admin API を有効にする必要があります。

gcloud services enable sqladmin

Cloud SQL Proxy のインストール

Cloud SQL Proxy をダウンロードしてインストールします。Cloud SQL Proxy は、ローカルで実行中の Cloud SQL インスタンスに接続します。

Linux 64 ビット

  1. プロキシをダウンロードします。
    wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 -O cloud_sql_proxy
    
  2. プロキシを実行できるようにします。
    chmod +x cloud_sql_proxy
    

Linux 32 ビット

  1. プロキシをダウンロードします。
    wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.386 -O cloud_sql_proxy
    
  2. プロキシを実行できるようにします。
    chmod +x cloud_sql_proxy
    

macOS 64 ビット

  1. プロキシをダウンロードします。
    curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.amd64
    
  2. プロキシを実行できるようにします。
    chmod +x cloud_sql_proxy
    

macOS 32 ビット

  1. プロキシをダウンロードします。
    curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.386
    
  2. プロキシを実行できるようにします。
    chmod +x cloud_sql_proxy
    

Windows 64 ビット

https://dl.google.com/cloudsql/cloud_sql_proxy_x64.exe を右クリックして [名前を付けてリンク先を保存] を選択し、プロキシをダウンロードします。ファイル名を cloud_sql_proxy.exe に変更します。

Windows 32 ビット

https://dl.google.com/cloudsql/cloud_sql_proxy_x86.exe を右クリックして [名前を付けてリンク先を保存] を選択し、プロキシをダウンロードします。ファイル名を cloud_sql_proxy.exe に変更します。
お使いのオペレーティング システムがここに記載されていない場合は、ソースからプロキシをコンパイルすることもできます。

Cloud SQL インスタンスの作成

  1. Cloud SQL for PostgreSQL のインスタンスを作成します。

    インスタンスに polls-instance などの名前を付けます。インスタンスを使用できるようになるまで数分かかることがあります。インスタンスの準備が整うと、インスタンス リストに表示されます。

  2. Cloud SDK を使用して、次のコマンドを実行します。ここで、[YOUR_INSTANCE_NAME] は、Cloud SQL インスタンスの名前を表します。
    gcloud sql instances describe [YOUR_INSTANCE_NAME]

    出力の [CONNECTION_NAME] に示されている値を書き留めます。

    [CONNECTION_NAME] の値は [PROJECT_NAME]:[REGION_NAME]:[INSTANCE_NAME] という形式です。

Cloud SQL インスタンスの初期化

  1. 上記の手順の [CONNECTION_NAME] の値を使用して Cloud SQL Proxy を起動します。

    Linux / macOS

    ./cloud_sql_proxy -instances="[YOUR_INSTANCE_CONNECTION_NAME]"=tcp:5432

    Windows

    cloud_sql_proxy.exe -instances="[YOUR_INSTANCE_CONNECTION_NAME]"=tcp:5432

    [YOUR_INSTANCE_CONNECTION_NAME] を上記の手順で記録した [CONNECTION_NAME] の値に置き換えます。

    ローカルでテストを行うため、このステップでローカル コンピュータから Cloud SQL インスタンスへの接続を確立します。ローカルでのアプリのテストが終了するまで、Cloud SQL Proxy を実行したままにしてください。

  2. Cloud SQL のユーザーとデータベースを作成します。

    Cloud Console

    1. Cloud SQL インスタンス polls-instanceCloud Console を使用して新しいデータベースを作成します。たとえば、名前 polls を使用できます。
    2. Cloud SQL インスタンス polls-instanceCloud Console を使用して新しいユーザーを作成します。

    Postgres クライアント

    1. 別のコマンドライン タブで、Postgres クライアントをインストールします。
      sudo apt-get install postgresql
    2. Postgres クライアント、または同様のプログラムを使用して、インスタンスに接続します。プロンプトが表示されたら、構成したルート パスワードを使用します。
      psql --host 127.0.0.1 --user postgres --password
    3. 次のコマンドを使用して、必要なデータベース、ユーザー、アクセス権限を Cloud SQL データベース内に作成します。その際、[POSTGRES_USER][POSTGRES_PASSWORD] は使用するユーザー名とパスワードに置き換えます。
      CREATE DATABASE polls;
      CREATE USER [POSTGRES_USER] WITH PASSWORD '[POSTGRES_PASSWORD]';
      GRANT ALL PRIVILEGES ON DATABASE polls TO [POSTGRES_USER];
      GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO [POSTGRES_USER];
      

サービス アカウントの作成

プロキシには、Cloud SQL インスタンスに対する編集者の権限を持つサービス アカウントが必要です。サービス アカウントの詳細については、Google Cloud 認証の概要をご覧ください。

サービス アカウントを使用してプロキシの認証情報を提示する場合は、十分な権限が付与されたサービス アカウントを作成する必要があります。よりきめ細かい Identity Access and Management(IAM)のロールを使用して Cloud SQL 権限を管理する場合は、サービス アカウントに cloudsql.instances.connect 権限を含むロールを付与する必要があります。この権限を含む事前定義された Cloud SQL のロールは次のとおりです。

  • Cloud SQL クライアント
  • Cloud SQL 編集者
  • Cloud SQL 管理者

以前のプロジェクトのロール(閲覧者、編集者、オーナー)を使用する場合、サービス アカウントには少なくとも編集者のロールが付与されている必要があります。

  1. Google Cloud Console の [サービス アカウント] ページに移動します。

    [サービス アカウント] ページに移動

  2. Cloud SQL インスタンスを含むプロジェクトを選択します。
  3. [サービス アカウントを作成] をクリックします。
  4. [サービス アカウントの作成] ダイアログで、わかりやすいサービス アカウント名を指定します。
  5. [役割] で、次のいずれかの役割を選択します。
    • [Cloud SQL] > [Cloud SQL クライアント]
    • [Cloud SQL] > [Cloud SQL 編集者]
    • [Cloud SQL] > [Cloud SQL 管理者]
  6. [サービス アカウント ID] を一意のわかりやすい値に変更します。
  7. [新しい秘密鍵の提供] をクリックし、キーのタイプが JSON であることを確認します。
  8. [作成] をクリックします。

    秘密鍵ファイルがマシンにダウンロードされます。秘密鍵ファイルは、別の場所に移動できます。安全な場所に鍵ファイルを保管してください。

データベースを構成する

データベースにアクセスするための環境変数を設定するには、次のコマンドを使用します。 これらの環境変数はローカルテストに使用されます。

Linux / macOS

export DATABASE_USER=<your-database-user>
export DATABASE_PASSWORD=<your-database-password>

Windows

set DATABASE_USER=<your-database-user>
set DATABASE_PASSWORD=<your-database-password>

GKE を構成する

  1. このアプリケーションは、polls という名前の単一の Kubernetes 構成で表されます。polls.yaml で、<your-project-id> を実際の Google Cloud プロジェクト ID に置き換えます。

  2. 次のコマンドを実行して、connectionNameの値をメモします。

    gcloud beta sql instances describe [YOUR_INSTANCE_NAME]
    
  3. polls.yaml ファイルで、<your-cloudsql-connection-string>connectionName 値に置き換えます。

ローカル パソコン上でのアプリの実行

  1. ローカル コンピュータ上で Django アプリを実行するには、Python、pip、および virtualenv を含む Python 開発環境をセットアップする必要があります。

  2. 隔離された Python 環境を作成し、依存関係をインストールします。Python 3 のインストールの名前が異なる場合は、最初のコマンドでその名前を使用します。

    virtualenv env
    source env/bin/activate
    pip install -r requirements.txt
    
  3. モデルを設定するために Django の移行を実行します。

    python manage.py makemigrations
    python manage.py makemigrations polls
    python manage.py migrate
    
  4. ローカル ウェブサーバーを起動します。

    python manage.py runserver
    
  5. ブラウザで、http://localhost:8000 にアクセスします。

    「Hello, world. You're at the polls index.」というテキストを含む簡単なウェブページが表示されます。コンピュータで実行されている Django ウェブサーバーは、サンプルアプリのページを配信します。

  6. Control+C キーを押して、ローカル ウェブサーバーを停止します。

Django 管理コンソールを使用する

  1. スーパーユーザーを作成します。ユーザー名とパスワードを指定する必要があります。

    python manage.py createsuperuser
    
  2. メイン プログラムを実行します。

    python manage.py runserver
    
  3. ブラウザで、http://localhost:8000/admin にアクセスします。

  4. createsuperuser の実行時に使用したユーザー名とパスワードで管理サイトにログインします。

アプリを GKE にデプロイする

アプリが Google Cloud にデプロイされると、Gunicorn サーバーが使用されます。Gunicorn は静的コンテンツを処理しないため、アプリは Cloud Storage を使用して静的コンテンツを処理します。

静的リソースの収集とアップロード

  1. Cloud Storage バケットを作成して、一般公開します。[YOUR_GCS_BUCKET] を任意のバケット名に置き換えます。たとえば、プロジェクト ID をバケット名として使用できます。

    gsutil mb gs://[YOUR_GCS_BUCKET]
    gsutil defacl set public-read gs://[YOUR_GCS_BUCKET]
    
  2. すべての静的コンテンツをローカルで 1 つのフォルダにまとめます。

    python manage.py collectstatic
    
  3. 静的コンテンツを Cloud Storage にアップロードします。

    gsutil -m rsync -r ./static gs://[YOUR_GCS_BUCKET]/static
    
  4. mysite/settings.py で、STATIC_URL の値を次の URL に設定します。[YOUR_GCS_BUCKET] は実際のバケット名に置き換えます。

    http://storage.googleapis.com/[YOUR_GCS_BUCKET]/static/
    

GKE の設定

  1. GKE を初期化するには、[クラスタ] ページに移動します。

    [クラスタ] ページに移動

    プロジェクトで初めて GKE を使用する場合は、[Kubernetes Engine is getting ready. This may take a minute or more] というメッセージが消えるまで待ちます。

  2. GKE クラスタを作成します。

    gcloud container clusters create polls \
      --scopes "https://www.googleapis.com/auth/userinfo.email","cloud-platform" \
      --num-nodes 4 --zone "us-central1-a"
    

    Project [PROJECT_ID] is not fully initialized with the default service accounts.」というエラーが表示されましたか。

    GKE の初期化

    エラーが表示された場合は、Google Cloud Console に移動してプロジェクトの GKE を初期化します。

    [クラスタ] ページに移動

    [Kubernetes Engine is getting ready. This can take a minute or more」というメッセージが消えるまで待ちます。

  3. クラスタを作成した後、gcloud ツールと統合された kubectl コマンドライン ツールを使用して、GKE クラスタを操作します。gcloudkubectl は別々のツールであるため、kubectl が適切なクラスタとやり取りするように構成されていることを確認してください。

    gcloud container clusters get-credentials polls --zone "us-central1-a"
    

Cloud SQL の設定

  1. GKE アプリを Cloud SQL インスタンスに接続できるようにするには、いくつかのシークレットが必要です。1 つはインスタンスレベルのアクセス(接続)に必要となり、他の 2 つはデータベース アクセスに必要となります。この 2 つのレベルのアクセス制御の詳細については、インスタンスのアクセス制御をご覧ください。

    1. インスタンス レベルのアクセス用のシークレットを作成するには、サービス アカウントの作成時にダウンロードした JSON サービス アカウント キーの場所([PATH_TO_CREDENTIAL_FILE])を指定します(サービス アカウントの作成を参照)。

      kubectl create secret generic cloudsql-oauth-credentials --from-file=credentials.json=[PATH_TO_CREDENTIAL_FILE]
      
    2. データベース アクセス用のシークレットを作成するには、Cloud SQL インスタンスの初期化のステップ 2 で定義した SQL [DATABASE_USERNAME][PASSWORD] を使用します。

      kubectl create secret generic cloudsql --from-literal=username=[DATABASE_USERNAME] --from-literal=password=[PASSWORD]
      
  2. Cloud SQL プロキシのパブリック Docker イメージを取得します。

    docker pull b.gcr.io/cloudsql-docker/gce-proxy
    
  3. Docker イメージをビルドします。<your-project-id> は実際のプロジェクト ID に置き換えます。

    docker build -t gcr.io/<your-project-id>/polls .
    
  4. 認証ヘルパーとして gcloud を使用するように Docker を構成します。これにより、イメージを Container Registry に push できます。

    gcloud auth configure-docker
    
  5. Docker イメージを push します。<your-project-id> は、プロジェクト ID に置き換えます。

    docker push gcr.io/<your-project-id>/polls
    
  6. GKE リソースを作成します。

    kubectl create -f polls.yaml
    

GKE にアプリをデプロイする

リソースを作成すると、クラスタ上に polls ポッドが 3 つ生成されます。ポッドのステータスを確認します。

    kubectl get pods

ポッドのステータスが Running と表示されるまで数分待ちます。ポッドの準備ができていない場合や再起動が発生した場合は、特定のポッドのログを取得して問題を確認できます。[YOUR-POD-ID] は、前の kubectl get pods コマンドで返された出力の一部です。

    kubectl logs [YOUR_POD_ID]

Google Cloud でアプリが動作することを確認する

ポッドの準備ができたら、ロードバランサのパブリック IP アドレスを取得します。

kubectl get services polls

ブラウザで EXTERNAL-IP アドレスに移動して Django の基本ランディング ページを開き、管理コンソールにアクセスします。

コードの説明

Django サンプルアプリは、Django の標準ツールを使用して作成されています。以下のコマンドは、プロジェクトと polls アプリを作成します。

django-admin startproject mysite
python manage.py startapp polls

settings.py には、SQL データベースの構成が含まれています。

DATABASES = {
    'default': {
        # If you are using Cloud SQL for MySQL rather than PostgreSQL, set
        # 'ENGINE': 'django.db.backends.mysql' instead of the following.
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'polls',
        'USER': os.getenv('DATABASE_USER'),
        'PASSWORD': os.getenv('DATABASE_PASSWORD'),
        'HOST': '127.0.0.1',
        'PORT': '5432',
    }
}

polls.yaml ファイルには、2 つの Kubernetes リソースが指定されています。1 つ目はServiceで、Django ウェブアプリの一貫した名前とプライベート IP アドレスを定義します。2 つ目は、一般公開される外部 IP アドレスを持つHTTP ロードバランサです。

# The polls service provides a load-balancing proxy over the polls app
# pods. By specifying the type as a 'LoadBalancer', Container Engine will
# create an external HTTP load balancer.
# For more information about Services see:
#   https://cloud.google.com/container-engine/docs/services/
# For more information about external HTTP load balancing see:
#   https://cloud.google.com/container-engine/docs/load-balancer
apiVersion: v1
kind: Service
metadata:
  name: polls
  labels:
    app: polls
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: polls

このサービスはネットワーク名と IP アドレスを提供し、GKE ポッドはこのサービスの背後でアプリのコードを実行します。polls.yaml ファイルは、GKE ポッドの宣言型更新を行う deployment を指定します。このサービスは、サービスのセレクタを deployment のラベルと照合し、トラフィックを deployment に送信します。この場合、セレクタ polls はラベル polls と一致します。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: polls
  labels:
    app: polls
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: polls
    spec:
      containers:
      - name: polls-app
        # Replace  with your project ID or use `make template`
        image: gcr.io/<your-project-id>/polls
        # This setting makes nodes pull the docker image every time before
        # starting the pod. This is useful when debugging, but should be turned
        # off in production.
        imagePullPolicy: Always
        env:
            - name: DATABASE_USER
              valueFrom:
                secretKeyRef:
                  name: cloudsql
                  key: username
            - name: DATABASE_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: cloudsql
                  key: password
        ports:
        - containerPort: 8080

      - image: gcr.io/cloudsql-docker/gce-proxy:1.16
        name: cloudsql-proxy
        command: ["/cloud_sql_proxy", "--dir=/cloudsql",
                  "-instances=<your-cloudsql-connection-string>=tcp:5432",
                  "-credential_file=/secrets/cloudsql/credentials.json"]
        volumeMounts:
          - name: cloudsql-oauth-credentials
            mountPath: /secrets/cloudsql
            readOnly: true
          - name: ssl-certs
            mountPath: /etc/ssl/certs
          - name: cloudsql
            mountPath: /cloudsql
      volumes:
        - name: cloudsql-oauth-credentials
          secret:
            secretName: cloudsql-oauth-credentials
        - name: ssl-certs
          hostPath:
            path: /etc/ssl/certs
        - name: cloudsql
          emptyDir: