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: Add serviceAccounts, rbac, and small fixes #13747

2 changes: 1 addition & 1 deletion helm/druid/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ dependencies:
version: 8.6.4
repository: https://charts.helm.sh/stable
condition: postgresql.enabled
version: 0.3.4
version: 0.3.5
home: https://druid.apache.org/
icon: https://druid.apache.org/img/favicon.png
sources:
Expand Down
31 changes: 31 additions & 0 deletions helm/druid/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,16 @@ The following table lists the configurable parameters of the Druid chart and the
| `configVars` | druid configuration variables for all components | `` |
| `gCloudStorage.enabled` | look for secret to set google cloud credentials | `false` |
| `gCloudStorage.secretName` | secretName to be mounted as google cloud credentials | `false` |
| `rbac.create` | Create roles and roleBindings for service Accounts | `true` |
| `broker.enabled` | enable broker | `true` |
| `broker.name` | broker component name | `broker` |
| `broker.replicaCount` | broker node replicas (deployment) | `1` |
| `broker.port` | port of broker component | `8082` |
| `broker.serviceAccount.create` | Create a service account for broker service | `true` |
| `broker.serviceAccount.name` | Service account name | Derived from the name of service |
| `broker.serviceAccount.annotations` | Annotations applied to created service account | `{}` |
| `broker.serviceAccount.labels` | Labels applied to created service account | `{}` |
| `broker.serviceAccount.automountServiceAccountToken` | Automount API credentials for the Service Account | `true` |
| `broker.serviceType` | service type for service | `ClusterIP` |
| `broker.resources` | broker node resources requests & limits | `{}` |
| `broker.podAnnotations` | broker deployment annotations | `{}` |
Expand All @@ -117,6 +123,11 @@ The following table lists the configurable parameters of the Druid chart and the
| `coordinator.replicaCount` | coordinator node replicas (deployment) | `1` |
| `coordinator.port` | port of coordinator component | `8081` |
| `coordinator.serviceType` | service type for service | `ClusterIP` |
| `coordinator.serviceAccount.create` | Create a service account for coordinator service | `true` |
| `coordinator.serviceAccount.name` | Service account name | Derived from the name of service |
| `coordinator.serviceAccount.annotations` | Annotations applied to created service account | `{}` |
| `coordinator.serviceAccount.labels` | Labels applied to created service account | `{}` |
| `coordinator.serviceAccount.automountServiceAccountToken` | Automount API credentials for the Service Account | `true` |
| `coordinator.resources` | coordinator node resources requests & limits | `{}` |
| `coordinator.podAnnotations` | coordinator Deployment annotations | `{}` |
| `coordinator.nodeSelector` | node labels for coordinator pod assignment | `{}` |
Expand All @@ -133,6 +144,11 @@ The following table lists the configurable parameters of the Druid chart and the
| `overlord.replicaCount` | overlord node replicas (deployment) | `1` |
| `overlord.port` | port of overlord component | `8081` |
| `overlord.serviceType` | service type for service | `ClusterIP` |
| `overlord.serviceAccount.create` | Create a service account for overlord service | `true` |
| `overlord.serviceAccount.name` | Service account name | Derived from the name of service |
| `overlord.serviceAccount.annotations` | Annotations applied to created service account | `{}` |
| `overlord.serviceAccount.labels` | Labels applied to created service account | `{}` |
| `overlord.serviceAccount.automountServiceAccountToken` | Automount API credentials for the Service Account | `true` |
| `overlord.resources` | overlord node resources requests & limits | `{}` |
| `overlord.podAnnotations` | overlord Deployment annotations | `{}` |
| `overlord.nodeSelector` | node labels for overlord pod assignment | `{}` |
Expand All @@ -149,6 +165,11 @@ The following table lists the configurable parameters of the Druid chart and the
| `historical.replicaCount` | historical node replicas (statefulset) | `1` |
| `historical.port` | port of historical component | `8083` |
| `historical.serviceType` | service type for service | `ClusterIP` |
| `historical.serviceAccount.create` | Create a service account for historical service | `true` |
| `historical.serviceAccount.name` | Service account name | Derived from the name of service |
| `historical.serviceAccount.annotations` | Annotations applied to created service account | `{}` |
| `historical.serviceAccount.labels` | Labels applied to created service account | `{}` |
| `historical.serviceAccount.automountServiceAccountToken` | Automount API credentials for the Service Account | `true` |
| `historical.resources` | historical node resources requests & limits | `{}` |
| `historical.livenessProbeInitialDelaySeconds` | historical node liveness probe initial delay in seconds | `60` |
| `historical.readinessProbeInitialDelaySeconds` | historical node readiness probe initial delay in seconds | `60` |
Expand All @@ -173,6 +194,11 @@ The following table lists the configurable parameters of the Druid chart and the
| `middleManager.replicaCount` | middleManager node replicas (statefulset) | `1` |
| `middleManager.port` | port of middleManager component | `8091` |
| `middleManager.serviceType` | service type for service | `ClusterIP` |
| `middleManager.serviceAccount.create` | Create a service account for middleManager service | `true` |
| `middleManager.serviceAccount.name` | Service account name | `` |
| `middleManager.serviceAccount.annotations` | Annotations applied to created service account | `{}` |
| `middleManager.serviceAccount.labels` | Labels applied to created service account | `{}` |
| `middleManager.serviceAccount.automountServiceAccountToken` | Automount API credentials for the Service Account | `true` |
| `middleManager.resources` | middleManager node resources requests & limits | `{}` |
| `middleManager.podAnnotations` | middleManager Deployment annotations | `{}` |
| `middleManager.nodeSelector` | Node labels for middleManager pod assignment | `{}` |
Expand All @@ -199,6 +225,11 @@ The following table lists the configurable parameters of the Druid chart and the
| `router.replicaCount` | router node replicas (deployment) | `1` |
| `router.port` | port of router component | `8888` |
| `router.serviceType` | service type for service | `ClusterIP` |
| `router.serviceAccount.create` | Create a service account for router service | `true` |
| `router.serviceAccount.name` | Service account name | Derived from the name of service |
| `router.serviceAccount.annotations` | Annotations applied to created service account | `{}` |
| `router.serviceAccount.labels` | Labels applied to created service account | `{}` |
| `router.serviceAccount.automountServiceAccountToken` | Automount API credentials for the Service Account | `true` |
| `router.resources` | router node resources requests & limits | `{}` |
| `router.podAnnotations` | router Deployment annotations | `{}` |
| `router.nodeSelector` | node labels for router pod assignment | `{}` |
Expand Down
66 changes: 66 additions & 0 deletions helm/druid/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,69 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this
{{- define "druid.router.fullname" -}}
{{ template "druid.fullname" . }}-{{ .Values.router.name }}
{{- end -}}

