Linkerd 与 Ingress-Nginx 结合使用以及对服务的访问限制

Linkerd 与 Ingress-Nginx 结合使用以及对服务的访问限制

作者:阳明 2022-09-09 20:55:38

云计算

云原生 对 Ingress 控制器进行网格化将允许 Linkerd 在流量进入集群时提供 L7 指标和 mTLS 等功能,Linkerd 支持与大部分 Ingress 控制器进行集成。

出于简单,Linkerd 本身并没有提供内置的 Ingress 控制器,Linkerd 旨在与现有的 Kubernetes Ingress 解决方案一起使用。

要结合 Linkerd 和你的 Ingress 解决方案需要两件事:

  • 配置你的 Ingress 以支持 Linkerd。
  • 网格化你的 Ingress 控制器,以便它们安装 Linkerd 代理。

对 Ingress 控制器进行网格化将允许 Linkerd 在流量进入集群时提供 L7 指标和 mTLS 等功能,Linkerd 支持与大部分 Ingress 控制器进行集成,包括:

  • Ambassador
  • Nginx
  • Traefik
  • Traefik 1.x
  • Traefik 2.x
  • GCE
  • Gloo
  • Contour
  • Kong
  • Haproxy

ingress-nginx

我们这里以集群中使用的 ingress-nginx 为例来说明如何将其与 Linkerd 进行集成使用。

$kubectlgetdeploy-ningress-nginx
NAMEREADYUP-TO-DATEAVAILABLEAGE
ingress-nginx-controller1/11157d
ingress-nginx-defaultbackend1/11157d
$kubectlgetpods-ningress-nginx
NAMEREADYSTATUSRESTARTSAGE
ingress-nginx-controller-7647c44fb9-sss9m1/1Running26 (59mago) 57d
ingress-nginx-defaultbackend-84854cd6cb-rvgd21/1Running27 (59mago) 57d

首先我们需要更新 ingress-nginx-controller 控制器,为 Pod 添加一个 linkerd.io/inject: enabled 注解,可以直接 kubectl edit 这个 Deployment,由于我们集群中的 ingress-nginx 使用的 Helm Chart 安装的,所以可以在 values 中添加如下所示的配置:

controller:
podAnnotations:
linkerd.io/inject: enabled
# ......

然后使用该 values 重新更新即可:

#Updateyourhelmreposwiththeingress-nginxrepo
$helmrepoaddingress-nginxhttps://kubernetes.github.io/ingress-nginx
$helmrepoupdate
#Installtheingress-nginxchart
$helmupgrade--installingress-nginxingress-nginx/ingress-nginx--namespace=ingress-nginx--values=values.yaml

更新后 ingress-nginx 的控制器 Pod 就会被自动注入一个 linkerd proxy 的 sidecar 容器:

$kubectlgetpods-ningress-nginx
NAMEREADYSTATUSRESTARTSAGE
ingress-nginx-controller-f56c7f6fd-rxhrs2/2Running04m21s
ingress-nginx-defaultbackend-84854cd6cb-rvgd21/1Running27 (62mago) 57d

这样 ingress 控制器也被加入到网格中去了,所以也具有了 Linkerd 网格的相关功能:

  • 为 Ingress 控制器提供黄金指标(每秒请求数等)。
  • Ingress 控制器 Pod 和网格应用 Pod 之间的流量是加密的(并相互验证)。
  • 可以看到 HTTP 流量
  • 当应用程序返回错误(如 5xx HTTP 状态代码)时,这将在 Linkerd UI 中看到,不仅是应用程序,还有 nginx ingress 控制器,因为它向客户端返回错误代码。

在 Linkerd Dashboard 中也可以看到对应的指标数据了。

ingress-nginx metrics

对应在 Grafana 中也可以看到对应的图表信息。

ingress-nginx grafana

接下来我们为 Emojivoto 应用添加一个对应的 Ingress 资源对象来对外暴露服务。

