将库存访问限制在应用内部

KubernetesBeginner
立即练习

介绍

Meadow Supply 有一个小型商品目录,以及正常工作的购物篮报价功能。其公开页面向 Shop API 查询供应情况。API 是 Application Programming Interface(应用程序编程接口)的缩写:在这里,它是顾客页面与内部库存服务之间的应用请求接口,由它为页面读取库存。目前,顾客进程和一个独立的访问者进程也可以直接读取库存,包括公开商品目录不需要的货架详情。

在保持正常顾客流程可用的同时,将库存连接限制为仅允许来自批准命名空间中的批准 API 角色。你将得到可复用的 NetworkPolicy 文件和与其一致的实际生效边界,以真实请求作为证据,而非仅凭图示上的绿色状态。

你应当已经了解基本终端路径、简单的 YAML、命名空间、Pod、Deployment、Service 和标签。本实验会在使用策略字段、提供的诊断命令和请求结果之前解释它们。带 Calico 的真实单节点 Kubernetes 集群、应用和合成数据均已准备就绪。无需安装集群、构建镜像或编写应用程序。时长由作者估计,包括阅读和处理普通错误的时间。这里的报价用于训练,不会下单、预留库存或付款。

仅允许通过批准路径访问库存

在这一步中,你将允许 Shop API 访问库存,同时阻止顾客进程和访问者进程绕过它。

从 Shop Tab 开始。Meadow Supply 应显示 Good things for everyday 和三件商品。打开 Glass water bottle,留意其 $18.00 价格和 Available · 6 in stock 状态,再将 Quantity 设为 1,选择 Try a basket quote。结果应显示 Ready for collection、**$18.00**,并明确说明没有预留库存、下单或付款。使用 Back to product,再使用 Back to collection 返回。

实际请求路径为:

顾客页面 → Shop API → 库存服务

顾客页面在自己的 Pod 中运行。打开网站不会让你的浏览器变成集群 Pod;库存请求来自准备好的应用进程。API 通过新的网络连接读取库存,并将其与批准的商品目录价格结合。它没有静态库存备用数据。独立的 Reference Tab 显示 Meadow Dispatch 提货记录。打开它,读取 P-104 和 P-108,再切换到 Workspace。这个独立服务必须继续工作。

终端起始目录为 /home/labex/project/stock-policy。pwd 打印当前目录;ls 列出目录条目。如需返回此处,请使用绝对路径 cd 命令:

pwd
ls
cd /home/labex/project/stock-policy

预期看到 scope.json、starter 和 tools。cat 打印准备好的操作范围文件。它使用 JSON(JavaScript Object Notation),一种由命名值和列表组成的文本格式。文件列出真实资源名称和请求目标,而非虚构的拓扑状态:

cat scope.json

--context=labex-v135 选择准备好的真实集群。--show-labels 显示对象标签。命名空间将对象分组,但本身并不会阻止其网络连接。读取命名空间身份:

kubectl --context=labex-v135 get namespaces meadow-shop meadow-stock meadow-visitors --show-labels

每个命名空间都有内置的 kubernetes.io/metadata.name 标签,值等于其名称。-n 选择命名空间。读取 Pod 及其标签:

kubectl --context=labex-v135 -n meadow-shop get pods --show-labels
kubectl --context=labex-v135 -n meadow-stock get pods --show-labels
kubectl --context=labex-v135 -n meadow-visitors get pods --show-labels

顾客进程的标签为 role=customer,API 为 role=shop-api,库存为 role=inventory。独立提货服务的标签为 role=dispatch。访问者位于 meadow-visitors,却刻意使用与真实 API 相同的 role=shop-api 标签。因此,仅凭角色标签不能识别批准的命名空间。

读取 Service。Service 选择准备好的 Pod,并提供稳定地址。端口标识应用的监听端点。TCP(Transmission Control Protocol,传输控制协议)为这些 Web 请求提供连接;库存进程监听 TCP 端口 8080:

kubectl --context=labex-v135 -n meadow-stock get services

