Рубрики
Без рубрики

Разверните любой проект Python в Kubernetes

По мере роста вашего проекта он может добраться до того, что оно становится слишком сложно, чтобы справиться с одним … Теги с DevOps, Python, Docker, Cloud.

Когда ваш проект растет, он может добраться до того, что оно становится слишком сложно, чтобы справиться с одним виртуалом или несколькими простыми решениеми SaaS. Вы можете решить, что, переключаясь на более надежное решение, как Кубернеты . Это, однако, может быть немного сложным, если вы не знакомы с его концепциями или если просто никогда не использовали его раньше. Итак, чтобы помочь вам – в этой статье – мы перейдем над всем, что вам нужно, чтобы самостоятельно начаться, и у вас Python Проект развернут на кластере – включая настройку кластера, все Кубернаны проявляется и некоторая дополнительная автоматизация, чтобы сделать вашу жизнь проще по дороге!

Это следующее до предыдущей статьи (ов) о Автоматизация каждого аспекта вашего проекта Python Так что вы можете проверить это, прежде чем прочитать этот.

TL; DR: Вот мой репозиторий с полным исходным кодом и документами: https://github.com/MartinHeinz/python-project-blueprint

Установка удобной разработки

Быть продуктивным в вашем процессе разработки, вам нужно иметь Удобность Местное разработка Настройка. Что в этом случае означает простых в использовании Кубернаны На местном, внимательно отражающем ваш реальный, производственный кластер и для этого мы будем использовать Добрый :

Добрый (Кубернес-in-докер) Как подразумевает имя, работает Кубернаны кластеры в Докер контейнеры. Это официальный инструмент, используемый Кубернаны сопровождающие для Кубернаны V1.11 + тестирование соответствия. Он поддерживает мульти-узловые кластеры, а также кластеры HA. Потому что он работает K8s в Докер , Добрый Может работать на Windows, Mac и Linux. Итак, вы можете запустить его где угодно, вам просто нужно установить Docker.

Итак, давайте установимся Добрый (на Linux – если вы находитесь в Windows, см. Информацию о установке здесь ):

~ $ curl -Lo ./kind https://github.com/kubernetes-sigs/kind/releases/download/v0.7.0/kind-$(uname)-amd64
~ $ chmod +x ./kind
~ $ sudo mv ./kind /usr/local/bin/kind
~ $ kind --version
kind version 0.7.0

С этим мы готовы настроить наш кластер. Для этого нам понадобится следующий файл YAML:

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  kubeadmConfigPatches:
  - |
    kind: InitConfiguration
    nodeRegistration:
      kubeletExtraArgs:
        node-labels: "ingress-ready=true"
        authorization-mode: "AlwaysAllow"
  extraPortMappings:
  - containerPort: 80
    hostPort: 80
    protocol: TCP
  - containerPort: 443
    hostPort: 443
    protocol: TCP
- role: worker
- role: worker

Этот манифест описывает наш кластер. У него будет 3 узла – плоскость управления ( Роль: Контроль-плоскость ) и 2 рабочих Роль: работник Отказ Мы также даем ему еще несколько настроек и аргументов, чтобы позволить настроить контроллер входа позже, чтобы мы могли иметь HTTPS на этом кластере. Все, что вам нужно знать об этих настройках, это то, что внепортмены Сообщает кластеру пересылать порты от хоста на контроллер входа, работающего на узле.

Примечание: все проявления как для кластера, так и для _PYthon Приложение доступно в моем репо здесь в K8s каталог. _

Теперь нам нужно запустить несколько команд, чтобы принести это:

$ ~ kind create cluster --config kind-config.yaml --name cluster
$ ~ kubectl cluster-info --context kind-cluster
Kubernetes master is running at https://127.0.0.1:32769
KubeDNS is running at https://127.0.0.1:32769/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

$ ~ kubectl get nodes
NAME                    STATUS    ROLES     AGE       VERSION
cluster-control-plane   Ready     master    2m39s     v1.17.0
cluster-worker          Ready         2m3s      v1.17.0
cluster-worker2         Ready         2m3s      v1.17.0

Чтобы создать кластер, нам просто нужно запустить первую команду. После этого мы можем проверить, хорошо ли пойти бежать Кластер-информация и Получить узлы команды. Выбрав эти команды, надоедят через некоторое время, поэтому мы будем Сделать Это проще позже, но с этим у нас есть кластер и работает.

