diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 057b1a7c2..de446207a 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -2,7 +2,8 @@ Release Notes ============= ## 1.9.12 -* VMSS overprovisioning controls +* VM Scale Sets: overprovisioning controls +* AKS Cluster: Added link_to_subnet and link_to_pod_subnet to agent pool config ## 1.9.11 * VM extensions: support for auto-upgrades and initial version diff --git a/docs/content/api-overview/resources/aks-cluster.md b/docs/content/api-overview/resources/aks-cluster.md index 6f6ef4e62..7b5cf5014 100644 --- a/docs/content/api-overview/resources/aks-cluster.md +++ b/docs/content/api-overview/resources/aks-cluster.md @@ -56,6 +56,8 @@ The Agent Pool builder (`agentPool`) constructs agent pools in the AKS cluster. | os_type | Sets the OS type of the VM's in the agent pool. | | pod_subnet | Sets the name of a virtual network subnet where this AKS cluster should be attached. | | subnet | Sets the name of a virtual network subnet where this AKS cluster should be attached. | +| link_to_subnet | Specify an existing subnet this AKS cluster should be attached. | +| link_to_pod_subnet | Specify an existing subnet this AKS cluster should be attached. | | vm_size | Sets the size of the VM's in the agent pool. | | add_availability_zones | Sets the Azure availability zones for the VM's in the agent pool. | | vnet | Sets the name of a virtual network in the same region where this AKS cluster should be attached. | diff --git a/src/Farmer/Arm/ContainerService.fs b/src/Farmer/Arm/ContainerService.fs index 498a1ea4d..e3cb6b66e 100644 --- a/src/Farmer/Arm/ContainerService.fs +++ b/src/Farmer/Arm/ContainerService.fs @@ -186,6 +186,8 @@ type ManagedCluster = { AvailabilityZones: string list VirtualNetworkName: ResourceName option SubnetName: ResourceName option + Subnet: LinkedResource option + PodSubnet: LinkedResource option PodSubnetName: ResourceName option AutoscaleSetting: FeatureFlag option ScaleDownMode: ScaleDownMode option @@ -240,6 +242,16 @@ type ManagedCluster = { let dependencies = [ this.AgentPoolProfiles + |> List.choose (fun pool -> + match pool.PodSubnet with + | Some(Managed podSubnet) -> Some podSubnet + | _ -> None) + this.AgentPoolProfiles + |> List.choose (fun pool -> + match pool.Subnet with + | Some(Managed subnet) -> Some subnet + | _ -> None) + this.AgentPoolProfiles |> List.choose (fun pool -> pool.VirtualNetworkName) |> List.map virtualNetworks.resourceId this.Identity.Dependencies @@ -300,11 +312,17 @@ type ManagedCluster = { vnetSubnetID = match agent.VirtualNetworkName, agent.SubnetName with | Some vnet, Some subnet -> subnets.resourceId(vnet, subnet).Eval() - | _ -> null + | _ -> + match agent.Subnet with + | Some subnet -> subnet.ResourceId.Eval() + | _ -> null podSubnetID = match agent.VirtualNetworkName, agent.PodSubnetName with | Some vnet, Some pod_subnet -> subnets.resourceId(vnet, pod_subnet).Eval() - | _ -> null + | _ -> + match agent.PodSubnet with + | Some podSubnet -> podSubnet.ResourceId.Eval() + | _ -> null enableAutoScaling = agent.AutoscaleSetting |> Option.mapBoxed _.AsBoolean scaleDownMode = match agent.ScaleDownMode with diff --git a/src/Farmer/Builders/Builders.ContainerService.fs b/src/Farmer/Builders/Builders.ContainerService.fs index ed720088a..c0d7bcf0a 100644 --- a/src/Farmer/Builders/Builders.ContainerService.fs +++ b/src/Farmer/Builders/Builders.ContainerService.fs @@ -23,6 +23,8 @@ type AgentPoolConfig = { VirtualNetworkName: ResourceName option SubnetName: ResourceName option PodSubnetName: ResourceName option + Subnet: LinkedResource option + PodSubnet: LinkedResource option AutoscaleSetting: FeatureFlag option ScaleDownMode: ScaleDownMode option MinCount: int option @@ -42,6 +44,8 @@ type AgentPoolConfig = { VirtualNetworkName = None SubnetName = None PodSubnetName = None + PodSubnet = None + Subnet = None VmSize = Standard_DS2_v2 AvailabilityZones = [] AutoscaleSetting = None @@ -186,6 +190,8 @@ type AksConfig = { OsType = agentPool.OsType SubnetName = agentPool.SubnetName PodSubnetName = agentPool.PodSubnetName + Subnet = agentPool.Subnet + PodSubnet = agentPool.PodSubnet VmSize = agentPool.VmSize AvailabilityZones = agentPool.AvailabilityZones VirtualNetworkName = agentPool.VirtualNetworkName @@ -270,6 +276,21 @@ type AgentPoolBuilder() = [] member _.UserMode(state: AgentPoolConfig) = { state with Mode = AgentPoolMode.User } + + /// Sets the name of a virtual network where this agent pool should be attached. + [] + member _.LinkToSubnetId(state: AgentPoolConfig, subnetId: ResourceId) = { + state with + Subnet = Some(Unmanaged subnetId) + } + + /// Sets the name of a virtual network where this agent pool should be attached. + [] + member _.LinkToPodSubnetId(state: AgentPoolConfig, subnetId: ResourceId) = { + state with + PodSubnet = Some(Unmanaged subnetId) + } + /// Sets the disk size for the VM's in the agent pool. [] member _.DiskSizeGB(state: AgentPoolConfig, size) = { state with OsDiskSize = size } diff --git a/src/Tests/ContainerService.fs b/src/Tests/ContainerService.fs index fc2ccf2ce..6fcbf165c 100644 --- a/src/Tests/ContainerService.fs +++ b/src/Tests/ContainerService.fs @@ -232,6 +232,62 @@ let tests = Expect.hasLength aks.AgentPoolProfiles 1 "" Expect.equal aks.AgentPoolProfiles.[0].Name "linuxpool" "" } + test "AKS cluster on linked VNet" { + let myAks = aks { + name "private-k8s-cluster" + dns_prefix "testprivateaks" + + add_agent_pools [ + agentPool { + name "linuxPool" + count 3 + + link_to_subnet ( + Arm.Network.subnets.resourceId (ResourceName "aks-rg", ResourceName "vnet-subnet") + ) + + link_to_pod_subnet ( + Arm.Network.subnets.resourceId (ResourceName "aks-rg", ResourceName "vnet-pod") + ) + } + ] + + network_profile (azureCniNetworkProfile { service_cidr "10.250.0.0/16" }) + linux_profile "aksuser" "public-key-here" + service_principal_client_id "some-spn-client-id" + } + + let template = arm { + location Location.EastUS + add_resource myAks + output "oidcUrl" myAks.OidcIssuerUrl + } + + let json = template.Template |> Writer.toJson + let jobj = JObject.Parse(json) + + let podSubnetId = + jobj.SelectToken( + "resources[?(@.name=='private-k8s-cluster')].properties.agentPoolProfiles[0].podSubnetID" + ) + |> string + + let subnetId = + jobj.SelectToken( + "resources[?(@.name=='private-k8s-cluster')].properties.agentPoolProfiles[0].vnetSubnetID" + ) + |> string + + Expect.equal + podSubnetId + "[resourceId('Microsoft.Network/virtualNetworks/subnets', 'aks-rg', 'vnet-pod')]" + "pod subnet not enabled on agent pool" + + Expect.equal + subnetId + "[resourceId('Microsoft.Network/virtualNetworks/subnets', 'aks-rg', 'vnet-subnet')]" + "subnet not enabled on agent pool" + } test "AKS with private API must use a standard load balancer." { Expect.throws (fun () ->