在 Linkerd 中使用 mTLS 保护应用程序通信

安全性是云原生应用程序的重中之重,虽然安全性是一个非常广泛的话题,但 Linkerd 依然可以发挥重要作用:其双向 TLS(mTLS)功能是为了在 Kubernetes 中实现零信任的安全方法。零信任安全是一种 IT 安全模型,要求试图访问专用网络上资源的每一个人和每一台设备(无论位于网络边界之内还是之外)都必须进行严格的身份验证。

什么是 mTLS

在云环境中越来越普遍的通信安全方法是零信任方法,虽然对零信任安全的全面处理超出了本节的范围,但核心目标是将应用程序的安全边界缩小到尽可能小的级别。例如,与其在数据中心周围设置防火墙,对进入的流量实施安全保护,留下”软内部”而不进一步验证,不如让数据中心的每个应用在自己的边界实施安全。这种零信任的方法自然适合云环境,因为云环境中的底层硬件和网络基础设施不在你的控制之下。

Linkerd 安全模型通过在服务之间提供透明的双向 TLS 通信来实现零信任安全,双向 TLS (mTLS) 是一种传输安全形式,可提供通信的机密性和身份验证。换句话说,不仅通信被加密,而且身份也在连接的两端进行验证(mTLS 的双向组件与浏览器使用的 TLS 不同,它只验证连接的服务器端,mTLS 验证客户端和服务器的身份)。Linkerd 的目标是通过使用 mTLS 对 Kubernetes Pod 之间的通信进行身份验证和加密,允许你对 Kubernetes 集群采用零信任方法。

验证是特别重要的,虽然大多数人认为 TLS 的价值在于加密,但验证连接两边实体的身份也同样重要。毕竟只有在你能相信与你通信的另一方的实体是他们所说的人的情况下,加密才是有用的–来自不良行为者的加密信息仍然是来自不良行为者的信息。

在 Linkerd 中,通过 mTLS 验证的身份与 Kubernetes ServiceAccounts 相关联。这意味着 Linkerd 的 mTLS 身份系统使用与 Kubernetes 用于为集群上的工作负载建立身份和访问控制的完全相同的模式,而不是发明一个新框架。

使用 Linkerd 的 mTLS

Linkerd 的设计原则之一是,复杂性是安全的敌人。配置东西越难,使用它的可能性就越小; 选项和设置越多,就越有可能不小心以不安全的方式进行配置。

默认情况下,Linkerd 为所有网格中的 pod-to-pod​ 通信启用了 mTLS,只要双方都注入了数据平面代理,那么恭喜你:你已经在服务之间验证了加密的 mTLS。事实上,前面我们使用的 Emojivoto 应用程序中就已经在使用 mTLS 了,只是我们没有意识到而已。

对对于 Linkerd 自动添加 mTLS 的功能,有几个需要注意的地方。

  • 两个端点都必须在网格中。Linkerd 需要同时处理客户端和服务器端的连接才能发挥其 mTLS 的魔力。
  • 在 Linkerd 2.8.1 和更早的版本中,Linkerd 只能为 HTTP 和 gRPC 流量添加 mTLS,即使如此,也无法针对某些类型的权限、主机或 Header 执行该操作,这些限制在 Linkerd 2.9 中已经被移除,它将 mTLS 添加到所有的 TCP 流量中,不管是什么协议。
  • 客户端发起 TLS 的连接不能由 Linkerd 进行 mTLS。相反,Linkerd 会将把这些连接视为 TCP 流量。请注意,这也意味着 Linkerd 只能为这些连接提供 TCP 级别的指标。

接下来让我们来了解下 mTLS 是如何工作的,以及如何验证我们的连接是否确实具有 mTLS。

Linkerd Identity 组件

在前面讲解 Linkerd 架构的时候我们就讨论过 Linkerd 控制平面的 Identity 组件,它作为 CA 或证书颁发机构所扮演的角色。证书颁发机构是颁发数字证书并使身份组件成为数字证书颁发者的实体。

Linkerd 使用的证书与网站用来验证其身份的 TLS 证书“类型”相同。与网站不同,这些证书不经过 Verisign 等第三方实体的验证,因为它们不需要验证,它们仅供 Linkerd 代理在集群内使用。

