Skip to content

Commit 0ce3ce4

Browse files
authored
Merge pull request crossplane#5540 from Argannor/feat/configurable-ports
feat/configurable ports
2 parents 8a75274 + a3978ae commit 0ce3ce4

File tree

11 files changed

+334
-22
lines changed

11 files changed

+334
-22
lines changed

cluster/charts/crossplane/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ and their default values.
8585
| `imagePullSecrets` | The imagePullSecret names to add to the Crossplane ServiceAccount. | `[]` |
8686
| `leaderElection` | Enable [leader election](https://docs.crossplane.io/latest/concepts/pods/#leader-election) for the Crossplane pod. | `true` |
8787
| `metrics.enabled` | Enable Prometheus path, port and scrape annotations and expose port 8080 for both the Crossplane and RBAC Manager pods. | `false` |
88+
| `metrics.port` | The port the metrics server listens on. | `""` |
8889
| `nodeSelector` | Add `nodeSelectors` to the Crossplane pod deployment. | `{}` |
8990
| `packageCache.configMap` | The name of a ConfigMap to use as the package cache. Disables the default package cache `emptyDir` Volume. | `""` |
9091
| `packageCache.medium` | Set to `Memory` to hold the package cache in a RAM backed file system. Useful for Crossplane development. | `""` |
@@ -105,6 +106,7 @@ and their default values.
105106
| `rbacManager.skipAggregatedClusterRoles` | Don't install aggregated Crossplane ClusterRoles. | `false` |
106107
| `rbacManager.tolerations` | Add `tolerations` to the RBAC Manager pod deployment. | `[]` |
107108
| `rbacManager.topologySpreadConstraints` | Add `topologySpreadConstraints` to the RBAC Manager pod deployment. | `[]` |
109+
| `readiness.port` | The port the readyz server listens on. | `""` |
108110
| `registryCaBundleConfig.key` | The ConfigMap key containing a custom CA bundle to enable fetching packages from registries with unknown or untrusted certificates. | `""` |
109111
| `registryCaBundleConfig.name` | The ConfigMap name containing a custom CA bundle to enable fetching packages from registries with unknown or untrusted certificates. | `""` |
110112
| `replicas` | The number of Crossplane pod `replicas` to deploy. | `1` |
@@ -132,6 +134,7 @@ and their default values.
132134
| `tolerations` | Add `tolerations` to the Crossplane pod deployment. | `[]` |
133135
| `topologySpreadConstraints` | Add `topologySpreadConstraints` to the Crossplane pod deployment. | `[]` |
134136
| `webhooks.enabled` | Enable webhooks for Crossplane and installed Provider packages. | `true` |
137+
| `webhooks.port` | The port the webhook server listens on. | `""` |
135138

136139
### Command Line
137140

cluster/charts/crossplane/templates/deployment.yaml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,14 +141,14 @@ spec:
141141
port: readyz
142142
ports:
143143
- name: readyz
144-
containerPort: 8081
144+
containerPort: {{ .Values.readiness.port | default 8081 }}
145145
{{- if .Values.metrics.enabled }}
146146
- name: metrics
147-
containerPort: 8080
147+
containerPort: {{ .Values.metrics.port | default 8080 }}
148148
{{- end }}
149149
{{- if .Values.webhooks.enabled }}
150150
- name: webhooks
151-
containerPort: 9443
151+
containerPort: {{ .Values.webhooks.port | default 9443 }}
152152
{{- end }}
153153
{{- with .Values.securityContextCrossplane }}
154154
securityContext:
@@ -185,6 +185,18 @@ spec:
185185
- name: "WEBHOOK_ENABLED"
186186
value: "false"
187187
{{- end }}
188+
{{- if and .Values.webhooks.enabled .Values.webhooks.port }}
189+
- name: "WEBHOOK_PORT"
190+
value: "{{ .Values.webhooks.port }}"
191+
{{- end}}
192+
{{- if and .Values.metrics.enabled .Values.metrics.port }}
193+
- name: "METRICS_PORT"
194+
value: "{{ .Values.metrics.port }}"
195+
{{- end}}
196+
{{- if .Values.readiness.port }}
197+
- name: "HEALTH_PROBE_PORT"
198+
value: "{{ .Values.readiness.port }}"
199+
{{- end}}
188200
- name: "TLS_SERVER_SECRET_NAME"
189201
value: crossplane-tls-server
190202
- name: "TLS_SERVER_CERTS_DIR"

cluster/charts/crossplane/templates/service.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@ spec:
2121
ports:
2222
- protocol: TCP
2323
port: 9443
24-
targetPort: 9443
24+
targetPort: {{ .Values.webhooks.port | default 9443 }}
2525
{{- end }}

cluster/charts/crossplane/values.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ service:
8080
webhooks:
8181
# -- Enable webhooks for Crossplane and installed Provider packages.
8282
enabled: true
83+
# -- The port the webhook server listens on.
84+
port: ""
8385

8486
rbacManager:
8587
# -- Deploy the RBAC Manager pod and its required roles.
@@ -167,6 +169,12 @@ securityContextRBACManager:
167169
metrics:
168170
# -- Enable Prometheus path, port and scrape annotations and expose port 8080 for both the Crossplane and RBAC Manager pods.
169171
enabled: false
172+
# -- The port the metrics server listens on.
173+
port: ""
174+
175+
readiness:
176+
# -- The port the readyz server listens on.
177+
port: ""
170178

171179
# -- Add custom environmental variables to the Crossplane pod deployment.
172180
# Replaces any `.` in a variable name with `_`. For example, `SAMPLE.KEY=value1` becomes `SAMPLE_KEY=value1`.

cmd/crossplane/core/core.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838
"sigs.k8s.io/controller-runtime/pkg/cache"
3939
"sigs.k8s.io/controller-runtime/pkg/client"
4040
"sigs.k8s.io/controller-runtime/pkg/healthz"
41+
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
4142
"sigs.k8s.io/controller-runtime/pkg/webhook"
4243

4344
"github.com/crossplane/crossplane-runtime/pkg/certificates"
@@ -105,6 +106,10 @@ type startCommand struct {
105106
WebhookEnabled bool `default:"true" env:"WEBHOOK_ENABLED" help:"Enable webhook configuration."`
106107
AutomaticDependencyDowngradeEnabled bool `default:"false" env:"AUTOMATIC_DEPENDENCY_DOWNGRADE_ENABLED" help:"Enable automatic dependency version downgrades. This configuration requires the 'EnableDependencyVersionUpgrades' feature flag to be enabled."`
107108

109+
WebhookPort int `default:"9443" env:"WEBHOOK_PORT" help:"The port the webhook server listens on."`
110+
MetricsPort int `default:"8080" env:"METRICS_PORT" help:"The port the metrics server listens on."`
111+
HealthProbePort int `default:"8081" env:"HEALTH_PROBE_PORT" help:"The port the health probe endpoint listens on."`
112+
108113
TLSServerSecretName string `env:"TLS_SERVER_SECRET_NAME" help:"The name of the TLS Secret that will store Crossplane's server certificate."`
109114
TLSServerCertsDir string `env:"TLS_SERVER_CERTS_DIR" help:"The path of the folder which will store TLS server certificate of Crossplane."`
110115
TLSClientSecretName string `env:"TLS_CLIENT_SECRET_NAME" help:"The name of the TLS Secret that will be store Crossplane's client certificate."`
@@ -165,15 +170,21 @@ func (c *startCommand) Run(s *runtime.Scheme, log logging.Logger) error { //noli
165170
t.MinVersion = tls.VersionTLS13
166171
},
167172
},
173+
Port: c.WebhookPort,
168174
}),
169175
Client: client.Options{
170176
Cache: &client.CacheOptions{
171177
DisableFor: []client.Object{&corev1.Secret{}},
172178
Unstructured: false, // this is the default to not cache unstructured objects
173179
},
174180
},
181+
175182
EventBroadcaster: eb,
176183

