istio-双向tls
- stio 跟踪迁移到 sidecar 的服务端工作负载,并将客户端 sidecar 配置为自动向这些工作负载发送双向 TLS 流量, 同时将明文流量发送到没有 sidecar 的工作负载。这使您可以通过最少的配置,逐步在网格中使用双向 TLS。
- 安装 Istio 时,配置 global.mtls.enabled 选项为 false,global.mtls.auto 选项为 true。 以安装 demo 配置文件为例
[root@master bin]# istioctl manifest apply --set profile=demo \
> --set values.global.mtls.auto=true \
> --set values.global.mtls.enabled=false
Detected that your cluster does not support third party JWT authentication. Falling back to less secure first party JWT. See https://istio.io/docs/ops/best-practices/security/#configure-third-party-service-account-tokens for details.
! global.mtls.enabled is deprecated; use the PeerAuthentication resource instead
! global.mtls.auto is deprecated; use meshConfig.enableAutoMtls instead
✔ Istio core installed
✔ Istiod installed
✔ Egress gateways installed
✔ Ingress gateways installed
✔ Addons installed
✔ Installation complete [root@master bin]#
- 安装
本例中,我们部署 httpbin 服务到 full、partial 和 legacy 三个命名空间中,分别 代表 Istio 迁移的不同阶段。命名空间 full 包含已完成 Istio 迁移的所有服务器工作负载。 每一个部署都有 Sidecar 注入
[root@master ~]# kubectl create ns full
namespace/full created
[root@master ~]# kubectl apply -f <(istioctl kube-inject -f samples/httpbin/httpbin.yaml) -n full
Error: open samples/httpbin/httpbin.yaml: no such file or directory
error: no objects passed to apply
[root@master ~]# cd istio-1.6.3/
[root@master istio-1.6.3]# kubectl apply -f <(istioctl kube-inject -f samples/httpbin/httpbin.yaml) -n full
serviceaccount/httpbin created
service/httpbin created
deployment.apps/httpbin created
[root@master istio-1.6.3]# kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml) -n full
serviceaccount/sleep created
service/sleep created
deployment.apps/sleep created
[root@master istio-1.6.3]#
命名空间 partial 包含部分迁移到 Istio 的服务器工作负载。 只有完成迁移的服务器工作负载(由于已注入 Sidecar)能够使用双向 TLS 流量
$ kubectl create ns partial $ kubectl apply -f <(istioctl kube-inject -f [samples/httpbin/httpbin.yaml](https://raw.githubusercontent.com/istio/istio/release-1.6/samples/httpbin/httpbin.yaml)) -n partial $ cat <<EOF | kubectl apply -n partial -f - apiVersion: apps/v1 kind: Deployment metadata: name: httpbin-nosidecar spec: replicas: 1 selector: matchLabels: app: httpbin template: metadata: labels: app: httpbin version: nosidecar spec: containers: - image: docker.io/kennethreitz/httpbin imagePullPolicy: IfNotPresent name: httpbin ports: - containerPort: 80 EOF
命名空间 legacy 中的工作负载,都没有注入 Sidecar。
[root@master istio-1.6.3]# kubectl create ns legacy
namespace/legacy created
[root@master istio-1.6.3]# kubectl apply -f samples/httpbin/httpbin.yaml -n legacy
serviceaccount/httpbin created
service/httpbin created
deployment.apps/httpbin created
[root@master istio-1.6.3]# kubectl apply -f samples/sleep/sleep.yaml -n legacy
serviceaccount/sleep created
service/sleep created
deployment.apps/sleep created
[root@master istio-1.6.3]#
您可以确认在所有命名空间部署完成。
[root@master istio-1.6.3]# kubectl get pods -n legacy
NAME READY STATUS RESTARTS AGE
httpbin-779c54bf49-9t8wr 1/1 Running 0 5m29s
sleep-f8cbf5b76-2xfsd 1/1 Running 0 5m22s
[root@master istio-1.6.3]# kubectl get pods -n full
NAME READY STATUS RESTARTS AGE
httpbin-56f87c9c66-9rv66 2/2 Running 0 10m
sleep-7486b7547d-nmknf 2/2 Running 0 9m49s
[root@master istio-1.6.3]# kubectl get pods -n partial
NAME READY STATUS RESTARTS AGE
httpbin-56f87c9c66-5v8ls 0/2 Init:0/1 0 88s
httpbin-nosidecar-cc684fdb4-nqp8d 1/1 Running 0 7m45s
[root@master istio-1.6.3]#
您还需验证系统中是否存在默认的网格验证策略,可以参考下面操作:
[root@master istio-1.6.3]# kubectl get policies.authentication.istio.io --all-namespaces
error: the server doesn't have a resource type "policies"
[root@master istio-1.6.3]# kubectl get meshpolicies -o yaml | grep ' mode'
error: the server doesn't have a resource type "meshpolicies"
[root@master istio-1.6.3]#
最后但并非最不重要的一点是,确认没有应用于示例服务的目标规则。 您可以通过检查已有目标规则的 host: 字段,并确保它们没有匹配我们的示例服务。例如:
[root@master istio-1.6.3]# kubectl get destinationrules.networking.istio.io --all-namespaces -o yaml | grep "host:"
[root@master istio-1.6.3]#
您可通过使用 curl 从命名空间 full、partial 或 legacy 中的任一 sleep Pod 发送 HTTP 请求到 httpbin.full、httpbin.partial 或 httpbin.legacy 以验证安装。 所有的请求都应成功返回 HTTP 200 状态码。
例如,这是一个检查 sleep.full 到 httpbin.full 可达性的命令
[root@master istio-1.6.3]# kubectl exec $(kubectl get pod -l app=sleep -n full -o jsonpath={.items..metadata.name}) -c sleep -n full -- curl http://httpbin.full:8000/headers -s -w "response %{http_code}\n" | egrep -o 'URI\=spiffe.*sa/[a-z]*|response.*$'
URI=spiffe://cluster.local/ns/full/sa/sleep
response 200
[root@master istio-1.6.3]#
SPIFFE URI 显示来自 X509 证书的客户端标识,它表明流量是在双向 TLS 中发送的。 如果流量为明文,将不会显示客户端证书。
[root@master istio-1.6.3]# kubectl get namespaces
NAME STATUS AGE
default Active 5d22h
full Active 17m
heptio-contour Active 5d17h
istio-system Active 5d17h
kube-node-lease Active 5d22h
kube-public Active 5d22h
kube-system Active 5d22h
legacy Active 12m
partial Active 14m
[root@master istio-1.6.3]# kubectl get pods -n full
NAME READY STATUS RESTARTS AGE
httpbin-56f87c9c66-9rv66 2/2 Running 0 16m
sleep-7486b7547d-nmknf 2/2 Running 0 16m
[root@master istio-1.6.3]# kubectl exec -it sleep-7486b7547d-nmknf -c sleep -- curl http://httpbin.full:8000/headers
Error from server (NotFound): pods "sleep-7486b7547d-nmknf" not found
[root@master istio-1.6.3]# kubectl exec -it sleep-7486b7547d-nmknf -n full -c sleep -- curl http://httpbin.full:8000/headers
{
"headers": {
"Accept": "*/*",
"Content-Length": "0",
"Host": "httpbin.full:8000",
"User-Agent": "curl/7.69.1",
"X-B3-Parentspanid": "971df015905548b4",
"X-B3-Sampled": "1",
"X-B3-Spanid": "df4cc5e1187fb09f",
"X-B3-Traceid": "42951d2c32eb240e971df015905548b4",
"X-Envoy-Attempt-Count": "1",
"X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/full/sa/httpbin;Hash=9302b39c8b2077e5933cfed8f17d8e86b2a503880a04068126517f4edfe01aaf;Subject=\"\";URI=spiffe://cluster.local/ns/full/sa/sleep"
}
}
[root@master istio-1.6.3]# kubectl exec -it sleep-7486b7547d-nmknf -n full -c sleep -- curl http://httpbin.legacy:8000/headers
{
"headers": {
"Accept": "*/*",
"Content-Length": "0",
"Host": "httpbin.legacy:8000",
"User-Agent": "curl/7.69.1",
"X-B3-Sampled": "1",
"X-B3-Spanid": "f78d3c023364cb2c",
"X-B3-Traceid": "3ea979fb1c0a73faf78d3c023364cb2c",
"X-Envoy-Attempt-Count": "1",
"X-Envoy-Decorator-Operation": "httpbin.legacy.svc.cluster.local:8000/*",
"X-Envoy-Peer-Metadata": "ChoKCkNMVVNURVJfSUQSDBoKS3ViZXJuZXRlcwoeCgxJTlNUQU5DRV9JUFMSDhoMMTAwLjEyMi4yNS45CnkKBkxBQkVMUxJvKm0KDgoDYXBwEgcaBXNsZWVwChIKDGlzdGlvLmlvL3JldhICGgAKIQoRcG9kLXRlbXBsYXRlLWhhc2gSDBoKNzQ4NmI3NTQ3ZAokChlzZWN1cml0eS5pc3Rpby5pby90bHNNb2RlEgcaBWlzdGlvChoKB01FU0hfSUQSDxoNY2x1c3Rlci5sb2NhbAogCgROQU1FEhgaFnNsZWVwLTc0ODZiNzU0N2Qtbm1rbmYKEwoJTkFNRVNQQUNFEgYaBGZ1bGwKSQoFT1dORVISQBo+a3ViZXJuZXRlczovL2FwaXMvYXBwcy92MS9uYW1lc3BhY2VzL2RlZmF1bHQvZGVwbG95bWVudHMvc2xlZXAKGgoPU0VSVklDRV9BQ0NPVU5UEgcaBXNsZWVwChgKDVdPUktMT0FEX05BTUUSBxoFc2xlZXA=",
"X-Envoy-Peer-Metadata-Id": "sidecar~100.122.25.9~sleep-7486b7547d-nmknf.full~full.svc.cluster.local"
}
}
[root@master istio-1.6.3]#
SPIFFE URI 显示来自 X509 证书的客户端标识,它表明流量是在双向 TLS 中发送的。 如果流量为明文,将不会显示客户端证书
PERMISSIVE 模式
这里,我们从开启网格服务双向 TLS 的 PERMISSIVE 模式开始
- 所有的 httpbin.full 工作负载以及在 httpbin.partial 中使用了 Sidecar 的工作负载都能够使用双向 TLS 和明文流量。
- 命名空间 httpbin.partial 中没有 Sidecar 的服务和 httpbin.legacy 中的服务都只能使用明文流量。
自动双向 TLS 将客户端和 sleep.full 配置为可将双向 TLS 流量发送到具有 Sidecar 的工作负载,明文流量发送到没有 Sidecar 的工作负载。
[root@master istio-1.6.3]# for from in "full" "legacy"; do for to in "full" "partial" "legacy"; do echo "sleep.${from} to httpbin.${to}";kubectl exec $(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name}) -c sleep -n ${from} -- curl http://httpbin.${to}:8000/headers -s -w "response code: %{http_code}\n" | egrep -o 'URI\=spiffe.*sa/[a-z]*|response.*$'; echo -n "\n"; done; done
sleep.full to httpbin.full
URI=spiffe://cluster.local/ns/full/sa/sleep
response code: 200
\nsleep.full to httpbin.partial
URI=spiffe://cluster.local/ns/full/sa/sleep
response code: 200
\nsleep.full to httpbin.legacy
response code: 200
\nsleep.legacy to httpbin.full
response code: 200
\nsleep.legacy to httpbin.partial
response code: 200
\nsleep.legacy to httpbin.legacy
response code: 200
\n[root@master istio-1.6.3]#
使用 Sidecar 迁移:
无论工作负载是否带有 Sidecar,对 httpbin.partial 的请求都可以到达。 Istio 自动将 sleep.full 客户端配置为使用双向 TLS 连接带有 Sidecar 的工作负载。
[root@master istio-1.6.3]# for i in `seq 1 10`; do kubectl exec $(kubectl get pod -l app=sleep -n full -o jsonpath={.items..metadata.name}) -c sleep -nfull -- curl http://httpbin.partial:8000/headers -s -w "response code: %{http_code}\n" | egrep -o 'URI\=spiffe.*sa/[a-z]*|response.*$'; echo -n "\n"; done
URI=spiffe://cluster.local/ns/full/sa/sleep
response code: 200
\nresponse code: 200
\nURI=spiffe://cluster.local/ns/full/sa/sleep
response code: 200
\nresponse code: 200
\nresponse code: 200
\nURI=spiffe://cluster.local/ns/full/sa/sleep
response code: 200
\nresponse code: 200
\nURI=spiffe://cluster.local/ns/full/sa/sleep
response code: 200
\nresponse code: 200
\nURI=spiffe://cluster.local/ns/full/sa/sleep
response code: 200
\n[root@master istio-1.6.3]#
如果不使用自动双向 TLS,您必须跟踪 Sidecar 迁移完成情况,然后显式的配置目标规则,使客户端发送双向 TLS 流量到 httpbin.full。
锁定双向 TLS 为 STRICT 模式
您可配置认证策略为 STRICT,以锁定 httpbin.full 服务仅接收双向 TLS 流量
[root@master istio-1.6.3]# kubectl apply -n full -f - <<EOF
> apiVersion: "security.istio.io/v1beta1"
> kind: "PeerAuthentication"
> metadata:
> name: "default"
> spec:
> mtls:
> mode: STRICT
> EOF
peerauthentication.security.istio.io/default created
[root@master istio-1.6.3]#
测试:
[root@master istio-1.6.3]# kubectl exec -it sleep-f8cbf5b76-2xfsd -n legacy -- curl http://httpbin.full:8000
curl: (56) Recv failure: Connection reset by peer
command terminated with exit code 56
[root@master istio-1.6.3]#
现在来自 sleep.legacy 的请求将开始失败,因为其不支持发送双向 TLS 流量。 但是客户端 sleep.full 的请求将仍可成功返回 200 状态码,因为它已配置为自动双向 TLS,并且发送双向 TLS 请求。
整个服务网格全部限定为双向tls 流量:
kubectl apply -n istio-system -f - <<EOF
apiVersion: "security.istio.io/v1beta1"
kind: "PeerAuthentication"
metadata:
name: "default"
spec:
mtls:
mode: STRICT
EOF
清理:
[root@master istio-1.6.3]# kubectl delete ns full partial legacy
namespace "full" deleted
namespace "partial" deleted
namespace "legacy" deleted