Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kubernetes_cluster -pod_cidrs/service_cidrs #16657

Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func TestAccKubernetesCluster_advancedNetworkingKubenet(t *testing.T) {
data.ImportStep(),
})
}

func TestAccKubernetesCluster_advancedNetworkingIPVersionsIPv4(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_kubernetes_cluster", "test")
r := KubernetesClusterResource{}
Expand Down Expand Up @@ -411,6 +412,36 @@ func TestAccKubernetesCluster_privateClusterOff(t *testing.T) {
})
}

func TestAccKubernetesCluster_podCidrs(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_kubernetes_cluster", "test")
r := KubernetesClusterResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.podCidrs(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func TestAccKubernetesCluster_serviceCidrs(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_kubernetes_cluster", "test")
r := KubernetesClusterResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.serviceCidrs(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func TestAccKubernetesCluster_standardLoadBalancer(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_kubernetes_cluster", "test")
r := KubernetesClusterResource{}
Expand Down Expand Up @@ -1800,6 +1831,70 @@ resource "azurerm_kubernetes_cluster" "test" {
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, enablePrivateCluster, data.RandomInteger)
}

func (KubernetesClusterResource) podCidrs(data acceptance.TestData) string {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we also add a test case where we're providing both an IPv4 and IPv6 address?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure

return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-aks-%d"
location = "%s"
}

resource "azurerm_kubernetes_cluster" "test" {
name = "acctestaks%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
dns_prefix = "acctestaks%d"

default_node_pool {
name = "default"
node_count = 1
vm_size = "Standard_DS2_v2"
}

network_profile {
network_plugin = "kubenet"
pod_cidrs = ["10.1.1.0/24"]
}

identity {
type = "SystemAssigned"
}
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger)
}

func (KubernetesClusterResource) serviceCidrs(data acceptance.TestData) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-aks-%d"
location = "%s"
}

resource "azurerm_kubernetes_cluster" "test" {
name = "acctestaks%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
dns_prefix = "acctestaks%d"

default_node_pool {
name = "default"
node_count = 1
vm_size = "Standard_DS2_v2"
}

network_profile {
network_plugin = "kubenet"
dns_service_ip = "10.1.1.10"
docker_bridge_cidr = "172.18.0.1/16"
service_cidrs = ["10.1.1.0/24"]
}

identity {
type = "SystemAssigned"
}
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger)
}

func (KubernetesClusterResource) standardLoadBalancerConfig(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,62 @@ func TestAccKubernetesCluster_oidcIssuer(t *testing.T) {
})
}

func TestAccKubernetesCluster_namespace(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we rename this to

Suggested change
func TestAccKubernetesCluster_namespace(t *testing.T) {
func TestAccKubernetesCluster_namespaceToggle(t *testing.T) {

data := acceptance.BuildTestData(t, "azurerm_kubernetes_cluster", "test")
r := KubernetesClusterResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.namespaceEnabled(data, false),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.namespaceEnabled(data, true),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.namespaceEnabled(data, false),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func (KubernetesClusterResource) namespaceEnabled(data acceptance.TestData, enabled bool) string {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this to

Suggested change
func (KubernetesClusterResource) namespaceEnabled(data acceptance.TestData, enabled bool) string {
func (KubernetesClusterResource) namespace(data acceptance.TestData, enabled bool) string {

return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-aks-%d"
location = "%s"
}

resource "azurerm_kubernetes_cluster" "test" {
name = "acctestaks%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
dns_prefix = "acctestaks%d"
namespace_resources_enabled = "%t"

default_node_pool {
name = "default"
node_count = 1
vm_size = "Standard_DS2_v2"
}

identity {
type = "SystemAssigned"
}
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, enabled)
}

func (KubernetesClusterResource) basicAvailabilitySetConfig(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
Expand Down
79 changes: 62 additions & 17 deletions internal/services/containers/kubernetes_cluster_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,11 @@ func resourceKubernetesCluster() *pluginsdk.Resource {
},
},

"namespace_resources_enabled": {
Type: pluginsdk.TypeBool,
Optional: true,
},

"network_profile": {
Type: pluginsdk.TypeList,
Optional: true,
Expand Down Expand Up @@ -470,6 +475,17 @@ func resourceKubernetesCluster() *pluginsdk.Resource {
ValidateFunc: validate.CIDR,
},

"pod_cidrs": {
Type: pluginsdk.TypeList,
Optional: true,
Computed: true,
ForceNew: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
ValidateFunc: validate.CIDR,
},
},

"service_cidr": {
Type: pluginsdk.TypeString,
Optional: true,
Expand All @@ -478,6 +494,17 @@ func resourceKubernetesCluster() *pluginsdk.Resource {
ValidateFunc: validate.CIDR,
},

"service_cidrs": {
Type: pluginsdk.TypeList,
Optional: true,
Computed: true,
ForceNew: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
ValidateFunc: validate.CIDR,
},
},

"load_balancer_sku": {
Type: pluginsdk.TypeString,
Optional: true,
Expand Down Expand Up @@ -595,6 +622,7 @@ func resourceKubernetesCluster() *pluginsdk.Resource {
},
},
},

"ip_versions": {
Type: pluginsdk.TypeList,
Optional: true,
Expand Down Expand Up @@ -1098,23 +1126,24 @@ func resourceKubernetesClusterCreate(d *pluginsdk.ResourceData, meta interface{}
Tier: containerservice.ManagedClusterSKUTier(d.Get("sku_tier").(string)),
},
ManagedClusterProperties: &containerservice.ManagedClusterProperties{
APIServerAccessProfile: &apiAccessProfile,
AadProfile: azureADProfile,
AddonProfiles: *addonProfiles,
AgentPoolProfiles: agentProfiles,
AutoScalerProfile: autoScalerProfile,
DNSPrefix: utils.String(dnsPrefix),
EnableRBAC: utils.Bool(d.Get("role_based_access_control_enabled").(bool)),
KubernetesVersion: utils.String(kubernetesVersion),
LinuxProfile: linuxProfile,
WindowsProfile: windowsProfile,
NetworkProfile: networkProfile,
NodeResourceGroup: utils.String(nodeResourceGroup),
PublicNetworkAccess: publicNetworkAccess,
DisableLocalAccounts: utils.Bool(d.Get("local_account_disabled").(bool)),
HTTPProxyConfig: httpProxyConfig,
OidcIssuerProfile: oidcIssuerProfile,
SecurityProfile: microsoftDefender,
APIServerAccessProfile: &apiAccessProfile,
AadProfile: azureADProfile,
AddonProfiles: *addonProfiles,
AgentPoolProfiles: agentProfiles,
AutoScalerProfile: autoScalerProfile,
DNSPrefix: utils.String(dnsPrefix),
EnableRBAC: utils.Bool(d.Get("role_based_access_control_enabled").(bool)),
EnableNamespaceResources: utils.Bool(d.Get("namespace_resources_enabled").(bool)),
KubernetesVersion: utils.String(kubernetesVersion),
LinuxProfile: linuxProfile,
WindowsProfile: windowsProfile,
NetworkProfile: networkProfile,
NodeResourceGroup: utils.String(nodeResourceGroup),
PublicNetworkAccess: publicNetworkAccess,
DisableLocalAccounts: utils.Bool(d.Get("local_account_disabled").(bool)),
HTTPProxyConfig: httpProxyConfig,
OidcIssuerProfile: oidcIssuerProfile,
SecurityProfile: microsoftDefender,
},
Tags: tags.Expand(t),
}
Expand Down Expand Up @@ -1374,6 +1403,11 @@ func resourceKubernetesClusterUpdate(d *pluginsdk.ResourceData, meta interface{}
existing.ManagedClusterProperties.DisableLocalAccounts = utils.Bool(d.Get("local_account_disabled").(bool))
}

if d.HasChange("namespace_resources_enabled") {
updateCluster = true
existing.ManagedClusterProperties.EnableNamespaceResources = utils.Bool(d.Get("namespace_resources_enabled").(bool))
}

if d.HasChange("network_profile") {
updateCluster = true

Expand Down Expand Up @@ -1698,6 +1732,7 @@ func resourceKubernetesClusterRead(d *pluginsdk.ResourceData, meta interface{})
d.Set("node_resource_group", props.NodeResourceGroup)
d.Set("enable_pod_security_policy", props.EnablePodSecurityPolicy)
d.Set("local_account_disabled", props.DisableLocalAccounts)
d.Set("namespace_resources_enabled", props.EnableNamespaceResources)
d.Set("public_network_access_enabled", props.PublicNetworkAccess != containerservice.PublicNetworkAccessDisabled)

upgradeChannel := ""
Expand Down Expand Up @@ -2134,6 +2169,10 @@ func expandKubernetesClusterNetworkProfile(input []interface{}) (*containerservi
networkProfile.PodCidr = utils.String(podCidr)
}

if v, ok := config["pod_cidrs"]; ok {
networkProfile.PodCidrs = utils.ExpandStringSlice(v.([]interface{}))
}

if v, ok := config["docker_bridge_cidr"]; ok && v.(string) != "" {
dockerBridgeCidr := v.(string)
networkProfile.DockerBridgeCidr = utils.String(dockerBridgeCidr)
Expand All @@ -2144,6 +2183,10 @@ func expandKubernetesClusterNetworkProfile(input []interface{}) (*containerservi
networkProfile.ServiceCidr = utils.String(serviceCidr)
}

if v, ok := config["service_cidrs"]; ok {
networkProfile.ServiceCidrs = utils.ExpandStringSlice(v.([]interface{}))
}

return &networkProfile, nil
}

Expand Down Expand Up @@ -2364,7 +2407,9 @@ func flattenKubernetesClusterNetworkProfile(profile *containerservice.NetworkPro
"network_mode": string(profile.NetworkMode),
"network_policy": string(profile.NetworkPolicy),
"pod_cidr": podCidr,
"pod_cidrs": utils.FlattenStringSlice(profile.PodCidrs),
"service_cidr": serviceCidr,
"service_cidrs": utils.FlattenStringSlice(profile.ServiceCidrs),
"outbound_type": string(profile.OutboundType),
},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,16 @@ func validateKubernetesCluster(d *pluginsdk.ResourceData, cluster *containerserv
dnsServiceIP := profile["dns_service_ip"].(string)
serviceCidr := profile["service_cidr"].(string)
podCidr := profile["pod_cidr"].(string)
serviceCidrs := profile["service_cidrs"].([]interface{})
isCidrset := serviceCidr != "" || len(serviceCidrs) != 0

// Azure network plugin is not compatible with pod_cidr
if podCidr != "" && networkPlugin == "azure" {
return fmt.Errorf("`pod_cidr` and `azure` cannot be set together")
}

// if not All empty values or All set values.
if !(dockerBridgeCidr == "" && dnsServiceIP == "" && serviceCidr == "") && !(dockerBridgeCidr != "" && dnsServiceIP != "" && serviceCidr != "") {
if !(dockerBridgeCidr == "" && dnsServiceIP == "" && !isCidrset) && !(dockerBridgeCidr != "" && dnsServiceIP != "" && isCidrset) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This validation makes sure that docker_bridge_cidr, dns_service_ip and service_cidr are either all set or empty rather than preventing the user from setting both service_cidr/service_cidrs and pod_cidr/pod_cidrs. In any case after trying this out it is indeed possible to set both _cidr and _cidrs.

However it seems this validation may no longer be relevant or needed since AKS no longer supports docker for the container runtime (see #18119). Could you please update the validation here while you're at it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About depreciating docker_bridge_cidr, I think it's better to make another PR for it.

return fmt.Errorf("`docker_bridge_cidr`, `dns_service_ip` and `service_cidr` should all be empty or all should be set")
}
}
Expand Down
6 changes: 6 additions & 0 deletions website/docs/r/kubernetes_cluster.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ In addition, one of either `identity` or `service_principal` blocks must be spec

-> **Note:** This requires that the Preview Feature `Microsoft.ContainerService/AKS-AzureDefender` is enabled, see [the documentation](https://docs.microsoft.com/azure/defender-for-cloud/defender-for-containers-enable?tabs=aks-deploy-portal%2Ck8s-deploy-asc%2Ck8s-verify-asc%2Ck8s-remove-arc%2Caks-removeprofile-api&pivots=defender-for-container-aks) for more information.

* `namespace_resources_enabled` - (Optional) It can be enabled/disabled on creation and updation of the managed cluster. The default value is false.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* `namespace_resources_enabled` - (Optional) It can be enabled/disabled on creation and updation of the managed cluster. The default value is false.
* `namespace_resources_enabled` - (Optional) Specifies whether Namespace Resources should be enabled. Defaults to `false`.


* `network_profile` - (Optional) A `network_profile` block as defined below.

-> **Note:** If `network_profile` is not defined, `kubenet` profile will be used by default.
Expand Down Expand Up @@ -515,8 +517,12 @@ A `network_profile` block supports the following:

* `pod_cidr` - (Optional) The CIDR to use for pod IP addresses. This field can only be set when `network_plugin` is set to `kubenet`. Changing this forces a new resource to be created.

* `pod_cidrs` - (Optional) One IPv4 CIDR is expected for single-stack networking. Two CIDRs, one for each IP family (IPv4/IPv6), is expected for dual-stack networking. Changing this forces a new resource to be created.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* `pod_cidrs` - (Optional) One IPv4 CIDR is expected for single-stack networking. Two CIDRs, one for each IP family (IPv4/IPv6), is expected for dual-stack networking. Changing this forces a new resource to be created.
* `pod_cidrs` - (Optional) A list of CIDRs to use for pod IP addresses. For single-stack networking a single IPv4 CIDR is expected. For dual-stack networking an IPv4 and IPv6 CIDR are expected. Changing this forces a new resource to be created.


* `service_cidr` - (Optional) The Network Range used by the Kubernetes service. Changing this forces a new resource to be created.

* `service_cidrs` - (Optional) One IPv4 CIDR is expected for single-stack networking. Two CIDRs, one for each IP family (IPv4/IPv6), is expected for dual-stack networking. Changing this forces a new resource to be created.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* `service_cidrs` - (Optional) One IPv4 CIDR is expected for single-stack networking. Two CIDRs, one for each IP family (IPv4/IPv6), is expected for dual-stack networking. Changing this forces a new resource to be created.
* `service_cidrs` - (Optional) A list of CIDRs to use for Kubernetes services. For single-stack networking a single IPv4 CIDR is expected. For dual-stack networking an IPv4 and IPv6 CIDR are expected. Changing this forces a new resource to be created.


~> **Note:** This range should not be used by any network element on or connected to this VNet. Service address CIDR must be smaller than /12. `docker_bridge_cidr`, `dns_service_ip` and `service_cidr` should all be empty or all should be set.

Examples of how to use [AKS with Advanced Networking](https://docs.microsoft.com/en-us/azure/aks/networking-overview#advanced-networking) can be [found in the `./examples/kubernetes/` directory in the Github repository](https://github.com/hashicorp/terraform-provider-azurerm/tree/main/examples/kubernetes).
Expand Down