如何使用 Kubernetes 部署可扩展且安全的 Django 应用程序

介绍

在本教程中,您将部署一个集装箱化的Django调查应用程序到Kubernetes集群中。

[Django] (https://www.djangoproject.com/)是一个强大的网络框架,可以帮助您快速地将您的Python应用程序从地上取出. 它包括几个方便的功能,如对象-关系映射器,用户认证,以及您应用程序的自定义的行政界面. 它还包括一个搜索框架,并通过其URL调度机Template system鼓励清洁应用设计.

在"如何用多克来构建 Django 和 Gunicorn 应用程序"(https://andsky.com/tech/tutorials/how-to-build-a-django-and-gunicorn-application-with-docker)中,Django Tutorial Polls 应用程序被按照 12-Factor方法修改,用于构建可伸缩的,云族的网络应用程序. 这种被装入容器的设置被放大并加装了Nginx倒置代用并加密了 [How To Scale and Secure a Django applications with Docker, Nginx, and Let's Encrypt] (https://andsky.com/tech/tutorials/how-to-scale-and-secure-a-django-application-with-docker-nginx-and-let-s-encrypt) 的由加密签名的TLS证书. 在[从集装箱到与Django的Kubernetes]系列(https://www.digitalocean.com/community/tutorial_series/from-containers-to-kubernetes-with-django)的最后辅导中,现代化的Django民意测验应用将部署到Kubernetes集群.

[Kubernetes] (https://kubernetes.io/)是一个强大的开源集装箱管弦乐器,能使集装箱化应用的部署,缩放和管理自动化. Kubernetes 等对象 ConfigMaps and Secrets 允许您从容器中集中并解析配置,而部署等控制器则自动重启已失效的容器并允许快速缩放容器复制. TLS 加密被启用,有入侵对象和 [engress-nginx] (https://github.com/kubernetes/ingress-nginx) 开源入侵控制器. [Cert-manager] (https://github.com/jetstack/cert-manager). Kubernetes 添加更新并使用免费的 [让我们加密] (https://letsencrypt.org/) 证书权限签发证书.

如果您正在寻找一个管理的Kubernetes托管服务,请查看我们的简单的,用于增长的管理的Kubernetes服务(https://www.digitalocean.com/products/kubernetes)。

前提条件

要遵循本教程,您将需要:

  • 具有基于作用的存取控制的Kubernetes 1.15+集群(RBAC)启用. 此设置将使用 [数字Ocean Kubernetes] (https://www.digitalocean.com/products/kubernetes/]] 集群, 但是您可以自由地使用 [另一种方法] (https://andsky.com/tech/tutorials/how-to-create-a-kubernetes-cluster-using-kubeadm-on-ubuntu-18-04) 创建集群 。
  • 联合国 在您的本地机器上安装了)。 如果您正在使用 DigitalOcean Kubernetes 集群,请参见[如何连接到 DigitalOcean Kubernetes 集群 (https://www.digitalocean.com/docs/kubernetes/how-to/connect-to-cluster/),学习如何使用 kubectl 连接您的集群 。
  • 一个已注册域名。 此教程将使用 your_ domain.com 整个 您可以在 [Freenom] (http://www.freenom.com/en/index.html] 免费获取, 或者使用您选择的域注册员 。
  • [英 (https://github.com/kubernetes/ingress-nginx) 入侵控制员和证书管理员 TLS 证书管理器安装在您的集群中, 并配置为发行 TLS 证书 。 为学习如何安装和配置带有证书管理器的入侵者,请咨询[如何在数字海洋库伯内特斯上安装带有证书管理器的Nginx入侵者(https://andsky.com/tech/tutorials/how-to-set-up-an-nginx-ingress-with-cert-manager-on-digitalocean-kubernetes)。
  • A'DNS记录,并有`your_domain.com'指向入侵负载平衡器的公共IP地址。 如果您正在使用 DigitalOcean 来管理域名的 DNS 记录,请查看 [如何管理 DNS 记录 (https://www.digitalocean.com/docs/networking/dns/how-to/manage-records/) 学习如何创建 'A ' 记录
  • 联合国 用于存储您 Django 项目的静态文件以及此空间的一组访问密钥的 S3 对象存储桶, 如 [数字海洋空间] (https://www.digitalocean.com/products/spaces/ ) 。 要学习如何创建空间,请查阅如何创建空间产品文档. 要学习如何为空间创建访问密钥,请咨询用访问密钥共享访问空间. 通过小的修改,您可以使用django-storages插件支持的任何对象存储服务.
  • 用于您的 Django 应用程序的 PostgreSQL 服务器实例、数据库和用户。 通过小的修改,可以使用任何Django支持的数据库.
  • PostgreSQL数据库应称为polls (或下面的配置文件中输入另一个值得纪念的名字),在此教程中,Django数据库用户将命名为** Sammy** 。 关于创建这些应用程序的指导,请遵循[如何用多克来构建Django和Gunicorn应用程序]的第1步(https://andsky.com/tech/tutorials/how-to-build-a-django-and-gunicorn-application-with-docker# step-1-%E2%80%94-creating-the-postgresql-database-and-user)。 你应该从你的本地机器上完成这些步骤。
  • 本教程中使用了数字海洋(Managed PostgreSQL集群)(https://www.digitalocean.com/products/managed-databases/). 为学习如何创建集群,请查阅"数字海洋"管理数据库产品文档.
  • 也可以安装和运行自己的 PostgreSQL 实例。 关于在 Ubuntu 服务器上安装和管理 PostgreSQL 的指南,请参见[如何安装和使用 Ubuntu 18.04 上的 PostgreSQL (https://andsky.com/tech/tutorials/how-to-install-and-use-postgresql-on-ubuntu-18-04).
  • ADocker Hub帐户和公共存放处。 关于创建这些功能的更多信息,请参见Docker文档中的[仓库] (https://docs.docker.com/docker-hub/repos/).
  • 安装在您本地机器上的多克引擎。 请参看[如何在Ubuntu 18.04上安装和使用多克 (https://andsky.com/tech/tutorials/how-to-install-and-use-docker-on-ubuntu-18-04)来学习更多. .

一旦您设置了这些组件,您已经准备好开始使用本指南。

步骤1 - 克隆和配置应用程序

在此步骤中,我们将从 GitHub 克隆应用程序代码,并配置数据库凭证和对象存储密钥等设置。

应用程序代码和Dockerfile可以在Django Tutorial Polls App(github.com/do-community/django-polls/tree/polls-docker)的),该重组包含了Django文档的),教你如何从头开始构建投票应用程序。

要了解如何在容器化环境中有效地工作,请参阅 如何使用 Docker 构建 Django 和 Gunicorn 应用程序

开始使用)到您的本地机器:

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

导航到‘django-polls’目录:

1cd django-polls

该目录包含了Django应用程序Python代码,一个Dockerfile,Docker将用来构建容器图像,以及一个env文件,其中包含一份将环境变量列入容器运行环境的列表。

1cat Dockerfile
 1[secondary_label Output]
 2FROM python:3.7.4-alpine3.10
 3
 4ADD django-polls/requirements.txt /app/requirements.txt
 5
 6RUN set -ex \
 7    && apk add --no-cache --virtual .build-deps postgresql-dev build-base \
 8    && python -m venv /env \
 9    && /env/bin/pip install --upgrade pip \
10    && /env/bin/pip install --no-cache-dir -r /app/requirements.txt \
11    && runDeps="$(scanelf --needed --nobanner --recursive /env \
12        | awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \
13        | sort -u \
14        | xargs -r apk info --installed \
15        | sort -u)" \
16    && apk add --virtual rundeps $runDeps \
17    && apk del .build-deps
18
19ADD django-polls /app
20WORKDIR /app
21
22ENV VIRTUAL_ENV /env
23ENV PATH /env/bin:$PATH
24
25EXPOSE 8000
26
27CMD ["gunicorn", "--bind", ":8000", "--workers", "3", "mysite.wsgi"]

这个多克文件使用官方的Python 3.7.4 [Docker image] (https://hub.docker.com/_/python)作为底盘,并安装了"django-polls/requiments.txt"文件中定义的Django和Gunicorn的Python包要求. 然后删除一些不必要的构建文件,将应用程序代码复制到图像中,并设置执行"PATH". 最后,它宣布,8000'港将用来接受即将进入的集装箱连接,并用3名工人在8000'港旁听,运行`gunicorn'.

有关此 Dockerfile中的每一个步骤的更多信息,请参阅 如何使用 Docker 构建 Django 和 Gunicorn 应用程序的第 6 步。

现在,使用docker build来构建图像:

1docker build -t polls .

我们使用t旗号命名图像调查,并在当前目录中作为 build context 传输,这是构建图像时要参考的文件集。

在 Docker 构建和标记图像后,使用docker 图像列出可用的图像:

1docker images

你应该看到列出的民意调查图像:

1OutputREPOSITORY TAG IMAGE ID CREATED SIZE
2polls latest 80ec4f33aae1 2 weeks ago 197MB
3python 3.7.4-alpine3.10 f309434dea3a 8 months ago 98.7MB

在运行Django容器之前,我们需要使用当前目录中存在的env文件来配置其运行环境,该文件将传入用于运行容器的docker run命令,Docker将将配置的环境变量注入容器的运行环境。

使用nano或您最喜欢的编辑器打开env文件:

1nano env
 1[label django-polls/env]
 2DJANGO_SECRET_KEY=
 3DEBUG=True
 4DJANGO_ALLOWED_HOSTS=
 5DATABASE_ENGINE=postgresql_psycopg2
 6DATABASE_NAME=polls
 7DATABASE_USERNAME=
 8DATABASE_PASSWORD=
 9DATABASE_HOST=
10DATABASE_PORT=
11STATIC_ACCESS_KEY_ID=
12STATIC_SECRET_KEY=
13STATIC_BUCKET_NAME=
14STATIC_ENDPOINT_URL=
15DJANGO_LOGLEVEL=info

填写以下键的缺失值:

  • `DJANGO-SECRET-KEY':将此设定为一个独特的、无法预测的价值,详见Django docs。 生成此密钥的一个方法是在 [可扩展 Django App (https://andsky.com/tech/tutorials/how-to-set-up-a-scalable-django-app-with-digitalocean-managed-databases-and-spaces step-5-%E2%80%94-adjusting-the-app-settings) 教程中的 [调整 App 设置 (https://andsky.com/tech/tutorials/how-to-set-up-a-scalable-django-app-with-digitalocean-managed-databases-and-spaces# step-5-%E2%80%94-adjusting-the-app-settings ) 中提供 。
  • `DJANGO_ALLOUED-HOSTS': 这个变量可以保护应用程序,防止HTTP主机头攻击. 为测试目的, 将此设定为QQ, 一个匹配所有主机的通配符 。 在制作中,您应该将此设定为 )。
  • `巴哈马-美国 ' : 设定为在先决条件步骤中创建的 PostgreSQL 数据库用户 。
  • DATABASE-NAME':将此设定为Polls'或按先决条件步骤创建的PostgreSQL数据库的名称。
  • `DATABASE-PASSWORD': 设定为先决条件步骤中创建的 PostgreSQL 用户密码 。
  • `DATABASE-HOST ' :将其设定为数据库的主机名。
  • `DATABASE-PORT ' :将其设置在数据库的端口。
  • `统计-ACCESS-KEY-ID': 设置到您的 空间或物体存储的访问密钥.
  • `STATIC_SECRET_KEY':将此设定在您的空间或物体存储器的存取密钥上。
  • `STIC_BUKET_NAME: 设置到您的 空间名称或物体存储桶。
  • 统计-ENDPOINT-URL': 将其设定为相应的空间或物体存储端点 URL, 例如 https://your_space_name.nyc3. digital Oceanspaces.com' 如果您的空间位于nyc3区域。 .

完成编辑后,保存并关闭文件。

在下一步中,我们将本地运行配置的容器并创建数据库方案,我们还将上传静态资产,如风格表和图像到对象存储。

步骤 2 — 创建数据库方案并将资产上传到对象存储

有了集装箱的构建和配置,使用docker run来取代 Dockerfile中的CMD设置,并使用manage.py makemigrationsmanage.py migrate命令创建数据库方案:

1docker run --env-file env polls sh -c "python manage.py makemigrations && python manage.py migrate"

我们运行polls:latest容器图像,传入我们刚刚修改的环境变量文件,并用sh -c``python manage.py makemigrations && python manage.py迁移来翻译Dockerfile命令,这将创建应用程序代码定义的数据库方案。

如果你第一次使用此功能,你应该看到:

 1[secondary_label Output]
 2No changes detected
 3Operations to perform:
 4  Apply all migrations: admin, auth, contenttypes, polls, sessions
 5Running migrations:
 6  Applying contenttypes.0001_initial... OK
 7  Applying auth.0001_initial... OK
 8  Applying admin.0001_initial... OK
 9  Applying admin.0002_logentry_remove_auto_add... OK
10  Applying admin.0003_logentry_add_action_flag_choices... OK
11  Applying contenttypes.0002_remove_content_type_name... OK
12  Applying auth.0002_alter_permission_name_max_length... OK
13  Applying auth.0003_alter_user_email_max_length... OK
14  Applying auth.0004_alter_user_username_opts... OK
15  Applying auth.0005_alter_user_last_login_null... OK
16  Applying auth.0006_require_contenttypes_0002... OK
17  Applying auth.0007_alter_validators_add_error_messages... OK
18  Applying auth.0008_alter_user_username_max_length... OK
19  Applying auth.0009_alter_user_last_name_max_length... OK
20  Applying auth.0010_alter_group_name_max_length... OK
21  Applying auth.0011_update_proxy_permissions... OK
22  Applying polls.0001_initial... OK
23  Applying sessions.0001_initial... OK

这表明数据库方案已成功创建。

如果您在随后的时间运行迁移,Django 将执行禁令,除非数据库架构发生了变化。

接下来,我们将运行应用程序容器的另一个实例,并使用其内部的交互式壳创建 Django 项目的管理用户。

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

这将为您提供运行容器内部的壳提示,您可以使用它来创建Django用户:

1python manage.py createsuperuser

输入您的用户的用户名、电子邮件地址和密码,然后创建用户后,点击CTRL+D,离开容器并杀死它。

最后,我们将生成应用程序的静态文件,并使用collectstatic将其上传到DigitalOcean Space。

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

这些文件被生成和上传后,您将收到以下输出。

1[secondary_label Output]
2121 static files copied.

现在我们可以运行应用程序:

1docker run --env-file env -p 80:8000 polls
1[secondary_label Output]
2[2019-10-17 21:23:36 +0000] [1] [INFO] Starting gunicorn 19.9.0
3[2019-10-17 21:23:36 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1)
4[2019-10-17 21:23:36 +0000] [1] [INFO] Using worker: sync
5[2019-10-17 21:23:36 +0000] [7] [INFO] Booting worker with pid: 7
6[2019-10-17 21:23:36 +0000] [8] [INFO] Booting worker with pid: 8
7[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被映射到调查容器的端口8000

您现在应该能够通过在URL栏中键入http://localhost来导航到调查应用程序,因为没有定义的路径,您可能会收到一个404页未找到错误,这是预期的。

导航到http://localhost/polls,以查看调查应用程序界面:

Polls Apps Interface

要查看管理界面,请访问http://localhost/admin。你应该看到调查应用程序管理员身份验证窗口:

Polls Admin Auth Page

输入您用createsuperuser命令创建的管理用户名和密码。

验证后,您可以访问 Polls 应用程序的管理界面:

Polls Admin Main Interface

请注意,对)。

当你完成探索时,在运行 Docker 容器的终端窗口中按CTRL + C来杀死容器。

有了 Django 应用程序 Docker 图像测试,将静态资产上传到对象存储中,以及配置并准备与您的应用程序一起使用的数据库架构,您可以将 Django 应用程序图像上传到像 Docker Hub 这样的图像注册表中。

步骤 3 — 将 Django 应用程序图像推到 Docker Hub

要在 Kubernetes 上运行应用程序,必须将应用程序图像上传到像 [Docker Hub] 这样的注册表(https://hub.docker.com/). Kubernetes 会将应用程序图像从其存储库中提取,然后部署到您的集群中。

您可以使用私人 Docker 注册表,如 DigitalOcean Container Registry,目前在 Early Access 中免费使用,或者使用公共 Docker 注册表,如 Docker Hub。 Docker Hub 还允许您创建私人 Docker 存储库。 公共存储库允许任何人查看和提取容器图像,而私人存储库允许您限制对您和您的团队成员的访问。

在本教程中,我们将将Django图像推到在前提条件下创建的公共Docker Hub存储库中。您还可以将图像推到私人存储库,但从私人存储库中提取图像超出了本文的范围。 有关使用Docker Hub验证Kubernetes和提取私人图像的更多信息,请参阅 从私人注册库提取图像从Kubernetes文件库。

首先,请在本地计算机上登录 Docker Hub:

1docker login
1[secondary_label Output]
2Login 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.
3Username:

输入您的 Docker Hub 用户名和密码来登录。

Django 图像目前有 polls:latest 标签. 要将其推到您的 Docker Hub 复印件,请用您的 Docker Hub 用户名和复印件名重新标签图像:

1docker tag polls:latest your_dockerhub_username/your_dockerhub_repo_name:latest

将图像推到 Repo:

1docker push sammy/sammy-django:latest

在本教程中,Docker Hub 用户名为 sammy 和 Repo 名为** sammy-django** . 您应该用自己的 Docker Hub 用户名和 Repo 名更换这些值。

您将看到一些输出更新,因为图像层被推到Docker Hub。

现在,您的图像在Docker Hub上可用于Kubernetes,您可以开始在集群中滚动它。

步骤4 - 设置 ConfigMap

当我们在本地运行Django容器时,我们将)和)注入配置变量。

ConfigMaps 应该用于存储非机密配置信息,如应用设置,Secrets 应该用于敏感信息,如 API 密钥和数据库凭证。它们都以类似的方式注入到容器中,但Secrets 具有额外的访问控制和安全功能,如 安静加密.Secrets 也将数据存储在 base64中,而 ConfigMaps 将数据存储在简单的文本中。

首先,创建一个名为yaml的目录,在其中我们将存储我们的Kubernetes宣言。

1mkdir yaml
2cd

nano或您喜爱的文本编辑器中打开名为polls-configmap.yaml的文件:

1nano polls-configmap.yaml

插入以下 ConfigMap 宣言:

 1[label polls-configmap.yaml]
 2apiVersion: v1
 3kind: ConfigMap
 4metadata:
 5  name: polls-config
 6data:
 7  DJANGO_ALLOWED_HOSTS: "*"
 8  STATIC_ENDPOINT_URL: "https://your_space_name.space_region.digitaloceanspaces.com"
 9  STATIC_BUCKET_NAME: "your_space_name"
10  DJANGO_LOGLEVEL: "info"
11  DEBUG: "True"
12  DATABASE_ENGINE: "postgresql_psycopg2"

我们从 [步骤 1] 修改的 env 文件中提取了非敏感的配置(https://andsky.com/tech/tutorials/how-to-deploy-a-scalable-and-secure-django-application-with-kubernetes# step-1-%E2%80%94-cloning-and-configuring-the-application)并将其粘贴到 ConfigMap 宣言中。 ConfigMap 对象被称为 polls-config. 在上一步中将输入 `env' 文件的相同值复制。

为了测试,将DJANGO_ALLOWED_HOSTS放置为* ,以禁用基于主机标题的过滤。

当你完成编辑文件时,保存并关闭它。

在您的集群中使用kubectl应用创建 ConfigMap:

1kubectl apply -f polls-configmap.yaml
1[secondary_label Output]
2configmap/polls-config created

随着 ConfigMap 创建,我们将在下一步创建应用程序使用的秘密。

第5步:设定秘密

秘密值必须是 base64-coded,这意味着在您的群集中创建秘密对象比创建 ConfigMaps 更重要。您可以重复从前一步的过程,手动 base64-coding 秘密值并粘贴到一个显而易见的文件中。您还可以使用环境变量文件, kubectl create--from-env-file 旗帜创建它们,我们将在本步中完成。

我们将再次使用从 Step 1env 文件,删除插入 ConfigMap 的变量。在 yaml 目录中创建一个名为 env 文件的副本:

1cp ../env ./polls-secrets

在您喜爱的编辑器中编辑文件:

1nano polls-secrets
 1[label polls-secrets]
 2DJANGO_SECRET_KEY=
 3DEBUG=True
 4DJANGO_ALLOWED_HOSTS=
 5DATABASE_ENGINE=postgresql_psycopg2
 6DATABASE_NAME=polls
 7DATABASE_USERNAME=
 8DATABASE_PASSWORD=
 9DATABASE_HOST=
10DATABASE_PORT=
11STATIC_ACCESS_KEY_ID=
12STATIC_SECRET_KEY=
13STATIC_BUCKET_NAME=
14STATIC_ENDPOINT_URL=
15DJANGO_LOGLEVEL=info

删除 ConfigMap 演示文中插入的所有变量. 完成后,它应该看起来像这样:

1[label polls-secrets]
2DJANGO_SECRET_KEY=your_secret_key
3DATABASE_NAME=polls
4DATABASE_USERNAME=your_django_db_user
5DATABASE_PASSWORD=your_django_db_user_password
6DATABASE_HOST=your_db_host
7DATABASE_PORT=your_db_port
8STATIC_ACCESS_KEY_ID=your_space_access_key
9STATIC_SECRET_KEY=your_space_access_key_secret

请确保在 [步骤 1] 中使用相同的值(https://andsky.com/tech/tutorials/how-to-deploy-a-scalable-and-secure-django-application-with-kubernetes# step-1-%E2%80%94-cloning-and-configuring-the-application)。

在您的集群中使用kubectl创建秘密创建秘密:

1kubectl create secret generic polls-secret --from-env-file=poll-secrets
1[secondary_label Output]
2secret/polls-secret created

在这里,我们创建了一个名为polls-secret的秘密对象,并通过我们刚刚创建的秘密文件。

您可以使用「kubectl 描述」檢查秘密:

1kubectl describe secret polls-secret
 1[secondary_label Output]
 2Name:         polls-secret
 3Namespace:    default
 4Labels:       <none>
 5Annotations:  <none>
 6
 7Type:  Opaque
 8
 9Data
10====
11DATABASE_PASSWORD:     8 bytes
12DATABASE_PORT:         5 bytes
13DATABASE_USERNAME:     5 bytes
14DJANGO_SECRET_KEY:     14 bytes
15STATIC_ACCESS_KEY_ID:  20 bytes
16STATIC_SECRET_KEY:     43 bytes
17DATABASE_HOST:         47 bytes
18DATABASE_NAME:         5 bytes

此时,您已使用 Secret 和 ConfigMap 对象类型将应用程序的配置存储在您的 Kubernetes 集群中,我们现在已经准备好将应用程序部署到集群中。

步骤 6 — 使用部署将 Django 应用程序滚动

在此步骤中,您将为您的 Django 应用程序创建部署。Kubernetes 部署是可用于管理群集中的无状态应用程序的 _controller。

部署控制一个或多个 Pods,这是 Kubernetes 集群中最小的可部署单元。 Pods 包含一个或多个容器。 若要了解您可以启动的不同类型的工作负载,请查看 An Introduction to Kubernetes

首先,在您最喜爱的编辑器中打开名为 'polls-deployment.yaml' 的文件:

1nano polls-deployment.yaml

点击下面的部署宣言:

 1[label polls-deployment.yaml]
 2apiVersion: apps/v1
 3kind: Deployment
 4metadata:
 5  name: polls-app
 6  labels:
 7    app: polls
 8spec:
 9    replicas: 2
10  selector:
11    matchLabels:
12      app: polls
13  template:
14    metadata:
15      labels:
16        app: polls
17    spec:
18      containers:
19        - image: your_dockerhub_username/app_repo_name:latest
20          name: polls
21          envFrom:
22          - secretRef:
23              name: polls-secret
24          - configMapRef:
25              name: polls-config
26          ports:
27            - containerPort: 8000
28              name: gunicorn

填写适当的容器图像名称,引用您在 [步骤 2] 中推出的 Django Polls 图像(https://andsky.com/tech/tutorials/how-to-deploy-a-scalable-and-secure-django-application-with-kubernetes# step-2-%E2%80%94-creating-the-database-schema-and-uploading-assets-to-object-storage)。

在这里,我们定义了一个名为Polls-app的Kubernetes部署,并将其标记为关键值对app:polls

使用envFromsecretRefconfigMapRef,我们指定从polls-secret Secret 和polls-config ConfigMap 的所有数据应该作为环境变量注入到容器中。

最后,我们将容器港``8000曝光,并将其命名为gunicorn

要了解有关配置 Kubernetes 部署的更多信息,请参阅 Kubernetes 文档中的 Deployments

当你完成编辑文件时,保存并关闭它。

在您的集群中使用 kubectl apply -f 创建部署:

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

检查部署是否使用kubectl get运行正确:

1kubectl get deploy polls-app
1[secondary_label Output]
2NAME READY UP-TO-DATE AVAILABLE AGE
3polls-app 2/2 2 2 6m38s

如果您遇到错误或某些东西不完全工作,您可以使用kubectl 描述来检查失败的部署:

1kubectl describe deploy

您可以使用kubectl get pod检查两个Pod:

1kubectl get pod
1[secondary_label Output]
2NAME READY STATUS RESTARTS AGE
3polls-app-847f8ccbf4-2stf7 1/1 Running 0 6m42s
4polls-app-847f8ccbf4-tqpwm 1/1 Running 0 6m57s

您的 Django 应用程序的两个复制品现在在集群中运行,要访问该应用程序,您需要创建 Kubernetes 服务,我们将接下来做。

步骤 7 — 使用服务允许外部访问

在此步骤中,您将为您的 Django 应用程序创建一个服务。Kubernetes 服务是一种抽象,允许您将一组运行 Pod 作为网络服务曝光。

有多种服务类型,包括ClusterIP Services,在集成内部IP,NodePort Services上曝光服务,在被称作"NodePort"的静态端口上曝光每个节点上的服务,以及LoadBalancer Services,它提供云负荷平衡器来引导外部流量到您集群中的Pods(通过NodePorts,它自动创建). 欲了解更多这方面的情况,请见Kubernetes文件Service.

在我们的最终设置中,我们将使用使用 Ingress 和 Ingress 控制器在本指南的前提条件中设置的 ClusterIP 服务。

开始使用您最喜欢的编辑器创建名为 `polls-svc.yaml’的文件:

1nano polls-svc.yaml

点击下面的服务宣言:

 1[label polls-svc.yaml]
 2apiVersion: v1
 3kind: Service
 4metadata:
 5  name: polls
 6  labels:
 7    app: polls
 8spec:
 9  type: NodePort
10  selector:
11    app: polls
12  ports:
13    - port: 8000
14      targetPort: 8000

在这里,我们创建了一个名为调查的NodePort服务,并给它app:polls标签,然后选择带有app:polls标签的后端Pod,并瞄准其8000端口。

当你完成编辑文件时,保存并关闭它。

使用「kubectl 應用」發佈服務:

1kubectl apply -f polls-svc.yaml
1[secondary_label Output]
2service/polls created

确认您的服务是使用kubectl get svc创建的:

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

此输出显示服务的集群内部IP和NodePort(32654)。 要连接到服务,我们需要我们的集群节点的外部IP地址:

1kubectl get node -o wide
1[secondary_label Output]
2NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
3pool-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
4pool-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
5pool-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 浏览器中,使用任何 Node 的外部 IP 地址和 NodePort 访问您的 Polls 应用程序. 考虑到上述输出,该应用程序的 URL 将是:http://203.0.113.1:32654/polls`。

您应该看到在步骤 1 中本地访问的相同的调查应用程序界面:

Polls Apps Interface

您可以使用 /admin 路線重複同樣的測試: http://203.0.113.1:32654/admin. 您應該看到與之前相同的 Admin 界面:

Polls Admin Auth Page

在此阶段,您使用部署部署了 Django Polls 应用程序容器的两个复制品,并为这两个复制品创建了一个稳定的网络终端,并通过使用 NodePort 服务使其外部可用。

本教程的最后一步是通过HTTPS向您的应用程序提供安全的外部流量. 为了做到这一点,我们将使用在前提条件中安装的ingress-nginx Ingress Controller,并创建一个 Ingress 对象来将外部流量路由到调查的 Kubernetes 服务。

步骤 8 — 使用 Nginx Ingress 和 cert-manager 配置 HTTPS

Kubernetes Ingresses允许您灵活地将流量从您的 Kubernetes 集群以外路由到您的集群内的服务。 这是通过使用 Ingress 对象实现的,这些对象定义了向 Kubernetes 服务路由 HTTP 和 HTTPS 流量的规则,以及 Ingress Controllers 通过负载平衡流量并将其路由到相应的后端服务来执行规则。

在先决条件中您安装了 [engress-nginx] (https://github.com/kubernetes/ingress-nginx) 入侵控制员和核证人-管理人 TLS 证书自动化加载. 您还使用 让我们加密证书 权限为您的域设置了 ClusterIssuers , 并创建了 Ingress 测试证书签发和 TLS 加密到两个假后端服务 。 在继续采取这一步骤之前,你应删除`echo-engress'。 在 [先决条件教程] (https://andsky.com/tech/tutorials/how-to-set-up-an-nginx-ingress-with-cert-manager-on-digitalocean-kubernetes 中创建的入侵 :

1kubectl delete ingress echo-ingress

如果你想,你也可以使用kubectl delete svckubectl delete deploy删除虚假服务和部署,但这不是完成本教程所必需的。

您还应该创建一个带有) 学习如何创建 `A' 记录 .

如果您正在使用DigitalOcean Kubernetes,请确保您已执行在 [如何在DigitalOcean Kubernetes上使用Cert-Manager设置 Nginx Ingress 的步骤 5]中描述的解决方案(https://andsky.com/tech/tutorials/how-to-set-up-an-nginx-ingress-with-cert-manager-on-digitalocean-kubernetes# step-5-%E2%80%94-enabling-pod-communication-through-the-load-balancer-(可选))。

一旦您有指向 Ingress 控制器负载平衡器的A记录,您可以为your_domain.com调查服务创建一个 Ingress。

使用您最喜欢的编辑器打开名为 polls-ingress.yaml 的文件:

1nano polls-ingress.yaml

请在以下 Ingress 宣言中填写:

 1[polls-ingress.yaml]
 2apiVersion: networking.k8s.io/v1beta1
 3kind: Ingress
 4metadata:
 5  name: polls-ingress
 6  annotations:
 7    kubernetes.io/ingress.class: "nginx"
 8    cert-manager.io/cluster-issuer: "letsencrypt-staging"
 9spec:
10  tls:
11  - hosts:
12    - your_domain.com
13    secretName: polls-tls
14  rules:
15  - host: your_domain.com
16    http:
17      paths:
18      - backend:
19          serviceName: polls
20          servicePort: 8000

我们创建了一个名为polls-ingress的 Ingress 对象,并注释它以指示控制平面使用 ingress-nginx Ingress 控制器并设置 ClusterIssuer. 我们还为your_domain.com启用 TLS,并将证书和私钥存储在一个名为polls-tls的秘密中。

当你完成编辑文件时,保存并关闭它。

在您的集群中使用kubectl应用创建 Ingress:

1kubectl apply -f polls-ingress.yaml
1[secondary_label Output]
2ingress.networking.k8s.io/polls-ingress created

您可以使用kubectl 描述来跟踪您刚刚创建的 Ingress 的状态:

1kubectl describe ingress polls-ingress
 1[secondary_label Output]
 2Name:             polls-ingress
 3Namespace:        default
 4Address:          workaround.your_domain.com
 5Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
 6TLS:
 7  polls-tls terminates your_domain.com
 8Rules:
 9  Host Path Backends
10  ----        ----  --------
11  your_domain.com
12                 polls:8000 (10.244.0.207:8000,10.244.0.53:8000)
13Annotations:  cert-manager.io/cluster-issuer: letsencrypt-staging
14              kubernetes.io/ingress.class: nginx
15Events:
16  Type Reason Age From Message
17  ----    ------             ----  ----                      -------
18  Normal CREATE 51s nginx-ingress-controller Ingress default/polls-ingress
19  Normal CreateCertificate 51s cert-manager Successfully created Certificate "polls-tls"
20  Normal UPDATE 25s nginx-ingress-controller Ingress default/polls-ingress

您也可以在polls-tls证书上运行描述,以进一步确认其成功创建:

1kubectl describe certificate polls-tls
1[secondary_label Output]
2. . .
3Events:
4  Type Reason Age From Message
5  ----    ------     ----   ----          -------
6  Normal Issuing 3m33s cert-manager Issuing certificate as Secret does not exist
7  Normal Generated 3m32s cert-manager Stored new private key in temporary Secret resource "polls-tls-v9lv9"
8  Normal Requested 3m32s cert-manager Created new CertificateRequest resource "polls-tls-drx9c"
9  Normal Issuing 2m58s cert-manager The certificate has been successfully issued

这确认了 TLS 证书的成功发行,并且 HTTPS 加密现在对 your_domain.com 是有效的。

鉴于我们使用了嵌入式 ClusterIssuer,大多数网页浏览器不会信任它发行的假 Let's Encrypt 证书,因此导航到 your_domain.com 将导致您到达错误页面。

要发送测试请求,我们将从命令行中使用wget:

1wget -O - http://your_domain.com/polls
1[secondary_label Output]
2. . .
3ERROR: cannot verify your_domain.com's certificate, issued by ‘CN=Fake LE Intermediate X1’:
4  Unable to locally verify the issuer's authority.
5To connect to your_domain.com insecurely, use `--no-check-certificate'.

我们将使用建议的--no-check-certificate旗帜来绕过证书验证:

1wget --no-check-certificate -q -O - http://your_domain.com/polls
1[secondary_label Output]
2
3<link rel="stylesheet" type="text/css" href="https://your_space.nyc3.digitaloceanspaces.com/django-polls/static/polls/style.css">
4
5    <p>No polls are available.</p>

此输出显示了 `/polls’ 界面页面的 HTML,也确认了风格表正在从对象存储中提供服务。

现在,您已经成功测试了使用阶段性 ClusterIssuer 的证书发行,您可以修改 Ingress 以使用生产 ClusterIssuer。

打开polls-ingress.yaml再次编辑:

1nano polls-ingress.yaml

更改集群发送者的注释:

 1[polls-ingress.yaml]
 2apiVersion: networking.k8s.io/v1beta1
 3kind: Ingress
 4metadata:
 5  name: polls-ingress
 6  annotations:
 7    kubernetes.io/ingress.class: "nginx"
 8    cert-manager.io/cluster-issuer: "letsencrypt-prod"
 9spec:
10  tls:
11  - hosts:
12    - your_domain.com
13    secretName: polls-tls
14  rules:
15  - host: your_domain.com
16    http:
17      paths:
18      - backend:
19          serviceName: polls
20          servicePort: 8000

完成后,保存并关闭文件. 使用 kubectl 应用 更新 Ingress:

1kubectl apply -f polls-ingress.yaml
1[secondary_label Output]
2ingress.networking.k8s.io/polls-ingress configured

您可以使用kubectl 描述证书调查结果kubectl 描述入门调查结果来跟踪证书发行状态:

1kubectl describe ingress polls-ingress
1[secondary_label Output]
2. . .
3Events:
4  Type Reason Age From Message
5  ----    ------             ----               ----                      -------
6  Normal CREATE 23m nginx-ingress-controller Ingress default/polls-ingress
7  Normal CreateCertificate 23m cert-manager Successfully created Certificate "polls-tls"
8  Normal UPDATE 76s (x2 over 22m)  nginx-ingress-controller Ingress default/polls-ingress
9  Normal UpdateCertificate 76s cert-manager Successfully updated Certificate "polls-tls"

上述结果证实,新生产证书已成功发行并存储在民意调查秘密中。

在您的 Web 浏览器中导航到your_domain.com/polls,以确认 HTTPS 加密已启用,一切按预期运行。

Polls Apps Interface

检查 HTTPS 加密是否在您的 Web 浏览器中活跃. 如果您使用 Google Chrome,在上面的页面上没有任何错误,确认一切正常工作。此外,您应该在 URL 栏中看到一个锁定。

作为最后的清理任务,您可以选择将调查服务类型从 NodePort 转换为内部只使用的 ClusterIP 类型。

使用您的编辑器更改 polls-svc.yaml:

1nano polls-svc.yaml

类型NodePort改为ClusterIP:

 1[label polls-svc.yaml]
 2apiVersion: v1
 3kind: Service
 4metadata:
 5  name: polls
 6  labels:
 7    app: polls
 8spec:
 9  type: ClusterIP
10  selector:
11    app: polls
12  ports:
13    - port: 8000
14      targetPort: 8000

当你完成编辑文件时,保存并关闭它。

使用kubectl 应用滚动更改:

1kubectl apply -f polls-svc.yaml --force
1[secondary_label Output]
2service/polls configured

确认您的服务已使用kubectl get svc进行修改:

1kubectl get svc polls
1[secondary_label Output]
2NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)    AGE
3polls ClusterIP 10.245.203.186   <none>        8000/TCP 22s

此输出显示服务类型现在是 ClusterIP. 访问它的唯一途径是通过您的域和在此步骤中创建的 Ingress。

结论

在本教程中,您将可扩展的、HTTPS 安全的 Django 应用部署到 Kubernetes 集群中. 静态内容直接从对象存储中提供,并且可以使用调查应用部署宣言中的复制品字段快速扩展运行 Pods 的数量。

如果您正在使用 DigitalOcean Space,您还可以通过内容交付网络启用静态资产交付并为您的 Space 创建自定义子域。 请参阅 Enabling CDN from How to Set Up a Scalable Django App with DigitalOcean Managed Databases and Spaces以获取更多信息。

要查看该系列的其余部分,请访问我们的 从容器到 Kubernetes 与 Django 系列页面

Published At
Categories with 技术
comments powered by Disqus