Доступный слайд здесь Отказ Оригинальная статья опубликована здесь Отказ Исходный код здесь Отказ
В этом семинаре мы собираемся:
- Разверните службы Kubernetes и Gateway API посол API.
- Изучите разницу между kubernetes Proxies и Service Mesh, как ISTIO.
- Доступ к API Kubernetes снаружи и от стручка.
- Понять, что выбрать API.
- Посмотрите, как Сервисные учетные записи и RBAC работает
- Откройте для себя некоторые подводные камни безопасности при строительстве докеровских изображений и много интересных вещей.
- Другие вещи:-)
Мы начнем с разработки, развертываем простое приложение Python (API Flask, которая возвращает список репозиториев на тенденции по языку программирования).
Среда разработки
Мы собираемся использовать Python 3.6.7
Мы используем Ubuntu 18.04, который по умолчанию поставляется с Python 3.6. Вы должны быть в состоянии вызвать его с помощью команды Python3. (Ubuntu 17.10 и выше, а выше поставляется с Python 3.6.7)
Если вы используете Ubuntu 16.10 и 17.04, вы должны быть в состоянии установить его со следующими командами:
sudo apt-get update sudo apt-get install python3.6
Если вы используете Ubuntu 14.04 или 16.04, вам нужно получить Python 3 из персонального архива пакета (PPA):
sudo add-apt-repository ppa:deadsnakes/ppa sudo apt-get update sudo apt-get install python3.6
Для других операционных систем посетите Это руководство Следуйте инструкциям и установите Python3.
Теперь установите PIP, диспетчер пакетов:
sudo apt-get install python3-pip
Следуйте по этому поводу установкой VirtualenVWrapper, которая является диспетчером виртуальной среды:
sudo pip3 install virtualenvwrapper
Создайте папку для ваших VirtualenVS (я использую ~/dev/python_envs) и установить его как workon_home:
mkdir ~/dev/PYTHON_ENVS export WORKON_HOME=~/dev/PYTHON_ENVS
Для того, чтобы источнить детали окружающей среды, когда вход пользователя, добавьте следующие строки в ~/.bashrc:
source "/usr/local/bin/virtualenvwrapper.sh" export WORKON_HOME="~/dev/PYTHON_ENVS"
Обязательно адаптируйте работу Workon_home для вашей реальной рабочих мест. Теперь нам нужно создать, а затем активировать новую среду:
mkvirtualenv --python=/usr/bin/python3 trendinggitrepositories workon trendinggitrepositories
Давайте создадим каталоги заявки:
mkdir trendinggitrepositories cd trendinggitrepositories mkdir api cd api
Как только виртуальная среда активирована, мы можем установить колбу:
pip install flask
Разработка API для репозиториев Trending Git (колба)
Внутри папки API API.
Создайте файл под названием app.py
и добавьте следующий код:
from flask import Flask app = Flask(__name__) @app.route('/') def index(): return "Hello, World!" if __name__ == '__main__': app.run(debug=True)
Это вернет сообщение Hello World, когда пользователь запрашивает маршрут «/».
Теперь запустите его, используя: Python App.py
И вы увидите аналогичный выход к следующему:
* Serving Flask app "api" (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: on * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) * Restarting with stat * Debugger is active! * Debugger PIN: 465-052-587
Теперь нам нужно установить Pygitub, поскольку нам нужно, чтобы общаться с GitHub API V3.
pip install PyGithub
Перейти к Github и Создать новое приложение Отказ Нам понадобится приложение «Клиент ID» и «Секрет клиента»:
from github import Github g = Github("xxxxxxxxxxxxx", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
Вот как выглядит мини-API:
from flask import Flask, jsonify, abort import urllib.request, json from flask import request app = Flask(__name__) from github import Github g = Github("xxxxxx", "xxxxxxxxxxxxx") @app.route('/') def get_repos(): r = [] try: args = request.args n = int(args['n']) except (ValueError, LookupError) as e: abort(jsonify(error="No integer provided for argument 'n' in the URL")) repositories = g.search_repositories(query='language:python')[:n] for repo in repositories: with urllib.request.urlopen(repo.url) as url: data = json.loads(url.read().decode()) r.append(data) return jsonify({'repos':r }) if __name__ == '__main__': app.run(debug=True)
Давайте скрываем токен и секрет GitHub, а также другие переменные в окружающей среде.
from flask import Flask, jsonify, abort, request import urllib.request, json, os from github import Github app = Flask(__name__) CLIENT_ID = os.environ['CLIENT_ID'] CLIENT_SECRET = os.environ['CLIENT_SECRET'] DEBUG = os.environ['DEBUG'] g = Github(CLIENT_ID, CLIENT_SECRET) @app.route('/') def get_repos(): r = [] try: args = request.args n = int(args['n']) except (ValueError, LookupError) as e: abort(jsonify(error="No integer provided for argument 'n' in the URL")) repositories = g.search_repositories(query='language:python')[:n] for repo in repositories: with urllib.request.urlopen(repo.url) as url: data = json.loads(url.read().decode()) r.append(data) return jsonify({'repos':r }) if __name__ == '__main__': app.run(debug=DEBUG)
Вышеуказанный код вернет лучшие «n» репозитории, используя Python в качестве языка программирования. Мы можем использовать другие языки тоже:
from flask import Flask, jsonify, abort, request import urllib.request, json, os from github import Github app = Flask(__name__) CLIENT_ID = os.environ['CLIENT_ID'] CLIENT_SECRET = os.environ['CLIENT_SECRET'] DEBUG = os.environ['DEBUG'] g = Github(CLIENT_ID, CLIENT_SECRET) @app.route('/') def get_repos(): r = [] try: args = request.args n = int(args['n']) l = args['l'] except (ValueError, LookupError) as e: abort(jsonify(error="Please provide 'n' and 'l' parameters")) repositories = g.search_repositories(query='language:' + l)[:n] try: for repo in repositories: with urllib.request.urlopen(repo.url) as url: data = json.loads(url.read().decode()) r.append(data) return jsonify({ 'repos':r, 'status': 'ok' }) except IndexError as e: return jsonify({ 'repos':r, 'status': 'ko' }) if __name__ == '__main__': app.run(debug=DEBUG)
В файле .env Добавьте переменные, которые вы хотите использовать:
CLIENT_ID="xxxxx" CLIENT_SECRET="xxxxxx" ENV="dev" DEBUG="True"
Перед запуском приложения Flask вам необходимо источник этих переменных:
source .env
Теперь вы можете пойти в http://0.0.0.0:5000/?n=1&l=. Python
чтобы получить самого спокойного хранилища Python или http://0.0.0.0:5000/?n=1&l=. C
Для языка программирования C. Вот список других языков программирования, которые вы можете проверить свой код с:
C++ Assembly Objective Makefile Shell Perl Python Roff Yacc Lex Awk UnrealScript Gherkin M4 Clojure XS Perl sed
Список длинный, но наш мини-API работает нормально. Теперь давайте заморожем зависимости:
pip freeze > requirements.txt
Перед запуском API на Kubernetes давайте создадим DockerFile. Это типичная докера для приложения Python:
FROM python:3 ENV PYTHONUNBUFFERED 1 RUN mkdir /app WORKDIR /app COPY requirements.txt /app RUN pip install --upgrade pip RUN pip install -r requirements.txt COPY . /app EXPOSE 5000 CMD [ "python", "app.py" ]
Теперь вы можете построить это:
docker build --no-cache -t tgr .
Затем запустите:
docker rm -f tgr docker run --it --name tgr -p 5000:5000 -e CLIENT_ID="xxxxxxx" -e CLIENT_SECRET="xxxxxxxxxxxxxxx" -e DEBUG="True" tgr
Давайте включаем некоторые другие переменные в качестве переменных среды:
from flask import Flask, jsonify, abort, request import urllib.request, json, os from github import Github app = Flask(__name__) CLIENT_ID = os.environ['CLIENT_ID'] CLIENT_SECRET = os.environ['CLIENT_SECRET'] DEBUG = os.environ['DEBUG'] HOST = os.environ['HOST'] PORT = os.environ['PORT'] g = Github(CLIENT_ID, CLIENT_SECRET) @app.route('/') def get_repos(): r = [] try: args = request.args n = int(args['n']) l = args['l'] except (ValueError, LookupError) as e: abort(jsonify(error="Please provide 'n' and 'l' parameters")) repositories = g.search_repositories(query='language:' + l)[:n] try: for repo in repositories: with urllib.request.urlopen(repo.url) as url: data = json.loads(url.read().decode()) r.append(data) return jsonify({ 'repos':r, 'status': 'ok' }) except IndexError as e: return jsonify({ 'repos':r, 'status': 'ko' }) if __name__ == '__main__': app.run(debug=DEBUG, host=HOST, port=PORT)
По соображениям безопасности давайте изменим пользователь внутри контейнера от root до пользователя с тем, что мы создаем:
FROM python:3 ENV PYTHONUNBUFFERED 1 RUN adduser pyuser RUN mkdir /app WORKDIR /app COPY requirements.txt /app RUN pip install --upgrade pip RUN pip install -r requirements.txt COPY . . RUN chmod +x app.py RUN chown -R pyuser:pyuser /app USER pyuser EXPOSE 5000 CMD ["python","./app.py"]
Теперь, если мы хотим запустить контейнер, нам нужно добавить много переменных среды в команду Docker Run. Простые решение использует --env-файл
С Docker Run:
docker run -it --env-file .env my_container
Наш файл .env выглядит следующим образом:
CLIENT_ID="xxxx" CLIENT_SECRET="xxxx" ENV="dev" DEBUG="True" HOST="0.0.0.0" PORT=5000
После этой модификации восстановить изображение Docker Build -T TGR.
и запустить его, используя:
docker rm -f tgr; docker run -it --name tgr -p 5000:5000 --env-file .env tgr
Наше приложение работает с использованием Python App.py
Который является веб-сервером, который поставляется с Flask и T отличным для разработки и локального выполнения вашей программы, однако, он не предназначен для запуска в режиме производства, будь то монолитное приложение или микросервис.
Производственный сервер обычно получает злоупотребление от спамеров, сценариев детей и должен иметь возможность обрабатывать высокий трафик. В нашем случае хорошее решение использует HTTP-сервере WSGI, как Gunicorn (или UWSGI).
Во-первых, давайте установим боевик
Со следующей командой: Пип устанавливает боевиков
. Это потребует от нас обновить наши требования .txt
с PIP Freeze> требования.
Вот почему мы собираемся изменить наш файл докера:
FROM python:3 ENV PYTHONUNBUFFERED 1 RUN adduser pyuser RUN mkdir /app WORKDIR /app COPY requirements.txt /app RUN pip install --upgrade pip RUN pip install -r requirements.txt COPY . . RUN chmod +x app.py RUN chown -R pyuser:pyuser /app USER pyuser EXPOSE 5000 CMD ["gunicorn", "app:app", "-b", "0.0.0.0:5000"]
Чтобы оптимизировать сервер WSGI, нам нужно установить количество своих работников и потоков:
workers = multiprocessing.cpu_count() * 2 + 1 threads = 2 * multiprocessing.cpu_count()
Вот почему мы собираемся создать еще один файл конфигурации Python ( config.py
):
import multiprocessing workers = multiprocessing.cpu_count() * 2 + 1 threads = 2 * multiprocessing.cpu_count()
В том же файле мы собираемся включить другие конфигурации Gunicorn:
from os import environ as env bind = env.get("HOST","0.0.0.0") +":"+ env.get("PORT", 5000)
Это последний config.py
файл:
import multiprocessing workers = multiprocessing.cpu_count() * 2 + 1 threads = 2 * multiprocessing.cpu_count() from os import environ as env bind = env.get("HOST","0.0.0.0") +":"+ env.get("PORT", 5000)
Вследствие, мы должны адаптировать Dockerfile в новую конфигурацию Gunicorn, изменив последнюю строку в:
CMD ["gunicorn", "app:app", "--config=config.py"]
Теперь построить Docker Build -T TGR.
и бежать Docker Run -it --env-file .env -P 5000: 5000 TGR
Отказ
Реестр Docker – это система хранения и распределения для именованных изображений Docker.
Изображения, которые мы создали, хранятся в нашей локальной среде и могут использоваться только при развертывании локально. Однако, если вы решите развернуть кластер Kubernetes в облаке или любую другую среду, эти изображения будут не найдены. Вот почему нам нужно подтолкнуть изображения сборки в удаленный реестр.
Подумайте о реестрах контейнера в качестве системы Git для Docker Images.
Есть много реестров контейнеров:
- Docker Hub.
- Амазонский эластичный реестр (ECR)
- Реестр контейнера Azure (ACR)
- Реестр контейнера Google (GCR)
- Кореос набережной
Вы также можете принять реестр вашего частного контейнера, который поддерживает аутентификацию OAUTH, LDAP и Active Directory с помощью реестра, предоставленного Docker:
docker run -d -p 5000:5000 --restart=always --name registry registry:2
Подробнее о самостоятельном хостинге реестра можно найти в Официальная документация Docker Отказ
Мы собираемся использовать Dockerhub; Вот почему вам нужно создать учетную запись на hub.docker.com .
Теперь, используя Docker CLI, логин:
docker login
Теперь восстановите изображение, используя новый тег:
docker build -t/ : .
Пример:
docker build -t eon01/tgr:1 .
Наконец, нажмите на изображение:
docker push eon01/tgr:1
Уведомление о безопасности
Многие из общедоступных (и даже частных образов Docker), кажется, безопасны, но это не так. Когда мы создали наш образ, мы сказали Docker копировать все изображения из папки приложения на изображение, и мы нажимаем на внешний публичный реестр.
COPY . .
Или
ADD . .
Вышеуказанные команды даже скопируют .env
Файл, содержащий наши секреты.
Хорошее решение – сказать Docker, чтобы игнорировать эти файлы во время сборки, используя файл .dockingore:
**.git **.gitignore **README.md **env.* **Dockerfile* **docker-compose* **.env
На этом этапе вы должны удалить любое изображение, которое вы нажали в отдаленный реестр, сбросьте токены GitHub, создайте новое изображение без какого-либо кэша:
docker build -t eon01/tgr:1 . --no-cache
Нажмите это снова:
docker push eon01/tgr:1
Один из самых быстрых способов попробовать Kubernetes использует MINCUBE, который создаст виртуальную машину для вас и развернут готов к использованию кластера Kubernetes.
Прежде чем начать установку, вам необходимо убедиться, что ваш ноутбук поддерживает виртуализацию:
Если вы используете Linux, запустите следующую команду и убедитесь, что выход не пустое:
grep -E --color 'vmx|svm' /proc/cpuinfo
Пользователи Mac должны выполняться:
sysctl -a | grep -E --color 'machdep.cpu.features|VMX'
Если вы видите VMX
На выходе функция VT-X включена в вашу машину.
Пользователи Windows должны использовать системная информация
И вы должны увидеть следующий вывод:
Hyper-V Requirements: VM Monitor Mode Extensions: Yes Virtualization Enabled In Firmware: Yes Second Level Address Translation: Yes Data Execution Prevention Available: Yes
Если все в порядке, вам нужно установить гипервизор. У вас есть список возможностей здесь:
Некоторые из этих гипервизоров совместимы только с некоторыми oss, как Hyper-V (ранее известные как виртуализация Windows Server) для Windows.
Виртуальная коробка, однако, кроссплатформенная, и именно поэтому мы собираемся использовать его здесь. Обязательно Следуйте инструкциям установить его.
Теперь установите Minikube.
Linux Systems:
curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && chmod +x minikube sudo install minikube /usr/local/bin
Macos:
brew cask install minikube curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64 && chmod +x minikube sudo mv minikube /usr/local/bin
Windows:
Используйте шоколад, как администратор:
choco install minikube
Или использовать Установщик двоичный Отказ
Minikube не поддерживает все функции Kubernetes (например, балансировка нагрузки), однако, вы можете найти самые важные функции там:
Minikube поддерживает следующие функции Kubernetes:
- Днс
- Odeports.
- Configmaps и Secrets.
- Приборные панели
- Контейнер Runtime: Docker, RKT , CRI-O и контейнер
- Включение CNI (интерфейс контейнеров)
- Проходность
Вы также можете добавить разные дополнения, как:
- аддон-менеджер
- панель приборов
- storageClass
- эфир
- первоклассный
- ГВИСОР
- Heappster.
- проходность
- LogViewer.
- Метрики-сервер
- nvidia-водитель-установщик
- nvidia-gpu-устройство-плагин
- реестр
- Реестр-кредиты
- хранилище
- хранилище
Если вы запустите Minikube Start
Будет создан кластер под названием Minikube; Тем не менее, у вас есть другие варианты, а не просто создание регулярного минимального кластера. В этом примере мы собираемся создать кластер под названием «Schoolop», включите интернет-интерфейс для просмотра API и активируйте журналы хвостовой связи:
minikube start -p workshop --extra-config=apiserver.enable-swagger-ui=true --alsologtostderr
У вас есть много других вариантов для начала кластера Minikube; Например, вы можете выбрать версию Kubernetes и драйвера VM:
minikube start --kubernetes-version="v1.12.0" --vm-driver="virtualbox"
Начните новый кластер:
minikube start -p workshop --extra-config=apiserver.enable-swagger-ui=true --alsologtostderr
Вы можете получить подробную информацию о кластере, используя:
kubectl cluster-info
Если вы не установили kubectl, Следуйте официальным инструкциям Отказ
Вы можете открыть приборную панель, используя Minikube -P Schathoph Dashboard
У нас есть три основных способа развертывания нашего контейнера к Kubernetes и масштабируйте его до реплики.
Первый – это оригинальная форма репликации в Куберане, и она называется Контроллер репликации Отказ
Даже если реплики заменяют его, он все еще используется в некоторых кодах.
Это типичный пример:
apiVersion: v1 kind: ReplicationController metadata: name: app spec: replicas: 3 selector: app: app template: metadata: name: app labels: app: app spec: containers: - name: tgr image: reg/app:v1 ports: - containerPort: 80
Мы также можем использовать наборы реплики, другой способ развертывать приложение и реплицировать его:
apiVersion: extensions/v1beta1 kind: ReplicaSet metadata: name: app spec: replicas: 3 selector: matchLabels: app: app template: metadata: labels: app: app environment: dev spec: containers: - name: app image: reg/app:v1 ports: - containerPort: 80
Набор реплики и контроллер репликации делают почти одно и то же.
Они гарантируют, что у вас есть указанное количество копий POD Replica, работающих в любой момент времени в вашем кластере.
Однако есть некоторые различия.
Как вы можете заметить, мы используем Matchlabels
вместо этикетка
Отказ
Реплика Установка Используйте наборные селекторы в то время как контроллеры репликации используют селекторы на основе акций.
Селекторы соответствуют объектам Kubernetes (например, PODS), используя ограничения указанной метки, и мы увидим пример в файле спецификации развертывания.
Маркирные селекторы с Требования на основе равенства Используйте три оператора: =
, ==.
и знак равно
.
environment = production tier != frontend app == my_app (similar to app = my_app)
В последнем примере мы использовали это обозначение:
... spec: replicas: 3 selector: matchLabels: app: app template: metadata: ...
Мы могли бы использовать Установленные требования :
... spec: replicas: 3 selector: matchExpressions: - {key: app, operator: In, values: [app]} template: metadata: ...
Если у нас будет более 1 значение для ключа приложения, мы можем использовать:
... spec: replicas: 3 selector: matchExpressions: - {key: app, operator: In, values: [app, my_app, myapp, application]} template: metadata: ...
И если у нас есть другие ключи, мы можем использовать их в следующем примере:
... spec: replicas: 3 selector: matchExpressions: - {key: app, operator: In, values: [app]} - {key: tier, operator: NotIn, values: [frontend]} - {key: environment, operator: NotIn, values: [production]} template: metadata: ...
Новые ресурсы Kubernetes, такие как рабочие места, развертывания, реплизет и Daemonsets Все также поддерживают наборные требования, а также.
Это пример того, как мы используем Kubectl с селекторами:
kubectl delete pods -l 'env in (production, staging, testing)'
До сих пор мы видели, что контроллер репликации и набор реплик являются двумя способами развертывания нашего контейнера и управление его в кластере Kubernetes. Однако рекомендуемый подход использует развертывание, которое настраивает реплиз.
Довольно маловероятно, что нам когда-либо потребуется создавать стручки непосредственно для производственного использования, поскольку развертывание удается создавать подмышки для нас через реплизет.
Это простое определение POD:
apiVersion: v1 kind: Pod metadata: name: infinite labels: env: production owner: eon01 spec: containers: - name: infinite image: eon01/infinite
На практике нам нужно:
- Объект развертывания : Контейнеры указаны здесь.
- Объект сервиса : Абстрактный способ разоблачить приложение, запущенное на наборе стручков в качестве сетевой службы.
Это объект развертывания, который создает три копирования приложения контейнера, выполняющим изображение «REG/APP: V1». Эти контейнеры могут быть достигнуты с помощью порта 80:
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: app spec: replicas: 3 template: metadata: labels: app: app spec: containers: - name: app image: reg/app:v1 ports: - containerPort: 80
Это файл развертывания, который мы будем использовать (сохранить его на Kubernetes/API-развертывание. YAML
:
apiVersion: apps/v1 kind: Deployment metadata: name: tgr labels: name: tgr spec: replicas: 1 selector: matchLabels: name: tgr template: metadata: name: tgr labels: name: tgr spec: containers: - name: tgr image: eon01/tgr:1 ports: - containerPort: 5000 resources: requests: memory: 128Mi limits: memory: 256Mi env: - name: CLIENT_ID value: "xxxx" - name: CLIENT_SECRET value: "xxxxxxxxxxxxxxxxxxxxx" - name: ENV value: "prod" - name: DEBUG value: "False" - name: HOST value: "0.0.0.0" - name: PORT value: "5000"
Давайте сначала поговорим о версии API; В первом примере мы использовали Расширения/v1beta1
А во втором, мы использовали Приложения/V1
Отказ Вы можете знать, что разработка проекта Kubernetes очень активна, и иногда может быть запутано, чтобы следовать за всеми обновлениями программного обеспечения.
В Kubernetes версии 1.9, Приложения/V1
введен, а Расширения/v1beta1
, Приложения/v1beta1
и Приложения/v1beta2
устарены.
Чтобы сделать все возможное, узнать, какую версию API вам нужно использовать, используйте команду:
kubectl api-versions
Эта вышеданная команда даст вам версии API, совместимые с вашим кластером.
V1 был первым устойчивым выпуском API Kubernetes. Он содержит много основных объектов.
Приложения/V1 Является самая популярная группа API в Kubernetes, и она включает в себя функциональность, связанные с запущенными приложениями на Kubernetes, таких как развертывание, RollingUpdates и ReplicaSets.
** AutoScaling/V1 ** позволяет автоматически быть автоматически на основе различных метрик использования ресурсов.
Пакет/v1 связано с пакетной обработкой и рабочими работами
Пакет/v1beta1 Бета-выпуск партии/V1
Сертификаты.k8s.io/v1beta1 Проверяет сетевые сертификаты для безопасной связи в вашем кластере.
Расширения/v1beta1 Включает в себя много новых, обычно используемых функций. В Kubernetes 1.6 некоторые из этих функций были перемещены от
Расширения
к определенным группам API, таких какприложения
ОтказПолитика/v1beta1 Позволяет установить бюджет нарушения POD и новых правил безопасности POD
rbac.authorization.k8s.io/v1 Включает дополнительную функциональность для Kubernetes RBAC (контроль доступа на основе ролей)
.. и т.д
Давайте разверним POD, используя файл развертывания, который мы создали.
kubcetl apply -f kubernetes/api-deployment.yaml
Обратите внимание, что вы можете использовать Kubectl Create -f Kubernetes/API-развертывание.yaml
команда. Тем не менее, есть разница, между Применить
и Создать
Отказ
Kubectl Создать
это то, что мы называем Императивное управление объектами Kubernetes с использованием файлов конфигурации . Kubectl Создать
Перезаписывает все изменения, и если ресурс имеет тот же ID, уже существует, он столкнулся с ошибкой.
Используя этот подход, вы сообщите API Kubernetes, что вы хотите создать, заменить или удалять, а не как вы хотите, чтобы ваш кластер K8S Cluster выглядит как.
Kubectl Применить
это то, что мы называем Декларативное управление объектами Kubernetes с использованием файлов конфигурации подход. Kubectl Применить
делает инкрементные изменения. Если объект уже существует, и вы хотите применить новое значение для реплики без удаления и воссоздания объекта снова, то Kubectl Применить
это то, что вам нужно. Кубцетл применить
Также можно использовать даже если объект (развертывание E.G) еще не существует.
В конфигурации развертывания мы также определили наш контейнер. Мы запустим один контейнер здесь, так как реплика установлена на 1
Отказ В то же время наш контейнер будет использовать изображение EON01/TGR: 1
Отказ Поскольку наш контейнер понадобится некоторые переменные среды, лучший способ – предоставить им использование файла определения развертывания Kubernetes.
Кроме того, мы можем добавить много других конфигураций, таких как запрошенная память и его предел. Целью здесь не использует все, что позволяет использовать Kubernetes, – это использовать в файле развертывания, но чтобы увидеть некоторые основные функции.
spec: containers: - name: tgr image: eon01/tgr:1 ports: - containerPort: 5000 resources: requests: memory: 128Mi limits: memory: 256Mi env: - name: CLIENT_ID value: "xxxx" - name: CLIENT_SECRET value: "xxxxxxxxxxxxxxxxxxxxx" - name: ENV value: "prod" - name: DEBUG value: "False" - name: HOST value: "0.0.0.0" - name: PORT value: "5000"
В некоторых случаях реестр Docker может быть частным, и в этом случае вытягивает подлинность аутентификации изображения. В этом случае нам нужно добавить imagepullsecrets
Конфигурация:
... containers: - name: private-reg-container image:imagePullSecrets: - name: registry-credentials ...
Вот как Реестр-учетные данные
секрет создан:
kubectl create secret docker-registry registry-credentials --docker-server=--docker-username= --docker-password= --docker-email=
Вы также можете подать заявку/создать Реестр-учетные данные
используя файл yaml. Это пример:
apiVersion: v1 kind: Secret metadata: ... name: registry-credentials ... data: .dockerconfigjson: adjAalkazArrA ... JHJH1QUIIAAX0= type: kubernetes.io/dockerconfigjson
Если вы декодируете файл .dockerConfigjson, используя Base64 --DeCode
Команда, вы поймете, что это простой файл, хранящий конфигурацию для доступа к реестру:
kubectl get secret regcred --output="jsonpath={.data.\.dockerconfigjson}" | base64 --decode
Вы получите аналогичный вывод к следующему:
{"auths":{"your.private.registry.domain.com":{"username":"eon01","password":"xxxxxxxxxxx","email":"aymen@eralabs.io","auth":"dE3xxxxxxxxx"}}}
Опять же, давайте декодируем значение «AUTH», используя echo "de3xxxxxxxxx" | Base64 --DeCode
И это даст вам что-то вроде EON01: XXXXXXXX
который имеет формат Имя пользователя: Пароль
Отказ
Теперь посмотрим, сделано ли развертывание, давайте посмотрим, сколько у нас есть:
kubectl get pods
Эта команда покажет все стручки в кластере.
Мы можем масштабировать наше развертывание, используя команду, аналогичную следующему:
kubectl scale --replicas=deployment
Наше развертывание называется TGR
Поскольку это имя, которое мы дали ему в конфигурации развертывания. Вы также можете сделать проверку, набрав KubeClt Получить развертывание
Отказ Давайте масштабируемся это:
kubectl scale --replicas=2 deployment tgr
Каждая из этих контейнеров будет доступна по порту 500 из-за пределов контейнера, но не из-за пределов кластера.
Количество стручков/контейнеров для нашего API, может быть переменным и может меняться динамически.
Мы можем настроить балансировщик нагрузки, который будет сбалансировать трафик между двумя созданными подводами, но поскольку каждый POD может исчезнуть, его имя хоста и адрес изменятся.
Во всех случаях стручки не предназначены для того, чтобы получать движение напрямую, но им нужно подвергаться дорогу с использованием услуг. Другими словами, набор стручков, работающих в одном моменте во времени, может отличаться от набора стручков, выполняющих это приложение на мгновение.
На данный момент единственным управлением службы является кластер IP (который связан с Minikube и дает нам доступ к созданию кластера):
kubectl get services
Услуги
В Кубейнетах, поскольку стручки являются смертными, мы должны создать абстракцию, которая определяет логический набор стручков и как к ним доступу. Это роль услуг.
В нашем случае создание балансировщика нагрузки является подходящим решением. Это файл конфигурации объекта сервисного сервиса, который будет прослушивать порта 80 и баланс нагрузки на POD с меткой Имя
равна приложение
. Последнее доступно внутри, используя порт 5000, как он определен в конфигурации развертывания:
... ports: - containerPort: 5000 ...
Так выглядит услугу:
apiVersion: v1 kind: Service metadata: name: lb labels: name: lb spec: ports: - port: 80 targetPort: 5000 selector: name: tgr type: LoadBalancer
Сохраните этот файл в Kubernetes/API-Service.yaml
и разверните его, используя Kubectl Apply Printe -F Kubernetes/API-Service.yaml
Отказ
Если вы ввести Kubectl Получить Сервис
Вы получите список услуг, работающих в нашем локальном кластере:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1443/TCP 51m lb LoadBalancer 10.99.147.117 80:30546/TCP 21s
Не то чтобы Clusterip не имеет внешнего IP, в то время как сервис приложений Внешний IP ожидается. Не нужно ждать внешнего IP созданного сервиса, Поскольку Minikube на самом деле не развертывает балансировщик нагрузки, и эта функция будет работать только, если вы настроите поставщика балансировщика нагрузки.
Если вы используете облачный провайдер, скажите AWS, для вас будет настроен балансировщик нагрузки AWS, GKE обеспечит балансировщик облачного нагрузки. ETC Вы также можете настроить другие типы балансировщиков нагрузки.
Существуют различные типы услуг, которые мы можем использовать для публично доступа к API:
Clusterip
: это служба по умолчанию Kubernetes. Он предоставляет услугу на кластерной внутреннем IP. Вы можете получить доступ к нему, используя прокси Kubernetes.
( Photo Credit )
NodePort
: Раскрывает сервис на IP-адресе каждого узла (VM) в статическом порту под названиемNodePort
Отказ (В нашем примере у нас есть один узел). Это примитивный способ сделать приложение доступным из-за пределов кластера и не подходит для многих случаев использования, поскольку IP-адреса узлов (VMS) могут измениться в любое время. Услуга доступна с использованием
Отказ:
( Photo Credit )
LoadBalancer
: Это более продвинуто, чемNodePort
Услуга. Обычно балансировщик нагрузки обнажает услугу снаружи, используя балансировщик нагрузки нагрузки облака.Нотепорт
иClusterip
Услуги, к которым автоматически создаются внешние маршруты балансировщика нагрузки.
( Photo Credit )
Мы создали балансировщик нагрузки, используя услугу на нашем кластере Minikube, но поскольку у нас нет балансировщика нагрузки, мы можем получить доступ к службе API, используя IP-кластер, а затем внутренний порт сервиса:
minikube -p workshop ip
Выход:
192.168.99.100
Теперь выполнить Kubectl Получить услуги
:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1443/TCP 51m lb LoadBalancer 10.99.147.117 80:30546/TCP 21s
Используйте IP 192.168.99.199
сопровождаемый портом 30546
Для доступа к API.
Вы можете проверить это, используя Curl
команда:
curl "http://192.168.99.100:30546/?l=python&n=1" --- {"repos":[{"archive_url":"https://api.github.com/repos/vinta/awesome-python/{archive_format}{/ref}","archived":false,"assignees_url":"https://api.github.com/repos/vinta/awesome-python/assignees{/user}","blobs_url":"https://api.github.com/repos/vinta/awesome-python/git/blobs{/sha}","branches_url":"https://api.github.com/repos/vinta/awesome-python/branches{/branch}","clone_url":"https://github.com/vinta/awesome-python.git","collaborators_url":"https://api.github.com/repos/vinta/awesome-python/collaborators{/collaborator}","comments_url":"https://api.github.com/repos/vinta/awesome-python/comments{/number}","commits_url":"https://api.github.com/repos/vinta/awesome-python/commits{/sha}","compare_url":"https://api.github.com/repos/vinta/awesome-python/compare/{base}...{head}","contents_url":"https://api.github.com/repos/vinta/awesome-python/contents/{+path}","contributors_url":"https://api.github.com/repos/vinta/awesome-python/contributors","created_at":"2014-06-27T21:00:06Z","default_branch":"master","deployments_url":"https://api.github.com/repos/vinta/awesome-python/deployments","description":"A curated list of awesome Python frameworks, libraries, software and resources","disabled":false,"downloads_url":"https://api.github.com/repos/vinta/awesome-python/downloads","events_url":"https://api.github.com/repos/vinta/awesome-python/events","fork":false,"forks":13929,"forks_count":13929,"forks_url":"https://api.github.com/repos/vinta/awesome-python/forks","full_name":"vinta/awesome-python","git_commits_url":"https://api.github.com/repos/vinta/awesome-python/git/commits{/sha}","git_refs_url":"https://api.github.com/repos/vinta/awesome-python/git/refs{/sha}","git_tags_url":"https://api.github.com/repos/vinta/awesome-python/git/tags{/sha}","git_url":"git://github.com/vinta/awesome-python.git","has_downloads":true,"has_issues":true,"has_pages":true,"has_projects":false,"has_wiki":false,"homepage":"https://awesome-python.com/","hooks_url":"https://api.github.com/repos/vinta/awesome-python/hooks","html_url":"https://github.com/vinta/awesome-python","id":21289110,"issue_comment_url":"https://api.github.com/repos/vinta/awesome-python/issues/comments{/number}","issue_events_url":"https://api.github.com/repos/vinta/awesome-python/issues/events{/number}","issues_url":"https://api.github.com/repos/vinta/awesome-python/issues{/number}","keys_url":"https://api.github.com/repos/vinta/awesome-python/keys{/key_id}","labels_url":"https://api.github.com/repos/vinta/awesome-python/labels{/name}","language":"Python","languages_url":"https://api.github.com/repos/vinta/awesome-python/languages","license":{"key":"other","name":"Other","node_id":"MDc6TGljZW5zZTA=","spdx_id":"NOASSERTION","url":null},"merges_url":"https://api.github.com/repos/vinta/awesome-python/merges","milestones_url":"https://api.github.com/repos/vinta/awesome-python/milestones{/number}","mirror_url":null,"name":"awesome-python","network_count":13929,"node_id":"MDEwOlJlcG9zaXRvcnkyMTI4OTExMA==","notifications_url":"https://api.github.com/repos/vinta/awesome-python/notifications{?since,all,participating}","open_issues":482,"open_issues_count":482,"owner":{"avatar_url":"https://avatars2.githubusercontent.com/u/652070?v=4","events_url":"https://api.github.com/users/vinta/events{/privacy}","followers_url":"https://api.github.com/users/vinta/followers","following_url":"https://api.github.com/users/vinta/following{/other_user}","gists_url":"https://api.github.com/users/vinta/gists{/gist_id}","gravatar_id":"","html_url":"https://github.com/vinta","id":652070,"login":"vinta","node_id":"MDQ6VXNlcjY1MjA3MA==","organizations_url":"https://api.github.com/users/vinta/orgs","received_events_url":"https://api.github.com/users/vinta/received_events","repos_url":"https://api.github.com/users/vinta/repos","site_admin":false,"starred_url":"https://api.github.com/users/vinta/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vinta/subscriptions","type":"User","url":"https://api.github.com/users/vinta"},"private":false,"pulls_url":"https://api.github.com/repos/vinta/awesome-python/pulls{/number}","pushed_at":"2019-08-16T15:21:42Z","releases_url":"https://api.github.com/repos/vinta/awesome-python/releases{/id}","size":4994,"ssh_url":"git@github.com:vinta/awesome-python.git","stargazers_count":71222,"stargazers_url":"https://api.github.com/repos/vinta/awesome-python/stargazers","statuses_url":"https://api.github.com/repos/vinta/awesome-python/statuses/{sha}","subscribers_count":5251,"subscribers_url":"https://api.github.com/repos/vinta/awesome-python/subscribers","subscription_url":"https://api.github.com/repos/vinta/awesome-python/subscription","svn_url":"https://github.com/vinta/awesome-python","tags_url":"https://api.github.com/repos/vinta/awesome-python/tags","teams_url":"https://api.github.com/repos/vinta/awesome-python/teams","trees_url":"https://api.github.com/repos/vinta/awesome-python/git/trees{/sha}","updated_at":"2019-08-17T16:11:44Z","url":"https://api.github.com/repos/vinta/awesome-python","watchers":71222,"watchers_count":71222}],"status":"ok"}
Неудобное обслуживание балансировщика нагрузки
Как правило, балансировщики нагрузки обеспечиваются облачным провайдером, который вы используете.
Балансировщик нагрузки может обрабатывать один сервис, но представьте, если у вас есть десять услуг, каждый понадобится балансировщик нагрузки; Это когда это становится дорогостоящим.
Наилучшим решением, в этом случае устанавливается контроллером входа, который действует как умный маршрутизатор, и может быть развернут на краю кластера, поэтому в передней панели всех услуг вы развертываете.
( Photo Credit )
Посол – это открытый исходный код Kubernetes-Wate API Gateway, построенный на прокси-подтверждении посланника. Он обеспечивает решение для управления трафиком и безопасности приложений. Описано как является специализированной плоскостью управления, которая переводит аннотации Kubernetes для конфигурации посланника.
Весь трафик напрямую обрабатывается высокопроизводительным прокси-сервером поклонника.
( Фото кредиты )
Как описано в Посол Официальный сайт :
Первоначально построен в Лифти Посланник является высокопроизводительным распределенным прокси-сервером C ++, предназначенным для одиночных услуг и приложений, а также на автобусе связи и «Универсальная плоскость данных», предназначенной для крупных архитектурных архитектур. Построенные на изучениях решений, таких как Nginx, Haproxy, Haproxy, Abourduare Balancers, а также балансировщики облачных нагрузок, посланница работает рядом с каждым приложением и тезисов сети, обеспечивая общие функции в платформе – агностическую способ. Когда все сервисные трафик в инфраструктуре течет через сетку поклонника, становится легко визуализировать заданные зоны с помощью последовательной наблюдаемости, настроить общую производительность и добавлять функции подложки в одном месте.
Мы собираемся использовать посол в качестве шлюза API; Мы больше не нуждаемся в службе балансировки нагрузки, которые мы создали в первой части. Давайте удалим это:
kubectl delete -f kubernetes/api-service.yaml
Развернуть посол в вашем по умолчанию Именное пространство, во-первых, вам нужно проверить, включил ли Kubernetes RBAC:
kubectl cluster-info dump --namespace kube-system | grep authorization-mode
Если RBAC включен:
kubectl apply -f https://getambassador.io/yaml/ambassador/ambassador-rbac.yaml
Без RBAC вы можете использовать:
kubectl apply -f https://getambassador.io/yaml/ambassador/ambassador-no-rbac.yaml
Посол развернут как служба Kubernetes, которые ссылаются на развертывание посла, которое вы развернули ранее. Создайте следующий YAML и поместите его в файл под названием Кубернаны/посол-сервис.ЯМЛ
Отказ
--- apiVersion: v1 kind: Service metadata: name: ambassador spec: type: LoadBalancer externalTrafficPolicy: Local ports: - port: 80 targetPort: 8080 selector: service: ambassador
Разверните услугу:
kubectl apply -f ambassador-service.yaml
Теперь давайте будем использовать этот файл, содержащий конфигурацию развертывания для нашего API, а также конфигурацию службы посла относительно того же развертывания. Позвоните в этот файл Kubernetes/API-развертывание - с-посол.Ямль
:
--- apiVersion: v1 kind: Service metadata: name: tgr annotations: getambassador.io/config: | --- apiVersion: ambassador/v1 kind: Mapping name: tgr_mapping prefix: / service: tgr:5000 spec: ports: - name: tgr port: 5000 targetPort: 5000 selector: app: tgr --- apiVersion: apps/v1 kind: Deployment metadata: name: tgr spec: replicas: 1 selector: matchLabels: app: tgr strategy: type: RollingUpdate template: metadata: labels: app: tgr spec: containers: - name: tgr image: eon01/tgr:1 ports: - containerPort: 5000 env: - name: CLIENT_ID value: "xxxx" - name: CLIENT_SECRET value: "xxxxxxxxxx" - name: ENV value: "prod" - name: DEBUG value: "False" - name: HOST value: "0.0.0.0" - name: PORT value: "5000"
Разверните ранее созданную конфигурацию:
kubectl apply -f kubernetes/api-deployment-with-ambassador.yaml
Давайте тестируем вещи: нам нужен внешний IP для посла:
kubectl get svc -o wide ambassador
Вы должны увидеть что-то вроде:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR ambassador LoadBalancer 10.103.201.13080:30283/TCP 9m2s service=ambassador
Если вы используете Minikube, нормально видеть внешний IP в в ожидании
штат.
Мы можем использовать Minikube-P Список услуг семинара
чтобы получить посол IP. Вы получите выход, аналогичный следующему:
|-------------|------------------|-----------------------------| | NAMESPACE | NAME | URL | |-------------|------------------|-----------------------------| | default | ambassador | http://192.168.99.100:30283 | | default | ambassador-admin | http://192.168.99.100:30084 | | default | kubernetes | No node port | | default | tgr | No node port | | kube-system | kube-dns | No node port | |-------------|------------------|-----------------------------|
Теперь вы можете использовать API, используя IP http://192.168.99.100:30283
:
curl "http://192.168.99.100:30283/?l=python&n=1" --- {"repos":[{"archive_url":"https://api.github.com/repos/vinta/awesome-python/{archive_format}{/ref}","archived":false,"assignees_url":"https://api.github.com/repos/vinta/awesome-python/assignees{/user}","blobs_url":"https://api.github.com/repos/vinta/awesome-python/git/blobs{/sha}","branches_url":"https://api.github.com/repos/vinta/awesome-python/branches{/branch}","clone_url":"https://github.com/vinta/awesome-python.git","collaborators_url":"https://api.github.com/repos/vinta/awesome-python/collaborators{/collaborator}","comments_url":"https://api.github.com/repos/vinta/awesome-python/comments{/number}","commits_url":"https://api.github.com/repos/vinta/awesome-python/commits{/sha}","compare_url":"https://api.github.com/repos/vinta/awesome-python/compare/{base}...{head}","contents_url":"https://api.github.com/repos/vinta/awesome-python/contents/{+path}","contributors_url":"https://api.github.com/repos/vinta/awesome-python/contributors","created_at":"2014-06-27T21:00:06Z","default_branch":"master","deployments_url":"https://api.github.com/repos/vinta/awesome-python/deployments","description":"A curated list of awesome Python frameworks, libraries, software and resources","disabled":false,"downloads_url":"https://api.github.com/repos/vinta/awesome-python/downloads","events_url":"https://api.github.com/repos/vinta/awesome-python/events","fork":false,"forks":13933,"forks_count":13933,"forks_url":"https://api.github.com/repos/vinta/awesome-python/forks","full_name":"vinta/awesome-python","git_commits_url":"https://api.github.com/repos/vinta/awesome-python/git/commits{/sha}","git_refs_url":"https://api.github.com/repos/vinta/awesome-python/git/refs{/sha}","git_tags_url":"https://api.github.com/repos/vinta/awesome-python/git/tags{/sha}","git_url":"git://github.com/vinta/awesome-python.git","has_downloads":true,"has_issues":true,"has_pages":true,"has_projects":false,"has_wiki":false,"homepage":"https://awesome-python.com/","hooks_url":"https://api.github.com/repos/vinta/awesome-python/hooks","html_url":"https://github.com/vinta/awesome-python","id":21289110,"issue_comment_url":"https://api.github.com/repos/vinta/awesome-python/issues/comments{/number}","issue_events_url":"https://api.github.com/repos/vinta/awesome-python/issues/events{/number}","issues_url":"https://api.github.com/repos/vinta/awesome-python/issues{/number}","keys_url":"https://api.github.com/repos/vinta/awesome-python/keys{/key_id}","labels_url":"https://api.github.com/repos/vinta/awesome-python/labels{/name}","language":"Python","languages_url":"https://api.github.com/repos/vinta/awesome-python/languages","license":{"key":"other","name":"Other","node_id":"MDc6TGljZW5zZTA=","spdx_id":"NOASSERTION","url":null},"merges_url":"https://api.github.com/repos/vinta/awesome-python/merges","milestones_url":"https://api.github.com/repos/vinta/awesome-python/milestones{/number}","mirror_url":null,"name":"awesome-python","network_count":13933,"node_id":"MDEwOlJlcG9zaXRvcnkyMTI4OTExMA==","notifications_url":"https://api.github.com/repos/vinta/awesome-python/notifications{?since,all,participating}","open_issues":482,"open_issues_count":482,"owner":{"avatar_url":"https://avatars2.githubusercontent.com/u/652070?v=4","events_url":"https://api.github.com/users/vinta/events{/privacy}","followers_url":"https://api.github.com/users/vinta/followers","following_url":"https://api.github.com/users/vinta/following{/other_user}","gists_url":"https://api.github.com/users/vinta/gists{/gist_id}","gravatar_id":"","html_url":"https://github.com/vinta","id":652070,"login":"vinta","node_id":"MDQ6VXNlcjY1MjA3MA==","organizations_url":"https://api.github.com/users/vinta/orgs","received_events_url":"https://api.github.com/users/vinta/received_events","repos_url":"https://api.github.com/users/vinta/repos","site_admin":false,"starred_url":"https://api.github.com/users/vinta/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vinta/subscriptions","type":"User","url":"https://api.github.com/users/vinta"},"private":false,"pulls_url":"https://api.github.com/repos/vinta/awesome-python/pulls{/number}","pushed_at":"2019-08-16T15:21:42Z","releases_url":"https://api.github.com/repos/vinta/awesome-python/releases{/id}","size":4994,"ssh_url":"git@github.com:vinta/awesome-python.git","stargazers_count":71269,"stargazers_url":"https://api.github.com/repos/vinta/awesome-python/stargazers","statuses_url":"https://api.github.com/repos/vinta/awesome-python/statuses/{sha}","subscribers_count":5254,"subscribers_url":"https://api.github.com/repos/vinta/awesome-python/subscribers","subscription_url":"https://api.github.com/repos/vinta/awesome-python/subscription","svn_url":"https://github.com/vinta/awesome-python","tags_url":"https://api.github.com/repos/vinta/awesome-python/tags","teams_url":"https://api.github.com/repos/vinta/awesome-python/teams","trees_url":"https://api.github.com/repos/vinta/awesome-python/git/trees{/sha}","updated_at":"2019-08-19T08:21:51Z","url":"https://api.github.com/repos/vinta/awesome-python","watchers":71269,"watchers_count":71269}],"status":"ok"}
Edge Proxy VS Сервисная сетка
Возможно, вы слышали о таких инструментах, как ISTIO и LinkerD, и это может быть запутано для сравнения посла или посланника к этим инструментам. Мы собираемся понимать различия здесь.
ISTIO описан как инструмент для подключения, безопасного, управления и наблюдения за обслуживанием. Те же функции реализуются своими альтернативами, такими как linkerd или consul. Эти инструменты называются сервисной сеткой.
Посол – это шлюз API для услуг (или микросервисов), и он развернут на краю вашей сети. Он направляет входящий трафик в кластерные внутренние услуги и это то, что мы называем «Север-Юг» трафик.
ISTIO, в другой руке, является сервисной сеткой для услуг Kubernetes (или микросервисов). Он предназначен для добавления уровня приложений (L7) наблюдаемости, маршрутизации и устойчивости к трафику услуг по обслуживанию услуг, и это то, что мы называем движением «Восток-Запад».
Тот факт, что как ISTIO, так и посол построены с использованием посланника, не означает, что у них есть те же особенности или удобства использования. Следовательно, их можно развернуть вместе в том же кластере.
Если вы помните, когда мы создали наш Minikube кластер, который мы использовали --extra-config = apisiserver.enable-swagger-ui = true
Отказ Эта конфигурация делает API Kubernetes «Roadiable» через веб-браузер.
При использовании Minikube, чтобы получить доступ к API Kubernetes с помощью браузера, нам нужно создать прокси:
kubectl proxy --port=8080 &
Теперь мы можем проверить это, используя CURL:
curl http://localhost:8080/api/ --- { "kind": "APIVersions", "versions": [ "v1" ], "serverAddressByClientCIDRs": [ { "clientCIDR": "0.0.0.0/0", "serverAddress": "192.168.99.100:8443" } ] }
Мы можем получить список API и ресурсов, которые мы можем получить доступ, посетив: http://localhost: 8080/
Отказ
Например, мы можем получить список метрик здесь http://localhost: 8080/метрики
Отказ
Использование клиента API
Мы собираемся использовать клиент Kubernetes:
pip install kubernetes
# import json # import requests # @app.route('/pods') # def monitor(): # # api_url = "http://kubernetes.default.svc/api/v1/pods/" # response = requests.get(api_url) # if response.status_code == 200: # return json.loads(response.content.decode('utf-8')) # else: # return None
Доступ к API изнутри стручка
По умолчанию POD связан с учетной записью службы, а учетная запись (токен) для этой учетной записи службы помещается в дерево файловых систем каждого контейнера в этом POD, в …/var/run/secrets/kubernetes.io/serviceacccount/totoken. .
Давайте попробуем зайти в POD и получить доступ к API. Использовать Kubectl Получить стручки
Чтобы получить список стручков
NAME READY STATUS RESTARTS AGE ambassador-64d8b877f9-4bzvn 1/1 Running 0 103m ambassador-64d8b877f9-b68w6 1/1 Running 0 103m ambassador-64d8b877f9-vw9mm 1/1 Running 0 103m tgr-8d78d599f-pt5xx 1/1 Running 0 4m17s
Теперь Войти внутри API POD:
kubectl exec -it tgr-8d78d599f-pt5xx bash
Назначьте токен к переменной:
KUBE_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
Обратите внимание, что файл токена добавляется автоматически Kubernetes.
У нас также есть другие переменные, уже установленные:
echo $KUBERNETES_SERVICE_HOST 10.96.0.1 echo $KUBERNETES_PORT_443_TCP_PORT 443 echo $HOSTNAME tgr-8d78d599f-pt5xx
Мы собираемся использовать эти переменные для доступа к списку PODS, используя эту команду CURL:
curl -sSk -H "Authorization: Bearer $KUBE_TOKEN" https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT/api/v1/namespaces/default/pods/$HOSTNAME
На этом этапе вы должны иметь выходную ошибку, говоря, что у вас нет прав на доступ к этой конечной точке API, что является нормальным:
{ "kind": "Status", "apiVersion": "v1", "metadata": { }, "status": "Failure", "message": "pods \"tgr-8d78d599f-pt5xx\" is forbidden: User \"system:serviceaccount:default:default\" cannot get resource \"pods\" in API group \"\" in the namespace \"default\"", "reason": "Forbidden", "details": { "name": "tgr-8d78d599f-pt5xx", "kind": "pods" }, "code": 403 }
POD использует учетную запись службы по умолчанию, и она не имеет права на передачу стручков.
Для того, чтобы исправить это, выйдите из контейнера и создайте файл под названием Kubernetes/Service-Account.yaml
Добавьте следующие строки:
kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: pods-list rules: - apiGroups: [""] resources: ["pods"] verbs: ["list"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: pods-list subjects: - kind: ServiceAccount name: default namespace: default roleRef: kind: ClusterRole name: pods-list apiGroup: rbac.authorization.k8s.io
Затем примените новую конфигурацию, используя Kubectl Apply Printe -F Kubernetes/Service-Account.yaml
Отказ
Теперь вы можете получить доступ к списку PODS:
{ "kind": "PodList", "apiVersion": "v1", "metadata": { "selfLink": "/api/v1/namespaces/default/pods/", "resourceVersion": "19589" }, "items": [ { "metadata": { "name": "ambassador-64d8b877f9-4bzvn", "generateName": "ambassador-64d8b877f9-", "namespace": "default", "selfLink": "/api/v1/namespaces/default/pods/ambassador-64d8b877f9-4bzvn", "uid": "63f62ede-de77-441d-85f7-daf9cbc7040f", "resourceVersion": "1047", "creationTimestamp": "2019-08-19T08:12:47Z", "labels": { "pod-template-hash": "64d8b877f9", "service": "ambassador" }, "annotations": { "consul.hashicorp.com/connect-inject": "false", "sidecar.istio.io/inject": "false" }, "ownerReferences": [ { "apiVersion": "apps/v1", "kind": "ReplicaSet", "name": "ambassador-64d8b877f9", "uid": "383c2e4b-7179-4806-b7bf-3682c7873a10", "controller": true, "blockOwnerDeletion": true } ] }, "spec": { "volumes": [ { "name": "ambassador-token-rdqq6", "secret": { "secretName": "ambassador-token-rdqq6", "defaultMode": 420 } } ], "containers": [ { "name": "ambassador", "image": "quay.io/datawire/ambassador:0.75.0", "ports": [ { "name": "http", "containerPort": 8080, "protocol": "TCP" }, ...
Как насчет создания собственного решения мониторинга/наблюдательного решения с использованием Python (или любого другого языка программирования) и API Kubernetes? Это может быть, вероятно, предмет предстоящего семинара.
Вы можете клонировать и внести свой вклад в Git Repos Отказ Дайте ему звезду, если вам это нравится:)
Оригинал: “https://dev.to/eon01/a-gentle-introduction-to-kubernetes-52en”