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

Helm chart support for webhook sidecar #3966

Closed
wants to merge 2 commits into from

Conversation

johngmyers
Copy link
Contributor

Description

Adds support to the Helm chart for running a webhook provider as a sidecar

Checklist

  • Unit tests updated
  • End user documentation updated

@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. labels Sep 30, 2023
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please ask for approval from johngmyers. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@johngmyers
Copy link
Contributor Author

/cc @Raffo

@k8s-ci-robot k8s-ci-robot requested a review from Raffo September 30, 2023 22:54
@johngmyers johngmyers force-pushed the webhook-chart branch 3 times, most recently from 427869c to 51e3b34 Compare October 1, 2023 18:03
securityContext:
{{- toYaml . | nindent 12 }}
{{- end }}
image: {{ .Values.webhook.image . }}

This comment was marked as resolved.

{{- toYaml .Values.webhook.livenessProbe | nindent 12 }}
readinessProbe:
{{- toYaml .Values.webhook.readinessProbe | nindent 12 }}
{{- if or .Values.webhook.secretConfiguration.enabled .Values.webhook.extraVolumeMounts }}
Copy link
Contributor

Choose a reason for hiding this comment

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

.Values.webhook.secretConfiguration.enabled is not in the values.yaml

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to use mountPath instead of enabled, to match the external-dns container and the condition two lines below.

This does mean that setting either mountPath without also setting enabled will result in mounting a nonexistent volume. We could make the condition for the volume definition be an or of the two mountPath, leaving enabled to just control creating the Secret.

