
network-endpoint-groups

## 问题分析

GKE Gateway 创建的 NEG 是 **GCP 层面的资源**，删除 K8s 侧的 HTTPRoute/Gateway 资源后，GCP 侧的 NEG 不一定会自动清理，原因：

| 原因             | 说明                                      |
| ---------------- | ----------------------------------------- |
| 控制器还在运行   | GKE Gateway Controller 可能还在 reconcile |
| 资源依赖未解除   | NEG 被 Backend Service 引用时无法删除     |
| Finalizer 未清理 | K8s 资源有 finalizer 阻止级联删除         |
| 控制器 Bug       | GKE 已知问题，NEG 有时需要手动清理        |

---

## 清理步骤

### Step 1：理清 NEG 的依赖链

NEG 被删除前必须先从 Backend Service 解绑：

```mermaid
graph LR
    A[Forwarding Rule] --> B[Target HTTP/HTTPS Proxy]
    B --> C[URL Map]
    C --> D[Backend Service]
    D --> E[NEG]
    E --> F[Pod IP Endpoints]

    style E fill:#ff6b6b
    style D fill:#ffa94d
```

```bash
# 1. 列出所有相关 NEG
gcloud compute network-endpoint-groups list \
  --format="table(name,zone,networkEndpointType,size)" \
  | grep <your-namespace-or-keyword>

# 2. 查看 NEG 被哪些 Backend Service 引用
NEG_NAME="your-neg-name"
ZONE="asia-east2-a"  # 替换为你的 zone

gcloud compute backend-services list --global \
  --format="table(name)" | while read BS; do
  gcloud compute backend-services describe $BS --global \
    --format="yaml(name,backends)" 2>/dev/null | grep -l "$NEG_NAME" && echo "Found in: $BS"
done

# 更直接的方式
gcloud compute backend-services list --global --format=json | \
  python3 -c "
import json,sys
data=json.load(sys.stdin)
neg='$NEG_NAME'
for bs in data:
  for b in bs.get('backends',[]):
    if neg in b.get('group',''):
      print(bs['name'])
"
```

### Step 2：从 Backend Service 移除 NEG

```bash
# 查看 Backend Service 的完整 backends 列表
gcloud compute backend-services describe <backend-service-name> \
  --global --format=yaml | grep -A5 "backends"

# 从 Backend Service 中移除该 NEG
gcloud compute backend-services remove-backend <backend-service-name> \
  --global \
  --network-endpoint-group=$NEG_NAME \
  --network-endpoint-group-zone=$ZONE
```

### Step 3：删除 NEG

```bash
# 单个删除
gcloud compute network-endpoint-groups delete $NEG_NAME \
  --zone=$ZONE \
  --quiet

# 批量删除（按 namespace 关键字过滤）
gcloud compute network-endpoint-groups list \
  --format="value(name,zone)" | grep <keyword> | \
  while read NAME ZONE; do
    echo "Deleting NEG: $NAME in $ZONE"
    gcloud compute network-endpoint-groups delete $NAME \
      --zone=$ZONE --quiet
  done
```

### Step 4：检查 K8s 侧 Finalizer 残留

```bash
# 检查是否有资源卡在 Terminating 状态
kubectl get httproute,gateway,gcpbackendpolicy -n <namespace> -A

# 如果有 Terminating 卡住的资源，强制移除 finalizer
kubectl patch httproute <name> -n <namespace> \
  --type=json \
  -p='[{"op":"remove","path":"/metadata/finalizers"}]'

kubectl patch gateway <name> -n <namespace> \
  --type=json \
  -p='[{"op":"remove","path":"/metadata/finalizers"}]'
```

### Step 5：验证清理完成

```bash
# 确认 NEG 已删除
gcloud compute network-endpoint-groups list | grep <keyword>

# 确认 Backend Service 无孤立 backend
gcloud compute backend-services list --global --format=json | \
  python3 -c "
import json,sys
data=json.load(sys.stdin)
for bs in data:
  backends = bs.get('backends',[])
  if not backends:
    print(f'Empty backends: {bs[\"name\"]}')
"

# 确认响应头 istio-envoy 消失
curl -sv http://<LB-IP>/ 2>&1 | grep -i "server\|transfer-encoding"
```

---

## 注意事项

