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 annotation for exposing NEGs #284

Merged
merged 10 commits into from
Jun 20, 2018
Merged

Conversation

agau4779
Copy link
Contributor

@agau4779 agau4779 commented May 23, 2018

This PR adds a new annotation for exposing standalone NEGs on Services without requiring an Ingress.

Additionally:

  • Refactors NEG naming to use ServicePort Ports instead of TargetPorts, because it is possible to have multiple ServicePorts point to the same TargetPort. Note that ServicePort Ports are always int32, while TargetPorts may be an int or a string.
  • Pass ServicePort into via a map mapping Port:TargetPort within /pkg/neg (PortNameMap type)
  • feature flag around exposed NEGs

To do in later PRs:

  • merge the expose NEG and ingress NEG annotations

@k8s-ci-robot k8s-ci-robot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels May 23, 2018
@agau4779 agau4779 changed the title [WIP] add annotation for expose NEGs Add annotation for exposing NEGs May 23, 2018
@k8s-ci-robot k8s-ci-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label May 23, 2018
@agau4779
Copy link
Contributor Author

/assign freehan

@nicksardo
Copy link
Contributor

/ok-to-test

@k8s-ci-robot k8s-ci-robot removed the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label May 24, 2018
glog.V(2).Infof("Applying annotation to service: %s", annotation)

service.Annotations[negVisibilityAnnotationKey] = annotation
c.serviceLister.Update(service)
Copy link
Contributor

Choose a reason for hiding this comment

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

do not omit the error

res.NetworkEndpointGroups[port] = c.namer.NEG(namespace, name, port)
}

return fmt.Sprintf("%+v", res), nil
Copy link
Contributor

Choose a reason for hiding this comment

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

Use a struct to represent the annotation schema. And then use json.Marshal to convert it into json.

// To enable this feature, the value of the annotation must be "true".
// This annotation should be specified on services that are backing ingresses.
// WARNING: The feature will NOT be effective in the following circumstances:
// 1. NEG feature is not enabled in feature gate.
// 2. Service is not referenced in any ingress.
// 3. Adding this annotation on ingress.
NetworkEndpointGroupAlphaAnnotation = "alpha.cloud.google.com/load-balancer-neg"
Copy link
Contributor

Choose a reason for hiding this comment

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

let us keep the boolean trigger for now.

Add a separate annotation for expose neg

@agau4779 agau4779 force-pushed the expose-negs branch 2 times, most recently from 4a83279 to 80b03d8 Compare May 25, 2018 18:50
Copy link
Contributor

@freehan freehan left a comment

Choose a reason for hiding this comment

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

need to remove visibility annotation or make it empty when trigger annotations are removed.

