为什么需要服务网络
服务网,在这种情况下,Istio是管理和配置服务间交互所需的一切的绑定:路由,身份验证,授权,跟踪,访问控制等等。而且,尽管有许多开放库可以直接在服务代码中直接实现这些功能,但使用Istio,您可以得到相同的结果,而无需在服务本身中添加任何内容。
组件
为istio 1.6撰写的文章
关于变更
Istio在逻辑上分为数据平面和控制平面。
数据平面是代理服务器(Envoy)的集合,这些代理服务器以边车的形式添加到了Pod中。这些代理提供并控制微服务之间的所有网络通信,并从控制平面进行配置。
管理平面(阶段)提供证书的服务发现,配置和管理。它将Istio对象转换为Envoy友好的配置,并将其分布在数据平面中。
Istio服务网格组件
您可以手动添加使节到应用程序窗格,也可以使用Istio在安装过程中添加的Mutating Admission webhook设置自动添加来将其添加到应用程序窗格。为此,请将istio-injection = enabled标签放置在所需的名称空间上。
除了带有特使的代理小车外,Istio还将在吊舱中添加一个特殊的初始化容器,该容器会将战斗流量重定向到带有特使的容器。但是,如何实现呢?在这种情况下,没有魔术,这是通过在Pod的网络名称空间中设置其他iptables规则来实现的。
关于资源消耗
, 100 Istio ~2-3 , envoy 40 , CPU 5%-7% pod.
让我们实际研究一下Sidecar如何捕获来自容器的入站和出站流量。为此,请看一下添加了Istio sidecar的Pod的网络空间。
演示台
Kubernetes Istio.
Kubernetes minikube:
Istio demo :
: productpage details. Istio .
Kubernetes minikube:
Linux:
curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && chmod +x minikube
sudo mkdir -p /usr/local/bin/
sudo install minikube /usr/local/bin/
minikube start --driver=<driver_name> // --driver=none .
MacOS:
brew install minikube
minikube start --driver=<driver_name>
Istio demo :
curl -L https://istio.io/downloadIstio | sh -
cd istio-1.6.3
export PATH=$PWD/bin:$PATH
istioctl install --set profile=demo
: productpage details. Istio .
kubectl label namespace default istio-injection=enabled
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
让我们看看productpage应用程序容器的列表:
kubectl -n default get pods productpage-v1-7df7cb7f86-ntwzz -o jsonpath="{.spec['containers','initContainers'][*].name}"
productpage
istio-proxy
istio-init
除了productpage本身之外,sidecar istio-proxy(同一个使节)和init容器istio-init在pod中工作。
您可以使用nsenter实用程序查看在pod空间中配置的iptables规则。为此,我们需要找出容器过程的pid:
docker inspect k8s_productpage --format '{{ .State.Pid }}'
16286
现在,我们可以看到此容器中安装了iptables规则。
您可以看到几乎所有传入和传出的流量现在都被拦截并重定向到已经在其上等待特使的端口。
打开双向流量加密
策略和MeshPolicy对象已从istio 1.6中删除。相反,他们建议使用PeerAuthentication对象。
Istio允许您加密容器之间的所有流量,应用程序本身甚至都不知道它们通过tls进行通信。这是由Istio自己直接使用一个清单来完成的,因为客户端证书已经安装在代理端设备中。
算法如下:
- 客户端和服务器端的Envoy代理在发送请求之前先进行身份验证。
- 如果检查成功,则客户端代理将对流量进行加密并将其发送到服务器代理;
- 代理服务器端解密流量并将其本地重定向到实际的目标服务。
您可以在不同级别启用mTLS:
- 在整个网络层面;
- 在名称空间级别;
- 在特定广告连播级别。
操作模式:
- 允许:允许加密和纯文本流量;
- 严格:仅允许使用TLS;
- 禁用:仅允许使用纯文本。
让我们在没有启用TLS的情况下使用curl在productpage窗格中查看详细信息服务,并使用tcpdump
查看详细信息:请求:
转储流量:
所有正文和标头均以纯文本格式清晰可读。
让我们打开tls。为此,请使用我们的Pod在名称空间中创建PeerAuthentication类型的对象。
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: default
spec:
mtls:
mode: STRICT
重新运行产品页面上的请求以再次查看详细信息,然后看看我们能得到什么:
流量已加密
授权书
ClusterRbacConfig,ServiceRole和ServiceRoleBinding对象已随新授权策略的实现一起删除。相反,建议使用AuthorizationPolicy对象。
Istio使用授权策略来配置从一个应用程序到另一个应用程序的访问。而且,与纯粹的Kubernetes网络策略不同,它可以在L7级别工作。例如,对于http流量,您可以精确控制请求的方法和路径。
正如我们在前面的示例中看到的那样,默认情况下,对整个集群的所有Pod都开放访问。
现在,我们将使用以下yaml文件禁用默认名称空间中的所有活动:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: deny-all
namespace: default
spec:
{}
并尝试获得详细信息服务:
curl details:9080
RBAC: access denied
太好了,现在我们的请求失败了。
现在让我们配置访问权限,以便仅GET请求通过且仅沿着路径/详细信息通过,而所有其他请求都将被拒绝。有几种选择:
- 您可以配置通过特定标头的请求。
- 通过应用程序的服务帐户;
- 通过传出的ip地址;
- 通过传出名称空间;
- 通过JWT令牌中的声明。
维护最简单的方法是建立对应用程序服务帐户的访问权限,因为对此不需要任何初步配置,因为bookinfo演示应用程序已经带有一个已创建并受监视的服务帐户。
要使用基于服务帐户的授权策略,必须启用TLS相互认证。
设置新的访问策略:
apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
name: "details-viewer"
namespace: default
spec:
selector:
matchLabels:
app: details
rules:
- from:
- source:
principals: ["cluster.local/ns/default/sa/bookinfo-productpage"]
to:
- operation:
methods: ["GET"]
paths: ["/details/*"]
并尝试再次联系:
root@productpage-v1-6b64c44d7c-2fpkc:/# curl details:9080/details/0
{"id":0,"author":"William Shakespeare","year":1595,"type":"paperback","pages":200,"publisher":"PublisherA","language":"English","ISBN-10":"1234567890","ISBN-13":"123-1234567890"}
一切正常。让我们尝试其他方法和方式:
root@productpage-v1-6b64c44d7c-2fpkc:/# curl -XPOST details:9080/details/0
RBAC: access denied
root@productpage-v1-6b64c44d7c-2fpkc:/#
root@productpage-v1-6b64c44d7c-2fpkc:/# curl -XGET details:9080/ping
RBAC: access denied
结论
总之,我注意到所考虑的功能只是Istio可以做的一小部分。开箱即用,我们接收并配置了服务间流量加密和授权,尽管以增加其他组件为代价,因此增加了资源消耗。
谢谢大家!