提供的 ./tools/network-test 使用 kubectl exec,以现有应用身份发起真实请求。开头的 ./ 表示工具位于当前目录。第一个参数选择 customer、api、visitor、stock 或 reference;下一个选择 http、dns 或 dns-tcp;最后一个是目标。工具不会修改策略或修复应用。http 请求使用 HTTP(Hypertext Transfer Protocol,超文本传输协议),这是这些 Web/API 端点采用的请求与响应协议。完整名称 stock.meadow-stock.svc.cluster.local 通过集群 DNS(Domain Name System,域名系统)标识其命名空间中的库存 Service;DNS 将 Service 名称解析为地址。

先确认当前连接和内容。隔离之前,预期以下两个请求都成功:

./tools/network-test api http http://stock.meadow-stock.svc.cluster.local:8080/stock.json
./tools/network-test customer http http://stock.meadow-stock.svc.cluster.local:8080/stock.json

预期返回 HTTP_REPLY 200,后面是相同的库存数据:bottle 在货架 M-03 上有 6 件,notebook 在 M-08 上有 4 件,bag 在 M-12 上有 0 件。顾客应通过 API 获取公开的供应情况,而不是直接进行这种内部读取。这个基线证明,在限制访问之前目标处于正常运行状态。

NetworkPolicy 选择 Pod,并允许某个流量方向上的特定连接。Ingress 指到达所选 Pod 的入站连接。一旦入站策略选中库存,除 Kubernetes 文档规定的节点/自身流量例外之外,就只允许策略批准的入站路径。这是 Pod 网络控制,不是用户身份验证或 HTTP 授权。

创建发布目录。mkdir -p 在需要时创建目录,并保留已有目录。下面的 cat 命令将完整策略写入你自己的发布文件:> 将输出重定向到该文件;带引号的 YAML 标记让文本保持字面值,直到最后单独占一行的结束标记。重复执行只会替换这个可编辑策略文件。

mkdir -p release
cat > release/stock-ingress.yaml <<'YAML'
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: stock-ingress
  namespace: meadow-stock
spec:
  podSelector:
    matchLabels:
      role: inventory
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: meadow-shop
          podSelector:
            matchLabels:
              role: shop-api
      ports:
        - protocol: TCP
          port: 8080
YAML

应用前读取保存的文件:

cat release/stock-ingress.yaml

外层 podSelector 只选择库存,提货服务不在此策略范围内。在同一个 from 条目内,namespaceSelector 和 podSelector 必须同时匹配:来源必须位于 meadow-shop,并且具有 role=shop-api。两个选择器对齐在同一个列表项下。如果在内层 podSelector 前再添加一个短横线,就会创建第二个可选条件,含义变为 OR(或),使批准命名空间中的其他 Pod 也能访问。端口是库存 Pod 监听的 TCP 端口。此规则不限制 API 的出站连接。

apply -f 读取保存的清单,创建或更新指定名称的策略,不会重启应用:

kubectl --context=labex-v135 apply -f release/stock-ingress.yaml

describe 显示 Kubernetes 如何理解该规则:

kubectl --context=labex-v135 -n meadow-stock describe networkpolicy stock-ingress

读取选中的库存角色、来源命名空间和 API 角色,以及 TCP 端口。策略执行可能需要几秒钟才会收敛。先确认原本允许的请求仍返回完整数据:

./tools/network-test api http http://stock.meadow-stock.svc.cluster.local:8080/stock.json

现在测试来源必须被拒绝的两种不同原因:

./tools/network-test customer http http://stock.meadow-stock.svc.cluster.local:8080/stock.json
./tools/network-test visitor http http://stock.meadow-stock.svc.cluster.local:8080/stock.json

最后两条命令预期返回 NETWORK_TIMEOUT,且命令以非零状态退出。Customer 位于批准命名空间,但角色不正确;Visitor 的角色匹配,却位于错误的命名空间。连接被拒绝、DNS 错误或目标已停止,都不能证明隔离正确。API 对同一目标的成功请求是正向对照。如果刚应用策略后立即重复请求仍然成功,请等待几秒再试;在实际应拒绝的路径超时之前,不要认定隔离已经生效。

