[译] 解密 Cilium 原生认证功能

在本文中,我们更深入地探讨了 Cilium 的功能,特别是它从服务网格获得的相互认证功能。

声明
此文为个人翻译,仅供参考,不代表我个人立场。翻译过程中可能有删改或遗漏,如需了解原文,请自行查阅。如有疏漏,欢迎指正。
查看本文大纲

我们已经讨论了 Cilium 一段时间了,但是这个话题有很多值得关注的地方,我们知道我们会再次回到这个话题。今天,我建议我们探索一个用于认证工作负载的功能。在讨论这个话题之前,我们需要一些定义。

我们的议程将按照以下顺序进行:

  1. 了解 Cilium 认证功能
  2. 尝试认证功能

Cilium 认证功能

为什么我们需要认证

在基于微服务的架构中,安全是一个巨大的话题。在 Kubernetes 环境中,我们可以查看网络,并通过限制只允许必要端口和协议的流量来实施最小权限原则。在这种情况下,我们可以依赖网络策略。例如,这个策略拒绝 basic 命名空间中的所有入站流量:

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: default-deny-all
  namespace: basics
spec:
  podSelector: {}
  ingress: []

这个策略仅允许标有 app=userprofile 标签的 pod 在端口 8082 上从带有标签 tier=frontapp=tripsinsights 的命名空间中的 pod 接收流量。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-tripviewer-ingress-apiprofile
  namespace: api
spec:
  podSelector: 
    matchLabels:
      app: userprofile
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          tier: front
          app: tripinsights
    ports:
    - protocol: TCP
      port: 8082   

但这可能还不够,全局管理也相当困难,这是分布式安全的悖论。

我们在之前的文章中谈到了服务网格,其目的是为网络流量提供一个集中的控制平面。我们还看到,在标准化的倡议中,我们有一些特定的流量控制对象,其中包括了认证功能。

apiVersion: access.smi-spec.io/v1alpha4
kind: IdentityBinding
metadata:
 name: service-a
 namespace: default
spec:
 schemes:
   podLabelSelector:
    matchLabels:
      app: service-a
   spiffeIdentities:
     - "cluster.local/ns/default/sa/service-a"
     - "federated.trustdomain/boundary/boundaryName/identifierType/identifier"
   serviceAccount: service-a

我们将在 Cilium 服务网格中,尤其是基于身份的安全性方面探讨这一点。在基础设施层拥有这样的功能是有趣的,因为应用层不总是能够包含认证功能,尤其是当我们考虑多服务时。最多,不幸的是,我们可能在前端获得认证,但不会更多。这里,我们提出了增加基于身份的安全性的建议。

让我们看看它是如何工作的。

Cilium 认证功能的底层原理

认证意味着,某种程度上,身份。正如之前在 smi 规范中暗示的,并在 Cilium 文档中记录的,所使用的技术是 SPIFFE,即每个人的安全生产身份框架。它也是 CNCF 中的一个毕业项目,自 2022 年 8 月以来。Spiffe 规范在一个 专用的 github上定义。

此时,我们将在 github 仓库中描述的 SPIFFE 标准的高层概述,其中包括:

  • SPIFFE ID,一个结构化的字符串(表示为 URI),用作实体的“名称”。
  • SPIFFE 可验证身份文档(SVID)是携带 SPIFFE ID 的文档。它是护照的功能等同物 - 一个携带提供者身份的文档。
  • 工作负载 API 是工作负载或计算过程获取其 SVID 的方法。它通常在本地暴露(例如,通过 Unix 域套接字),并且明确不包括来自工作负载的认证握手或认证令牌。

此外,重要的是要提到信任域,这是一个身份命名空间,由一组加密密钥支持的发行机构支持。这些密钥共同作为居住在信任域中的所有身份的加密锚点。

再次强调,由于 SPIFFE 是一组规范,所有这些概念/标准实际上都在 github 仓库中详细说明。

现在我们知道了规范和标准,但还有很多工作要做,因为,毕竟,这只是规范。幸运的是,还有 SPIRE 项目另一个毕业的 CNCF 项目,这是 SPIFFE 规范的一个生产就绪实现。

