[ English | English (United Kingdom) | Deutsch | русский ]

Использование точек доступа на основе домена (или пути) вместо точек входа на основе порта

По умолчанию OpenStack-Ansible использует точки доступа на основе портов. Это означает, что каждая служба будет обслуживаться на своем собственном уникальном порту как для публичных, так и для внутренних точек доступа. Например, Keystone будет добавлен как https://domain.com:5000/v3, а Nova как https://domain.com:8774/v2.1 и так далее.

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

Чтобы обойти эти ограничения, начиная с версии 2023.1 (Antelope), можно использовать точки доступа на основе домена или пути.

Настройка точек доступа на основе пути

Точки доступа на основе пути подразумевают обслуживание служб на одном и том же полном доменном имени, но дифференциацию их на основе URI.

Например, Keystone можно настроить как https://domain.com/identity/v3, а Nova как https://domain.com/compute/v2.1

Предупреждение

Обратите внимание, что Horizon использует /identity для своей панели Keystone, поэтому, если вы обслуживаете Horizon на / (по умолчанию) и используете /identity для пересылки трафика на бекэнд Keystone, управление пользователями, ролями и проектами внутри Horizon будет нарушено из-за конфликта.

Хотя точки доступа на основе пути могут выглядеть заманчиво из-за использования FQDN и, таким образом, отсутствия необходимости в wildcard TLS, их сложнее поддерживать и настраивать. Также стоит упомянуть, что не все службы готовы поддерживать точки доступа на основе пути, несмотря на то, что этот подход используется в devstack.