如果路径拼写有误,请使用之前的 pwd、ls 和绝对路径 cd,再重复失败的操作。如果 YAML 无法解析,请读取发布文件,与完整示例比较缩进和短横线的位置,重写这个可编辑文件后再次应用。如果 API 也被阻止,请检查 describe 和前面显示的标签及端口,修正保存的策略并重新应用。保留原始命名空间、标签、工作负载、Pod、Service、应用、源文件和诊断工具。不要停止库存、修改标签、使用 Pod IP/CIDR 规则、修改主机网络或重置 VM 来人为制造拒绝结果。

检查完整顾客流程

在这一步中,你将验证隔离后的完整顾客体验,并让独立的提货服务继续可用。

从 Workspace 开始,位于 /home/labex/project/stock-policy。Customer 的直接库存请求已被有意阻止,但 Customer 必须仍能访问 Shop API。通过原始路径请求商品目录:

./tools/network-test customer http http://api.meadow-shop.svc.cluster.local:8080/catalogue.json

预期返回 HTTP_REPLY 200 和已批准的三件商品,价格与数量保持原值:Glass water bottle 为 1800 分 / 6 件,Everyday notebook 为 1400 / 4,Canvas market bag 为 2400 / 0。API 还会报告哪个原始库存 Pod 作出了响应;公开页面不会暴露这种基础设施详情。API 路径成功与直接路径失败并不矛盾:API 会自行建立获准的库存连接。

切换到 Shop 并重新加载。打开 Glass water bottle,将 Quantity 设为 2,选择 Try a basket quote。预期看到 Ready for collection、Quantity 2、Total $36.00 和 Units available 6。阅读训练提示:不会预留库存。使用 Back to product 和 Back to collection 返回。

打开标记为 Back soon 的 Canvas market bag,尝试 Quantity 1 的报价。预期看到 Not enough stock、Total $24.00 和 Units available 0。这是有效的业务结果,不是网络故障;不要修改库存来让每次报价都成功。使用 Back to product,再使用 Back to collection 返回。打开 Our approach,阅读训练报价的说明,再使用 Back to collection 返回。

完成后的商品目录有三件原始商品和实时供应情况;将其标题、价格和供应状态与这个运行中的示例比较:

受到保护的 Meadow Supply 商品系列

切换到 Reference 并重新加载。P-104 · Ready 和 P-108 · Packed 必须仍然可见。选择 Download notes,打开实际下载的 notes.json:它包含两条未改变的提货记录,而不是库存数据。浏览器下载位置与终端工作区不同;本任务不要求把该文件复制到工作区。

返回 Workspace,从 Customer 读取同一个独立 Service:

./tools/network-test customer http http://dispatch.meadow-stock.svc.cluster.local:8080/notes.json

预期返回 HTTP_REPLY 200 和两条原始记录。策略选择的是库存 Pod,而不是整个库存命名空间。保留提货进程、数据和原始 Service;将其关闭会掩盖规则范围过大的问题。

你的交付内容是 release/stock-ingress.yaml 和与其匹配的实际生效边界。完整商品目录和两种报价结果必须继续由原始应用提供,同时两条直接绕过 API 的库存路径保持拒绝。保留每份准备好的源文件、应用对象和原始 Pod。如果页面显示 Live availability unavailable,请回到已教过的标签、策略和请求检查,只修正发布策略并重新应用;用静态页面替代不是修复。这里的测试是在一个准备好的集群上执行的有限次真实 TCP 请求,不是对生产安全或始终不间断可用的保证。

总结

你保留了真实的顾客 → API → 库存流程,同时阻止了角色错误的顾客进程,以及位于另一命名空间、角色却匹配的访问者进程直接读取库存。保存的入站策略表达了命名空间与角色必须同时匹配的关系,实时商品目录、训练报价和独立提货服务仍然正常工作。

NetworkPolicy 控制 Pod 网络路径,而非顾客身份验证。只有目标和获准连接仍正常工作时,超时才是有用的证据。下一个独立实验将考虑另一个方向:API 出站连接、DNS,以及其他策略带来的权限。