184+
Metrics: metricsserver.Options{
185+
BindAddress: fmt.Sprintf(":%d", c.MetricsPort),
186+
},
187+
177188
// controller-runtime uses both ConfigMaps and Leases for leader
178189
// election by default. Leases expire after 15 seconds, with a
179190
// 10 second renewal deadline. We've observed leader loss due to
@@ -189,7 +200,7 @@ func (c *startCommand) Run(s *runtime.Scheme, log logging.Logger) error { //noli
189200
RenewDeadline: func() *time.Duration { d := 50 * time.Second; return &d }(),
190201

191202
PprofBindAddress: c.Profile,
192-
HealthProbeBindAddress: ":8081",
203+
HealthProbeBindAddress: fmt.Sprintf(":%d", c.HealthProbePort),
193204
})
194205
if err != nil {
195206
return errors.Wrap(err, "cannot create manager")

internal/controller/pkg/revision/runtime.go

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
corev1 "k8s.io/api/core/v1"
2323
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2424
"k8s.io/apimachinery/pkg/runtime"
25-
"k8s.io/apimachinery/pkg/util/intstr"
2625

2726
"github.com/crossplane/crossplane-runtime/pkg/meta"
2827

@@ -44,6 +43,7 @@ const (
4443

4544
// See https://github.com/grpc/grpc/blob/v1.58.0/doc/naming.md
4645
grpcPortName = "grpc"
46+
grpcPort = 9443
4747
servicePort = 9443
4848
serviceEndpointFmt = "dns:///%s.%s:%d"
4949

@@ -283,14 +283,7 @@ func (b *RuntimeManifestBuilder) Service(overrides ...ServiceOverride) *corev1.S
283283
// Overrides that we are opinionated about.
284284
ServiceWithNamespace(b.namespace),
285285
ServiceWithOwnerReferences([]metav1.OwnerReference{meta.AsController(meta.TypedReferenceTo(b.revision, b.revision.GetObjectKind().GroupVersionKind()))}),
286-
ServiceWithSelectors(b.podSelectors()),
287-
ServiceWithAdditionalPorts([]corev1.ServicePort{
288-
{
289-
Protocol: corev1.ProtocolTCP,
290-
Port: servicePort,
291-
TargetPort: intstr.FromInt32(servicePort),
292-
},
293-
}))
286+
ServiceWithSelectors(b.podSelectors()))
294287