Хорошим примером исключений, которые в данный момент не поддерживают точки доступа на основе путей, являются консоли VNC для виртуальных машин (будут реализованы с помощью blueprint), Magnum (отчет об ошибке <https://launchpad.net/bugs/2083168>) и Ceph Rados Gateway.

Конфигурация HAProxy

Подобно доменным точкам доступа мы полагаемся на функциональность карт HAProxy. Но вместо map_dom мы будем использовать map_reg.

Итак, нам нужно определить файл карты, который будет использоваться, и способ его анализа. Для этого нам нужно применить переопределение для службы base.

haproxy_base_service_overrides:
  haproxy_maps:
    - 'use_backend %[path,map_reg(/etc/haproxy/base_regex.map)]'

Если вам действительно нужен Ceph RGW или вы хотите объединить подходы на основе домена и пути, вы можете сделать это, определив два файла карт:

Примечание

В случае каких-либо изменений в переменной haproxy_base_service_overrides необходимо повторно запустить openstack-ansible openstack.osa.haproxy --tags haproxy-service-config.

haproxy_base_service_overrides:
  haproxy_maps:
    - 'use_backend %[req.hdr(host),map_dom(/etc/haproxy/base_domain.map)] if { req.hdr(host),map_dom(/etc/haproxy/base_domain.map) -m found }'
    - 'use_backend %[path,map_reg(/etc/haproxy/base_regex.map)]'

Если ни один домен не будет совпадать, HAProxy продолжит работу с точками доступа на основе пути.

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

Примечание

После внесения изменений в переменную haproxy_<service>_service_overrides вам необходимо повторно запустить сценарий для конкретной службы с тегом haproxy-service-config, например openstack-ansible openstack.osa.keystone --tags haproxy-service-config.

haproxy_keystone_service_overrides:
  haproxy_backend_only: True
  haproxy_map_entries:
    - name: base_regex
      entries:
        - "^/identity keystone_service-back"

haproxy_nova_api_compute_service_overrides:
  haproxy_backend_only: True
  haproxy_map_entries:
    - name: base_regex
      entries:
        - "^/compute nova_api_os_compute-back"

Конфигурация службы

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

  • <service>_service_publicuri

  • <service>_service_internaluri

  • <service>_service_adminuri

Ниже вы можете найти пример определения точек доступа для Keystone и Nova:

keystone_service_publicuri: "{{ openstack_service_publicuri_proto }}://{{ external_lb_vip_address }}/identity"
keystone_service_internaluri: "{{ openstack_service_internaluri_proto }}://{{ internal_lb_vip_address }}/identity"
keystone_service_adminuri: "{{ openstack_service_adminuri_proto }}://{{ internal_lb_vip_address }}/identity"

nova_service_publicuri: "{{ openstack_service_publicuri_proto }}://{{ external_lb_vip_address }}/compute"
nova_service_internaluri: "{{ openstack_service_internaluri_proto }}://{{ internal_lb_vip_address }}/compute"
nova_service_adminuri: "{{ openstack_service_adminuri_proto }}://{{ internal_lb_vip_address }}/compute"

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

Итак, теперь нам нужно заставить службу уважать путь и правильно реагировать на него. Одним из способов сделать это может быть использование rewrite механизма в uWSGI, например:

Предупреждение

Пример ниже не отображает правильный подход к настройке точки доступа на основе пути для большинства служб

keystone_uwsgi_ini_overrides:
  uwsgi:
    route: '^/identity(.*)$ rewrite:$1'

Но этот подход не является правильным и приведет к проблемам в некоторых клиентах или вариантах использования, несмотря на то, что служба выглядит полностью функциональной. Проблема с подходом выше связана с тем, как службы возвращают self URL, когда его запрашивают. Большинство служб ответят своей текущей микроверсией и URI этой микроверсии в ответе.

Если вы используете rewrite uWSGI, как показано выше, вы получите такой ответ:

curl https://cloud.com/identity/ | jq
{
"versions": {
    "values": [
    {
        "id": "v3.14",
        "status": "stable",
        "updated": "2020-04-07T00:00:00Z",
        "links": [
        {
            "rel": "self",
            "href": "https://cloud.com/v3/"
        }
        ],
        "media-types": [
        {
            "base": "application/json",
            "type": "application/vnd.openstack.identity-v3+json"
        }
        ]
    }
    ]
}
}

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

Некоторые службы, такие как keystone, имеют параметры конфигурации, которые могут контролировать, как определяется href. Например, keystone имеет параметр [DEFAULT]/public_endpoint, но этот подход не является единообразным для всех служб. Более того, keystone вернет предоставленный public_endpoint для всех точек доступа, включая административную и внутреннюю.

При этом единственным правильным подходом здесь будет настройка api-paste.ini для каждой соответствующей службы. Но, в частности, Keystone не поддерживает файлы api-paste.ini. Поэтому единственный способ обойти это — фактически использовать uWSGI rewrite и определить public_endpoint в keystone.conf:

keystone_keystone_conf_overrides:
  DEFAULT:
    public_endpoint: "{{ keystone_service_publicuri }}"

Для других служб применение api-paste.ini можно сделать с переменными, но у каждой службы там довольно уникальный контент, поэтому подход нельзя легко обобщить. Ниже вы можете найти переопределения, сделанные для некоторых служб в качестве примера:

_glance_api_paste_struct:
    /: {}
    /healthcheck: {}
    /image: api
    /image/healthcheck: healthcheck
glance_glance_api_paste_ini_overrides:
  composite:glance-api: "{{ _glance_api_paste_struct }}"
  composite:glance-api-caching: "{{ _glance_api_paste_struct }}"
  composite:glance-api-cachemanagement: "{{ _glance_api_paste_struct }}"
  composite:glance-api-keystone: "{{ _glance_api_paste_struct }}"
  composite:glance-api-keystone+caching: "{{ _glance_api_paste_struct }}"
  composite:glance-api-keystone+cachemanagement: "{{ _glance_api_paste_struct }}"

neutron_api_paste_ini_overrides:
  composite:neutron:
    /: {}
    /v2.0: {}
    /network/: neutronversions_composite
    /network/v2.0: neutronapi_v2_0

nova_api_paste_ini_overrides:
  composite:osapi_compute:
    /: {}
    /v2: {}
    /v2.1: {}
    /v2/+: {}
    /v2.1/+: {}
    /compute: oscomputeversions
    /compute/v2: oscomputeversion_legacy_v2
    /compute/v2.1: oscomputeversion_v2
    /compute/v2/+: openstack_compute_api_v21_legacy_v2_compatible
    /compute/v2.1/+: openstack_compute_api_v21

Мы рекомендуем обратиться к api-paste.ini каждой службы для получения более подробной информации о том, как правильно настроить переопределения.