Skip to content
This repository has been archived by the owner on Oct 24, 2023. It is now read-only.

Commit

Permalink
add support for single stack IPv6
Browse files Browse the repository at this point in the history
  • Loading branch information
aramase committed Feb 25, 2020
1 parent 85f5bd2 commit 48d7c66
Show file tree
Hide file tree
Showing 20 changed files with 129 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ data:
kubeconfig: /var/lib/kubelet/kubeconfig
clusterCIDR: "{{ContainerConfig "cluster-cidr"}}"
mode: "{{ContainerConfig "proxy-mode"}}"
{{- if ContainerConfig "bind-address"}}
bindAddress: "{{ContainerConfig "bind-address"}}"
{{end -}}
{{- if ContainerConfig "healthz-bind-address"}}
healthzBindAddress: "{{ContainerConfig "healthz-bind-address"}}"
{{end -}}
{{- if ContainerConfig "metrics-bind-address"}}
metricsBindAddress: "{{ContainerConfig "metrics-bind-address"}}"
{{end -}}
featureGates:
{{ContainerConfig "featureGates"}}
metadata:
Expand Down
3 changes: 3 additions & 0 deletions parts/k8s/addons/coredns.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,9 @@ spec:
- all
readOnlyRootFilesystem: true
dnsPolicy: Default
{{- if ContainerConfig "use-host-network"}}
hostNetwork: {{ContainerConfig "use-host-network"}}
{{end -}}
volumes:
- name: config-volume
configMap:
Expand Down
2 changes: 1 addition & 1 deletion parts/k8s/cloud-init/artifacts/cse_config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ ensureKMS() {
}
{{end}}

{{if IsIPv6DualStackFeatureEnabled}}
{{if IsIPv6Enabled}}
ensureDHCPv6() {
wait_for_file 3600 1 {{GetDHCPv6ServiceCSEScriptFilepath}} || exit $ERR_FILE_WATCH_TIMEOUT
wait_for_file 3600 1 {{GetDHCPv6ConfigCSEScriptFilepath}} || exit $ERR_FILE_WATCH_TIMEOUT
Expand Down
4 changes: 2 additions & 2 deletions parts/k8s/cloud-init/artifacts/cse_main.sh
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,8 @@ if [[ -n "${MASTER_NODE}" && "${KMS_PROVIDER_VAULT_NAME}" != "" ]]; then
fi
{{end}}

{{/* configure and enable dhcpv6 for dual stack feature */}}
{{- if IsIPv6DualStackFeatureEnabled}}
{{/* configure and enable dhcpv6 for ipv6 features */}}
{{- if IsIPv6Enabled}}
time_metric "EnsureDHCPv6" ensureDHCPv6
{{end}}

Expand Down
2 changes: 1 addition & 1 deletion parts/k8s/cloud-init/masternodecustomdata.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ write_files:
{{CloudInitData "aptPreferences"}}
{{end}}

{{if IsIPv6DualStackFeatureEnabled}}
{{if IsIPv6Enabled}}
- path: {{GetDHCPv6ServiceCSEScriptFilepath}}
permissions: "0644"
encoding: gzip
Expand Down
2 changes: 1 addition & 1 deletion parts/k8s/cloud-init/nodecustomdata.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ write_files:
{{CloudInitData "aptPreferences"}}
{{end}}

{{if IsIPv6DualStackFeatureEnabled}}
{{if IsIPv6Enabled}}
- path: {{GetDHCPv6ServiceCSEScriptFilepath}}
permissions: "0644"
encoding: gzip
Expand Down
15 changes: 15 additions & 0 deletions pkg/api/addons.go
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,13 @@ func (cs *ContainerService) setAddonsConfig(isUpgrade bool) {
},
}

// set host network to true for single stack IPv6 as the the nameserver is currently
// IPv4 only. By setting it to host network, we can leverage the host routes to successfully
// resolve dns.
if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6Only") {
defaultCorednsAddonsConfig.Config["use-host-network"] = "true"
}

