Skip to content

Commit

Permalink
Manage DNS for load balancer services
Browse files Browse the repository at this point in the history
  • Loading branch information
ironcladlou committed Nov 9, 2018
1 parent 425cae0 commit 008f4fd
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 1 deletion.
1 change: 1 addition & 0 deletions cmd/cluster-ingress-operator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ func main() {
// TODO Use a named constant for the router's namespace or get the
// namespace from config.
sdk.Watch("apps/v1", "DaemonSet", "openshift-ingress", resyncPeriod)
sdk.Watch("v1", "Service", "openshift-ingress", resyncPeriod)
sdk.Handle(handler)
sdk.Run(context.TODO())
}
14 changes: 14 additions & 0 deletions manifests/01-kube-system-aws-creds-role-binding.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Binds the operator role to its Service Account.
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: ingress-operator-aws-creds-secret-reader
namespace: kube-system
subjects:
- kind: ServiceAccount
name: ingress-operator
namespace: openshift-ingress-operator
roleRef:
kind: Role
apiGroup: rbac.authorization.k8s.io
name: aws-creds-secret-reader
2 changes: 1 addition & 1 deletion pkg/manifests/manifests.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (f *Factory) DefaultClusterIngress(ic *util.InstallConfig) (*ingressv1alpha
if err != nil {
return nil, err
}
ingressDomain := fmt.Sprintf("%s.%s", ic.Metadata.Name, ic.BaseDomain)
ingressDomain := fmt.Sprintf("*.apps.%s.%s", ic.Metadata.Name, ic.BaseDomain)
ci.Spec.IngressDomain = &ingressDomain
return ci, nil
}
Expand Down
82 changes: 82 additions & 0 deletions pkg/stub/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,15 @@ import (

"github.com/operator-framework/operator-sdk/pkg/sdk"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utilerrors "k8s.io/apimachinery/pkg/util/errors"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/route53"
)

const (
Expand Down Expand Up @@ -242,6 +248,12 @@ func (h *Handler) ensureRouterForIngress(ci *ingressv1alpha1.ClusterIngress) err
} else if !errors.IsAlreadyExists(err) {
return fmt.Errorf("failed to create router service %s/%s: %v", service.Namespace, service.Name, err)
}
if ci.Spec.IngressDomain != nil {
err = h.ensureDNSForLoadBalancer(*ci.Spec.IngressDomain, service)
if err != nil {
return fmt.Errorf("failed to ensure DNS for router service %s/%s: %v", service.Namespace, service.Name, err)
}
}
}
}
}
Expand All @@ -262,3 +274,73 @@ func (h *Handler) ensureRouterDeleted(ci *ingressv1alpha1.ClusterIngress) error
}
return nil
}

// TODO: Tag the record so it gets cleaned up during cluster destroy
// TODO: Discover the domain hosted zone ID
// TODO: Discover the target hosted zone ID
// TODO: Figure out why the event loop is so spammy
// TODO: Don't update unless there's a diff
func (h *Handler) ensureDNSForLoadBalancer(domain string, service *corev1.Service) error {
if len(service.Status.LoadBalancer.Ingress) == 0 {
logrus.Infof("won't update DNS record for load balancer service %s/%s because status contains no ingresses", service.Namespace, service.Name)
return nil
}

target := service.Status.LoadBalancer.Ingress[0].Hostname
if len(target) == 0 {
logrus.Infof("won't update DNS record for load balancer service %s/%s because ingress hostname is empty", service.Namespace, service.Name)
return nil
}

domainHostedZoneID := "Z3URY6TWQ91KVV"
targetHostedZoneID := "Z3AADJGX6KTTL2"

awsCreds := &corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: "aws-creds",
Namespace: "kube-system",
},
}
err := sdk.Get(awsCreds)
if err != nil {
return fmt.Errorf("failed to get aws creds from %s/%s: %v", awsCreds.Namespace, awsCreds.Name, err)
}

creds := credentials.NewStaticCredentials(string(awsCreds.Data["aws_access_key_id"]), string(awsCreds.Data["aws_secret_access_key"]), "")
sess, err := session.NewSession(&aws.Config{Credentials: creds})
if err != nil {
return fmt.Errorf("couldn't create AWS client session while updating DNS for service %s/%s: %v", service.Namespace, service.Name, err)
}
svc := route53.New(sess)

params := &route53.ChangeResourceRecordSetsInput{
HostedZoneId: aws.String(domainHostedZoneID),
ChangeBatch: &route53.ChangeBatch{
Changes: []*route53.Change{
{
Action: aws.String("UPSERT"),
ResourceRecordSet: &route53.ResourceRecordSet{
Name: aws.String(domain),
Type: aws.String("A"),
AliasTarget: &route53.AliasTarget{
HostedZoneId: aws.String(targetHostedZoneID),
DNSName: aws.String(target),
EvaluateTargetHealth: aws.Bool(false),
},
},
},
},
Comment: aws.String("ingress.openshift.io/cluster-ingress=" + h.InstallConfig.Metadata.Name),
},
}
resp, err := svc.ChangeResourceRecordSets(params)
if err != nil {
return fmt.Errorf("couldn't update DNS record for service %s/%s: %v", service.Namespace, service.Name, err)
}
logrus.Infof("updated DNS record for service %s/%s, %s -> %s: %v", service.Namespace, service.Name, domain, target, resp)
return nil
}

0 comments on commit 008f4fd

Please sign in to comment.