{{/*
Create the name of the broker service account
*/}}
{{- define "druid.broker.serviceAccountName" -}}
{{- if .Values.broker.serviceAccount.create }}
{{- default (include "druid.broker.fullname" .) .Values.broker.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.broker.serviceAccount.name }}
{{- end }}
{{- end }}

{{/*
Create the name of the historical service account
*/}}
{{- define "druid.historical.serviceAccountName" -}}
{{- if .Values.historical.serviceAccount.create }}
{{- default (include "druid.historical.fullname" .) .Values.historical.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.historical.serviceAccount.name }}
{{- end }}
{{- end }}

{{/*
Create the name of the middleManager service account
*/}}
{{- define "druid.middleManager.serviceAccountName" -}}
{{- if .Values.middleManager.serviceAccount.create }}
{{- default (include "druid.middleManager.fullname" .) .Values.middleManager.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.middleManager.serviceAccount.name }}
{{- end }}
{{- end }}

{{/*
Create the name of the coordinator service account
*/}}
{{- define "druid.coordinator.serviceAccountName" -}}
{{- if .Values.coordinator.serviceAccount.create }}
{{- default (include "druid.coordinator.fullname" .) .Values.coordinator.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.coordinator.serviceAccount.name }}
{{- end }}
{{- end }}

{{/*
Create the name of the overlord service account
*/}}
{{- define "druid.overlord.serviceAccountName" -}}
{{- if .Values.overlord.serviceAccount.create }}
{{- default (include "druid.overlord.fullname" .) .Values.overlord.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.overlord.serviceAccount.name }}
{{- end }}
{{- end }}

{{/*
Create the name of the router service account
*/}}
{{- define "druid.router.serviceAccountName" -}}
{{- if .Values.router.serviceAccount.create }}
{{- default (include "druid.router.fullname" .) .Values.router.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.router.serviceAccount.name }}
{{- end }}
{{- end }}
20 changes: 12 additions & 8 deletions helm/druid/templates/broker/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,19 @@ spec:
release: {{ .Release.Name }}
component: {{ .Values.broker.name }}
annotations:
{{- with .Values.broker.podAnnotations }}
{{ toYaml . | indent 8 }}
{{- end }}
{{- if .Values.prometheus.enabled }}
{{- with .Values.prometheus.annotation }}
{{ toYaml . | indent 8 }}
{{- end }}
{{- end }}
druid.k8s.enablePatching: "true"
{{- with .Values.broker.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- if .Values.prometheus.enabled }}
{{- with .Values.prometheus.annotation }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}
spec:
{{- if .Values.broker.serviceAccount.create }}
Copy link
Contributor

Choose a reason for hiding this comment

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

This blocks external creation of the serviceAccount. Most other charts allow you to bring your own serviceAccount which may also make reusing the same one for all druid service types easier.

