Skip to content

Commit 0a9cb64

Browse files
authored
Merge pull request #345 from Till0196/support-nftables
Add nftables support for egress NAT functionality
2 parents d801193 + 4a70e68 commit 0a9cb64

File tree

22 files changed

+861
-144
lines changed

22 files changed

+861
-144
lines changed

.github/workflows/ci.yaml

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ jobs:
4848
ipv4: ["false", "true"]
4949
ipv6: ["false", "true"]
5050
ipv6-primary: ["false", "true"]
51+
backend: ["iptables", "nftables"]
5152
exclude:
5253
- ipv4: "false"
5354
ipv6: "false"
@@ -57,6 +58,8 @@ jobs:
5758
- ipv4: "true"
5859
ipv6: "false"
5960
ipv6-primary: "true"
61+
- with-ipam: "true"
62+
backend: "nftables"
6063
runs-on: ubuntu-24.04
6164
steps:
6265
- uses: actions/checkout@v4
@@ -85,13 +88,22 @@ jobs:
8588
if: matrix.with-ipam == 'true'
8689
working-directory: v2/e2e
8790
- run: make install-coil-egress-v4
88-
if: matrix.with-ipam == 'false' && matrix.ipv4 == 'true' && matrix.ipv6 == 'false'
91+
if: matrix.with-ipam == 'false' && matrix.ipv4 == 'true' && matrix.ipv6 == 'false' && matrix.backend == 'iptables'
92+
working-directory: v2/e2e
93+
- run: make install-coil-egress-v4-nft
94+
if: matrix.with-ipam == 'false' && matrix.ipv4 == 'true' && matrix.ipv6 == 'false' && matrix.backend == 'nftables'
8995
working-directory: v2/e2e
9096
- run: make install-coil-egress-v6
91-
if: matrix.with-ipam == 'false' && matrix.ipv4 == 'false' && matrix.ipv6 == 'true'
97+
if: matrix.with-ipam == 'false' && matrix.ipv4 == 'false' && matrix.ipv6 == 'true' && matrix.backend == 'iptables'
98+
working-directory: v2/e2e
99+
- run: make install-coil-egress-v6-nft
100+
if: matrix.with-ipam == 'false' && matrix.ipv4 == 'false' && matrix.ipv6 == 'true' && matrix.backend == 'nftables'
92101
working-directory: v2/e2e
93102
- run: make install-coil-egress-dualstack
94-
if: matrix.with-ipam == 'false' && matrix.ipv4 == 'true' && matrix.ipv6 == 'true'
103+
if: matrix.with-ipam == 'false' && matrix.ipv4 == 'true' && matrix.ipv6 == 'true' && matrix.backend == 'iptables'
104+
working-directory: v2/e2e
105+
- run: make install-coil-egress-dualstack-nft
106+
if: matrix.with-ipam == 'false' && matrix.ipv4 == 'true' && matrix.ipv6 == 'true' && matrix.backend == 'nftables'
95107
working-directory: v2/e2e
96108
- run: make test TEST_IPAM=${{ matrix.with-ipam }} TEST_EGRESS=true TEST_IPV4=${{ matrix.ipv4 }} TEST_IPV6=${{ matrix.ipv6 }}
97109
working-directory: v2/e2e
@@ -101,7 +113,7 @@ jobs:
101113
- uses: actions/upload-artifact@v4
102114
if: always()
103115
with:
104-
name: logs-ipv4-${{ matrix.ipv4 }}-ipv6-${{ matrix.ipv6 }}-with-ipam-${{ matrix.with-ipam }}-ipv6-primary-${{ matrix.ipv6-primary }}-${{ matrix.kindest-node }}.tar.gz
116+
name: logs-ipv4-${{ matrix.ipv4 }}-ipv6-${{ matrix.ipv6 }}-with-ipam-${{ matrix.with-ipam }}-ipv6-primary-${{ matrix.ipv6-primary }}-backend-${{ matrix.backend }}-${{ matrix.kindest-node }}.tar.gz
105117
path: v2/e2e/logs.tar.gz
106118
certs-generation:
107119
name: Cert generation test