在 Cilium 中,SPIFFE 的实现基于 SPIRE 中央服务器。这个 SPIRE 服务器扮演我们之前在规范和标准中提到的信任域的角色。它与每个节点的 SPIRE 代理一起工作,这些代理从服务器获取自己的身份,然后验证工作负载的身份请求。

要了解 SPIRE 是如何工作的,我们需要再次一些概念:

  • 工作负载注册是 SPIRE 将能够识别所述工作负载的过程。它告诉 SPIRE 如何识别工作负载以及给它分配哪个 SPIFFE ID。
  • SPIRE 实现工作负载的认证,即断言其身份,通过收集来自工作负载和运行 SPIRE 代理的节点的属性。还值得注意的是,认证是由称为 认证器 的软件完成的。在我们的案例中,我们将有一个 Kubernetes 认证器用于托管在 Kubernetes 上的工作负载,但也有节点认证器用于需要首先注册的 SPIRE 代理,然后才能进行工作负载认证。在 Azure 上,节点认证/注册依赖于具有托管身份的 Azure VMs。

节点认证遵循以下步骤:

  1. 代理节点认证器插件查询平台以获取节点身份的证明,并将该信息提供给代理。
  2. 代理将这个身份证明传递给服务器。服务器将这些数据传递给其节点认证器。
  3. 服务器节点认证器通过调用平台 API 验证身份证明,使用它在第 2 步中获得的信息。节点认证器还为代理创建一个 SPIFFE ID,并将此 ID 以及它发现的任何节点选择器一起传回服务器进程。
  4. 服务器为代理节点发送回一个 SVID。
image
图 1:节点认证流程

一个请求身份的工作负载遵循以下步骤:

  1. 它调用代理公开的工作负载 API 请求一个 SVID。
  2. 代理询问调用工作负载认证器插件,向其提供有关工作负载的信息。
  3. 工作负载认证器通过查询邻近的平台特定组件(如 Kubernetes kubelet)发现有关工作负载的额外信息。
  4. 认证器将发现的信息以选择器的形式返回给代理。
  5. 代理通过将发现的选择器与注册条目进行比较来确定工作负载的身份,并将正确的缓存 SVID 返回给工作负载。
image
图 2:工作负载认证流程

好了,这就是这个概述的全部内容。SPIFFE 规范中还有更多细节,我只能建议进行更彻底的阅读以获得更好的理解。让我们看看当我们在 AKS 集群中部署时情况如何。

尝试 Cilium 认证

准备环境

为了尝试这个功能,我们将使用一个仅包含 AKS 集群及其默认节点池的环境,位于虚拟网络中。

shcemainfra

认证需要在安装 Cilium 时指定,参数 authentication.mutual.spire.enabledauthentication.mutual.spire.install.enabled 必须设置为 true。

我们使用的 Helm 参数的完整列表如下所示

Helm 参数 描述
hubble.relay.enabled true 启用 Hubble Relay
hubble.ui.enabled true 是否启用 Hubble UI
aksbyocni.enabled true 启用 AKS BYOCNI 集成。注意,这与未在 BYOCNI 模式下创建的 AKS 集群不兼容:改用 Azure 集成(azure.enabled)。
nodeinit.enabled true 启用节点初始化 DaemonSet
kubeProxyReplacement true 替换 kubeproxy
k8sServiceHost “" Kubernetes 服务主机 - 使用“auto”从集群信息 ConfigMap 中自动查找(仅限基于 kubeadm 的集群)
k8sServicePort 443 Kubernetes 服务端口
cluster.id 1 集群的唯一 ID。必须在所有连接的集群中是唯一的,并且在 1 到 255 的范围内。只有在使用 Cluster Mesh 时才需要,如果不使用 Cluster Mesh 可以为 0。
cluster.name “" 集群的名称。只有在使用 Cluster Mesh 和与 SPIRE 的互相认证时才需要。它必须满足以下限制:* 最多包含 32 个字符;* 必须以小写字母或数字字符开头和结尾;* 之间可以包含小写字母或数字字符和破折号。如果集群 ID 不同于 0,则不能使用“default”名称。
azure.resourceGroup “" AKS 资源组
ipam.operator.clusterPoolIPv4PodCIDRList “{Ip_Range}” PoolIPv4PodCIDRList 列表 [“10.0.0.0/8”] IPv4 CIDR 范围列表,分配给单个节点用于 IPAM。
prometheus.enabled true 启用 prometheus 指标
operator.prometheus.enabled true 启用以 OpenMetrics 格式导出 hubble 指标。
hubble.metrics.enableOpenMetrics false 启用以 OpenMetrics 格式导出 hubble 指标。
hubble.metrics.enabled “{dns,drop,tcp,flow,port-distribution,icmp,httpV2:exemplars=true;labelsContext=source_ip,source_namespace,source_workload,destination_ip,destination_namespace,destination_workload,traffic_direction}” 配置要收集的指标列表。如果为空或 null,则禁用指标。示例:enabled: - dns:query;ignoreAAAA - drop - tcp - flow - icmp - http 您可以从 helm CLI 指定指标列表:–set hubble.metrics.enabled=”{dns:query;ignoreAAAA,drop,tcp,flow,icmp,http}”
authentication.mutual.spire.enabled true mutual.spire.enabled bool false 启用 SPIRE 集成(beta)
authentication.mutual.spire.install.enabled true ion.mutual.spire.install.enabled bool true 启用 SPIRE 安装。这将仅在 authentication.mutual.spire.enabled 为 true 时生效

