One place for hosting & domains

      Как

      Как настроить комплекс регистрации данных Elasticsearch, Fluentd и Kibana (EFK) в Kubernetes


      Введение

      При запуске разнообразных служб и приложений в кластере Kubernetes централизованный комплекс регистрации данных кластерного уровня поможет быстро сортировать и анализировать большие объемы данных журналов подов. В числе популярных централизованных решений регистрации данных нельзя не назвать комплекс Elasticsearch, Fluentd, and Kibana (EFK).

      Elasticsearch — распределенный и масштабируемый механизм поиска в реальном времени, поддерживающий полнотекстовый и структурированный поиск, а также аналитику. Он обычно используется для индексации больших журналов и поиска в них данных, но также его можно использовать и для поиска во многих различных видах документов.

      Elasticsearch обычно развертывается вместе с Kibana, мощным интерфейсом визуализации данных, который выступает как панель управления Elasticsearch. Kibana позволяет просматривать данные журналов Elasticsearch через веб-интерфейс и создавать информационные панели и запросы для быстрого получения ответов на вопросы и аналитических данных по вашим приложениям Kubernetes.

      В этом обучающем модуле мы используем Fluentd для сбора данных журнала и их преобразования и отправки на сервер Elasticsearch. Fluentd — популярный сборщик данных с открытым исходным кодом, который мы настроим на узлах Kubernetes для отслеживания файлов журнала контейнеров, фильтрации и преобразования данных журнала и их доставки в кластер Elasticsearch, где они будут индексироваться и храниться.

      Для начала мы настроим и запустим масштабируемый кластер Elasticsearch, а затем создадим службу и развертывание Kibana в Kubernetes. В заключение мы настроим Fluentd как DaemonSet, который будет запускаться на каждом рабочем узле Kubernetes.

      Предварительные требования

      Прежде чем начать прохождение этого обучающего модуля, вам потребуется следующее:

      • Кластер Kubernetes 1.10+ с включенным контролем доступа на основе ролей (RBAC)

        • Убедитесь, что кластер имеет достаточно ресурсов для развертывания комплекса EFK. Если ресурсов недостаточно, добавьте в кластер еще рабочие узлы. Мы развернем кластер Elasticsearch с 3 подами (при необходимости вы можете масштабировать развертывание до 1 пода), а также один под Kibana. На каждом рабочем узле также будет запущен под Fluentd. Используемый в этом обучающем модуле кластер будет состоять из 3 рабочих узлов и управляемого уровня управления.
      • Инструмент командной строки kubectl, установленный на локальном компьютере и настроенный для подключения к вашему кластеру. Дополнительную информацию об установке kubectl можно найти в официальной документации.

      Проверив наличие этих компонентов, вы можете начинать прохождение этого обучающего модуля.

      Шаг 1 — Создание пространства имен

      Прежде чем разворачивать кластер Elasticsearch, мы создадим пространство имен, куда установим весь инструментарий ведения журналов. Kubernetes позволяет отделять объекты, работающие в кластере, с помощью виртуального абстрагирования кластеров через пространства имен. В этом обучающем модуле мы создадим пространство имен kube-logging, куда установим компоненты комплекса EFK. Это пространство имен также позволит нам быстро очищать и удалять комплекс журналов без потери функциональности кластера Kubernetes.

      Для начала исследуйте существующие пространства имен в вашем кластере с помощью команды kubectl:

      kubectl get namespaces
      

      Вы должны увидеть следующие три начальных пространства имен, которые предустанавливаются в кластерах Kubernetes:

      Output

      • NAME STATUS AGE
      • default Active 5m
      • kube-system Active 5m
      • kube-public Active 5m

      Пространство имен default содержит объекты, которые создаются без указания пространства имен. Пространство имен kube-system содержит объекты, созданные и используемые системой Kubernetes, в том числе kube-dns, kube-proxy и kubernetes-dashboard. Это пространство имен лучше регулярно очищать и не засорять его рабочими задачами приложений и инструментария.

      Пространство имен kube-public — это еще одно автоматически создаваемое пространство имен, которое можно использовать для хранения объектов, которые вы хотите сделать доступными и читаемыми во всем кластере, в том числе для пользователей, которые не прошли аутентификацию.

      Для создания пространства имен kube-logging откройте файл kube-logging.yaml в своем любимом текстовом редакторе, например nano:

      В редакторе вставьте следующий код YAML объекта пространства имен:

      kube-logging.yaml

      kind: Namespace
      apiVersion: v1
      metadata:
        name: kube-logging
      

      Затем сохраните и закройте файл.

      Здесь мы зададим kind объекта Kubernetes как объект Namespace. Чтобы узнать больше об объектах Namespace, ознакомьтесь с кратким обзором пространств имен в официальной документации по Kubernetes. Также мы зададим версию Kubernetes API, используемую для создания объекта (v1), и присвоим ему name kube-logging.

      После создания файла объекта пространства имен kube-logging.yaml создайте пространство имен с помощью команды kubectl create с флагом -f имя файла:

      • kubectl create -f kube-logging.yaml

      Вы должны увидеть следующий результат:

      Output

      namespace/kube-logging created

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

      Теперь вы должны увидеть новое пространство имен kube-logging:

      Output

      NAME STATUS AGE default Active 23m kube-logging Active 1m kube-public Active 23m kube-system Active 23m

      Теперь мы можем развернуть кластер Elasticsearch в изолированном пространстве имен logging, предназначенном для журналов.

      Шаг 2 — Создание набора Elasticsearch StatefulSet

      Мы создали пространство имен для нашего комплекса ведения журналов, и теперь можем начать развертывание его компонентов. Вначале мы развернем кластер Elasticsearch из 3 узлов.

      В этом руководстве мы будем использовать 3 пода Elasticsearch, чтобы избежать проблемы «разделения мозга», которая встречается в сложных кластерах с множеством узлов и высоким уровнем доступности. Такое «разделение мозга» происходит, когда несколько узлов не могут связываться с другими узлами, и в связи с этим выбирается несколько отдельных основных узлов. В случае с 3 узлами, если один узел временно отключается от кластера, остальные два узла могут выбрать новый основной узел, и кластер будет продолжать работу, пока последний узел будет пытаться снова присоединиться к нему. Дополнительную информацию можно найти в документах «Новая эпоха координации кластеров в Elasticsearch» и «Конфигурации голосования».

      Создание службы без главного узла

      Для начала мы создадим службу Kubernetes без главного узла с именем elasticsearch, которая будет определять домен DNS для 3 подов. Служба без главного узла не выполняет балансировку нагрузки и не имеет статического IP-адреса. Дополнительную информацию о службах без главного узла можно найти в официальной документации по Kubernetes.

      Откройте файл с именем elasticsearch_svc.yaml в своем любимом редакторе:

      • nano elasticsearch_svc.yaml

      Вставьте следующий код YAML службы Kubernetes:

      elasticsearch_svc.yaml

      kind: Service
      apiVersion: v1
      metadata:
        name: elasticsearch
        namespace: kube-logging
        labels:
          app: elasticsearch
      spec:
        selector:
          app: elasticsearch
        clusterIP: None
        ports:
          - port: 9200
            name: rest
          - port: 9300
            name: inter-node
      

      Затем сохраните и закройте файл.

      Мы определяем Service с именем elasticsearch в пространстве имен kube-logging и присваиваем ей ярлык app: elasticsearch. Затем мы задаем для .spec.selector значение app: elasticsearch, чтобы служба выбирала поды с ярлыком app: elasticsearch. Когда мы привязываем Elasticsearch StatefulSet к этой службе, служба возвращает записи DNS A, которые указывают на поды Elasticsearch с ярлыком app: elasticsearch.

      Затем мы задаем параметр clusterIP: None, который делает эту службу службой без главного узла. В заключение мы определяем порты 9200 и 9300, которые используются для взаимодействия с REST API и для связи между узлами соответственно.

      Создайте службу с помощью kubectl:

      • kubectl create -f elasticsearch_svc.yaml

      Вы должны увидеть следующий результат:

      Output

      service/elasticsearch created

      Еще раз проверьте создание службы с помощью команды kubectl get:

      kubectl get services --namespace=kube-logging
      

      Вы должны увидеть следующее:

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE elasticsearch ClusterIP None <none> 9200/TCP,9300/TCP 26s

      Мы настроили службу без главного узла и стабильный домен .elasticsearch.kube-logging.svc.cluster.local для наших подов. Теперь мы можем создать набор StatefulSet.

      Создание набора StatefulSet

      Набор Kubernetes StatefulSet позволяет назначать подам стабильный идентификатор и предоставлять им стабильное и постоянное хранилище. Elasticsearch требуется стабильное хранилище, чтобы его данные сохранялись при перезапуске и изменении планировки подов. Дополнительную информацию о рабочей задаче StatefulSet можно найти на странице Statefulsets в документации по Kubernetes.

      Откройте файл с именем elasticsearch_statefulset.yaml в своем любимом редакторе:

      • nano elasticsearch_statefulset.yaml

      Мы изучим каждый раздел определения объекта StatefulSet, вставляя в этот файл блоки.

      Для начала вставьте следующий блок:

      elasticsearch_statefulset.yaml

      apiVersion: apps/v1
      kind: StatefulSet
      metadata:
        name: es-cluster
        namespace: kube-logging
      spec:
        serviceName: elasticsearch
        replicas: 3
        selector:
          matchLabels:
            app: elasticsearch
        template:
          metadata:
            labels:
              app: elasticsearch
      

      В этом блоке мы определяем объект StatefulSet под названием es-cluster в пространстве имен kube-logging. Затем мы связываем его с ранее созданной службой elasticsearch, используя поле serviceName. За счет этого каждый под набора StatefulSet будет доступен по следующему адресу DNS: es-cluster-[0,1,2].elasticsearch.kube-logging.svc.cluster.local, где [0,1,2] соответствует назначенному номеру пода в виде обычного целого числа.

      Мы задали 3 копии (пода) и устанлвили для селектора matchLabels значение app: elasticseach, которое мы также отразим в разделе .spec.template.metadata. Поля .spec.selector.matchLabels и .spec.template.metadata.labels должны совпадать.

      Теперь мы можем перейти к спецификации объекта. Вставьте следующий блок кода YAML непосредственно под предыдущим блоком:

      elasticsearch_statefulset.yaml

      . . .
          spec:
            containers:
            - name: elasticsearch
              image: docker.elastic.co/elasticsearch/elasticsearch:7.2.0
              resources:
                  limits:
                    cpu: 1000m
                  requests:
                    cpu: 100m
              ports:
              - containerPort: 9200
                name: rest
                protocol: TCP
              - containerPort: 9300
                name: inter-node
                protocol: TCP
              volumeMounts:
              - name: data
                mountPath: /usr/share/elasticsearch/data
              env:
                - name: cluster.name
                  value: k8s-logs
                - name: node.name
                  valueFrom:
                    fieldRef:
                      fieldPath: metadata.name
                - name: discovery.seed_hosts
                  value: "es-cluster-0.elasticsearch,es-cluster-1.elasticsearch,es-cluster-2.elasticsearch"
                - name: cluster.initial_master_nodes
                  value: "es-cluster-0,es-cluster-1,es-cluster-2"
                - name: ES_JAVA_OPTS
                  value: "-Xms512m -Xmx512m"
      

      Здесь мы определяем поды в наборе StatefulSet. Мы присвоим контейнерам имя elasticsearch и выберем образ Docker docker.elastic.co/elasticsearch/elasticsearch:7.2.0. Сейчас вы можете изменить метку образа, чтобы она соответствовала вашему собственному образу Elasticsearch или другой версии образа. Для целей настоящего обучающего модуля тестировалась только версия Elasticsearch 7.2.0.

      Мы используем поле resources, чтобы указать, что контейнеру требуется всего гарантировать всего десятую часть ресурсов vCPU с возможностью увеличения загрузки до 1 vCPU (что ограничивает использование ресурсов подом при первоначальной обработке большого объема данных или при пиковой нагрузке). Вам следует изменить эти значения в зависимости от ожидаемой нагрузки и доступных ресурсов. Дополнительную информацию о запросах ресурсов и ограничениях можно найти в официальной документации по Kubernetes.

      Мы откроем и назовем порты 9200 и 9300 для REST API и связи между узлами соответственно. Мы зададим volumeMount с именем data, который будет монтировать постоянный том с именем data в контейнер по пути /usr/share/elasticsearch/data. Мы определим VolumeClaims для набора StatefulSet в другом блоке YAML позднее.

      В заключение мы зададим в контейнере несколько переменных среды:

      • cluster.name: имя кластера Elasticsearch, в данном обучающем модуле это k8s-logs.
      • node.name: имя узла, которое мы устанавливаем как значение поля .metadata.name с помощью valueFrom. Оно разрешается как es-cluster-[0,1,2] в зависимости от назначенного узлу порядкового номера.
      • discovery.seed_hosts: это поле использует список потенциальных главных узлов в кластере, инициирующем процесс обнаружения узлов. Поскольку в этом обучающем модуле мы уже настроили службу без главного узла, наши поды имеют домены в форме es-cluster-[0,1,2].elasticsearch.kube-logging.svc.cluster.local, так что мы зададим соответствующее значение для этой переменной. Используя разрешение DNS в локальном пространстве имен Kubernetes мы можем сократить это до es-cluster-[0,1,2].elasticsearch. Дополнительную информацию об обнаружении Elasticsearch можно найти в официальной документации по Elasticsearch.
      • cluster.initial_master_nodes: в этом поле также задается список потенциальных главных узлов, которые будут участвовать в процессе выбора главного узла. Обратите внимание, что для этого поля узлы нужно указывать по имени node.name, а не по именам хостов.
      • ES_JAVA_OPTS: здесь мы задаем значение -Xms512m -Xmx512m, которое предписывает JVM использовать минимальный и максимальный размер выделения памяти 512 МБ. Вам следует настроить эти параметры в зависимости от доступности ресурсов и потребностей вашего кластера. Дополнительную информацию можно найти в разделе «Настройка размера выделяемой памяти».

      Следующий блок, который мы будем вставлять, выглядит следующим образом:

      elasticsearch_statefulset.yaml

      . . .
            initContainers:
            - name: fix-permissions
              image: busybox
              command: ["sh", "-c", "chown -R 1000:1000 /usr/share/elasticsearch/data"]
              securityContext:
                privileged: true
              volumeMounts:
              - name: data
                mountPath: /usr/share/elasticsearch/data
            - name: increase-vm-max-map
              image: busybox
              command: ["sysctl", "-w", "vm.max_map_count=262144"]
              securityContext:
                privileged: true
            - name: increase-fd-ulimit
              image: busybox
              command: ["sh", "-c", "ulimit -n 65536"]
              securityContext:
                privileged: true
      

      В этом блоке мы определяем несколько контейнеров инициализации, которые запускаются до главного контейнера приложения elasticsearch. Каждый из этих контейнеров инициализации выполняется до конца в заданном порядке. Дополнительную информацию о контейнерах инициализации можно найти в официальной документации по Kubernetes.

      Первый такой контейнер с именем fix-permissions запускает команду chown для смены владельца и группы каталога данных Elasticsearch на 1000:1000, UID польздователя Elasticsearch. По умолчанию Kubernetes монтирует каталог данных как root, что делает его недоступным для Elasticsearch. Дополнительную информацию об этом шаге можно найти в документации по Elasticsearch «Замечания по использованию в производстве и значения по умолчанию».

      Второй контейнер с именем increase-vm-max-map запускает команду для увеличения предельного количества mmap в операционной системе, которое по умолчанию может быть слишком низким, в результате чего могут возникать ошибки памяти. Дополнительную информацию об этом шаге можно найти в официальной документации по Elasticsearch.

      Следующим запускается контейнер инициализации increase-fd-ulimit, который запускает команду ulimit для увеличения максимального количества дескрипторов открытых файлов. Дополнительную информацию об этом шаге можно найти в документации по Elasticsearch «Замечания по использованию в производстве и значения по умолчанию».

      Примечание. В документе «Замечания по использованию в производстве и значения по умолчанию» для Elasticsearch также указывается возможность отключения подкачки для повышения производительности. В зависимости от вида установки Kubernetes и провайдера, подкачка может быть уже отключена. Чтобы проверить это, выполните команду exec в работающем контейнере и запустите cat /proc/swaps для вывода активных устройств подкачки. Если этот список пустой, подкачка отключена.

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

      Вставьте следующий блок volumeClaimTemplate:

      elasticsearch_statefulset.yaml

      . . .
        volumeClaimTemplates:
        - metadata:
            name: data
            labels:
              app: elasticsearch
          spec:
            accessModes: [ "ReadWriteOnce" ]
            storageClassName: do-block-storage
            resources:
              requests:
                storage: 100Gi
      

      В этом блоке мы определяем для StatefulSet шаблоны volumeClaimTemplates. Kubernetes использует эти настройки для создания постоянных томов для подов. В приведенном выше блоке мы использовали имя data (это name, на которое мы уже ссылались в определении volumeMounts), и присвоили ему тот же ярлык app: elasticsearch, что и для набора StatefulSet.

      Затем мы задаем для него режим доступа ReadWriteOnce, и это означает, что его может монтировать для чтения и записи только один узел. В этом обучающем модуле мы определяем класс хранения do-block-storage, поскольку мы используем для демонстрации кластер DigitalOcean Kubernetes. Вам следует изменить это значение в зависимости от того, где вы запускаете свой кластер Kubernetes. Дополнительную информацию можно найти в документации по постоянным томам.

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

      Полная спецификация StatefulSet должна выглядеть примерно так:

      elasticsearch_statefulset.yaml

      apiVersion: apps/v1
      kind: StatefulSet
      metadata:
        name: es-cluster
        namespace: kube-logging
      spec:
        serviceName: elasticsearch
        replicas: 3
        selector:
          matchLabels:
            app: elasticsearch
        template:
          metadata:
            labels:
              app: elasticsearch
          spec:
            containers:
            - name: elasticsearch
              image: docker.elastic.co/elasticsearch/elasticsearch:7.2.0
              resources:
                  limits:
                    cpu: 1000m
                  requests:
                    cpu: 100m
              ports:
              - containerPort: 9200
                name: rest
                protocol: TCP
              - containerPort: 9300
                name: inter-node
                protocol: TCP
              volumeMounts:
              - name: data
                mountPath: /usr/share/elasticsearch/data
              env:
                - name: cluster.name
                  value: k8s-logs
                - name: node.name
                  valueFrom:
                    fieldRef:
                      fieldPath: metadata.name
                - name: discovery.seed_hosts
                  value: "es-cluster-0.elasticsearch,es-cluster-1.elasticsearch,es-cluster-2.elasticsearch"
                - name: cluster.initial_master_nodes
                  value: "es-cluster-0,es-cluster-1,es-cluster-2"
                - name: ES_JAVA_OPTS
                  value: "-Xms512m -Xmx512m"
            initContainers:
            - name: fix-permissions
              image: busybox
              command: ["sh", "-c", "chown -R 1000:1000 /usr/share/elasticsearch/data"]
              securityContext:
                privileged: true
              volumeMounts:
              - name: data
                mountPath: /usr/share/elasticsearch/data
            - name: increase-vm-max-map
              image: busybox
              command: ["sysctl", "-w", "vm.max_map_count=262144"]
              securityContext:
                privileged: true
            - name: increase-fd-ulimit
              image: busybox
              command: ["sh", "-c", "ulimit -n 65536"]
              securityContext:
                privileged: true
        volumeClaimTemplates:
        - metadata:
            name: data
            labels:
              app: elasticsearch
          spec:
            accessModes: [ "ReadWriteOnce" ]
            storageClassName: do-block-storage
            resources:
              requests:
                storage: 100Gi
      

      Когда вы будете удовлетворены конфигурацией Elasticsearch, сохраните и закройте файл.

      Теперь мы развернем набор StatefulSet с использованием kubectl:

      • kubectl create -f elasticsearch_statefulset.yaml

      Вы должны увидеть следующий результат:

      Output

      statefulset.apps/es-cluster created

      Вы можете отслеживать набор StatefulSet, развернутый с помощью kubectl rollout status:

      • kubectl rollout status sts/es-cluster --namespace=kube-logging

      При развертывании кластера вы увидите следующие результаты:

      Output

      Waiting for 3 pods to be ready... Waiting for 2 pods to be ready... Waiting for 1 pods to be ready... partitioned roll out complete: 3 new pods have been updated...

      После развертывания всех подов вы можете использовать запрос REST API, чтобы убедиться, что кластер Elasticsearch функционирует нормально.

      Для этого вначале нужно перенаправить локальный порт 9200 на порт 9200 одного из узлов Elasticsearch (es-cluster-0) с помощью команды kubectl port-forward:

      • kubectl port-forward es-cluster-0 9200:9200 --namespace=kube-logging

      В отдельном окне терминала отправьте запрос curl к REST API:

      • curl http://localhost:9200/_cluster/state?pretty

      Результат должен выглядеть следующим образом:

      Output

      { "cluster_name" : "k8s-logs", "compressed_size_in_bytes" : 348, "cluster_uuid" : "QD06dK7CQgids-GQZooNVw", "version" : 3, "state_uuid" : "mjNIWXAzQVuxNNOQ7xR-qg", "master_node" : "IdM5B7cUQWqFgIHXBp0JDg", "blocks" : { }, "nodes" : { "u7DoTpMmSCixOoictzHItA" : { "name" : "es-cluster-1", "ephemeral_id" : "ZlBflnXKRMC4RvEACHIVdg", "transport_address" : "10.244.8.2:9300", "attributes" : { } }, "IdM5B7cUQWqFgIHXBp0JDg" : { "name" : "es-cluster-0", "ephemeral_id" : "JTk1FDdFQuWbSFAtBxdxAQ", "transport_address" : "10.244.44.3:9300", "attributes" : { } }, "R8E7xcSUSbGbgrhAdyAKmQ" : { "name" : "es-cluster-2", "ephemeral_id" : "9wv6ke71Qqy9vk2LgJTqaA", "transport_address" : "10.244.40.4:9300", "attributes" : { } } }, ...

      Это показывает, что журналы k8s-logs нашего кластера Elasticsearch успешно созданы с 3 узлами: es-cluster-0, es-cluster-1 и es-cluster-2. В качестве главного узла выступает узел es-cluster-0.

      Теперь ваш кластер Elasticsearch запущен, и вы можете перейти к настройке на нем клиентского интерфейса Kibana.

      Шаг 3 — Создание развертывания и службы Kibana

      Чтобы запустить Kibana в Kubernetes, мы создадим службу с именем kibana, а также развертывание, состоящее из одной копии пода. Вы можете масштабировать количество копий в зависимости от ваших производственных потребностей и указывать тип LoadBalancer, чтобы служба запрашивала балансировку нагрузки на подах развертывания.

      В этом случае мы создадим службу и развертывание в одном и том же файле. Откройте файл с именем kibana.yaml в своем любимом редакторе:

      Вставьте следующую спецификацию службы:

      kibana.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: kibana
        namespace: kube-logging
        labels:
          app: kibana
      spec:
        ports:
        - port: 5601
        selector:
          app: kibana
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: kibana
        namespace: kube-logging
        labels:
          app: kibana
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: kibana
        template:
          metadata:
            labels:
              app: kibana
          spec:
            containers:
            - name: kibana
              image: docker.elastic.co/kibana/kibana:7.2.0
              resources:
                limits:
                  cpu: 1000m
                requests:
                  cpu: 100m
              env:
                - name: ELASTICSEARCH_URL
                  value: http://elasticsearch:9200
              ports:
              - containerPort: 5601
      

      Затем сохраните и закройте файл.

      В этой спецификации мы определили службу с именем kibana в пространстве имен kube-logging и присвоить ему ярлык app: kibana.

      Также мы указали, что она должна быть доступна на порту 5601, и использовали ярлык app: kibana для выбора целевых подов службы.

      В спецификации Deployment мы определим развертывание с именем kibana и укажем, что нам требуется 1 копия пода.

      Мы будем использовать образ docker.elastic.co/kibana/kibana:7.2.0. Сейчас вы можете заменить этот образ на собственный частный или публичный образ Kibana, который вы хотите использовать.

      Мы укажем, что нам требуется гарантировать для пода не менее 0.1 vCPU и не более 1 vCPU при пиковой нагрузке. Вам следует изменить эти значения в зависимости от ожидаемой нагрузки и доступных ресурсов.

      Теперь мы используем переменную среды ELASTICSEARCH_URL для установки конечной точки и порта для кластера Elasticsearch. При использовании Kubernetes DNS эта конечная точка соответствует названию службы elasticsearch. Этот домен разрешится в список IP-адресов для 3 подов Elasticsearch. Дополнительную информацию о Kubernetes DNS можно получить в документе DNS для служб и подов.

      Наконец мы настроим для контейнера Kibana порт 5601, куда служба kibana будет перенаправлять запросы.

      Когда вы будете удовлетворены конфигурацией Kibana, вы можете развернуть службу и развертывание с помощью команды kubectl:

      • kubectl create -f kibana.yaml

      Вы должны увидеть следующий результат:

      Output

      service/kibana created deployment.apps/kibana created

      Вы можете проверить успешность развертывания, запустив следующую команду:

      • kubectl rollout status deployment/kibana --namespace=kube-logging

      Вы должны увидеть следующий результат:

      Output

      deployment "kibana" successfully rolled out

      Чтобы получить доступ к интерфейсу Kibana, мы снова перенаправим локальный порт на узел Kubernetes, где запущена служба Kibana. Получите подробную информацию о поде Kibana с помощью команды kubectl get:

      • kubectl get pods --namespace=kube-logging

      Output

      NAME READY STATUS RESTARTS AGE es-cluster-0 1/1 Running 0 55m es-cluster-1 1/1 Running 0 54m es-cluster-2 1/1 Running 0 54m kibana-6c9fb4b5b7-plbg2 1/1 Running 0 4m27s

      Здесь мы видим, что наш под Kibana имеет имя kibana-6c9fb4b5b7-plbg2.

      Перенаправьте локальный порт 5601 на порт 5601 этого пода:

      • kubectl port-forward kibana-6c9fb4b5b7-plbg2 5601:5601 --namespace=kube-logging

      Вы должны увидеть следующий результат:

      Output

      Forwarding from 127.0.0.1:5601 -> 5601 Forwarding from [::1]:5601 -> 5601

      Откройте в своем браузере следующий URL:

      http://localhost:5601
      

      Если вы увидите следующую приветственную страницу Kibana, это означает, что вы успешно развернули Kibana в своем кластере Kubernetes:

      Приветственный экран Kibana

      Теперь вы можете перейти к развертыванию последнего компонента комплекса EFK: сборщика данных журнала Fluentd.

      Шаг 4 — Создание набора демонов Fluentd

      В этом обучающем модуле мы настроим Fluentd как набор демонов. Это тип рабочей задачи Kubernetes, запускающий копию указанного пода на каждом узле в кластере Kubernetes. Используя контроллер набора демонов, мы развернем под агента регистрации данных Fluentd на каждом узле нашего кластера. Дополнительную информацию об архитектуре регистрации данных можно найти в документе «Использование агента регистрации данных узлов» в официальной документации по Kubernetes.

      В Kubernetes приложения в контейнерах записывают данные в stdout и stderr, и их потоки регистрируемых данных записываются и перенаправляются в файлы JSON на узлах. Под Fluentd отслеживает эти файлы журналов, фильтрует события журналов, преобразует данные журналов и отправляет их на сервенюу часть регистрации данных Elasticsearch, которую мы развернули на шаге 2.

      Помимо журналов контейнеров, агент Fluentd также отслеживает журналы системных компонентов Kubernetes, в том числе журналы kubelet, kube-proxy и Docker. Полный список источников, отслеживаемых агентом регистрации данных Fluentd, можно найти в файле kubernetes.conf, используемом для настройки агента регистрации данных. Дополнительную информацию по регистрации данных в кластерах Kubernetes можно найти в документе «Регистрация данных на уровне узлов» в официальной документации по Kubernetes.

      Для начала откройте файл fluentd.yaml в предпочитаемом текстовом редакторе:

      Мы снова будем вставлять определения объектов Kubernetes по блокам с указанием дополнительного контекста. В этом руководстве мы используем спецификацию набора демонов Fluentd, предоставленную командой обслуживания Fluentd. Также команда обслуживания Fluentd предоставляет полезный ресурс Kuberentes Fluentd.

      Вставьте следующее определение служебной учетной записи:

      fluentd.yaml

      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: fluentd
        namespace: kube-logging
        labels:
          app: fluentd
      

      Здесь мы создаем служебную учетную запись fluentd, которую поды Fluentd будут использовать для доступа к Kubernetes API. Мы создаем ее в пространстве имен kube-logging и снова присваиваем ей ярлык app: fluentd. Дополнительную информацию о служебных учетных записях в Kubernetes можно найти в документе «Настройка служебных учетных записей для подов» в официальной документации по Kubernetes.

      Затем вставьте следующий блок ClusterRole:

      fluentd.yaml

      . . .
      ---
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRole
      metadata:
        name: fluentd
        labels:
          app: fluentd
      rules:
      - apiGroups:
        - ""
        resources:
        - pods
        - namespaces
        verbs:
        - get
        - list
        - watch
      

      Здесь мы определяем блок ClusterRole с именем fluentd, которому мы предоставляем разрешения get, list и watch для объектов pods и namespaces. ClusterRoles позволяет предоставлять доступ к ресурсам в кластере Kubernetes, в том числе к узлам. Дополнительную информацию о контроле доступа на основе ролей и ролях кластеров можно найти в документе «Использование авторизации RBAC» в официальной документации Kubernetes.

      Теперь вставьте следующий блок ClusterRoleBinding:

      fluentd.yaml

      . . .
      ---
      kind: ClusterRoleBinding
      apiVersion: rbac.authorization.k8s.io/v1
      metadata:
        name: fluentd
      roleRef:
        kind: ClusterRole
        name: fluentd
        apiGroup: rbac.authorization.k8s.io
      subjects:
      - kind: ServiceAccount
        name: fluentd
        namespace: kube-logging
      

      В этом блоке мы определяем объект ClusterRoleBinding с именем fluentd, которй привязывает роль кластера fluentd к служебной учетной записи fluentd. Это дает служебной учетной записи fluentd разрешения, заданные для роли кластера fluentd.

      Сейчас мы можем начать вставку спецификации набора демонов:

      fluentd.yaml

      . . .
      ---
      apiVersion: apps/v1
      kind: DaemonSet
      metadata:
        name: fluentd
        namespace: kube-logging
        labels:
          app: fluentd
      

      Здесь мы определяем набор демонов с именем fluentd в пространстве имен kube-logging и назначаем ему ярлык app: fluentd.

      Вставьте следующий раздел:

      fluentd.yaml

      . . .
      spec:
        selector:
          matchLabels:
            app: fluentd
        template:
          metadata:
            labels:
              app: fluentd
          spec:
            serviceAccount: fluentd
            serviceAccountName: fluentd
            tolerations:
            - key: node-role.kubernetes.io/master
              effect: NoSchedule
            containers:
            - name: fluentd
              image: fluent/fluentd-kubernetes-daemonset:v1.4.2-debian-elasticsearch-1.1
              env:
                - name:  FLUENT_ELASTICSEARCH_HOST
                  value: "elasticsearch.kube-logging.svc.cluster.local"
                - name:  FLUENT_ELASTICSEARCH_PORT
                  value: "9200"
                - name: FLUENT_ELASTICSEARCH_SCHEME
                  value: "http"
                - name: FLUENTD_SYSTEMD_CONF
                  value: disable
      

      Здесь мы сопоставляем ярлык app: fluentd, определенный в .metadata.labels и назначаем для набора демонов служебную учетную запись fluentd. Также мы выбираем app: fluentd как поды, управляемые этим набором демонов.

      Затем мы определяем допуск NoSchedule для соответствия эквивалентному вызову в главных узлах Kubernetes. Это гарантирует, что набор демонов также будет развернут на главных узлах Kubernetes. Если вы не хотите запускать под Fluentd на главных узлах, удалите этот допуск. Дополнительную информацию о вызовах и допусках Kubernetes можно найти в разделе «Вызовы и допуски» в официальной документации по Kubernetes.

      Теперь мы начнем определять контейнер пода с именем fluentd.

      Мы используем официальный образ v1.4.2 Debian от команды, обслуживающей Fluentd. Если вы хотите использовать свой частный или публичный образ Fluentd или использовать другую версию образа, измените тег image в спецификации контейнера. Файл Dockerfile и содержание этого образа доступны в репозитории fluentd-kubernetes-daemonset на Github.

      Теперь мы настроим Fluentd с помощью нескольких переменных среды:

      • FLUENT_ELASTICSEARCH_HOST: мы настроим службу Elasticsearch без главных узлов, которую мы определили ранее: elasticsearch.kube-logging.svc.cluster.local. Это разрешается список IP-адресов для 3 подов Elasticsearch. Скорее всего, реальный хост Elasticsearch будет первым IP-адресом, который будет выведен в этом списке. Для распределения журналов в этом кластере вам потребуется изменить конфигурацию плагина вывода Fluentd Elasticsearch. Дополнительную информацию об этом плагине можно найти в документе «Плагин вывода Elasticsearch».
      • FLUENT_ELASTICSEARCH_PORT: в этом параметре мы задаем ранее настроенный порт Elasticsearch 9200.
      • FLUENT_ELASTICSEARCH_SCHEME: мы задаем для этого параметра значение http.
      • FLUENTD_SYSTEMD_CONF: мы задаем для этого параметра значение disable, чтобы подавить вывод systemd, который не настроен в контейнере.

      Вставьте следующий раздел:

      fluentd.yaml

      . . .
              resources:
                limits:
                  memory: 512Mi
                requests:
                  cpu: 100m
                  memory: 200Mi
              volumeMounts:
              - name: varlog
                mountPath: /var/log
              - name: varlibdockercontainers
                mountPath: /var/lib/docker/containers
                readOnly: true
            terminationGracePeriodSeconds: 30
            volumes:
            - name: varlog
              hostPath:
                path: /var/log
            - name: varlibdockercontainers
              hostPath:
                path: /var/lib/docker/containers
      

      Здесь мы указываем предельный объем памяти 512 МиБ в поде FluentD и гарантируем выделение 0,1 vCPU и 200 МиБ памяти. Вы можете настроить эти ограничения ресурсов и запросы в зависимости от ожидаемого объема журнала и доступных ресурсов.

      Затем мы смонтируем пути хостов /var/log и /var/lib/docker/containers в контейнер, используя varlog и varlibdockercontainers volumeMounts. Эти тома определяются в конце блока.

      Последний параметр, который мы определяем в этом блоке, — это параметр terminationGracePeriodSeconds, дающий Fluentd 30 секунд для безопасного выключения при получении сигнала SIGTERM. После 30 секунд контейнеры получают сигнал SIGKILL. Значение по умолчанию для terminationGracePeriodSeconds составляет 30 с, так что в большинстве случаев этот параметр можно пропустить. Дополнительную информацию о безопасном прекращении рабочих задач Kubernetes можно найти в документе Google «Лучшие практики Kubernetes: осторожное прекращение работы».

      Полная спецификация Fluentd должна выглядеть примерно так:

      fluentd.yaml

      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: fluentd
        namespace: kube-logging
        labels:
          app: fluentd
      ---
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRole
      metadata:
        name: fluentd
        labels:
          app: fluentd
      rules:
      - apiGroups:
        - ""
        resources:
        - pods
        - namespaces
        verbs:
        - get
        - list
        - watch
      ---
      kind: ClusterRoleBinding
      apiVersion: rbac.authorization.k8s.io/v1
      metadata:
        name: fluentd
      roleRef:
        kind: ClusterRole
        name: fluentd
        apiGroup: rbac.authorization.k8s.io
      subjects:
      - kind: ServiceAccount
        name: fluentd
        namespace: kube-logging
      ---
      apiVersion: apps/v1
      kind: DaemonSet
      metadata:
        name: fluentd
        namespace: kube-logging
        labels:
          app: fluentd
      spec:
        selector:
          matchLabels:
            app: fluentd
        template:
          metadata:
            labels:
              app: fluentd
          spec:
            serviceAccount: fluentd
            serviceAccountName: fluentd
            tolerations:
            - key: node-role.kubernetes.io/master
              effect: NoSchedule
            containers:
            - name: fluentd
              image: fluent/fluentd-kubernetes-daemonset:v1.4.2-debian-elasticsearch-1.1
              env:
                - name:  FLUENT_ELASTICSEARCH_HOST
                  value: "elasticsearch.kube-logging.svc.cluster.local"
                - name:  FLUENT_ELASTICSEARCH_PORT
                  value: "9200"
                - name: FLUENT_ELASTICSEARCH_SCHEME
                  value: "http"
                - name: FLUENTD_SYSTEMD_CONF
                  value: disable
              resources:
                limits:
                  memory: 512Mi
                requests:
                  cpu: 100m
                  memory: 200Mi
              volumeMounts:
              - name: varlog
                mountPath: /var/log
              - name: varlibdockercontainers
                mountPath: /var/lib/docker/containers
                readOnly: true
            terminationGracePeriodSeconds: 30
            volumes:
            - name: varlog
              hostPath:
                path: /var/log
            - name: varlibdockercontainers
              hostPath:
                path: /var/lib/docker/containers
      

      После завершения настройки набора демонов Fluentd сохраните и закройте файл.

      Теперь выгрузите набор демонов с помощью команды kubectl:

      • kubectl create -f fluentd.yaml

      Вы должны увидеть следующий результат:

      Output

      serviceaccount/fluentd created clusterrole.rbac.authorization.k8s.io/fluentd created clusterrolebinding.rbac.authorization.k8s.io/fluentd created daemonset.extensions/fluentd created

      Убедитесь, что набор демонов успешно развернут, с помощью команды kubectl:

      • kubectl get ds --namespace=kube-logging

      Вы должны увидеть следующее состояние:

      Output

      NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE fluentd 3 3 3 3 3 <none> 58s

      Такой результат показывает, что работает 3 пода fluentd, что соответствует количеству узлов в нашем кластере Kubernetes.

      Теперь мы можем проверить Kibana и убедиться, что данные журнала собираются надлежащим образом и отправляются в Elasticsearch.

      При активном перенаправлении kubectl port-forward перейдите на адрес http://localhost:5601.

      Нажмите Discover в левом меню навигации:

      Kibana Discover

      Вы увидите следующее окно конфигурации:

      Конфигурация шаблона индексов Kibana

      Эта конфигурация позволяет определить индексы Elasticsearch, которые вы хотите просматривать в Kibana. Дополнительную информацию можно найти в документе «Определение шаблонов индексов» в официальной документации по Kibana. Сейчас мы будем использовать шаблон с подстановочным символом logstash-* для сбора всех данных журнала в нашем кластере Elasticsearch. Введите logstash-* в текстовое поле и нажмите «Следующий шаг».

      Откроется следующая страница:

      Настройки шаблона индексов Kibana

      Эти настройки позволяют указать, какое поле будет использовать Kibana для фильтрации данных по времени. Выберите в выпадающем списке поле @timestamp и нажмите «Создать шаблон индекса».

      Теперь нажмите Discover в левом меню навигации.

      Вы увидите гистограмму и несколько последних записей в журнале:

      Входящие журналы Kibana

      Вы успешно настроили и развернули комплекс EFK в своем кластере Kubernetes. Чтобы научиться использовать Kibana для анализа данных журнала, используйте «Руководство пользователя Kibana».

      В следующем необязательном разделе мы развернем простой под счетчика, который распечатывает числа в stdout, и найдем его журналы в Kibana.

      Шаг 5 (необязательный) — Тестирование регистрации данных контейнеров

      Для демонстрации простого примера использования Kibana для просмотра последних журналов пода мы развернем простой под счетчика, распечатывающий последовательности чисел в stdout.

      Для начала создадим под. Откройте файл с именем counter.yaml в своем любимом редакторе:

      Вставьте в него следующую спецификацию пода:

      counter.yaml

      apiVersion: v1
      kind: Pod
      metadata:
        name: counter
      spec:
        containers:
        - name: count
          image: busybox
          args: [/bin/sh, -c,
                  'i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done']
      

      Сохраните и закройте файл.

      Это простой под с именем counter, который запускает цикл while и печатает последовательности чисел.

      Разверните под counter с помощью kubectl:

      • kubectl create -f counter.yaml

      Когда под будет создан и запущен, вернитесь в информационную панель Kibana.

      В панели поиска на странице Discover введите kubernetes.pod_name:counter. Этот запрос отфильтрует данные журнала для пода с именем counter.

      Вы увидите список записей в журнале для пода counter:

      Журналы счетчика в Kibana

      Вы можете нажать на любую запись в журнале, чтобы посмотреть дополнительные метаданные, в том числе имя контейнера, узел Kubernetes, пространство имен и т. д.

      Заключение

      В этом обучающем модуле мы продемонстрировали процессы установки и настройки Elasticsearch, Fluentd и Kibana в кластере Kubernetes. Мы использовали минимальную архитектуру журнала, состоящую из простого пода агента ведения журнала на каждом рабочем узле Kubernetes.

      Прежде чем развернуть комплекс ведения журнала в рабочем кластере Kubernetes, лучше всего настроить требования к ресурсам и ограничения в соответствии с указаниями этого обучающего модуля. Также вы можете настроить X-Pack для поддержки встроенных функций мониторинга и безопасности.

      Использованная нами архитектура ведения журналов включает 3 пода Elasticsearch, один под Kibana (без балансировки нагрузки), а также набор подов Fluentd, развернутый в форме набора демонов. При желании вы можете масштабировать эти настройки в зависимости от конкретной реализации решения. Дополнительную информацию о масштабировании комплекса Elasticsearch и Kibana можно найти в документе «Масштабирование Elasticsearch».

      Kubernetes также позволяет использовать более сложны архитектуры агентов регистрации данных, которые могут лучше подойти для определенных решений. Дополнительную информацию можно найти в документе «Архитектура регистрации данных» в документации по Kubernetes.



      Source link

      Как настроить сервер IKEv2 VPN с StrongSwan в Ubuntu 18.04


      Введение

      Виртуальная частная сеть (VPN) позволяет выполнять защищенное шифрование трафика, передаваемого через незащищенные сети, например, в кафе, на конференции или в аэропорту.

      Протокол IKEv2 или Internet Key Exchange v2 позволяет создавать прямые туннели IPSec между сервером и клиентом. IPSec обеспечивает шифрование сетевого трафика в виртуальных частных сетях IKEv2. IKEv2 изначально поддерживается на ряде платформ OS X 10.11+, iOS 9.1+, Windows 10) без дополнительных приложений и легко решает проблемы с подключением клиентов.

      В этом обучающем модуле мы выполним настройку сервера IKEv2 VPN с помощью StrongSwan на сервере Ubuntu 18.04 и подключимся к нему с клиентов Windows, macOS, Ubuntu, iOS и Android.

      Предварительные требования

      Для данного обучающего руководства вам потребуется следующее:

      Шаг 1 — Установка StrongSwan

      Вначале мы установим StrongSwan, демона IPSec с открытым исходным кодом, а затем настроим его как наш сервер VPN. Также мы установим компонент инфраструктуры открытых ключей, чтобы создать центр сертификации, который будет предоставлять учетные данные для нашей инфраструктуры.

      Обновите кэш локальных пакетов и установите программное обеспечение с помощью следующей команды:

      • sudo apt update
      • sudo apt install strongswan strongswan-pki

      После завершения установки перейдем к созданию сертификатов.

      Шаг 2 — Создание центра сертификации

      Для идентификации на клиентских системах серверу IKEv2 требуется сертификат. Пакет strongswan-pki включает утилиту, которая может сгенерировать центр сертификации и сертификаты сервера. Для начала создадим несколько каталогов для хранения всех активо, с которыми мы будем работать. Структура каталогов соответствует некоторым каталогам в /etc/ipsec.d, куда мы постепенно переместим все создаваемые элементы. Мы заблокируем разрешения, чтобы другие пользователи не могли видеть наши частные файлы:

      • mkdir -p ~/pki/{cacerts,certs,private}
      • chmod 700 ~/pki

      Располагая структурой каталогов для хранения всех элементов, мы можем сгенерировать ключ root. Это будет 4096-битный ключ RSA, который будет использоваться для подписи корневого центра сертификации.

      Запустите следующие команды, чтобы сгенерировать ключ:

      • ipsec pki --gen --type rsa --size 4096 --outform pem > ~/pki/private/ca-key.pem

      Получив ключ, мы можем перейти к созданию корневого центра сертификации, используя ключ для подписания сертификата root:

      • ipsec pki --self --ca --lifetime 3650 --in ~/pki/private/ca-key.pem
      • --type rsa --dn "CN=VPN root CA" --outform pem > ~/pki/cacerts/ca-cert.pem

      Вы можете изменить значение distinguished name (DN) на любое другое имя по своему желанию. Используемое здесь имя common приведено просто для примера, имя не должно соответствовать какому-либо элементу вашей инфраструктуры.

      Настроив и запустив корневой центр сертификации, мы можем создать сертификат, который будет использоваться сервером VPN.

      Шаг 3 — Генерирование сертификата для сервера VPN

      Теперь мы создадим сертификат и ключ для сервера VPN. Этот сертификат позволит клиентам проверять подлинность сервера, используя только что сгенерированный нами сертификат CA.

      Вначале создайте закрытый ключ сервера VPN с помощью следующей команды:

      • ipsec pki --gen --type rsa --size 4096 --outform pem > ~/pki/private/server-key.pem

      Затем создайте и подпишите сертификат сервера VPN, используя ключ центра сертификации, созданный на предыдущем шаге. Запустите следующую команду, но измените поля Common Name (CN) и Subject Alternate Name (SAN) на имя DNS или IP-адрес вашего сервера VPN:

      • ipsec pki --pub --in ~/pki/private/server-key.pem --type rsa
      • | ipsec pki --issue --lifetime 1825
      • --cacert ~/pki/cacerts/ca-cert.pem
      • --cakey ~/pki/private/ca-key.pem
      • --dn "CN=server_domain_or_IP" --san "server_domain_or_IP"
      • --flag serverAuth --flag ikeIntermediate --outform pem
      • > ~/pki/certs/server-cert.pem

      Теперь мы сгенерировали все файлы TLS/SSL, необходимые StrongSwan, и можем переместить их в каталог /etc/ipsec.d следующим образом:

      • sudo cp -r ~/pki/* /etc/ipsec.d/

      На этом шаге мы создали пару сертификатов, которые можно будет использовать для защиты связи между клиентом и сервером. Также мы подписали сертификаты ключом CA, и теперь клиент сможет проверять подлинность сервера VPN, используя сертификат CA. Подготовив все сертификаты, мы можем перейти к настройке программного обеспечения.

      Шаг 4 — Настройка StrongSwan

      StrongSwan имеет файл конфигурации по умолчанию с несколькими образцами, но большинство настроек нужно будет выполнить самостоятельно. Прежде чем начинать, создадим резервную копию файла для справки:

      • sudo mv /etc/ipsec.conf{,.original}

      Создайте и откройте новый пустой файл конфигурации, введя следующую команду:

      • sudo nano /etc/ipsec.conf

      Вначале мы укажем StrongSwan регистрировать состояния демонов для целей отладки и разрешить дублирующиеся соединения. Добавьте в файл следующие строки:

      /etc/ipsec.conf

      config setup
          charondebug="ike 1, knl 1, cfg 0"
          uniqueids=no
      

      Затем мы создадим раздел конфигурации для сервера VPN. Также мы укажем StrongSwan создать туннели IKEv2 VPN и автоматически загружать этот раздел конфигурации при запуске. Добавьте в файл следующие строки:

      /etc/ipsec.conf

      . . .
      conn ikev2-vpn
          auto=add
          compress=no
          type=tunnel
          keyexchange=ikev2
          fragmentation=yes
          forceencaps=yes
      

      Также мы настроем обнаружение отсутствующих узлов, чтобы закрывать неиспользуемые соединения при непредвиденном отключении клиента. Добавьте следующие строки:

      /etc/ipsec.conf

      . . .
      conn ikev2-vpn
          . . .
          dpdaction=clear
          dpddelay=300s
          rekey=no
      

      Теперь мы настроим параметры IPSec нашего сервера (слева). Добавьте в файл следующее:

      /etc/ipsec.conf

      . . .
      conn ikev2-vpn
          . . .
          left=%any
          leftid=@server_domain_or_IP
          leftcert=server-cert.pem
          leftsendcert=always
          leftsubnet=0.0.0.0/0
      

      Примечание. При настройке идентификатора сервера (leftid) символ @ нужно указывать только в случае, если ваш сервер VPN будет идентифицироваться по доменному имени:

          leftid=@vpn.example.com
      

      Если сервер будет идентифицироваться по IP-адресу, просто укажите IP-адрес:

          leftid=203.0.113.7
      

      Теперь мы можем настроить параметры IPSec на стороне клиента (справа) как диапазоны частных IP-адресов и серверы DNS, которые нужно будет использовать:

      /etc/ipsec.conf

      . . .
      conn ikev2-vpn
          . . .
          right=%any
          rightid=%any
          rightauth=eap-mschapv2
          rightsourceip=10.10.10.0/24
          rightdns=8.8.8.8,8.8.4.4
          rightsendcert=never
      

      Наконец, мы укажем StrongSwan запрашивать у клиента учетные данные пользователя при подключении:

      /etc/ipsec.conf

      . . .
      conn ikev2-vpn
          . . .
          eap_identity=%identity
      

      Файл конфигурации должен выглядеть следующим образом:

      /etc/ipsec.conf

      config setup
          charondebug="ike 1, knl 1, cfg 0"
          uniqueids=no
      
      conn ikev2-vpn
          auto=add
          compress=no
          type=tunnel
          keyexchange=ikev2
          fragmentation=yes
          forceencaps=yes
          dpdaction=clear
          dpddelay=300s
          rekey=no
          left=%any
          leftid=@server_domain_or_IP
          leftcert=server-cert.pem
          leftsendcert=always
          leftsubnet=0.0.0.0/0
          right=%any
          rightid=%any
          rightauth=eap-mschapv2
          rightsourceip=10.10.10.0/24
          rightdns=8.8.8.8,8.8.4.4
          rightsendcert=never
          eap_identity=%identity
      

      Когда вы убедитесь, что конфигурация соответствует показанной, сохраните и закройте файл.

      Теперь мы настроили параметры VPN и можем перейти к созданию учетной записи, чтобы наши пользователи могли подключаться к серверу.

      Шаг 5 — Настройка аутентификации VPN

      Теперь наш сервер VPN настроен на принятие подключений клиентов, но мы еще не настроили учетные данные. Нам нужно задать пару настроек в специальном файле конфигурации с именем ipsec.secrets:

      • Нам нужно указать StrongSwan, где можно найти закрытый ключ для нашего сертификата сервера, чтобы сервер мог пройти аутентификацию на стороне клиента.
      • Также нам потребуется список пользователей, которым будет разрешено подключаться к VPN.

      Откроем для редактирования файл secrets

      • sudo nano /etc/ipsec.secrets

      Вначале мы укажем StrongSwan, где можно найти закрытый ключ:

      /etc/ipsec.secrets

      : RSA "server-key.pem"
      

      Затем мы зададим учетные данные пользователя. Вы можете создать любую комбинацию имени пользователя и пароля:

      /etc/ipsec.secrets

      your_username : EAP "your_password"
      

      Сохраните и закройте файл. Мы завершили настройку параметров VPN и теперь можем перезапустить службу VPN, чтобы применить новую конфигурацию:

      • sudo systemctl restart strongswan

      Мы полностью настроили параметры сервера и учетные данные пользователя на сервере VPN и теперь можем перейти к самой важной части: настройке брандмауэра.

      Шаг 6 — Настройка брандмауэра и переадресации IP ядра

      После настройки конфигурации StrongSwan нам нужно настроить брандмауэр, чтобы он разрешал трафик VPN и перенаправлял его.

      Если вы выполнили указания предварительных обучающих модулей, у вас должен быть включен базовый брандмауэр UFW. Если вы еще не настроили UFW, вы можете базовую конфигурацию и включить ее с помощью следующей команды:

      • sudo ufw allow OpenSSH
      • sudo ufw enable

      Теперь добавьте правило, которое будет разрешать трафик UDP на стандартных портах IPSec, 500 и 4500:

      • sudo ufw allow 500,4500/udp

      Затем мы откроем один из файлов конфигурации UFW, чтобы добавить несколько политик нижнего уровня для маршрутизации и перенаправления пакетов IPSec. Перед этим нам нужно будет определить, какой сетевой интерфейс нашего сервера будет использоваться для доступа к интернету. Для этого мы можем отправить запрос интерфейса, связанного с маршрутом по умолчанию:

      Ваш публичный интерфейс должен содержать слово «dev». Например, в этом результате показан интерфейс с именем eth0, который выделен ниже:

      Output

      default via 203.0.113.7 dev eth0 proto static

      Определив интерфейс публичной сети, откройте файл правил /etc/ufw/before.rules в своем текстовом редакторе:

      • sudo nano /etc/ufw/before.rules

      Добавьте в верхнюю часть файла (перед строкой *filter) следующий блок конфигурации:

      /etc/ufw/before.rules

      *nat
      -A POSTROUTING -s 10.10.10.0/24 -o eth0 -m policy --pol ipsec --dir out -j ACCEPT
      -A POSTROUTING -s 10.10.10.0/24 -o eth0 -j MASQUERADE
      COMMIT
      
      *mangle
      -A FORWARD --match policy --pol ipsec --dir in -s 10.10.10.0/24 -o eth0 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360
      COMMIT
      
      *filter
      :ufw-before-input - [0:0]
      :ufw-before-output - [0:0]
      :ufw-before-forward - [0:0]
      :ufw-not-local - [0:0]
      . . .
      

      Измените каждый экземпляр eth0 в конфигурации выше для соответствия имени интерфейса, которое вы определили с помощью ip route. Строки *nat создают правила, благодаря которым брандмауэр может обеспечивать маршрутизацию и управление трафиком между клиентами VPN и интернетом. Строка *mangle позволяет настроить максимальный размер сегмента пакета, чтобы предотвратить возможные проблемы с некоторыми клиентами VPN.

      После строки *filter и строк определения цепочки нужно добавить еще один блок конфигурации:

      /etc/ufw/before.rules

      . . .
      *filter
      :ufw-before-input - [0:0]
      :ufw-before-output - [0:0]
      :ufw-before-forward - [0:0]
      :ufw-not-local - [0:0]
      
      -A ufw-before-forward --match policy --pol ipsec --dir in --proto esp -s 10.10.10.0/24 -j ACCEPT
      -A ufw-before-forward --match policy --pol ipsec --dir out --proto esp -d 10.10.10.0/24 -j ACCEPT
      

      Эти строки указывают брандмауэру перенаправлять трафик ESP (защищенная инкапсуляция полезной нагрузки), чтобы дать клиентам VPN возможность подключения. ESP обеспечивает дополнительную защиту пакетов VPN, когда они проходят через ненадежные сети.

      Завершив редактирование, сохраните и закройте файл.

      Прежде чем перезапустить брандмауэр, нам нужно изменить некоторые параметры ядра сети, чтобы разрешить маршрутизацию с одного интерфейса на другой. Откройте файл конфигурации параметров ядра UFW:

      • sudo nano /etc/ufw/sysctl.conf

      Нам нужно настроить несколько параметров:

      • Прежде всего, мы активируем перенаправление пакетов PIv4.
      • Мы отключим обнаружение путей MTU, чтобы предотвратить проблемы с фрагментацией пакетов.
      • Также мы запретим перенаправление ICMP и отправку перенаправлений ICMP, чтобы предотвратить атаки через посредников.

      Внесенные в файл изменения выделены в приведенном ниже фрагменте кода:

      /etc/ufw/sysctl.conf

      
      . . .
      
      # Enable forwarding
      # Uncomment the following line
      net/ipv4/ip_forward=1
      
      . . .
      
      # Do not accept ICMP redirects (prevent MITM attacks)
      # Ensure the following line is set
      net/ipv4/conf/all/accept_redirects=0
      
      # Do not send ICMP redirects (we are not a router)
      # Add the following lines
      net/ipv4/conf/all/send_redirects=0
      net/ipv4/ip_no_pmtu_disc=1
      

      Завершив изменения, сохраните файл. UFW применит эти изменения при следующем запуске.

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

      • sudo ufw disable
      • sudo ufw enable

      Вам будет предложено подтвердить процесс. Введите Y, чтобы активировать UFW с новыми настройками.

      Шаг 7 — Тестирование подключения в в Windows, iOS и macOS

      Мы завершили подготовку, и пришло время для тестирования. Вначале нужно скопировать созданный вами сертификат CA и установить его на клиентские устройства, которые будут подключаться к VPN. Для этого удобнее всего выполнить вход на ваш сервер и вывести содержимое файла сертификата:

      • cat /etc/ipsec.d/cacerts/ca-cert.pem

      Вывод будет выглядеть следующим образом:

      Output

      -----BEGIN CERTIFICATE----- MIIFQjCCAyqgAwIBAgIIFkQGvkH4ej0wDQYJKoZIhvcNAQEMBQAwPzELMAkGA1UE . . . EwbVLOXcNduWK2TPbk/+82GRMtjftran6hKbpKGghBVDPVFGFT6Z0OfubpkQ9RsQ BayqOb/Q -----END CERTIFICATE-----

      Скопируйте эти данные на свой компьютер, включая строки -----BEGIN CERTIFICATE----- и -----END CERTIFICATE-----, и сохраните их в файл с понятным именем, например, ca-cert.pem. Созданный файл должен иметь расширение .pem.

      Также вы можете использовать SFTP, чтобы перенести файл на свой компьютер.

      Когда файл ca-cert.pem будет загружен на ваш компьютер, вы можете настроить подключение к VPN.

      Подключение из Windows

      Вначале импортировать сертификат root, выполнив следующие шаги:

      1. Нажмите WINDOWS+R, чтобы открыть диалоговое окно Выполнить и введите mmc.exe, чтобы открыть консоль управления Windows.
      2. Из меню Файл перейдите в раздел Добавить или удалить оснастку, выберите Сертификаты из списка доступных оснасток и нажмите Добавить.
      3. Чтобы разрешить VPN работать для любых пользователей, выберите Учетная запись компьютера и нажмите Далее.
      4. Поскольку мы выполняем настройку на локальном компьютере, выберите пункт Локальный компьютер и нажмите Готово.
      5. Под узлом Корень консоли откройте запись Сертификаты (локальный компьютер), раскройте Доверенные корневые центры сертификации и выберите запись Сертификаты: Просмотр сертификатов

      6. В меню Действие выберите пункт Все задачи и нажмите Импорт, чтобы открыть мастер импорта сертификатов. Нажмите Далее, чтобы пролистать вводное окно.

      7. На экране Импортируемый файл нажмите кнопку Обзор и выберите сохраненный файл сертификата. Затем нажмите Далее.

      8. Убедитесь, что Хранилище сертификатов имеет значение Доверенные корневые центры сертификации и нажмите Далее.

      9. Нажмите Готово, чтобы импортировать сертификат.

      Затем выполните следующие шаги по настройке VPN:

      1. Откройте Панель управления и перейдите в Центр управления сетями и общим доступом.
      2. Нажмите Создание и настройка нового подключения или сети и выберите пункт Подключение к рабочем месту.
      3. Выберите пункт Использовать мое подключение к Интернету (VPN).
      4. Введите данные сервера VPN. Введите доменное имя сервера или IP-адрес в поле Адрес в Интернете, затем введите в поле Имя пункта назначения описание своего соединения VPN. Затем нажмите Готово.

      Ваше новое подключение VPN появится в списке сетей. Выберите VPN и нажмите Подключиться. Вам будет предложено ввести свои имя пользователя и пароль. Введите эти данные, нажмите OK, и подключение будет установлено.

      Подключение из macOS

      Выполните следующие шаги по импорту сертификата:

      1. Дважды щелкните файл сертификата. Откроется экран «Keychain Access» с диалоговым окном, где будет указано: «Keychain Access is trying to modify the system keychain. Enter your password to allow this».
      2. Введите свой пароль и нажмите Modify Keychain
      3. Дважды щелкните импортированный сертификат VPN. После этого откроется небольшое окно свойств, где вы сможете указать уровни доверия. Укажите для параметра IP Security (IPSec) значение Always Trust (всегда доверять), после чего вам нужно будет снова ввести пароль. Настройка будет сохранена автоматически после ввода пароля.

      Теперь сертификат импортирован и настроен как доверенный, и вы можете настроить соединение VPN:

      1. Откройте раздел System Preferences (настройки системы) и выберите пункт Network (сеть).
      2. Нажмите небольшую кнопку «плюс» в нижнем левом углу списка сетей.
      3. В открывшемся всплывающем окне установите для параметра Interface (интерфейс) значение VPN, установите для параметра VPN Type (тип VPN) значение IKEv2 и присвойте имя соединению.
      4. В поле Server (сервер) и Remote ID (удаленный идентификатор) введите доменное имя или IP-адрес сервера. Оставьте поле Local ID (локальный идентификатор) пустым.
      5. Нажмите Authentication Settings (настройки аутентификации), выберите пункт Username (имя пользователя) и введите имя пользователя и пароль, которые вы настроили для своего пользователя VPN. Затем нажмите OK.

      Наконец, нажмите кнопку Connect (подключение) для подключения к VPN. Теперь вы должны быть подключены к VPN.

      Подключение из Ubuntu

      Чтобы подключиться с компьютера под управлением Ubuntu, вы должны настроить и управлять StrongSwan как службой или использовать разовую команду при каждой попытке подключения. Далее приводятся инструкции для обоих случаев.

      Управление StrongSwan как службой

      1. Обновите кэш локальных пакетов: sudo apt update
      2. Установите StrongSwan и связанное программное обеспечение: sudo apt install strongswan libcharon-extra-plugins
      3. Скопируйте сертификат CA в каталог /etc/ipsec.d/cacerts: sudo cp /tmp/ca-cert.pem /etc/ipsec.d/cacerts
      4. Отключите StrongSwan для отключения автоматического запуска VPN: sudo systemctl disable --now strongswan
      5. Настройте имя пользователя и пароль для VPN в файле /etc/ipsec.secrets: your_username : EAP "your_password"
      6. Отредактируйте файл /etc/ipsec.conf, чтобы определить конфигурацию.

      /etc/ipsec.conf

      config setup
      
      conn ikev2-rw
          right=server_domain_or_IP
          # This should match the `leftid` value on your server's configuration
          rightid=server_domain_or_IP
          rightsubnet=0.0.0.0/0
          rightauth=pubkey
          leftsourceip=%config
          leftid=username
          leftauth=eap-mschapv2
          eap_identity=%identity
          auto=start
      

      Чтобы подключиться к VPN, введите:

      • sudo systemctl start strongswan

      Чтобы снова отключиться, введите:

      • sudo systemctl stop strongswan

      Использование простого клиента для разовых подключений

      1. Обновите кэш локальных пакетов: sudo apt update
      2. Установите charon-cmd и связанное программное обеспечение: sudo apt install charon-cmd libcharon-extra-plugins
      3. Перейдите в каталог, куда вы скопировали сертификат CA: cd <^>/path/to/ca-cert.pem
      4. Подключитесь к серверу VPN с помощью charon-cmd, используя сертификат CA сервера, IP-адрес сервера VPN и настроенное имя пользователя:sudo charon-cmd --cert ca-cert.pem --host vpn_domain_or_IP --identity your_username
      5. Укажите пароль пользователя VPN, когда он будет запрошен.

      Теперь вы должны быть подключены к VPN. Чтобы отключиться, нажмите CTRL+C и дождитесь, пока соединение не будет закрыто.

      Подключение из iOS

      Чтобы настроить соединение VPN на устройстве iOS, выполните следующие действия:

      1. Отправьте себе электронное письмо с прикрепленным корневым сертификатом.
      2. Откройте электронное письмо на устройстве iOS, нажмите на вложенный файл сертификата, затем нажмите Установить и введите код доступа. После установки нажмите Готово.
      3. Откройте Настройки, Общие, VPN и нажмите Добавить конфигурацию VPN. После этого откроется экран конфигурации подключения VPN.
      4. Нажмите Тип и выберите IKEv2.
      5. В поле Описание введите короткое имя подключения VPN. Вы можете выбрать все, что угодно.
      6. В поле Server (сервер) и Remote ID (удаленный идентификатор) введите доменное имя или IP-адрес сервера. Поле Local ID (локальный идентификатор) нельзя оставлять пустым.
      7. Введите имя пользователя и пароль в разделе Аутентификация, а затем нажмите Готово.
      8. Выберите соединение VPN, которое вы только что создали, нажмите переключатель вверху страницы, и подключение будет установлено.

      Подключение из Android

      Выполните следующие шаги по импорту сертификата:

      1. Отправьте себе электронное письмо с прикрепленным сертификатом CA. Сохраните сертификат CA в папку «Загрузки».
      2. Загрузите клиент StrongSwan VPN из магазина Play Store.
      3. Откройте приложение. Нажмите значок «подробнее» в правом верхнем углу (три точки) и выберите пункт Сертификаты CA.
      4. Снова нажмите значок «Подробнее» в правом верхнем углу. Выберите пункт Импорт сертификата.
      5. Найдите файл сертификата CA в папке «Загрузки» и выберите его для импорта в приложение.

      Теперь сертификат импортирован в приложение StrongSwan, и вы можете настроить соединение VPN следующим образом:

      1. В приложении нажмите ADD VPN PROFILE (добавить профиль VPN) сверху.
      2. Введите в поле Server (сервер) доменное имя или публичный IP-адрес вашего сервера VPN.
      3. Обязательно выберите тип VPN: IKEv2 EAP (Username/Password).
      4. Введите поля Username (имя пользователя) и Password (пароль) учетные данные, определенные на сервере.
      5. Уберите флажок Select automatically (выбирать автоматически) в разделе CA certificate (сертификат CA) и нажмите Select CA certificate (выбрать сертификат CA).
      6. Откройте вкладку IMPORTED (импортированные) вверху экрана и выберите импортированный CA (он будет иметь имя «VPN root CA», если вы до этого не изменяли значение «DN»).
      7. Если хотите, можете ввести в поле Profile name (optional) (имя профиля, необязательно) более понятное имя.

      Когда вы захотите подключится к VPN, нажмите на профиль, созданный в приложении StrongSwan.

      Диагностика и устранение неисправностей подключения

      Если вы не сможете импортировать сертификат, убедитесь, что файл имеет расширение .pem, а не .pem.txt.

      Если вы не можете подключиться к VPN, проверьте используемые имя сервера и IP-адрес. Доменное имя или IP-адрес сервера должны соответствовать настроенным как общее имя (CN) при создании сертификата. Если они не совпадают, соединение VPN не будет работать. Если вы настроили сертификат с CN vpn.example.com, вы должны использовать vpn.example.com при вводе данных сервера VPN. Еще раз проверьте команду, которую вы использовали для генерирования сертификата и значения, которые использовали при создании соединения VPN.

      Наконец, проверьте конфигурацию VPN и убедитесь, что значение leftid настроено с символом @, если вы используете доменное имя:

          leftid=@vpn.example.com
      

      Если вы используете IP-адрес, убедитесь, что символ @ опущен.

      Заключение

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

      Чтобы добавить или удалить пользователей, еще раз изучите шаг 5. Каждая строка предназначена для одного пользователя, и поэтому для добавления или удаления пользователей достаточно просто отредактировать файл.

      Также вы можете захотеть использовать анализатор файлов журнала, потому что StrongSwan отправляет дампы своих журналов в syslog. В обучающем модуле Установка и использование инструмента Logwatch Log Analyzer and Reporter с VPS можно найти дополнительную информацию по этой процедуре.

      Вы также можете заинтересовать это руководство EFF по конфиденциальности в режиме онлайн.



      Source link

      Как настроить Nginx Ingress с Cert-Manager в DigitalOcean Kubernetes


      Введение

      Сущности Ingress в Kubernetes обеспечивают гибкую маршрутизацию внешнего трафика кластера Kubernetes среди служб внутри кластера. Это достигается с помощью ресурсов Ingress, которые определяют правила маршрутизации трафика HTTP и HTTPS для служб Kubernetes, и контроллеров Ingress, которые реализуют правила порседством балансировки нагрузки трафика и его перенаправления на соответствующие службы серверной части. В число популярных контроллеров Ingress входят Nginx, Contour, HAProxy и Traefik. Сущности Ingress — это более эффективная и гибкая альтернатива настройке множеству разных объектов служб LoadBalancer, каждый из которых использует собственный выделенный балансировщик нагрузки.

      В этом руководстве мы настроим контроллер Nginx Ingress, обслуживаемый Kubernetes, и создадим несколько ресурсов Ingress для маршуртизации трафика на фиктивные серверные службы. После настройки Ingress мы установим в наш кластер cert-manager для управления и распределения сертификатами TLS для шифрования трафика HTTP в Ingress.

      Предварительные требования

      Прежде чем начать прохождение этого обучающего модуля, вам потребуется следующее:

      • Кластер Kubernetes 1.10+ с включенным контролем доступа на основе ролей (RBAC)
      • Инструмент командной строки kubectl, установленный на локальном компьютере и настроенный для подключения к вашему кластеру. Дополнительную информацию об установке kubectl можно найти в официальной документации.
      • Доменное имя и записи DNS A, которые можно направить на балансировщик нагрузки DigitalOcean, используемый Ingress. Если вы используете DigitalOcean для управления записями DNS вашего домена, руководство Управление записями DNS поможет вам научиться создавать записи класса A.
      • Диспетчер пакетов Helm на локальном компьютере и Tiller на кластере, установленные в соответствии с указаниями обучающего модуля «Установка программного обеспечения на кластерах Kubernetes с диспетчером пакетов Helm». Убедитесь, что вы используете версию Helm 2.12.1 или более позднюю, иначе могут возникнуть проблемы с установкой таблицы cert-manager в Helm. Чтобы проверить установленную версию Helm, запустите команду helm version на локальном компьютере.
      • Инструмент командной строки wget, установленный на локальном компьютере. Вы можете установить wget с помощью диспетчера пакетов, встроенного в операционную систему.

      Проверив наличие этих компонентов, вы можете начинать прохождение этого обучающего модуля.

      Шаг 1 — Настройка фиктивных серверных служб

      Перед развертыванием контроллера Ingress мы создадим и развернем две фиктивных службы echo, на которые будем перенаправлять внешний трафик с помощью Ingress. Службы echo будут запускать контейнер hashicorp/http-echo, возвращающий страницу с текстовой строкой, переданной при запуске веб-сервера. Дополнительную информацию по http-echo можно получить в GitHub Repo, а дополнительную информацию о службах Kubernetes можно найти в разделе Services в официальной документации Kubernetes.

      Создайте на локальном компьютере файл echo1.yaml и откройте его в nano или другом текстовом редакторе:

      Вставьте в него следующий манифест служб и развертывания:

      echo1.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: echo1
      spec:
        ports:
        - port: 80
          targetPort: 5678
        selector:
          app: echo1
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: echo1
      spec:
        selector:
          matchLabels:
            app: echo1
        replicas: 2
        template:
          metadata:
            labels:
              app: echo1
          spec:
            containers:
            - name: echo1
              image: hashicorp/http-echo
              args:
              - "-text=echo1"
              ports:
              - containerPort: 5678
      

      В этом файле мы определяем службу с именем echo1, которая перенаправляет трафик в поды с помощью селектора ярлыка app: echo1. Она принимает трафик TCP на порту 80 и перенаправляет его на порт 5678,используемый http-echo по умолчанию.

      Затем мы определяем развертывание с именем echo1, которое управляет подами с селектором app: echo1 Label Selector. Мы указываем, что в развертывании должно быть 2 копии пода, и что поды должны запускать контейнер echo1 с образом hashicorp/http-echo. Мы передаем параметр text и устанавливаем для него значение echo1, так что веб-сервер http-echo возвращает echo1. Наконец, мы открываем порт 5678 в контейнере подов.

      Проверив манифест фиктивной службы и развертывания, сохраните и закройте файл.

      Создайте ресурсы Kubernetes с помощью kubectl create с флагом -f, указав только что сохраненный файл в качестве параметра:

      • kubectl create -f echo1.yaml

      Вы должны увидеть следующий результат:

      Output

      service/echo1 created deployment.apps/echo1 created

      Убедитесь, что служба запустилась правильно, и проверьте наличие ClusterIP, внутреннего IP-адреса, по которому доступна служба:

      Вы должны увидеть следующий результат:

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE echo1 ClusterIP 10.245.222.129 <none> 80/TCP 60s

      Это означает, что служба echo1 доступна по внутреннему IP-адресу 10.245.222.129 на порту 80. Она будет перенаправлять трафик в порт контейнера 5678 на выбранных ей подах.

      Теперь служба echo1 запущена, и мы можем повторить процедуру для службы echo2.

      Создайте и откройте файл с именем echo2.yaml:

      echo2.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: echo2
      spec:
        ports:
        - port: 80
          targetPort: 5678
        selector:
          app: echo2
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: echo2
      spec:
        selector:
          matchLabels:
            app: echo2
        replicas: 1
        template:
          metadata:
            labels:
              app: echo2
          spec:
            containers:
            - name: echo2
              image: hashicorp/http-echo
              args:
              - "-text=echo2"
              ports:
              - containerPort: 5678
      

      Здесь мы используем тот же манифест служб и развертывания, что и выше, но будем использовать имя и ярлык echo2. Кроме того, для разнообразия мы создадим только 1 копию пода. Для параметра text мы установим значение echo2, чтобы веб-сервер возвращал текст echo2.

      Сохраните и закройте файл и создайте ресурсы Kubernetes с помощью kubectl:

      • kubectl create -f echo2.yaml

      Вы должны увидеть следующий результат:

      Output

      service/echo2 created deployment.apps/echo2 created

      Еще раз проверьте, запущена ли служба:

      Вы должны увидеть службы echo1 и echo2 с назначенными им значениями ClusterIP:

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE echo1 ClusterIP 10.245.222.129 <none> 80/TCP 6m6s echo2 ClusterIP 10.245.128.224 <none> 80/TCP 6m3s kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 4d21h

      Теперь наши фиктивные веб-службы эхо запущены, и мы можем перейти к развертыванию контроллера Nginx Ingress.

      Шаг 2 — Настройка контроллера Kubernetes Nginx Ingress

      На этом шаге мы развернем версию v0.24.1 контроллера Nginx Ingress, обслуживаемого Kubernetes. Существует несколько контроллеров Nginx Ingress. Сообщество Kubernetes обслуживает контроллер, используемый в этом обучающем модуле, а Nginx Inc. обслуживает kubernetes-ingress. Указания этого обучающего модуля основаны на приведенных в официальном руководстве по установке контроллера Kubernetes Nginx Ingress.

      Контроллер Nginx Ingress состоит из пода, который запускает веб-сервер Nginx и наблюдает за плоскостью управления Kubernetes для обнаружения новых и обновленных объектов ресурсов Ingress. Ресурс Ingress фактически представляет собой список правил маршрутизации трафика для серверных служб. Например, правило Ingress может указывать, что входящий трафик HTTP на пути /web1 следует перенаправлять на веб-сервер web1. С помощью ресурсов Ingress также можно выполнять маршрутизацию на базе хоста: например, запросы маршрутизации для web1.your_domain.com на серверную службу Kubernetes web1.

      В данном случае мы развертываем контроллер Ingress в кластере DigitalOcean Kubernetes, и контроллер создаст службу LoadBalancer, запускающую балансировщик нагрузки DigitalOcean, на который будет направляться весь внешний трафик. Балансировщик нагрузки будет направлять внешний трафик на под контроллера Ingress под управлением Nginx, откуда трафик будет перенаправляться в соответствующие серверные службы.

      Для начала мы создадим необходимые ресурсы Kubernetes для контроллера Nginx Ingress. В их число входят карты ConfigMaps, содержащие конфигурацию контроллера, роли системы RBAC, предоставляющие контроллеру доступ Kubernetes API, и фактическое развертывание контроллера Ingress, использующее версию 0.24.1 образа контроллера Nginx Ingress. Чтоб просмотреть полный список требуемых ресурсов, ознакомьтесь с манифестом репозитория контроллера Kubernetes Nginx Ingress на GitHub.

      Для создания этих обязательных ресурсов используйте команду kubectl apply с флагом -f для указания файла манифеста, размещенного на GitHub:

      • kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.24.1/deploy/mandatory.yaml

      Мы используем apply вместо create ,чтобы в будущем мы могли применять изменения к объектам контроллера Ingress, а не перезаписывать их полностью. Дополнительную информацию о команде apply можно найти в разделе «Управление ресурсами» в официальной документации по Kubernetes.

      Вы должны увидеть следующий результат:

      Output

      namespace/ingress-nginx created configmap/nginx-configuration created configmap/tcp-services created configmap/udp-services created serviceaccount/nginx-ingress-serviceaccount created clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created role.rbac.authorization.k8s.io/nginx-ingress-role created rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created deployment.extensions/nginx-ingress-controller created

      На этом экране результатов приведен удобный обзор всех объектов контроллера Ingress, созданных из манифеста mandatory.yaml.

      Далее мы создадим службу LoadBalancer контроллера Ingress, которая создаст балансировщик нагрузки DigitalOcean для балансировки и маршрутизации трафика HTTP и HTTPS на под контроллера Ingress, который мы развернули предыдущей командой.

      Для создания службы LoadBalancer мы снова используем команду kubectl apply с файлом манифеста, содержащим определение службы:

      • kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.24.1/deploy/provider/cloud-generic.yaml

      Вы должны увидеть следующий результат:

      Output

      service/ingress-nginx created

      Убедитесь, что балансировщик нагрузки DigitalOcean создан успешно, получив детали службы с помощью команды kubectl:

      • kubectl get svc --namespace=ingress-nginx

      Вы должны использовать внешний IP-адрес, соответствующий IP-адресу балансировщика нагрузки DigitalOcean:

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ingress-nginx LoadBalancer 10.245.247.67 203.0.113.0 80:32486/TCP,443:32096/TCP 20h

      Запишите внешний IP-адрес балансировщика нагрузки, поскольку он потребуется вам позднее.

      Примечание. По умолчанию служба Nginx Ingress LoadBalancer использует для параметра service.spec.externalTrafficPolicy значение Local, в результате чего весь трафик балансировщика нагрузки перенаправляется на узлы, где запущены поды Nginx Ingress. Другие узлы целенаправленно не будут проходить проверки балансировщика нагрузки, чтобы трафик Ingress не направлялся на эти узлы. Политики внешнего трафика не описываются в этом обучающем модуле, но дополнительную информацию можно найти в руководствах «Подробное описание политик внешнего трафика Kubernetes» и «Исходный IP для служб с типом Type=LoadBalancer» в официальной документации по Kubernetes.

      Этот балансировщик нагрузки принимает трафик на портах HTTP и HTTPS 80 и 443, и перенаправляет его на под контроллера Ingress. Контроллер Ingress перенаправляет трафик на соответствующую серверную службу.

      Теперь мы сделаем так, чтобы наши записи DNS указывали на этот внешний балансировщик нагрузки, и создадим некоторые ресурсы Ingress для внедрения правил маршрутизации трафика.

      Шаг 3 — Создание ресурсов Ingress

      Для начала мы создадим минимальный ресурс Ingress для перенаправления трафика указанного субдомена на соответствующую серверную службу.

      В этом обучающем модуле мы используем тестовый домен example.com. Вы должны заменить его вашим доменным именем.

      Вначале мы создадим простое правило для перенаправления адресованного echo1.example.com трафика на серверную службу echo1 и адресованного echo2.example.com трафика на серверную службу echo2.

      Для начала откройте файл echo_ingress.yaml в предпочитаемом редакторе:

      Вставьте следующее определение Ingress:

      echo_ingress.yaml

      apiVersion: extensions/v1beta1
      kind: Ingress
      metadata:
        name: echo-ingress
      spec:
        rules:
        - host: echo1.example.com
          http:
            paths:
            - backend:
                serviceName: echo1
                servicePort: 80
        - host: echo2.example.com
          http:
            paths:
            - backend:
                serviceName: echo2
                servicePort: 80
      

      Когда вы закончите редактирование правил Ingress, сохраните и закройте файл.

      Мы указали, что хотим создать ресурс Ingress с именем echo-ingress и перенаправлять трафик на базе заголовка Host. В запросе HTTP заголовок Host указывает доменное имя целевого сервера. Дополнительную информацию о заголовках Host можно найти на странице определений Mozilla Developer Network. Запросы хоста echo1.example.com будут перенаправляться на серверную службу echo1, настроенную на шаге 1, а запросы хоста echo2.example.com будут перенаправляться на серверную службу echo2.

      Теперь вы можете создать Ingress с помощью kubectl:

      • kubectl apply -f echo_ingress.yaml

      Вы увидите следующий экран результатов, подвтерждающий создание Ingress:

      Output

      ingress.extensions/echo-ingress created

      Чтобы протестировать Ingress, перейдите в службу управления DNS и создайте записи A для echo1.example.com и echo2.example.com, указывающие на внешний IP-адрес балансировщика нагрузки DigitalOcean. Внешний IP-адрес балансировщика нагрузки соответствует внешнему IP-адресу службы ingress-nginx, полученному на предыдущем шаге. Если вы используете DigitalOcean для управления записями DNS вашего домена, руководство Управление записями DNS поможет вам научиться создавать записи класса A.

      После создания необходимых записей echo1.example.com и echo2.example.com вы можете протестировать контроллер Ingress и созданные ресурсы с помощью утилиты командной строки curl.

      Выполните команду curl для службы echo1 на локальном компьютере:

      Вы должны получить следующий ответ от службы echo1:

      Output

      echo1

      Это подтверждает, что ваш запрос echo1.example.com правильно перенаправляется через Nginx ingress в серверную службу echo1.

      Теперь повторите этот тест для службы echo2:

      Вы должны получить следующий ответ от службы echo2:

      Output

      echo2

      Это подтверждает, что ваш запрос echo2.example.com правильно перенаправляется через Nginx ingress в серверную службу echo2.

      Вы успешно выполнили базовую настройку Nginx Ingress для маршрутизации на базе виртуального хоста. На следующем шаге мы установим cert-manager с помощью Helm для предоставления сертификатов TLS для Ingress и использования более защищенного протокола HTTPS.

      Шаг 4 — Установка и настройка Cert-Manager

      На этмо шаге мы используем Helm для установки cert-manager в нашем кластере. cert-manager — это служба Kubernetes, предоставляющая сертификаты TLS от Let’s Encrypt и других центров сертификации и управляющая их жизненными циклами. Сертификаты можно запрашивать и настраивать посредством аннотации ресурсов Ingress с помощью аннотации certmanager.k8s.io/issuer с добавлением раздела tls в спецификацию Ingress и настройкой одного или нескольких элементов Issuer для определения предпочитаемого центра сертификации. Дополнительную информацию об объектах Issuer можно найти в официальной документации cert-manager по элементам Issuer.

      Примечание. Перед установкой cert-manager убедитесь, что вы используете версию Helm 2.12.1 или более позднюю версию. Чтобы проверить установленную версию Helm, запустите команду helm version на локальном компьютере.

      Прежде чем использовать Helm для установки cert-manager в нашем кластере, нам нужно создать собственные определения ресурсов (CRD) для cert-manager. Используйте для их создания команду apply, чтобы применить их непосредственно из репозитория cert-manager на GitHub:

      • kubectl apply
      • -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.8/deploy/manifests/00-crds.yaml

      Вы должны увидеть следующий результат:

      Output

      customresourcedefinition.apiextensions.k8s.io/certificates.certmanager.k8s.io created customresourcedefinition.apiextensions.k8s.io/issuers.certmanager.k8s.io created customresourcedefinition.apiextensions.k8s.io/clusterissuers.certmanager.k8s.io created customresourcedefinition.apiextensions.k8s.io/orders.certmanager.k8s.io created customresourcedefinition.apiextensions.k8s.io/challenges.certmanager.k8s.io created

      Теперь мы добавим ярлык пространства имен kube-system, куда мы устанавливаем cert-manager, чтобы обеспечить расширенную проверку ресурсов с помощью webhook:

      • kubectl label namespace kube-system certmanager.k8s.io/disable-validation="true"

      Теперь мы добавим репозиторий Jetstack Helm в Helm. Этот репозиторий содержит таблицу Helm для cert-manager.

      • helm repo add jetstack https://charts.jetstack.io

      Наконец, мы установим таблицу в пространство имен kube-system:

      • helm install --name cert-manager --namespace kube-system jetstack/cert-manager --version v0.8.0

      Вы должны увидеть следующий результат:

      Output

      . . . NOTES: cert-manager has been deployed successfully! In order to begin issuing certificates, you will need to set up a ClusterIssuer or Issuer resource (for example, by creating a 'letsencrypt-staging' issuer). More information on the different types of issuers and how to configure them can be found in our documentation: https://cert-manager.readthedocs.io/en/latest/reference/issuers.html For information on how to configure cert-manager to automatically provision Certificates for Ingress resources, take a look at the `ingress-shim` documentation: https://cert-manager.readthedocs.io/en/latest/reference/ingress-shim.html

      Это означает, что установка cert-manager выполнена успешно.

      Прежде чем мы начнем выдачу сертификатов для наших хостов Ingress, нам нужно создать элемент Issuer, определяющий центр сертификации, откуда можно получить подписанные сертификаты x509. В этом обучающем модуле мы используем центр сертификации Let’s Encrypt, предоставляющий бесплатные сертификаты TLS и обеспечивающий сервер для тестирования конфигурации сертификатов и рабочий сервер для развертывания проверяемых сертификатов TLS.

      Создадим тестовый элемент Issuer, чтобы проверить правильность работы механизма распределения сертификатов. Откройте файл с именем staging_issuer.yaml в своем любимом текстовом редакторе:

      nano staging_issuer.yaml
      

      Вставьте в него следующий манифест ClusterIssuer:

      staging_issuer.yaml

      apiVersion: certmanager.k8s.io/v1alpha1
      kind: ClusterIssuer
      metadata:
       name: letsencrypt-staging
      spec:
       acme:
         # The ACME server URL
         server: https://acme-staging-v02.api.letsencrypt.org/directory
         # Email address used for ACME registration
         email: your_email_address_here
         # Name of a secret used to store the ACME account private key
         privateKeySecretRef:
           name: letsencrypt-staging
         # Enable the HTTP-01 challenge provider
         http01: {}
      

      Здесь мы указываем, что хотим создать объект ClusterIssuer с именем letsencrypt-staging и использовать сервер размещения Let’s Encrypt. Далее мы будем использовать для развертывания сертификатов производственный сервер, но в на этом сервере может быть ограничено количество запросов, и поэтому для тестирования лучше всего использовать URL сервера размещения.

      Затем мы укажем адрес электронной почты для регистрации сертификата и создадим секрет Kubernetes с именем letsencrypt-staging для сохранения закрытого ключа учетной записи ACME. Также мы активируем механизм вызовов HTTP-01. Дополнительную информацию об этих параметрах можно найти в официальной документации cert-manager по элементам Issuer.

      Разверните ClusterIssuer с помощью kubectl:

      • kubectl create -f staging_issuer.yaml

      Вы должны увидеть следующий результат:

      Output

      clusterissuer.certmanager.k8s.io/letsencrypt-staging created

      Теперь мы создали элемент Issuer для сервера размещения Let’s Encrypt и готовы изменить созданный выше ресурс Ingress и активировать шифрование TLS для путей echo1.example.com и echo2.example.com.

      Откройте echo_ingress.yaml в своем любимом редакторе еще раз:

      Добавьте в манифест ресурсов Ingress следующее:

      echo_ingress.yaml

      apiVersion: extensions/v1beta1
      kind: Ingress
      metadata:
        name: echo-ingress
        annotations:  
          kubernetes.io/ingress.class: nginx
          certmanager.k8s.io/cluster-issuer: letsencrypt-staging
      spec:
        tls:
        - hosts:
          - echo1.example.com
          - echo2.example.com
          secretName: letsencrypt-staging
        rules:
        - host: echo1.example.com
          http:
            paths:
            - backend:
                serviceName: echo1
                servicePort: 80
        - host: echo2.example.com
          http:
            paths:
            - backend:
                serviceName: echo2
                servicePort: 80
      

      Здесь мы добавим несколько аннотаций для указания класса Ingress.class, определяющего контроллер Ingress, который должен использоваться для реализации правил Ingress. Кроме того, мы определим для cluster-issuer элемент сертификации letsencrypt-staging, который мы только что создали.

      Наконец, мы добавим блок tls для указания хостов, для которых мы хотим получить сертификаты, а также укажем secretName. Этот секрет будет содержать закрытый ключ TLS и выданный сертификат.

      Когда вы закончите внесение изменений, сохраните и закройте файл.

      Теперь мы обновим существующие ресурсы Ingress с помощью команды kubectl apply:

      • kubectl apply -f echo_ingress.yaml

      Вы должны увидеть следующий результат:

      Output

      ingress.extensions/echo-ingress configured

      Вы можете использовать команду kubectl describe для отслеживания состояния изменений Ingress, которые вы только что применили:

      Output

      Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal CREATE 14m nginx-ingress-controller Ingress default/echo-ingress Normal UPDATE 1m (x2 over 13m) nginx-ingress-controller Ingress default/echo-ingress Normal CreateCertificate 1m cert-manager Successfully created Certificate "letsencrypt-staging"

      После успешного создания сертификата вы можете запустить дополнительную команду describe, чтобы еще раз убедиться в успешном его создании:

      • kubectl describe certificate

      Вы должны увидеть следующие результаты в разделе Events:

      Output

      Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Generated 63s cert-manager Generated new private key Normal OrderCreated 63s cert-manager Created Order resource "letsencrypt-staging-147606226" Normal OrderComplete 19s cert-manager Order "letsencrypt-staging-147606226" completed successfully Normal CertIssued 18s cert-manager Certificate issued successfully

      Это подтверждает, что сертификат TLS выдан успешно, и шифрование HTTPS активно для двух настроенных доменов.

      Теперь мы готовы отправить запрос на сервер echo для тестирования работы HTTPS.

      Запустите следующую команду wget для отправки запроса на echo1.example.com и распечатайте заголовки ответов в STDOUT:

      • wget --save-headers -O- echo1.example.com

      Вы должны увидеть следующий результат:

      Output

      URL transformed to HTTPS due to an HSTS policy --2018-12-11 14:38:24-- https://echo1.example.com/ Resolving echo1.example.com (echo1.example.com)... 203.0.113.0 Connecting to echo1.example.com (echo1.example.net)|203.0.113.0|:443... connected. ERROR: cannot verify echo1.example.com's certificate, issued by ‘CN=Fake LE Intermediate X1’: Unable to locally verify the issuer's authority. To connect to echo1.example.com insecurely, use `--no-check-certificate'.

      Это означает, что протокол HTTPS успешно активирован, но сертификат не удается проверить, поскольку это фиктивный временный сертификат, выданный сервером размещения Let’s Encrypt.

      Мы убедились, что с временным фиктивным сертификатом все работает и можем развернуть два производственных сертификата для двух хостов echo1.example.com и echo2.example.com.

      Шаг 5 — Развертывание элемента Issuer в производственной среде

      На этом шаге мы изменим процедуру, используемую для выделения фиктивных сертификатов, и генерируем действительный производственный сертификат для наших хостов Ingress.

      Вначале мы создадим производственный сертификат ClusterIssuer.

      Откройте файл с именем prod_issuer.yaml в своем любимом редакторе:

      nano prod_issuer.yaml
      

      Вставьте в него следующий манифест:

      prod_issuer.yaml

      apiVersion: certmanager.k8s.io/v1alpha1
      kind: ClusterIssuer
      metadata:
        name: letsencrypt-prod
      spec:
        acme:
          # The ACME server URL
          server: https://acme-v02.api.letsencrypt.org/directory
          # Email address used for ACME registration
          email: your_email_address_here
          # Name of a secret used to store the ACME account private key
          privateKeySecretRef:
            name: letsencrypt-prod
          # Enable the HTTP-01 challenge provider
          http01: {}
      

      Обратите внимание на другой URL сервера ACME и имя секретного ключа letsencrypt-prod.

      Когда вы закончите редактирование, сохраните и закройте файл.

      Теперь разверните элемент Issuer с помощью kubectl:

      • kubectl create -f prod_issuer.yaml

      Вы должны увидеть следующий результат:

      Output

      clusterissuer.certmanager.k8s.io/letsencrypt-prod created

      Обновите echo_ingress.yaml для использования нового элемента Issuer:

      Внесите в файл следующие изменения:

      echo_ingress.yaml

      apiVersion: extensions/v1beta1
      kind: Ingress
      metadata:
        name: echo-ingress
        annotations:  
          kubernetes.io/ingress.class: nginx
          certmanager.k8s.io/cluster-issuer: letsencrypt-prod
      spec:
        tls:
        - hosts:
          - echo1.example.com
          - echo2.example.com
          secretName: letsencrypt-prod
        rules:
        - host: echo1.example.com
          http:
            paths:
            - backend:
                serviceName: echo1
                servicePort: 80
        - host: echo2.example.com
          http:
            paths:
            - backend:
                serviceName: echo2
                servicePort: 80
      

      Здесь мы обновим ClusterIssuer и секретное имя на letsencrypt-prod.

      После внесения изменений сохраните и закройте файл.

      Разверните изменения с помощью команды kubectl apply:

      • kubectl apply -f echo_ingress.yaml

      Output

      ingress.extensions/echo-ingress configured

      Подождите несколько минут, чтобы дать производственному серверу Let’s Encrypt выдать сертификат. Вы можете отслеживать ход выполнения с помощью команды kubectl describe для объекта certificate:

      • kubectl describe certificate letsencrypt-prod

      Следующий экран результатов означает, что сертификат успешно установлен:

      Output

      Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Generated 82s cert-manager Generated new private key Normal OrderCreated 82s cert-manager Created Order resource "letsencrypt-prod-2626449824" Normal OrderComplete 37s cert-manager Order "letsencrypt-prod-2626449824" completed successfully Normal CertIssued 37s cert-manager Certificate issued successfully

      Теперь мы проведем тестирование с помощью curl, чтобы подтвердить правильную работу HTTPS:

      Вы должны увидеть следующее:

      Output

      <html> <head><title>308 Permanent Redirect</title></head> <body> <center><h1>308 Permanent Redirect</h1></center> <hr><center>nginx/1.15.9</center> </body> </html>

      Это означает, что запросы HTTP перенаправляются для использования HTTPS.

      Запустите curl на https://echo1.example.com:

      • curl https://echo1.example.com

      Вы должны увидеть следующий результат:

      Output

      echo1

      Вы можете запустить предыдущую команду с флагом -v для получения развернутой информации о соединении сертификата и проверки информации о сертификате.

      Вы успешно настроили HTTPS с помощью сертификата Let’s Encrypt для вашего Nginx Ingress.

      Заключение

      В этом обучающем модуле вы настроили Nginx Ingress для балансировки нагрузки и перенаправления внешних запросов на серверные службы внутри кластера Kubernetes. Также вы защитили Ingress, установив элемент обеспечения сертификата cert-manager и установив для двух путей хоста сертификат Let’s Encrypt.

      Существует множество альтернатив использованию контроллера Nginx Ingress. Дополнительную информацию можно найти в разделе «Контроллеры Ingress» в официальной документации Kubernetes.



      Source link