Merge ~hloeung/content-cache-charm:sysctl into content-cache-charm:master

Proposed by Haw Loeung
Status: Merged
Approved by: Paul Collins
Approved revision: 7f4095920d44de7283d3b076efff7a01a630073d
Merged at revision: f471a5fc678ccc5ca10b71e3465c3785368161a0
Proposed branch: ~hloeung/content-cache-charm:sysctl
Merge into: content-cache-charm:master
Diff against target: 287 lines (+122/-6)
7 files modified
config.yaml (+6/-1)
reactive/content_cache.py (+4/-0)
templates/sysctl_conf.tmpl (+3/-0)
tests/unit/files/sysctl.conf (+2/-0)
tests/unit/files/sysctl_nf_conntrack_max.conf (+23/-0)
tests/unit/files/sysctl_nf_conntrack_max_none.conf (+21/-0)
tests/unit/test_content_cache.py (+63/-5)
Reviewer Review Type Date Requested Status
Paul Collins lgtm Approve
Canonical IS Reviewers Pending
Review via email: mp+451489@code.launchpad.net

Commit message

Allow overriding Netfilter conntrack_max - LP:1860631

To post a comment you must log in.
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

This merge proposal is being monitored by mergebot. Change the status to Approved to merge.

Revision history for this message
Paul Collins (pjdc) :
review: Approve (lgtm)
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