安装完成后,我们可以查看 Cilium 的状态。

yumemaru@azure:~$ cilium status
    /¯¯\
 /¯¯\__/¯¯\    Cilium:             OK
 \__/¯¯\__/    Operator:           OK
 /¯¯\__/¯¯\    Envoy DaemonSet:    OK
 \__/¯¯\__/    Hubble Relay:       OK
    \__/       ClusterMesh:        disabled

Deployment             hubble-ui          Desired: 1, Ready: 1/1, Available: 1/1
DaemonSet              cilium-envoy       Desired: 3, Ready: 3/3, Available: 3/3
DaemonSet              cilium             Desired: 3, Ready: 3/3, Available: 3/3
Deployment             hubble-relay       Desired: 1, Ready: 1/1, Available: 1/1
Deployment             cilium-operator    Desired: 2, Ready: 2/2, Available: 2/2
Containers:            cilium             Running: 3
                       hubble-ui          Running: 1
                       cilium-envoy       Running: 3
                       cilium-operator    Running: 2
                       hubble-relay       Running: 1
Cluster Pods:          29/29 managed by Cilium
Helm chart version:    1.16.0
Image versions         cilium             quay.io/cilium/cilium:v1.16.0@sha256:46ffa4ef3cf6d8885dcc4af5963b0683f7d59daa90d49ed9fb68d3b1627fe058: 3
                       hubble-ui          quay.io/cilium/hubble-ui:v0.13.1@sha256:e2e9313eb7caf64b0061d9da0efbdad59c6c461f6ca1752768942bfeda0796c6: 1
                       hubble-ui          quay.io/cilium/hubble-ui-backend:v0.13.1@sha256:0e0eed917653441fded4e7cdb096b7be6a3bddded5a2dd10812a27b1fc6ed95b: 1
                       cilium-envoy       quay.io/cilium/cilium-envoy:v1.29.7-39a2a56bbd5b3a591f69dbca51d3e30ef97e0e51@sha256:bd5ff8c66716080028f414ec1cb4f7dc66f40d2fb5a009fff187f4a9b90b566b: 3
                       cilium-operator    quay.io/cilium/operator-generic:v1.16.0@sha256:d6621c11c4e4943bf2998af7febe05be5ed6fdcf812b27ad4388f47022190316: 2
                       hubble-relay       quay.io/cilium/hubble-relay:v1.16.0@sha256:33fca7776fc3d7b2abe08873319353806dc1c5e07e12011d7da4da05f836ce8d: 1

我们还可以查看其他 Kubernetes 对象:

  • 一个 SPIRE 服务器的部署
  • 在每个节点上运行的代理的守护进程集。
yumemaru@azure:~$ k get all -n cilium-spire 
NAME                    READY   STATUS    RESTARTS   AGE
pod/spire-agent-65sh2   1/1     Running   0          7h2m
pod/spire-agent-hqnsm   1/1     Running   0          7h2m
pod/spire-agent-lcqrz   1/1     Running   0          7h2m
pod/spire-server-0      2/2     Running   0          24h