```bash
# 如果 NEG 删除报错 "resourceInUseByAnotherResource"
# 说明还有 Backend Service 引用，先执行 Step 2

# 查看完整错误依赖
gcloud compute network-endpoint-groups delete $NEG_NAME \
  --zone=$ZONE 2>&1 | grep -i "used by\|referenced by"
```

| 清理顺序 | 资源                      | 原因               |
| -------- | ------------------------- | ------------------ |
| 1st      | HTTPRoute / Gateway (K8s) | 防止控制器重建 NEG |
| 2nd      | Backend Service 解绑 NEG  | 解除依赖           |
| 3rd      | NEG                       | 此时才能删除       |
| 4th      | 空的 Backend Service      | 可选清理           |

- **先删 K8s 资源**，否则 GKE Gateway Controller 会持续重建 NEG
- 删除前确认 NEG size 为 0，避免误删仍在服务的资源


不是。Ingress 和 Network Endpoint Groups 是两个不同的概念。

Ingress 是一个 Kubernetes 资源，用于将外部流量路由到 Kubernetes 集群中的 Pod。Ingress 可以使用各种规则来匹配请求，并将请求路由到特定的 Pod。

Network Endpoint Groups 是一个 Google Cloud 资源，用于将一组虚拟机或容器集群中的 IP 地址映射到一个 DNS 名称。Network Endpoint Groups 可以用于将流量路由到这些 IP 地址。

在 Google 工程中，Ingress 和 Network Endpoint Groups 可以一起使用来将外部流量路由到 Kubernetes 集群中的 Pod。例如，您可以创建一个 Ingress，将所有流量路由到一个 Network Endpoint Group。

但是，Ingress 本身并不是 Network Endpoint Group。Ingress 只是一个指向 Network Endpoint Group 的路由器。

以下是 Ingress 和 Network Endpoint Groups 之间一些关键区别：

| 特征   | Ingress                                  | Network Endpoint Group                                |
| ------ | ---------------------------------------- | ----------------------------------------------------- |
| 类型   | Kubernetes 资源                          | Google Cloud 资源                                     |
| 用途   | 将外部流量路由到 Kubernetes 集群中的 Pod | 将一组虚拟机或容器集群中的 IP 地址映射到一个 DNS 名称 |
| 功能   | 匹配请求并将请求路由到特定的 Pod         | 将 IP 地址映射到 DNS 名称                             |
| 可用性 | Kubernetes 集群                          | Google Cloud Platform                                 |


以下是一个使用 Ingress 和 Network Endpoint Groups 的示例：

1. 创建一个 Ingress 资源，将所有流量路由到一个 Network Endpoint Group。

2. 创建一个 Network Endpoint Group，将一组虚拟机或容器集群中的 IP 地址映射到一个 DNS 名称。

3. 将 Ingress 资源的 DNS 名称设置为 Network Endpoint Group 的 DNS 名称。

4. 当外部流量到达 Ingress 的 DNS 名称时，Ingress 将流量路由到 Network Endpoint Group 中的 IP 地址。

5. Network Endpoint Group 将流量路由到虚拟机或容器集群中的 Pod。

通过这种方式，您可以将外部流量路由到 Kubernetes 集群中的 Pod，而无需使用负载均衡器或代理服务器。

请注意，Ingress 和 Network Endpoint Groups 之间没有直接的关系。Ingress 只是一个路由器，将流量路由到 Network Endpoint Group。Network Endpoint Group 负责将流量路由到目标 IP 地址。

因此，Ingress 和 Network Endpoint Groups 可以一起使用，将外部流量路由到 Kubernetes 集群中的 Pod。


https://cloud.google.com/vpc/docs/private-service-connect?hl=zh-cn#endpoints


https://cloud.google.com/vpc/docs/private-service-connect?hl=zh-cn#backends

https://cloud.google.com/sdk/gcloud/reference/compute/network-endpoint-groups/create


如果我创建Network Endpoint Group报错,  Network Endpoint Group for private connect GOOGLE_APIS is not allowed 什么愿意?


该错误表示您尝试为私有连接创建 Network Endpoint Group (NEG)，但该 NEG 的服务类型为 GOOGLE_APIS。GOOGLE_APIS 服务类型仅用于 Google 内部使用，因此您无法创建此类型的 NEG。

要解决此错误，请将 NEG 的服务类型更改为其他值。例如，您可以将其更改为 HTTP、HTTPS 或 TCP。

以下是使用 gcloud CLI 更改 NEG 服务类型的示例：

```
gcloud compute network-endpoint-groups set-service-type NEG_NAME HTTP
```

替换 `NEG_NAME` 为您的 NEG 名称。

您还可以通过 Google Cloud 控制台更改 NEG 服务类型。为此，请转到 Google Cloud 控制台的 **网络** 页面，然后单击您的 NEG。在 **服务类型** 下，选择您要使用的服务类型。

完成上述步骤后，您应该能够成功创建 Network Endpoint Group。



是的，Network Endpoint Group 的创建有以下前提条件：

* 您必须有一个 VPC 网络和子网。
* 您必须为 NEG 选择一个区域。
* 您必须选择要将 NEG 与之关联的子网。

如果您满足上述所有条件，您就可以创建 Network Endpoint Group。

以下是有关 Network Endpoint Group 创建前提条件的详细信息：

* **VPC 网络和子网**：您必须创建一个 VPC 网络和子网，然后才能创建 NEG。您可以使用 Google Cloud 控制台、gcloud CLI 或 API 进行操作。
* **区域**：您必须为 NEG 选择一个区域。NEG 将在您选择的区域中创建。
* **子网**：您必须选择要将 NEG 与之关联的子网。NEG 将使用子网中的 IP 地址。

如果您不满足上述所有条件，您将收到错误消息。

 这个错误信息的意思是在GCP项目中,不允许为私有连接GOOGLE_APIS创建网络端点组(Network Endpoint Group)。

Google APIs是GCP提供的一组公共API和服务接口。这些API默认是公开的,用于GCP项目与Google服务集成。

而网络端点组(NEG)通常用于管理负载均衡后端集群的私有IP地址,提供更灵活的网络管理。

所以创建NEG时不应该选择Google API服务,这属于公共接口。相反,NEG应该关联在项目内的私有负载均衡后端资源上,比如GKE集群或者VM实例组。

所以在你创建NEG时选择的后端目标是Google APIs私有连接,这是不被允许的。你应该将后端目标改为项目内的Compute Engine实例或GKE集群工作负载。

总结一下原因:

1. Google APIs是公共接口,不能作为NEG的私有后端目标
2. NEG用于管理内部私有负载均衡后端集群
3. 所以不能在项目内为Google APIs创建NEG

我理解这可能是一个误操作。希望上述解释能帮助你明确原因和解决方法。


这个错误提示表明你正在尝试为 "GOOGLE_APIS" 创建私有连接（Private Google Access）时出现了问题。

Private Google Access 允许你的虚拟机实例（VM）访问 Google API 和服务，而不需要公共 IP 地址。但是，并非所有 Google 服务都支持 Private Google Access。

错误表明你尝试为 "GOOGLE_APIS" 创建 Network Endpoint Group（网络端点组），但是对于该服务来说，这是不被允许的。这可能是因为该服务不支持 Private Google Access，或者可能有其他限制。

你可以检查一下文档或者相关的错误消息，以获取更详细的信息。可能需要查看网络端点组和 Private Google Access 的文档，了解哪些服务支持私有连接，以及如何正确配置。确保你的操作是符合 Google Cloud 平台的限制和要求的。


是的，在 GKE 中创建 ingress deployment 时，系统会自动创建一个相应的 Network Endpoint Group (NEG)。NEG 是一个由 Pod IP 地址组成的逻辑集合，用于将流量负载均衡到这些 Pod 上。

当您创建 ingress deployment 时，系统会创建一个新的 NEG，并将该 NEG 与 ingress deployment 相关联。当您更新 ingress deployment 时，系统也会相应地更新 NEG。当您删除 ingress deployment 时，系统也会删除相应的 NEG。

您可以使用以下命令查看与 ingress deployment 关联的 NEG：

```
kubectl get networkendpointgroups -n <namespace>
```

其中 `<namespace>` 是您创建 ingress deployment 的命名空间。

您还可以使用以下命令查看 NEG 的详细信息：

```
kubectl describe networkendpointgroups <neg-name> -n <namespace>
```

其中 `<neg-name>` 是 NEG 的名称，`<namespace>` 是 NEG 所在的命名空间。

请注意，NEG 是一个内部资源，您无法直接访问它。但是，您可以通过查看 ingress deployment 的详细信息或使用 `kubectl` 命令来了解与 ingress deployment 关联的 NEG。