295288
// We append the overrides passed to the function last so that they can
296289
// override the above ones.

internal/controller/pkg/revision/runtime_function.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
corev1 "k8s.io/api/core/v1"
2626
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2727
"k8s.io/apimachinery/pkg/runtime"
28+
"k8s.io/apimachinery/pkg/util/intstr"
2829
"sigs.k8s.io/controller-runtime/pkg/client"
2930

3031
"github.com/crossplane/crossplane-runtime/pkg/errors"
@@ -94,7 +95,8 @@ func (h *FunctionHooks) Pre(ctx context.Context, _ runtime.Object, pr v1.Package
9495
if !ok {
9596
return errors.Errorf("cannot apply function package hooks to %T", pr)
9697
}
97-
fRev.Status.Endpoint = fmt.Sprintf(serviceEndpointFmt, svc.Name, svc.Namespace, servicePort)
98+
99+
fRev.Status.Endpoint = fmt.Sprintf(serviceEndpointFmt, svc.Name, svc.Namespace, grpcPort)
98100

99101
secServer := build.TLSServerSecret()
100102
if err := h.client.Apply(ctx, secServer); err != nil {
@@ -183,7 +185,7 @@ func functionDeploymentOverrides(image string) []DeploymentOverride {
183185
DeploymentRuntimeWithAdditionalPorts([]corev1.ContainerPort{
184186
{
185187
Name: grpcPortName,
186-
ContainerPort: servicePort,
188+
ContainerPort: grpcPort,
187189
},
188190
}),
189191
}
@@ -199,6 +201,14 @@ func functionServiceOverrides() []ServiceOverride {
199201
// FunctionComposer) can load balance across the endpoints.
200202
// https://kubernetes.io/docs/concepts/services-networking/service/#headless-services
201203
ServiceWithClusterIP(corev1.ClusterIPNone),
204+
ServiceWithAdditionalPorts([]corev1.ServicePort{
205+
{
206+
Name: grpcPortName,
207+
Protocol: corev1.ProtocolTCP,
208+
Port: grpcPort,
209+
TargetPort: intstr.FromString(grpcPortName),
210+
},
211+
}),
202212
}
203213
}
204214

internal/controller/pkg/revision/runtime_override_options.go

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ limitations under the License.
1717
package revision
1818

1919
import (
20+
"strconv"
21+
2022
appsv1 "k8s.io/api/apps/v1"
2123
corev1 "k8s.io/api/core/v1"
2224
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -99,9 +101,16 @@ func DeploymentWithOptionalPodScrapeAnnotations() DeploymentOverride {
99101
if d.Spec.Template.Annotations == nil {
100102
d.Spec.Template.Annotations = map[string]string{}
101103
}
104+
metricsPort := strconv.Itoa(metricsPortNumber)
105+
for _, port := range d.Spec.Template.Spec.Containers[0].Ports {
106+
if port.Name == metricsPortName {
107+
metricsPort = strconv.Itoa(int(port.ContainerPort))
108+
break
109+
}
110+
}
102111
if _, ok := d.Spec.Template.Annotations["prometheus.io/scrape"]; !ok {
103112
d.Spec.Template.Annotations["prometheus.io/scrape"] = "true"
104-
d.Spec.Template.Annotations["prometheus.io/port"] = "8080"
113+
d.Spec.Template.Annotations["prometheus.io/port"] = metricsPort
105114
d.Spec.Template.Annotations["prometheus.io/path"] = "/metrics"
106115
}
107116
}
@@ -223,10 +232,19 @@ func DeploymentRuntimeWithAdditionalEnvironments(env []corev1.EnvVar) Deployment
223232
}
224233

225234
// DeploymentRuntimeWithAdditionalPorts adds additional ports to the runtime
226-
// container of a Deployment.
235+
// container of a Deployment. A port will be added only if a port of the same name doesn't already exist.
227236
func DeploymentRuntimeWithAdditionalPorts(ports []corev1.ContainerPort) DeploymentOverride {
228237
return func(d *appsv1.Deployment) {
229-
d.Spec.Template.Spec.Containers[0].Ports = append(d.Spec.Template.Spec.Containers[0].Ports, ports...)
238+
names := make(map[string]bool)
239+
for _, p := range d.Spec.Template.Spec.Containers[0].Ports {
240+
names[p.Name] = true
241+
}
242+
for _, p := range ports {
243+
if _, ok := names[p.Name]; ok {
244+
continue
245+
}
246+
d.Spec.Template.Spec.Containers[0].Ports = append(d.Spec.Template.Spec.Containers[0].Ports, p)
247+
}
230248
}
231249
}
232250

@@ -401,10 +419,19 @@ func ServiceWithSelectors(selectors map[string]string) ServiceOverride {
401419
}
402420
}
403421