NAME                   TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
service/spire-server   ClusterIP   100.65.61.5   <none>        8081/TCP   27h

NAME                         DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
daemonset.apps/spire-agent   3         3         3       3            3           <none>          27h

NAME                            READY   AGE
statefulset.apps/spire-server   1/1     27h

在进行一些测试之前,让我们看看我们的 SPIRE 服务器。我们可以在相应文档中找到查看它的命令。

首先我们可以检查 SPIRE 服务器的健康状况:

yumemaru@azure:~$ kubectl exec -n cilium-spire spire-server-0 -c spire-server -- /opt/spire/bin/spire-server healthcheck
Server is healthy.

然后我们可以看看 SPIRE 代理及其认证状态。因为我们有 3 个节点,所以在守护进程集中有 3 个 pod

yumemaru@azure:~$ k get ds -n cilium-spire 
NAME          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
spire-agent   3         3         3       3            3           <none>          27h

yumemaru@azure:~$ kubectl exec -n cilium-spire spire-server-0 -c spire-server -- /opt/spire/bin/spire-server agent list
Found 3 attested agents:

SPIFFE ID         : spiffe://spiffe.cilium/spire/agent/k8s_psat/cluster1/c0c6afc3-1e0a-4ffb-b61e-18442b04123d
Attestation type  : k8s_psat
Expiration time   : 2024-07-30 17:27:15 +0000 UTC
Serial number     : 8338212869267325996294354393424215766
Can re-attest     : true

SPIFFE ID         : spiffe://spiffe.cilium/spire/agent/k8s_psat/cluster1/08af80d6-0166-4f46-b575-0aa0dc6a5152
Attestation type  : k8s_psat
Expiration time   : 2024-07-30 17:27:15 +0000 UTC
Serial number     : 317183292034746089049553637864798125627
Can re-attest     : true

SPIFFE ID         : spiffe://spiffe.cilium/spire/agent/k8s_psat/cluster1/bdd0dfa9-20ec-4f24-a82f-c646754588ce
Attestation type  : k8s_psat
Expiration time   : 2024-07-30 17:27:15 +0000 UTC
Serial number     : 215301213544348190052950735212628656167
Can re-attest     : true

接下来我们可以检查 SPIFFE 身份。

yumemaru@azure:~$ kubectl exec -n cilium-spire spire-server-0 -c spire-server -- /opt/spire/bin/spire-server entry show -parentID spiffe://spiffe.cilium/ns/cilium-spire/sa/spire-agent
Found 2 entries
Entry ID         : 53b6506b-ebe3-4cd8-89b4-9647fa535c37
SPIFFE ID        : spiffe://spiffe.cilium/cilium-agent
Parent ID        : spiffe://spiffe.cilium/ns/cilium-spire/sa/spire-agent
Revision         : 0
X509-SVID TTL    : default
JWT-SVID TTL     : default
Selector         : k8s:ns:kube-system
Selector         : k8s:sa:cilium

Entry ID         : 8c361104-31a1-480e-b97d-83673a63ce72
SPIFFE ID        : spiffe://spiffe.cilium/cilium-operator
Parent ID        : spiffe://spiffe.cilium/ns/cilium-spire/sa/spire-agent
Revision         : 0
X509-SVID TTL    : default
JWT-SVID TTL     : default
Selector         : k8s:ns:kube-system

使用相互认证

现在让我们部署一些工作负载。为了简单起见,我们将创建一系列基于 nginx 的部署:

一个目标应用:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: demodeployment
  name: demodeployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: demodeployment
  strategy: {}
  template:
    metadata:
      labels:
        app: demodeployment
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
status: {}
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: demodeployment
  name: demodeployment
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: demodeployment
status:
  loadBalancer: {}

以及客户端:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: client1
  name: client1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: client1
  strategy: {}
  template:
    metadata:
      labels:
        app: client1
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
status: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: client2
  name: client2
spec:
  replicas: 3
  selector:
    matchLabels:
      app: client2
  strategy: {}
  template:
    metadata:
      labels:
        app: client2
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
status: {}

如果我们查看 Cilium 端点,我们应该能看到关联身份的信息:

yumemaru@azure:~$ k get ciliumendpoint -o wide
NAME                             SECURITY IDENTITY   INGRESS ENFORCEMENT   EGRESS ENFORCEMENT   VISIBILITY POLICY   ENDPOINT STATE   IPV4           IPV6
client1-599c487979-dqm4v         76513                                                                              ready            100.64.1.197   
client1-599c487979-qqzvl         76513                                                                              ready            100.64.0.206   
client1-599c487979-t8728         76513                                                                              ready            100.64.2.214   
client2-d64dd865b-cj56m          77602                                                                              ready            100.64.0.77    
client2-d64dd865b-kb7cs          77602                                                                              ready            100.64.1.51    
client2-d64dd865b-qskqc          77602                                                                              ready            100.64.2.25    
demodeployment-bf5d895b5-6s4xn   108597                                                                             ready            100.64.0.124   
demodeployment-bf5d895b5-pmzkm   108597                                                                             ready            100.64.1.244   
demodeployment-bf5d895b5-vz4gq   108597                                                                             ready            100.64.2.127   

使用安全身份值,我们可以在 SPIRE 服务器上检查相应的身份。我们将使用 '{.items[0].status.identity.id}' 作为 jsonpath 值来提取安全身份作为变量。

yumemaru@azure:~$ k get deployment --show-labels 
NAME             READY   UP-TO-DATE   AVAILABLE   AGE   LABELS
client1          3/3     3            3           14h   app=client1
client2          3/3     3            3           14h   app=client2
demodeployment   3/3     3            3           15h   app=demodeployment
yumemaru@azure:~$ export client1=$(k get ciliumendpoints.cilium.io -l app=client1 -o=jsonpath='{.items[0].status.identity.id}')id}')
yumemaru@azure:~$ export client2Id=$(k get ciliumendpoints.cilium.io -l app=client2 -o=jsonpath='{.items[0].status.identity.id}')
yumemaru@azure:~$ export demoId=$(k get ciliumendpoints.cilium.io -l app=demodeployment -o=jsonpath='{.items[0].status.identity.id}')

在 SPIRE 服务器 pod 内部,我们现在可以检查每个工作负载对应的身份:

yumemaru@azure:~$ kubectl exec -n cilium-spire spire-server-0 -c spire-server -- /opt/spire/bin/spire-server entry show -spiffeID spiffe://spiffe.cilium/identity/$client1Id
Found 1 entry
Entry ID         : 7bf9a3b0-a06c-480e-8f0c-1fd654d3ec56
SPIFFE ID        : spiffe://spiffe.cilium/identity/76513
Parent ID        : spiffe://spiffe.cilium/cilium-operator
Revision         : 0
X509-SVID TTL    : default
JWT-SVID TTL     : default
Selector         : cilium:mutual-auth

yumemaru@azure:~$ kubectl exec -n cilium-spire spire-server-0 -c spire-server -- /opt/spire/bin/spire-server entry show -spiffeID spiffe://spiffe.cilium/identity/$client2Id
Found 1 entry
Entry ID         : 62b158d0-c90b-449a-9b30-a8a24ba012ba
SPIFFE ID        : spiffe://spiffe.cilium/identity/77602
Parent ID        : spiffe://spiffe.cilium/cilium-operator
Revision         : 0
X509-SVID TTL    : default
JWT-SVID TTL     : default
Selector         : cilium:mutual-auth

yumemaru@azure:~$ kubectl exec -n cilium-spire spire-server-0 -c spire-server -- /opt/spire/bin/spire-server entry show -spiffeID spiffe://spiffe.cilium/identity/$demoId
Found 1 entry
Entry ID         : 07f27f3c-7a94-450b-aecc-bb006f57b97e
SPIFFE ID        : spiffe://spiffe.cilium/identity/108597
Parent ID        : spiffe://spiffe.cilium/cilium-operator
Revision         : 0
X509-SVID TTL    : default
JWT-SVID TTL     : default
Selector         : cilium:mutual-auth

但也可以直接作为 cilium api 对象查看身份。以下是 client1 应用的结果:

yumemary@azure:~$ k describe ciliumidentities.cilium.io $client1Id 
Name:         76513
Namespace:    
Labels:       app=client1
              io.cilium.k8s.policy.cluster=cluster1
              io.cilium.k8s.policy.serviceaccount=default
              io.kubernetes.pod.namespace=default
Annotations:  <none>
API Version:  cilium.io/v2
Kind:         CiliumIdentity
Metadata:
  Creation Timestamp:  2024-07-30T16:46:43Z
  Generation:          1
  Resource Version:    224640
  UID:                 433dd70b-58ba-41c0-abef-c9d5785eaddb
Security - Labels:
  k8s:app:                                                         client1
  k8s:io.cilium.k8s.namespace.labels.kubernetes.io/metadata.name:  default
  k8s:io.cilium.k8s.policy.cluster:                                cluster1
  k8s:io.cilium.k8s.policy.serviceaccount:                         default
  k8s:io.kubernetes.pod.namespace:                                 default
Events:                                                            <none>

我们会注意到 Cilium 身份名称、Cilium 端点上显示的安全身份和我们在 SPIRE 服务器上得到的 SPIFFE ID spiffe://spiffe.cilium/identity/76513 之间的对应关系。

那很好。现在,我们如何强制执行相互认证呢?实际上很简单,我们只需要在 Cilium 网络策略中添加适当的参数:

authentication:
    mode: "required"

让我们编写 3 个网络策略:

  • 首先,按应有的方式,一个拒绝所有策略。
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "demo1-default-deny"
  namespace: default
spec:
  description: "Default-deny ingress policy for demo app"
  endpointSelector:
    matchLabels:
      app: demodeployment
  ingress:
  - {}
  • 其次,一个允许 app1 流量到 demo 应用的策略。
  • 第三,一个网络策略允许 app2 到 demo 应用,但这次需要认证。

如果我们仅应用第一个策略,我们应该无法再访问 demo 应用。这可以通过 hubble observe 命令看到

yumemary@azure:~$ k exec deployments/client1 -- curl -i -X GET http://demodeployment
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:--  0:02:09 --:--:--     0
curl: (28) Failed to connect to demodeployment port 80 after 129180 ms: Couldn't connect to server
command terminated with exit code 28
yumemary@azure:~$ hubble observe --to-label app=demodeployment
Jul 31 09:54:42.541: default/client1-599c487979-t8728:54548 (ID:76513) -> default/demodeployment-bf5d895b5-pmzkm:80 (ID:108597) to-overlay FORWARDED (TCP Flags: SYN)

然而,我们仍然可以访问 client2 部署的一个 pod,因为我们只针对其标签的 demo 应用。

yumemary@azure:~$ k get pod -o custom-columns=Name:.metadata.name,PodIp:.status.podIP,HostIp:.status.hostIP
Name                             PodIp          HostIp
client1-599c487979-dqm4v         100.64.1.197   172.21.14.69
client1-599c487979-qqzvl         100.64.0.206   172.21.14.68
client1-599c487979-t8728         100.64.2.214   172.21.14.70
client2-d64dd865b-cj56m          100.64.0.77    172.21.14.68
client2-d64dd865b-kb7cs          100.64.1.51    172.21.14.69
client2-d64dd865b-qskqc          100.64.2.25    172.21.14.70
client3-6fbfd96c6f-bwhqh         100.64.1.150   172.21.14.69
client3-6fbfd96c6f-cfhhv         100.64.0.91    172.21.14.68
client3-6fbfd96c6f-wldx5         100.64.2.95    172.21.14.70
demodeployment-bf5d895b5-6s4xn   100.64.0.124   172.21.14.68
demodeployment-bf5d895b5-pmzkm   100.64.1.244   172.21.14.69
demodeployment-bf5d895b5-vz4gq   100.64.2.127   172.21.14.70
yumemary@azure:~$ k exec deployments/client1 -- curl -i -X GET http://100.64.2.25
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   615  100   615    0     0   499k      0 --:--:-- --:--:-- --:--:--  600k
HTTP/1.1 200 OK
Server: nginx/1.27.0
Date: Wed, 31 Jul 2024 10:01:58 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 28 May 2024 13:22:30 GMT
Connection: keep-alive
ETag: "6655da96-267"
Accept-Ranges: bytes

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