// If we have any explicit coredns or kube-dns configuration in the addons array
if getAddonsIndexByName(o.KubernetesConfig.Addons, common.KubeDNSAddonName) != -1 || getAddonsIndexByName(o.KubernetesConfig.Addons, common.CoreDNSAddonName) != -1 {
// Ensure we don't we don't prepare an addons spec w/ both kube-dns and coredns enabled
Expand All @@ -701,6 +708,14 @@ func (cs *ContainerService) setAddonsConfig(isUpgrade bool) {
},
}

// set bind address, healthz and metric bind address to :: explicitly for
// single stack IPv6 cluster as it is single stack IPv6 on dual stack host
if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6Only") {
defaultKubeProxyAddonsConfig.Config["bind-address"] = "::"
defaultKubeProxyAddonsConfig.Config["healthz-bind-address"] = "::"
defaultKubeProxyAddonsConfig.Config["metrics-bind-address"] = "::1"
}

defaultPodSecurityPolicyAddonsConfig := KubernetesAddon{
Name: common.PodSecurityPolicyAddonName,
Enabled: to.BoolPtr(common.IsKubernetesVersionGe(o.OrchestratorVersion, "1.15.0") || to.Bool(o.KubernetesConfig.EnablePodSecurityPolicy)),
Expand Down
6 changes: 5 additions & 1 deletion pkg/api/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -438,11 +438,15 @@ const (
// DefaultKubernetesClusterSubnet specifies the default subnet for pods.
DefaultKubernetesClusterSubnet = "10.244.0.0/16"
// DefaultKubernetesClusterSubnetIPv6 specifies the IPv6 default subnet for pods.
DefaultKubernetesClusterSubnetIPv6 = "fc00::/8"
DefaultKubernetesClusterSubnetIPv6 = "fc00::/48"
// DefaultKubernetesServiceCIDR specifies the IP subnet that kubernetes will create Service IPs within.
DefaultKubernetesServiceCIDR = "10.0.0.0/16"
// DefaultKubernetesDNSServiceIP specifies the IP address that kube-dns listens on by default. must by in the default Service CIDR range.
DefaultKubernetesDNSServiceIP = "10.0.0.10"
// DefaultKubernetesServiceCIDRIPv6 specifies the IPv6 subnet that kubernetes will create Service IPs within.
DefaultKubernetesServiceCIDRIPv6 = "fd00::/108"
// DefaultKubernetesDNSServiceIPv6 specifies the IPv6 address that kube-dns listens on by default. must by in the default Service CIDR range.
DefaultKubernetesDNSServiceIPv6 = "fd00::10"
// DefaultMobyVersion specifies the default Azure build version of Moby to install.
DefaultMobyVersion = "3.0.10"
// DefaultContainerdVersion specifies the default containerd version to install.
Expand Down
1 change: 1 addition & 0 deletions pkg/api/converterfromapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,7 @@ func convertFeatureFlagsToVLabs(api *FeatureFlags, vlabs *vlabs.FeatureFlags) {
vlabs.BlockOutboundInternet = api.BlockOutboundInternet
vlabs.EnableIPv6DualStack = api.EnableIPv6DualStack
vlabs.EnableTelemetry = api.EnableTelemetry
vlabs.EnableIPv6Only = api.EnableIPv6Only
}

func convertCloudProfileToVLabs(api *CustomCloudProfile, vlabsccp *vlabs.CustomCloudProfile) {
Expand Down
1 change: 1 addition & 0 deletions pkg/api/convertertoapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ func convertVLabsFeatureFlags(vlabs *vlabs.FeatureFlags, api *FeatureFlags) {
api.BlockOutboundInternet = vlabs.BlockOutboundInternet
api.EnableIPv6DualStack = vlabs.EnableIPv6DualStack
api.EnableTelemetry = vlabs.EnableTelemetry
api.EnableIPv6Only = vlabs.EnableIPv6Only
}

func convertVLabsExtensionProfile(vlabs *vlabs.ExtensionProfile, api *ExtensionProfile) {
Expand Down
8 changes: 8 additions & 0 deletions pkg/api/defaults-apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,14 @@ func (cs *ContainerService) setAPIServerConfig() {
delete(o.KubernetesConfig.APIServerConfig, key)
}
}
// Set bind address to prefer IPv6 address for single stack IPv6 cluster
// Remove --advertise-address so that --bind-address will be used
if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6Only") {
o.KubernetesConfig.APIServerConfig["--bind-address"] = "::"
for _, key := range []string{"--advertise-address"} {
delete(o.KubernetesConfig.APIServerConfig, key)
}
}
}

func getDefaultAdmissionControls(cs *ContainerService) (string, string) {
Expand Down
10 changes: 10 additions & 0 deletions pkg/api/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ func (cs *ContainerService) setOrchestratorDefaults(isUpgrade, isScale bool) {
o.KubernetesConfig.ClusterSubnet = DefaultKubernetesSubnet
} else {
o.KubernetesConfig.ClusterSubnet = DefaultKubernetesClusterSubnet
// ipv6 only cluster
if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6Only") {
o.KubernetesConfig.ClusterSubnet = DefaultKubernetesClusterSubnetIPv6
}
// ipv4 and ipv6 subnet for dual stack
if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6DualStack") {
o.KubernetesConfig.ClusterSubnet = strings.Join([]string{DefaultKubernetesClusterSubnet, DefaultKubernetesClusterSubnetIPv6}, ",")
Expand Down Expand Up @@ -233,12 +237,18 @@ func (cs *ContainerService) setOrchestratorDefaults(isUpgrade, isScale bool) {
}
if o.KubernetesConfig.DNSServiceIP == "" {
o.KubernetesConfig.DNSServiceIP = DefaultKubernetesDNSServiceIP
if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6Only") {
o.KubernetesConfig.DNSServiceIP = DefaultKubernetesDNSServiceIPv6
}
}
if o.KubernetesConfig.DockerBridgeSubnet == "" {
o.KubernetesConfig.DockerBridgeSubnet = DefaultDockerBridgeSubnet
}
if o.KubernetesConfig.ServiceCIDR == "" {
o.KubernetesConfig.ServiceCIDR = DefaultKubernetesServiceCIDR
if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6Only") {
o.KubernetesConfig.ServiceCIDR = DefaultKubernetesServiceCIDRIPv6
}
}

