Q:

Why the rules I create in the iptables OUTPUT chain are deleted after a while?

I have a robot on local server that has the task of creating rules a number of times per day on remote server.The purpose of the robot is to calculate the traffic consumed by each port. Access to the remote server is via SSH and the robot is written in Python. The operating system of both servers is Ubuntu.
The rules that bot created:
sudo iptables -I OUTPUT -p tcp --sport port_number -j DROP
sudo iptables -I OUTPUT -p tcp --sport port_number -m quota --quota 500000000 -j ACCEPT
iptables -nvL OUTPUT --line-numbers|grep "\<tcp spt:port\>"

At that moment I check the remote server
iptables -nvL OUTPUT --line-numbers

Okay the rules are created.
But after a while (2 or 3 hours) the rules are deleted.
All the rules that the robot is allowed to make are listed above.
None of the rules can not clear or flush the OUTPUT chain.
Clearing rules causes the script to run poorly and cannot control the bandwidth of each port.
Now I realize the robot execute below command every few hours
firewall-cmd --reload

This command removes the rules. How can I reload the firewall and prevent rules from being deleted?

A:

The fact that running firewall-cmd --reload removes the manually added rules indicates your system is running firewalld. It is a management system for IPTables firewall (and its future replacement nftables). 
Since your robot is manipulating IPTables directly instead of telling firewalld what it wants done, firewalld will override the directly-added settings and reset all the IPtables settings according to what firewalld's configuration says they should be.
You should replace any iptables commands that make changes to firewall settings with the equivalent firewall-cmd commands. Viewing the existing firewall settings with iptables -nvL can probably be kept as-is.
The line
iptables -nvL OUTPUT --line-numbers|grep "\<tcp spt:port\>"

will not create any rules, it just displays the contents of the OUTPUT table with line numbers included, and filters out any lines that won't include the string "".
sudo iptables -I OUTPUT -p tcp --sport port_number -j DROP
sudo iptables -I OUTPUT -p tcp --sport port_number -m quota --quota 500000000 -j ACCEPT

Since both of these commands prepend the new rule to any existing rules, the result of these two commands will be two rules in this order:
1.) on output, any IPv4 TCP traffic originating from port_number will have a quota of 500000000 applied to it, and accepted only if the quota allows it
2.) if the quota did not cause the previously-mentioned traffic to be accepted, it will be dropped.
To replicate this exactly with firewall-cmd, it seems you'll have to use direct rules:
firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 0 -p tcp --sport port_number -m quota --quota 500000000 -j ACCEPT
firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 1 -p tcp --sport port_number -j DROP
firewall-cmd --reload

The first two commands will record the new rules to the permanent firewalld configuration, and the third command makes the new configuration effective.
Note that you'll have to use the priority numbers to specify the intended ordering of direct rules, otherwise the proper ordering will not be guaranteed. Also, your bot cannot just keep inserting new pairs of rules to the beginning of the chain, making the chain longer and longer.
I'll have to ask: what is the purpose of the periodic firewall-cmd --reload executed by your bot? It may be resetting the quota counter, as it causes all the rules to be reloaded. (I guess this may be precisely why your bot is doing this, but if you need the quota counter values for e.g. statistics, make sure the old values are read and stored somewhere before this command is executed.)

