Когда ваш проект растет, он может добраться до того, что оно становится слишком сложно, чтобы справиться с одним виртуалом или несколькими простыми решениеми 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 Ready2m3s 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.31443/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”