From 845154bffa4bf43e77f0138321b85b3e94bba157 Mon Sep 17 00:00:00 2001 From: Andreas Bleischwitz Date: Sat, 13 May 2023 10:07:48 +0200 Subject: [PATCH] * Feature: Add option to enable local Squid proxy - pulls quay.io/openshifttest/squid-proxy:latest and configures a SystemD service - optionally enables upstream cache proxy (proxy_cache_peer and proxy_cache_peer_port). - configures installation config to make use of this proxy. --- README.md | 3 + .../tasks/create-network.yml | 10 ++ .../roles/openshift-4-proxy/defaults/main.yml | 5 + .../roles/openshift-4-proxy/tasks/create.yml | 66 +++++++++++++ .../roles/openshift-4-proxy/tasks/destroy.yml | 24 +++++ .../roles/openshift-4-proxy/tasks/start.yml | 15 +++ .../roles/openshift-4-proxy/tasks/stop.yml | 17 ++++ .../templates/squid-config.j2 | 99 +++++++++++++++++++ .../templates/systemd.service.j2 | 29 ++++++ docs/release-notes.md | 4 + 10 files changed, 272 insertions(+) create mode 100644 ansible/roles/openshift-4-proxy/defaults/main.yml create mode 100644 ansible/roles/openshift-4-proxy/tasks/create.yml create mode 100644 ansible/roles/openshift-4-proxy/tasks/destroy.yml create mode 100644 ansible/roles/openshift-4-proxy/tasks/start.yml create mode 100644 ansible/roles/openshift-4-proxy/tasks/stop.yml create mode 100644 ansible/roles/openshift-4-proxy/templates/squid-config.j2 create mode 100644 ansible/roles/openshift-4-proxy/templates/systemd.service.j2 diff --git a/README.md b/README.md index 2422945d..7b974ccb 100644 --- a/README.md +++ b/README.md @@ -226,6 +226,9 @@ Please configure in `cluster.yml` all necessary credentials: |`sdn_plugin_name`|`OVNKubernetes`|This allows you to change SDN plugin. Valid values are OpenShiftSDN and OVNKubernetes. (Default is OVNKubernetes.) |`masters_schedulable`|true|Set to false if don't want to allow workload onto the master nodes. (Default is to allow this)| |`install_config_capabilities`|null|Configure [Cluster capabilities](https://docs.openshift.com/container-platform/latest/post_installation_configuration/cluster-capabilities.html) +|`proxy_cache_enabled`|false|Enable local Squid in a container to allow caching and IPv6 to IPv4 conversion (requires external dual-stack system which also has a Squid running)| +|`proxy_cache_peer`|none|Host (IP/name) of Squid upstream cache. If unset, no upstream cache will be used| +|`proxy_cache_peer_port`|3128|Listening port of remote Squid proxy| ## Prepare kvm-host and install OpenShift diff --git a/ansible/roles/openshift-4-cluster/tasks/create-network.yml b/ansible/roles/openshift-4-cluster/tasks/create-network.yml index c09c5829..b6e32070 100644 --- a/ansible/roles/openshift-4-cluster/tasks/create-network.yml +++ b/ansible/roles/openshift-4-cluster/tasks/create-network.yml @@ -132,6 +132,16 @@ lb_haproxy_cfg: "{{ lb_haproxy_cfg }}" tags: lb +# +# System-wide proxy +# Optionally tunnel IPv6 to IPv4 addresses +# +- name: Ensure Squid Proxy is configured + ansible.builtin.import_role: + name: openshift-4-proxy + tasks_from: create.yml + when: proxy_cache_enabled is defined and proxy_cache_enabled + # # Public DNS # diff --git a/ansible/roles/openshift-4-proxy/defaults/main.yml b/ansible/roles/openshift-4-proxy/defaults/main.yml new file mode 100644 index 00000000..5c71938a --- /dev/null +++ b/ansible/roles/openshift-4-proxy/defaults/main.yml @@ -0,0 +1,5 @@ +--- +proxy_name: "openshift-4-proxy" +proxy_container_image: quay.io/openshifttest/squid-proxy:latest +proxy_cache_dir: "/var/srv/containers/squid" +proxy_cache_peer_port: 3128 diff --git a/ansible/roles/openshift-4-proxy/tasks/create.yml b/ansible/roles/openshift-4-proxy/tasks/create.yml new file mode 100644 index 00000000..b605a9f4 --- /dev/null +++ b/ansible/roles/openshift-4-proxy/tasks/create.yml @@ -0,0 +1,66 @@ +--- +- name: Create "install_config_proxy" for local proxy + ansible.builtin.set_fact: + install_config_proxy: + # yamllint disable rule:line-length + httpProxy: "http://{{ ansible_host }}:3128" + httpsProxy: "http://{{ ansible_host }}:3128" + noProxy: "{{ ansible_host }}" + # yamllint enable rule:line-length + when: proxy_cache_enabled is defined and proxy_cache_enabled + +- name: Ensure Podman is present + ansible.builtin.package: + name: + - podman + - netavark + state: present + +- name: Ensure OpenShift 4 Proxy environment-file exists + ansible.builtin.copy: + content: | + ### environment for squid-proxy + SQUID_DIR={{ proxy_cache_dir }} + dest: "/etc/sysconfig/{{ proxy_name }}.env" + mode: 0644 + +- name: Ensure Squid disk-cache directory exists + ansible.builtin.file: + path: "{{ proxy_cache_dir }}" + state: directory + mode: 0770 + owner: 23 + group: 23 + setype: container_var_lib_t + +- name: Ensure OpenShift 4 Proxy configuration-file exists + ansible.builtin.template: + src: squid-config.j2 + dest: "/etc/sysconfig/{{ proxy_name }}.conf" + mode: 0644 + +- name: Ensure OpenShift 4 Proxy SystemD service exists + ansible.builtin.template: + src: systemd.service.j2 + dest: "/etc/systemd/system/{{ proxy_name }}.service" + mode: 0644 + +- name: Enable and start {{ proxy_name }}.service + ansible.builtin.systemd: + name: "{{ proxy_name }}.service" + daemon_reload: yes + enabled: yes + state: started + +- name: Allow services to start up + ansible.builtin.pause: + seconds: 30 + +- name: Collect services facts + ansible.builtin.service_facts: + register: services_state + +- name: Check {{ proxy_name }}.service status + fail: + msg: "Proxy service {{ proxy_name }}.service is not running!!! Please check, run: systemctl status {{ proxy_name }}.service" + when: services_state.ansible_facts.services[ proxy_name + '.service'].state != 'running' diff --git a/ansible/roles/openshift-4-proxy/tasks/destroy.yml b/ansible/roles/openshift-4-proxy/tasks/destroy.yml new file mode 100644 index 00000000..421a9e08 --- /dev/null +++ b/ansible/roles/openshift-4-proxy/tasks/destroy.yml @@ -0,0 +1,24 @@ +--- +- name: Collect services facts + ansible.builtin.service_facts: + register: services_state + +- name: Ensure {{ proxy_name }}.service is stopped and disabled + ansible.builtin.systemd: + name: "{{ proxy_name }}.service" + enabled: false + state: stopped + when: services_state.ansible_facts.services[ proxy_name + '.service'] is defined + +- name: Remove OpenShift 4 Proxy SystemD service + ansible.builtin.file: + path: "{{ item }}" + state: absent + with_items: + - "/etc/sysconfig/{{ proxy_name }}.env" + - "/etc/sysconfig/{{ proxy_name }}.conf" + - "/etc/systemd/system/{{ proxy_name }}.service" + +- name: Podman will stay in the Host, Play with it! ;-) + debug: + msg: "Podman will stay in the Host, Play with it! ;-)" diff --git a/ansible/roles/openshift-4-proxy/tasks/start.yml b/ansible/roles/openshift-4-proxy/tasks/start.yml new file mode 100644 index 00000000..2d68a11a --- /dev/null +++ b/ansible/roles/openshift-4-proxy/tasks/start.yml @@ -0,0 +1,15 @@ +--- +- name: Ensure {{ proxy_name }}.service is enabled and started + ansible.builtin.systemd: + name: "{{ proxy_name }}.service" + enabled: yes + state: started + +- name: Collect services facts + ansible.builtin.service_facts: + register: services_state + +- name: Check {{ proxy_name }}.service + fail: + msg: "Load balancer service {{ proxy_name }}.service is not running!!! Please check, run: systemctl status {{ proxy_name }}.service" + when: services_state.ansible_facts.services[ proxy_name + '.service'].state != 'running' diff --git a/ansible/roles/openshift-4-proxy/tasks/stop.yml b/ansible/roles/openshift-4-proxy/tasks/stop.yml new file mode 100644 index 00000000..4ccf50cd --- /dev/null +++ b/ansible/roles/openshift-4-proxy/tasks/stop.yml @@ -0,0 +1,17 @@ +--- +- name: Ensure {{ proxy_name }}.service is stopped and disabled + ansible.builtin.systemd: + name: "{{ proxy_name }}.service" + enabled: no + state: stopped + +- name: Collect services facts + ansible.builtin.service_facts: + register: services_state + +- name: Check {{ proxy_name }}.service + fail: + msg: "Load balancer service {{ proxy_name }}.service is not running!!! Please check, run: systemctl status {{ proxy_name }}.service" + when: + - services_state.ansible_facts.services[ proxy_name + '.service'].state != 'inactive' + - services_state.ansible_facts.services[ proxy_name + '.service'].status != 'disabled' diff --git a/ansible/roles/openshift-4-proxy/templates/squid-config.j2 b/ansible/roles/openshift-4-proxy/templates/squid-config.j2 new file mode 100644 index 00000000..b6da846b --- /dev/null +++ b/ansible/roles/openshift-4-proxy/templates/squid-config.j2 @@ -0,0 +1,99 @@ +pid_filename /run/squid.pid +logfile_rotate 0 +access_log stdio:/dev/tty +cache_log stdio:/dev/tty + +# the hostname squid displays in error messages +visible_hostname localhost + +# Squid listening port +http_port 3128 + + +# cache size +cache_mem 256 MB +cache_dir ufs /var/spool/squid 4000 16 256 + +acl acl_direct_access dstdomain .quay.io +acl acl_direct_access dstdomain registry.redhat.io +acl acl_direct_access dstdomain registry.connect.redhat.com +acl acl_direct_access dstdomain .ipv6.docker.com +acl acl_direct_access dstdomain .cloudflare.docker.com +acl acl_direct_access dstdomain registry.ipv6.docker.com +acl acl_direct_access dstdomain .gcr.io +acl acl_direct_access dstdomain .googleapis.com +acl acl_direct_access dstdomain .{{ public_domain }} +acl acl_direct_access dstdomain .stackrox.io + + +# cache peering: +# Proxy requests are send to peering cache first. +# Used for i.e. IPv6 only networks where IPv4 hosts won't be reachable at all even from the host +# You will need to setup your local squid to *only* allow connections from this host (and probably your local-networks' hosts) +# A public IPv6 address exposed to the internet (and therefore also the Hetzner host) will be required, as well +# as a public ipv4 address - but there is no need to expose Squid on IPv4 as well. We just need to send requests +# to the remote proxy via IPv6 and reach out to IPv4 hosts via that host. +{% if proxy_cache_peer is defined %} +cache_peer {{ proxy_cache_peer }} parent {{ proxy_cache_peer_port }} 0 default no-query no-digest no-netdb-exchange +# always request access via parent +prefer_direct off +nonhierarchical_direct off + +always_direct allow acl_direct_access +always_direct deny all + +never_direct deny acl_direct_access +never_direct allow all +{% endif %} + +# Example rule allowing access from your local networks. +# Adapt to list your (internal) IP networks from where browsing +# should be allowed +acl localnet src 0.0.0.1-0.255.255.255 # RFC 1122 "this" network (LAN) +acl localnet src 10.0.0.0/8 # RFC 1918 local private network (LAN) +acl localnet src 100.64.0.0/10 # RFC 6598 shared address space (CGN) +acl localnet src 169.254.0.0/16 # RFC 3927 link-local (directly plugged) machines +acl localnet src 172.16.0.0/12 # RFC 1918 local private network (LAN) +acl localnet src 192.168.0.0/16 # RFC 1918 local private network (LAN) +acl localnet src fc00::/7 # RFC 4193 local private network range +acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines + +{% if 'IPv4' in ip_families %} +{%if public_ip is defined %}#acl localhost src {{ public_ip }} # The host may need to send proxy requests too{% endif %} +#acl localhost src 127.0.0.1 # The host may need to send proxy requests too +acl localnet src {{ vn_subnet }}/24 # OpenShift network +{% endif %} +{% if 'IPv6' in ip_families %} +{%if public_ipv6 is defined %}#acl localhost src {{ public_ipv6 }} # With IPv6 chances are that some services are not IPv6 enabled, make use of peering Squid{% endif %} +#acl localhost src ::1 # With IPv6 chances are that some services are not IPv6 enabled, make use of peering Squid +acl localnet src {{ vn_subnet_ipv6 }}::/80 # OpenShift network +{% endif %} + +acl SSL_ports port 443 +acl SSL_ports port 6443 # API +acl Safe_ports port 80 # http +acl Safe_ports port 21 # ftp +acl Safe_ports port 443 # https +acl Safe_ports port 70 # gopher +acl Safe_ports port 210 # wais +acl Safe_ports port 1025-65535 # unregistered ports +acl Safe_ports port 280 # http-mgmt +acl Safe_ports port 488 # gss-http +acl Safe_ports port 591 # filemaker +acl Safe_ports port 777 # multiling http + +acl CONNECT method CONNECT + +http_access deny !Safe_ports +http_access deny CONNECT !SSL_ports +http_access allow localhost manager +http_access deny manager + +# +# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS +# + +http_access allow localnet +http_access allow localhost +http_access deny all + diff --git a/ansible/roles/openshift-4-proxy/templates/systemd.service.j2 b/ansible/roles/openshift-4-proxy/templates/systemd.service.j2 new file mode 100644 index 00000000..d07725c9 --- /dev/null +++ b/ansible/roles/openshift-4-proxy/templates/systemd.service.j2 @@ -0,0 +1,29 @@ +[Unit] +Description=OpenShift 4 {{ proxy_name }}) +After=network.target libvirtd.service + +[Service] +Type=simple +TimeoutStartSec=5m + +EnvironmentFile=/etc/sysconfig/{{ proxy_name }}.env + +ExecStartPre=-/usr/bin/podman rm "{{ proxy_name }}" +ExecStartPre=/usr/bin/podman pull {{ proxy_container_image }} +ExecStart=/usr/bin/podman run --name {{ proxy_name }} --net host \ + --expose 3128 \ + --group-add tty \ + --tty \ + --privileged \ + --volume /etc/sysconfig/{{ proxy_name }}.conf:/etc/squid/squid.conf:ro \ + --volume ${SQUID_DIR}:/var/spool/squid:rw,noexec,nosuid,z \ + {{ proxy_container_image }} + +ExecReload=-/usr/bin/podman stop "{{ proxy_name }}" +ExecReload=-/usr/bin/podman rm "{{ proxy_name }}" +ExecStop=-/usr/bin/podman stop "{{ proxy_name }}" +Restart=always +RestartSec=30 + +[Install] +WantedBy=multi-user.target diff --git a/docs/release-notes.md b/docs/release-notes.md index 34df73cd..0979f0e9 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,5 +1,9 @@ # RELEASE NOTES +## 2023-05-12 + * Added new option `proxy_cache_enabled` to configure Squid in a container. + * Added new option `proxy_cache_peer` and `proxy_cache_peer_port` to allow upstream Squid cache + ## 2023-04-14 * Bump OpenShift version to 4.12.10