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

Нежное введение в Кубебение

В этой истории мы собираемся использовать участие в развертывании услуг Kubernetes и Gateway API посол API. Мы собираемся изучить разницу между kubernetes Proxies и Service Mesh, как ISTIO. Мы увидим, как получить доступ к API Kubernetes и откройте для себя некоторые подводные камни безопасности при строительстве докеровских изображений и много интересных вещей. Теги с Docker, Kubernetes, Python, Devops.

Доступный слайд здесь Отказ Оригинальная статья опубликована здесь Отказ Исходный код здесь Отказ

В этом семинаре мы собираемся:

  • Разверните службы 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

На практике нам нужно:

  1. Объект развертывания : Контейнеры указаны здесь.
  2. Объект сервиса : Абстрактный способ разоблачить приложение, запущенное на наборе стручков в качестве сетевой службы.

Это объект развертывания, который создает три копирования приложения контейнера, выполняющим изображение «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.1               443/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.1               443/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.130        80: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”