Wire the composition root: flags, providers, runnables, manifests, samples, docs

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-09 17:28:11 +02:00
parent add120c033
commit c489832ce7
21 changed files with 695 additions and 138 deletions

View File

@@ -0,0 +1,18 @@
apiVersion: v1
kind: Service
metadata:
labels:
control-plane: controller-manager
app.kubernetes.io/name: egress-proxies-operator
app.kubernetes.io/managed-by: kustomize
name: controller-manager-discovery-service
namespace: system
spec:
ports:
- name: discovery
port: 8090
protocol: TCP
targetPort: discovery
selector:
control-plane: controller-manager
app.kubernetes.io/name: egress-proxies-operator

View File

@@ -22,6 +22,8 @@ resources:
#- ../prometheus
# [METRICS] Expose the controller manager metrics service.
- metrics_service.yaml
# Expose the discovery/lease HTTP API inside the cluster.
- discovery_service.yaml
# Uncomment the patches line if you enable Metrics
patches:

View File

@@ -1,5 +1,6 @@
resources:
- manager.yaml
- providers_config.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
images:

View File

@@ -63,12 +63,28 @@ spec:
args:
- --leader-elect
- --health-probe-bind-address=:8081
- --providers-config=/etc/proxy-operator/providers.yaml
env:
# Bearer token for the discovery API. Optional: without the
# Secret the API serves unauthenticated (with a loud warning).
# Create it with:
# kubectl -n egress-proxies-operator-system create secret \
# generic discovery-token --from-literal=token=<your-token>
- name: DISCOVERY_TOKEN
valueFrom:
secretKeyRef:
name: discovery-token
key: token
optional: true
image: controller:latest
name: manager
ports:
- containerPort: 8081
name: health
protocol: TCP
- containerPort: 8090
name: discovery
protocol: TCP
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
@@ -96,7 +112,13 @@ spec:
requests:
cpu: 10m
memory: 64Mi
volumeMounts: []
volumes: []
volumeMounts:
- name: providers-config
mountPath: /etc/proxy-operator
readOnly: true
volumes:
- name: providers-config
configMap:
name: providers-config
serviceAccountName: controller-manager
terminationGracePeriodSeconds: 10

View File

@@ -0,0 +1,17 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: providers-config
namespace: system
labels:
app.kubernetes.io/name: egress-proxies-operator
app.kubernetes.io/managed-by: kustomize
data:
# Mounted at /etc/proxy-operator/providers.yaml (--providers-config).
# The default ships only the kubernetes-pod provider so the operator runs
# out of the box; add gcp entries (type: gcp, gcp.project: ...) for real
# egress fleets — see config/samples/providers-config.yaml.
providers.yaml: |
providers:
- name: kubernetes
type: kubernetes

View File

@@ -4,6 +4,16 @@ kind: ClusterRole
metadata:
name: manager-role
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- create
- delete
- get
- list
- watch
- apiGroups:
- ""
resources:

View File

@@ -1,9 +0,0 @@
apiVersion: crawl.example.com/v1alpha1
kind: Proxy
metadata:
labels:
app.kubernetes.io/name: egress-proxies-operator
app.kubernetes.io/managed-by: kustomize
name: proxy-sample
spec:
# TODO(user): Add fields here

View File

@@ -1,4 +1,8 @@
## Append samples of your project ##
# providers-config.yaml is deliberately absent: it is a sample
# --providers-config file, not a Kubernetes manifest.
resources:
- crawl_v1alpha1_proxy.yaml
- proxy_kubernetes.yaml
- proxy_gcp.yaml
- proxy_external.yaml
# +kubebuilder:scaffold:manifestskustomizesamples

View File

@@ -0,0 +1,21 @@
# Sample --providers-config file (not a Kubernetes manifest). In-cluster
# this content lives in the providers-config ConfigMap
# (config/manager/providers_config.yaml); for `make run-dev` a
# kubernetes-only variant is at hack/providers-dev.yaml.
#
# Named provider instances: "gcp-eu" and "gcp-us" are two configs of the
# same type. spec.provider on a Proxy refers to the name, not the type.
providers:
- name: kubernetes
type: kubernetes
# kubernetes:
# image: ubuntu/squid:6.6-24.04_edge # the default
- name: gcp-eu
type: gcp
gcp:
project: my-project
# network: default # VPC network name
# networkTag: proxy-operator # firewall tag on created instances
# diskSizeGb: 10
# auth: Application Default Credentials (workload identity
# in-cluster, gcloud ADC locally). No key-file plumbing.

View File

@@ -0,0 +1,15 @@
# An External proxy: the VM exists outside the operator's control; the
# operator only tracks and health-checks it through the endpoint. No
# finalizer, no provider calls, and deleting the CR touches nothing.
apiVersion: crawl.example.com/v1alpha1
kind: Proxy
metadata:
name: proxy-external-sample
spec:
mode: External
endpoint:
host: 203.0.113.7
port: 3128
attributes:
geo: eu
purpose: crawl

View File

@@ -0,0 +1,36 @@
# A Managed proxy backed by GCP: the operator creates a VM with an
# ephemeral external IP and installs Squid via cloud-init. Requires a
# providers-config entry named "gcp-eu" (see providers-config.yaml) and
# Application Default Credentials with compute.instanceAdmin.v1.
#
# All three placement fields are required for GCP; the operator sets the
# Proxy to Failed with a message naming any missing one.
apiVersion: crawl.example.com/v1alpha1
kind: Proxy
metadata:
name: proxy-gcp-sample
spec:
mode: Managed
provider: gcp-eu
placement:
zone: europe-west1-b
machineType: e2-micro
image: projects/debian-cloud/global/images/family/debian-12
port: 3128
cloudInit:
inline: |
#cloud-config
packages:
- squid
write_files:
- path: /etc/squid/conf.d/proxy-operator.conf
content: |
http_port 3128
http_access allow all
via off
forwarded_for off
runcmd:
- systemctl restart squid
attributes:
geo: eu
purpose: crawl

View File

@@ -0,0 +1,14 @@
# A Managed proxy backed by the kubernetes-pod provider: the operator runs
# a real Squid pod in this cluster. This is the local-dev/CI sample — pods
# share the cluster's egress IP, so it exercises the full lifecycle but
# does not provide a distinct egress path (use the gcp provider for that).
apiVersion: crawl.example.com/v1alpha1
kind: Proxy
metadata:
name: proxy-kubernetes-sample
spec:
mode: Managed
provider: kubernetes
attributes:
geo: local
purpose: crawl