I am wondering if we should default serviceAccount.name to unset and if create is true it uses what the default would be. Then if serviceAccount.name is set and serviceAccount.create is false we can still set the value here.

The charts I am used to using have a template like:

{{/*
Create the name of the forwarder service account to use
*/}}
{{- define "fluentd.forwarder.serviceAccountName" -}}
{{- if .Values.forwarder.serviceAccount.create -}}
    {{ default (printf "%s-forwarder" (include "common.names.fullname" .)) .Values.forwarder.serviceAccount.name }}
{{- else -}}
    {{ default "default" .Values.forwarder.serviceAccount.name }}
{{- end -}}
{{- end -}}

and then always set the serviceAccountName with the output of the template.

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 see what you're saying. I have a bit of an opposite experience from you in terms of what other public widely used charts offer which is why I went this way but I'm not married to it. I can create a helper definition which does the above sort of style.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

serviceAccountName: {{ include "druid.broker.serviceAccountName" . }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
Expand Down
40 changes: 40 additions & 0 deletions helm/druid/templates/broker/role.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{{/*

Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/}}

{{- if and (.Values.rbac.create) (.Values.broker.enabled) }}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ template "druid.broker.fullname" . }}
labels:
app: {{ include "druid.name" . }}
chart: {{ include "druid.chart" . }}
component: {{ .Values.broker.name }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
rules:
- apiGroups:
- ""
resources:
- pods
- configmaps
verbs:
- '*'
Comment on lines +32 to +38
Copy link
Contributor

Choose a reason for hiding this comment

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

Unclear on why the broker needs access to delete Pods, or really any of these. Are these permissions only needed by the Overlord?

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 found that when this role did not exist none of the pods could start. They seem to all manage labels when using the kubernetes extension. Unclear if they will remove when not needed the same as they add when needed. I can test that and narrow down permission sets for each service.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

An update:

  • Just an FYI that this is the role settings recommended in the official druid documentation for these extensions.
  • Attempting to convert my dev cluster over to this version of the helm chart has been met with some very frustrating complications. For some reason, which as far as I can tell has nothing to do with service accounts, I am not getting the
    2023-02-09T21:56:09,734 INFO [k8s-task-runner-3] org.apache.druid.indexing.overlord.TaskQueue - Received SUCCESS status for task: <some_task> response after a job when running with a cluster deployed via this version of the helm chart.
  • This means a task of {"type":"noop"} is spawning a k8s job, executing successfully, the job has a zero return code and completes successfully, but the job status is reported as FAILED in the UI.
  • The logs for that, in debug mode, look like this:
2023-02-09T21:55:51,559 DEBUG [k8s-task-runner-25] org.apache.http.wire - http-outgoing-22 >> "2023-02-09T21:39:13,653 DEBUG [task-runner-0-priority-0] org.apache.druid.indexing.common.actions.RemoteTaskActionClient - Performing action for task[noop_2023-02-09T21:39:02.008Z_936917b3-a0af-4656-a1e1-9e77ced24d92]: UpdateStatusAction{status=successful}[\n]"
2023-02-09T21:55:51,560 DEBUG [k8s-task-runner-25] org.apache.http.wire - http-outgoing-22 >> "2023-02-09T21:39:13,663 DEBUG [task-runner-0-priority-0] org.apache.druid.indexing.common.actions.RemoteTaskActionClient - Performing action for task[noop_2023-02-09T21:39:02.008Z_936917b3-a0af-4656-a1e1-9e77ced24d92]: UpdateLocationAction{taskLocation=TaskLocation{host='null', port=-1, tlsPort=-1}}[\n]"
2023-02-09T21:55:51,560 DEBUG [k8s-task-runner-25] org.apache.http.wire - http-outgoing-22 >> "2023-02-09T21:39:13,671 DEBUG [task-runner-0-priority-0] org.apache.druid.indexing.overlord.TaskRunnerUtils - Task [noop_2023-02-09T21:39:02.008Z_936917b3-a0af-4656-a1e1-9e77ced24d92] status changed to [SUCCESS].[\n]"
2023-02-09T21:55:51,560 DEBUG [k8s-task-runner-25] org.apache.http.wire - http-outgoing-22 >> "  "id" : "noop_2023-02-09T21:39:02.008Z_936917b3-a0af-4656-a1e1-9e77ced24d92",[\n]"
2023-02-09T21:55:51,561 DEBUG [k8s-task-runner-25] org.apache.http.wire - http-outgoing-22 >> "2023-02-09T21:39:13,737 INFO [main] org.apache.druid.indexing.overlord.SingleTaskBackgroundRunner - Starting graceful shutdown of task[noop_2023-02-09T21:39:02.008Z_936917b3-a0af-4656-a1e1-9e77ced24d92].[\n]"
2023-02-09T21:55:51,561 DEBUG [k8s-task-runner-25] org.apache.http.wire - http-outgoing-22 >> "af-4656-a1e1-9e77ced24d92] status changed to [FAILED].[\n]"

The job status in the UI shows as:

{
  "id": "noop_2023-02-09T21:39:02.008Z_936917b3-a0af-4656-a1e1-9e77ced24d92",
  "groupId": "noop_2023-02-09T21:39:02.008Z_936917b3-a0af-4656-a1e1-9e77ced24d92",
  "type": "noop",
  "createdTime": "2023-02-09T21:39:02.014Z",
  "queueInsertionTime": "1970-01-01T00:00:00.000Z",
  "statusCode": "FAILED",
  "status": "FAILED",
  "runnerStatusCode": "WAITING",
  "duration": -1,
  "location": {
    "host": "10.233.68.10",
    "port": 8100,
    "tlsPort": -1
  },
  "dataSource": "none",
  "errorMsg": "Task failed %s: [ noop_2023-02-09T21:39:02.008Z_936917b3-a0af-4656-a1e1-9e77ced24d92, noop20230209t2..."
}

The logs from the actual job itself show a noop task with success:

2023-02-09T16:53:23,371 INFO [task-runner-0-priority-0] org.apache.druid.indexing.worker.executor.ExecutorLifecycle - Task completed with status: {
  "id" : "noop_2023-02-09T16:53:12.037Z_3c8e9f26-6ca4-4600-8723-572d2c8baf48",
  "status" : "SUCCESS",
  "duration" : 3887,
  "errorMsg" : null,
  "location" : {
    "host" : null,
    "port" : -1,
    "tlsPort" : -1
  }
}

I'm at a complete loss at this point so if anyone wanted to help I'd be all ears and welcome any type of paired-troubleshooting. I've gone as far as to give all the service accounts full cluster admin permissions but again I don't really think this has anything to do with service accounts at this point.

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 pushed up the changes requested except for the RBAC changes since I haven't actually been able to say I've had a successful deployment with these chart changes yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Turns out this is a bug with the kubernetes overlord extension and kubernetes 1.25+

Copy link
Contributor

Choose a reason for hiding this comment

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

Were you able to file an issue for it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Discovered this with the author of the kubernetes overlord extension @churromorales . I believe #13759 already fixes the issues and relates to #13749 but maybe @churromorales can comment further if another issue is required I will happily make one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@dampcake putting aside the potential for a new issue to be created I would ask that we merge the RBAC in its current state since it matches the official documentation. Once the bugs are fixed for K8s 1.25 I will test for the minimum viable role permissions and make a new PR to apply those via the helm chart as well as allow for concatenating or overriding the role permissions via the chart .Values.rbac map so people won't get blocked on changes required for rbac in the future.

If you're good with this let me know and I'll create the issue and it can be assigned to me.

{{- end }}

39 changes: 39 additions & 0 deletions helm/druid/templates/broker/roleBinding.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{{/*

Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/}}

{{- if and (.Values.rbac.create) (.Values.broker.enabled) }}
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ template "druid.broker.fullname" . }}
labels:
app: {{ include "druid.name" . }}
chart: {{ include "druid.chart" . }}
component: {{ .Values.broker.name }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ template "druid.broker.fullname" . }}
subjects:
- kind: ServiceAccount
name: {{ include "druid.broker.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- end }}
39 changes: 39 additions & 0 deletions helm/druid/templates/broker/serviceAccount.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{{/*

Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/}}

{{- if and (.Values.broker.serviceAccount.create) (.Values.broker.enabled) }}
apiVersion: v1
kind: ServiceAccount
automountServiceAccountToken: {{ .Values.broker.serviceAccount.automountServiceAccountToken }}
metadata:
name: {{ include "druid.broker.serviceAccountName" . }}
{{- with .Values.broker.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
labels:
app: {{ include "druid.name" . }}
chart: {{ include "druid.chart" . }}
component: {{ .Values.broker.name }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
{{- with .Values.broker.serviceAccount.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
20 changes: 12 additions & 8 deletions helm/druid/templates/coordinator/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,19 @@ spec:
release: {{ .Release.Name }}
component: {{ .Values.coordinator.name }}
annotations:
{{- with .Values.coordinator.podAnnotations }}
{{ toYaml . | indent 8 }}
{{- end }}
{{- if .Values.prometheus.enabled }}
{{- with .Values.prometheus.annotation }}
{{ toYaml . | indent 8 }}
{{- end }}
{{- end }}
druid.k8s.enablePatching: "true"
{{- with .Values.coordinator.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- if .Values.prometheus.enabled }}
{{- with .Values.prometheus.annotation }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}
spec:
{{- if .Values.coordinator.serviceAccount.create }}
serviceAccountName: {{ include "druid.coordinator.serviceAccountName" . }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
Expand Down
Loading