我们有一些负载平衡的网络服务器,它们被配置为使用虚拟主机来托管多个网站。 由于虚拟主机的存在,我们在与任何网站建立连接时都需要将正确的域名发送到网络服务器。
我们希望 Ansible 直接访问各个后端 Web 服务器(使用 uri 模块)。
类似于我们如何使用curl中的
--connect-to
参数覆盖主机:
curl --connect-to serverhostname:443 ``https://www.example.com
现在我想我们可以使用 url 字段直接连接到后端服务器,并将 www.domain.com 网站作为 http 主机标头传递。但我找不到如何覆盖 HTTPS 网站的 SNI 扩展。
或者让 Ansible 使用正确的 URL,但覆盖连接本身的 IP/主机名(类似于curl 的做法)
- name: Wait for the webserver to return a 200
uri:
url: "https://serverhostname:443/"
method: GET
status_code: 200
return_content: no
headers:
host: "www.example.com"
register: result
until: result.status == 200
retries: 10
delay: 1
我也尝试过使用Ansible代理功能来连接到后端服务器。同时保持 uri 的 URL 参数正确。但这会导致“错误隧道连接失败”。
背景信息/目标:我们希望单独测试我们的冗余后端网络服务器,并确保它们在剧本继续在其他服务器上进行更改之前仍然正确响应。
socat
创建一个转发到目标 URL 的 unix 套接字,然后将其与 unix_socket
选项一起使用到 ansible.builtin.uri
:
---
- name: Example URI request with alternate hostname using socat
hosts: all
vars:
target_url: https://127.0.0.1/balancer-manager
target_hostname: www.example.com
- name: Set variables for socat connection
when: target_hostname is defined and (target_url | urlsplit('hostname')) != target_hostname
ansible.builtin.set_fact:
socat_unix_socket: "/var/tmp/{{ target_hostname }}"
socat_target_address: >-
{% if target_url | urlsplit('scheme') == 'https' %}
OPENSSL:{{ target_url | urlsplit('hostname') }}:{{ target_url | urlsplit('port') | default(443, true) }},commonname={{ target_hostname }}
{% else %}
TCP:{{ target_url | urlsplit('hostname') }}:{{ target_url | urlsplit('port') | default(80, true) }}
{% endif %}
modified_url: "http://{{ target_hostname }}{{ target_url | urlsplit('path') }}?{{ target_url | urlsplit('query') }}"
- name: Start socat and run URI task(s)
block:
- name: Start socat asynchronously
when: socat_unix_socket is defined
ansible.builtin.command: >
socat
UNIX-LISTEN:{{ socat_unix_socket }},fork,accept-timeout=10
{{ socat_target_address }}
changed_when: false
register: socat_result
async: 300
poll: 0
- name: Access target URL via unix socket
ansible.builtin.uri:
url: "{{ modified_url | default(target_url) }}"
unix_socket: "{{ socat_unix_socket | default(omit) }}"
always:
- name: Wait for socat to finish (timeout)
when: socat_unix_socket is defined
ansible.builtin.async_status:
jid: "{{ socat_result.ansible_job_id }}"
register: socat_job_result
until: socat_job_result.finished
retries: 60
delay: 5