Skip to content

Commit a24db8c

Browse files
committed
ClusterNetworkPolicy
1 parent 4edbe53 commit a24db8c

File tree

5 files changed

+969
-4
lines changed

5 files changed

+969
-4
lines changed

Makefile

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ REGISTRY?=gcr.io/k8s-staging-networking
1212
TAG?=$(shell echo "$$(date +v%Y%m%d)-$$(git describe --always --dirty)")
1313
PLATFORMS?=linux/amd64,linux/arm64
1414

15-
.PHONY: all build build-standard build-npa-v1alpha1
15+
.PHONY: all build build-standard build-npa-v1alpha1 build-npa-v1alpha2
1616
all: build
17-
build: build-standard build-npa-v1alpha1
17+
build: build-standard build-npa-v1alpha1 build-npa-v1alpha2
1818

1919
build-standard:
2020
@echo "Building standard binary..."
@@ -24,6 +24,10 @@ build-npa-v1alpha1:
2424
@echo "Building npa-v1alpha1 binary..."
2525
go build -o ./bin/kube-network-policies-npa-v1alpha1 ./cmd/npa-v1alpha1
2626

27+
build-npa-v1alpha2:
28+
@echo "Building npa-v1alpha2 binary..."
29+
go build -o ./bin/kube-network-policies-npa-v1alpha2 ./cmd/npa-v1alpha2
30+
2731
clean:
2832
rm -rf "$(OUT_DIR)/"
2933

@@ -56,6 +60,12 @@ image-build-npa-v1alpha1: build-npa-v1alpha1
5660
--tag="${REGISTRY}/$(IMAGE_NAME):$(TAG)-npa-v1alpha1" \
5761
--load
5862

63+
image-build-npa-v1alpha2: build-npa-v1alpha2
64+
docker buildx build . \
65+
--build-arg TARGET_BUILD=npa-v1alpha2 \
66+
--tag="${REGISTRY}/$(IMAGE_NAME):$(TAG)-npa-v1alpha2" \
67+
--load
68+
5969
# Individual image push targets (multi-platform)
6070
image-push-standard: build-standard
6171
docker buildx build . \
@@ -71,14 +81,21 @@ image-push-npa-v1alpha1: build-npa-v1alpha1
7181
--tag="${REGISTRY}/$(IMAGE_NAME):$(TAG)-npa-v1alpha1" \
7282
--push
7383

84+
image-push-npa-v1alpha2: build-npa-v1alpha2
85+
docker buildx build . \
86+
--build-arg TARGET_BUILD=npa-v1alpha2 \
87+
--platform="${PLATFORMS}" \
88+
--tag="${REGISTRY}/$(IMAGE_NAME):$(TAG)-npa-v1alpha2" \
89+
--push
90+
7491
# --- Aggregate Targets ---
7592
.PHONY: images-build images-push release
7693

7794
# Build all image variants and load them into the local Docker daemon
78-
images-build: ensure-buildx image-build-standard image-build-npa-v1alpha1
95+
images-build: ensure-buildx image-build-standard image-build-npa-v1alpha1 image-build-npa-v1alpha2
7996

8097
# Build and push all multi-platform image variants to the registry
81-
images-push: ensure-buildx image-push-standard image-push-npa-v1alpha1
98+
images-push: ensure-buildx image-push-standard image-push-npa-v1alpha1 image-build-npa-v1alpha2
8299

83100
# The main release target, which pushes all images
84101
release: images-push

cmd/npa-v1alpha2/main.go

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"flag"
6+
"fmt"
7+
"net"
8+
"os"
9+
"os/signal"
10+
"syscall"
11+
"time"
12+
13+
"sigs.k8s.io/kube-network-policies/pkg/api"
14+
"sigs.k8s.io/kube-network-policies/pkg/cmd"
15+
"sigs.k8s.io/kube-network-policies/pkg/dataplane"
16+
"sigs.k8s.io/kube-network-policies/pkg/dns"
17+
"sigs.k8s.io/kube-network-policies/pkg/networkpolicy"
18+
"sigs.k8s.io/kube-network-policies/pkg/podinfo"
19+
pluginsnpav1alpha2 "sigs.k8s.io/kube-network-policies/plugins/npa-v1alpha2"
20+
npav1alpha2 "sigs.k8s.io/network-policy-api/apis/v1alpha2"
21+
npaclient "sigs.k8s.io/network-policy-api/pkg/client/clientset/versioned"
22+
npainformers "sigs.k8s.io/network-policy-api/pkg/client/informers/externalversions"
23+
24+
"k8s.io/apimachinery/pkg/api/meta"
25+
"k8s.io/client-go/informers"
26+
"k8s.io/client-go/tools/clientcmd"
27+
28+
"k8s.io/client-go/kubernetes"
29+
"k8s.io/client-go/rest"
30+
"k8s.io/component-base/logs"
31+
logsapi "k8s.io/component-base/logs/api/v1"
32+
_ "k8s.io/component-base/logs/json/register"
33+
nodeutil "k8s.io/component-helpers/node/util"
34+
"k8s.io/klog/v2"
35+
)
36+
37+
// This is a pattern to ensure that deferred functions executes before os.Exit
38+
func main() {
39+
os.Exit(run())
40+
}
41+
42+
func run() int {
43+
// Setup logging
44+
logCfg := logsapi.NewLoggingConfiguration()
45+
logsapi.AddGoFlags(logCfg, flag.CommandLine)
46+
47+
// Setup flags
48+
opts := cmd.NewOptions()
49+
opts.AddFlags(flag.CommandLine)
50+
51+
flag.Parse()
52+
53+
// init logging
54+
logs.InitLogs()
55+
if err := logsapi.ValidateAndApply(logCfg, nil); err != nil {
56+
fmt.Fprintf(os.Stderr, "%v\n", err)
57+
return 1
58+
}
59+
60+
// Create a context for structured logging, and catch termination signals
61+
ctx, cancel := signal.NotifyContext(
62+
context.Background(), os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
63+
defer cancel()
64+
65+
logger := klog.FromContext(ctx)
66+
logger.Info("called", "args", flag.Args())
67+
68+
flag.VisitAll(func(flag *flag.Flag) {
69+
logger.Info("flag", "name", flag.Name, "value", flag.Value)
70+
})
71+
72+
if _, _, err := net.SplitHostPort(opts.MetricsBindAddress); err != nil {
73+
logger.Error(err, "parsing metrics bind address", "address", opts.MetricsBindAddress)
74+
return 1
75+
}
76+
77+
nodeName, err := nodeutil.GetHostname(opts.HostnameOverride)
78+
if err != nil {
79+
klog.Fatalf("can not obtain the node name, use the hostname-override flag if you want to set it to a specific value: %v", err)
80+
}
81+
82+
dpCfg := dataplane.Config{
83+
FailOpen: opts.FailOpen,
84+
QueueID: opts.QueueID,
85+
NetfilterBug1766Fix: opts.NetfilterBug1766Fix,
86+
}
87+
88+
var config *rest.Config
89+
if opts.Kubeconfig != "" {
90+
config, err = clientcmd.BuildConfigFromFlags("", opts.Kubeconfig)
91+
} else {
92+
// creates the in-cluster config
93+
config, err = rest.InClusterConfig()
94+
}
95+
if err != nil {
96+
klog.Fatalf("can not create client-go configuration: %v", err)
97+
}
98+
99+
// use protobuf for better performance at scale
100+
// https://kubernetes.io/docs/reference/using-api/api-concepts/#alternate-representations-of-resources
101+
npaConfig := config // shallow copy because CRDs does not support proto
102+
config.AcceptContentTypes = "application/vnd.kubernetes.protobuf,application/json"
103+
config.ContentType = "application/vnd.kubernetes.protobuf"
104+
105+
// creates the clientset
106+
clientset, err := kubernetes.NewForConfig(config)
107+
if err != nil {
108+
panic(err.Error())
109+
}
110+
111+
informersFactory := informers.NewSharedInformerFactory(clientset, 0)
112+
nsInformer := informersFactory.Core().V1().Namespaces()
113+
networkPolicyInfomer := informersFactory.Networking().V1().NetworkPolicies()
114+
podInformer := informersFactory.Core().V1().Pods()
115+
nodeInformer := informersFactory.Core().V1().Nodes()
116+
117+
// Set the memory-saving transform function on the pod informer.
118+
err = podInformer.Informer().SetTransform(func(obj interface{}) (interface{}, error) {
119+
if accessor, err := meta.Accessor(obj); err == nil {
120+
accessor.SetManagedFields(nil)
121+
}
122+
return obj, nil
123+
})
124+
if err != nil {
125+
klog.Fatalf("Failed to set pod informer transform: %v", err)
126+
}
127+
128+
npaClient, err := npaclient.NewForConfig(npaConfig)
129+
if err != nil {
130+
klog.Fatalf("Failed to create Network client: %v", err)
131+
}
132+
npaInformerFactory := npainformers.NewSharedInformerFactory(npaClient, 0)
133+
cnpInformer := npaInformerFactory.Policy().V1alpha2().ClusterNetworkPolicies()
134+
135+
// Create the Pod IP resolvers.
136+
// First, given an IP address they return the Pod name/namespace.
137+
informerResolver, err := podinfo.NewInformerResolver(podInformer.Informer())
138+
if err != nil {
139+
klog.Fatalf("Failed to create informer resolver: %v", err)
140+
}
141+
resolvers := []podinfo.IPResolver{informerResolver}
142+
143+
// Create an NRI Pod IP resolver if enabled, since NRI connects to the container runtime
144+
// the Pod and IP information is provided at the time the Pod Sandbox is created and before
145+
// the containers start running, so policies can be enforced without race conditions.
146+
if !opts.DisableNRI {
147+
nriIPResolver, err := podinfo.NewNRIResolver(ctx)
148+
if err != nil {
149+
klog.Infof("failed to create NRI plugin, using apiserver information only: %v", err)
150+
}
151+
resolvers = append(resolvers, nriIPResolver)
152+
}
153+
154+
// Create the pod info provider to obtain the Pod information
155+
// necessary for the network policy evaluation, it uses the resolvers
156+
// to obtain the key (Pod name and namespace) and use the informers to obtain
157+
// the labels that are necessary to match the network policies.
158+
podInfoProvider := podinfo.NewInformerProvider(
159+
podInformer,
160+
nsInformer,
161+
nodeInformer,
162+
resolvers)
163+
164+
// Create the evaluators for the Pipeline to process the packets
165+
// and take a network policy action. The evaluators are processed
166+
// by the order in the array.
167+
evaluators := []api.PolicyEvaluator{}
168+
169+
// Logging evaluator must go first if enabled.
170+
if klog.V(2).Enabled() {
171+
evaluators = append(evaluators, networkpolicy.NewLoggingPolicy())
172+
}
173+
174+
// Admin Network Policy need to associate IP addresses to Domains
175+
// NewDomainCache implements the interface DomainResolver using
176+
// nftables to create a cache with the resolved IP addresses from the
177+
// Pod domain queries.
178+
domainResolver := dns.NewDomainCache(opts.QueueID + 1)
179+
go func() {
180+
err := domainResolver.Run(ctx)
181+
if err != nil {
182+
klog.Infof("domain cache controller exited: %v", err)
183+
}
184+
}()
185+
186+
evaluators = append(evaluators, pluginsnpav1alpha2.NewClusterNetworkPolicy(
187+
npav1alpha2.AdminTier,
188+
cnpInformer,
189+
domainResolver,
190+
))
191+
192+
// Standard Network Policy goes after AdminNetworkPolicy and before BaselineAdminNetworkPolicy
193+
evaluators = append(evaluators, networkpolicy.NewStandardNetworkPolicy(
194+
nodeName,
195+
nsInformer,
196+
podInformer,
197+
networkPolicyInfomer,
198+
))
199+
200+
evaluators = append(evaluators, pluginsnpav1alpha2.NewClusterNetworkPolicy(
201+
npav1alpha2.BaselineTier,
202+
cnpInformer,
203+
domainResolver,
204+
))
205+
206+
informersFactory.Start(ctx.Done())
207+
npaInformerFactory.Start(ctx.Done())
208+
209+
cmd.Start(ctx, networkpolicy.NewPolicyEngine(podInfoProvider, evaluators), dpCfg, opts.MetricsBindAddress)
210+
211+
<-ctx.Done()
212+
logger.Info("Received termination signal, starting cleanup...")
213+
// grace period to cleanup resources
214+
time.Sleep(5 * time.Second)
215+
logger.Info("Cleanup completed, exiting...")
216+
return 0
217+
}

install-cnp.yaml

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
---
2+
kind: ClusterRole
3+
apiVersion: rbac.authorization.k8s.io/v1
4+
metadata:
5+
name: kube-network-policies
6+
rules:
7+
- apiGroups:
8+
- ""
9+
resources:
10+
- pods
11+
- namespaces
12+
- nodes
13+
verbs:
14+
- list
15+
- watch
16+
- apiGroups:
17+
- "networking.k8s.io"
18+
resources:
19+
- networkpolicies
20+
verbs:
21+
- list
22+
- watch
23+
- apiGroups:
24+
- "policy.networking.k8s.io"
25+
resources:
26+
- clusternetworkpolicies
27+
verbs:
28+
- list
29+
- watch
30+
---
31+
kind: ClusterRoleBinding
32+
apiVersion: rbac.authorization.k8s.io/v1
33+
metadata:
34+
name: kube-network-policies
35+
roleRef:
36+
apiGroup: rbac.authorization.k8s.io
37+
kind: ClusterRole
38+
name: kube-network-policies
39+
subjects:
40+
- kind: ServiceAccount
41+
name: kube-network-policies
42+
namespace: kube-system
43+
---
44+
apiVersion: v1
45+
kind: ServiceAccount
46+
metadata:
47+
name: kube-network-policies
48+
namespace: kube-system
49+
---
50+
apiVersion: apps/v1
51+
kind: DaemonSet
52+
metadata:
53+
name: kube-network-policies
54+
namespace: kube-system
55+
labels:
56+
tier: node
57+
app: kube-network-policies
58+
k8s-app: kube-network-policies
59+
spec:
60+
selector:
61+
matchLabels:
62+
app: kube-network-policies
63+
template:
64+
metadata:
65+
labels:
66+
tier: node
67+
app: kube-network-policies
68+
k8s-app: kube-network-policies
69+
spec:
70+
hostNetwork: true
71+
dnsPolicy: ClusterFirst
72+
nodeSelector:
73+
kubernetes.io/os: linux
74+
tolerations:
75+
- operator: Exists
76+
effect: NoSchedule
77+
serviceAccountName: kube-network-policies
78+
containers:
79+
- name: kube-network-policies
80+
image: registry.k8s.io/networking/kube-network-policies:v0.8.0-npa-v1alpha2
81+
args:
82+
- /bin/netpol
83+
- --hostname-override=$(MY_NODE_NAME)
84+
- --v=4
85+
- --nfqueue-id=89
86+
volumeMounts:
87+
- name: nri-plugin
88+
mountPath: /var/run/nri
89+
- name: netns
90+
mountPath: /var/run/netns
91+
mountPropagation: HostToContainer
92+
resources:
93+
requests:
94+
cpu: "100m"
95+
memory: "50Mi"
96+
securityContext:
97+
privileged: true
98+
capabilities:
99+
add: ["NET_ADMIN"]
100+
env:
101+
- name: MY_NODE_NAME
102+
valueFrom:
103+
fieldRef:
104+
fieldPath: spec.nodeName
105+
volumes:
106+
- name: nri-plugin
107+
hostPath:
108+
path: /var/run/nri
109+
- name: netns
110+
hostPath:
111+
path: /var/run/netns
112+
---

0 commit comments

Comments
 (0)