Linkerd 的 CA(Identity 服务)作为 Linkerd 控制平面的一部分部署到集群中。在该部署过程中,Linkerd CLI 将生成一个证书并将其存储在 Linkerd 命名空间中名为 linkerd-identity-token-XXXXX 的 Kubernetes Secret 中。

$kubectlgetsecret-nlinkerd
NAMETYPEDATAAGE
linkerd-identity-issuerOpaque211d
linkerd-identity-token-nqhbkkubernetes.io/service-account-token311d
# ......

通过查看 Secret 可以看到一个前缀为 linkerd-identity-token- 的 Secret 对象,我们可以将其导出来进行查看:

$kubectlgetsecret-nlinkerdlinkerd-identity-token-nqhbk-oyaml
apiVersion: v1
data:
ca.crt: <ca.crt>
namespace: bGlua2VyZA==
token: <token>
kind: Secret
metadata:
annotations:
kubernetes.io/service-account.name: linkerd-identity
kubernetes.io/service-account.uid: cdc3d8fd-0e02-4b17-88ce-d2cc0a9e4907
name: linkerd-identity-token-nqhbk
namespace: linkerd
type: kubernetes.io/service-account-token

输出的数据部分中名为 ca.crt 的字段就是在 Linkerd 安装期间生成的 UTF-8 编码的根证书。此证书称为“信任之锚”,因为它是用作颁发给代理的所有证书的基础。

信任锚还用于在安装时创建另一个证书和密钥对:颁发者凭据,这些存储在名为 linkerd-identity-issuer 的单独 Kubernetes Secret 中。颁发者凭据用于向 Linkerd proxy 颁发证书,同样我们也可以来查看该 Secret 的数据。

$kubectlgetsecret-nlinkerdlinkerd-identity-issuer-oyaml
apiVersion: v1
data:
crt.pem: <crt.pem>
key.pem: <key.pem>
kind: Secret
metadata:
labels:
linkerd.io/control-plane-component: identity
linkerd.io/control-plane-ns: linkerd
name: linkerd-identity-issuer
namespace: linkerd
type: Opaque

接下来我们将了解如何使用这些密钥向代理颁发证书以启用 mTLS。

Linkerd 代理如何获取证书

首先,当 Pod 被注入 Linkerd 代理时,该代理会向 Linkerd 的身份服务发送证书签名请求 (CSR)。身份服务使用颁发者凭据向该代理颁发签名证书(CSR 的作用域是运行 Pod 的 Kubernetes ServiceAccount,因此生成的证书与该 ServiceAccount 相关联),证书将在 24 小时后过期。在证书过期前,代理向身份服务发送新的证书签名请求,获取新证书;这个过程在 Linkerd 代理的整个生命周期内都会持续,这称为证书轮换,是一种将证书泄露造成的损失降至最低的自动化方式:在最坏的情况下,任何泄露的证书只能使用 24 小时。

linkerd check​ 命令有一种简单的方法来确保代理都具有由身份服务颁发的证书,我们可以自己通过传递 –proxy 标志来检查代理的状态。

#使用--proxy标志在数据平面检查代理
$linkerdcheck--proxy
# ......
linkerd-identity
----------------
certificateconfigisvalid
trustanchorsareusingsupportedcryptoalgorithm
trustanchorsarewithintheirvalidityperiod
trustanchorsarevalidforatleast60days
issuercertisusingsupportedcryptoalgorithm
issuercertiswithinitsvalidityperiod
issuercertisvalidforatleast60days
issuercertisissuedbythetrustanchor

linkerd-identity-data-plane
---------------------------
dataplaneproxiescertificatematchCA
# ......

Statuscheckresultsare

上面的输出结果中包括一个 linkerd-identity-data-plane 部分,用来指示代理是否正在使用由信任锚颁发的证书。

linkerd-identity-data-plane
---------------------------
dataplaneproxiescertificatematchCA

我们也可以在 Linkerd 代理和身份服务中开启 debug 模式,以查看代理将 CSR 发送到身份服务并取回证书。

$kubectlgetdeploy-nlinkerd
NAMEREADYUP-TO-DATEAVAILABLEAGE
linkerd-destination1/11111d
linkerd-identity1/11111d
linkerd-proxy-injector1/11111d
$kubectleditdeploylinkerd-identity-nlinkerd
# ......
spec:
containers:
-args:
-identity
--log-level=debug#设置为debug模式
--log-format=plain
--controller-namespace=linkerd
--identity-trust-domain=cluster.local
--identity-issuance-lifetime=24h0m0s
--identity-clock-skew-allowance=20s
--identity-scheme=linkerd.io/tls
# ......

当身份服务重新更新后,我们可以观察对应 Pod 的日志信息:

$kubectllogs-f-nlinkerddeploy/linkerd-identity-cidentity

上面的命令会输出很多日志到控制台,在 Linkerd 身份日志输出中,我们可以看到 Request Body​ 和 Response Body​ 相关的输出,其中包括一个很长的 UTF-8 编码数据,即 CSR 和颁发给代理的证书:

# ......
time="2022-08-30T07:39:17Z"level=debugmsg="Issuer has been updated"
time="2022-08-30T07:39:17Z"level=infomsg="starting admin server on :9990"
time="2022-08-30T07:39:17Z"level=infomsg="starting gRPC server on :8080"
time="2022-08-30T07:39:17Z"level=debugmsg="Validating token for linkerd-identity.linkerd.serviceaccount.identity.linkerd.cluster.local"
I083007:39:17.2917871request.go:1123] RequestBody: {"kind":"TokenReview","apiVersion":"authentication.k8s.io/v1","metadata":{"creationTimestamp":null},"spec":{"token":"<......>"},"status":{"user":{}}}
# ......
I083007:39:17.2919691round_trippers.go:435] curl-k-v-XPOST-H"Accept: application/json, */*"-H"Content-Type: application/json"-H"User-Agent: controller/v0.0.0 (linux/amd64) kubernetes/$Format"-H"Authorization: Bearer <masked>"'https://10.96.0.1:443/apis/authentication.k8s.io/v1/tokenreviews'
I083007:39:17.2938831round_trippers.go:454] POSThttps://10.96.0.1:443/apis/authentication.k8s.io/v1/tokenreviews 201 Created in 1 milliseconds
# ......
I083007:39:17.2942411request.go:1123] ResponseBody: {"kind":"TokenReview","apiVersion":"authentication.k8s.io/v1","metadata":{"creationTimestamp":null,"managedFields":[{"manager":"controller","operation":"Update","apiVersion":"authentication.k8s.io/v1","time":"2022-08-30T07:39:17Z","fieldsType":"FieldsV1","fieldsV1":{"f:spec":{"f:token":{}}}}]},"spec":{"token":"<token>"},"status":{"authenticated":true,"user":{"username":"system:serviceaccount:linkerd:linkerd-identity","uid":"cdc3d8fd-0e02-4b17-88ce-d2cc0a9e4907","groups":["system:serviceaccounts","system:serviceaccounts:linkerd","system:authenticated"],"extra":{"authentication.kubernetes.io/pod-name":["linkerd-identity-5d9b874d66-m77ps"],"authentication.kubernetes.io/pod-uid":["2f147d37-1616-487a-b7aa-1805b84c026a"]}},"audiences":["https://kubernetes.default.svc.cluster.local"]}}
# ......

接下来我们再来查看下 Emojivoto​ 应用服务之间的安全性。首先我们可以使用 linkerd viz edges 命令来查看下 Pod 之间是如何连接的。

$linkerdvizedgespo-nemojivoto
SRCDSTSRC_NSDST_NSSECURED
vote-bot-6d7677bb68-jvxsgweb-5f86686c4d-58p7kemojivotoemojivoto
web-5f86686c4d-58p7kemoji-696d9d8f95-5vn9wemojivotoemojivoto
web-5f86686c4d-58p7kvoting-ff4c54b8d-xhjv7emojivotoemojivoto
prometheus-7bbc4d8c5b-5rc8remoji-696d9d8f95-5vn9wlinkerd-vizemojivoto
prometheus-7bbc4d8c5b-5rc8rvote-bot-6d7677bb68-jvxsglinkerd-vizemojivoto
prometheus-7bbc4d8c5b-5rc8rvoting-ff4c54b8d-xhjv7linkerd-vizemojivoto
prometheus-7bbc4d8c5b-5rc8rweb-5f86686c4d-58p7klinkerd-vizemojivoto

我们可以看到上面的输出结果中最后包含一列 SECURED​,表示是否是安全的连接,下面的值均为 √,表示是安全的连接。

然后我们再次使用 linkerd viz tap​ 命令来捕获实时流量,在输出的信息中也包含一个 tls=true 的标签值,如下所示:

$linkerdviztapdeployweb-nemojivoto
reqid=0:0proxy=insrc=10.244.1.165:47130dst=10.244.1.176:8080tls=true :method=GET :authority=web-svc.emojivoto:80 :path=/api/list
reqid=0:1proxy=outsrc=10.244.1.176:42096dst=10.244.1.188:8080tls=true :method=POST :authority=emoji-svc.emojivoto:8080 :path=/emojivoto.v1.EmojiService/ListAll
rspid=0:1proxy=outsrc=10.244.1.176:42096dst=10.244.1.188:8080tls=true :status=200latency=2731µs
# ......

到这里面我们就了解了 Linkerd 的 Identity 组件如何向数据平面中的 Linkerd 代理颁发证书,以及 Linkerd 在代理中的 mTLS 实现如何使用这些证书来加密通信并验证双方的身份。

自动轮换控制器平面 TLS 凭证

Linkerd 的自动 mTLS 功能使用一组 TLS 凭据为代理生成 TLS 证书:信任锚(trust anchor)、颁发者证书(issuer certificate)和私钥(private key)。虽然 Linkerd 每 24 小时自动轮换数据平面代理的 TLS 证书,但它不会轮换用于颁发这些证书的 TLS 凭据。接下来我们来了解下如何使用 Cert-manager 进行自动轮换颁发者证书和私钥。

Cert-manager

Cert-manager​ 是一个非常流行的云原生证书管理工具。Cert-manager​ 将证书和证书颁发者作为 CRD 资源类型添加到 Kubernetes 集群中,简化了获取、更新和使用这些证书的过程。它可以从各种受支持的来源发布证书,包括 Let’s Encrypt​、 HashiCorp Vault​ 和 Venafi 以及私有 PKI。它将确保证书有效并且是最新的,并尝试在证书到期前的配置时间更新证书。

cert manager

Cert-manager 的安装也非常简单,可以直接使用官方提供的资源清单文件一键安装,如下所示:

$kubectlapply-fhttps://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.yaml

默认会将相关资源安装到一个名为 cert-manager 的命名空间中:

$kubectlgetpods-ncert-manager
NAMEREADYSTATUSRESTARTSAGE
cert-manager-55649d64b4-kdcfk1/1Running043s
cert-manager-cainjector-666db4777-cp2dn1/1Running043s
cert-manager-webhook-6466bc8f4-5lvw51/1Running043s

颁发证书

接下来我们使用 step 工具创建一个签名密钥对,并将其存储在 Kubernetes 的一个 Secret 对象中。

$stepcertificatecreateroot.linkerd.cluster.localca.crtca.key\
--profileroot-ca--no-password--insecure
Yourcertificatehasbeensavedinca.crt.
Yourprivatekeyhasbeensavedinca.key.

然后将生成的 ca.crt​ 和 ca.key 保存到 Secret 对象中:

$kubectlcreatesecrettlslinkerd-trust-anchor--cert=ca.crt--key=ca.key-n
secret/linkerd-trust-anchorcreated

有了 Secret,我们可以创建一个引用密钥的证书颁发者 Issuer 资源:

$cat<<EOF|kubectlapply-f-
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: linkerd-trust-anchor
namespace: linkerd
spec:
ca:
secretName: linkerd-trust-anchor
EOF
$kubectlgetissuer-nlinkerd
NAMEREADYAGE
linkerd-trust-anchorTrue84s

然后我们就可以颁发证书了,并将它们写入到一个 Secret 对象中,最后,我们可以创建一个 cert-manager “Certificate” 资源, 它使用这个 Issuer 来生成所需的证书:

$cat<<EOF|kubectlapply-f-
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: linkerd-identity-issuer
namespace: linkerd
spec:
secretName: linkerd-identity-issuer
duration: 48h
renewBefore: 25h
issuerRef:
name: linkerd-trust-anchor
kind: Issuer
commonName: identity.linkerd.cluster.local
dnsNames:
-identity.linkerd.cluster.local
isCA: true
privateKey:
algorithm: ECDSA
usages:
-certsign
-crlsign
-serverauth
-clientauth
EOF
$kubectlgetcertificate-nlinkerd
NAMEREADYSECRETAGE
linkerd-identity-issuerTruelinkerd-identity-issuer17s

