웹사이트 검색

Kubernetes로 확장 가능하고 안전한 Django 애플리케이션을 배포하는 방법


소개

이 튜토리얼에서는 컨테이너화된 Django 폴링 애플리케이션을 Kubernetes 클러스터에 배포합니다.

템플릿 시스템.

From Containers to Kubernetes with Django 시리즈에서는 현대화된 Django 투표 애플리케이션이 Kubernetes 클러스터에 배포됩니다.

인증 기관을 암호화합시다.

전제 조건

이 자습서를 따르려면 다음이 필요합니다.

  • 다른 방법을 사용하는 Kubernetes 1.15+ 클러스터.
  • 로컬 시스템에 설치되고 클러스터에 연결하도록 구성된 kubectl 명령줄 도구. kubectl DigitalOcean Kubernetes 클러스터에 연결하는 방법 설치에 대해 자세히 읽고 kubectl을 사용하여 클러스터에 연결하는 방법을 알아볼 수 있습니다.
  • 등록된 도메인 이름. 이 자습서에서는 전체적으로 your_domain.com을 사용합니다. Freenom에서 무료로 받거나 선택한 도메인 등록 기관을 사용할 수 있습니다.
  • DigitalOcean Kubernetes에서 Cert-Manager로 Nginx 인그레스를 설정하는 방법
  • Ingress 로드 밸런서의 공개 IP 주소를 가리키는 your_domain.com이 있는 A DNS 레코드. DigitalOcean을 사용하여 도메인의 DNS 레코드를 관리하는 경우 DNS 레코드 관리 방법을 참조하여 A 레코드를 생성하는 방법을 알아보세요.
  • django-storages 플러그인과 같은 S3 객체 스토리지 버킷이 지원합니다.
  • Django 앱의 PostgreSQL 서버 인스턴스, 데이터베이스 및 사용자. 사소한 변경으로 Django가 지원하는 모든 데이터베이스를 사용할 수 있습니다.\n
    • PostgreSQL 데이터베이스는 polls(또는 아래 구성 파일에 입력할 기억하기 쉬운 다른 이름)라고 해야 하며 이 자습서에서는 Django 데이터베이스 사용자의 이름을 sammy로 지정합니다. 이들 생성에 대한 지침은 Docker로 Django 및 Gunicorn 애플리케이션을 빌드하는 방법의 1단계를 따르십시오. 로컬 시스템에서 이 단계를 수행해야 합니다.
    • DigitalOcean 관리형 데이터베이스 제품 설명서
    • 자신만의 PostgreSQL 인스턴스를 설치하고 실행할 수도 있습니다. Ubuntu 서버에서 PostgreSQL을 설치하고 관리하는 방법에 대한 지침은 Ubuntu 18.04에서 PostgreSQL을 설치하고 사용하는 방법을 참조하세요.

    이러한 구성 요소를 설정했으면 이 가이드를 시작할 준비가 된 것입니다.

    1단계 - 애플리케이션 복제 및 구성

    이 단계에서는 GitHub에서 애플리케이션 코드를 복제하고 데이터베이스 자격 증명 및 객체 스토리지 키와 같은 설정을 구성합니다.

    애플리케이션 코드와 Dockerfile은 Django Tutorial Polls App 샘플 Polls 애플리케이션의 polls-docker 브랜치에서 찾을 수 있습니다. 여기에서 폴링 애플리케이션을 처음부터 빌드하는 방법을 배울 수 있습니다.

    polls-docker 브랜치에는 이 Polls 앱의 Docker화된 버전이 포함되어 있습니다. Polls 앱이 컨테이너화된 환경에서 효과적으로 작동하도록 수정된 방법을 알아보려면 Docker를 사용하여 Django 및 Gunicorn 애플리케이션을 빌드하는 방법을 참조하십시오.

    git을 사용하여 Django Tutorial Polls App GitHub 리포지토리의 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 이미지를 기본으로 사용하고 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는 구성된 환경 변수를 컨테이너의 실행 환경에 주입합니다.

    nano 또는 선호하는 편집기로 env 파일을 엽니다.

    1. 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: Scalable 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로 설정합니다(예: https://your_space_name.nyc3.digitaloceanspaces.com ). 귀하의 공간이 nyc3 지역에 있는 경우.

    편집이 끝나면 파일을 저장하고 닫습니다.

    다음 단계에서는 구성된 컨테이너를 로컬에서 실행하고 데이터베이스 스키마를 생성합니다. 또한 스타일시트 및 이미지와 같은 정적 자산을 개체 저장소에 업로드합니다.

    2단계 - 데이터베이스 스키마 생성 및 오브젝트 스토리지에 자산 업로드

    컨테이너를 빌드하고 구성한 상태에서 docker run을 사용하여 Dockerfile에 설정된 CMD를 재정의하고 manage.py makemigrations를 사용하여 데이터베이스 스키마를 생성합니다. 및 manage.py 마이그레이션 명령:

    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을 사용하여 DigitalOcean Space에 업로드합니다. 완료하는 데 약간의 시간이 걸릴 수 있습니다.

    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을 노출하여 포트가 로컬 시스템의 80polls 컨테이너의 포트 8000에 매핑됩니다.

    이제 URL 표시줄에 http://localhost를 입력하여 웹 브라우저를 사용하여 polls 앱으로 이동할 수 있습니다. / 경로에 대해 정의된 경로가 없으므로 404 페이지를 찾을 수 없음 오류가 발생할 가능성이 높습니다.

    투표 앱 인터페이스를 보려면 http://localhost/polls로 이동합니다.

    관리 인터페이스를 보려면 http://localhost/admin을 방문하십시오. 설문 조사 앱 관리자 인증 창이 표시되어야 합니다.

    createsuperuser 명령으로 만든 관리 사용자 이름과 암호를 입력합니다.

    인증 후 투표 앱의 관리 인터페이스에 액세스할 수 있습니다.

    adminpolls 앱에 대한 정적 자산은 개체 저장소에서 직접 제공됩니다. 이를 확인하려면 Testing Spaces Static File Delivery를 참조하십시오.

    탐색을 마쳤으면 Docker 컨테이너를 실행하는 터미널 창에서 CTRL+C를 눌러 컨테이너를 종료합니다.

    테스트된 Django 앱 Docker 이미지, 오브젝트 스토리지에 업로드된 정적 자산, 구성되어 앱과 함께 사용할 준비가 된 데이터베이스 스키마를 사용하면 Django 앱 이미지를 Docker Hub와 같은 이미지 레지스트리에 업로드할 준비가 된 것입니다.

    3단계 — Django 앱 이미지를 Docker 허브로 푸시

    Kubernetes에서 앱을 롤아웃하려면 앱 이미지를 Docker Hub와 같은 레지스트리에 업로드해야 합니다. Kubernetes는 리포지토리에서 앱 이미지를 가져온 다음 클러스터에 배포합니다.

    현재 Early Access에서 무료로 제공되는 DigitalOcean Container Registry와 같은 개인 Docker 레지스트리 또는 Docker Hub와 같은 공용 Docker 레지스트리를 사용할 수 있습니다. Docker Hub를 사용하면 비공개 Docker 리포지토리를 만들 수도 있습니다. 공개 리포지토리를 사용하면 누구나 컨테이너 이미지를 보고 가져올 수 있으며, 비공개 리포지토리를 사용하면 귀하와 귀하의 팀 구성원에 대한 액세스를 제한할 수 있습니다.

    이 자습서에서는 Django 이미지를 전제 조건에서 생성된 공개 Docker Hub 리포지토리로 푸시합니다. 이미지를 프라이빗 리포지토리로 푸시할 수도 있지만 프라이빗 리포지토리에서 이미지를 가져오는 것은 이 문서의 범위를 벗어납니다. Docker Hub로 Kubernetes를 인증하고 비공개 이미지를 가져오는 방법에 대해 자세히 알아보려면 Kubernetes 문서에서 비공개 레지스트리에서 이미지 가져오기를 참조하세요.

    로컬 머신에서 Docker Hub에 로그인하여 시작합니다.

    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:

    로그인하려면 Docker Hub 사용자 이름과 암호를 입력하십시오.

    Django 이미지에는 현재 polls:latest 태그가 있습니다. Docker Hub 리포지토리로 푸시하려면 Docker Hub 사용자 이름 및 리포지토리 이름으로 이미지에 다시 태그를 지정합니다.

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

    저장소에 이미지를 푸시합니다.

    1. docker push sammy/sammy-django:latest

    이 자습서에서 Docker Hub 사용자 이름은 sammy이고 리포지토리 이름은 sammy-django입니다. 이 값을 고유한 Docker Hub 사용자 이름 및 리포지토리 이름으로 바꿔야 합니다.

    이미지 레이어가 Docker Hub로 푸시될 때 업데이트되는 일부 출력이 표시됩니다.

    Docker Hub의 Kubernetes에서 이미지를 사용할 수 있으므로 이제 클러스터에서 롤아웃을 시작할 수 있습니다.

    4단계 - ConfigMap 설정

    Django 컨테이너를 로컬로 실행할 때 env 파일을 docker run에 전달하여 구성 변수를 런타임 환경에 주입했습니다. Kubernetes에서 비밀을 사용하여 구성 변수를 주입할 수 있습니다.

    ConfigMaps는 앱 설정과 같은 비기밀 구성 정보를 저장하는 데 사용해야 하며 Secrets는 API 키 및 데이터베이스 자격 증명과 같은 민감한 정보에 사용해야 합니다. 둘 다 비슷한 방식으로 컨테이너에 주입되지만 Secrets에는 미사용 암호화와 같은 추가 액세스 제어 및 보안 기능이 있습니다. 비밀은 또한 base64에 데이터를 저장하는 반면 ConfigMap은 데이터를 일반 텍스트로 저장합니다.

    시작하려면 Kubernetes 매니페스트를 저장할 yaml이라는 디렉터리를 만듭니다. 디렉터리로 이동합니다.

    1. mkdir yaml
    2. cd

    nano 또는 선호하는 텍스트 편집기에서 polls-configmap.yaml 파일을 엽니다.

    1. 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"
    

    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 플래그를 사용하여 생성할 수도 있으며 이 단계에서 수행할 것입니다.

    다시 한 번 1단계의 env 파일을 사용하여 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 배포는 클러스터에서 상태 비저장 애플리케이션을 관리하는 데 사용할 수 있는 컨트롤러입니다. 컨트롤러는 워크로드를 확장 또는 축소하여 워크로드를 조절하는 제어 루프입니다. 컨트롤러는 또한 실패한 컨테이너를 다시 시작하고 정리합니다.

    배포는 Kubernetes 클러스터에서 배포 가능한 가장 작은 단위인 하나 이상의 포드를 제어합니다. 포드는 하나 이상의 컨테이너를 포함합니다. 실행할 수 있는 다양한 유형의 워크로드에 대해 자세히 알아보려면 Kubernetes 소개를 검토하세요.

    좋아하는 편집기에서 polls-deployment.yaml 파일을 열어 시작합니다.

    1. 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 이미지를 참조하여 적절한 컨테이너 이미지 이름을 입력합니다.

    여기에서 polls-app이라는 Kubernetes 배포를 정의하고 키-값 쌍 app: polls로 레이블을 지정합니다. template 필드 아래에 정의된 Pod의 두 복제본을 실행하도록 지정합니다.

    secretRefconfigMapRef와 함께 envFrom을 사용하여 polls-secret Secret 및 의 모든 데이터가 >polls-config ConfigMap은 환경 변수로 컨테이너에 주입되어야 합니다. ConfigMap 및 비밀 키는 환경 변수 이름이 됩니다.

    마지막으로 containerPort 8000을 노출하고 이름을 gunicorn으로 지정합니다.

    Kubernetes 배포 구성에 대한 자세한 내용은 Kubernetes 설명서에서 배포를 참조하십시오.

    파일 편집이 끝나면 저장하고 닫습니다.

    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를 사용하여 두 포드를 검사할 수 있습니다.

    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 앱의 복제본 두 개가 클러스터에서 실행되고 있습니다. 앱에 액세스하려면 다음에 수행할 Kubernetes 서비스를 생성해야 합니다.

    7단계 - 서비스를 사용하여 외부 액세스 허용

    이 단계에서는 Django 앱용 서비스를 생성합니다. Kubernetes Service는 실행 중인 Pod 집합을 네트워크 서비스로 노출할 수 있는 추상화입니다. 서비스를 사용하면 포드가 죽고 다시 생성될 때 변경되지 않는 안정적인 앱 엔드포인트를 생성할 수 있습니다.

    서비스를 클러스터 내부 IP에 노출하는 ClusterIP 서비스, NodePort라는 정적 포트에서 각 노드의 서비스를 노출하는 NodePort 서비스, 클라우드 로드 밸런서를 프로비저닝하는 LoadBalancer 서비스 등 여러 서비스 유형이 있습니다. 자동으로 생성되는 NodePort를 통해 외부 트래픽을 클러스터의 Pod로 보냅니다. 이에 대한 자세한 내용은 Kubernetes 문서의 서비스를 참조하세요.

    최종 설정에서는 이 가이드의 전제 조건에 설정된 수신 및 수신 컨트롤러를 사용하여 노출되는 ClusterIP 서비스를 사용합니다. 지금은 모든 것이 올바르게 작동하는지 테스트하기 위해 Django 앱에 액세스하기 위한 임시 NodePort 서비스를 생성합니다.

    좋아하는 편집기를 사용하여 polls-svc.yaml이라는 파일을 생성하여 시작합니다.

    1. 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
    

    여기에서 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

    웹 브라우저에서 Node의 외부 IP 주소와 NodePort를 사용하여 Polls 앱을 방문하십시오. 위의 출력에서 앱의 URL은 http://203.0.113.1:32654/polls입니다.

    1단계에서 로컬로 액세스한 것과 동일한 설문 조사 앱 인터페이스가 표시되어야 합니다.

    /admin 경로( http://203.0.113.1:32654/admin)를 사용하여 동일한 테스트를 반복할 수 있습니다. 이전과 동일한 관리 인터페이스가 표시되어야 합니다.

    이 단계에서 배포를 사용하여 Django Polls 앱 컨테이너의 복제본 두 개를 롤아웃했습니다. 또한 이 두 복제본에 대해 안정적인 네트워크 끝점을 만들고 NodePort 서비스를 사용하여 외부에서 액세스할 수 있도록 했습니다.

    이 자습서의 마지막 단계는 HTTPS를 사용하여 앱에 대한 외부 트래픽을 보호하는 것입니다. 이를 위해 전제 조건에 설치된 ingress-nginx 인그레스 컨트롤러를 사용하고 외부 트래픽을 polls Kubernetes 서비스로 라우팅하는 인그레스 객체를 생성합니다.

    8단계 - Nginx Ingress 및 cert-manager를 사용하여 HTTPS 구성

    Kubernetes Ingress를 사용하면 Kubernetes 클러스터 외부에서 클러스터 내부의 서비스로 트래픽을 유연하게 라우팅할 수 있습니다. 이는 HTTP 및 HTTPS 트래픽을 Kubernetes Services로 라우팅하기 위한 규칙을 정의하는 Ingress 개체와 트래픽 부하를 분산하고 적절한 백엔드 서비스로 라우팅하여 규칙을 구현하는 Ingress 컨트롤러를 사용하여 수행됩니다.

    전제 조건에서 전제 조건 자습서를 설치했습니다.

    1. kubectl delete ingress echo-ingress

    원하는 경우 kubectl delete svckubectl delete deploy를 사용하여 더미 서비스 및 배포를 삭제할 수도 있지만 이 튜토리얼을 완료하는 데 필수적인 것은 아닙니다.

    Ingress 로드 밸런서의 공개 IP 주소를 가리키는 your_domain.com이 있는 DNS A 레코드도 생성했어야 합니다. DigitalOcean Load Balancer를 사용하는 경우 DNS 레코드 관리 방법에서 이 IP 주소를 찾아 A 레코드를 만드는 방법을 알아볼 수 있습니다.

    DigitalOcean Kubernetes를 사용하는 경우 DigitalOcean Kubernetes에서 Cert-Manager로 Nginx Ingress를 설정하는 방법의 5단계에 설명된 해결 방법을 구현했는지도 확인하세요.

    인그레스 컨트롤러 로드 밸런서를 가리키는 A 레코드가 있으면 your_domain.com폴링에 대한 인그레스를 만들 수 있습니다. 서비스.

    원하는 편집기를 사용하여 polls-ingress.yaml 파일을 엽니다.

    1. nano polls-ingress.yaml

    다음 인그레스 매니페스트를 붙여넣습니다.

    [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-nginx Ingress 컨트롤러와 스테이징 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를 사용하여 방금 생성한 Ingress의 상태를 추적할 수 있습니다.

    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 인증서가 성공적으로 발급되었고 HTTPS 암호화가 이제 your_domain.com에 대해 활성화되었음을 확인합니다.

    스테이징 ClusterIssuer를 사용했기 때문에 대부분의 웹 브라우저는 발급된 가짜 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를 사용하여 Ingress를 업데이트합니다.

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

    kubectl describe certificate polls-tlskubectl 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 Secret에 저장되었음을 확인합니다.

    웹 브라우저에서 your_domain.com/polls로 이동하여 HTTPS 암호화가 활성화되어 있고 모든 것이 예상대로 작동하는지 확인합니다. 투표 앱 인터페이스가 표시되어야 합니다.

    웹 브라우저에서 HTTPS 암호화가 활성화되어 있는지 확인하십시오. Google Chrome을 사용하는 경우 오류 없이 위의 페이지에 도달하면 모든 것이 올바르게 작동하는 것입니다. 또한 URL 표시줄에 자물쇠가 표시되어야 합니다. 자물쇠를 클릭하면 Let’s Encrypt 인증서 세부 정보를 검사할 수 있습니다.

    최종 정리 작업으로 polls 서비스 유형을 NodePort에서 내부 전용 ClusterIP 유형으로 선택적으로 전환할 수 있습니다.

    편집기를 사용하여 polls-svc.yaml을 수정합니다.

    1. nano polls-svc.yaml

    유형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를 사용하여 변경 사항을 롤아웃합니다.

    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임을 보여줍니다. 액세스할 수 있는 유일한 방법은 도메인과 이 단계에서 생성된 인그레스를 통하는 것입니다.

    결론

    이 자습서에서는 확장 가능한 HTTPS 보안 Django 앱을 Kubernetes 클러스터에 배포했습니다. 정적 콘텐츠는 개체 스토리지에서 직접 제공되며 실행 중인 포드 수는 polls-app 배포 매니페스트의 replicas 필드를 사용하여 빠르게 확장하거나 축소할 수 있습니다.

    DigitalOcean Space를 사용하는 경우 콘텐츠 전송 네트워크를 통해 정적 자산의 전송을 활성화하고 공간에 대한 사용자 정의 하위 도메인을 생성할 수도 있습니다. 자세한 내용은 DigitalOcean Managed Databases and Spaces로 확장 가능한 Django 앱을 설정하는 방법에서 CDN 활성화를 참조하십시오.

    시리즈의 나머지 부분을 검토하려면 Django 시리즈 페이지에서 컨테이너에서 쿠버네티스까지를 방문하십시오.