Далее мы хотим настроить вход Для нашего кластера. Для этого мы должны бежать несколько kubectl Команды, чтобы сделать это работать с Добрый :

~ $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
~ $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/baremetal/service-nodeport.yaml
~ $ kubectl patch deployments -n ingress-nginx nginx-ingress-controller -p '{"spec":{"template":{"spec":{"containers":[{"name":"nginx-ingress-controller","ports":[{"containerPort":80,"hostPort":80},{"containerPort":443,"hostPort":443}]}],"nodeSelector":{"ingress-ready":"true"},"tolerations":[{"key":"node-role.kubernetes.io/master","operator":"Equal","effect":"NoSchedule"}]}}}}'

Сначала мы развертываем обязательные Ingress-Nginx компоненты. Кроме того, мы выставляем nginx Сервис с использованием Нотепорт , что делает второй команд. Последняя команда применяется некоторые Добрый Специфические патчи для контроллера входа.

Определение проявления

С помощью кластеров готов, пришло время настроить и развернуть наше приложение. Для этого мы будем использовать очень просто Колбу Применение – Echo Server :

# __main__.py

from flask import Flask, request

app = Flask(__name__)


@app.route("/")
def echo():
    return f"You said: {request.args.get('text', '')}\n"


if __name__ == "__main__":
    app.run(host='0.0.0.0', port=5000)

Я выбрал Колбу Приложение вместо какого-либо инструмента CLI (или Python пакет), поскольку нам нужно приложение, которое не будет расторгнуть мгновенно, как некоторые Python пакет будет. Также обратите внимание хозяин Параметр установлен на 0,0.0.0 Без этого не удалось добраться до приложения, когда мы выставляем его через Кубернаны Сервис и проникновение.

Следующее, что нам нужно, это ямль, проявляется для этого приложения, давайте сломаемся на отдельные объекты:

  • Пространство имен:
apiVersion: v1
kind: Namespace
metadata:
  name: blueprint

Нечего говорить здесь. Как правило, мы не хотим развертывать приложения в по умолчанию пространство имен, так что это тот, который будет вместо этого будет использовать.

  • Configmap:
apiVersion: v1
kind: ConfigMap
metadata:
  name: env-config-blueprint
  namespace: blueprint
data:  # Example vars that will get picked up by Flask application
  FLASK_ENV: development
  FLASK_DEBUG: "1"

Это где мы можем определить переменные для приложения. Эти варс от данные Раздел будет введен в контейнер приложения в качестве переменных среды. В качестве примера я включил Flask_env и Flask_debug , который будет поднят Колбу автоматически при запуске приложения.

  • Секрет:
apiVersion: v1
kind: Secret
metadata:
  name: env-secrets-blueprint
  namespace: blueprint
data:
  VAR: VkFMVUU=  # base64 of "VALUE"

Так же, как мы указываем открытый текст варс, мы можем использовать Секрет Чтобы добавить такие вещи, как учетные данные и клавиши в наше приложение. Этот объект, однако, не должен быть отодвинут в ваш репозиторий, как оно содержит конфиденциальные данные. Мы можем создавать его динамически со следующей командой:

~ $ kubectl create secret generic env-secrets-blueprint -n blueprint \
    --from-literal=VAR=VALUE \
    --from-literal=VAR2=VALUE2 \
    --dry-run -o yaml >> app.yaml

Примечание. Это и другие команды, необходимые для развертывания приложения, перечислены в README в репозитории, а также в нижних манифестах файл здесь

  • Развертывание:
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: blueprint
  name: blueprint
  namespace: blueprint
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: blueprint
    spec:
      containers:
#        - image: docker.pkg.github.com/martinheinz/python-project-blueprint/example:flask
#          ^^^^^  https://github.com/containerd/containerd/issues/3291 https://github.com/kubernetes-sigs/kind/issues/870
        - image: martinheinz/python-project-blueprint:flask
          name: blueprint
          imagePullPolicy: Always
          ports:
            - containerPort: 5000
              protocol: TCP
          envFrom:
            - configMapRef:
                name: env-config-blueprint
            - secretRef:
                name: env-secrets-blueprint
#      imagePullSecrets:  # In case you are using private registry (see kubectl command at the bottom on how to create regcred)
#        - name: regcred
  selector:
    matchLabels:
      app: blueprint