实施策略 2 和 3

现在我们来从客户端 1 和客户端 2 使用命令 kubectl exec deployments/<deploymentname> -- curl -i -X GET http://demodeployment 访问 demo 应用,我们可以通过 hubble 观察到客户端 1 的流量被授权:

yumemary@azure:~$ hubble observe --to-label app=demodeployment --from-label app=client1
Jul 31 11:33:48.647: default/client1-599c487979-t8728:54594 (ID:76513) <> default/demodeployment-bf5d895b5-vz4gq (ID:108597) pre-xlate-rev TRACED (TCP)
Jul 31 11:33:48.647: default/client1-599c487979-t8728 (ID:76513) <> default/demodeployment-bf5d895b5-vz4gq:80 (ID:108597) post-xlate-fwd TRANSLATED (TCP)
Jul 31 11:33:48.647: default/client1-599c487979-t8728:54594 (ID:76513) -> default/demodeployment-bf5d895b5-vz4gq:80 (ID:108597) policy-verdict:L3-L4 INGRESS ALLOWED (TCP Flags: SYN)
Jul 31 11:33:48.647: default/client1-599c487979-t8728:54594 (ID:76513) -> default/demodeployment-bf5d895b5-vz4gq:80 (ID:108597) to-endpoint FORWARDED (TCP Flags: SYN)
Jul 31 11:33:48.647: default/client1-599c487979-t8728:54594 (ID:76513) -> default/demodeployment-bf5d895b5-vz4gq:80 (ID:108597) to-endpoint FORWARDED (TCP Flags: ACK)

以及客户端 2 的认证步骤:

yumemary@azure:~$ hubble observe --to-label app=demodeployment --from-label app=client2
Jul 31 11:35:18.651: default/client2-d64dd865b-qskqc (ID:77602) <> default/demodeployment-bf5d895b5-6s4xn:80 (ID:108597) post-xlate-fwd TRANSLATED (TCP)
Jul 31 11:35:18.651: default/client2-d64dd865b-qskqc:50986 (ID:77602) -> default/demodeployment-bf5d895b5-6s4xn:80 (ID:108597) to-overlay FORWARDED (TCP Flags: SYN)
Jul 31 11:35:18.651: default/client2-d64dd865b-qskqc:50986 (ID:77602) <> default/demodeployment-bf5d895b5-6s4xn:80 (ID:108597) policy-verdict:L3-L4 INGRESS DENIED (TCP Flags: SYN; Auth: SPIRE)
Jul 31 11:35:18.651: default/client2-d64dd865b-qskqc:50986 (ID:77602) <> default/demodeployment-bf5d895b5-6s4xn:80 (ID:108597) Authentication required DROPPED (TCP Flags: SYN)
Jul 31 11:35:19.661: default/client2-d64dd865b-qskqc:50986 (ID:77602) -> default/demodeployment-bf5d895b5-6s4xn:80 (ID:108597) policy-verdict:L3-L4 INGRESS ALLOWED (TCP Flags: SYN; Auth: SPIRE)
Jul 31 11:35:19.661: default/client2-d64dd865b-qskqc:50986 (ID:77602) -> default/demodeployment-bf5d895b5-6s4xn:80 (ID:108597) to-endpoint FORWARDED (TCP Flags: SYN)

到此为止就是所有的内容了。让我们来总结一下。

总结

在本文中,我们更深入地探讨了 Cilium 的功能,特别是它从服务网格获得的相互认证功能。这一功能依赖于实现 SPIFFE 框架的 SPIRE 服务器部署。之后,实际上非常简单。网络策略中的简单规范确保了工作负载间的身份验证。而且在 hubble 上也很容易看到这一点。下一步应该是在 hubble 部分以及 SPIRE 服务器上配置更多的监控。这就是为什么在图表配置中添加了与指标相关的值。目前这对我来说还不起作用,所以我稍后还得回来处理这个问题。还需要对 SPIRE 服务器的可观测性进行一些思考。可能查看 loki 或类似工具的日志会很不错。但那将是下一次的内容。

最后更新于 2024/09/18