76 lines
2.6 KiB
Go
76 lines
2.6 KiB
Go
package kubernetes
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
"gitea.home.hrajfrisbee.cz/kacerr/egress-proxies-operator/internal/provider"
|
|
)
|
|
|
|
const proxyContainerName = "squid"
|
|
|
|
// writeConfigAndExec is the container's entrypoint: write the config the
|
|
// SQUID_CONF env var carries to disk, then exec squid against it. Avoids a
|
|
// separate ConfigMap object per proxy instance — there's still only one
|
|
// Kubernetes object (the Pod) to create, track, and clean up per proxy.
|
|
const writeConfigAndExec = `printf '%s' "$SQUID_CONF" > /etc/squid/squid.conf && exec squid -N -f /etc/squid/squid.conf`
|
|
|
|
// buildPod constructs the Pod for a proxy instance. Pure and side-effect
|
|
// free, so it's unit-tested directly without a cluster — the same pattern
|
|
// the GCP provider's buildInsertRequest uses.
|
|
func buildPod(image string, req provider.CreateRequest) *corev1.Pod {
|
|
return &corev1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: req.Name,
|
|
Namespace: req.Namespace,
|
|
Labels: map[string]string{
|
|
provider.LabelManaged: provider.LabelManagedYes,
|
|
provider.LabelUID: req.UID,
|
|
},
|
|
},
|
|
Spec: corev1.PodSpec{
|
|
RestartPolicy: corev1.RestartPolicyAlways,
|
|
Containers: []corev1.Container{{
|
|
Name: proxyContainerName,
|
|
Image: image,
|
|
Command: []string{"/bin/sh", "-c"},
|
|
Args: []string{writeConfigAndExec},
|
|
Env: []corev1.EnvVar{{
|
|
Name: "SQUID_CONF",
|
|
Value: squidConf(req.Port),
|
|
}},
|
|
Ports: []corev1.ContainerPort{{
|
|
ContainerPort: req.Port,
|
|
Protocol: corev1.ProtocolTCP,
|
|
}},
|
|
}},
|
|
},
|
|
}
|
|
}
|
|
|
|
// squidConf generates a minimal Squid config listening on port, permissive
|
|
// enough to forward CONNECT and plain HTTP to any destination. Open by
|
|
// design: this is a proxy for a private cluster, not internet-facing, and
|
|
// installing/configuring proxy software is explicitly out of scope for
|
|
// this operator's real (GCP) provider too — cloud-init is passed through
|
|
// there, never interpreted. via/forwarded_for are turned off so the proxy
|
|
// doesn't leak the Pod's identity to the origin.
|
|
func squidConf(port int32) string {
|
|
// max_filedescriptors is load-bearing in containers: squid sizes its FD
|
|
// tables from RLIMIT_NOFILE at startup, and containerd commonly sets
|
|
// that to effectively unlimited (kind: ~10^9) — squid then allocates
|
|
// gigabytes and is OOM-killed before it ever listens. cache_mem is
|
|
// trimmed because a forwarding proxy for crawling gains nothing from
|
|
// squid's 256 MB default cache.
|
|
return fmt.Sprintf(`http_port %d
|
|
acl all src 0.0.0.0/0
|
|
http_access allow all
|
|
via off
|
|
forwarded_for off
|
|
max_filedescriptors 1024
|
|
cache_mem 16 MB
|
|
`, port)
|
|
}
|