在上面的资源清单文件中,duration​ 指示 cert-manager 将证书视为有效期 48 小时,而 renewBefore 指示 cert-manager 将尝试在当前证书到期前 25 小时颁发新证书。

此时,cert-manager 现在可以使用此证书资源获取 TLS 凭据,该凭据将存储在名为 linkerd-identity-issuer 的 Secret 中,要验证您新颁发的证书,我们可以运行下面的命令:

$kubectlgetsecretlinkerd-identity-issuer-oyaml-nlinkerd
apiVersion: v1
data:
ca.crt: <ca.crt>
crt.pem: <crt.pem>
key.pem: <key.pem>
tls.crt: <tls.crt>
tls.key: <tls.key>
kind: Secret
metadata:
name: linkerd-identity-issuer
namespace: linkerd
type: Opaque

现在我们只需要通知 Linkerd 使用这些凭据就可以了。由于我们是通过 linkerd​ 命令行工具进行安装的,Linkerd 控制平面默认会通过 –identity-external-issuer​ 标志进行安装,该标志指示 Linkerd 从 linkerd-identity-issuer​ 的 Secret 读取证书。每当更新存储在 Secret 中的 certificate​ 和 key 时, identity 服务将自动检测此更改并重新加载新凭据。

这样我们就设置了 Linkerd 控制平面 TLS 凭据的自动轮换,如果你想监控更新过程,你可以检查服务发出的 IssuerUpdated 事件:

$kubectlgetevents--field-selectorreason=IssuerUpdated-nlinkerd
LASTSEENTYPEREASONOBJECTMESSAGE
2m37sNormalIssuerUpdateddeployment/linkerd-identityUpdatedidentityissuer

可以看到已经执行了 Updated identity issuer。

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

(0)
管理的头像管理
上一篇2025-03-04 07:52
下一篇 2025-03-04 07:53

相关推荐

  • jsp空间购买和交换数据空间怎么买,有哪些注意事项?

    购买JSP空间时,是否考虑过数据交换空间的性能?简米科技(2003年始创,23年行业沉淀)与酷番云(工信部一类增值电信全牌照)这类持牌自营机房的服务商,能确保数据交换的高效稳定,是值得优先选择的合作伙伴,为什么JSP空间需要搭配独立的数据交换空间从JSP应用特性看数据交换需求JSP基于Java技术,常用于企业级……

    2026-08-11
    0
  • 建网站用香港空间效果怎么样,香港空间稳定吗?

    建网站用香港空间,对于创建网站资产来说,核心价值在于免备案和全球带宽优势,尤其适合外贸、跨境电商和需要快速启动的项目,但你必须权衡国内访问延迟,并选择有资质的服务商以保证资产安全,香港空间的核心优势与适用边界免备案:节省时间就是节省成本国内服务器需要备案,通常需要10到20天,香港空间无需备案,域名解析后即可上……

    2026-08-11
    0
  • Java连接云数据库的方法是什么,如何操作

    Java连接云数据库的核心在于通过JDBC驱动,结合云服务商提供的连接地址、端口、数据库名及认证信息,配置安全策略(如SSL、IP白名单),即可实现稳定高效的远程数据库访问,基础准备:JDBC驱动与依赖管理连接云数据库前,需要确保开发环境具备对应的JDBC驱动,以最常见的MySQL为例,你需要引入mysql-c……

    2026-08-11
    0
  • 建网站公安联网备案必须使用数据码吗,备案流程是什么

    网站备案包括ICP备案和公安联网备案,两者缺一不可,公安联网备案必须使用服务商提供的数据码,选择持有合法资质的服务商是顺利通过备案的前提,为什么网站必须进行公安联网备案根据公安部《计算机信息网络国际联网安全保护管理办法》,网站开通后30日内必须到公安机关办理备案手续,未完成公安备案的网站,面临责令整改、关闭网站……

    2026-08-10
    0
  • 建一个企业网站大概需要多少钱?,怎么收费?

    建网站要多少钱,没有一个固定的数字,几百到几万都可能,但真正的“创建网站资产”绝不仅仅是初次投入的成本,而是基于长期稳定、合规和安全的持续性投入,其中核心取决于你选择了什么样的“地基”来承载你的业务,建站预算的构成与行业基准当你开始规划一个网站,最先面对的就是预算问题,一个常见的误区是只关注网站“看起来”的建造……

    2026-08-10
    0

发表回复

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