Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 22 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ REGISTRY?=gcr.io/k8s-staging-networking
TAG?=$(shell echo "$$(date +v%Y%m%d)-$$(git describe --always --dirty)")
PLATFORMS?=linux/amd64,linux/arm64

.PHONY: all build build-standard build-npa-v1alpha1 build-iptracker build-kube-ip-tracker
.PHONY: all build build-standard build-npa-v1alpha1 build-npa-v1alpha2 build-iptracker build-kube-ip-tracker

build: build-standard build-npa-v1alpha1 build-iptracker build-kube-ip-tracker
build: build-standard build-npa-v1alpha1 build-npa-v1alpha2 build-iptracker build-kube-ip-tracker

build-standard:
@echo "Building standard binary..."
Expand All @@ -24,6 +24,10 @@ build-npa-v1alpha1:
@echo "Building npa-v1alpha1 binary..."
go build -o ./bin/kube-network-policies-npa-v1alpha1 ./cmd/kube-network-policies/npa-v1alpha1

build-npa-v1alpha2:
@echo "Building npa-v1alpha2 binary..."
go build -o ./bin/kube-network-policies-npa-v1alpha2 ./cmd/kube-network-policies/npa-v1alpha2

build-iptracker:
@echo "Building iptracker binary..."
go build -o ./bin/kube-network-policies-iptracker ./cmd/kube-network-policies/iptracker
Expand All @@ -32,7 +36,6 @@ build-kube-ip-tracker:
@echo "Building kube-ip-tracker binary..."
go build -o ./bin/kube-ip-tracker ./cmd/kube-ip-tracker


clean:
rm -rf "$(OUT_DIR)/"

Expand Down Expand Up @@ -65,6 +68,12 @@ image-build-npa-v1alpha1: build-npa-v1alpha1
--tag="${REGISTRY}/$(IMAGE_NAME):$(TAG)-npa-v1alpha1" \
--load

image-build-npa-v1alpha2: build-npa-v1alpha2
docker buildx build . \
--build-arg TARGET_BUILD=npa-v1alpha2 \
--tag="${REGISTRY}/$(IMAGE_NAME):$(TAG)-npa-v1alpha2" \
--load

image-build-iptracker: build-iptracker
docker buildx build . \
--build-arg TARGET_BUILD=iptracker \
Expand All @@ -91,6 +100,13 @@ image-push-npa-v1alpha1: build-npa-v1alpha1
--tag="${REGISTRY}/$(IMAGE_NAME):$(TAG)-npa-v1alpha1" \
--push

image-push-npa-v1alpha2: build-npa-v1alpha2
docker buildx build . \
--build-arg TARGET_BUILD=npa-v1alpha2 \
--platform="${PLATFORMS}" \
--tag="${REGISTRY}/$(IMAGE_NAME):$(TAG)-npa-v1alpha2" \
--push

image-push-iptracker: build-iptracker
docker buildx build . \
--build-arg TARGET_BUILD=iptracker \
Expand All @@ -103,15 +119,15 @@ image-push-kube-ip-tracker: build-kube-ip-tracker
--tag="${REGISTRY}/kube-ip-tracker:$(TAG)" \
--push


# --- Aggregate Targets ---
.PHONY: images-build images-push release

# Build all image variants and load them into the local Docker daemon
images-build: ensure-buildx image-build-standard image-build-npa-v1alpha1
images-build: ensure-buildx image-build-standard image-build-npa-v1alpha1 image-build-npa-v1alpha2 image-build-iptracker image-build-kube-ip-tracker


# Build and push all multi-platform image variants to the registry
images-push: ensure-buildx image-push-standard image-push-npa-v1alpha1
images-push: ensure-buildx image-push-standard image-push-npa-v1alpha1 image-build-npa-v1alpha2 image-push-iptracker image-push-kube-ip-tracker

# The main release target, which pushes all images
release: images-push
217 changes: 217 additions & 0 deletions cmd/kube-network-policies/npa-v1alpha2/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
package main