if common.IsKubernetesVersionGe(o.OrchestratorVersion, "1.14.0") {
Expand Down
4 changes: 4 additions & 0 deletions pkg/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ type FeatureFlags struct {
BlockOutboundInternet bool `json:"blockOutboundInternet,omitempty"`
EnableIPv6DualStack bool `json:"enableIPv6DualStack,omitempty"`
EnableTelemetry bool `json:"enableTelemetry,omitempty"`
EnableIPv6Only bool `json:"enableIPv6Only,omitempty"`
}

// ServicePrincipalProfile contains the client and secret used by the cluster for Azure Resource CRUD
Expand Down Expand Up @@ -2203,6 +2204,8 @@ func (f *FeatureFlags) IsFeatureEnabled(feature string) bool {
return f.EnableIPv6DualStack
case "EnableTelemetry":
return f.EnableTelemetry
case "EnableIPv6Only":
return f.EnableIPv6Only
default:
return false
}
Expand Down Expand Up @@ -2298,6 +2301,7 @@ func (cs *ContainerService) GetProvisionScriptParametersCommon(input ProvisionSc
"KMS_PROVIDER_VAULT_NAME": input.ClusterKeyVaultName,
"IS_HOSTED_MASTER": strconv.FormatBool(cs.Properties.IsHostedMasterProfile()),
"IS_IPV6_DUALSTACK_FEATURE_ENABLED": strconv.FormatBool(cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6DualStack")),
"IS_IPV6_ENABLED": strconv.FormatBool(cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6Only")),
"AUTHENTICATION_METHOD": cs.Properties.GetCustomCloudAuthenticationMethod(),
"IDENTITY_SYSTEM": cs.Properties.GetCustomCloudIdentitySystem(),
"NETWORK_API_VERSION": APIVersionNetwork,
Expand Down
6 changes: 6 additions & 0 deletions pkg/api/vlabs/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type FeatureFlags struct {
BlockOutboundInternet bool `json:"blockOutboundInternet,omitempty"`
EnableIPv6DualStack bool `json:"enableIPv6DualStack,omitempty"`
EnableTelemetry bool `json:"enableTelemetry,omitempty"`
EnableIPv6Only bool `json:"enableIPv6Only,omitempty"`
}

// ServicePrincipalProfile contains the client and secret used by the cluster for Azure Resource CRUD
Expand Down Expand Up @@ -926,3 +927,8 @@ func (k *KubernetesConfig) IsAddonEnabled(addonName string) bool {
func (f *FeatureFlags) IsIPv6DualStackEnabled() bool {
return f != nil && f.EnableIPv6DualStack
}

// IsIPv6OnlyEnabled checks if IPv6Only feature is enabled
func (f *FeatureFlags) IsIPv6OnlyEnabled() bool {
return f != nil && f.EnableIPv6Only
}
34 changes: 26 additions & 8 deletions pkg/api/vlabs/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ func (a *Properties) ValidateOrchestratorProfile(isUpdate bool) error {
}

if o.KubernetesConfig != nil {
err := o.KubernetesConfig.Validate(version, a.HasWindows(), a.FeatureFlags.IsIPv6DualStackEnabled())
err := o.KubernetesConfig.Validate(version, a.HasWindows(), a.FeatureFlags.IsIPv6DualStackEnabled(), a.FeatureFlags.IsIPv6OnlyEnabled())
if err != nil {
return err
}
Expand Down Expand Up @@ -386,10 +386,10 @@ func (a *Properties) validateMasterProfile(isUpdate bool) error {
if m.IsVirtualMachineScaleSets() && m.VnetSubnetID != "" && m.FirstConsecutiveStaticIP != "" {
return errors.New("when masterProfile's availabilityProfile is VirtualMachineScaleSets and a vnetSubnetID is specified, the firstConsecutiveStaticIP should be empty and will be determined by an offset from the first IP in the vnetCidr")
}
// validate os type is linux if dual stack feature is enabled
if a.FeatureFlags.IsIPv6DualStackEnabled() {
// validate distro is ubuntu if dual stack or ipv6 only feature is enabled
if a.FeatureFlags.IsIPv6DualStackEnabled() || a.FeatureFlags.IsIPv6OnlyEnabled() {
if m.Distro == CoreOS {
return errors.Errorf("Dual stack feature is currently supported only with Ubuntu, but master is of distro type %s", m.Distro)
return errors.Errorf("Dual stack and single stack IPv6 feature is currently supported only with Ubuntu, but master is of distro type %s", m.Distro)
}
}
}
Expand Down Expand Up @@ -454,12 +454,12 @@ func (a *Properties) validateAgentPoolProfiles(isUpdate bool) error {
}

// validate os type is linux if dual stack feature is enabled
if a.FeatureFlags.IsIPv6DualStackEnabled() {
if a.FeatureFlags.IsIPv6DualStackEnabled() || a.FeatureFlags.IsIPv6OnlyEnabled() {
if agentPoolProfile.OSType == Windows {
return errors.Errorf("Dual stack feature is supported only with Linux, but agent pool '%s' is of os type %s", agentPoolProfile.Name, agentPoolProfile.OSType)
return errors.Errorf("Dual stack and single stack IPv6 feature is supported only with Linux, but agent pool '%s' is of os type %s", agentPoolProfile.Name, agentPoolProfile.OSType)
}
if agentPoolProfile.Distro == CoreOS {
return errors.Errorf("Dual stack feature is currently supported only with Ubuntu, but agent pool '%s' is of distro type %s", agentPoolProfile.Name, agentPoolProfile.Distro)
return errors.Errorf("Dual stack and single stack IPv6 feature is currently supported only with Ubuntu, but agent pool '%s' is of distro type %s", agentPoolProfile.Name, agentPoolProfile.Distro)
}
}

Expand Down Expand Up @@ -1233,7 +1233,7 @@ func validatePasswordComplexity(name string, password string) (out bool) {
}

// Validate validates the KubernetesConfig
func (k *KubernetesConfig) Validate(k8sVersion string, hasWindows, ipv6DualStackEnabled bool) error {
func (k *KubernetesConfig) Validate(k8sVersion string, hasWindows, ipv6DualStackEnabled, isIPv6 bool) error {
// number of minimum retries allowed for kubelet to post node status
const minKubeletRetries = 4

Expand All @@ -1255,6 +1255,24 @@ func (k *KubernetesConfig) Validate(k8sVersion string, hasWindows, ipv6DualStack
}
}

if isIPv6 {
sv, err := semver.Make(k8sVersion)
if err != nil {
return errors.Errorf("could not validate version %s", k8sVersion)
}
minVersion, err := semver.Make("1.18.0-alpha.4")
if err != nil {
return errors.New("could not validate version")
}
if sv.LT(minVersion) {
return errors.Errorf("IPv6 single stack not available in kubernetes version %s", k8sVersion)
}
// singel stack IPv6 feature is currently only supported with kubenet
if k.NetworkPlugin != "kubenet" {
return errors.Errorf("OrchestratorProfile.KubernetesConfig.NetworkPlugin '%s' is invalid. IPv6 single stack supported only with kubenet.", k.NetworkPlugin)
}
}

if k.ClusterSubnet != "" {
clusterSubnets := strings.Split(k.ClusterSubnet, ",")
if !ipv6DualStackEnabled && len(clusterSubnets) > 1 {
Expand Down
6 changes: 3 additions & 3 deletions pkg/engine/networkinterfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func CreateMasterVMNetworkInterfaces(cs *api.ContainerService) NetworkInterfaceA
}

// add ipv6 nic config for dual stack
if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6DualStack") {
if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6DualStack") || cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6Only") {
ipv6Config := network.InterfaceIPConfiguration{
Name: to.StringPtr("ipconfigv6"),
InterfaceIPConfigurationPropertiesFormat: &network.InterfaceIPConfigurationPropertiesFormat{
Expand Down Expand Up @@ -374,7 +374,7 @@ func createAgentVMASNetworkInterface(cs *api.ContainerService, profile *api.Agen
}
}

if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6DualStack") {
if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6DualStack") || cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6Only") {
if cs.Properties.OrchestratorProfile.KubernetesConfig.LoadBalancerSku != api.StandardLoadBalancerSku {
var backendPools []network.BackendAddressPool
if ipConfig.LoadBalancerBackendAddressPools != nil {
Expand All @@ -390,7 +390,7 @@ func createAgentVMASNetworkInterface(cs *api.ContainerService, profile *api.Agen
}

// add ipv6 nic config for dual stack
if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6DualStack") {
if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6DualStack") || cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6Only") {
ipv6Config := network.InterfaceIPConfiguration{
Name: to.StringPtr("ipconfigv6"),
InterfaceIPConfigurationPropertiesFormat: &network.InterfaceIPConfigurationPropertiesFormat{
Expand Down
3 changes: 3 additions & 0 deletions pkg/engine/template_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,9 @@ func getContainerServiceFuncMap(cs *api.ContainerService) template.FuncMap {
"IsIPv6DualStackFeatureEnabled": func() bool {
return cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6DualStack")
},
"IsIPv6Enabled": func() bool {
return cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6Only")
},
"GetBase64EncodedEnvironmentJSON": func() string {
customEnvironmentJSON, _ := cs.Properties.GetCustomEnvironmentJSON(false)
return base64.StdEncoding.EncodeToString([]byte(customEnvironmentJSON))
Expand Down
22 changes: 17 additions & 5 deletions pkg/engine/templates_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/engine/virtualmachinescalesets.go
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ func CreateAgentVMSS(cs *api.ContainerService, profile *api.AgentPoolProfile) Vi
ipconfig.VirtualMachineScaleSetIPConfigurationProperties = &ipConfigProps
ipConfigurations = append(ipConfigurations, ipconfig)

if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6DualStack") {
if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6DualStack") || cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6Only") {
ipconfigv6 := compute.VirtualMachineScaleSetIPConfiguration{
Name: to.StringPtr(fmt.Sprintf("ipconfig%dv6", i)),
VirtualMachineScaleSetIPConfigurationProperties: &compute.VirtualMachineScaleSetIPConfigurationProperties{
Expand Down

0 comments on commit 48d7c66

Please sign in to comment.