Теперь для самой важной части – Развертывание Отказ Соответствующая часть здесь – Спец Раздел, который определяет изображение, порты и переменные среды. Для изображение Мы указываем изображение из Docker Hub Отказ Если мы хотели использовать какой-то частный реестр, как Артефактория нам придется добавить imagepullsecret который дает учетные данные кластера для потягивания изображения. Этот секрет может быть создан с помощью следующей команды:

kubectl create secret docker-registry regcred \
    --docker-server=docker.pkg.github.com \
    --docker-username= --docker-password= \
    --dry-run -o yaml >> app.yaml

Это показывает, как вы позволили потянуть ваши изображения из GitHub Package Registry , который, к сожалению, не работает с Добрый Прямо сейчас из-за проблем, перечисленных в вышеуказанном ямле , но Это будет работать совсем хорошо с вашим производственным кластером в облаке (предполагая, что он не использует добрые ).

Если вы хотите избежать толкания изображения в удаленный реестр каждый раз, когда вы перераспределите свое приложение, то можете нагрузка Ваше изображение в кластер с помощью добрые нагрузки докен-изображение Martinheinz/Python-Project-stoneprint: колба Отказ

После изображение , мы также указываем порты . Это порты, на которые наша заявка слушает, в этом случае 5000 потому что наше приложение начинает использовать app.run (host = '0.0.0.0',) Отказ

Последняя часть, Engram Раздел используется для введения переменных и секретов открытого текста от Configmap. и Секрет показано выше, указав их имена в соответствующей Ref поля.

  • Оказание услуг:
apiVersion: v1
kind: Service
metadata:
  name: blueprint
  namespace: blueprint
  labels:
    app: blueprint
spec:
  selector:
    app: blueprint
  ports:
    - name: http
      targetPort: 5000  # port the container accepts traffic on
      port: 443  # port other pods use to access the Service
      protocol: TCP

Теперь, что у нас есть приложение, слушая на порт нам нужно Сервис это будет разоблачить это. Все эти объекты определяют это приложение, слушающее порта 5000 должен быть выставлен на кластерный узел на порту 443 .

  • Вход:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: blueprint-ingress
  namespace: blueprint
  annotations:
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
  labels:
    app: blueprint
spec:
  tls:
    - hosts:
      - localhost
      secretName: tls-secret
  rules:
    - host: localhost
      http:
        paths:
          - path: "/"
            backend:
              serviceName: blueprint
              servicePort: 443

Последний большой кусок головоломки – Вход – объект, который управляет внешним доступом к Услуги в кластере. Давайте сначала посмотрим на правила Раздел – в этом случае мы определяем, что наш хост локальный . Мы также устанавливаем путь к / Это означает, что любой запрос отправлен на localhost/ принадлежит связанным Backend Определяется по имени ранее показано Сервис и его порт Отказ

Другой раздел здесь TLS. . Этот раздел предоставляет HTTPS для перечисленных хозяева Указав Секрет Это включает в себя tlscrt. и Tlskey Отказ Давайте создадим это Секрет :

KEY_FILE="blueprint.key"
CERT_FILE="blueprint.crt"
HOST="localhost"
CERT_NAME=tls-secret
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ${KEY_FILE} -out ${CERT_FILE} -subj "/CN=${HOST}/O=${HOST}"
kubectl create secret tls ${CERT_NAME} --key ${KEY_FILE} --cert ${CERT_FILE} --dry-run -o yaml >> app.yaml

Над фрагментом сначала устанавливает несколько переменных, которые затем используются для генерации сертификата и ключевых файлов для TLS, используя openssl Отказ Последняя команда создает Секрет содержащий эти 2 файла.

Развертывание приложения

Со всеми проявлениями готовыми, мы, наконец, можем развернуть наше приложение:

$ ~ kubectl config set-context kind-cluster --namespace blueprint

$ ~ KEY_FILE="blueprint.key"
$ ~ CERT_FILE="blueprint.crt"
$ ~ HOST="localhost"
$ ~ CERT_NAME=tls-secret

$ ~ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ${KEY_FILE} -out ${CERT_FILE} -subj "/CN=${HOST}/O=${HOST}"

$ ~ kubectl create secret generic env-secrets-blueprint --from-literal=VAR=VALUE --dry-run -o yaml >> app.yaml && echo "---" >> app.yaml
$ ~ kubectl create secret tls ${CERT_NAME} --key ${KEY_FILE} --cert ${CERT_FILE} --dry-run -o yaml >> app.yaml