// ExposeNegAnnotation is the format of the annotation associated with the
// cloud.google.com/use-neg key.
type ExposeNegAnnotation struct {
SvcPorts map[string]NegAttributes
Copy link
Contributor

Choose a reason for hiding this comment

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

You can add json tags: https://eager.io/blog/go-and-json/

// NEGAnnotation is the annotation key to specify standalone NEGs associated
// with the service. This should be a valid JSON string, for example:
// {"SvcPorts":{"80":{"Enabled":true}}}
NEGAnnotation = "cloud.google.com/use-neg"
Copy link
Contributor

Choose a reason for hiding this comment

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

expose-load-balancer-neg

func (svc Service) NEGEnabled() bool {
// NEGIngress returns true if the annotation is to be applied on
// Ingress-referenced ports
func (svc Service) NEGIngress() bool {
v, ok := svc.v[NetworkEndpointGroupAlphaAnnotation]
Copy link
Contributor

Choose a reason for hiding this comment

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

change to something like:

NEGEnabledForIngress

v, ok := svc.v[NetworkEndpointGroupAlphaAnnotation]
return ok && v == "true"
}

// NEGEnabled is true if the service uses NEGs.
func (svc Service) NEGEnabled() bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

NEGExposed


var portMap ExposeNegAnnotation
if err := json.Unmarshal([]byte(v), &portMap); err != nil {
return nil, fmt.Errorf("NEG annotation %s is not well-formed", v)
Copy link
Contributor

Choose a reason for hiding this comment

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

Add a TODO or something to point to the documentation.

@@ -265,6 +294,30 @@ func (c *Controller) synced() bool {
c.ingressSynced()
}

type negSvcState struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here: use json tag

Copy link
Contributor

Choose a reason for hiding this comment

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

Use json tag here.

Copy link
Member

Choose a reason for hiding this comment

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

negServiceState

@@ -40,6 +41,11 @@ const (
// 3. Adding this annotation on ingress.
NetworkEndpointGroupAlphaAnnotation = "alpha.cloud.google.com/load-balancer-neg"
Copy link
Contributor

Choose a reason for hiding this comment

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

cloud.google.com/use-load-balancer-neg

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this was the original annotation for NEG + Ingress - is it ok to change it?

Copy link
Contributor

Choose a reason for hiding this comment

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

yes. it is okay

Copy link
Member

Choose a reason for hiding this comment

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

we should change to beta?

Copy link
Member

Choose a reason for hiding this comment

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

note that if we put beta, it will stay forever right now (new deprecation rules)

@bowei
Copy link
Member

bowei commented May 25, 2018

/assign

@agau4779 agau4779 force-pushed the expose-negs branch 2 times, most recently from 70f9758 to 6a2cd8d Compare May 29, 2018 16:24

// NEGAnnotation is the annotation key to specify standalone NEGs associated
// with the service. This should be a valid JSON string, for example:
// {"service_ports":{"80":{"enabled":true}}}
Copy link
Contributor

Choose a reason for hiding this comment

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

Let us do this:

{"service_ports":{"80":{}}}

@@ -57,6 +63,18 @@ const (
ProtocolHTTP2 AppProtocol = "HTTP2"
)

// ExposeNegAnnotation is the format of the annotation associated with the
// NEGAnnotation key.
type ExposeNegAnnotation struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

Make it empty for now. Leave a comment to say there will be future extensions in this struct

if err == nil {
svcPorts = svcPorts.Union(negSvcPorts)
} else {
glog.Warning("Failed to parse %v annotation on Service, err: %v. Ignoring the annotation.", annotations.NEGAnnotation, err)
Copy link
Contributor

Choose a reason for hiding this comment

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

use event recorder to record and error event to the service object

Copy link
Contributor

Choose a reason for hiding this comment

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

Also check if the service port actually exists. If not, record an event.

Add a TODO to say that will move the validation logic to validation webhook.

@@ -265,6 +294,30 @@ func (c *Controller) synced() bool {
c.ingressSynced()
}

type negSvcState struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

Use json tag here.

// ExposeNegAnnotation is the format of the annotation associated with the
// NEGAnnotation key. ServicePorts present in this map will be NEG-enabled.
type ExposeNegAnnotation struct {
SvcPorts map[string]NegAttributes `json:"service_ports,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we get rid of the service_ports key?

"cloud.google.com/expose-load-balancer-neg": "{"80":{}, "8080": {}}"

@agau4779 agau4779 force-pushed the expose-negs branch 2 times, most recently from 27998a4 to a4aa68a Compare May 31, 2018 22:51
NetworkEndpointGroupAlphaAnnotation = "cloud.google.com/use-load-balancer-neg"

// NEGAnnotation is the annotation key to specify standalone NEGs associated
// with the service. This should be a valid JSON string, for example:
Copy link
Member

Choose a reason for hiding this comment

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

can you put where the actual schema struct is defined?

func (svc Service) NEGEnabled() bool {
// NEGEnabledForIngress returns true if the annotation is to be applied on
// Ingress-referenced ports
func (svc Service) NEGEnabledForIngress() bool {
Copy link
Member

Choose a reason for hiding this comment

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

is using this as a value type on purpose? (svc *Service)

// NEGExposed is true if the service exposes NEGs
func (svc Service) NEGExposed() bool {
v, ok := svc.v[NEGAnnotation]
return ok && len(v) > 0
Copy link
Member

Choose a reason for hiding this comment

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

wouldn't len(v) be == 0 if it didn't exist?

return nil, fmt.Errorf("No NEG ServicePorts specified")
}

// TODO: add link to documentation
Copy link
Member

Choose a reason for hiding this comment

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

which doc?

// TODO: add link to documentation
var portMap ExposeNegAnnotation
if err := json.Unmarshal([]byte(v), &portMap); err != nil {
return nil, fmt.Errorf("NEG annotation %s is not well-formed", v)
Copy link
Member

Choose a reason for hiding this comment

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

...well-formed: %v", v, err

might as well report the error so people know how to fix

if annotations.FromService(service).NEGExposed() {
negSvcPorts, err := annotations.FromService(service).NEGServicePorts()
if err == nil {
knownPorts := sets.NewString()
Copy link
Member

Choose a reason for hiding this comment

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

This feels like it should be a helper function.

negSvcPorts, err := annotations.FromService(service).NEGServicePorts()
if err == nil {
knownPorts := sets.NewString()
for _, sp := range service.Spec.Ports {
Copy link
Member

Choose a reason for hiding this comment

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

This block that collects the service ports should be a helper function and unit tested


if len(svcPorts) > 0 {
annotation, err := c.negVisibilityAnnotation(namespace, name, svcPorts.List())
service.Annotations[negVisibilityAnnotationKey] = annotation
Copy link
Member

Choose a reason for hiding this comment

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

I would like this to be part of the annotations pkg to keep annotation related code together

@@ -265,6 +294,30 @@ func (c *Controller) synced() bool {
c.ingressSynced()
}

type negSvcState struct {
Copy link
Member

Choose a reason for hiding this comment

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

negServiceState

// associated with the given ports.
// NetworkEndpointGroups is a mapping between ServicePort and NEG name
// Zones is a list of zones where the NEGs exist.
func (c *Controller) negVisibilityAnnotation(namespace, name string, ports []string) (string, error) {
Copy link
Member

Choose a reason for hiding this comment

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

move the logic to annotations

@agau4779 agau4779 force-pushed the expose-negs branch 2 times, most recently from 73252dc to 85f09ef Compare June 1, 2018 22:24
@k8s-ci-robot k8s-ci-robot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Jun 19, 2018
Copy link
Contributor

@freehan freehan left a comment

Choose a reason for hiding this comment

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

rename the pkg/neg/annotation.go to pkg/neg/utils.go

NEG: true,
Http2: true,
NEG: true,
NEGExposed: true,
Copy link
Contributor

Choose a reason for hiding this comment

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

default to false?


// NEGStatusKey is the annotation key whose value is the status of the NEGs
// on the Service, and is applied by the NEG Controller.
NEGStatusKey = "cloud.google.com/neg"
Copy link
Contributor

Choose a reason for hiding this comment

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

cloud.google.com/neg-status

// with the service. This should be a valid JSON string, as defined in
// ExposeNegAnnotation.
// example: {"80":{},"443":{}}
ExposeNEGAnnotationKey = "cloud.google.com/expose-load-balancer-neg"
Copy link
Contributor

Choose a reason for hiding this comment

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

cloud.google.com/neg


// NegAttributes houses the attributes of the NEGs that are associated with the
// service. Future extensions to the Expose NEGs annotation should be added here.
type NegAttributes struct{}
Copy link
Contributor

Choose a reason for hiding this comment

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

Name string


// NegServiceState contains name and zone of the Network Endpoint Group
// resources associated with this service
type NegServiceState struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

rename to NegStatus

// associated with the given ports.
// NetworkEndpointGroups is a mapping between ServicePort and NEG name
// Zones is a list of zones where the NEGs exist.
func GenNegServiceState(zones []string, portToNegs PortNameMap) NegServiceState {
Copy link
Contributor

Choose a reason for hiding this comment

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

GetNegStatus

testCases := []struct {
desc string
previousPortMap PortNameMap
portMap PortNameMap
Copy link
Contributor

Choose a reason for hiding this comment

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

add a boolean speicify expect service update or not

let me find an example for you.

@agau4779 agau4779 force-pushed the expose-negs branch 3 times, most recently from 0a7c879 to 4bb2b9c Compare June 20, 2018 00:03
@freehan
Copy link
Contributor

freehan commented Jun 20, 2018

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jun 20, 2018
@freehan
Copy link
Contributor

freehan commented Jun 20, 2018

I0620 00:05:56.000] Checking go vet: FAIL
I0620 00:05:56.000] # k8s.io/ingress-gce/pkg/annotations
I0620 00:05:56.000] pkg/annotations/service.go:81: struct field tag `json:name,omitempty` not compatible with reflect.StructTag.Get: bad syntax for struct tag value
I0620 00:05:56.001] 
I0620 00:05:56.415] build/rules.mk:188: recipe for target 'test' failed
W0620 00:05:56.421] make: *** [test] Error 1

@k8s-ci-robot k8s-ci-robot removed the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jun 20, 2018
@freehan
Copy link
Contributor

freehan commented Jun 20, 2018

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jun 20, 2018
@freehan freehan merged commit 3722e74 into kubernetes:master Jun 20, 2018
@agau4779 agau4779 deleted the expose-negs branch June 20, 2018 17:51
k8s-github-robot pushed a commit to kubernetes/kubernetes that referenced this pull request Jun 23, 2018
Automatic merge from submit-queue (batch tested with PRs 65338, 64535). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

[GCE] e2e test for expose neg on gce ingress

**What this PR does / why we need it**:
- Adds e2e test for the expose NEG annotation (which allows for standalone NEGs)

**Special notes for your reviewer**:
Note, kubernetes/ingress-gce#350 must be merged first before this is merged.

`[Unreleased]` tag is on this PR because it depends on code from kubernetes/ingress-gce#350 and kubernetes/ingress-gce#284 being in an Ingress release. Will update this test and test-infra once this is released in the next Ingress.

**Release note**:
```release-note
NONE
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants