@@ -28,8 +28,10 @@ import (
28
28
"crypto/sha256"
29
29
"encoding/base32"
30
30
"fmt"
31
+ "golang.org/x/time/rate"
31
32
"net"
32
33
"os"
34
+ "os/exec"
33
35
"reflect"
34
36
"strconv"
35
37
"strings"
@@ -193,7 +195,8 @@ type Proxier struct {
193
195
// which proxier is operating on, can be directly consumed by knftables.
194
196
serviceCIDRs string
195
197
196
- logger klog.Logger
198
+ logger klog.Logger
199
+ logRateLimiter * rate.Limiter
197
200
198
201
clusterIPs * nftElementStorage
199
202
serviceIPs * nftElementStorage
@@ -266,6 +269,7 @@ func NewProxier(ctx context.Context,
266
269
networkInterfacer : proxyutil.RealNetwork {},
267
270
staleChains : make (map [string ]time.Time ),
268
271
logger : logger ,
272
+ logRateLimiter : rate .NewLimiter (rate .Every (24 * time .Hour ), 1 ),
269
273
clusterIPs : newNFTElementStorage ("set" , clusterIPsSet ),
270
274
serviceIPs : newNFTElementStorage ("map" , serviceIPsMap ),
271
275
firewallIPs : newNFTElementStorage ("map" , firewallIPsMap ),
@@ -1136,6 +1140,21 @@ func (s *nftElementStorage) cleanupLeftoverKeys(tx *knftables.Transaction) {
1136
1140
s .resetLeftoverKeys ()
1137
1141
}
1138
1142
1143
+ // logFailure logs the transaction and the full table with a rate limit.
1144
+ func (proxier * Proxier ) logFailure (tx * knftables.Transaction ) {
1145
+ if klogV4 := klog .V (4 ); klogV4 .Enabled () && proxier .logRateLimiter .Allow () {
1146
+ klogV4 .InfoS ("Failed transaction" , "transaction" , tx .String ())
1147
+ // knftables doesn't supporting listing the full table yet, this is a workaround.
1148
+ cmd := exec .Command ("nft" , "list" , "table" , kubeProxyTable )
1149
+ out , err := cmd .Output ()
1150
+ if err != nil {
1151
+ klogV4 .InfoS ("Listing full table failed" , "error" , err )
1152
+ } else {
1153
+ klogV4 .InfoS ("Listing full table" , "result" , string (out ))
1154
+ }
1155
+ }
1156
+ }
1157
+
1139
1158
// This is where all of the nftables calls happen.
1140
1159
// This assumes proxier.mu is NOT held
1141
1160
func (proxier * Proxier ) syncProxyRules () {
@@ -1209,6 +1228,10 @@ func (proxier *Proxier) syncProxyRules() {
1209
1228
// (with a later timestamp) at the end of the sync.
1210
1229
proxier .logger .Error (err , "Unable to delete stale chains; will retry later" )
1211
1230
metrics .NFTablesCleanupFailuresTotal .WithLabelValues (string (proxier .ipFamily )).Inc ()
1231
+ tryPartialSync = false
1232
+
1233
+ // Log failed transaction and list full kube-proxy table.
1234
+ proxier .logFailure (tx )
1212
1235
}
1213
1236
}
1214
1237
}
@@ -1808,6 +1831,8 @@ func (proxier *Proxier) syncProxyRules() {
1808
1831
// staleChains is now incorrect since we didn't actually flush the
1809
1832
// chains in it. We can recompute it next time.
1810
1833
clear (proxier .staleChains )
1834
+ // Log failed transaction and list full kube-proxy table.
1835
+ proxier .logFailure (tx )
1811
1836
return
1812
1837
}
1813
1838
success = true
0 commit comments