Releasenotes
https://docs.openstack.org/releasenotes/octavia/
CLI
https://docs.openstack.org/octavia/latest/user/guides/basic-cookbook.html
https://clouddocs.web.cern.ch/networking/load_balancing.html
openstack loadbalancer list --project ${PROJECT_ID} openstack floating ip list --project ${PROJECT_ID} --fixed-ip-address 10.1.2.13 # show loadbalancer listener openstack loadbalancer listener list --loadbalancer ${LB_NAME} -c id -f value | \ xargs -L1 openstack loadbalancer listener show -c name -c id -c protocol -c default_tls_container_ref -c sni_container_refs # get for HTTPS listener ID openstack loadbalancer listener list --loadbalancer ${LB_NAME} -f json | jq -r '.[] | select(.protocol_port == 443) | .id'
Create Amphora image
sudo apt install -y python3-pip git qemu qemu-utils debootstrap kpartx sudo pip3 install diskimage-builder git clone https://github.com/openstack/octavia.git -b stable/stein cd octavia sudo ./diskimage-create/diskimage-create.sh -d bionic -t raw chmod a+r ./amphora-x64-haproxy.raw
Upload Amphora image
#openstack image create --container-format bare --disk-format qcow2 --private --file amphora-x64-haproxy.qcow2 --tag amphora amphora openstack image create --container-format bare --disk-format raw --public --file amphora-x64-haproxy.raw --tag amphora amphora --os-cloud=dev-admin openstack image set --protected amphora --os-cloud=dev-admin openstack image list --long
Configure OpenStack
OCTAVIA_KEYSTONE_PASSWORD=$(cat /etc/kolla/passwords.yml | grep octavia_keystone_password | cut -d":" -f2) echo ${OCTAVIA_KEYSTONE_PASSWORD} #openstack flavor create --id octavia --disk 20 --private --ram 512 --vcpus 1 octavia openstack flavor create --disk 20 --public --ram 512 --vcpus 1 octavia openstack --os-username octavia --os-password ${OCTAVIA_KEYSTONE_PASSWORD} keypair create --public-key ~/.ssh/id_rsa.pub octavia_ssh_key openstack security group create --description 'used by Octavia amphora instance' octavia openstack security group rule create --protocol icmp octavia openstack security group rule create --protocol tcp --dst-port 5555 --egress octavia openstack security group rule create --protocol tcp --dst-port 9443 --ingress octavia
Deploy Octavia (with kolla-ansible
https://docs.openstack.org/octavia/queens/configuration/configref.html
openstack image create amphora --file /root/amphora-x64-haproxy.raw --disk-format raw --min-disk 0 --min-ram 0 --private --protected --tag amphora --property os_distro=ubuntu --property os_admin_user=ubuntu --property os_version="18.04" octavia_amp_boot_network_list="$(openstack network create lb-mgmt-net -f value -c id)" octavia_subnet="$(openstack subnet create lb-mgmt-subnet1 --network lb-mgmt-net --subnet-range 172.16.0.0/12 --allocation-pool start=172.16.100.1,end=172.31.200.200 -f value -c id)" octavia_amp_flavor_id="$(openstack flavor create --disk 20 --private --ram 4096 --vcpus 2 octavia -f value -c id)" octavia_amp_secgroup_list="$(openstack security group create octavia -f value -c id)" openstack security group rule create --protocol icmp $octavia_amp_secgroup_list openstack security group rule create --protocol tcp --dst-port 5555 --egress $octavia_amp_secgroup_list openstack security group rule create --protocol tcp --dst-port 9443 --ingress $octavia_amp_secgroup_list openstack role add --user admin --domain Default admin nova keypair-add --pub-key=/root/.ssh/id_rsa.pub --user $(openstack user show octavia --domain Default -f value -c id) octavia_ssh_key echo "octavia_amp_boot_network_list: ${octavia_amp_boot_network_list}" >> /etc/kolla/globals.yml echo "octavia_amp_secgroup_list: ${octavia_amp_secgroup_list}" >> /etc/kolla/globals.yml echo "octavia_amp_flavor_id: ${octavia_amp_flavor_id}" >> /etc/kolla/globals.yml # sed -i "s|^octavia_amp_boot_network_list: .*|octavia_amp_boot_network_list: ${octavia_amp_boot_network_list}|g" /etc/kolla/globals.yml # sed -i "s|^octavia_amp_secgroup_list: .*|octavia_amp_secgroup_list: ${octavia_amp_secgroup_list}|g" /etc/kolla/globals.yml # sed -i "s|^octavia_amp_flavor_id: .*|octavia_amp_flavor_id: ${octavia_amp_flavor_id}|g" /etc/kolla/globals.yml cd /opt/kolla-ansible/tools ./kolla-ansible -i ../ansible/inventory/all-in-one deploy -t octavia # debug docker restart octavia_api octavia_health_manager octavia_housekeeping octavia_worker
Create LoadBalancer
OS_USER=foo LB_NAME=lb1 LB_SUBNET=${OS_USER}-subnet LB_BACKEND_IPS="10.0.1.11 10.0.1.12" # # Convert certificates # # Convert first Let's Encrypt certificate to p12 openssl pkcs12 -export -out cert1.p12 -inkey privkey1.pem -in cert1.pem -certfile chain1.pem -passout "pass:" openstack secret store --name=cert1 -t "application/octet-stream" -e base64 --payload="$(base64 < cert1.p12)" # Convert second Let's Encrypt certificate to p12 openssl pkcs12 -export -out cert2.p12 -inkey privkey1.pem -in cert1.pem -certfile chain1.pem -passout "pass:" openstack secret store --name=cert2 -t 'application/octet-stream' -e base64 --payload="$(base64 < cert2.p12)" # DEBUG: show available certificates openstack secret list # # Configure LB # # Create LoadBalancer LB_PORT_ID=$(openstack loadbalancer create --name ${OS_USER}-${LB_NAME} --vip-subnet-id ${LB_SUBNET} -c vip_port_id -f value) while ! [ "$(openstack loadbalancer show ${OS_USER}-${LB_NAME} -c provisioning_status -f value)" == "ACTIVE" ]; do sleep 1; done # DEBUG: list available LB openstack loadbalancer list # Add floating IP FLOATING_IP=$(openstack floating ip create public -c floating_ip_address -f value --floating-ip-address 10.71.95.8) openstack floating ip set --port ${LB_PORT_ID} ${FLOATING_IP} # DEBUG: show floating ip echo ${FLOATING_IP} # # Configure HTTP # # Create HTTP listener openstack loadbalancer listener create ${OS_USER}-${LB_NAME} \ --name ${OS_USER}-${LB_NAME}-http-listener \ --insert-headers X-Forwarded-For=true,X-Forwarded-Proto=true \ --protocol HTTP \ --protocol-port 80 # DEBUG: list LB listener openstack loadbalancer listener list # Create pool and add member openstack loadbalancer pool create --name ${OS_USER}-${LB_NAME}-http-pool --lb-algorithm ROUND_ROBIN --listener ${OS_USER}-${LB_NAME}-http-listener --protocol HTTP for LB_BACKEND_IP in ${LB_BACKEND_IPS}; do openstack loadbalancer member create ${OS_USER}-${LB_NAME}-http-pool --address ${LB_BACKEND_IP} --protocol-port 80 done # DEBUG: list LB member openstack loadbalancer member list ${OS_USER}-${LB_NAME}-http-pool # DEBUG: test http LB curl http://${FLOATING_IP} -I # # Configure HTTPS # # Create HTTPS listener # CERTIFICATE_1=https://barbican.service.example.com/v1/secrets/c223df80-84fb-45de-9d47-c0a02a0c5b75 CERTIFICATE_1=$(openstack secret list --name cert1 -c "Secret href" -f value) CERTIFICATE_2=$(openstack secret list --name cert2 -c "Secret href" -f value) openstack loadbalancer listener create ${LB_NAME} \ --name ${OS_USER}-${LB_NAME}-https-listener \ --protocol-port 443 \ --protocol TERMINATED_HTTPS \ --insert-headers X-Forwarded-For=true,X-Forwarded-Port=true \ --default-tls-container=${CERTIFICATE_1} \ --sni-container-refs ${CERTIFICATE_1} ${CERTIFICATE_2} \ --default-pool ${LB_POOL_ID} \ # X-Forwarded-Proto=true while ! [ "$(openstack loadbalancer listener show ${OS_USER}-https-listener -c provisioning_status -f value)" == "ACTIVE" ]; do sleep 1; done # Create pool and add member openstack loadbalancer pool create --name ${OS_USER}-${LB_NAME}-https-pool --lb-algorithm ROUND_ROBIN --listener ${OS_USER}-${LB_NAME}-https-listener --protocol HTTP for LB_BACKEND_IP in ${LB_BACKEND_IPS}; do openstack loadbalancer member create ${OS_USER}-${LB_NAME}-https-pool --address ${LB_BACKEND_IP} --protocol-port 80 done
Delete LoadBalancer (recursive)
openstack loadbalancer delete --cascade LB_NAME
Statistics
openstack loadbalancer stats show ${LB_ID} openstack loadbalancer listener stats show ${LB_LISTENER_ID} # # Debug # <code> openstack secret list openstack loadbalancer list openstack loadbalancer listener list --loadbalancer lb1 openstack loadbalancer member list http-pool openstack loadbalancer amphora list openstack loadbalancer amphora list --loadbalancer 0ce30f0e-1d75-486c-a09f-79125abf44b8 +--------------------------------------+--------------------------------------+-----------+--------+---------------+-------------+ | id | loadbalancer_id | status | role | lb_network_ip | ha_ip | +--------------------------------------+--------------------------------------+-----------+--------+---------------+-------------+ | daee2f88-01fd-4ffa-b80d-15c63771d99d | 0ce30f0e-1d75-486c-a09f-79125abf44b8 | ERROR | BACKUP | 172.16.100.30 | 172.28.0.26 | | f22186b1-2865-4f4a-aae2-7f869b7aae12 | 0ce30f0e-1d75-486c-a09f-79125abf44b8 | ALLOCATED | MASTER | 172.16.100.5 | 172.28.0.26 | +--------------------------------------+--------------------------------------+-----------+--------+---------------+-------------+ openstack server show amphora-${AMPHORA_ID} -c id -f value ssh compute1 ps axf | grep dce0e225-9f23-46a2-b2e0-6e027ddfd6d0 # show updated LB openstack loadbalancer list --provisioning-status PENDING_UPDATE -c id -f value | xargs -L1 openstack loadbalancer show -c updated_at -c provisioning_status -c id -c name
Enable / Disable LB
openstack loadbalancer set --disable 2fc1a9be-a9e4-4288-9464-cf486d266483 openstack loadbalancer set --enable 2fc1a9be-a9e4-4288-9464-cf486d266483
Find broken LB
# List broken LoadBalancer instances openstack loadbalancer list --provisioning-status ERROR openstack loadbalancer list --provisioning-status PENDING_UPDATE # List broken Loadbalancer VMs openstack loadbalancer amphora list --provisioning-status ERROR openstack loadbalancer amphora list --role STANDALONE
Debug
# List LB VMs (admin only) openstack loadbalancer amphora list --os-cloud=dev-admin --loadbalancer foo-lb1 # Show LB VM details (admin only) openstack server show amphora-<AMPHORA_ID> --os-cloud=dev-admin # Show LB port IPs LB_PORT_IDS=$(openstack loadbalancer amphora list --loadbalancer pko-lb4 -c id -f value) for LB_PORT_ID in ${LB_PORT_IDS}; do openstack port list | grep octavia-lb-vrrp-${LB_PORT_ID} done # get broken / single VM LB # find single ampora VM for LOADBALANCER_ID in $(openstack loadbalancer list -c id -f value); do if [ $(openstack loadbalancer amphora list --loadbalancer ${LOADBALANCER_ID} -f value | wc -l) -lt 2 ]; then openstack loadbalancer show ${LOADBALANCER_ID} fi done
API
curl -s -H "X-Auth-Token: $(openstack token issue -c id -f value)" -X GET http://octavia.service.i.example.com:9876/v2/lbaas/loadbalancers | jq
Generate certificate
https://github.com/openstack/octavia.git
git clone https://github.com/openstack/octavia.git -b stable/stein sed -i "s#foobar#\$(grep octavia_ca_password /etc/kolla/passwords.yml | awk '{print \$2}')#g" octavia/bin/create_certificates.sh /opt/octavia/bin/create_certificates.sh /etc/kolla/config/foo/octavia /etc/kolla/config/foo/octavia/openssl.cnf
Test: create certificate
https://docs.openstack.org/de/api-quick-start/api-quick-start.html
CERT_1=$(openstack secret store -c "Secret href" -f value --name=cert_1 -t "application/octet-stream" -e base64 --payload="$(base64 < cert.pem)") PRIV_1=$(openstack secret store -c "Secret href" -f value --name=privkey_1 -t "application/octet-stream" -e base64 --payload="$(base64 < privkey.pem)") curl -X POST -H "X-Auth-Token: ${TOKEN}" -H "Content-Type:application/json" -d "{ \"type\": \"certificate\", \"name\": \"certificate container 1\", \"secret_refs\": [ { \"name\": \"certificate\", \"secret_ref\": \"${CERT_1}\" }, { \"name\": \"private_key\", \"secret_ref\": \"${PRIV_1}\" } ] }" https://barbican.service.stage.example.com/v1/containers
Log
https://docs.openstack.org/octavia/latest/admin/log-offloading.html
http://www.panticz.de/haproxy
# HAProxy configuration files sed -i 's/notice/info/g' /var/lib/octavia/*/haproxy.cfg vi /var/lib/octavia/*/haproxy.cfg ... defaults log global mode tcp option tcplog option logasap ... # check HAproxy configuration ls /var/lib/octavia/*/haproxy.cfg | xargs -L1 haproxy -c -f # restart HAProxy #pgrep -a haproxy #/usr/sbin/haproxy -Ws -f /var/lib/octavia/12d13d89-d8e5-4c1e-bb9f-f7b8bb700a67/haproxy.cfg -f /var/lib/octavia/haproxy-default-user-group.conf -p /var/lib/octavia/12d13d89-d8e5-4c1e-bb9f-f7b8bb700a67/12d13d89-d8e5-4c1e-bb9f-f7b8bb700a67.pid -L nPBdf6NS4c5Tq3WsOcB8Lc9aFjA -sf $(cat /var/lib/octavia/12d13d89-d8e5-4c1e-bb9f-f7b8bb700a67/12d13d89-d8e5-4c1e-bb9f-f7b8bb700a67.pid) killall haproxy # watch logfile tail -f /var/log/haproxy.log
Allow user / octavia access to certificate
https://docs.mirantis.com/mcp/q4-18/mcp-deployment-guide/advanced-config/configure-octavia/example-lb-topology-tls.html
openstack acl user add -u ${USER_ID} https://barbican.service.example.com/v1/secrets/1111111-2222-3333-4444-5555555555555
Update secred / certificate
# set certificate (as admin) openstack loadbalancer listener set --default-tls-container-ref=https://barbican.service.example.com/v1/secrets/11111111-2222-3333-4444-5555555555 ${LOADBALANCER_LISTENER_ID} openstack loadbalancer listener show ${LOADBALANCER_LISTENER_ID}
Update certificate
openstack loadbalancer listener list --loadbalancer ${LB_NAME} -f json | jq -r '.[] | select(.protocol_port == 443) | .id' # broken? https://storyboard.openstack.org/#!/story/2001971 openstack loadbalancer listener set --sni-container-refs https://barbican.service.example.com/v1/secrets/999a68f0-c55e-48bc-9707-520e89a22a66 https://barbican.service.example.com/v1/secrets/7837480b-0f7e-4750-8331-2f5809ccd90b -- 53613fb4-d048-49e2-8d86-4d4f057ad911
Fake LB ping (ping only floating IP in the namespace)
LB_ID=foo-lb01-prod VIP_ADDRESS=$(openstack loadbalancer show ${LB_ID} -c vip_address -f value) FLOATING_IP_PORT=$(openstack floating ip list --fixed-ip-address ${VIP_ADDRESS} -c Port -f value) SECURITY_GROUP_ID=$(openstack port show ${FLOATING_IP_PORT} -c security_group_ids -f value) # DEBUG: show existing ingress ICMP rules openstack security group rule list --ingress --protocol icmp ${SECURITY_GROUP_ID} # allow incomming ICMP traffic openstack security group rule create --remote-ip 0.0.0.0/0 --protocol icmp --ingress ${SECURITY_GROUP_ID}
Fix deletet certificate / secret
https://bugs.launchpad.net/octavia/+bug/1852599
DB_PASS=$(grep octavia_database_password /etc/kolla/passwords.yml | cut -d " " -f2) mysql --host=db.service.i.example.com --port=3306 --database=octavia --user=octavia --password=${DB_PASS} select * from listener where load_balancer_id = 'b41c7bfb-0411-48c9-b133-6ee95c4dc20e' \G update listener set tls_certificate_id='' where load_balancer_id = 'b41c7bfb-0411-48c9-b133-6ee95c4dc20e'; delete from sni where listener_id = '894abf55-2257-469f-b102-987a90342abe'; update listener set tls_certificate_id='https://barbican.service.example.com/v1/secrets/68c2c456-eb17-43f5-a99e-57dc099046c5' where load_balancer_id = 'b41c7bfb-0411-48c9-b133-6ee95c4dc20e';
TCP listener
# tcp 80 listener openstack loadbalancer listener create --name foo-lb1-tcp-80 --protocol TCP --protocol-port 80 foo-lb1 openstack loadbalancer pool create --name foo-lb1-tcp-80-pool --lb-algorithm ROUND_ROBIN --listener foo-lb1-tcp-80 --protocol TCP #openstack loadbalancer healthmonitor create --delay 5 --max-retries 4 --timeout 10 --type TCP foo-lb1-tcp-80-pool openstack loadbalancer member create --subnet-id foo-subnet --address 10.0.1.13 --protocol-port 80 foo-lb1-tcp-80-pool # tcp 443 listener openstack loadbalancer listener create --name foo-lb1-tcp-443 --protocol TCP --protocol-port 443 foo-lb1 openstack loadbalancer pool create --name foo-lb1-tcp-443-pool --lb-algorithm ROUND_ROBIN --listener foo-lb1-tcp-443 --protocol TCP #openstack loadbalancer healthmonitor create --delay 5 --max-retries 4 --timeout 10 --type TCP foo-lb1-tcp-443-pool openstack loadbalancer member create --subnet-id foo-subnet --address 10.0.1.13 --protocol-port 443 foo-lb1-tcp-443-pool
Assign flating IP
LB_PORT_ID=$(openstack loadbalancer show pako-lb1 -c vip_port_id -f value) openstack floating ip set --port ${LB_PORT_ID} 8.9.10.11
Upgrade
https://docs.openstack.org/octavia/latest/admin/guides/upgrade.html
Octavia Policies
https://docs.openstack.org/octavia/latest/configuration/policy.html
Migrate all Octavia Amphora VM out from specific compute node
# openstack server list --all-projects --host az1-com4-prod AMPHORA_ID=amphora-xxxxx-xxxx-xxxx-xxxx-xxxxx AMPHORA_ID=${AMPHORA_ID#*-} openstack loadbalancer amphora list | grep ${AMPHORA_ID} LB_ID=$(openstack loadbalancer amphora list | grep ${AMPHORA_ID} | cut -d "|" -f3) openstack loadbalancer show ${LB_ID} openstack loadbalancer amphora list --loadbalancer ${LB_ID} echo "Failover Amphora ${AMPHORA_ID}" openstack loadbalancer amphora failover ${AMPHORA_ID} sleep 60 openstack loadbalancer amphora list --loadbalancer ${LB_ID} openstack loadbalancer show ${LB_ID}
Failover all / ERROR Octavia LoadBalancer (Amphora image update)
LB_IDS=$(openstack loadbalancer amphora list --status ERROR -c loadbalancer_id -f value | sort -u) for LB_ID in ${LB_IDS}; do echo "Failover LoadBalancer: ${LB_ID}" openstack loadbalancer failover ${LB_ID} while [[ $(openstack loadbalancer amphora list --loadbalancer ${LB_ID} -f value -c status | grep ALLOCATED | wc -l) < 2 ]]; do sleep 1; done sleep 10 openstack loadbalancer amphora list --loadbalancer ${LB_ID} done # List amphora VMs openstack server list --project service
Recreate Octavia port
openstack port create \ --network 45bb34d3-70e2-43ea-aff7-dfd7750ce68a \ --fixed-ip 'ip-address=192.168.38.221,subnet=68f2f3ca-9fab-4ac1-9b46-e8c9a078ac66' \ --device lb-84cd79db-9bd1-4490-9d3f-acdf668f00ef \ --device-owner Octavia \ --security-group lb-1dbacdba-ccf3-4319-b15a-296fcdaadce3 \ --project a772e4ab888e4f039b3430d688f4559d \ --description my-lb01-dev \ octavia-lb-1dbacdba-ccf3-4319-b15a-296fcdaadce3
Links
https://releases.openstack.org/teams/octavia.html#team-rocky-octavia
https://docs.openstack.org/python-octaviaclient/latest/cli/index.html
https://docs.openstack.org/mitaka/networking-guide/config-lbaas.html
https://docs.openstack.org/octavia/latest/user/guides/basic-cookbook.html
https://shreddedbacon.com/post/openstack-kolla/
https://access.redhat.com/documentation/en-us/red_hat_openstack_platform/13/html/networking_guide/sec-octavia
https://docs.openstack.org/octavia/latest/user/feature-classification/index.html#operation_insert_headers_X_Forwarded_For
https://github.com/openstack/octavia/blob/master/api-ref/source/v2/listener.inc
http://www.loadbalancer.org/blog/nginx-and-x-forwarded-for-header/
https://dataops.ga/2018/12/octavia/
https://docs.openstack.org/octavia/latest/admin/guides/operator-maintenance.html - rotate Amphora images
https://docs.openstack.org/releasenotes/octavia/rocky.html - available versions