diff --git a/deploy/helm/k8s-node-termination-handler/Chart.yaml b/deploy/helm/k8s-node-termination-handler/Chart.yaml new file mode 100644 index 00000000..eb146aec --- /dev/null +++ b/deploy/helm/k8s-node-termination-handler/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v2 +appVersion: "1.0" +description: A Helm chart for Kubernetes that provides an adapter for translating GCE node termination events to graceful pod terminations in Kubernetes. +name: k8s-node-termination-handler +version: 0.1.0 diff --git a/deploy/helm/k8s-node-termination-handler/README.md b/deploy/helm/k8s-node-termination-handler/README.md new file mode 100644 index 00000000..91902c4b --- /dev/null +++ b/deploy/helm/k8s-node-termination-handler/README.md @@ -0,0 +1,29 @@ +# k8s-node-termination-handler-helm-chart +A solution to gracefully handle GCE VM terminations in kubernetes clusters + +## Introduction +This chart bootstraps an [adapter for translating GCE node termination events to graceful pod terminations in Kubernetes](https://github.com/GoogleCloudPlatform/k8s-node-termination-handler) deployment on a Kubernetes cluster using the Helm package manager. + +## Prerequisites +* Kubernetes 1.11+ +* Helm 3.0.2+ + +## Parameters +| Parameter | Description | Default | Aditional notes | +| --- | --- | --- | --- | +| `gke_accelerator.enabled` | GKE node GPU accelerator enabled | false | - | +| `gke_preemptible.enabled` | GKE preemtible nodes enabled | true | - | +| `image.repository` | image name | k8s.gcr.io/gke-node-termination-handler@sha256 | - | +| `image.tag` | image tag | aca12d17b222dfed755e28a44d92721e477915fb73211d0a0f8925a1fa847cca | - | +| `image.pullPolicy` | Image pull policy | IfNotPresent | - | +| `rbac.pspEnabled` | If true, create and use a restricted pod security policy | true | - | +| `resources.limits.cpu` | cpu limit | 150m | - | +| `resources.limits.memory` | memory limit | 30Mi | - | +| `slack` | slack webhook | - | This functionality has been added to the project recently. We are currently testing it. | +| `updateStrategy` | Set up update strategy | RollingUpdate | - | + +## Installing the Chart + +``` +helm install k8s-node-termination-handler-helm-chart --namespace +``` diff --git a/deploy/helm/k8s-node-termination-handler/templates/NOTES.txt b/deploy/helm/k8s-node-termination-handler/templates/NOTES.txt new file mode 100644 index 00000000..d2ac71c9 --- /dev/null +++ b/deploy/helm/k8s-node-termination-handler/templates/NOTES.txt @@ -0,0 +1,3 @@ +The agents are spinning up on each node in your cluster. It provides an adapter for translating GCE node termination events to graceful pod terminations in Preemptible VMs and VMs with Accelerators. + +No further action should be required. diff --git a/deploy/helm/k8s-node-termination-handler/templates/_helpers.tpl b/deploy/helm/k8s-node-termination-handler/templates/_helpers.tpl new file mode 100644 index 00000000..9ff35b79 --- /dev/null +++ b/deploy/helm/k8s-node-termination-handler/templates/_helpers.tpl @@ -0,0 +1,51 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "k8s-node-termination-handler.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "k8s-node-termination-handler.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "k8s-node-termination-handler.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "k8s-node-termination-handler.labels" -}} +app.kubernetes.io/name: {{ include "k8s-node-termination-handler.name" . }} +helm.sh/chart: {{ include "k8s-node-termination-handler.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "k8s-node-termination-handler.serviceAccountName" -}} +{{- end -}} diff --git a/deploy/helm/k8s-node-termination-handler/templates/daemonset.yaml b/deploy/helm/k8s-node-termination-handler/templates/daemonset.yaml new file mode 100644 index 00000000..541d0dab --- /dev/null +++ b/deploy/helm/k8s-node-termination-handler/templates/daemonset.yaml @@ -0,0 +1,88 @@ +{{- $serviceName := include "k8s-node-termination-handler.fullname" . -}} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ include "k8s-node-termination-handler.fullname" . }} + labels: + app: {{ template "k8s-node-termination-handler.name" . }} + app.kubernetes.io/name: {{ template "k8s-node-termination-handler.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + helm.sh/chart: {{ template "k8s-node-termination-handler.chart" . }} +spec: + selector: + matchLabels: + app: {{ template "k8s-node-termination-handler.name" . }} + app.kubernetes.io/name: {{ template "k8s-node-termination-handler.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + updateStrategy: + type: {{ .Values.updateStrategy.type }} + {{- if (eq "Recreate" .Values.updateStrategy.type) }} + rollingUpdate: null + {{- end }} + template: + metadata: + labels: + app: {{ template "k8s-node-termination-handler.name" . }} + app.kubernetes.io/name: {{ template "k8s-node-termination-handler.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + helm.sh/chart: {{ template "k8s-node-termination-handler.chart" . }} + spec: + {{ if .Values.gke_accelerator.enabled }} + hostPID: true + {{ end }} + serviceAccountName: {{ $serviceName }} + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + {{ if .Values.gke_accelerator.enabled }} + - matchExpressions: + - key: cloud.google.com/gke-accelerator + operator: Exists + {{ end }} + {{ if .Values.gke_preemptible.enabled }} + - matchExpressions: + - key: cloud.google.com/gke-preemptible + operator: Exists + {{ end }} + containers: + - image: "{{ .Values.image.repository }}:{{ default .Chart.AppVersion .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + name: {{ .Chart.Name }} + command: ["./node-termination-handler"] + args: ["--logtostderr", "--exclude-pods=$(POD_NAME):$(POD_NAMESPACE)", "-v=10", "--taint=cloud.google.com/impending-node-termination::NoSchedule"] + securityContext: + capabilities: + add: ["SYS_BOOT"] + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if .Values.slack }} + - name: SLACK_WEBHOOK_URL + value: "{{ .Values.slack }}" + {{- end }} + resources: + {{- if or .Values.cpuRequest .Values.memoryRequest .Values.cpuLimit .Values.memoryLimit }} + requests: + cpu: {{ .Values.cpuRequest | quote }} + memory: {{ .Values.memoryRequest | quote }} + limits: + cpu: {{ .Values.cpuLimit | quote }} + memory: {{ .Values.memoryLimit | quote }} + {{- else }} +{{ toYaml .Values.resources | indent 10 }} + {{- end }} + tolerations: + - effect: NoSchedule + operator: Exists + - effect: NoExecute + operator: Exists diff --git a/deploy/helm/k8s-node-termination-handler/templates/psp.yaml b/deploy/helm/k8s-node-termination-handler/templates/psp.yaml new file mode 100644 index 00000000..e349d686 --- /dev/null +++ b/deploy/helm/k8s-node-termination-handler/templates/psp.yaml @@ -0,0 +1,67 @@ +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "k8s-node-termination-handler.fullname" . }} + labels: + app: {{ template "k8s-node-termination-handler.name" . }} + app.kubernetes.io/name: {{ template "k8s-node-termination-handler.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + helm.sh/chart: {{ template "k8s-node-termination-handler.chart" . }} + annotations: + seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' +spec: + privileged: false + hostIPC: false + hostNetwork: true + hostPID: false + readOnlyRootFilesystem: false + allowPrivilegeEscalation: false + allowedCapabilities: + - '*' + fsGroup: + rule: RunAsAny + runAsUser: + rule: RunAsAny + seLinux: + rule: RunAsAny + supplementalGroups: + rule: RunAsAny + volumes: + - '*' +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "k8s-node-termination-handler.fullname" . }}-psp + labels: + app: {{ template "k8s-node-termination-handler.name" . }} + app.kubernetes.io/name: {{ template "k8s-node-termination-handler.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + helm.sh/chart: {{ template "k8s-node-termination-handler.chart" . }} +rules: + - apiGroups: ['policy'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "k8s-node-termination-handler.fullname" . }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "k8s-node-termination-handler.fullname" . }}-psp + labels: + app: {{ template "k8s-node-termination-handler.name" . }} + app.kubernetes.io/name: {{ template "k8s-node-termination-handler.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + helm.sh/chart: {{ template "k8s-node-termination-handler.chart" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "k8s-node-termination-handler.fullname" . }}-psp +subjects: + - kind: ServiceAccount + name: {{ include "k8s-node-termination-handler.fullname" . }} + namespace: {{ .Release.Namespace }} \ No newline at end of file diff --git a/deploy/helm/k8s-node-termination-handler/templates/rbac.yaml b/deploy/helm/k8s-node-termination-handler/templates/rbac.yaml new file mode 100644 index 00000000..1ed44ae2 --- /dev/null +++ b/deploy/helm/k8s-node-termination-handler/templates/rbac.yaml @@ -0,0 +1,54 @@ +{{- $serviceName := include "k8s-node-termination-handler.fullname" . -}} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ $serviceName }} + labels: + app: {{ $serviceName }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ $serviceName }} + labels: + app.kubernetes.io/name: {{ include "k8s-node-termination-handler.fullname" . }}-app-installer + helm.sh/chart: {{ include "k8s-node-termination-handler.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +rules: + # Allow Node Termination Handler to get and update nodes (for posting taints). +- apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "update"] + # Allow Node Termination Handler to create events +- apiGroups: [""] + resources: ["events"] + verbs: ["create"] + # Allow Node Termination Handler to list and delete pods (for draining nodes) +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list", "delete"] +--- +{{- $serviceName := include "k8s-node-termination-handler.fullname" . -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ $serviceName }} + labels: + app: {{ $serviceName }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ $serviceName }} +subjects: +- kind: ServiceAccount + name: {{ $serviceName }} + namespace: {{ .Release.Namespace }} + diff --git a/deploy/helm/k8s-node-termination-handler/values.yaml b/deploy/helm/k8s-node-termination-handler/values.yaml new file mode 100644 index 00000000..7af27e47 --- /dev/null +++ b/deploy/helm/k8s-node-termination-handler/values.yaml @@ -0,0 +1,26 @@ +# Default values for k8s-node-termination-handler. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +image: + repository: k8s.gcr.io/gke-node-termination-handler@sha256 + tag: aca12d17b222dfed755e28a44d92721e477915fb73211d0a0f8925a1fa847cca + pullPolicy: IfNotPresent + +resources: + limits: + cpu: 150m + memory: 30Mi + +updateStrategy: + type: RollingUpdate + +rbac: + # rbac.pspEnabled: `true` if PodSecurityPolicy resources should be created + pspEnabled: true + +gke_accelerator: + enabled: false + +gke_preemptible: + enabled: true