$ ~ kubectl apply -f app.yaml
namespace/blueprint unchanged
deployment.apps/blueprint created
configmap/env-config-blueprint unchanged
service/blueprint created
ingress.extensions/blueprint-ingress unchanged
secret/env-secrets-blueprint configured
secret/tls-secret configured

$ ~ kubectl get all
NAME                             READY   STATUS    RESTARTS   AGE
pod/blueprint-5d86484b76-dkw7z   1/1     Running   0          13s

NAME                TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/blueprint   ClusterIP   10.96.253.31           443/TCP   13s

NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/blueprint   1/1     1            1           13s

NAME                                   DESIRED   CURRENT   READY   AGE
replicaset.apps/blueprint-5d86484b76   1         1         1       13s

$ ~ curl -k https://localhost/?text=Hello
You said: Hello

Большинство команд выше, которые мы уже видели в разделах ранее. Что нового – kubectl Apply -F App.yaml Что создает весь необходимый объект в нашем кластере. После создания мы можем проверить наличие этих объектов, использующих Kubectl Получить все Отказ Наконец мы можем проверить, доступно ли приложение, используя Curl и это! Итак, с этим у нас есть наше приложение, работающее на кластере!

Сделать это просто

Если вы не чувствуете себя полностью комфортно со всеми добрый и kubectl команды еще Или вы просто ленивы, как я, и ты не хочешь все их вводить, то у меня есть пара Сделать Цели для вас – сделать вашу жизнь проще:

  • Поднимите кластер:
cluster:
    @if [ $$(kind get clusters | wc -l) = 0 ]; then \
        kind create cluster --config ./k8s/cluster/kind-config.yaml --name kind; \
    fi
    @kubectl cluster-info --context kind-kind
    @kubectl get nodes
    @kubectl config set-context kind-kind --namespace $(MODULE)

сделать кластер Команда настроит кластер для вас, если он еще не готов, и если это так, он даст вам всю информацию об этом. Это приятно, если вам нужно проверить статус узлов и переключиться на пространство имен в разработке.

  • Применение редита/перезагрузки:
deploy-local:
    @kubectl rollout restart deployment $(MODULE)

Этот очень просто – все, что он делает, это развернут новое развертывание – так, на случай, если есть новое изображение, он будет развернуть его, в противном случае он просто будет перезапустить ваше приложение.

  • Отладка:
cluster-debug:
    @echo "\n${BLUE}Current Pods${NC}\n"
    @kubectl describe pods
    @echo "\n${BLUE}Recent Logs${NC}\n"
    @kubectl logs --since=1h -lapp=$(MODULE)

Если вам нужно отладить свое приложение, вы, вероятно, захотите увидеть недавние события, связанные с POD Application, а также последние (последние час) журналы. Это именно то, что Сделайте кластер-отладки делает для тебя.

  • Получить удаленную оболочку:
cluster-rsh:
    # if your container has bash available
    @kubectl exec -it $$(kubectl get pod -l app=${MODULE} -o jsonpath="{.items[0].metadata.name}") -- /bin/bash

Если журналы недостаточно, чтобы решить некоторые проблемы, которые вы можете иметь, и вы решите, что вам нужно ткать внутри контейнера, тогда вы можете запустить Сделать кластер-RSH Чтобы получить удаленную оболочку.

  • Обновление манифеста:
manifest-update:
    @kubectl apply -f ./k8s/app.yaml

Мы видели эту команду раньше. Это просто повторно применяет ямлевые проявления, что удобно, когда вы настраиваете некоторые свойства Кубернаны объекты.

Заключение

Эта статья не должна была быть Кубернаны Учебное пособие, но я думаю, что он достаточно показывает, чтобы вы начали, и у вас есть приложение и быстро работает. Чтобы узнать больше о Кубернеты Я рекомендую просто играть, настраивать и изменять вещи в проявлениях и видеть, что произойдет. Это, по моему мнению, хороший способ узнать, как дела работают и комфортно с kubectl команды. Если у вас есть какие-либо вопросы, предложения или проблемы, не стесняйтесь обращаться ко мне или создавать проблему в моем Репозиторий Отказ В этом репо, вы также можете найти документы и все проявления, показанные в этом посте.

Ресурсы

Оригинал: “https://dev.to/martinheinz/deploy-any-python-project-to-kubernetes-2h2l”