Skip to content

Commit 62d1cd5

Browse files
Merge pull request #229 from omersch381/add_predict_ip_bind
Generate predictable IPs for bind stateful set
2 parents c5389f5 + f6b5e87 commit 62d1cd5

File tree

3 files changed

+130
-76
lines changed

3 files changed

+130
-76
lines changed

controllers/designate_controller.go

Lines changed: 122 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,7 @@ func (r *DesignateReconciler) reconcileNormal(ctx context.Context, instance *des
715715
}
716716
Log.Info("Deployment API task reconciled")
717717

718+
// Handle Mdns predictable IPs configmap
718719
nad, err := nad.GetNADWithName(ctx, helper, instance.Spec.DesignateNetworkAttachment, instance.Namespace)
719720
if err != nil {
720721
return ctrl.Result{}, err
@@ -725,31 +726,6 @@ func (r *DesignateReconciler) reconcileNormal(ctx context.Context, instance *des
725726
return ctrl.Result{}, err
726727
}
727728

728-
nodeConfigMap := &corev1.ConfigMap{
729-
ObjectMeta: metav1.ObjectMeta{
730-
Name: designate.MdnsPredIPConfigMap,
731-
Namespace: instance.GetNamespace(),
732-
Labels: labels.GetLabels(instance, labels.GetGroupLabel(instance.ObjectMeta.Name), map[string]string{}),
733-
},
734-
Data: make(map[string]string),
735-
}
736-
737-
// Look for existing config map and if exists, read existing data and match
738-
// against nodes.
739-
foundMap := &corev1.ConfigMap{}
740-
err = helper.GetClient().Get(ctx, types.NamespacedName{Name: designate.MdnsPredIPConfigMap, Namespace: instance.GetNamespace()},
741-
foundMap)
742-
if err != nil {
743-
if k8s_errors.IsNotFound(err) {
744-
Log.Info(fmt.Sprintf("Ip map %s doesn't exist, creating.", designate.MdnsPredIPConfigMap))
745-
} else {
746-
return ctrl.Result{}, err
747-
}
748-
} else {
749-
Log.Info("Retrieved existing map, updating..")
750-
nodeConfigMap.Data = foundMap.Data
751-
}
752-
753729
//
754730
// Predictable IPs.
755731
//
@@ -761,6 +737,28 @@ func (r *DesignateReconciler) reconcileNormal(ctx context.Context, instance *des
761737
if err != nil {
762738
return ctrl.Result{}, err
763739
}
740+
741+
// Fetch allocated ips from Mdns and Bind config maps and store them in allocatedIPs
742+
mdnsLabels := labels.GetLabels(instance, labels.GetGroupLabel(instance.ObjectMeta.Name), map[string]string{})
743+
mdnsConfigMap, err := r.handleConfigMap(ctx, helper, instance, designate.MdnsPredIPConfigMap, mdnsLabels)
744+
if err != nil {
745+
return ctrl.Result{}, err
746+
}
747+
748+
bindLabels := labels.GetLabels(instance, labels.GetGroupLabel(instance.ObjectMeta.Name), map[string]string{})
749+
bindConfigMap, err := r.handleConfigMap(ctx, helper, instance, designate.BindPredIPConfigMap, bindLabels)
750+
if err != nil {
751+
return ctrl.Result{}, err
752+
}
753+
754+
allocatedIPs := make(map[string]bool)
755+
for _, predIP := range bindConfigMap.Data {
756+
allocatedIPs[predIP] = true
757+
}
758+
for _, predIP := range mdnsConfigMap.Data {
759+
allocatedIPs[predIP] = true
760+
}
761+
764762
// Get a list of the nodes in the cluster
765763

766764
// TODO(oschwart):
@@ -773,54 +771,51 @@ func (r *DesignateReconciler) reconcileNormal(ctx context.Context, instance *des
773771
if err != nil {
774772
return ctrl.Result{}, err
775773
}
776-
updatedMap := make(map[string]string)
777-
allocatedIPs := make(map[string]bool)
778-
var predictableIPsRequired []string
779774

780-
// First scan existing allocations so we can keep existing allocations.
781-
// Keeping track of what's required and what already exists. If a node is
782-
// removed from the cluster, it's IPs will not be added to the allocated
783-
// list and are effectively recycled.
775+
var nodeNames []string
784776
for _, node := range nodes.Items {
785-
nodeName := fmt.Sprintf("mdns_%s", node.Name)
786-
if ipValue, ok := nodeConfigMap.Data[nodeName]; ok {
787-
updatedMap[nodeName] = ipValue
788-
allocatedIPs[ipValue] = true
789-
Log.Info(fmt.Sprintf("%s has IP mapping %s: %s", node.Name, nodeName, ipValue))
790-
} else {
791-
predictableIPsRequired = append(predictableIPsRequired, nodeName)
792-
}
777+
nodeNames = append(nodeNames, fmt.Sprintf("mdns_%s", node.Name))
793778
}
794-
// Get new IPs using the range from predictableIPParmas minus the
795-
// allocatedIPs captured above.
796-
Log.Info(fmt.Sprintf("Allocating %d predictable IPs", len(predictableIPsRequired)))
797-
for _, nodeName := range predictableIPsRequired {
798-
nodeIP, err := designate.GetNextIP(predictableIPParams, allocatedIPs)
799-
if err != nil {
800-
// An error here is really unexpected- it means either we have
801-
// messed up the allocatedIPs list or the range we are assuming is
802-
// too small for the number of mdns pod.
803-
return ctrl.Result{}, err
804-
}
805-
updatedMap[nodeName] = nodeIP
779+
780+
updatedMap, allocatedIPs, err := r.allocatePredictableIPs(ctx, predictableIPParams, nodeNames, mdnsConfigMap.Data, allocatedIPs)
781+
if err != nil {
782+
return ctrl.Result{}, err
806783
}
807784

808-
mapLabels := labels.GetLabels(instance, labels.GetGroupLabel(instance.ObjectMeta.Name), map[string]string{})
809-
_, err = controllerutil.CreateOrPatch(ctx, helper.GetClient(), nodeConfigMap, func() error {
810-
nodeConfigMap.Labels = util.MergeStringMaps(nodeConfigMap.Labels, mapLabels)
811-
nodeConfigMap.Data = updatedMap
812-
err := controllerutil.SetControllerReference(instance, nodeConfigMap, helper.GetScheme())
813-
if err != nil {
814-
return err
815-
}
816-
return nil
785+
_, err = controllerutil.CreateOrPatch(ctx, helper.GetClient(), mdnsConfigMap, func() error {
786+
mdnsConfigMap.Labels = util.MergeStringMaps(mdnsConfigMap.Labels, mdnsLabels)
787+
mdnsConfigMap.Data = updatedMap
788+
return controllerutil.SetControllerReference(instance, mdnsConfigMap, helper.GetScheme())
817789
})
818790

819791
if err != nil {
820792
Log.Info("Unable to create config map for mdns ips...")
821793
return ctrl.Result{}, err
822794
}
823795

796+
// Handle Bind predictable IPs configmap
797+
bindReplicaCount := int(*instance.Spec.DesignateBackendbind9.Replicas)
798+
var bindNames []string
799+
for i := 0; i < bindReplicaCount; i++ {
800+
bindNames = append(bindNames, fmt.Sprintf("bind_address_%d", i))
801+
}
802+
803+
updatedBindMap, _, err := r.allocatePredictableIPs(ctx, predictableIPParams, bindNames, bindConfigMap.Data, allocatedIPs)
804+
if err != nil {
805+
return ctrl.Result{}, err
806+
}
807+
808+
_, err = controllerutil.CreateOrPatch(ctx, helper.GetClient(), bindConfigMap, func() error {
809+
bindConfigMap.Labels = util.MergeStringMaps(bindConfigMap.Labels, bindLabels)
810+
bindConfigMap.Data = updatedBindMap
811+
return controllerutil.SetControllerReference(instance, bindConfigMap, helper.GetScheme())
812+
})
813+
814+
if err != nil {
815+
Log.Info("Unable to create config map for bind ips...")
816+
return ctrl.Result{}, err
817+
}
818+
824819
// deploy designate-central
825820
designateCentral, op, err := r.centralDeploymentCreateOrUpdate(ctx, instance)
826821
if err != nil {
@@ -1083,6 +1078,72 @@ func (r *DesignateReconciler) reconcileNormal(ctx context.Context, instance *des
10831078
return ctrl.Result{}, nil
10841079
}
10851080

1081+
func (r *DesignateReconciler) handleConfigMap(ctx context.Context, helper *helper.Helper, instance *designatev1beta1.Designate, configMapName string, labels map[string]string) (*corev1.ConfigMap, error) {
1082+
Log := r.GetLogger(ctx)
1083+
1084+
nodeConfigMap := &corev1.ConfigMap{
1085+
ObjectMeta: metav1.ObjectMeta{
1086+
Name: configMapName,
1087+
Namespace: instance.GetNamespace(),
1088+
Labels: labels,
1089+
},
1090+
Data: make(map[string]string),
1091+
}
1092+
1093+
// Look for existing config map and if exists, read existing data and match
1094+
// against nodes.
1095+
foundMap := &corev1.ConfigMap{}
1096+
err := helper.GetClient().Get(ctx, types.NamespacedName{Name: configMapName, Namespace: instance.GetNamespace()}, foundMap)
1097+
if err != nil {
1098+
if k8s_errors.IsNotFound(err) {
1099+
Log.Info(fmt.Sprintf("Ip map %s doesn't exist, creating.", configMapName))
1100+
} else {
1101+
return nil, err
1102+
}
1103+
} else {
1104+
Log.Info("Retrieved existing map, updating..")
1105+
nodeConfigMap.Data = foundMap.Data
1106+
}
1107+
1108+
return nodeConfigMap, nil
1109+
}
1110+
1111+
func (r *DesignateReconciler) allocatePredictableIPs(ctx context.Context, predictableIPParams *designate.NADIpam, ipHolders []string, existingMap map[string]string, allocatedIPs map[string]bool) (map[string]string, map[string]bool, error) {
1112+
Log := r.GetLogger(ctx)
1113+
1114+
updatedMap := make(map[string]string)
1115+
var predictableIPsRequired []string
1116+
1117+
// First scan existing allocations so we can keep existing allocations.
1118+
// Keeping track of what's required and what already exists. If a node is
1119+
// removed from the cluster, it's IPs will not be added to the allocated
1120+
// list and are effectively recycled.
1121+
for _, ipHolder := range ipHolders {
1122+
if ipValue, ok := existingMap[ipHolder]; ok {
1123+
updatedMap[ipHolder] = ipValue
1124+
Log.Info(fmt.Sprintf("%s has IP mapping: %s", ipHolder, ipValue))
1125+
} else {
1126+
predictableIPsRequired = append(predictableIPsRequired, ipHolder)
1127+
}
1128+
}
1129+
1130+
// Get new IPs using the range from predictableIPParmas minus the
1131+
// allocatedIPs captured above.
1132+
Log.Info(fmt.Sprintf("Allocating %d predictable IPs", len(predictableIPsRequired)))
1133+
for _, nodeName := range predictableIPsRequired {
1134+
ipAddress, err := designate.GetNextIP(predictableIPParams, allocatedIPs)
1135+
if err != nil {
1136+
// An error here is really unexpected- it means either we have
1137+
// messed up the allocatedIPs list or the range we are assuming is
1138+
// too small for the number of mdns pod.
1139+
return nil, nil, err
1140+
}
1141+
updatedMap[nodeName] = ipAddress
1142+
}
1143+
1144+
return updatedMap, allocatedIPs, nil
1145+
}
1146+
10861147
func (r *DesignateReconciler) reconcileUpdate(ctx context.Context, instance *designatev1beta1.Designate) (ctrl.Result, error) {
10871148
Log := r.GetLogger(ctx)
10881149

pkg/designate/bind_ctrl_network.go

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,12 @@ func GetPredictableIPAM(networkParameters *NetworkParameters) (*NADIpam, error)
3636
return predParams, nil
3737
}
3838

39-
// GetNextIP picks the next available IP from the range defined by a NADIpam,
40-
// skipping ones that are already used appear as keys in the currentValues map.
41-
func GetNextIP(predParams *NADIpam, currentValues map[string]bool) (string, error) {
42-
candidateAddress := predParams.RangeStart
43-
for alloced := true; alloced; {
44-
45-
if _, ok := currentValues[candidateAddress.String()]; ok {
46-
if candidateAddress == predParams.RangeEnd {
47-
return "", fmt.Errorf("predictable IPs: out of available addresses")
48-
}
49-
candidateAddress = candidateAddress.Next()
50-
} else {
51-
alloced = false
39+
func GetNextIP(predParams *NADIpam, allocatedIPs map[string]bool) (string, error) {
40+
for candidateAddress := predParams.RangeStart; candidateAddress != predParams.RangeEnd; candidateAddress = candidateAddress.Next() {
41+
if !allocatedIPs[candidateAddress.String()] {
42+
allocatedIPs[candidateAddress.String()] = true
43+
return candidateAddress.String(), nil
5244
}
5345
}
54-
currentValues[candidateAddress.String()] = true
55-
return candidateAddress.String(), nil
46+
return "", fmt.Errorf("predictable IPs: out of available addresses")
5647
}

pkg/designate/const.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,6 @@ const (
4040
DesignateRndcKey = "rndc-key"
4141

4242
MdnsPredIPConfigMap = "designate-mdns-ip-map"
43+
44+
BindPredIPConfigMap = "designate-bind-ip-map"
4345
)

0 commit comments

Comments
 (0)