#emojivoto-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: emojivoto-ingress
labels:
name: emojivoto-ingress
namespace: emojivoto
annotations:
#addbelowlineofnginxismeshed
nginx.ingress.kubernetes.io/service-upstream: "true"
#nginx.ingress.kubernetes.io/affinity: "cookie"
#nginx.ingress.kubernetes.io/affinity-mode: "persistent"
spec:
ingressClassName: nginx
rules:
#updateIPwithyourownIPusedbyIngressController
-host: emoji.192.168.0.52.nip.io
http:
paths:
-pathType: Prefix
path: /
backend:
service:
name: web-svc-2
port:
number: 80

直接应用上面的资源对象即可:

$kubectlapply-femojivoto-ingress.yaml
$kubectlgetingress-nemojivoto
NAMECLASSHOSTSADDRESSPORTSAGE
emojivoto-ingressnginxemoji.192.168.0.52.nip.io192.168.0.528061s

其中 nip.io 是任何 IP 地址的简单通配符 DNS,这样我们就不用使用自定义主机名和 IP 地址映射来编辑你的 etc/hosts 文件了,nip.io 允许你通过使用以下格式将任何 IP 地址映射到一个主机名。

不带名称:

  • 10.0.0.1.nip.io 映射到 10.0.0.1
  • 192-168-1-250.nip.io 映射到 192.168.1.250
  • 0a000803.nip.io 映射到 10.0.8.3

带名称:

  • app.10.8.0.1.nip.io 映射到 10.8.0.1
  • app-116-203-255-68.nip.io 映射到 116.203.255.68
  • app-c0a801fc.nip.io 映射到 192.168.1.252
  • customer1.app.10.0.0.1.nip.io 映射到 10.0.0.1
  • customer2-app-127-0-0-1.nip.io 映射到 127.0.0.1
  • customer3-app-7f000101.nip.io 映射到 127.0.1.1

nip.io 将 <anything>[.-]<IP Address>.nip.io 以”点”、”破折号”或”十六进制”符号映射到相应的 <IP Address>。

我们这里使用一个自定义的域名 emoji.192.168.0.52.nip.io 相当于直接映射到 192.168.0.52 这个 IP 地址上,该地址是我们 ingress-nginx 的入口地址,这样我们不需要做任何映射即可访问服务了。

emojivoto

另外需要注意在上面的 Ingress 中我们添加了一个 nginx.ingress.kubernetes.io/service-upstream: true 的注解,这是用来告诉 Nginx Ingress Controller 将流量路由到网格应用的服务,而不是直接路由到 Pod。默认情况下,Ingress 控制器只是查询其目标服务的端点,以检索该服务背后的 Pod 的 IP 地址。而通过向网格服务发送流量,Linkerd 的相关功能如负载均衡和流量拆分则会被启用。

ingress-nginx meshed

限制对服务的访问

Linkerd policy 资源可用于限制哪些客户端可以访问服务。同样我们还是使用 Emojivoto 应用来展示如何限制对 Voting 微服务的访问,使其只能从 Web 服务中调用。

我们首先为 Voting 服务创建一个 Server 资源,Server 是 Linkerd 的另外一个 CRD 自定义资源,它用于描述工作负载的特定端口。一旦 Server 资源被创建,只有被授权的客户端才能访问它。

创建一个如下所示的资源对象:

#voting-server.yaml
apiVersion: policy.linkerd.io/v1beta1
kind: Server
metadata:
name: voting-grpc
namespace: emojivoto
labels:
app: voting-svc
spec:
podSelector:
matchLabels:
app: voting-svc
port: grpc
proxyProtocol: gRPC

直接应用上面的资源对象即可:

$kubectlapply-fvoting-server.yaml
server.policy.linkerd.io/voting-grpccreated
$kubectlgetserver-nemojivoto
NAMEPORTPROTOCOL
voting-grpcgrpcgRPC

我们可以看到该 Server 使用了一个 podSelector 属性来选择它所描述的 Voting 服务的 Pod,它还指定了它适用的命名端口 (grpc),最后指定在此端口上提供服务的协议为 gRPC, 这可确保代理正确处理流量并允许它跳过协议检测。

