Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update kube router iptables 1.8.11 #1790

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ on:
- prep-v[1-9].*

env:
BUILDTIME_BASE: "golang:1.22.3-alpine3.18"
BUILDTIME_BASE: "golang:1.23.4-alpine3.21"
# Do not bump past Alpine 3.18 until upstream netfilter problems in iptables v1.8.10 are resolved. See:
# https://github.com/cloudnativelabs/kube-router/issues/1676
RUNTIME_BASE: "alpine:3.18"
GO_VERSION: "~1.22.3"
RUNTIME_BASE: "alpine:3.21"
GO_VERSION: "~1.23.4"
GO_CACHE: "/home/runner/.cache/go-build"
GO_MOD_CACHE: "/home/runner/go/pkg/mod"

Expand Down
17 changes: 9 additions & 8 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@ run:
linters:
enable:
- bodyclose
- copyloopvar
- dogsled
- dupl
- durationcheck
- exportloopref
- exhaustive
- gochecknoinits
- goconst
- gocritic
- gofmt
- goimports
- gomnd
- gosec
- govet
- lll
- misspell
- mnd
- nakedret
- noctx
- nolintlint
Expand All @@ -35,24 +35,24 @@ issues:
# Excluding single digits from magic number detector because it produces too many obvious results (like klog)
- text: "Magic number: [0-9]{1},"
linters:
- gomnd
- mnd
# Exclude file masks from magic number detector because these numbers are obvious
- text: "Magic number: 0[0-7]{3},"
linters:
- gomnd
- mnd
# Exlude IP masks netmasks as substituting them for constants only makes these less obvious
- text: "Magic number: 255,"
linters:
- gomnd
- mnd
path: pkg/controllers/proxy/network_services_controller.go
# Exclude IP netmasks from magic number detector because these numbers are obvious
- text: "Magic number: 32,"
linters:
- gomnd
- mnd
# Exclude decimal bases from magic number detector because these numbers are obvious
- text: "Magic number: 10,"
linters:
- gomnd
- mnd
# Exclude file mask security findings as we are always intentional about the file masks we use
- text: "G306:"
linters:
Expand All @@ -70,6 +70,7 @@ issues:
# always show all issues of a type rather than showing 3
max-same-issues: 0
output:
format: tab
formats:
- format: tab
print-issued-lines: true
print-linter-name: true
2 changes: 1 addition & 1 deletion .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,4 @@ archives:
- Documentation*

snapshot:
name_template: SNAPSHOT-{{ .Commit }}
version_template: SNAPSHOT-{{ .Commit }}
7 changes: 6 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ FROM ${RUNTIME_BASE}

RUN apk add --no-cache \
iptables \
ip6tables \
iptables-legacy \
ipset \
iproute2 \
ipvsadm \
Expand All @@ -37,6 +37,11 @@ RUN apk add --no-cache \
curl -L -o /usr/local/share/bash-completion/bash-completion \
https://raw.githubusercontent.com/scop/bash-completion/master/bash_completion

COPY ./build/apks /apks

