支持Azure 虚拟专用系统 ,群集自动缩放器和用户分配的身份

作者: Krishnakumar R(KK) (微软), 倪鹏飞 (微软)

介绍

使用Kubernetes v1.12,Azure虚拟机规模集(VMSS)和群集自动缩放器已达到其通用(GA),并且用户分配的身份可用作预览功能。

Azure 虚拟专用系统 允许您创建和管理相同的,负载均衡的VM,这些VM可根据需求或设置的时间表自动增加或减少。这使您能够轻松管理和扩展多个VM,以提供高可用性和应用程序弹性,非常适合诸如容器工作负载之类的大规模应用程序 [1].

群集自动缩放器可让您根据负载条件自动调整Kubernetes群集的大小。

v1.12带来的另一个令人兴奋的功能是能够将用户分配的身份与Kubernetes集群一起使用 [12].

在本文中,我们将简要概述Azure上的VMSS,群集自动缩放器和用户分配的身份功能。

虚拟专用系统

Azure的虚拟机规模集(VMSS)功能使用户能够从单个中央配置自动创建VM,通过L4和L7负载平衡提供负载平衡,提供使用可用性区域实现高可用性的路径,提供大型VM实例等。等

虚拟专用系统 由一组虚拟机组成,它们是相同的,可以在组级别进行管理和配置。可在以下链接中找到Azure本身中此功能的更多详细信息 [1].

使用Kubernetes v1.12,客户可以在VMSS实例之外创建k8s集群并利用VMSS功能。

Azure上的群集组件

通常,Azure中的独立Kubernetes群集由以下部分组成

  • 计算-VM本身及其属性。
  • 网络-包括IP和负载平衡器。
  • 存储-与VM关联的磁盘。

计算

云k8s群集中的计算由VM组成。这些虚拟机是通过诸如acs-engine或AKS(如果是托管服务)之类的置备工具创建的。最终,它们作为进程(在某些版本中)或作为Docker容器运行各种系统守护程序,例如kubelet,kube-api服务器等。

联网

在Azure Kubernetes群集中,各种网络组件组合在一起以提供用户所需的功能。通常,它们由网络接口​​,网络安全组,公共IP资源,VNET(虚拟网络),负载平衡器等组成。

存储

Kubernetes群集建立在Azure中创建的磁盘之上。在典型的配置中,我们有托管磁盘,这些磁盘用于保存常规OS映像,而另一个磁盘用于etcd。

云提供商组件

Kubernetes云提供商接口提供与云的交互,以管理特定于云的资源,例如公共IP和路由。这些组件的详细概述在 [2]。如果是Azure Kubernetes群集,则Kubernetes交互会通过Azure云提供程序层并与云中运行的各种服务联系。

K8的云提供商实现可以大致分为以下我们需要实现的组件接口:

  1. 负载均衡器
  2. 执行个体
  3. 区域
  4. 路线

除上述接口外,云提供商的存储服务还通过卷插件层链接。

Azure云提供商实施和VMSS

在Azure云提供程序中,对于我们实现的每种类型的群集,都有一个我们指定的VMType选项。对于VMSS,VM类型为“ vmss”。供应软件(acs引擎,将来的AKS等)将在/etc/kubernetes/azure.json文件中设置这些值。基于此类型,将实例化各种实现 [3]

负载平衡器界面提供对基础云提供商负载平衡器服务的访问。 Kubernetes需要有关负载均衡器及其控制操作的信息,以处理托管在Kubernetes集群上的服务。对于VMSS支持,请确保所做的更改确保VMSS实例是所需的负载平衡器池的一部分。

实例接口可帮助云控制器从云提供程序层获取有关节点的各种详细信息。例如,控制器通过云提供程序层向其注册的实例接口来获取诸如IP地址,实例ID等之类的节点的详细信息。如果有VMSS支持,我们会与VMSS服务进行对话以收集有关实例的信息。