{{- toYaml . | nindent 12 }}
{{- end }}
{{- end }}
{{- if or .Values.secretConfiguration.enabled .Values.webhook.secretConfiguration.enabled .Values.extraVolumes }}
volumes:
{{- if .Values.secretConfiguration.enabled }}
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
{{- if .Values.secretConfiguration.enabled }}
{{- if or .Values.secretConfiguration.enabled .Values.webhook.secretConfiguration.enabled }}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had decided against having a .Values.webhook.secretConfiguration.enabled. The .Values.secretConfiguration.enabled setting defines the creation of the Secret, whereas each of the containers has its own mountPath setting. It is most likely that any secret will only be needed by the webhook (to authenticate to the provider's API).

@mloiseleur
Copy link
Contributor

@johngmyers With my 3 suggested changes and this values files:

webhook:
  image: "myhook:v1.2"
  args: ["-c","-v"]
  env:
    - name: TEST
      value: "TESTVAL"
  extraVolumeMounts: []
  resources:
    requests:
      cpu: 10m
      memory: 50Mi

  secretConfiguration:
    enabled: true
    mountPath: "/etc/mysecret"

It produced the expected output, with secret mounted on sidecar and not on main container.

Copy link
Contributor

@stevehipwell stevehipwell left a comment

Choose a reason for hiding this comment

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

I think this PR works in general but I don't think using .Values.webhook.image as the flag to enable this behaviour is a good API. Initially I was thinking that there should be .Values.webhook.enabled but this still leave the behaviour of .Values.provider as ambiguous.

I think that this PR should use eq .Values.provider "webhook" as the flag for this behaviour as it's consistent with the current API.

@johngmyers
Copy link
Contributor Author

@stevehipwell to enable the webhook provider you need to provide an image and there's no purpose to providing an image except to enable the webhook provider. So providing an image is equivalent to enabling the webhook provider.

So a .Values.webhook.enabled would be extraneous, serving no purpose other than to allow users to misconfigure the chart. Similarly, using eq .Values.provider "webhook" serves no purpose other than to allow users to misconfigure the chart.

@mloiseleur
Copy link
Contributor

@johngmyers I agree with @stevehipwell. The code would be more clear and consistent using eq .Values.provider "webhook".

For misconfiguration, it's possible to use fail when user has set webhook provider without a webhook image. See for instance how it's done on this HPA template when it's been enabled without the required maxReplicas.

As an alternative, there is also the required function.

@johngmyers
Copy link
Contributor Author

Keying off of eq .Values.provider "webhook" allows for the error where the user sets the webhook image but doesn't set provider: "webhook". In that case they will unexpectedly get the aws provider despite their stated intention to use a webhook image.

Keying off of eq .Values.provider "webhook" requires the user to configure two settings in order to enable a webhook image, whereas keying off of .Values.webhook.image only requires them to configure one. Keying off of .Values.provider confers disadvantage to the user without any compensating advantage.

@johngmyers johngmyers changed the title WIP Helm chart support for webhook sidecar Helm chart support for webhook sidecar Oct 4, 2023
@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 Oct 4, 2023
@mloiseleur
Copy link
Contributor

mloiseleur commented Oct 5, 2023

Following the use of webhook.secretConfiguration.mountPath, with this values:

secretConfiguration:
  data:
    credentials: |
      [default]
      my_secret_access = $MY_SECRET_KEY

webhook:
  image: "myhook:v1.2"
  args: ["-c","-v"]
  env:
    - name: TEST
      value: "TRUC"
  resources:
    requests:
      cpu: 10m
      memory: 50Mi

  secretConfiguration:
    mountPath: "/etc/mysecret"

Generated yaml is missing the annotation checksum/secret on Deployment, allowing to rollout when the secret content is updated.

@johngmyers
Copy link
Contributor Author

If secretConfiguration.enabled isn't true, then the chart doesn't render a Secret and secretConfiguration.data isn't referenced. In that case, the Secret would have to be deployed external to the chart and the chart wouldn't have a way to generate a useful checksum.

I do think it would be useful for the chart to support SecretProviderClass, but that's a separate PR.

@mloiseleur
Copy link
Contributor

Yes, that's the issue. And even if the user provides it externally, it won't be smooth : one will have to restart manually the pod each time the secret is updated.

With the current state of the PR, Secret (really) works:

  • on external-dns when secretConfiguration.enabled, secretConfiguration.data, secretConfiguration.mountPath are set
  • on webhook when secretConfiguration.enabled, secretConfiguration.data and webhook.secretConfiguration.mountPath are set.

Following this idea to enable it with mountPath, wdyt about also remove secretConfiguration.enabled and enforce with fail or required that user should set both secretConfiguration.data and ( secretConfiguration.mountPath or webhook.secretConfiguration.mountPath) ?

@stevehipwell
Copy link
Contributor

@johngmyers the primary behaviour for this chart is controlled by .Values.provider so having the provider be modified by a different value is not a consistent API. If you want to configure a webhook you need to set provider to webhook; if you haven't set an image this will fail and that's fine and a consistent API as there are other providers which need additional inputs.

@johngmyers
Copy link
Contributor Author

johngmyers commented Oct 12, 2023

@mloiseleur I agree that there's no benefit to having secretConfiguration.enabled. I'm unsure as to whether that should be part of this PR or whether it's out of scope and thus for a separate PR.

A theoretical feature to support SecretesProviderClass wouldn't be able to update an annotation either. A provider could be written to poll the contents of the mounted secret. I don't think it's necessary to ban configurations that aren't able to automatically rolling-update the deployment if the secret changes.

@johngmyers
Copy link
Contributor Author

We do not have agreement with this. I strongly disagree with @stevehipwell 's stance on this. The stance is not even logical: the entire point of the webhook provider is to change how providers are specifed, so how built-in providers used to be specified is not relevant to how external providers should be specified.

Users configuring an external provider should not be surprised by external-dns using the AWS provider because they failed to specify something that the chart could easily have figured out itself.

@stevehipwell
Copy link
Contributor

@Raffo there is no consensus between @johngmyers and myself. I stand by my review and am very much opposed to breaking the existing chart API; I can't see any benefit while I can see a significant number of downsides. I'm happy to provide a PR to add webhook support within the existing chart API; we can support single container, sidecar and external service patterns.

@johngmyers
Copy link
Contributor Author

This change does not break the existing chart API. All preexisting use cases continue to work with no change to config.

From a user experience perspective, this change has all benefit and no downside. There is no reason or benefit for a user of a sidecar provider to configure the provider setting. A user specifying webhook.image would not want to run the AWS route53 (or any other built-in provider) and doing so would be punishing them for no good reason.

The argument against this change is nonsensical. That it changes a previous configuration model that did not allow for the feature being added is unavoidable.

@k8s-ci-robot k8s-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Nov 7, 2023
@Raffo Raffo mentioned this pull request Nov 8, 2023
@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Nov 10, 2023
@florianmutter
Copy link

I think it would be confusing and inconsistent if the chart works different to what is described here: https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/webhook-provider.md. The documentation says there is a new provider webhook and it says you should use --provider=webhook and I think it should be the same for the chart.

@k8s-ci-robot k8s-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Nov 14, 2023
@johngmyers johngmyers force-pushed the webhook-chart branch 3 times, most recently from dac9319 to 90b69ea Compare November 14, 2023 06:18
@johngmyers
Copy link
Contributor Author

Moved all the settings under provider and used @mloiseleur's template to provide backwards compatibility to existing string provider values.

Comment on lines +156 to +159
ports:
- name: provider-metrics
protocol: TCP
containerPort: 8080
Copy link
Contributor

@mloiseleur mloiseleur Nov 14, 2023

Choose a reason for hiding this comment

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

Is this port expected on all webhook providers ?
FTM, I have seen they are using one port (8888) by default, to serve provider methods and probes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is my proposal. We'll want them to have a separate port for metrics because security depends on the provider methods not being accessible outside of the pod. I don't see any benefit in letting webhook providers choose different metrics ports.

@stevehipwell
Copy link
Contributor

@johngmyers @mloiseleur what is the situation with this PR and #4032?

@johngmyers
Copy link
Contributor Author

The situation between this and #4032 is that we have not yet converged.

@@ -22,32 +22,34 @@ spec:
matchLabels:
{{- include "external-dns.selectorLabels" . | nindent 6 }}
endpoints:
- port: http
{{- range (list "http" "provider-metrics" }}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I need to make the "provider-metrics" part of this conditional on there being a provider sidecar.

@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Dec 7, 2023
@k8s-ci-robot
Copy link
Contributor

PR needs rebase.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@k8s-ci-robot
Copy link
Contributor

@johngmyers: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
pull-external-dns-licensecheck d179660 link true /test pull-external-dns-licensecheck

Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

@mloiseleur
Copy link
Contributor

Since #4032 and #4085 are merged, I close this PR.
Feel free to reopen one if we missed something.
/close

@k8s-ci-robot
Copy link
Contributor

@mloiseleur: Closed this PR.

In response to this:

Since #4032 and #4085 are merged, I close this PR.
Feel free to reopen one if we missed something.
/close

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

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. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants