Documentation
¶
Overview ¶
Package controller provides the Kubernetes controller for watching pods and managing eBPF program attachments.
Index ¶
Constants ¶
const ( // AnnotationEnabled is the annotation that enables Kloak for a pod. AnnotationEnabled = "getkloak.io/enabled" // CgroupBasePath is the base path for cgroups v2. CgroupBasePath = "/sys/fs/cgroup" )
const ( // AnnotationSecretEnabled is the label/annotation to enable Kloak secret replication. AnnotationSecretEnabled = "getkloak.io/enabled" // AnnotationPort is the annotation to specify an allowed port for a secret. AnnotationPort = "getkloak.io/port" // AnnotationHosts is the annotation to specify allowed hosts for a secret. AnnotationHosts = "getkloak.io/hosts" // ShadowSecretSuffix is the suffix appended to the name of the shadow secret. ShadowSecretSuffix = "-kloak" )
const ( KubeDNSNamespace = "kube-system" KubeDNSName = "kube-dns" )
The cluster DNS Service, whose answers the data plane trusts.
const ( // DefaultNRISocket is where containerd (2.0+) and CRI-O (1.30+) serve // NRI by default. DefaultNRISocket = "/var/run/nri/nri.sock" )
const DefaultSecretResyncPeriod = 5 * time.Minute
DefaultSecretResyncPeriod is how often the data plane's secrets are synced when no Secret changes: what releases the virtual IP of a host no secret is restricted to any more once its retention is over, and repairs maps that drifted.
Variables ¶
This section is empty.
Functions ¶
func TrustedDNSServers ¶ added in v0.3.0
func TrustedDNSServers(ctx context.Context, reader client.Reader, static []net.IP, log *zap.SugaredLogger) []net.IP
TrustedDNSServers returns the DNS servers whose answers the data plane believes: kube-dns's ClusterIPs (both of a dual-stack Service, which pods are given both of as nameservers), the addresses of its endpoints, and static (--trusted-dns-servers). The endpoints are where answers come from when the CNI load balances Services at the socket (Cilium's kube-proxy replacement): the pod's query goes to a CoreDNS pod directly, and so the answer comes back from its address, not from the ClusterIP. A failed read leaves its addresses out.
Types ¶
type NRIPlugin ¶ added in v0.3.0
type NRIPlugin struct {
Preparer SandboxPreparer
SocketPath string
// HostRoot is the host's root filesystem as this process sees it: the
// runtime reports network namespace paths in the host's mount
// namespace. "" means /proc/1/root (with hostPID).
HostRoot string
Log *zap.SugaredLogger
// Reconnect delays: after the runtime's connection closed, and while no
// runtime serves NRI at SocketPath. Zero means the defaults.
RetryAfterClose time.Duration
// contains filtered or unexported fields
}
NRIPlugin hooks kloak into the container runtime through NRI (the Node Resource Interface of containerd and CRI-O). The runtime calls it while it creates each pod sandbox, and again before each container, and waits for it: kloak attaches the virtual IP DNS rewrite then (PrepareSandbox), before any container of the pod resolves a name. Without NRI (a runtime without it, NRI disabled, or the socket not mounted), the Reconciler attaches the rewrite by polling Pending pods instead.
The plugin never fails a runtime request: an error would fail the pod's sandbox or container. A request taking longer than the runtime's timeout (2 s by default) disconnects the plugin, which reconnects.
type Reconciler ¶
type Reconciler struct {
client.Client
Log *zap.SugaredLogger
Scheme *runtime.Scheme
UprobeManager *ebpf.TLSUprobeManager
CgroupRoot string
// NodeName filters pods to only those on this node (empty = all nodes)
NodeName string
// APIReader reads a pod from the API server when the cache does not have
// it yet (PrepareSandbox); nil: cache only.
APIReader client.Reader
// contains filtered or unexported fields
}
Reconciler watches pods and manages eBPF cgroup tracking.
func NewReconciler ¶
func NewReconciler(c client.Client, log *zap.SugaredLogger, scheme *runtime.Scheme, uprobeMgr *ebpf.TLSUprobeManager, cgroupRoot, nodeName string) *Reconciler
NewReconciler creates a new pod reconciler.
func (*Reconciler) GetTrackedPodCount ¶
func (r *Reconciler) GetTrackedPodCount() int
GetTrackedPodCount returns the number of currently tracked pods.
func (*Reconciler) PrepareSandbox ¶ added in v0.3.0
func (r *Reconciler) PrepareSandbox(ctx context.Context, sb *Sandbox) bool
PrepareSandbox attaches the virtual IP DNS rewrite in a kloak pod's network namespace and binds the pod at its addresses, while the container runtime creates the pod's sandbox or one of its containers (NRI): the runtime waits for it, so the rewrite is in place before any container of the pod resolves a name. It reports whether the pod is prepared; when it is not (no NRI, or a failure), the reconciler attaches the rewrite by polling the Pending pod, which leaves a short window at pod start.
func (*Reconciler) SetupWithManager ¶
func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error
SetupWithManager sets up the controller with the Manager.
type Sandbox ¶ added in v0.3.0
type Sandbox struct {
ID string
UID string
Namespace string
Name string
// Annotations are the pod's (the kubelet passes them to the sandbox).
Annotations map[string]string
// NetnsPath is the sandbox's network namespace as a path this process
// can open; "" when the runtime does not report one (host network).
NetnsPath string
// IPs are the pod's addresses, when the runtime reports them.
IPs []netip.Addr
}
Sandbox is a pod sandbox the container runtime is creating, as it reports it over NRI.
type SandboxPreparer ¶
SandboxPreparer prepares a pod sandbox the container runtime is creating (Reconciler.PrepareSandbox).
type SecretReconciler ¶
SecretReconciler reconciles a Secret object
func (*SecretReconciler) SetupWithManager ¶
func (r *SecretReconciler) SetupWithManager(mgr ctrl.Manager) error
type SecretSyncReconciler ¶ added in v0.3.0
type SecretSyncReconciler struct {
// Sync makes the data plane hold the cluster's current secrets
// (TLSUprobeManager.SyncSecrets). An error is logged by the controller
// and retried with backoff.
Sync func(context.Context) error
// ResyncPeriod is the time between syncs when nothing changes;
// 0 means DefaultSecretResyncPeriod.
ResyncPeriod time.Duration
}
SecretSyncReconciler keeps the data plane's secrets in step with the cluster's kloak Secrets: an enabled Secret or a shadow that is created, changed or deleted triggers a sync.
func (*SecretSyncReconciler) Reconcile ¶ added in v0.3.0
Reconcile syncs every secret. Every request is secretSyncRequest.
func (*SecretSyncReconciler) SetupWithManager ¶ added in v0.3.0
func (r *SecretSyncReconciler) SetupWithManager(mgr ctrl.Manager) error
SetupWithManager watches Secrets, through the cache the Secret reconciler already fills, and syncs once at start: with no kloak Secret there is no event, and the virtual IPs restored from the pinned maps still need to be retired.
type TrustedDNSReconciler ¶ added in v0.3.0
type TrustedDNSReconciler struct {
client.Client
// Static are the --trusted-dns-servers.
Static []net.IP
// Apply makes the data plane trust exactly these servers.
Apply func([]net.IP) error
Log *zap.SugaredLogger
// contains filtered or unexported fields
}
TrustedDNSReconciler keeps the trusted DNS servers (TrustedDNSServers) in the data plane as kube-dns changes: its endpoints come and go with the CoreDNS pods.
func (*TrustedDNSReconciler) Reconcile ¶ added in v0.3.0
Reconcile recomputes the trusted servers and applies them when they changed. Every request names kube-dns.
func (*TrustedDNSReconciler) SetupWithManager ¶ added in v0.3.0
func (r *TrustedDNSReconciler) SetupWithManager(mgr ctrl.Manager) error
SetupWithManager watches the kube-dns Service and its EndpointSlices.