404-
// ServiceWithAdditionalPorts adds additional ports to a Service.
422+
// ServiceWithAdditionalPorts adds additional ports to a Service if no port with the same name was found.
405423
func ServiceWithAdditionalPorts(ports []corev1.ServicePort) ServiceOverride {
406424
return func(s *corev1.Service) {
407-
s.Spec.Ports = append(s.Spec.Ports, ports...)
425+
names := make(map[string]bool)
426+
for _, p := range s.Spec.Ports {
427+
names[p.Name] = true
428+
}
429+
for _, p := range ports {
430+
if _, ok := names[p.Name]; ok {
431+
continue
432+
}
433+
s.Spec.Ports = append(s.Spec.Ports, p)
434+
}
408435
}
409436
}
410437

internal/controller/pkg/revision/runtime_override_options_test.go

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,3 +211,108 @@ func TestDeploymentWithRuntimeContainer(t *testing.T) {
211211
})
212212
}
213213
}
214+
215+
func TestDeploymentRuntimeWithAdditionalPorts(t *testing.T) {
216+
type args struct {
217+
deployment *appsv1.Deployment
218+
ports []corev1.ContainerPort
219+
}
220+
type want struct {
221+
deployment *appsv1.Deployment
222+
}
223+
224+
cases := map[string]struct {
225+
reason string
226+
args args
227+
want want
228+
}{
229+
"NoPorts": {
230+
reason: "Should add the given ports if no ports are set",
231+
args: args{
232+
deployment: &appsv1.Deployment{
233+
Spec: appsv1.DeploymentSpec{
234+
Template: corev1.PodTemplateSpec{
235+
Spec: corev1.PodSpec{
236+
Containers: []corev1.Container{
237+
{},
238+
},
239+
},
240+
},
241+
},
242+
},
243+
ports: []corev1.ContainerPort{
244+
{ContainerPort: 80, Name: "http"},
245+
{ContainerPort: 443, Name: "https"},
246+
},
247+
},
248+
want: want{
249+
deployment: &appsv1.Deployment{
250+
Spec: appsv1.DeploymentSpec{
251+
Template: corev1.PodTemplateSpec{
252+
Spec: corev1.PodSpec{
253+
Containers: []corev1.Container{
254+
{
255+
Ports: []corev1.ContainerPort{
256+
{ContainerPort: 80, Name: "http"},
257+
{ContainerPort: 443, Name: "https"},
258+
},
259+
},
260+
},
261+
},
262+
},
263+
},
264+
},
265+
},
266+
},
267+
"DontOverridePorts": {
268+
reason: "Should add only new ports and not override existing ports",
269+
args: args{
270+
deployment: &appsv1.Deployment{
271+
Spec: appsv1.DeploymentSpec{
272+
Template: corev1.PodTemplateSpec{
273+
Spec: corev1.PodSpec{
274+
Containers: []corev1.Container{
275+
{
276+
Ports: []corev1.ContainerPort{
277+
{ContainerPort: 8080, Name: "http"},
278+
},
279+
},
280+
},
281+
},
282+
},
283+
},
284+
},
285+
ports: []corev1.ContainerPort{
286+
{ContainerPort: 80, Name: "http"},
287+
{ContainerPort: 443, Name: "https"},
288+
},
289+
},
290+
want: want{
291+
deployment: &appsv1.Deployment{
292+
Spec: appsv1.DeploymentSpec{
293+
Template: corev1.PodTemplateSpec{
294+
Spec: corev1.PodSpec{
295+
Containers: []corev1.Container{
296+
{
297+
Ports: []corev1.ContainerPort{
298+
{ContainerPort: 8080, Name: "http"},
299+
{ContainerPort: 443, Name: "https"},
300+
},
301+
},
302+
},
303+
},
304+
},
305+
},
306+
},
307+
},
308+
},
309+
}
310+
for name, tc := range cases {
311+
t.Run(name, func(t *testing.T) {
312+
DeploymentRuntimeWithAdditionalPorts(tc.args.ports)(tc.args.deployment)
313+
if diff := cmp.Diff(tc.want.deployment, tc.args.deployment); diff != "" {
314+
t.Errorf("\n%s\nDeploymentRuntimeWithAdditionalPorts(...): -want, +got:\n%s", tc.reason, diff)
315+
}
316+
})
317+
}
318+
}

0 commit comments

Comments
 (0)