介绍
在本教程中,您将一个容器化的 Django 轮询应用程序部署到 Kubernetes 集群中。
Django是一个强大的 Web 框架,可以帮助您快速启动 Python 应用程序。它包括几个方便的功能,例如对象关系映射器、用户身份验证和应用程序的可自定义管理界面。它还包括一个缓存框架,并通过其URL 调度程序和模板系统鼓励干净的应用程序设计。
在How to Build a Django and Gunicorn Application with Docker 中,Django Tutorial Polls 应用程序根据用于构建可扩展的云原生 Web 应用程序的十二因素方法进行了修改。这个容器化设置通过 Nginx 反向代理和 Let’s Encrypt-signed TLS 证书进行了扩展和保护,如何使用 Docker、Nginx 和 Let’s Encrypt扩展和保护Django 应用程序。在使用 Django 从容器到 Kubernetes系列的最后一个教程中,现代化的 Django 轮询应用程序将部署到 Kubernetes 集群中。
Kubernetes是一个强大的开源容器编排器,可自动部署、扩展和管理容器化应用程序。像 ConfigMaps 和 Secrets 这样的 Kubernetes 对象允许您将配置与容器集中和分离,而像 Deployments 这样的控制器会自动重启失败的容器并实现容器副本的快速扩展。TLS 加密通过 Ingress 对象和ingress-nginx开源 Ingress Controller启用。该证书经理Kubernetes附加使用免费的续签和颁发证书让我们的加密证书颁发机构。
先决条件
要学习本教程,您需要:
- 启用了基于角色的访问控制(RBAC) 的Kubernetes 1.15+ 集群。此设置将使用DigitalOcean Kubernetes集群,但您可以使用另一种方法自由创建集群。
kubectl
安装在本地机器上并配置为连接到集群的命令行工具。您可以kubectl
在官方文档中阅读有关安装的更多信息。如果您使用的是 DigitalOcean Kubernetes 集群,请参阅如何连接到 DigitalOcean Kubernetes 集群以了解如何使用kubectl
.- 一个注册的域名。本教程将
your_domain.com
贯穿始终。您可以在Freenom免费获得一个,或者使用您选择的域名注册商。 - 一个ingress-nginx入口控制器和cert-manager TLS 证书管理器安装到您的集群中并配置为颁发 TLS 证书。要了解如何使用 cert-manager 安装和配置 Ingress,请参阅如何在 DigitalOcean Kubernetes 上使用 Cert-Manager 设置 Nginx Ingress。
- 指向 Ingress 负载均衡器公共 IP 地址的
A
DNS 记录your_domain.com
。如果您使用 DigitalOcean 来管理域的 DNS 记录,请参阅如何管理 DNS 记录以了解如何创建A
记录 - 一个 S3 对象存储桶,例如DigitalOcean Space,用于存储 Django 项目的静态文件和该空间的一组访问密钥。要了解如何创建空间,请参阅如何创建空间产品文档。要了解如何为空间创建访问密钥,请参阅使用访问密钥共享对空间的访问。只需稍作更改,您就可以使用django-storages插件支持的任何对象存储服务。
- Django 应用程序的 PostgreSQL 服务器实例、数据库和用户。只需稍作改动,您就可以使用Django 支持的任何数据库。
- PostgreSQL 数据库应该被称为polls(或者在下面的配置文件中输入另一个令人难忘的名字),在本教程中,Django 数据库用户将被命名为sammy。有关创建这些的指导,请按照如何使用 Docker 构建 Django 和 Gunicorn 应用程序的步骤 1 进行操作。您应该在本地机器上执行这些步骤。
- 本教程使用DigitalOcean Managed PostgreSQL 集群。要了解如何创建集群,请参阅 DigitalOcean Managed Databases 产品文档。
- 您还可以安装和运行您自己的 PostgreSQL 实例。有关在 Ubuntu 服务器上安装和管理 PostgreSQL 的指南,请参阅如何在 Ubuntu 18.04 上安装和使用 PostgreSQL。
- 一个泊坞窗中心账户和公共仓库。有关创建这些的更多信息,请参阅Docker 文档中的存储库。
- 安装在本地机器上的 Docker 引擎。请参阅如何在 Ubuntu 18.04 上安装和使用 Docker以了解更多信息。
设置好这些组件后,您就可以开始使用本指南了。
步骤 1 — 克隆和配置应用程序
在此步骤中,我们将从 GitHub 克隆应用程序代码并配置数据库凭据和对象存储密钥等设置。
应用程序代码和 Dockerfile 可以polls-docker
在 Django Tutorial Polls App GitHub 存储库的分支中找到。这个 repo 包含 Django 文档的示例 Polls application 的代码,它教你如何从头开始构建一个轮询应用程序。
该polls-docker
分支包含此 Polls 应用程序的 Dockerized 版本。要了解如何修改 Polls 应用程序以在容器化环境中有效工作,请参阅如何使用 Docker 构建 Django 和 Gunicorn 应用程序。
首先使用将 Django Tutorial Polls App GitHub 存储库git
的polls-docker
分支克隆到您的本地机器:
- git clone --single-branch --branch polls-docker https://github.com/do-community/django-polls.git
导航到django-polls
目录:
- cd django-polls
该目录包含 Django 应用程序 Python 代码,Dockerfile
Docker 将使用该代码构建容器映像,以及一个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 映像作为基础,并安装django-polls/requirements.txt
文件中定义的 Django 和 Gunicorn 的 Python 包要求。然后删除一些不必要的构建文件,将应用程序代码复制到映像中,并设置执行PATH
。最后,它声明 port8000
将用于接受传入的容器连接,并gunicorn
与 3 个 worker 一起运行,监听 port 8000
。
要了解有关此 Dockerfile 中每个步骤的更多信息,请参阅如何使用 Docker 构建 Django 和 Gunicorn 应用程序的步骤 6 。
现在,使用docker build
以下命令构建图像:
- docker build -t polls .
我们polls
使用-t
标志命名图像并将当前目录作为构建上下文传递,即构建图像时要引用的文件集。
在 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_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 文档中所述。调整可扩展 Django 应用教程的应用设置中提供了一种生成此密钥的方法。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
:将此设置为您的空间或对象存储的访问密钥 Secret。STATIC_BUCKET_NAME
:将此设置为您的空间名称或对象存储桶。STATIC_ENDPOINT_URL
:将其设置为适当的 Spaces 或对象存储端点 URL,例如,如果您的 Space 位于该区域。https://your_space_name.nyc3.digitaloceanspaces.com
nyc3
完成编辑后,保存并关闭文件。
在下一步中,我们将在本地运行配置的容器并创建数据库架构。我们还将将样式表和图像等静态资产上传到对象存储。
第 2 步 – 创建数据库架构并将资产上传到对象存储
构建和配置容器后,使用和命令docker run
覆盖CMD
Dockerfile 中的集合并创建数据库模式: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 将执行空操作。
接下来,我们将运行应用程序容器的另一个实例,并在其中使用交互式 shell 为 Django 项目创建管理用户。
- docker run -i -t --env-file env polls sh
这将在正在运行的容器内为您提供一个 shell 提示,您可以使用它来创建 Django 用户:
- python manage.py createsuperuser
为您的用户输入用户名、电子邮件地址和密码,创建用户后,点击CTRL+D
退出容器并杀死它。
最后,我们将为应用程序生成静态文件并使用collectstatic
. 请注意,这可能需要一些时间才能完成。
- 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
在本地计算机上被映射到端口8000
的的polls
容器。
您现在应该可以polls
通过http://localhost
在 URL 栏中键入来使用 Web 浏览器导航到该应用程序。由于没有为路径定义路由/
,您可能会收到一个404 Page Not Found
错误,这是意料之中的。
导航到http://localhost/polls
Polls 应用程序界面:
要查看管理界面,请访问http://localhost/admin
。您应该会看到 Polls 应用程序管理员身份验证窗口:
输入您使用该createsuperuser
命令创建的管理用户名和密码。
身份验证后,您可以访问 Polls 应用的管理界面:
请注意,应用程序admin
和polls
应用程序的静态资产直接从对象存储交付。要确认这一点,请参阅测试空间静态文件交付。
完成探索后,CTRL+C
在运行 Docker 容器的终端窗口中点击以终止容器。
测试 Django 应用 Docker 映像、将静态资产上传到对象存储、配置数据库架构并准备好与您的应用一起使用后,您就可以将 Django 应用映像上传到 Docker Hub 等映像注册表。
第 3 步 – 将 Django 应用镜像推送到 Docker Hub
要在 Kubernetes 上推出您的应用程序,您的应用程序映像必须上传到诸如Docker Hub 之类的注册表。Kubernetes 将从其存储库中提取应用程序映像,然后将其部署到您的集群。
您可以使用私有 Docker 注册表,例如DigitalOcean Container Registry,目前在 Early Access 中免费,或者使用公共 Docker 注册表,例如 Docker Hub。Docker Hub 还允许您创建私有 Docker 存储库。公共存储库允许任何人查看和拉取容器映像,而私有存储库允许您限制对您和您的团队成员的访问。
在本教程中,我们会将 Django 映像推送到先决条件中创建的公共 Docker Hub 存储库。您也可以将图像推送到私有存储库,但从私有存储库中提取图像超出了本文的范围。要了解有关使用 Docker Hub 对 Kubernetes 进行身份验证和提取私有映像的更多信息,请参阅Kubernetes 文档中的从私有注册表中提取映像。
首先登录到本地机器上的 Docker Hub:
- 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:
输入您的 Docker Hub 用户名和密码进行登录。
Django 图像当前具有polls:latest
标记。要将其推送到您的 Docker Hub 存储库,请使用您的 Docker Hub 用户名和存储库名称重新标记镜像:
- docker tag polls:latest your_dockerhub_username/your_dockerhub_repo_name:latest
将图像推送到 repo:
- docker push sammy/sammy-django:latest
在本教程中,Docker Hub 用户名是sammy,repo 名称是sammy-django。您应该将这些值替换为您自己的 Docker Hub 用户名和存储库名称。
您将看到一些输出,这些输出随着图像层被推送到 Docker Hub 而更新。
现在,您的映像可用于 Docker Hub 上的 Kubernetes,您可以开始在集群中推出它。
第 4 步 – 设置 ConfigMap
当我们在本地运行 Django 容器时,我们将env
文件传入docker run
以将配置变量注入运行时环境。在 Kubernetes 上,可以使用ConfigMaps和Secrets注入配置变量。
ConfigMaps 应该用于存储非机密的配置信息,如应用程序设置,而 Secrets 应该用于存储 API 密钥和数据库凭据等敏感信息。它们都以类似的方式注入到容器中,但 Secrets 具有额外的访问控制和安全功能,例如静态加密。Secrets 也以 base64 格式存储数据,而 ConfigMaps 以纯文本格式存储数据。
首先,创建一个名为的目录yaml
,我们将在其中存储 Kubernetes 清单。导航到目录。
- mkdir yaml
- cd
打开一个名为polls-configmap.yaml
中nano
或者您喜欢的文本编辑器:
- nano polls-configmap.yaml
粘贴以下 ConfigMap 清单:
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"
我们已经从env
在步骤 1 中修改的文件中提取了非敏感配置并将其粘贴到 ConfigMap 清单中。ConfigMap 对象被称为polls-config
。复制在env
上一步中输入到文件中的相同值。
出于测试目的,离开DJANGO_ALLOWED_HOSTS
作为*
对禁用基于主机的报头的过滤。在生产环境中,您应该将其设置为您的应用程序域。
完成文件编辑后,保存并关闭它。
使用kubectl apply
以下命令在集群中创建 ConfigMap :
- kubectl apply -f polls-configmap.yaml
Outputconfigmap/polls-config created
创建 ConfigMap 后,我们将在下一步中创建我们的应用程序使用的 Secret。
第 5 步 – 设置秘密
Secret 值必须是base64 编码的,这意味着在集群中创建 Secret 对象比创建 ConfigMap 稍微复杂一些。您可以重复上一步的过程,手动对 Secret 值进行 base64 编码并将它们粘贴到清单文件中。您还可以使用环境变量文件kubectl create
和--from-env-file
标志创建它们 ,我们将在此步骤中执行此操作。
我们将再次使用步骤 1 中的 env
文件,删除插入到 ConfigMap 中的变量。复制目录中调用的文件:env
polls-secrets
yaml
- 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
以下命令在您的集群中创建 Secret :
- kubectl create secret generic polls-secret --from-env-file=poll-secrets
Outputsecret/polls-secret created
这里我们创建了一个 Secret 对象,polls-secret
并传入我们刚刚创建的 secrets 文件。
您可以使用kubectl describe
以下方法检查 Secret :
- 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 部署是一个控制器,可用于管理集群中的无状态应用程序。控制器是一个控制回路,通过放大或缩小来调节工作负载。控制器还会重新启动并清除失败的容器。
部署控制一个或多个 Pod,这是 Kubernetes 集群中最小的可部署单元。Pod 包含一个或多个容器。要了解有关您可以启动的不同类型工作负载的更多信息,请查看Kubernetes 简介。
首先打开一个polls-deployment.yaml
在您喜欢的编辑器中调用的文件:
- nano 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 中推送到 Docker Hub 的 Django Polls 镜像。
在这里,我们定义了一个名为 Kubernetes Deploymentpolls-app
并用键值对标记它app: polls
。我们指定要运行template
字段下方定义的 Pod 的两个副本。
使用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
以下命令检查两个 Pod :
- 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 应用程序的两个副本现已启动并在集群中运行。要访问该应用程序,您需要创建一个 Kubernetes 服务,我们将在接下来进行。
步骤 7 — 允许使用服务进行外部访问
在此步骤中,您将为 Django 应用程序创建一个服务。Kubernetes Service 是一种抽象,它允许您将一组正在运行的 Pod 公开为网络服务。使用 Service,您可以为您的应用程序创建一个稳定的端点,该端点不会随着 Pod 死亡和重新创建而改变。
有多种服务类型,包括 ClusterIP 服务,它在集群内部 IP 上公开服务,NodePort 服务,在每个节点上的称为 NodePort 的静态端口上公开服务,以及 LoadBalancer 服务,它提供一个云负载均衡器。将外部流量定向到集群中的 Pod(通过它自动创建的 NodePorts)。要了解有关这些的更多信息,请参阅Kubernetes 文档中的服务。
在我们的最终设置中,我们将使用一个使用 Ingress 公开的 ClusterIP 服务,以及在本指南的先决条件中设置的 Ingress Controller。现在,为了测试一切是否正常运行,我们将创建一个临时的 NodePort 服务来访问 Django 应用程序。
首先polls-svc.yaml
使用您喜欢的编辑器创建一个名为的文件:
- nano polls-svc.yaml
粘贴以下服务清单:
apiVersion: v1
kind: Service
metadata:
name: polls
labels:
app: polls
spec:
type: NodePort
selector:
app: polls
ports:
- port: 8000
targetPort: 8000
在这里,我们创建了一个名为 NodePort 的服务polls
并为其指定app: polls
标签。然后我们选择带有app: polls
标签的后端 Pod并定位它们的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 浏览器中,使用任何 Node 的外部 IP 地址和 NodePort 访问您的 Polls 应用程序。鉴于上面的输出,应用程序的 URL 将是:。http://203.0.113.1:32654/polls
您应该会看到与您在步骤 1 中本地访问的相同的 Polls 应用程序界面:
您可以使用/admin
route:重复相同的测试。您应该会看到与以前相同的管理界面:http://203.0.113.1:32654/admin
在此阶段,您已使用 Deployment 推出了 Django Polls 应用程序容器的两个副本。您还为这两个副本创建了一个稳定的网络端点,并使用 NodePort 服务使其可从外部访问。
本教程的最后一步是使用 HTTPS 保护到您的应用程序的外部流量。为此,我们将使用ingress-nginx
先决条件中安装的入口控制器,并创建一个入口对象来将外部流量路由到polls
Kubernetes 服务。
第 8 步 – 使用 Nginx Ingress 和 cert-manager 配置 HTTPS
Kubernetes Ingresses允许您灵活地将流量从 Kubernetes 集群外部路由到集群内部的服务。这是使用 Ingress 对象完成的,这些对象定义了将 HTTP 和 HTTPS 流量路由到 Kubernetes 服务的规则,以及 Ingress Controllers,它们通过负载平衡流量并将其路由到适当的后端服务来实现规则。
在先决条件中,您安装了ingress-nginx入口控制器和cert-manager TLS 证书自动化插件。您还使用 Let’s Encrypt 证书颁发机构为您的域设置了临时和生产 ClusterIssuers,并创建了一个 Ingress 来测试证书颁发和 TLS 加密到两个虚拟后端服务。在继续此步骤之前,您应该删除echo-ingress
在先决条件教程中创建的Ingress :
- kubectl delete ingress echo-ingress
如果您愿意,也可以使用kubectl delete svc
和删除虚拟服务和部署kubectl delete deploy
,但这对于完成本教程不是必需的。
您还应该创建一个指向 Ingress 负载均衡器公共 IP 地址的 DNSA
记录your_domain.com
。如果您使用的是 DigitalOcean 负载均衡器,您可以在控制面板的负载均衡器部分找到此 IP 地址。如果您还使用 DigitalOcean 来管理域的 DNS 记录,请参阅如何管理 DNS 记录以了解如何创建A
记录。
如果您使用的是 DigitalOcean Kubernetes,还要确保您已经实施了如何在 DigitalOcean Kubernetes 上使用 Cert-Manager 设置 Nginx Ingress 的步骤 5 中描述的解决方法。
一旦你有一个A
记录指向入口控制器负载均衡器,你可以创建一个入口并your_domain.com
与polls
服务。
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
我们创建一个名为的 Ingress 对象polls-ingress
并对其进行注释,以指示控制平面使用 ingress-nginx Ingress Controller 和暂存 ClusterIssuer。我们还为your_domain.com
证书和私钥启用 TLS并将其存储在名为polls-tls
. 最后,我们定义了一个规则来将your_domain.com
主机的流量路由到polls
端口上的服务8000
。
完成文件编辑后,保存并关闭它。
使用kubectl apply
以下命令在集群中创建 Ingress :
- kubectl apply -f polls-ingress.yaml
Outputingress.networking.k8s.io/polls-ingress created
您可以使用kubectl describe
来跟踪您刚刚创建的 Ingress 的状态:
- 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
您还可以describe
在polls-tls
证书上运行 a以进一步确认其成功创建:
- 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 证书已成功颁发并且 HTTPS 加密现在对your_domain.com
.
鉴于我们使用了暂存 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 成功测试了证书颁发,您可以修改 Ingress 以使用生产 ClusterIssuer。
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
以下命令更新 Ingress :
- 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
Secret 中。
your_domain.com/polls
在 Web 浏览器中导航到以确认 HTTPS 加密已启用且一切正常。您应该会看到 Polls 应用程序界面:
验证 HTTPS 加密在您的 Web 浏览器中处于活动状态。如果您使用的是谷歌浏览器,在没有任何错误的情况下到达上述页面即确认一切正常。此外,您应该会在 URL 栏中看到一个挂锁。单击挂锁将允许您检查 Let’s Encrypt 证书详细信息。
作为最后的清理任务,您可以选择将polls
服务类型从 NodePort 切换到仅限内部使用的 ClusterIP 类型。
polls-svc.yaml
使用您的编辑器进行修改:
- nano polls-svc.yaml
type
将从更改NodePort
为ClusterIP
:
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
This output shows that the Service type is now ClusterIP. The only way to access it is via your domain and the Ingress created in this step.
Conclusion
In this tutorial you deployed a scalable, HTTPS-secured Django app into a Kubernetes cluster. Static content is served directly from object storage, and the number of running Pods can be quickly scaled up or down using the replicas
field in the polls-app
Deployment manifest.
If you’re using a DigitalOcean Space, you can also enable delivery of static assets via a content delivery network and create a custom subdomain for your Space. Please consult Enabling CDN from How to Set Up a Scalable Django App with DigitalOcean Managed Databases and Spaces to learn more.
要查看本系列的其余部分,请访问我们的从容器到 Kubernetes with Django 系列页面。