现在没有客户端被授权访问此服务,正常会看到成功率有所下降, 因为从 Web 服务到 Voting 的请求开始被拒绝,也可以直接查看 Web 服务的 Pod 日志来验证:

$kubectllogs-fweb-svc-2-f9d77474f-vxlrh-nemojivoto-cweb-svc-2
2022/09/0609:31:27Errorservingrequest [&{GET/api/vote?choice=:trophy: HTTP/1.111map[Accept-Encoding:[gzip] L5d-Client-Id:[default.emojivoto.serviceaccount.identity.linkerd.cluster.local] L5d-Dst-Canonical:[web-apex.emojivoto.svc.cluster.local:80] User-Agent:[Go-http-client/1.1] X-B3-Sampled:[1] X-B3-Spanid:[f9e1dc6e24803ea8] X-B3-Traceid:[5ae662deee8fdbf2f3b9eaa40eb673d5]] {} <nil>0 [] falseweb-apex.emojivoto:80map[choice:[:trophy:]] map[] <nil>map[] 10.244.1.87:51244/api/vote?choice=:trophy: <nil><nil><nil>0xc00045e4b0}]: rpcerror: code=PermissionDenieddesc=unauthorizedconnectiononservervoting-grpc
# ......

我们可以使用 linkerd viz authz 命令查看进入 Voting 服务的请求的授权状态:

$linkerdvizauthz-nemojivotodeploy/voting
SERVERAUTHZSUCCESSRPSLATENCY_P50LATENCY_P95LATENCY_P99
voting-grpc [UNAUTHORIZED] -0.9rps

可以看到所有传入的请求当前都处于未经授权状态。

接下来我们需要为客户端来授予访问该 Server 的权限,这里需要使用到另外一个 CRD 对象 ServerAuthorization,创建该对象来授予 Web 服务访问我们上面创建的 Voting Server 的权限,对应的资源清单文件如下所示:

#voting-server-auth.yaml
apiVersion: policy.linkerd.io/v1beta1
kind: ServerAuthorization
metadata:
name: voting-grpc
namespace: emojivoto
spec:
server:
name: voting-grpc#关联Server对象
#Thevotingserviceonlyallowsrequestsfromthewebservice.
client:
meshTLS:
serviceAccounts:
-name: web
-name: web-2

上面对象中通过 spec.server.name 来关联上面的 Server 对象,由于 meshTLS 使用 ServiceAccounts 作为身份基础,因此我们的授权也将基于 ServiceAccounts,所以通过 spec.client.meshTLS.serviceAccounts 来指定允许从哪些服务来访问 Voting 服务。

同样直接应用该资源清单即可:

$kubectlapply-fvoting-server-auth.yaml
serverauthorization.policy.linkerd.io/voting-grpccreated
$kubectlgetserverauthorization-nemojivoto
NAMESERVER
voting-grpcvoting-grpc

有了这个对象后,我们现在可以看到所有对 Voting 服务的请求都是由 voting-grpc 这个 ServerAuthorization 授权的。请注意,由于 linkerd viz auth 命令在一个时间窗口内查询,所以可能会看到一些未授权(UNAUTHORIZED)的请求在短时间内显示。

$linkerdvizauthz-nemojivotodeploy/voting
SERVERAUTHZSUCCESSRPSLATENCY_P50LATENCY_P95LATENCY_P99
voting-grpcvoting-grpc84.48%1.0rps1ms1ms1ms

我们还可以通过创建一个 gRPC 客户端 Pod 来尝试从中访问 Voting 服务测试来自其他 Pod 的请求是否会被拒绝:

$kubectlrungrpcurl--rm-it--image=networld/grpcurl--restart=Never--command-- ./grpcurl-plaintextvoting-svc.emojivoto:8080emojivoto.v1.VotingService/VoteDog
Ifyoudon't see a command prompt, try pressing enter.
Errorattaching, fallingbacktologs: unabletoupgradeconnection: containergrpcurlnotfoundinpodgrpcurl_default
Errorinvokingmethod"emojivoto.v1.VotingService/VoteDog": failedtoqueryforservicedescriptor"emojivoto.v1.VotingService": rpcerror: code=PermissionDenieddesc=
pod"grpcurl"deleted
poddefault/grpcurlterminated (Error)

由于该 client 未经授权,所以该请求将被拒绝并显示 PermissionDenied 错误。

我们可以根据需要创建任意数量的 ServerAuthorization 资源来授权许多不同的客户端,还可以指定是授权未经身份验证(即 unmeshed)的客户端、任何经过身份验证的客户端,还是仅授权具有特定身份的经过身份验证的客户端。

此外我们还可以为整个集群设置一个默认策略,该策略将应用于所有未定义 Server 资源的。Linkerd 在决定是否允许请求时会使用以下逻辑:

  • 如果有一个 Server 资源并且客户端为其匹配一个ServerAuthorization​ 资源,则为ALLOW。
  • 如果有一个 Server 资源,但客户端不匹配它的任何ServerAuthorizations​,则为DENY。
  • 如果端口没有 Server 资源,则使用默认策略。

比如我们可以使用 linkerd upgrade 命令将默认策略设置为 deny:

$linkerdupgrade--setpolicyController.defaultAllowPolicy=deny|kubectlapply-f-

另外我们也可以通过设置 config.linkerd.io/default-inbound-policy 注解,可以在单个工作负载或命名空间上设置默认策略。

意思就是除非通过创建 Server 和 ServerAuthorization 对象明确授权,否则所有请求都将被拒绝,这样的话对于 liveness 和 readiness 探针需要明确授权,否则 Kubernetes 将无法将 Pod 识别为 live 或 ready 状态,并将重新启动它们。我们可以创建如下所示的策略对象,来允许所有客户端访问 Linkerd admin 端口,以便 Kubernetes 可以执行 liveness 和 readiness 检查:

$cat<<EOF|kubectlapply-f-
---
#Server"admin": matchestheadminportforeverypodinthisnamespace
apiVersion: policy.linkerd.io/v1beta1
kind: Server
metadata:
namespace: emojivoto
name: admin
spec:
port: linkerd-admin
podSelector:
matchLabels: {} #everypod
proxyProtocol: HTTP/1
---
#ServerAuthorization"admin-everyone": allowsunauthenticatedaccesstothe
#"admin"Server, sothatKuberneteshealthcheckscangetthrough.
apiVersion: policy.linkerd.io/v1beta1
kind: ServerAuthorization
metadata:
namespace: emojivoto
name: admin-everyone
spec:
server:
name: admin
client:
unauthenticated: true

如果你知道 Kubelet(执行健康检查)的 IP 地址或范围, 也可以进一步将 ServerAuthorization 限制为这些 IP 地址或范围,比如如果你知道 Kubelet 在 10.244.0.1 上运行,那么你的 ServerAuthorization 可以改为:

#ServerAuthorization"admin-kublet": allowsunauthenticatedaccesstothe
#"admin"Serverfromthekubelet, sothatKuberneteshealthcheckscangetthrough.
apiVersion: policy.linkerd.io/v1beta1
kind: ServerAuthorization
metadata:
namespace: emojivoto
name: admin-kubelet
spec:
server:
name: admin
client:
networks:
-cidr: 10.244.0.1/32
unauthenticated: true

另外有一个值得注意的是在我们创建 Server 资源之后,但在创建 ServerAuthorization 之前有一段时间,所有请求都被拒绝。为了避免在实时系统中出现这种情况,我们建议你在部署服务之前创建 policy 资源,或者在创建 Server 之前创建 ServiceAuthorizations,以便立即授权客户端。

关于授权策略的更多使用可以查看官方文档 https://linkerd.io/2.11/reference/authorization-policy/ 以了解更多相关信息。

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/255040.html<

(0)
运维的头像运维
上一篇2025-04-30 15:56
下一篇 2025-04-30 15:58

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注