RUN apk add --allow-untrusted /apks/*.apk && \
rm -rf /apks

COPY build/image-assets/bashrc /root/.bashrc
COPY build/image-assets/profile /root/.profile
COPY build/image-assets/vimrc /root/.vimrc
Expand Down
12 changes: 6 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,22 @@ DOCKER=$(if $(or $(IN_DOCKER_GROUP),$(IS_ROOT),$(OSX)),docker,sudo docker)
MAKEFILE_DIR=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))
UPSTREAM_IMPORT_PATH=$(GOPATH)/src/github.com/cloudnativelabs/kube-router/
BUILD_IN_DOCKER?=true
DOCKER_BUILD_IMAGE?=golang:1.22.3-alpine3.18
DOCKER_BUILD_IMAGE?=golang:1.23.4-alpine3.21
## These variables are used by the Dockerfile as the bases for building and creating the runtime container
## During CI these come from .github/workflows/ci.yaml below we define for local builds as well
GO_CACHE?=$(shell go env GOCACHE)
GO_MOD_CACHE?=$(shell go env GOMODCACHE)
BUILDTIME_BASE?=$(DOCKER_BUILD_IMAGE)
# Do not bump past Alpine 3.18 until upstream netfilter problems in iptables v1.8.10 are resolved. See:
# https://github.com/cloudnativelabs/kube-router/issues/1676
RUNTIME_BASE?=alpine:3.18
DOCKER_LINT_IMAGE?=golangci/golangci-lint:v1.56.2
RUNTIME_BASE?=alpine:3.21
DOCKER_LINT_IMAGE?=golangci/golangci-lint:v1.62.2
DOCKER_MARKDOWNLINT_IMAGE?=tmknom/markdownlint:0.39.0
GOBGP_VERSION=v3.29.0
QEMU_IMAGE?=multiarch/qemu-user-static
GORELEASER_VERSION=v1.24.0
MOQ_VERSION=v0.3.4
CNI_VERSION=v1.4.0
GORELEASER_VERSION=v2.5.0
MOQ_VERSION=v0.5.1
CNI_VERSION=v1.6.1
UID?=$(shell id -u)
ifeq ($(GOARCH), arm)
ARCH_TAG_PREFIX=$(GOARCH)
Expand Down
Binary file added build/apks/APKINDEX.tar.gz
Binary file not shown.
Binary file added build/apks/iptables-1.8.11-r1.apk
Binary file not shown.
Binary file added build/apks/iptables-dev-1.8.11-r1.apk
Binary file not shown.
Binary file added build/apks/iptables-doc-1.8.11-r1.apk
Binary file not shown.
Binary file added build/apks/iptables-legacy-1.8.11-r1.apk
Binary file not shown.
Binary file added build/apks/iptables-openrc-1.8.11-r1.apk
Binary file not shown.
Binary file added build/apks/libip4tc-1.8.11-r1.apk
Binary file not shown.
Binary file added build/apks/libip6tc-1.8.11-r1.apk
Binary file not shown.
Binary file added build/apks/libipq-1.8.11-r1.apk
Binary file not shown.
Binary file added build/apks/libxtables-1.8.11-r1.apk
Binary file not shown.
2 changes: 1 addition & 1 deletion pkg/controllers/lballoc/lballoc.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func (lbc *LoadBalancerController) runLeaderElection(ctx context.Context, isLead
leaderelection.RunOrDie(ctx, leaderelection.LeaderElectionConfig{
Lock: lbc.lock,
ReleaseOnCancel: true,
LeaseDuration: 15 * time.Second, //nolint:gomnd // No reason for a 15 second constant
LeaseDuration: 15 * time.Second, //nolint:mnd // No reason for a 15 second constant
RenewDeadline: 10 * time.Second,
RetryPeriod: 2 * time.Second,
Callbacks: leaderelection.LeaderCallbacks{
Expand Down
2 changes: 0 additions & 2 deletions pkg/controllers/netpol/network_policy_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,6 @@ func (npc *NetworkPolicyController) fullPolicySync() {
}

for ipFamily, iptablesSaveRestore := range npc.iptablesSaveRestore {
ipFamily := ipFamily
restoreStart := time.Now()
err := iptablesSaveRestore.Restore("filter", npc.filterTableRules[ipFamily].Bytes())
restoreEndTime := time.Since(restoreStart)
Expand Down Expand Up @@ -855,7 +854,6 @@ func NewNetworkPolicyController(clientset kubernetes.Interface,
// Validate that ClusterIP service range type matches the configuration
if config.EnableIPv4 && !config.EnableIPv6 {
if !netutils.IsIPv4CIDR(&npc.serviceClusterIPRanges[0]) {
//nolint:goconst // we don't care about abstracting an error message
return nil, fmt.Errorf("failed to get parse --service-cluster-ip-range parameter: " +
"IPv4 is enabled but only IPv6 address is provided")
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/controllers/netpol/network_policy_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ func TestNetworkPolicyBuilder(t *testing.T) {
}
for ipFamily, filterTableRules := range krNetPol.filterTableRules {
for _, np := range netpols {
fmt.Printf(np.policyType)
fmt.Print(np.policyType)
if np.policyType == kubeEgressPolicyType || np.policyType == kubeBothPolicyType {
err = krNetPol.processEgressRules(np, "", nil, "1", ipFamily)
if err != nil {
Expand Down
1 change: 0 additions & 1 deletion pkg/controllers/netpol/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ func (npc *NetworkPolicyController) syncPodFirewallChains(networkPoliciesInfo []
for ipFamily, filterTableRules := range npc.filterTableRules {
_, err := getPodIPForFamily(pod, ipFamily)
if err != nil {
//nolint:goconst // don't need to make error messages a constant
klog.V(2).Infof("unable to get address for pod: %s -- skipping drop rules for pod "+
"(this is normal for pods that are not dual-stack)", err.Error())
continue
Expand Down
5 changes: 0 additions & 5 deletions pkg/controllers/netpol/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ func (npc *NetworkPolicyController) syncNetworkPolicyChains(networkPoliciesInfo
}

for ipFamily, ipset := range npc.ipSetHandlers {
ipFamily := ipFamily
restoreStart := time.Now()
err := ipset.Restore()
restoreEndTime := time.Since(restoreStart)
Expand Down Expand Up @@ -223,7 +222,6 @@ func (npc *NetworkPolicyController) processIngressRules(policy networkPolicyInfo
}
npc.ipSetHandlers[ipFamily].RefreshSet(namedPortIPSetName, setEntries, utils.TypeHashIP)

//nolint:goconst // don't need to make error messages a constant
comment := "rule to ACCEPT traffic from source pods to dest pods selected by policy name " +
policy.name + " namespace " + policy.namespace
if err := npc.appendRuleToPolicyChain(policyChainName, comment, srcPodIPSetName, namedPortIPSetName,
Expand All @@ -250,7 +248,6 @@ func (npc *NetworkPolicyController) processIngressRules(policy networkPolicyInfo
// with specified port (if any) and protocol
if ingressRule.matchAllSource && !ingressRule.matchAllPorts {
for _, portProtocol := range ingressRule.ports {
//nolint:goconst // don't need to make error messages a constant
comment := "rule to ACCEPT traffic from all sources to dest pods selected by policy name: " +
policy.name + " namespace " + policy.namespace
if err := npc.appendRuleToPolicyChain(policyChainName, comment, "", targetDestPodIPSetName,
Expand Down Expand Up @@ -296,7 +293,6 @@ func (npc *NetworkPolicyController) processIngressRules(policy networkPolicyInfo

if !ingressRule.matchAllPorts {
for _, portProtocol := range ingressRule.ports {
//nolint:goconst // don't need to make error messages a constant
comment := "rule to ACCEPT traffic from specified ipBlocks to dest pods selected by policy name: " +
policy.name + " namespace " + policy.namespace
if err := npc.appendRuleToPolicyChain(policyChainName, comment, srcIPBlockIPSetName,
Expand Down Expand Up @@ -407,7 +403,6 @@ func (npc *NetworkPolicyController) processEgressRules(policy networkPolicyInfo,
// with specified port (if any) and protocol
if egressRule.matchAllDestinations && !egressRule.matchAllPorts {
for _, portProtocol := range egressRule.ports {
//nolint:goconst // don't need to make error messages a constant
comment := "rule to ACCEPT traffic from source pods to all destinations selected by policy name: " +
policy.name + " namespace " + policy.namespace
if err := npc.appendRuleToPolicyChain(policyChainName, comment, targetSourcePodIPSetName,
Expand Down
33 changes: 26 additions & 7 deletions pkg/controllers/proxy/linux_networking.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,10 +265,18 @@ func (ln *linuxNetworking) ipvsAddService(svcs []*ipvs.Service, vip net.IP, prot
vip, svc.Address, protocol, svc.Protocol, port, svc.Port)
if vip.Equal(svc.Address) && protocol == svc.Protocol && port == svc.Port {
klog.V(2).Info("Service matched VIP")
ptim, err := utils.Int32ToUInt32(persistentTimeout)
if err != nil {
return svcs, nil, fmt.Errorf("failed to convert persistent timeout to uint32: %v", err)
}
if (persistent && (svc.Flags&ipvsPersistentFlagHex) == 0) ||
(!persistent && (svc.Flags&ipvsPersistentFlagHex) != 0) ||
svc.Timeout != uint32(persistentTimeout) {
ipvsSetPersistence(svc, persistent, persistentTimeout)
svc.Timeout != ptim {
err = ipvsSetPersistence(svc, persistent, persistentTimeout)
if err != nil {
return svcs, nil, fmt.Errorf("failed to set persistence for service %s due to: %v",
ipvsServiceString(svc), err)
}

err = ln.ipvsUpdateService(svc)
if err != nil {
Expand Down Expand Up @@ -323,7 +331,11 @@ func (ln *linuxNetworking) ipvsAddService(svcs []*ipvs.Service, vip net.IP, prot
Netmask: ipMask,
}

ipvsSetPersistence(&svc, persistent, persistentTimeout)
err = ipvsSetPersistence(&svc, persistent, persistentTimeout)
if err != nil {
return svcs, nil, fmt.Errorf("failed to set persistence for service %s due to: %v",
ipvsServiceString(&svc), err)
}
ipvsSetSchedFlags(&svc, flags)

klog.V(1).Infof("%s didn't match any existing IPVS services, creating a new IPVS service",
Expand Down Expand Up @@ -356,13 +368,17 @@ func (ln *linuxNetworking) ipvsAddFWMarkService(svcs []*ipvs.Service, fwMark uin
if fwMark == svc.FWMark {
if (persistent && (svc.Flags&ipvsPersistentFlagHex) == 0) ||
(!persistent && (svc.Flags&ipvsPersistentFlagHex) != 0) {
ipvsSetPersistence(svc, persistent, persistentTimeout)
err := ipvsSetPersistence(svc, persistent, persistentTimeout)
if err != nil {
return nil, fmt.Errorf("failed to set persistence for service %s due to: %v",
ipvsServiceString(svc), err)
}

if changedIpvsSchedFlags(svc, flags) {
ipvsSetSchedFlags(svc, flags)
}

err := ln.ipvsUpdateService(svc)
err = ln.ipvsUpdateService(svc)
if err != nil {
return nil, fmt.Errorf("failed to update persistence flags for service %s due to %v",
ipvsServiceString(svc), err)
Expand Down Expand Up @@ -419,10 +435,13 @@ func (ln *linuxNetworking) ipvsAddFWMarkService(svcs []*ipvs.Service, fwMark uin
SchedName: ipvs.RoundRobin,
}

ipvsSetPersistence(&svc, persistent, persistentTimeout)
err := ipvsSetPersistence(&svc, persistent, persistentTimeout)
if err != nil {
return nil, fmt.Errorf("failed to set persistence for service %s due to: %v", ipvsServiceString(&svc), err)
}
ipvsSetSchedFlags(&svc, flags)

err := ln.ipvsNewService(&svc)
err = ln.ipvsNewService(&svc)
if err != nil {
return nil, err
}
Expand Down
32 changes: 21 additions & 11 deletions pkg/controllers/proxy/network_services_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ func (nsc *NetworkServicesController) Run(healthChan chan<- *healthcheck.Control
// https://github.com/cloudnativelabs/kube-router/issues/282
err = nsc.setupIpvsFirewall()
if err != nil {
klog.Fatalf("error setting up ipvs firewall: %s" + err.Error())
klog.Fatalf("error setting up ipvs firewall: %v", err.Error())
}
nsc.ProxyFirewallSetup.Broadcast()

Expand Down Expand Up @@ -346,7 +346,7 @@ func (nsc *NetworkServicesController) Run(healthChan chan<- *healthcheck.Control
klog.V(1).Info("Performing requested full sync of services")
err = nsc.doSync()
if err != nil {
klog.Errorf("Error during full sync in network service controller. Error: " + err.Error())
klog.Errorf("error during full sync in network service controller. Error: %v", err)
}
case synctypeIpvs:
// We call the component pieces of doSync() here because for methods that send this on the channel they
Expand All @@ -356,11 +356,11 @@ func (nsc *NetworkServicesController) Run(healthChan chan<- *healthcheck.Control
nsc.mu.Lock()
err = nsc.syncIpvsServices(nsc.serviceMap, nsc.endpointsMap)
if err != nil {
klog.Errorf("Error during ipvs sync in network service controller. Error: " + err.Error())
klog.Errorf("error during ipvs sync in network service controller. Error: %v", err)
}
err = nsc.syncHairpinIptablesRules()
if err != nil {
klog.Errorf("Error syncing hairpin iptables rules: %s", err.Error())
klog.Errorf("error syncing hairpin iptables rules: %v", err)
}
nsc.mu.Unlock()
}
Expand All @@ -373,7 +373,7 @@ func (nsc *NetworkServicesController) Run(healthChan chan<- *healthcheck.Control
healthcheck.SendHeartBeat(healthChan, healthcheck.NetworkServicesController)
err := nsc.doSync()
if err != nil {
klog.Errorf("Error during periodic ipvs sync in network service controller. Error: " + err.Error())
klog.Errorf("error during periodic ipvs sync in network service controller. Error: %v", err.Error())
klog.Errorf("Skipping sending heartbeat from network service controller as periodic sync failed.")
} else {
healthcheck.SendHeartBeat(healthChan, healthcheck.NetworkServicesController)
Expand Down Expand Up @@ -581,7 +581,6 @@ func (nsc *NetworkServicesController) cleanupIpvsFirewall() {
}

for _, ipSetName := range []string{localIPsIPSetName, serviceIPsIPSetName, serviceIPPortsSetName} {
ipSetName := ipSetName
if _, ok := ipSetHandler.Sets()[ipSetName]; ok {
err = ipSetHandler.Destroy(ipSetName)
if err != nil {
Expand Down Expand Up @@ -731,16 +730,20 @@ func (nsc *NetworkServicesController) publishMetrics(serviceInfoMap serviceInfoM
protocol = convertSvcProtoToSysCallProto(svc.protocol)
for _, ipvsSvc := range ipvsSvcs {

uPort, err := utils.IntToUInt16(svc.port)
if err != nil {
klog.Errorf("failed to convert port %d to uint16: %v", svc.port, err)
}
switch svcAddress := ipvsSvc.Address.String(); svcAddress {
case svc.clusterIP.String():
if protocol == ipvsSvc.Protocol && uint16(svc.port) == ipvsSvc.Port {
if protocol == ipvsSvc.Protocol && uPort == ipvsSvc.Port {
pushMetric = true
svcVip = svc.clusterIP.String()
} else {
pushMetric = false
}
case nsc.krNode.GetPrimaryNodeIP().String():
if protocol == ipvsSvc.Protocol && uint16(svc.port) == ipvsSvc.Port {
if protocol == ipvsSvc.Protocol && uPort == ipvsSvc.Port {
pushMetric = true
svcVip = nsc.krNode.GetPrimaryNodeIP().String()
} else {
Expand Down Expand Up @@ -1541,14 +1544,21 @@ func ipvsDestinationString(d *ipvs.Destination) string {
return fmt.Sprintf("%s:%v (Family: %s, Weight: %v)", d.Address, d.Port, family, d.Weight)
}

func ipvsSetPersistence(svc *ipvs.Service, p bool, timeout int32) {
func ipvsSetPersistence(svc *ipvs.Service, p bool, timeout int32) error {
if p {
uTimeout, err := utils.Int32ToUInt32(timeout)
if err != nil {
return fmt.Errorf("failed to convert timeout to uint32: %v", err)
}

svc.Flags |= ipvsPersistentFlagHex
svc.Timeout = uint32(timeout)
svc.Timeout = uTimeout
} else {
svc.Flags &^= ipvsPersistentFlagHex
svc.Timeout = 0
}

return nil
}

func ipvsSetSchedFlags(svc *ipvs.Service, s schedFlags) {
Expand Down Expand Up @@ -1811,7 +1821,7 @@ func (nsc *NetworkServicesController) Cleanup() {
} else {
err = netlink.LinkDel(dummyVipInterface)
if err != nil {
klog.Errorf("Could not delete dummy interface " + KubeDummyIf + " due to " + err.Error())
klog.Errorf("could not delete dummy interface %s due to: %v", KubeDummyIf, err.Error())
return
}
}
Expand Down
Loading
Loading