区域接口可帮助云控制器获取每个节点的区域信息。调度程序可以使用此类信息将吊舱分散到不同的可用区域。还需要支持拓扑感知的动态预配置功能,例如AzureDisk。每个VMSS实例将使用其当前区域和区域进行标记。

路由接口可帮助云控制器为Pod网络设置高级路由。例如,将为每个节点设置带有前缀节点的podCIDR和下一跳节点的内部IP的路由。如果支持VMSS,则下一跳是VMSS虚拟机的内部IP地址。

已对Azure卷插件界面进行了修改,以使VMSS正常工作。例如,已对AzureDisk的附加/分离进行了修改,以在VMSS实例级别执行这些操作。

在Azure上设置VMSS群集

以下链接 [4] 提供了一个使用acs引擎创建Kubernetes集群的示例。

acs-engine deploy --subscription-id <subscription id> \
    --dns-prefix <dns> --location <location> \
    --api-model examples/kubernetes.json

API模型文件提供了acs-engine用于创建集群的各种配置。此处的API模型 [5] 提供了一个很好的入门配置来设置VMSS集群。

创建VMSS群集后,可以执行以下步骤来了解有关群集设置的更多信息。这是使用上述命令创建的集群中的kubectl get节点的输出:

$ kubectl get nodes
NAME                                 STATUS    ROLES     AGE       VERSION
k8s-agentpool1-92998111-vmss000000   Ready     agent     1h        v1.12.0-rc.2
k8s-agentpool1-92998111-vmss000001   Ready     agent     1h        v1.12.0-rc.2
k8s-master-92998111-0                Ready     master    1h        v1.12.0-rc.2

该集群由两个工作节点和一个主节点组成。现在,我们如何检查Azure术语中的哪个节点?在VMSS清单中,我们可以看到一个VMSS:

$ az vmss list -o table -g k8sblogkk1
Name                          ResourceGroup    Location    区域      Capacity  Overprovision    UpgradePolicy
----------------------------  ---------------  ----------  -------  ----------  ---------------  ---------------
k8s-agentpool1-92998111-vmss  k8sblogkk1       westus2                       2  False            Manual

我们视为代理的节点(在kubectl get nodes命令中)是此vmss的一部分。我们可以使用以下命令列出属于虚拟机规模集的实例:

$ az vmss list-instances -g k8sblogkk1 -n k8s-agentpool1-92998111-vmss -o table
  InstanceId  LatestModelApplied    Location    Name                            ProvisioningState    ResourceGroup    VmId
------------  --------------------  ----------  ------------------------------  -------------------  ---------------  ------------------------------------
           0  True                  westus2     k8s-agentpool1-92998111-vmss_0  Succeeded            K8SBLOGKK1       21c57d6c-9c8f-4a62-970f-63ed0fcba53f
           1  True                  westus2     k8s-agentpool1-92998111-vmss_1  Succeeded            K8SBLOGKK1       840743b9-0076-4a2e-920e-5ba9da296665

节点名称与vm scale集中的名称不匹配,但是如果我们运行以下命令来列出providerID,我们可以找到与实例名称相似的匹配节点:

$  kubectl describe nodes k8s-agentpool1-92998111-vmss000000| grep ProviderID
ProviderID:                  azure:///subscriptions/<subscription id>/resourceGroups/k8sblogkk1/providers/Microsoft.Compute/virtualMachineScaleSets/k8s-agentpool1-92998111-vmss/virtualMachines/0

现状与未来

当前支持以下内容:

  1. 虚拟专用系统 主节点和工作节点
  2. 工作节点上的VMSS和主节点上的可用性集组合。
  3. 每个虚拟机磁盘连接
  4. Azure磁盘和Azure文件支持
  5. 可用区(Alpha)

将来将支持以下内容:

  1. 支持VMSS的AKS
  2. 每个VM实例的公用IP

集群自动缩放器