v2/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ FROM --platform=$TARGETPLATFORM ghcr.io/cybozu/ubuntu:24.04
1313
LABEL org.opencontainers.image.source https://github.com/cybozu-go/coil
1414

1515
RUN apt-get update \
16-
&& apt-get install -y --no-install-recommends netbase kmod iptables iproute2 conntrack \
16+
&& apt-get install -y --no-install-recommends netbase kmod iptables nftables iproute2 conntrack \
1717
&& rm -rf /var/lib/apt/lists/*
1818

1919
COPY --from=build-env /workdir/work /usr/local/coil

v2/cmd/coil-egress-controller/sub/root.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ var config struct {
1818
webhookAddr string
1919
certDir string
2020
egressPort int32
21+
backend string
2122
zapOpts zap.Options
2223

2324
enableCertRotation bool
@@ -29,6 +30,13 @@ var rootCmd = &cobra.Command{
2930
Short: "controller for coil egress related custom resources",
3031
Long: `coil-egress-controller is a Kubernetes controller for coil egress related custom resources.`,
3132
Version: v2.Version(),
33+
PreRunE: func(cmd *cobra.Command, args []string) error {
34+
if config.backend != constants.BackendIPTables && config.backend != constants.BackendNFTables {
35+
return fmt.Errorf("invalid backend: %s (must be either %s or %s)",
36+
config.backend, constants.BackendIPTables, constants.BackendNFTables)
37+
}
38+
return nil
39+
},
3240
RunE: func(cmd *cobra.Command, _ []string) error {
3341
cmd.SilenceUsage = true
3442
return subMain()
@@ -51,6 +59,7 @@ func init() {
5159
pf.StringVar(&config.webhookAddr, "webhook-addr", ":9444", "bind address of admission webhook")
5260
pf.StringVar(&config.certDir, "cert-dir", "/certs", "directory to locate TLS certs for webhook")
5361
pf.Int32Var(&config.egressPort, "egress-port", 5555, "UDP port number used by coil-egress")
62+
pf.StringVar(&config.backend, "backend", constants.DefaultBackend, "Backend for egress NAT rules: iptables or nftables (default: iptables)")
5463
pf.BoolVar(&config.enableCertRotation, "enable-cert-rotation", constants.DefaultEnableCertRotation, "enables webhook's certificate generation")
5564
pf.BoolVar(&config.enableRestartOnCertRefresh, "enable-restart-on-cert-refresh", constants.DefaultEnableRestartOnCertRefresh, "enables pod's restart on webhook certificate refresh")
5665

v2/cmd/coil-egress-controller/sub/run.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,18 @@ func setupManager(mgr ctrl.Manager, certCompleted chan struct{}) error {
121121
if err != nil {
122122
return err
123123
}
124+
125+
backend := config.backend
126+
if backend == "" {
127+
backend = constants.DefaultBackend
128+
}
129+
124130
egressctrl := controllers.EgressReconciler{
125-
Client: mgr.GetClient(),
126-
Scheme: scheme,
127-
Image: img,
128-
Port: config.egressPort,
131+
Client: mgr.GetClient(),
132+
Scheme: scheme,
133+
Image: img,
134+
Port: config.egressPort,
135+
Backend: backend,
129136
}
130137
if err := egressctrl.SetupWithManager(mgr); err != nil {
131138
return err

v2/cmd/coil-egress/sub/root.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"os"
77

88
v2 "github.com/cybozu-go/coil/v2"
9+
"github.com/cybozu-go/coil/v2/pkg/constants"
910
"github.com/spf13/cobra"
1011
"k8s.io/klog/v2"
1112
"sigs.k8s.io/controller-runtime/pkg/log/zap"
@@ -16,6 +17,7 @@ var config struct {
1617
healthAddr string
1718
port int
1819
enableSportAuto bool
20+
backend string
1921
zapOpts zap.Options
2022
}
2123

@@ -24,6 +26,13 @@ var rootCmd = &cobra.Command{
2426
Short: "manage foo-over-udp tunnels in egress pods",
2527
Long: `coil-egress manages Foo-over-UDP tunnels in pods created by Egress.`,
2628
Version: v2.Version(),
29+
PreRunE: func(cmd *cobra.Command, args []string) error {
30+
if config.backend != constants.BackendIPTables && config.backend != constants.BackendNFTables {
31+
return fmt.Errorf("invalid backend: %s (must be either %s or %s)",
32+
config.backend, constants.BackendIPTables, constants.BackendNFTables)
33+
}
34+
return nil
35+
},
2736
RunE: func(cmd *cobra.Command, _ []string) error {
2837
cmd.SilenceUsage = true
2938
return subMain()
@@ -45,6 +54,7 @@ func init() {
4554
pf.StringVar(&config.healthAddr, "health-addr", ":8081", "bind address of health/readiness probes")
4655
pf.IntVar(&config.port, "fou-port", 5555, "port number for foo-over-udp tunnels")
4756
pf.BoolVar(&config.enableSportAuto, "enable-sport-auto", false, "enable automatic source port assignment")
57+
pf.StringVar(&config.backend, "backend", constants.DefaultBackend, "Backend for egress NAT rules: iptables or nftables (default: iptables)")
4858

4959
goflags := flag.NewFlagSet("klog", flag.ExitOnError)
5060
klog.InitFlags(goflags)

v2/cmd/coil-egress/sub/run.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ func subMain() error {
112112
return err
113113
}
114114

115-
setupLog.Info("initialize Egress", "ipv4", ipv4.String(), "ipv6", ipv6.String())
116-
eg := founat.NewEgress("eth0", ipv4, ipv6)
115+
setupLog.Info("initialize Egress", "ipv4", ipv4.String(), "ipv6", ipv6.String(), "backend", config.backend)
116+
eg := founat.NewEgress("eth0", ipv4, ipv6, config.backend)
117117
if err := eg.Init(); err != nil {
118118
return err
119119
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
resources:
2+
- ../../../crd/egress
3+
- ../../../rbac/egress
4+
- ../../../pod/egress/v4-nft
5+
- ../../../webhook/egress
6+
7+
# [CERTS] Following lines should be commented if automatic cert generation is used.
8+
patchesStrategicMerge:
9+
- ../webhook_manifests_patch.yaml
10+
11+
generatorOptions:
12+
disableNameSuffixHash: true
13+
14+
secretGenerator:
15+
# [EGRESS] Following lines be uncommented to enable Egress NAT features.
16+
- name: coilv2-egress-webhook-server-cert
17+
files:
18+
- ca.crt=../../cert.pem
19+
- tls.crt=../../egress-cert.pem
20+
- tls.key=../../egress-key.pem
21+
type: "kubernetes.io/tls"
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
resources:
2+
- ../../../crd/egress
3+
- ../../../rbac/egress
4+
- ../../../pod/egress/v6-nft
5+
- ../../../webhook/egress
6+
7+
# [CERTS] Following lines should be commented if automatic cert generation is used.
8+
patchesStrategicMerge:
9+
- ../webhook_manifests_patch.yaml
10+
11+
generatorOptions:
12+
disableNameSuffixHash: true
13+
14+
secretGenerator:
15+
# [EGRESS] Following lines be uncommented to enable Egress NAT features.
16+
- name: coilv2-egress-webhook-server-cert
17+
files:
18+
- ca.crt=../../cert.pem
19+
- tls.crt=../../egress-cert.pem
20+
- tls.key=../../egress-key.pem
21+
type: "kubernetes.io/tls"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: coil-egress-controller
5+
namespace: system
6+
spec:
7+
template:
8+
spec:
9+
containers:
10+
- name: coil-egress-controller
11+
args:
12+
- --zap-stacktrace-level=panic
13+
- --backend=nftables
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
resources:
2+
# [EGRESS] Following line should be uncommented to enable Egress NAT features.
3+
- ../../coil-egress-controller.yaml
4+
- ../v4/coild.yaml
5+
6+
patchesStrategicMerge:
7+
- ../../coil-egress-controller-nft-patch.yaml

0 commit comments

Comments
 (0)