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

HTTPProxy: add healthCheck port config #4761

Merged
merged 16 commits into from
Oct 28, 2022
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions apis/projectcontour/v1/httpproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,13 @@ type Service struct {
// +kubebuilder:validation:ExclusiveMinimum=false
// +kubebuilder:validation:ExclusiveMaximum=true
Port int `json:"port"`
// HealthPort is the port for this service healthcheck.
// If not specified, Port is used for service healthchecks.
//
// +kubebuilder:validation:Minimum=1
// +kubebuilder:validation:Maximum=65535
// +optional
HealthPort int `json:"healthPort,omitempty"`
// Protocol may be used to specify (or override) the protocol used to reach this Service.
// Values may be tls, h2, h2c. If omitted, protocol-selection falls back on Service annotations.
// +kubebuilder:validation:Enum=h2;h2c;tls
Expand Down
6 changes: 6 additions & 0 deletions changelogs/unreleased/4761-yangyy93-minor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## Add optional health check port for HTTP health check and TCP health check

HTTPProxy.Route.Service and HTTPProxy.TCPProxy.Service now has an optional `HealthPort` field which specifies a health check port that is different from the routing port. If not specified, the service `Port` field is used for healthchecking.



12 changes: 12 additions & 0 deletions examples/contour/01-crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4653,6 +4653,12 @@ spec:
- name
type: object
type: array
healthPort:
description: HealthPort is the port for this service healthcheck.
If not specified, Port is used for service healthchecks.
maximum: 65535
minimum: 1
type: integer
mirror:
description: If Mirror is true the Service will receive
a read only mirror of the traffic for this route.
Expand Down Expand Up @@ -5034,6 +5040,12 @@ spec:
- name
type: object
type: array
healthPort:
description: HealthPort is the port for this service healthcheck.
If not specified, Port is used for service healthchecks.
maximum: 65535
minimum: 1
type: integer
mirror:
description: If Mirror is true the Service will receive
a read only mirror of the traffic for this route.
Expand Down
12 changes: 12 additions & 0 deletions examples/render/contour-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4862,6 +4862,12 @@ spec:
- name
type: object
type: array
healthPort:
description: HealthPort is the port for this service healthcheck.
If not specified, Port is used for service healthchecks.
maximum: 65535
minimum: 1
type: integer
mirror:
description: If Mirror is true the Service will receive
a read only mirror of the traffic for this route.
Expand Down Expand Up @@ -5243,6 +5249,12 @@ spec:
- name
type: object
type: array
healthPort:
description: HealthPort is the port for this service healthcheck.
If not specified, Port is used for service healthchecks.
maximum: 65535
minimum: 1
type: integer
mirror:
description: If Mirror is true the Service will receive
a read only mirror of the traffic for this route.
Expand Down
12 changes: 12 additions & 0 deletions examples/render/contour-gateway-provisioner.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4667,6 +4667,12 @@ spec:
- name
type: object
type: array
healthPort:
description: HealthPort is the port for this service healthcheck.
If not specified, Port is used for service healthchecks.
maximum: 65535
minimum: 1
type: integer
mirror:
description: If Mirror is true the Service will receive
a read only mirror of the traffic for this route.
Expand Down Expand Up @@ -5048,6 +5054,12 @@ spec:
- name
type: object
type: array
healthPort:
description: HealthPort is the port for this service healthcheck.
If not specified, Port is used for service healthchecks.
maximum: 65535
minimum: 1
type: integer
mirror:
description: If Mirror is true the Service will receive
a read only mirror of the traffic for this route.
Expand Down
12 changes: 12 additions & 0 deletions examples/render/contour-gateway.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4868,6 +4868,12 @@ spec:
- name
type: object
type: array
healthPort:
description: HealthPort is the port for this service healthcheck.
If not specified, Port is used for service healthchecks.
maximum: 65535
minimum: 1
type: integer
mirror:
description: If Mirror is true the Service will receive
a read only mirror of the traffic for this route.
Expand Down Expand Up @@ -5249,6 +5255,12 @@ spec:
- name
type: object
type: array
healthPort:
description: HealthPort is the port for this service healthcheck.
If not specified, Port is used for service healthchecks.
maximum: 65535
minimum: 1
type: integer
mirror:
description: If Mirror is true the Service will receive
a read only mirror of the traffic for this route.
Expand Down
12 changes: 12 additions & 0 deletions examples/render/contour.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4862,6 +4862,12 @@ spec:
- name
type: object
type: array
healthPort:
description: HealthPort is the port for this service healthcheck.
If not specified, Port is used for service healthchecks.
maximum: 65535
minimum: 1
type: integer
mirror:
description: If Mirror is true the Service will receive
a read only mirror of the traffic for this route.
Expand Down Expand Up @@ -5243,6 +5249,12 @@ spec:
- name
type: object
type: array
healthPort:
description: HealthPort is the port for this service healthcheck.
If not specified, Port is used for service healthchecks.
maximum: 65535
minimum: 1
type: integer
mirror:
description: If Mirror is true the Service will receive
a read only mirror of the traffic for this route.
Expand Down
11 changes: 10 additions & 1 deletion internal/dag/accessors.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,20 @@ import (
// EnsureService looks for a Kubernetes service in the cache matching the provided
// namespace, name and port, and returns a DAG service for it. If a matching service
// cannot be found in the cache, an error is returned.
func (d *DAG) EnsureService(meta types.NamespacedName, port intstr.IntOrString, cache *KubernetesCache, enableExternalNameSvc bool) (*Service, error) {
func (d *DAG) EnsureService(meta types.NamespacedName, port intstr.IntOrString, healthPort intstr.IntOrString, cache *KubernetesCache, enableExternalNameSvc bool) (*Service, error) {
svc, svcPort, err := cache.LookupService(meta, port)
if err != nil {
return nil, err
}

healthSvcPort := svcPort
if (healthPort.IntVal != 0 || healthPort.StrVal != "") && healthPort != port {
_, healthSvcPort, err = cache.LookupService(meta, healthPort)
if err != nil {
return nil, err
}
}

err = validateExternalName(svc, enableExternalNameSvc)
if err != nil {
return nil, err
Expand All @@ -50,6 +58,7 @@ func (d *DAG) EnsureService(meta types.NamespacedName, port intstr.IntOrString,
ServiceName: svc.Name,
ServiceNamespace: svc.Namespace,
ServicePort: svcPort,
HealthPort: healthSvcPort,
Weight: 1,
},
Protocol: upstreamProtocol(svc, svcPort),
Expand Down
47 changes: 45 additions & 2 deletions internal/dag/accessors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,29 @@ func TestBuilderLookupService(t *testing.T) {
},
}

s2 := &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "includehealth",
Namespace: "default",
},
Spec: v1.ServiceSpec{
Ports: []v1.ServicePort{
{
Name: "http",
Protocol: "TCP",
Port: 8080,
TargetPort: intstr.FromInt(8080),
},
{
Name: "heath",
sunjayBhatia marked this conversation as resolved.
Show resolved Hide resolved
Protocol: "TCP",
Port: 8998,
TargetPort: intstr.FromInt(8998),
},
},
},
}

externalNameValid := &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "externalnamevalid",
Expand Down Expand Up @@ -77,13 +100,15 @@ func TestBuilderLookupService(t *testing.T) {

services := map[types.NamespacedName]*v1.Service{
{Name: "service1", Namespace: "default"}: s1,
{Name: "servicehealthcheck", Namespace: "default"}: s2,
{Name: "externalnamevalid", Namespace: "default"}: externalNameValid,
{Name: "externalnamelocalhost", Namespace: "default"}: externalNameLocalhost,
}

tests := map[string]struct {
types.NamespacedName
port intstr.IntOrString
healthPort intstr.IntOrString
enableExternalNameSvc bool
want *Service
wantErr error
Expand Down Expand Up @@ -113,11 +138,23 @@ func TestBuilderLookupService(t *testing.T) {
port: intstr.FromString("8080"),
wantErr: errors.New(`service "default/nonexistent-service" not found`),
},
"when port does not exist an error is returned": {
"when service port does not exist an error is returned": {
NamespacedName: types.NamespacedName{Name: "service1", Namespace: "default"},
port: intstr.FromString("9999"),
wantErr: errors.New(`port "9999" on service "default/service1" not matched`),
},
"when health port and service port are different": {
NamespacedName: types.NamespacedName{Name: "servicehealthcheck", Namespace: "default"},
port: intstr.FromString("8080"),
healthPort: intstr.FromString("8998"),
want: healthService(s2),
},
"when health port does not exist an error is returned": {
NamespacedName: types.NamespacedName{Name: "servicehealthcheck", Namespace: "default"},
port: intstr.FromString("8080"),
healthPort: intstr.FromString("8999"),
wantErr: errors.New(`port "8999" on service "default/servicehealthcheck" not matched`),
},
"When ExternalName Services are not disabled no error is returned": {
NamespacedName: types.NamespacedName{Name: "externalnamevalid", Namespace: "default"},
port: intstr.FromString("80"),
Expand All @@ -132,6 +169,12 @@ func TestBuilderLookupService(t *testing.T) {
Port: 80,
TargetPort: intstr.FromInt(80),
},
HealthPort: v1.ServicePort{
Name: "http",
Protocol: "TCP",
Port: 80,
TargetPort: intstr.FromInt(80),
},
},
ExternalName: "external.projectcontour.io",
},
Expand Down Expand Up @@ -161,7 +204,7 @@ func TestBuilderLookupService(t *testing.T) {

var dag DAG

got, gotErr := dag.EnsureService(tc.NamespacedName, tc.port, &b.Source, tc.enableExternalNameSvc)
got, gotErr := dag.EnsureService(tc.NamespacedName, tc.port, tc.healthPort, &b.Source, tc.enableExternalNameSvc)
assert.Equal(t, tc.want, got)
assert.Equal(t, tc.wantErr, gotErr)
})
Expand Down
Loading