import (
"context"
"flag"
"fmt"
"net"
"os"
"os/signal"
"syscall"
"time"

"sigs.k8s.io/kube-network-policies/pkg/api"
"sigs.k8s.io/kube-network-policies/pkg/cmd"
"sigs.k8s.io/kube-network-policies/pkg/dataplane"
"sigs.k8s.io/kube-network-policies/pkg/dns"
"sigs.k8s.io/kube-network-policies/pkg/networkpolicy"
"sigs.k8s.io/kube-network-policies/pkg/podinfo"
pluginsnpav1alpha2 "sigs.k8s.io/kube-network-policies/plugins/npa-v1alpha2"
npav1alpha2 "sigs.k8s.io/network-policy-api/apis/v1alpha2"
npaclient "sigs.k8s.io/network-policy-api/pkg/client/clientset/versioned"
npainformers "sigs.k8s.io/network-policy-api/pkg/client/informers/externalversions"

"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/client-go/informers"
"k8s.io/client-go/tools/clientcmd"

"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/component-base/logs"
logsapi "k8s.io/component-base/logs/api/v1"
_ "k8s.io/component-base/logs/json/register"
nodeutil "k8s.io/component-helpers/node/util"
"k8s.io/klog/v2"
)

// This is a pattern to ensure that deferred functions executes before os.Exit
func main() {
os.Exit(run())
}

func run() int {
// Setup logging
logCfg := logsapi.NewLoggingConfiguration()
logsapi.AddGoFlags(logCfg, flag.CommandLine)

// Setup flags
opts := cmd.NewOptions()
opts.AddFlags(flag.CommandLine)

flag.Parse()

// init logging
logs.InitLogs()
if err := logsapi.ValidateAndApply(logCfg, nil); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
return 1
}

// Create a context for structured logging, and catch termination signals
ctx, cancel := signal.NotifyContext(
context.Background(), os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
defer cancel()

logger := klog.FromContext(ctx)
logger.Info("called", "args", flag.Args())

flag.VisitAll(func(flag *flag.Flag) {
logger.Info("flag", "name", flag.Name, "value", flag.Value)
})

if _, _, err := net.SplitHostPort(opts.MetricsBindAddress); err != nil {
logger.Error(err, "parsing metrics bind address", "address", opts.MetricsBindAddress)
return 1
}

nodeName, err := nodeutil.GetHostname(opts.HostnameOverride)
if err != nil {
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)
}

dpCfg := dataplane.Config{
FailOpen: opts.FailOpen,
QueueID: opts.QueueID,
NetfilterBug1766Fix: opts.NetfilterBug1766Fix,
}

var config *rest.Config
if opts.Kubeconfig != "" {
config, err = clientcmd.BuildConfigFromFlags("", opts.Kubeconfig)
} else {
// creates the in-cluster config
config, err = rest.InClusterConfig()
}
if err != nil {
klog.Fatalf("can not create client-go configuration: %v", err)
}

// use protobuf for better performance at scale
// https://kubernetes.io/docs/reference/using-api/api-concepts/#alternate-representations-of-resources
npaConfig := config // shallow copy because CRDs does not support proto
config.AcceptContentTypes = "application/vnd.kubernetes.protobuf,application/json"
config.ContentType = "application/vnd.kubernetes.protobuf"

// creates the clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err.Error())
}

informersFactory := informers.NewSharedInformerFactory(clientset, 0)
nsInformer := informersFactory.Core().V1().Namespaces()
networkPolicyInfomer := informersFactory.Networking().V1().NetworkPolicies()
podInformer := informersFactory.Core().V1().Pods()
nodeInformer := informersFactory.Core().V1().Nodes()

// Set the memory-saving transform function on the pod informer.
err = podInformer.Informer().SetTransform(func(obj interface{}) (interface{}, error) {
if accessor, err := meta.Accessor(obj); err == nil {
accessor.SetManagedFields(nil)
}
return obj, nil
})
if err != nil {
klog.Fatalf("Failed to set pod informer transform: %v", err)
}

npaClient, err := npaclient.NewForConfig(npaConfig)
if err != nil {
klog.Fatalf("Failed to create Network client: %v", err)
}
npaInformerFactory := npainformers.NewSharedInformerFactory(npaClient, 0)
cnpInformer := npaInformerFactory.Policy().V1alpha2().ClusterNetworkPolicies()