Kubernetes集群由节点组成。这些节点可以是虚拟机,裸机服务器,甚至可以是虚拟节点(虚拟kubelet)。为了避免在Kubernetes生态系统的排列组合中迷失方向,我们考虑一下正在讨论的集群由虚拟机组成,这些虚拟机托管在云中(例如:Azure,Google或AWS)。这实际上意味着您可以访问运行Kubernetes代理的虚拟机以及运行k8s服务(如API服务器)的主节点。可以在此处找到k8s架构的详细版本 [11].

群集上所需的节点数取决于群集上的工作负载。当负载增加时,需要增加节点,而当其减少时,需要减少节点并清理不再使用的资源。解决这一问题的一种方法是手动扩展作为Kubernetes集群一部分的节点,并在需求减少时手动缩减。但是,这不应该自动完成吗?该问题的答案是群集自动缩放器(CA)。

集群自动缩放器本身作为kubernetes集群中的Pod运行。下图说明了有关k8s集群的设置的高级视图:

由于Cluster Autoscaler是k8s集群中的一个Pod,因此它可以使用集群内配置和Kubernetes go客户端 [10] 与API服务器联系。

内部构造

API服务器是中央服务,它使用后备存储(etcd数据库)管理k8s集群的状态,在管理节点上运行或在云中运行(对于托管服务,例如AKS)。对于Kubernetes集群中的任何组件来说,要弄清集群的状态,例如集群中注册的节点,都必须联系API服务器。

为了简化我们的讨论,我们将CA功能分为以下三个部分:

CA的主要部分是一个控制循环,该循环在每个扫描间隔都保持运行。此循环负责更新自动缩放器指标和运行状况探测器。在进入此循环之前,自动缩放器会执行各种操作,例如在执行Kubernetes领导者选举后声明领导者状态。主循环初始化静态自动定标器组件。该组件根据传递到CA的参数初始化基础云提供程序。

由CA执行的用于管理集群状态的各种操作将传递到云提供程序组件上。某些示例(例如-增加目标大小,减小目标大小等)会导致云提供程序组件在内部与云服务进行对话,并执行诸如添加节点或删除节点之类的操作。这些操作在集群中的节点组上执行。静态自动缩放器还可以通过查询API服务器来保持系统状态的标签-诸如列表容器和列表节点之类的操作可用于获取此类信息。

扩大规模的决定是基于未安排时间的广告连播以及各种制衡措施。可以按比例缩小的节点将从群集中删除,并从云本身中删除。集群自动缩放器在按比例放大和按比例缩小之前应用检查和平衡-例如,最近添加的节点受到特殊考虑。在删除期间,将耗尽节点以确保运行的吊舱不会发生中断。

在Azure上设置CA:

集群自动缩放器可作为带有acs-engine的附加组件使用。以下链接 [15] 有一个示例配置文件,用于通过acs-engine部署自动定标器。以下链接 [8] 提供有关逐步操作的详细信息。

在acs-engine的情况下,我们使用常规命令行进行部署:

acs-engine deploy --subscription-id <subscription id> \
    --dns-prefix <dns> --location <location> \
    --api-model examples/kubernetes.json

主要区别在于配置文件中的以下几行 [15] 确保将CA部署为插件:

"addons": [
          {
            "name": "cluster-autoscaler",
            "enabled": true,
            "config": {
              "minNodes": "1",
              "maxNodes": "5"
            }
          }
        ]

上面json中的config部分可用于为集群自动缩放器pod提供配置,例如:如上所述的min和max节点。

设置完成后,我们可以看到在系统名称空间中部署了集群自动缩放器pod:

$kubectl get pods -n kube-system  | grep autoscaler
cluster-autoscaler-7bdc74d54c-qvbjs             1/1       Running             1          6m

这是CA configmap的输出和示例群集的事件:

$kubectl -n kube-system describe configmap cluster-autoscaler-status
Name:         cluster-autoscaler-status
Namespace:    kube-system
Labels:       <none>
Annotations:  cluster-autoscaler.kubernetes.io/last-updated=2018-10-02 01:21:17.850010508 +0000 UTC

Data
====
status:
----
Cluster-autoscaler status at 2018-10-02 01:21:17.850010508 +0000 UTC:
Cluster-wide:
  Health:      Healthy (ready=3 unready=0 notStarted=0 longNotStarted=0 registered=3 longUnregistered=0)
               LastProbeTime:      2018-10-02 01:21:17.772229859 +0000 UTC m=+3161.412682204
               LastTransitionTime: 2018-10-02 00:28:49.944222739 +0000 UTC m=+13.584675084
  ScaleUp:     NoActivity (ready=3 registered=3)
               LastProbeTime:      2018-10-02 01:21:17.772229859 +0000 UTC m=+3161.412682204
               LastTransitionTime: 2018-10-02 00:28:49.944222739 +0000 UTC m=+13.584675084
  ScaleDown:   NoCandidates (candidates=0)
               LastProbeTime:      2018-10-02 01:21:17.772229859 +0000 UTC m=+3161.412682204
               LastTransitionTime: 2018-10-02 00:39:50.493307405 +0000 UTC m=+674.133759650

NodeGroups:
  Name:        k8s-agentpool1-92998111-vmss
  Health:      Healthy (ready=2 unready=0 notStarted=0 longNotStarted=0 registered=2 longUnregistered=0 cloudProviderTarget=2 (minSize=1, maxSize=5))
               LastProbeTime:      2018-10-02 01:21:17.772229859 +0000 UTC m=+3161.412682204
               LastTransitionTime: 2018-10-02 00:28:49.944222739 +0000 UTC m=+13.584675084
  ScaleUp:     NoActivity (ready=2 cloudProviderTarget=2)
               LastProbeTime:      2018-10-02 01:21:17.772229859 +0000 UTC m=+3161.412682204
               LastTransitionTime: 2018-10-02 00:28:49.944222739 +0000 UTC m=+13.584675084
  ScaleDown:   NoCandidates (candidates=0)
               LastProbeTime:      2018-10-02 01:21:17.772229859 +0000 UTC m=+3161.412682204
               LastTransitionTime: 2018-10-02 00:39:50.493307405 +0000 UTC m=+674.133759650


Events:
  Type    Reason          Age   From                Message
  ----    ------          ----  ----                -------
  Normal  ScaleDownEmpty  42m   cluster-autoscaler  Scale-down: removing empty node k8s-agentpool1-92998111-vmss000002

可以看到事件,集群自动缩放器按比例缩小并删除了一个节点,因为该集群上没有负载。在这种情况下,其余的configmap表示此时自动缩放器没有采取其他操作。

现状和未来:

集群自动缩放器当前支持四种VM类型:标准(VMAS),VMSS,ACS和AKS。将来,Cluster Autoscaler将集成到AKS产品中,以便用户可以一键启用它。

用户分配的身份

为了使Kubernetes集群组件能够安全地与云服务对话,它需要与云提供商进行身份验证。在Azure Kubernetes群集中,到目前为止,这是通过两种方式完成的-服务主体或托管身份。在使用服务主体的情况下,凭据存储在群集中,并且存在密码轮换和其他挑战,用户需要适应这些模型。托管服务标识可以减轻用户的负担,并直接管理服务实例 [12].

可能有两种管理身份-一种是系统分配的,另一种是用户分配的。对于系统分配的身份,在创建期间,会为Kubernetes集群中的每个虚拟机分配一个托管身份。需要访问Azure资源的各种Kubernetes组件都使用此身份。这些操作的示例包括获取/更新负载均衡器配置,获取/更新虚拟机信息等。通过为系统分配托管身份,用户无法控制分配给基础虚拟机的身份。系统自动为其分配,这降低了用户的灵活性。

