konsole-is/fqdn-controller
GitHub: konsole-is/fqdn-controller
一个轻量级 Kubernetes Operator,通过动态 DNS 解析将 FQDN 转换为 IP 并维护到标准 NetworkPolicy 中,实现基于域名的出站流量控制。
Stars: 24 | Forks: 3
# fqdn-controller
[](https://artifacthub.io/packages/search?repo=fqdn-controller)
[](https://goreportcard.com/report/github.com/konsole-is/fqdn-controller)
[](LICENSE)
传统的 Kubernetes NetworkPolicy 对象不支持基于完全限定域名 (FQDN) 的规则。
因此,团队往往不得不安装复杂的解决方案,例如 Cilium、自定义 VPC CNI 或 Service Mesh,这会增加运维开销、额外的依赖项,以及与集群网络栈更深的集成。
fqdn-controller 弥补了这一不足,它通过一个控制器扩展 Kubernetes,该控制器动态地将 FQDN 解析为 IP,并将其维护在标准的 NetworkPolicy 对象中。它避免了侵入性的网络变更,并与默认的 CNI 协同工作,使其适用于运行在云端或优先考虑简单性和可移植性的环境中的集群。
## 📚 目录
- [✨ 功能特性](#-features)
- [⚠️ 限制](#-limitations)
- [🧾 CRD 概览](#-crd-overview)
- [重要行为说明](#important-behavior-notes)
- [资源类型与短名称](#resource-kind--short-name)
- [关键字段](#key-fields)
- [IP 过滤](#ip-filtering)
- [失败时的 IP 保留](#ip-retention-on-failure)
- [状态与可观测性](#status-and-observability)
- [📄 自定义资源示例](#custom-resource-example)
- [🚀 安装](#-installation)
- [Helm 安装](#helm-installation)
- [Kubectl 安装](#kubectl-installation)
- [🧪 开发](#-development)
- [📦 发布](#-releases)
- [🤝 贡献](#-contributing)
## ✨ 功能特性
- 基于域名 (FQDN) 创建 `NetworkPolicy` 出口规则
- 根据可配置的计划自动解析和刷新 IP
- 可选择过滤私有 IP 以强制执行安全策略
- 支持 IPv4、IPv6 或两者兼有
- 可通过 Artifact Hub 获取 Helm Chart
## ⚠️ 限制
该控制器不适用于 IP 解析高度动态的域名。例如,像 google.com 这样的域名可能每隔几分钟就会返回不同的 IP。如果您的工作负载依赖于与这些域名的稳定 IP 连接,并且无法容忍短暂的网络中断,那么此 Operator 可能无法满足您的需求。
尽管如此,拥有 mostly 静态 IP 但偶尔可能更改的域名仍然可以很好地工作。在这种情况下,在 IP 更改与下一次成功 DNS 解析之间的时间窗口内,网络连接可能会短暂中断。此中断的持续时间最多等于您策略中指定的 `ttlSeconds` 值。
## 🧾 CRD 概览
NetworkPolicy 自定义资源允许您通过域名指定出口规则。控制器对这些 FQDN 执行 DNS 解析,并将解析出的 IP 应用到[标准的 Kubernetes NetworkPolicy 对象](https://kubernetes.io/docs/concepts/services-networking/network-policies/)中。
### 资源类型与短名称
此控制器定义了一个资源类型为 `NetworkPolicy` 的自定义资源(位于 fqdn.konsole.is API 组下)。
为了避免与内置的 Kubernetes networking.k8s.io/v1 NetworkPolicy 冲突,该 CRD 注册为:
- 长名称:`fqdnnetworkpolicy`
- 短名称:`fqdn`
这允许您通过 kubectl 轻松与资源交互,而不会与标准资源发生冲突:
```
kubectl get fqdn # shorthand
kubectl get fqdnnetworkpolicy # full resource name
```
在检查或管理集群中基于 FQDN 的策略时,请使用这些名称。
### 关键字段
| 字段 | 描述 |
|--------------------------|------------------------------------------------------------------------|
| `podSelector` | 用于匹配目标 Pod 的选择器 |
| `egress.toFQDNs` | 允许流量访问的 FQDN 列表(每条规则最多 20 个) |
| `egress.ports` | 每条出口规则的端口和协议 |
| `egress.blockPrivateIPs` | 是否针对该规则排除 RFC1918 IP(覆盖全局设置) |
| `ttlSeconds` | 重新解析 FQDN 的频率(秒)。默认值:`60` |
| `resolveTimeoutSeconds` | DNS 查询的超时时间(秒)。默认值:`3` |
| `retryTimeoutSeconds` | 在丢弃过期 IP 之前继续使用的时间。默认值:`3600` |
| `blockPrivateIPs` | 是否全局排除私有 IP |
| `enabledNetworkType` | 允许的 IP 类型:`ipv4`、`ipv6` 或 `all`。默认值:`ipv4` |
### IP 过滤
可以使用 `blockPrivateIPs` 设置从解析出的 FQDN 结果中排除私有 IP (RFC1918)。这有助于执行限制仅流向公共端点流量的策略。
- 默认值为 `false`(允许私有 IP)。
- 设置 `spec.blockPrivateIPs: true` 可默认对所有出口规则应用过滤。
- 您可以使用 `egress[].blockPrivateIPs` 在每个规则的基础上覆盖此行为。
如果设置了此值,则该值优先于全局 spec.blockPrivateIPs。
### 失败时的 IP 保留
当 FQDN 解析失败时,之前解析出的 IP 不会立即移除。相反,它们会被保留并继续在底层 NetworkPolicy 中使用,直到 `retryTimeoutSeconds` 窗口到期。这确保了临时的 DNS 问题不会中断网络访问。
#### ✅ 保留 IP 的情况包括:
- `TIMEOUT`:DNS 服务器未及时响应
- `TEMPORARY`:发生暂时性网络错误
- `UNKNOWN`:控制器无法确定具体错误
- `OTHER_ERROR`:解析期间未指明的失败
#### ❌ 立即丢弃 IP 的情况包括:
- `INVALID_DOMAIN`:FQDN 格式无效且无法解析
- `NXDOMAIN`(又称 DOMAIN_NOT_FOUND):域名不存在(永久性失败)
在保留期 (`retryTimeoutSeconds`) 之后,如果解析未再次成功,该 FQDN 将从活动策略中移除。
如果您**不**希望为可能具有暂时性的解析失败保留 IP 地址,可以将 `retryTimeoutSeconds` 设置为零。
### 状态与可观测性
每个基于 FQDN 的 NetworkPolicy CR 都包含详细的状态信息,以帮助您监控行为并排查 DNS 或策略问题。
#### .status 中的关键字段:
- `conditions[]`\
标准 Kubernetes 条件,包括:
- `Ready`:控制器是否成功应用了解析出的 IP。
- `Resolve`:指示最近的 DNS 解析尝试是否成功。使用此选项可快速确定策略的运行状况和协调状态。这是所有 FQDN 查找的汇总摘要,显示了最高可测量的错误。
- `fqdns[]`\
每个 FQDN 的解析状态:
- `fqdn`:正在解析的域名。
- `lastSuccessfulTime`:最近一次成功解析的时间戳。
- `resolveReason`:最近一次 DNS 尝试的结果(SUCCESS、TIMEOUT、NXDOMAIN 等)。
- `resolveMessage`:描述结果的人类可读消息。
- `addresses[]`:该 FQDN 当前解析出的 IP 列表。
有助于调试流量被允许或未被允许的原因,以及验证 DNS 行为。
- `appliedAddressCount`
当前应用于底层 NetworkPolicy 的唯一 IP 数量(经过过滤、重试和去重后)。
- `totalAddressesCount`
所有解析出的 IP 总数,包括因 blockPrivateIPs 或其他约束而被过滤掉的 IP(去重后)。
- `latestLookupTime`
上次解析此策略 FQDN 的时间。有助于追踪 IP 的新鲜度。
其中一些字段也会显示在 `kubectl get` 中,以便快速检查:
```
kubectl get fqdn networkpolicy-sample
NAME READY RESOLVED RESOLVED IPs APPLIED IPs LAST LOOKUP AGE
networkpolicy-sample True False 5 3 31s 2m
```
### 自定义资源示例
```
apiVersion: fqdn.konsole.is/v1alpha1
kind: NetworkPolicy
metadata:
name: networkpolicy-sample
namespace: default
spec:
podSelector:
matchLabels:
app: my-app
enabledNetworkType: ipv4
ttlSeconds: 60
resolveTimeoutSeconds: 3
retryTimeoutSeconds: 3600
blockPrivateIPs: false
egress:
- toFQDNS:
- api.example.com
- github.com
ports:
- protocol: TCP
port: 443
- toFQDNS:
- telemetry.example.net
ports:
- protocol: TCP
port: 443
blockPrivateIPs: true
```
## 🚀 安装
### Helm 安装
如果您希望在 helm chart 之外管理 CRD,可以从 release manifests 安装它们。如果您希望这样做,必须使用标志 `--set crd.enable=false` 在 helm chart 中显式禁用 crd 安装。
```
curl -sL https://github.com/konsole-is/fqdn-controller/releases/download//crds.yaml | kubectl apply -f -
```
Chart 安装
```
helm repo add fqdn-controller https://konsole-is.github.io/fqdn-controller/charts
helm install fqdn-controller fqdn-controller/fqdn-controller --version
```
### Kubectl 安装
```
curl -sL https://github.com/konsole-is/fqdn-controller/releases/download//install.yaml | kubectl apply -f -
```
注意:除非修改,否则将仅包含 1 个副本。
## 🧪 开发
该仓库配置了 [ASDF](https://asdf-vm.com/) 以安装项目依赖项。
运行 `make help` 获取开发命令的信息。
## 📦 发布
- Helm Chart:[Artifact Hub]()
- CRD Bundle:[GitHub Releases](https://github.com/konsole-is/fqdn-controller/releases)
- Release manifest:[GitHub Releases](https://github.com/konsole-is/fqdn-controller/releases)
## 🤝 贡献
欢迎贡献、错误报告和反馈!
请根据需要提交 issues 或 pull requests。
标签:3D图, ACL, CNI 兼容, Egress 流量控制, EVTX分析, EVTX分析, FQDN, Go, Helm Chart, K8s 安全, LangChain, Operator, Ruby工具, SYN扫描, 出站流量, 动态 IP 管理, 域名解析, 日志审计, 服务发现, 网络安全, 网络策略, 访问控制列表, 轻量级, 隐私保护, 零信任网络