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

Add support for deployments in existing subnet #780

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
**/dev
/bin
hack/tools/bin
/.run

*.coverprofile
*.html
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ COPY --from=builder /go/bin/gardener-extension-provider-openstack /gardener-exte
ENTRYPOINT ["/gardener-extension-provider-openstack"]

############# gardener-extension-admission-openstack
FROM base as gardener-extension-admission-openstack
FROM base AS gardener-extension-admission-openstack
WORKDIR /

COPY --from=builder /go/bin/gardener-extension-admission-openstack /gardener-extension-admission-openstack
Expand Down
4 changes: 2 additions & 2 deletions charts/internal/machineclass/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ machineClasses:
imageName: coreos-v1.0
#imageID: 836428cd-5f98-1305-af9d-9825d4dfd0ec
networkID: 426428cd-5e88-4005-9fad-9555d4dfd0fb
podNetworkCIDRs:
- 100.96.0.0/11
# podNetworkCIDRs:
# - 100.96.0.0/11
# rootDiskSize: 100 # 100GB
# rootDiskType: standard_hdd
# serverGroupID: b35e94c1-15a7-4b54-a0f6-8789fasdf79s
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ mountOptions:
parameters:
type: default
shareNetworkID: {{ $.Values.openstack.shareNetworkID }}
nfs-shareClient: {{ required "openstack.shareClient needs to be set" $.Values.openstack.shareClient }}
{{- if $.Values.openstack.shareClient}}
nfs-shareClient: {{ $.Values.openstack.shareClient }}
{{- end }}
csi.storage.k8s.io/provisioner-secret-name: manila-csi-plugin
csi.storage.k8s.io/provisioner-secret-namespace: {{ $.Release.Namespace }}
csi.storage.k8s.io/node-stage-secret-name: manila-csi-plugin
Expand Down Expand Up @@ -43,7 +45,9 @@ parameters:
type: default
autoTopology: "true"
shareNetworkID: {{ $.Values.openstack.shareNetworkID }}
nfs-shareClient: {{ required "openstack.shareClient needs to be set" $.Values.openstack.shareClient }}
{{- if $.Values.openstack.shareClient}}
nfs-shareClient: {{ $.Values.openstack.shareClient }}
{{- end }}
csi.storage.k8s.io/provisioner-secret-name: manila-csi-plugin
csi.storage.k8s.io/provisioner-secret-namespace: {{ $.Release.Namespace }}
csi.storage.k8s.io/node-stage-secret-name: manila-csi-plugin
Expand Down Expand Up @@ -72,7 +76,9 @@ parameters:
type: default
availability: {{ required "openstack.availabilityZones needs to be set" . }}
shareNetworkID: {{ $.Values.openstack.shareNetworkID }}
nfs-shareClient: {{ required "openstack.shareClient needs to be set" $.Values.openstack.shareClient }}
{{- if $.Values.openstack.shareClient}}
nfs-shareClient: {{ $.Values.openstack.shareClient }}
{{- end }}
csi.storage.k8s.io/provisioner-secret-name: manila-csi-plugin
csi.storage.k8s.io/provisioner-secret-namespace: {{ $.Release.Namespace }}
csi.storage.k8s.io/node-stage-secret-name: manila-csi-plugin
Expand Down Expand Up @@ -107,7 +113,9 @@ parameters:
type: default
availability: {{ required "openstack.availabilityZones needs to be set" . }}
shareNetworkID: {{ $.Values.openstack.shareNetworkID }}
nfs-shareClient: {{ required "openstack.shareClient needs to be set" $.Values.openstack.shareClient }}
{{- if $.Values.openstack.shareClient}}
nfs-shareClient: {{ $.Values.openstack.shareClient }}
{{- end }}
csi.storage.k8s.io/provisioner-secret-name: manila-csi-plugin
csi.storage.k8s.io/provisioner-secret-namespace: {{ $.Release.Namespace }}
csi.storage.k8s.io/node-stage-secret-name: manila-csi-plugin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ openstack:
- zone1
- zone2
shareNetworkID: shareNetworkIDValue
shareClient: 10.180.0.0/16
# shareClient: 10.180.0.0/16
shareProtocol: NFS
authURL: authURLValue
region: regionValue
Expand Down
33 changes: 18 additions & 15 deletions docs/usage/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,31 +61,34 @@ networks:
# enabled: true
```

The `floatingPoolName` is the name of the floating pool you want to use for your shoot.
If you don't know which floating pools are available look it up in the respective `CloudProfile`.
* The `floatingPoolName` is the name of the floating pool you want to use for your shoot.
If you don't know which floating pools are available look it up in the respective `CloudProfile`.

With `floatingPoolSubnetName` you can explicitly define to which subnet in the floating pool network (defined via `floatingPoolName`) the router should be attached to.
* With `floatingPoolSubnetName` you can explicitly define to which subnet in the floating pool network (defined via `floatingPoolName`) the router should be attached to.

`networks.id` is an optional field. If it is given, you can specify the uuid of an existing private Neutron network (created manually, by other tooling, ...) that should be reused. A new subnet for the Shoot will be created in it.
* `networks.id` is an optional field. If it is given, you can specify the uuid of an existing private Neutron network (created manually, by other tooling, ...) that should be reused. A new subnet for the Shoot will be created in it.

If a `networks.id` is given and calico shoot clusters are created without a network overlay within one network make sure that the pod CIDR specified in `shoot.spec.networking.pods` is not overlapping with any other pod CIDR used in that network.
If a `networks.id` is given and calico shoot clusters are created without a network overlay within one network make sure that the pod CIDR specified in `shoot.spec.networking.pods` is not overlapping with any other pod CIDR used in that network.
Overlapping pod CIDRs will lead to disfunctional shoot clusters.

The `networks.router` section describes whether you want to create the shoot cluster in an already existing router or whether to create a new one:

* If `networks.router.id` is given then you have to specify the router id of the existing router that was created by other means (manually, other tooling, ...).
* The `networks.router` section describes whether you want to create the shoot cluster in an already existing router or whether to create a new one:
* If `networks.router.id` is given then you have to specify the router id of the existing router that was created by other means (manually, other tooling, ...).
If you want to get a fresh router for the shoot then just omit the `networks.router` field.

* `networks.subnetID` is an optional field where you can specify the uuid of an existing private Neutron subnet.
The shoot worker nodes will be created in the provided subnet.
* In any other case, the shoot cluster will be created in a **new** subnet.

* In any case, the shoot cluster will be created in a **new** subnet.

The `networks.workers` section describes the CIDR for a subnet that is used for all shoot worker nodes, i.e., VMs which later run your applications.
* The `networks.workers` section describes the CIDR for a subnet that is used for all shoot worker nodes, i.e., VMs which later run your applications.

You can freely choose these CIDRs and it is your responsibility to properly design the network layout to suit your needs.
You can freely choose these CIDRs and it is your responsibility to properly design the network layout to suit your needs.

Apart from the router and the worker subnet the OpenStack extension will also create a network, router interfaces, security groups, and a key pair.
* Apart from the router and the worker subnet the OpenStack extension will also create a network, router interfaces, security groups, and a key pair.

The optional `networks.shareNetwork.enabled` field controls the creation of a share network. This is only needed if shared
file system storage (like NFS) should be used. Note, that in this case, the `ControlPlaneConfig` needs additional configuration, too.
* The optional `networks.shareNetwork.enabled` field controls the creation of a share network.
This is only needed if shared file system storage (like NFS) should be used. Note, that in this case, the `ControlPlaneConfig` needs additional configuration, too.
* if `networks.subnetID` is used then the `shareNetworks` property should not be enabled.
The user is responsible for creating the Share Network to the subnet before

## `ControlPlaneConfig`

Expand Down
12 changes: 12 additions & 0 deletions hack/api-reference/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1401,6 +1401,18 @@ string
</tr>
<tr>
<td>
<code>subnetId</code></br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>SubnetID is the ID of an existing subnet.</p>
</td>
</tr>
<tr>
<td>
<code>shareNetwork</code></br>
<em>
<a href="#openstack.provider.extensions.gardener.cloud/v1alpha1.ShareNetwork">
Expand Down
2 changes: 2 additions & 0 deletions pkg/apis/openstack/types_infrastructure.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ type Networks struct {
Workers string
// ID is the ID of an existing private network.
ID *string
// SubnetID is the ID of an existing subnet.
SubnetID *string
// ShareNetwork holds information about the share network (used for shared file systems like NFS)
ShareNetwork *ShareNetwork
}
Expand Down
3 changes: 3 additions & 0 deletions pkg/apis/openstack/v1alpha1/types_infrastructure.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ type Networks struct {
// ID is the ID of an existing private network.
// +optional
ID *string `json:"id,omitempty"`
// SubnetID is the ID of an existing subnet.
// +optional
SubnetID *string `json:"subnetId,omitempty"`
// ShareNetwork holds information about the share network (used for shared file systems like NFS)
// +optional
ShareNetwork *ShareNetwork `json:"shareNetwork,omitempty"`
Expand Down
2 changes: 2 additions & 0 deletions pkg/apis/openstack/v1alpha1/zz_generated.conversion.go

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

5 changes: 5 additions & 0 deletions pkg/apis/openstack/v1alpha1/zz_generated.deepcopy.go

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

11 changes: 7 additions & 4 deletions pkg/apis/openstack/validation/controlplane.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func ValidateControlPlaneConfig(controlPlaneConfig *api.ControlPlaneConfig, infr
allErrs = append(allErrs, featurevalidation.ValidateFeatureGates(controlPlaneConfig.CloudControllerManager.FeatureGates, version, fldPath.Child("cloudControllerManager", "featureGates"))...)
}

allErrs = append(allErrs, validateStorage(controlPlaneConfig.Storage, infraConfig.Networks.ShareNetwork, fldPath.Child("storage"))...)
allErrs = append(allErrs, validateStorage(controlPlaneConfig.Storage, infraConfig.Networks, fldPath.Child("storage"))...)

return allErrs
}
Expand Down Expand Up @@ -138,13 +138,16 @@ func validateLoadBalancerClassesConstraints(floatingPools []api.FloatingPool, sh
return allErrs
}

func validateStorage(storage *api.Storage, shareNetwork *api.ShareNetwork, fldPath *field.Path) field.ErrorList {
func validateStorage(storage *api.Storage, networks api.Networks, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
if storage == nil || storage.CSIManila == nil || !storage.CSIManila.Enabled {
return allErrs
}
if shareNetwork == nil || !shareNetwork.Enabled {
allErrs = append(allErrs, field.Invalid(fldPath.Child("csiManila", "enabled"), storage.CSIManila.Enabled, "share network must be created if CSI manila driver is enabled"))

// for an existing subnet we do not need to validate the storage since we can only do that at runtime by checking
// if the subnet has an existing shareNetwork connection.
if networks.SubnetID == nil && (networks.ShareNetwork == nil || !networks.ShareNetwork.Enabled) {
return append(allErrs, field.Invalid(fldPath.Child("csiManila", "enabled"), storage.CSIManila.Enabled, "share network must be created if CSI manila driver is enabled"))
}
return allErrs
}
16 changes: 15 additions & 1 deletion pkg/apis/openstack/validation/infrastructure.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func ValidateInfrastructureConfig(infra *api.InfrastructureConfig, nodesCIDR *st
}

networksPath := fldPath.Child("networks")
if len(infra.Networks.Worker) == 0 && len(infra.Networks.Workers) == 0 {
if len(infra.Networks.Worker) == 0 && len(infra.Networks.Workers) == 0 && infra.Networks.SubnetID == nil {
allErrs = append(allErrs, field.Required(networksPath.Child("workers"), "must specify the network range for the worker network"))
}

Expand All @@ -59,6 +59,20 @@ func ValidateInfrastructureConfig(infra *api.InfrastructureConfig, nodesCIDR *st
}
}

if infra.Networks.SubnetID != nil {
if infra.Networks.ID == nil {
allErrs = append(allErrs, field.Invalid(networksPath.Child("subnetId"), infra.Networks.SubnetID, "if subnet ID is provided a networkID must be provided"))
}
if _, err := uuid.Parse(*infra.Networks.SubnetID); err != nil {
allErrs = append(allErrs, field.Invalid(networksPath.Child("subnetId"), infra.Networks.SubnetID, "if subnet ID is provided it must be a valid OpenStack UUID"))
}

if infra.Networks.ShareNetwork != nil && infra.Networks.ShareNetwork.Enabled {
allErrs = append(allErrs, field.Invalid(networksPath.Child("shareNetwork").Child("enabled"), infra.Networks.ShareNetwork.Enabled,
"the ShareNetwork can not be enabled when a user provider subnet is used. Please disable this option and ensure the shareNetwork connection with your subnet"))
}
}

if infra.Networks.Router != nil && len(infra.Networks.Router.ID) == 0 {
allErrs = append(allErrs, field.Invalid(networksPath.Child("router", "id"), infra.Networks.Router.ID, "router id must not be empty when router key is provided"))
}
Expand Down
49 changes: 49 additions & 0 deletions pkg/apis/openstack/validation/infrastructure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,55 @@ var _ = Describe("InfrastructureConfig validation", func() {
"Field": Equal("floatingPoolSubnetName"),
}))
})

It("should forbid subnet id when network id is unspecified", func() {
infrastructureConfig.Networks.SubnetID = ptr.To(uuid.NewString())

errorList := ValidateInfrastructureConfig(infrastructureConfig, &nodes, nilPath)

Expect(errorList).To(ConsistOfFields(Fields{
"Type": Equal(field.ErrorTypeInvalid),
"Field": Equal("networks.subnetId"),
"Detail": Equal("if subnet ID is provided a networkID must be provided"),
}))
})

It("should forbid an invalid subnet id", func() {
infrastructureConfig.Networks.ID = ptr.To(uuid.NewString())
infrastructureConfig.Networks.SubnetID = ptr.To("thisiswrong")

errorList := ValidateInfrastructureConfig(infrastructureConfig, &nodes, nilPath)

Expect(errorList).To(ConsistOfFields(Fields{
"Type": Equal(field.ErrorTypeInvalid),
"Field": Equal("networks.subnetId"),
"Detail": Equal("if subnet ID is provided it must be a valid OpenStack UUID"),
}))
})

It("should allow an valid OpenStack UUID as subnet ID", func() {
infrastructureConfig.Networks.ID = ptr.To(uuid.NewString())
infrastructureConfig.Networks.SubnetID = ptr.To(uuid.NewString())

errorList := ValidateInfrastructureConfig(infrastructureConfig, &nodes, nilPath)

Expect(errorList).To(BeEmpty())
})

It("should forbid using user-managed subnet with a shareNetwork", func() {
infrastructureConfig.Networks.ID = ptr.To(uuid.NewString())
infrastructureConfig.Networks.SubnetID = ptr.To(uuid.NewString())
infrastructureConfig.Networks.ShareNetwork = &api.ShareNetwork{
Enabled: true,
}

errorList := ValidateInfrastructureConfig(infrastructureConfig, &nodes, nilPath)
Expect(errorList).To(ConsistOfFields(Fields{
"Type": Equal(field.ErrorTypeInvalid),
"Field": Equal("networks.shareNetwork.enabled"),
"Detail": Equal("the ShareNetwork can not be enabled when a user provider subnet is used. Please disable this option and ensure the shareNetwork connection with your subnet"),
}))
})
})

Context("CIDR", func() {
Expand Down
5 changes: 5 additions & 0 deletions pkg/apis/openstack/zz_generated.deepcopy.go

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

6 changes: 0 additions & 6 deletions pkg/controller/controlplane/valuesprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ import (
"github.com/gardener/gardener-extension-provider-openstack/charts"
api "github.com/gardener/gardener-extension-provider-openstack/pkg/apis/openstack"
"github.com/gardener/gardener-extension-provider-openstack/pkg/apis/openstack/helper"
"github.com/gardener/gardener-extension-provider-openstack/pkg/internal/infrastructure"
"github.com/gardener/gardener-extension-provider-openstack/pkg/openstack"
"github.com/gardener/gardener-extension-provider-openstack/pkg/utils"
)
Expand Down Expand Up @@ -958,10 +957,6 @@ func (vp *valuesProvider) addCSIManilaValues(
"clusterID": cp.Namespace,
}

infraConfig, err := helper.InfrastructureConfigFromRawExtension(cluster.Shoot.Spec.Provider.InfrastructureConfig)
if err != nil {
return fmt.Errorf("could not decode infrastructure config of controlplane '%s': %w", k8sclient.ObjectKeyFromObject(cp), err)
}
infraStatus, err := vp.getInfrastructureStatus(cp)
if err != nil {
return err
Expand Down Expand Up @@ -990,7 +985,6 @@ func (vp *valuesProvider) addCSIManilaValues(
values["openstack"] = map[string]interface{}{
"availabilityZones": vp.getAllWorkerPoolsZones(cluster),
"shareNetworkID": shareNetworkID,
"shareClient": infrastructure.WorkersCIDR(infraConfig),
Copy link
Contributor

Choose a reason for hiding this comment

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

How can the "shareClient" be set if we remove it from here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We don't set it basically. The shareClient constricts who can access the share, for which at the moment we have no strict need to do, it even restrict customer use cases. The template doesn't necessarily need to change, we just choose not to configure this.

"authURL": authURL,
"region": cp.Spec.Region,
"domainName": domainName,
Expand Down
20 changes: 10 additions & 10 deletions pkg/controller/controlplane/valuesprovider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -660,11 +660,11 @@ var _ = Describe("ValuesProvider", func() {
"authURL": authURL,
"region": "europe",
"applicationCredentialSecret": "",
"shareClient": "10.200.0.0/19",
"shareNetworkID": "1111-2222-3333-4444",
"domainName": "domain-name",
"tlsInsecure": "",
"caCert": "",
// "shareClient": "10.200.0.0/19",
"shareNetworkID": "1111-2222-3333-4444",
"domainName": "domain-name",
"tlsInsecure": "",
"caCert": "",
},
}),
}))
Expand Down Expand Up @@ -791,11 +791,11 @@ var _ = Describe("ValuesProvider", func() {
"authURL": authURL,
"region": "europe",
"applicationCredentialSecret": "",
"shareClient": "10.200.0.0/19",
"shareNetworkID": "1111-2222-3333-4444",
"domainName": "domain-name",
"tlsInsecure": "",
"caCert": "",
// "shareClient": "10.200.0.0/19",
"shareNetworkID": "1111-2222-3333-4444",
"domainName": "domain-name",
"tlsInsecure": "",
"caCert": "",
},
}),
}))
Expand Down
Loading
Loading