标准Azure Kubernetes服务集群的API服务器有一个公共IP地址,私有AKS集群的API服务器端点有一个私有IP地址。在标准AKS集群和私有AKS集群中,工作节点都有一个私有IP地址。
对于那些寻找长答案的人来说。
让我们先画出Azure Kubernetes集群的组成部分,这对任何Kubernetes集群都是一样的,无论是Azure、Amazon还是Google。
让我们从一个有三个节点的集群开始。
到目前为止,没有什么特别的吧?
我们有一个调度器,用于调度不同节点上的工作负载。还有API服务器,用于管理Kubernetes,然后我们还有Etcd。
Etcd是一个简单的数据库,用于Kubernetes存储配置,以键值对的形式存储,所有这些都在控制平面内。
然后,我们有工人节点。
Kubernetes集群的工作方式是,每个工作节点都有一个Kubelet。
Kubelet是一个从API服务器接收指令的组件。
它促进了API服务器和工作节点之间的通信。
在Azure中,所有的工作节点都在一个VNET里面。
所以我们来画一下,好吗?
所以现在我们有一个VNET。
让我们为VNET随机选择一个IP地址范围。我将假装我已经将我的VNET配置为10.0.0.0,CIDR为/20。这给了我们大约4000个IP地址。
我现在要给每个节点分配一个IP地址。
现在我们已经分配了三个IP地址。你会注意到,控制平面不在VNET内**。**
这是因为,在Azure中,我们并不管理控制平面。控制平面是由Azure管理的,在它自己的虚拟网络中运行。
问题是,控制平面如何连接到这些节点?
在标准AKS集群中,有一个用于控制平面的公共IP地址。
我也要为公共API端点创建一个随机的公共IP地址作为例子。
所以它是一个公共端点。值得注意的是,这里的这些节点是普通的虚拟机。
但是这些VMS没有一个公共IP地址。它们只有一个在VNET内定义的IP地址。
这意味着我们不能从VNET外部以常规方式访问这些VMS。
因此,AKS控制平面没有办法直接连接到每个工作节点的Kubelet。因为Kubelet是作为pod在工人节点内运行的,而且节点只有一个私有IP地址,所以Kubelet将无法从VNET外部到达。也就是说,如果不求助于负载平衡器或其他一些技巧。这正是我们要谈的。
工作节点是由客户管理的。而控制平面则由Azure管理。
一个标准的AKS集群默认比Google GKE的标准集群更安全。
让我来证明一下我刚才说的话。
以GCP为例,当你创建一个标准Kubernetes集群时,每个工作节点都有一个公共IP地址,此外还有一个私有IP地址。
因此,从安全的角度来看,标准Azure AKS集群默认比GCP GKE集群的默认设置更安全。
再回到我们最初的问题上。
Azure是如何启用控制平面和工作节点之间的连接的?
我们这里有一个由公共端点暴露的控制平面,用于向kubectl发布命令。
我们如何将控制平面连接到工作节点上,以便我们能够控制它们?
在Azure Kubernetes服务中,你可能会看到有三种不同类型的pod在每个Worker节点中运行,用来连接Azure控制平面和Worker节点。
为了连接控制平面和工作节点,我们需要使用隧道,这些隧道需要由工作节点发起。
AKS的变化非常快,所以你会发现这个隧道的不同版本。要想知道你的集群正在运行哪个版本的隧道,你可以运行以下命令。
kubectl get pods -n kube-system
Tunnelfront
如果你看到你的集群中运行的pod的名字以**tunnelfront-**开头,那么你知道你的集群正在运行Tunnelfront。在Tunnelfront中,是由工作节点使用公共端点来启动与控制平面的连接。因此,当节点在运行时,有一个SSH连接打开,从工作节点到控制平面。
控制平面能够以这种方式通过SSH隧道执行命令。
AKS-Link
Tunnelfront已经被淘汰了,在最近的AKS版本中,你可能会看到另一种类型的pod,它被称为AKS Link。
如果你的集群有AKS link,主要的区别是在工作节点和控制平面之间建立一个VPN隧道(使用OpenVPN),而不是使用SSH隧道。
这个概念与Tunnelfront的概念是一样的。VPN隧道打开一个安全连接,由工作节点启动到控制平面。与Tunnelfront相比,OpenVPN的主要优点是可以防止中间人攻击,因为工作节点可以使用SSL证书验证控制机的身份。
尽管工作节点在VNET内部,并且只有私人IP地址,但它们确实可以访问公共互联网。通过这种方式,他们可以通过公共IP地址到达控制平面。
AKS Konnectivity
最近,Azure推出了Konnectivity,以取代AKS-Link。
Azure正在废除tunnel-front和AKS-link,取而代之的是Konnectivity。
Konnectivity的作用与Tunnefront和AKS-Link的作用相同。但Konnectivity使用TCP级别的代理,而不是vpn隧道。
在Konnectivity中,Konnectivity-agent在工作节点中运行,Konnectivity-server在控制平面中运行。
如果你使用的是较新版本的Kubernetes,那么你可能会看到Konnectivity代理运行在worker节点内,在kube-system命名空间下。
这将创建一个TCP级别的代理,类似于一个VPN。
Konnectivity是AKS-link的改进版,是基于开箱即用的kubernetes组件,名为Konnectivity。
但不管是哪种实现方式,想法都是一样的。在由Azure管理的控制平面与运行在私有VNET中的工作节点之间建立连接。
这必须通过控制平面的公共IP地址来完成,而连接是由工人节点发起的。
我们应该担心我们使用的是公共IP地址吗?
这是否意味着控制平面和工人节点之间的通信可以被拦截,通过中间人攻击?
控制平面和工作节点应该在同一个Azure数据中心内(可用区)。控制平面和工作节点之间交换的数据包不应需要穿越公共互联网。此外,为了使中间人攻击发挥作用,攻击者需要以某种方式假装自己是控制平面。这意味着,攻击者需要访问控制平面的私人SSL证书。这不太可能,但有可能。
控制平面的目的是什么,我们可以用公共端点做什么?
公共端点的存在是为了方便通过控制平面使用kubectl对集群进行管理。Kubectl也被用来部署Kubernetes应用程序。
在一个典型的CI/CD工作流程中,kubectl被Gitlab CI、github CI或Jenkins用来部署Kubernetes应用。
因为控制平面是通过公共IP暴露的,所以从互联网上的任何地方将其与云CI/CD工具集成是非常方便的。
AKS默认启用了认证。如果你需要对集群进行认证,你需要有必要的k8s凭证。
一旦你有了你的凭证,你就可以使用kubectl连接到集群。
这不是很安全,因为,如果有人能够窃取k8s凭证,那么他们就能够连接到集群并对其做任何事情。也可能发生的是,Kubernetes集群中存在漏洞,甚至可能不需要认证。
是的,你也可以通过使用IP白名单来控制对API服务器的访问。这在一定程度上有帮助。
这种类型的k8s集群不会适合每一个担心安全的公司。
例如,一家银行不会想在互联网上暴露一个k8s集群,因为这不符合其安全政策。
这就是为什么微软不得不增加一个私有AKS集群,作为需要这种安全水平的客户的一个选项。
在私有AKS集群中,控制平面和工作节点之间的所有通信都发生在一个私有VNET内。
重要的是要认识到,在标准的AKS集群中,控制面和工作节点之间的所有通信都是通过隧道完成的,如果使用tunnelfront,可以是SSH,如果使用AKS-link,可以是VPN隧道。如果集群使用Konnectivity,它也可以是一个TCP级别的代理。
工作节点在VNET内,所以它们从外部世界联系的唯一方式是通过API服务器,当使用kubectl命令或我们创建一个负载平衡器时。
请注意,在AKS中,不可能使用NodePort暴露一个pod,因为所有的Worker Node都只有内部IP地址。
这样做的缺点是,如果有人要窃取你的证书,那么他们就可以控制k8s集群。
什么是私有Azure Kubernetes集群?
标准AKS类和私有AKS集群的主要区别是,在私有AKS集群中,你有一个私有端点,而不是一个公共端点。
私有端点有一个分配在VNET范围内的私有IP地址。
因为你有一个私有端点,而且IP地址本身与工作节点的IP地址在同一个子网中,所以不需要设置隧道。
另一个主要区别是,控制平面和私有端点之间的连接是通过私有链接完成的。
因为我们有一个私有端点,所以不再可能从公共互联网连接到私有k8s API端点。
为了从外部访问控制平面,你需要使用VPN,或者如果不可能的话,你可以通过一个跳线盒访问API服务器,或者最近你可以使用Azure Bastion。
虽然拥有一个私有的AKS集群绝对是最佳做法,但从安全的角度来看,拥有一个私有的AKS集群使得管理集群变得更加复杂。
例如,设置CI/CD变得更加棘手,特别是如果你使用Github或Gitlab这样的云服务。这是因为如果你使用Gitlab/Github的共享运行器,它在私有网络之外,就无法访问AKS集群私有端点所在的VNET。是的,有一些方法可以解决这个问题。但无论如何,你都会削弱安全性。
就这样吧。我希望你觉得这篇文章有用。现在你应该知道标准和私有AKS集群的区别了。现在你应该能够做出正确的决定,选择适合你的企业的那一个