通过v1.12,我们为Kubernetes带来了用户分配的托管身份支持。有了此支持,用户不必管理任何密码,但同时可以灵活地管理集群使用的身份。例如,如果用户需要允许访问特定存储帐户或Azure密钥保管库的群集,则可以提前创建用户分配的身份并提供密钥保管库访问。

内部构造

为了了解内部结构,我们将重点介绍使用acs-engine创建的集群。可以用其他方式进行配置,但是基本交互具有相同的模式。

The acs-engine sets up the cluster with the required configuration. The /etc/kubernetes/azure.json file provides a way for the cluster components (eg: kube-apiserver) to gather configuration on how to access the cloud resources. In a user managed identity cluster there is a value filled with the key as UserAssignedIdentityID. This value is filled with the client id of the user assigned identity created by acs-engine or provided by the user, however the case may be. The code which does the authentication for Kubernetes on azure can be found here [14]。此代码使用Azure adal软件包进行身份验证以访问云中的各种资源。对于用户分配的身份,将进行以下API调用以获取新令牌:

adal.NewServicePrincipalTokenFromMSIWithUserAssignedID(msiEndpoint,
env.ServiceManagementEndpoint,
config.UserAssignedIdentityID)

此调用将命中实例元数据服务或vm扩展 [12] 收集令牌,然后将令牌用于访问各种资源。

使用用户分配的身份设置集群

有了v1.12中对用户分配的身份的上游支持,现在在acs引擎中支持使用用户分配的身份创建集群。此处显示的json配置文件 [13] 可用于创建具有用户分配的身份的集群。用于创建vmss群集的同一步骤可用于创建已分配了用户分配的身份的群集。

acs-engine deploy --subscription-id <subscription id> \
    --dns-prefix <dns> --location <location> \
    --api-model examples/kubernetes-msi-userassigned/kube-vmss.json

这里的主要配置值如下:

"useManagedIdentity": true
"userAssignedID": "acsenginetestid"

The first one useManagedIdentity indicates to acs-engine that we are going to use the managed identity extension. This sets up the necessary packages and extensions required for the managed identities to work. The next one userAssignedID provides the information on the user identity which is to be used with the cluster.

现状与未来

当前,我们支持使用acs-engine的部署在集群中创建用户分配的身份。将来,它将成为AKS的一部分。

参与其中

有关天蓝色的特定讨论-请在以下位置查看Azure SIG页面 [6] 来加入 #sig-azure 闲置频道以获取更多信息。

对于CA,请在此处签出Autoscaler项目 [7] 并加入 #sig-autoscaling 请稍候片刻,以进行更多讨论。

对于Azure文档上的acs引擎(非托管版本),可以在这里找到: [9]。有关Azure Kubernetes服务(AKS)中托管服务的更多详细信息,请单击此处 [5].

参考文献

  1. //docs.microsoft.com/en-us/azure/virtual-machine-scale-sets/overview

  2. / docs / concepts / architecture / cloud-controller /

  3. //github.com/kubernetes/kubernetes/blob/release-1.17/staging/src/k8s.io/legacy-cloud-providers/azure/azure_vmss.go

  4. //github.com/Azure/acs-engine/blob/master/docs/kubernetes/deploy.md

  5. //docs.microsoft.com/en-us/azure/aks/

  6. //github.com/kubernetes/community/tree/master/sig-azure

  7. //github.com/kubernetes/autoscaler

  8. //github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/azure/README.md

  9. //github.com/Azure/acs-engine

  10. //github.com/kubernetes/client-go

  11. / docs / concepts / architecture /

  12. //docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview

  13. //github.com/Azure/acs-engine/tree/master/examples/kubernetes-msi-userassigned

14)//github.com/kubernetes/kubernetes/blob/release-1.17/staging/src/k8s.io/legacy-cloud-providers/azure/auth/azure_auth.go

  1. //github.com/Azure/acs-engine/tree/master/examples/addons/cluster-autoscaler