// Create the Pod IP resolvers.
// First, given an IP address they return the Pod name/namespace.
informerResolver, err := podinfo.NewInformerResolver(podInformer.Informer())
if err != nil {
klog.Fatalf("Failed to create informer resolver: %v", err)
}
resolvers := []podinfo.IPResolver{informerResolver}

// Create an NRI Pod IP resolver if enabled, since NRI connects to the container runtime
// the Pod and IP information is provided at the time the Pod Sandbox is created and before
// the containers start running, so policies can be enforced without race conditions.
if !opts.DisableNRI {
nriIPResolver, err := podinfo.NewNRIResolver(ctx)
if err != nil {
klog.Infof("failed to create NRI plugin, using apiserver information only: %v", err)
}
resolvers = append(resolvers, nriIPResolver)
}

// Create the pod info provider to obtain the Pod information
// necessary for the network policy evaluation, it uses the resolvers
// to obtain the key (Pod name and namespace) and use the informers to obtain
// the labels that are necessary to match the network policies.
podInfoProvider := podinfo.NewInformerProvider(
podInformer,
nsInformer,
nodeInformer,
resolvers)

// Create the evaluators for the Pipeline to process the packets
// and take a network policy action. The evaluators are processed
// by the order in the array.
evaluators := []api.PolicyEvaluator{}

// Logging evaluator must go first if enabled.
if klog.V(2).Enabled() {
evaluators = append(evaluators, networkpolicy.NewLoggingPolicy())
}

// Admin Network Policy need to associate IP addresses to Domains
// NewDomainCache implements the interface DomainResolver using
// nftables to create a cache with the resolved IP addresses from the
// Pod domain queries.
domainResolver := dns.NewDomainCache(opts.QueueID + 1)
go func() {
err := domainResolver.Run(ctx)
if err != nil {
klog.Infof("domain cache controller exited: %v", err)
}
}()

evaluators = append(evaluators, pluginsnpav1alpha2.NewClusterNetworkPolicy(
npav1alpha2.AdminTier,
cnpInformer,
domainResolver,
))

// Standard Network Policy goes after AdminNetworkPolicy and before BaselineAdminNetworkPolicy
evaluators = append(evaluators, networkpolicy.NewStandardNetworkPolicy(
nodeName,
nsInformer,
podInformer,
networkPolicyInfomer,
))

evaluators = append(evaluators, pluginsnpav1alpha2.NewClusterNetworkPolicy(
npav1alpha2.BaselineTier,
cnpInformer,
domainResolver,
))

informersFactory.Start(ctx.Done())
npaInformerFactory.Start(ctx.Done())

cmd.Start(ctx, networkpolicy.NewPolicyEngine(podInfoProvider, evaluators), dpCfg, opts.MetricsBindAddress)

<-ctx.Done()
logger.Info("Received termination signal, starting cleanup...")
// grace period to cleanup resources
time.Sleep(5 * time.Second)
logger.Info("Cleanup completed, exiting...")
return 0
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ require (
k8s.io/component-helpers v0.33.4
k8s.io/klog/v2 v2.130.1
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397
sigs.k8s.io/network-policy-api v0.1.6-0.20250401132235-45061d10895e
sigs.k8s.io/network-policy-api v0.1.8-0.20250826165010-d5cee02b3c1c
)

require (
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,8 @@ k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/network-policy-api v0.1.6-0.20250401132235-45061d10895e h1:b5Vm5aa0I37gToQmFhQ+gQMZVsPsxSiJzxZWtSCs99w=
sigs.k8s.io/network-policy-api v0.1.6-0.20250401132235-45061d10895e/go.mod h1:8J+z3UB9HgeqbmYprl6OKIobEDv27A3KRHPcteJ61rw=
sigs.k8s.io/network-policy-api v0.1.8-0.20250826165010-d5cee02b3c1c h1:ySTDTqw3flKypZ4OnU2Q1lY/MzCBbONPVL6Rmx4BRAQ=
sigs.k8s.io/network-policy-api v0.1.8-0.20250826165010-d5cee02b3c1c/go.mod h1:QIWX6Th2h0SmCwOwa1+9Urs0W+WDJGL5rujAPUemdkk=
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
Expand Down
Loading
Loading