Change successfully merged at revision f471a5fc678ccc5ca10b71e3465c3785368161a0

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/config.yaml b/config.yaml
2index 0b1f80f..47d9761 100644
3--- a/config.yaml
4+++ b/config.yaml
5@@ -148,9 +148,14 @@ options:
6 type: string
7 description: >
8 Override default ciphers used for TLS/SSL termination (OpenSSL format).
9+ tune_nf_conntrack_max:
10+ default: 0
11+ type: int
12+ description: >
13+ Tune or set net.nf_conntrack_max. Set to 0 to disable.
14 tune_tcp_mem_multiplier:
15- type: float
16 default: 1.5
17+ type: float
18 description: >
19 Tune net.ipv4.tcp_mem, apply multiplier.
20 worker_connections:
21diff --git a/reactive/content_cache.py b/reactive/content_cache.py
22index b090311..bc51c18 100644
23--- a/reactive/content_cache.py
24+++ b/reactive/content_cache.py
25@@ -518,6 +518,7 @@ def configure_nagios():
26
27
28 _SYSCTL_CORE_DEFAULT_QDISC = '/proc/sys/net/core/default_qdisc'
29+_SYSCTL_NETFILTER_CONNTRACK_MAX = '/proc/sys/net/nf_conntrack_max'
30
31
32 @reactive.when_not('content_cache.sysctl.configured')
33@@ -536,6 +537,9 @@ def configure_sysctl():
34 context['net_ipv4_tcp_congestion_control'] = utils.select_tcp_congestion_control(preferred_tcp_cc)
35 context['net_ipv4_tcp_mem'] = utils.tune_tcp_mem(config['tune_tcp_mem_multiplier'])
36
37+ if os.path.exists(_SYSCTL_NETFILTER_CONNTRACK_MAX):
38+ context['net_nf_conntrack_max'] = config['tune_nf_conntrack_max']
39+
40 # Set or lower tcp_notsent_lowat to optimise HTTP/2 prioritisation.
41 # https://blog.cloudflare.com/http-2-prioritization-with-nginx/
42 context['net_ipv4_tcp_notsent_lowat'] = '16384'
43diff --git a/templates/sysctl_conf.tmpl b/templates/sysctl_conf.tmpl
44index 60395f3..316a34d 100644
45--- a/templates/sysctl_conf.tmpl
46+++ b/templates/sysctl_conf.tmpl
47@@ -11,6 +11,9 @@ net.core.default_qdisc = {{ net_core_default_qdisc }}
48 {% if net_ipv4_tcp_mem %}
49 # Tune TCP memory
50 net.ipv4.tcp_mem = {{ net_ipv4_tcp_mem }}
51+{% endif -%}
52+{% if net_nf_conntrack_max and net_nf_conntrack_max > 0 %}
53+net.nf_conntrack_max = {{ net_nf_conntrack_max }}
54 {% endif %}
55
56 # Tune the TCP stack for Fast Failure Detection
57diff --git a/tests/unit/files/sysctl.conf b/tests/unit/files/sysctl.conf
58index 399a1bc..f64dbb8 100644
59--- a/tests/unit/files/sysctl.conf
60+++ b/tests/unit/files/sysctl.conf
61@@ -6,6 +6,8 @@ net.core.default_qdisc = fq
62 # Tune TCP memory
63 net.ipv4.tcp_mem = 92430 123242 184860
64
65+net.nf_conntrack_max = 2097152
66+
67
68 # Tune the TCP stack for Fast Failure Detection
69 # tcp_syn_retries set to 1, it takes ~9secs to timeout
70diff --git a/tests/unit/files/sysctl_nf_conntrack_max.conf b/tests/unit/files/sysctl_nf_conntrack_max.conf
71new file mode 100644
72index 0000000..130ce57
73--- /dev/null
74+++ b/tests/unit/files/sysctl_nf_conntrack_max.conf
75@@ -0,0 +1,23 @@
76+net.ipv4.tcp_notsent_lowat = 16384
77+
78+net.nf_conntrack_max = 2097152
79+
80+
81+# Tune the TCP stack for Fast Failure Detection
82+# tcp_syn_retries set to 1, it takes ~9secs to timeout
83+# tcp_syn_retries set to 2, it takes ~21secs to timeout
84+# tcp_syn_retries set to 3, it takes ~45secs to timeout
85+# tcp_syn_retries set to 4, it takes ~93secs to timeout
86+# tcp_syn_retries set to 5, it takes ~189secs to timeout (default)
87+# Reduce TCP connection timeouts to ~45 secs.
88+net.ipv4.tcp_syn_retries = 3
89+net.ipv4.tcp_synack_retries = 3
90+
91+# Reduce TCP KeepAlive timeout from 2 hrs to 30 mins.
92+net.ipv4.tcp_keepalive_time = 1800
93+
94+# Extend the source port range for outgoing TCP connections.
95+net.ipv4.ip_local_port_range = 16384 61000
96+
97+# Allow early reuse of a same source port for outgoing connections.
98+net.ipv4.tcp_tw_reuse = 1
99diff --git a/tests/unit/files/sysctl_nf_conntrack_max_none.conf b/tests/unit/files/sysctl_nf_conntrack_max_none.conf
100new file mode 100644
101index 0000000..1c7cccc
102--- /dev/null
103+++ b/tests/unit/files/sysctl_nf_conntrack_max_none.conf
104@@ -0,0 +1,21 @@
105+net.ipv4.tcp_notsent_lowat = 16384
106+
107+
108+# Tune the TCP stack for Fast Failure Detection
109+# tcp_syn_retries set to 1, it takes ~9secs to timeout
110+# tcp_syn_retries set to 2, it takes ~21secs to timeout
111+# tcp_syn_retries set to 3, it takes ~45secs to timeout
112+# tcp_syn_retries set to 4, it takes ~93secs to timeout
113+# tcp_syn_retries set to 5, it takes ~189secs to timeout (default)
114+# Reduce TCP connection timeouts to ~45 secs.
115+net.ipv4.tcp_syn_retries = 3
116+net.ipv4.tcp_synack_retries = 3
117+
118+# Reduce TCP KeepAlive timeout from 2 hrs to 30 mins.
119+net.ipv4.tcp_keepalive_time = 1800
120+
121+# Extend the source port range for outgoing TCP connections.
122+net.ipv4.ip_local_port_range = 16384 61000
123+
124+# Allow early reuse of a same source port for outgoing connections.
125+net.ipv4.tcp_tw_reuse = 1
126diff --git a/tests/unit/test_content_cache.py b/tests/unit/test_content_cache.py
127index 8ea2f21..789b411 100644
128--- a/tests/unit/test_content_cache.py
129+++ b/tests/unit/test_content_cache.py
130@@ -1474,6 +1474,7 @@ site1.local:
131 'reactive.content_cache',
132 SYSCTL_CONF_PATH=sysctl_conf_path,
133 _SYSCTL_CORE_DEFAULT_QDISC='some-file-does-not-exist',
134+ _SYSCTL_NETFILTER_CONNTRACK_MAX='some-file-does-not-exist',
135 ):
136 content_cache.configure_sysctl()
137 # Check contents
138@@ -1497,7 +1498,10 @@ site1.local:
139 @mock.patch('lib.utils.tune_tcp_mem')
140 def test_configure_sysctl_all(self, tune_tcp_mem, tcp_cc, process_rlimits, call, set_flag):
141 sysctl_conf_path = os.path.join(self.tmpdir, '90-content-cache.conf')
142- self.mock_config.return_value = {'tune_tcp_mem_multiplier': 1.5}
143+ self.mock_config.return_value = {
144+ 'tune_nf_conntrack_max': 2097152,
145+ 'tune_tcp_mem_multiplier': 1.5,
146+ }
147 process_rlimits.return_value = '1048777'
148
149 # Test with all 3, qdisc, tcp_congestion_control, and tcp_mem
150@@ -1505,11 +1509,13 @@ site1.local:
151 tcp_cc.return_value = 'bbr'
152 # Use '/proc/uptime' for unit test as that will always exist.
153 qdisc_path = '/proc/uptime'
154+ conntrack_max_path = '/proc/uptime'
155
156 with mock.patch.multiple(
157 'reactive.content_cache',
158 SYSCTL_CONF_PATH=sysctl_conf_path,
159 _SYSCTL_CORE_DEFAULT_QDISC=qdisc_path,
160+ _SYSCTL_NETFILTER_CONNTRACK_MAX=conntrack_max_path,
161 ):
162 content_cache.configure_sysctl()
163 with open('tests/unit/files/sysctl.conf', 'r') as f:
164@@ -1536,6 +1542,7 @@ site1.local:
165 'reactive.content_cache',
166 SYSCTL_CONF_PATH=sysctl_conf_path,
167 _SYSCTL_CORE_DEFAULT_QDISC=qdisc_path,
168+ _SYSCTL_NETFILTER_CONNTRACK_MAX='some-file-does-not-exist',
169 ):
170 content_cache.configure_sysctl()
171 with open('tests/unit/files/sysctl_core_default_qdisc.conf', 'r') as f:
172@@ -1549,6 +1556,7 @@ site1.local:
173 'reactive.content_cache',
174 SYSCTL_CONF_PATH=sysctl_conf_path,
175 _SYSCTL_CORE_DEFAULT_QDISC=qdisc_path,
176+ _SYSCTL_NETFILTER_CONNTRACK_MAX='some-file-does-not-exist',
177 ):
178 content_cache.configure_sysctl()
179 with open('tests/unit/files/sysctl_core_default_qdisc_none.conf', 'r') as f:
180@@ -1562,6 +1570,53 @@ site1.local:
181 @mock.patch('lib.utils.process_rlimits')
182 @mock.patch('lib.utils.select_tcp_congestion_control')
183 @mock.patch('lib.utils.tune_tcp_mem')
184+ def test_configure_sysctl_nf_conntrack_max(self, tune_tcp_mem, tcp_cc, process_rlimits, call, set_flag):
185+ sysctl_conf_path = os.path.join(self.tmpdir, '90-content-cache.conf')
186+ self.mock_config.return_value = {
187+ 'tune_nf_conntrack_max': 2097152,
188+ 'tune_tcp_mem_multiplier': 1.5,
189+ }
190+ process_rlimits.return_value = '1048777'
191+ tcp_cc.return_value = None
192+ tune_tcp_mem.return_value = None
193+ # Use '/proc/uptime' for unit test as that will always exist.
194+ conntrack_max_path = '/proc/uptime'
195+
196+ with mock.patch.multiple(
197+ 'reactive.content_cache',
198+ SYSCTL_CONF_PATH=sysctl_conf_path,
199+ _SYSCTL_CORE_DEFAULT_QDISC='some-file-does-not-exist',
200+ _SYSCTL_NETFILTER_CONNTRACK_MAX=conntrack_max_path,
201+ ):
202+ content_cache.configure_sysctl()
203+ with open('tests/unit/files/sysctl_nf_conntrack_max.conf', 'r') as f:
204+ want = f.read()
205+ with open(sysctl_conf_path, 'r') as f:
206+ got = f.read()
207+ self.assertEqual(got, want)
208+
209+ self.mock_config.return_value = {
210+ 'tune_nf_conntrack_max': 0,
211+ 'tune_tcp_mem_multiplier': 1.5,
212+ }
213+ with mock.patch.multiple(
214+ 'reactive.content_cache',
215+ SYSCTL_CONF_PATH=sysctl_conf_path,
216+ _SYSCTL_CORE_DEFAULT_QDISC='some-file-does-not-exist',
217+ _SYSCTL_NETFILTER_CONNTRACK_MAX=conntrack_max_path,
218+ ):
219+ content_cache.configure_sysctl()
220+ with open('tests/unit/files/sysctl_nf_conntrack_max_none.conf', 'r') as f:
221+ want = f.read()
222+ with open(sysctl_conf_path, 'r') as f:
223+ got = f.read()
224+ self.assertEqual(got, want)
225+
226+ @mock.patch('charms.reactive.set_flag')
227+ @mock.patch('subprocess.call')
228+ @mock.patch('lib.utils.process_rlimits')
229+ @mock.patch('lib.utils.select_tcp_congestion_control')
230+ @mock.patch('lib.utils.tune_tcp_mem')
231 def test_configure_sysctl_tcp_congestion_control(self, tune_tcp_mem, tcp_cc, process_rlimits, call, set_flag):
232 sysctl_conf_path = os.path.join(self.tmpdir, '90-content-cache.conf')
233 self.mock_config.return_value = {'tune_tcp_mem_multiplier': 1.5}
234@@ -1574,6 +1629,7 @@ site1.local:
235 'reactive.content_cache',
236 SYSCTL_CONF_PATH=sysctl_conf_path,
237 _SYSCTL_CORE_DEFAULT_QDISC=qdisc_path,
238+ _SYSCTL_NETFILTER_CONNTRACK_MAX='some-file-does-not-exist',
239 ):
240 content_cache.configure_sysctl()
241 with open('tests/unit/files/sysctl_net_tcp_congestion_control.conf', 'r') as f:
242@@ -1587,6 +1643,7 @@ site1.local:
243 'reactive.content_cache',
244 SYSCTL_CONF_PATH=sysctl_conf_path,
245 _SYSCTL_CORE_DEFAULT_QDISC=qdisc_path,
246+ _SYSCTL_NETFILTER_CONNTRACK_MAX='some-file-does-not-exist',
247 ):
248 content_cache.configure_sysctl()
249 with open('tests/unit/files/sysctl_net_tcp_congestion_control_bbr2.conf', 'r') as f:
250@@ -1600,6 +1657,7 @@ site1.local:
251 'reactive.content_cache',
252 SYSCTL_CONF_PATH=sysctl_conf_path,
253 _SYSCTL_CORE_DEFAULT_QDISC=qdisc_path,
254+ _SYSCTL_NETFILTER_CONNTRACK_MAX='some-file-does-not-exist',
255 ):
256 content_cache.configure_sysctl()
257 with open('tests/unit/files/sysctl_net_tcp_congestion_control_no_bbr.conf', 'r') as f:
258@@ -1618,13 +1676,13 @@ site1.local:
259 self.mock_config.return_value = {'tune_tcp_mem_multiplier': 1.5}
260 tcp_cc.return_value = None
261 process_rlimits.return_value = '1048777'
262- qdisc_path = 'some-file-does-not-exist'
263
264 tune_tcp_mem.return_value = '188081 250774 376162'
265 with mock.patch.multiple(
266 'reactive.content_cache',
267 SYSCTL_CONF_PATH=sysctl_conf_path,
268- _SYSCTL_CORE_DEFAULT_QDISC=qdisc_path,
269+ _SYSCTL_CORE_DEFAULT_QDISC='some-file-does-not-exist',
270+ _SYSCTL_NETFILTER_CONNTRACK_MAX='some-file-does-not-exist',
271 ):
272 content_cache.configure_sysctl()
273 with open('tests/unit/files/sysctl_net_tcp_mem.conf', 'r') as f:
274@@ -1634,11 +1692,11 @@ site1.local:
275 self.assertEqual(got, want)
276
277 tune_tcp_mem.return_value = None
278- qdisc_path = 'some-file-does-not-exist'
279 with mock.patch.multiple(
280 'reactive.content_cache',
281 SYSCTL_CONF_PATH=sysctl_conf_path,
282- _SYSCTL_CORE_DEFAULT_QDISC=qdisc_path,
283+ _SYSCTL_CORE_DEFAULT_QDISC='some-file-does-not-exist',
284+ _SYSCTL_NETFILTER_CONNTRACK_MAX='some-file-does-not-exist',
285 ):
286 content_cache.configure_sysctl()
287 with open('tests/unit/files/sysctl_net_tcp_mem_none.conf', 'r') as f:

Subscribers

People subscribed via source and target branches