diff --git a/kube-plex b/kube-plex deleted file mode 120000 index e5d009f9..00000000 --- a/kube-plex +++ /dev/null @@ -1 +0,0 @@ -.submodules/kube-plex/charts/kube-plex \ No newline at end of file diff --git a/kube-plex/.helmignore b/kube-plex/.helmignore new file mode 100644 index 00000000..f0c13194 --- /dev/null +++ b/kube-plex/.helmignore @@ -0,0 +1,21 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/kube-plex/Chart.yaml b/kube-plex/Chart.yaml new file mode 100644 index 00000000..59f227d4 --- /dev/null +++ b/kube-plex/Chart.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +appVersion: 1.16.0.1226-7eb2c8f6f +description: Plex Media Server +name: kube-plex +version: 0.2.4 +keywords: + - plex +home: https://plex.tv/ +icon: https://www.plex.tv/wp-content/uploads/2018/01/pmp-icon-1.png +sources: + - https://github.com/munnerz/kube-plex + - https://hub.docker.com/r/plexinc/pms-docker/ +maintainers: + - name: munnerz diff --git a/kube-plex/README.md b/kube-plex/README.md new file mode 100644 index 00000000..7a505c09 --- /dev/null +++ b/kube-plex/README.md @@ -0,0 +1,49 @@ +# Plex Media Server helm chart + +## Configuration + +The following tables lists the configurable parameters of the Plex chart and their default values. + +| Parameter | Description | Default | +|----------------------------|-------------------------------------|---------------------------------------------------------| +| `image.repository` | Image repository | `plexinc/pms-docker` | +| `image.tag` | Image tag. Possible values listed [here](https://hub.docker.com/r/plexinc/pms-docker/tags/).| `1.10.1.4602-f54242b6b`| +| `image.pullPolicy` | Image pull policy | `IfNotPresent` | +| `kubePlex.enabled` | Enable KubPlex transcoder | `true` | +| `kubePlex.image.repository` | Image repository | `quay.io/munnerz/kube-plex` | +| `kubePlex.image.tag` | Image tag. | `latest`| +| `kubePlex.image.pullPolicy` | Image pull policy | `IfNotPresent` | +| `claimToken` | Plex Claim Token to authenticate your acount | `` | +| `timezone` | Timezone plex instance should run as, e.g. 'America/New_York' | `Europe/London` | +| `service.type` | Kubernetes service type for the plex GUI/API | `ClusterIP` | +| `service.port` | Kubernetes port where the plex GUI/API is exposed| `32400` | +| `service.annotations` | Service annotations for the Plex GUI | `{}` | +| `service.labels` | Custom labels | `{}` | +| `service.loadBalancerIP` | Loadbalance IP for the Plex GUI | `{}` | +| `service.loadBalancerSourceRanges` | List of IP CIDRs allowed access to load balancer (if supported) | None +| `ingress.enabled` | Enables Ingress | `false` | +| `ingress.annotations` | Ingress annotations | `{}` | +| `ingress.labels` | Custom labels | `{}` +| `ingress.path` | Ingress path | `/` | +| `ingress.hosts` | Ingress accepted hostnames | `chart-example.local` | +| `ingress.tls` | Ingress TLS configuration | `[]` | +| `rbac.create` | Create RBAC roles? | `true` | +| `nodeSelector` | Node labels for pod assignment | `beta.kubernetes.io/arch: amd64` | +| `persistence.transcode.enabled` | Use persistent volume for transcoding | `false` | +| `persistence.transcode.size` | Size of persistent volume claim | `20Gi` | +| `persistence.transcode.claimName`| Use an existing PVC to persist data | `nil` | +| `persistence.transcode.subPath` | SubPath to use for existing Claim | `nil` | +| `persistence.transcode.storageClass` | Type of persistent volume claim | `-` | +| `persistence.data.size` | Size of persistent volume claim | `40Gi` | +| `persistence.data.existingClaim`| Use an existing PVC to persist data | `nil` | +| `persistence.data.subPath` | SubPath to use for existing Claim | `nil` | +| `persistence.data.storageClass` | Type of persistent volume claim | `-` | +| `persistence.config.size` | Size of persistent volume claim | `20Gi` | +| `persistence.config.existingClaim`| Use an existing PVC to persist data | `nil` | +| `persistence.config.subPath` | SubPath to use for existing Claim | `nil` | +| `persistence.config.storageClass` | Type of persistent volume claim | `-` | +| `resources` | CPU/Memory resource requests/limits | `{}` | +| `podAnnotations` | Key-value pairs to add as pod annotations | `{}` | + + +Read through the [values.yaml](values.yaml) file. It has several commented out suggested values. diff --git a/kube-plex/templates/NOTES.txt b/kube-plex/templates/NOTES.txt new file mode 100644 index 00000000..ccfecb7e --- /dev/null +++ b/kube-plex/templates/NOTES.txt @@ -0,0 +1,19 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range .Values.ingress.hosts }} + http://{{ . }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc -w {{ template "fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.service.externalPort }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl port-forward $POD_NAME 8080:{{ .Values.service.externalPort }} +{{- end }} diff --git a/kube-plex/templates/_helpers.tpl b/kube-plex/templates/_helpers.tpl new file mode 100644 index 00000000..f0d83d2e --- /dev/null +++ b/kube-plex/templates/_helpers.tpl @@ -0,0 +1,16 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "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). +*/}} +{{- define "fullname" -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/kube-plex/templates/deployment.yaml b/kube-plex/templates/deployment.yaml new file mode 100644 index 00000000..2538af95 --- /dev/null +++ b/kube-plex/templates/deployment.yaml @@ -0,0 +1,167 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "fullname" . }} + labels: + app: {{ template "name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: {{ template "name" . }} + release: {{ .Release.Name }} + template: + metadata: + labels: + app: {{ template "name" . }} + release: {{ .Release.Name }} + {{- if .Values.podAnnotations }} + annotations: + {{- range $key, $value := .Values.podAnnotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- end }} + spec: + serviceAccountName: {{ if .Values.rbac.create }}{{ template "fullname" . }}{{ else }}{{ .Values.rbac.serviceAccountName | quote }}{{ end }} + hostname: "{{ template "fullname" . }}" +{{- if .Values.kubePlex.enabled }} + initContainers: + - name: kube-plex-install + image: "{{ .Values.kubePlex.image.repository }}:{{ .Values.kubePlex.image.tag }}" + imagePullPolicy: {{ .Values.kubePlex.image.pullPolicy }} + command: + - cp + - /kube-plex + - /shared/kube-plex + volumeMounts: + - name: shared + mountPath: /shared +{{- end }} + containers: + - name: plex + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} +{{- if .Values.kubePlex.enabled }} + # We replace the PMS binary with a postStart hook to save having to + # modify the default image entrypoint. + lifecycle: + postStart: + exec: + command: + - bash + - -c + - | + #!/bin/bash + set -e + rm -f '/usr/lib/plexmediaserver/Plex Transcoder' + cp /shared/kube-plex '/usr/lib/plexmediaserver/Plex Transcoder' +{{- end }} + readinessProbe: + httpGet: + path: /identity + port: 32400 + initialDelaySeconds: 15 + timeoutSeconds: 5 + livenessProbe: + httpGet: + path: /identity + port: 32400 + initialDelaySeconds: 10 + timeoutSeconds: 10 + ports: + - name: pms + containerPort: 32400 + - name: http + containerPort: 32400 + - name: https + containerPort: 32443 + env: + - name: TZ + value: "{{ .Values.timezone }}" + # TODO: move this to a secret? + - name: PLEX_CLAIM + value: "{{ .Values.claimToken }}" + # kube-plex env vars + - name: PMS_INTERNAL_ADDRESS + value: http://{{ template "fullname" . }}:32400 + - name: PMS_IMAGE + value: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + - name: KUBE_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: TRANSCODE_PVC +{{- if .Values.persistence.transcode.claimName }} + value: "{{ .Values.persistence.transcode.claimName }}" +{{- else }} + value: "{{ template "fullname" . }}-transcode" +{{- end }} + - name: DATA_PVC +{{- if .Values.persistence.data.claimName }} + value: "{{ .Values.persistence.data.claimName }}" +{{- else }} + value: "{{ template "fullname" . }}-data" +{{- end }} + - name: CONFIG_PVC +{{- if .Values.persistence.config.claimName }} + value: "{{ .Values.persistence.config.claimName }}" +{{- else }} + value: "{{ template "fullname" . }}-config" +{{- end }} + volumeMounts: + - name: data + mountPath: /data + {{- if .Values.persistence.data.subPath }} + subPath: {{ .Values.persistence.data.subPath }} + {{ end }} + - name: config + mountPath: /config + {{- if .Values.persistence.config.subPath }} + subPath: {{ .Values.persistence.config.subPath }} + {{ end }} + - name: transcode + mountPath: /transcode + {{- if .Values.persistence.transcode.subPath }} + subPath: {{ .Values.persistence.transcode.subPath }} + {{ end }} + - name: shared + mountPath: /shared + resources: +{{ toYaml .Values.resources | indent 10 }} + {{- if .Values.nodeSelector }} + nodeSelector: +{{ toYaml .Values.nodeSelector | indent 8 }} + {{- end }} + volumes: + - name: data + persistentVolumeClaim: +{{- if .Values.persistence.data.claimName }} + claimName: "{{ .Values.persistence.data.claimName }}" +{{- else }} + claimName: "{{ template "fullname" . }}-data" +{{- end }} + - name: config + persistentVolumeClaim: +{{- if .Values.persistence.config.claimName }} + claimName: "{{ .Values.persistence.config.claimName }}" +{{- else }} + claimName: "{{ template "fullname" . }}-config" +{{- end }} + - name: transcode +{{- if .Values.persistence.transcode.enabled }} + persistentVolumeClaim: +{{- if .Values.persistence.transcode.claimName }} + claimName: "{{ .Values.persistence.transcode.claimName }}" +{{- else }} + claimName: "{{ template "fullname" . }}-transcode" +{{- end }} +{{- else }} + emptyDir: {} +{{- end }} + - name: shared + emptyDir: {} diff --git a/kube-plex/templates/ingress.yaml b/kube-plex/templates/ingress.yaml new file mode 100644 index 00000000..167f70b3 --- /dev/null +++ b/kube-plex/templates/ingress.yaml @@ -0,0 +1,31 @@ +{{- if .Values.ingress.enabled -}} +{{- $serviceName := include "fullname" . -}} +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ template "fullname" . }} + labels: + app: {{ template "name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + annotations: + {{- range $key, $value := .Values.ingress.annotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} +spec: + rules: + {{- range $host := .Values.ingress.hosts }} + - host: {{ $host }} + http: + paths: + - path: / + backend: + serviceName: {{ $serviceName }} + servicePort: pms + {{- end -}} + {{- if .Values.ingress.tls }} + tls: +{{ toYaml .Values.ingress.tls | indent 4 }} + {{- end -}} +{{- end -}} diff --git a/kube-plex/templates/rbac.yaml b/kube-plex/templates/rbac.yaml new file mode 100644 index 00000000..a3277700 --- /dev/null +++ b/kube-plex/templates/rbac.yaml @@ -0,0 +1,54 @@ +{{- if .Values.rbac.create -}} +{{- if .Values.kubePlex.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "fullname" . }} + labels: + app: {{ template "name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +rules: +- apiGroups: + - "" + resources: + - pods + - pods/attach + - pods/exec + - pods/portforward + - pods/proxy + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "fullname" . }} + labels: + app: {{ template "name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "fullname" . }} +subjects: +- kind: ServiceAccount + name: {{ template "fullname" . }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "fullname" . }} +{{- end }} diff --git a/kube-plex/templates/service.yaml b/kube-plex/templates/service.yaml new file mode 100644 index 00000000..f850d581 --- /dev/null +++ b/kube-plex/templates/service.yaml @@ -0,0 +1,59 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "fullname" . }} + labels: + app: {{ template "name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- if .Values.service.labels }} +{{ toYaml .Values.service.labels | indent 4 }} +{{- end }} +{{- with .Values.service.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: +{{- if (or (eq .Values.service.type "ClusterIP") (empty .Values.service.type)) }} + type: ClusterIP + {{- if .Values.service.clusterIP }} + clusterIP: {{ .Values.service.clusterIP }} + {{end}} +{{- else if eq .Values.service.type "LoadBalancer" }} + type: {{ .Values.service.type }} + {{- if .Values.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: +{{ toYaml .Values.service.loadBalancerSourceRanges | indent 4 }} + {{- end -}} +{{- else }} + type: {{ .Values.service.type }} +{{- end }} +{{- if .Values.service.externalIPs }} + externalIPs: +{{ toYaml .Values.service.externalIPs | indent 4 }} +{{- end }} + {{- if .Values.service.externalTrafficPolicy }} + externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy }} + {{- end }} + ports: + - name: pms + port: {{ .Values.service.port }} + protocol: TCP + targetPort: pms +{{ if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }} + nodePort: {{.Values.service.nodePort}} +{{ end }} + - name: http + port: 80 + targetPort: pms + - name: https + port: 443 + targetPort: 32443 + selector: + app: {{ template "name" . }} + release: {{ .Release.Name }} + diff --git a/kube-plex/templates/volumes.yaml b/kube-plex/templates/volumes.yaml new file mode 100644 index 00000000..9695c4ee --- /dev/null +++ b/kube-plex/templates/volumes.yaml @@ -0,0 +1,66 @@ +{{- if and (not .Values.persistence.transcode.claimName) .Values.persistence.transcode.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ template "fullname" . }}-transcode + labels: + app: {{ template "name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + component: transcode +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: {{ .Values.persistence.transcode.size | quote }} +{{- if .Values.persistence.transcode.storageClass }} + storageClassName: {{ .Values.persistence.transcode.storageClass | quote }} +{{- end }} +--- +{{- end }} +{{- if not .Values.persistence.config.claimName }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ template "fullname" . }}-config + labels: + app: {{ template "name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + component: config +spec: + accessModes: + - {{ .Values.persistence.config.accessMode | quote }} + resources: + requests: + storage: {{ .Values.persistence.config.size | quote }} +{{- if .Values.persistence.config.storageClass }} + storageClassName: {{ .Values.persistence.config.storageClass | quote }} +{{- end }} +--- +{{- end }} +{{- if not .Values.persistence.data.claimName }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ template "fullname" . }}-data + labels: + app: {{ template "name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + component: data +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: {{ .Values.persistence.data.size | quote }} +{{- if .Values.persistence.data.storageClass }} + storageClassName: {{ .Values.persistence.data.storageClass | quote }} +{{- end }} +--- +{{- end }} diff --git a/kube-plex/values.yaml b/kube-plex/values.yaml new file mode 100644 index 00000000..49c3f090 --- /dev/null +++ b/kube-plex/values.yaml @@ -0,0 +1,120 @@ +# Default values for kube-plex. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +image: + repository: plexinc/pms-docker + tag: 1.16.0.1226-7eb2c8f6f + pullPolicy: IfNotPresent + +kubePlex: + enabled: true + image: + repository: quay.io/munnerz/kube-plex + tag: latest + pullPolicy: Always + +# Override this with the plex claim token from plex.tv/claim +claimToken: "" + +# Set the timezone of the plex server +timezone: Europe/London + +service: + type: ClusterIP + port: 32400 + ## Specify the nodePort value for the LoadBalancer and NodePort service types. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + # nodePort: + ## Provide any additional annotations which may be required. This can be used to + ## set the LoadBalancer service type to internal only. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + annotations: {} + labels: {} + ## Use loadBalancerIP to request a specific static IP, + ## otherwise leave blank + ## + loadBalancerIP: + # loadBalancerSourceRanges: [] + ## Set the externalTrafficPolicy in the Service to either Cluster or Local + # externalTrafficPolicy: Cluster + +ingress: + enabled: false + # Used to create an Ingress record. + hosts: + - chart-example.local + annotations: + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + tls: + # Secrets must be manually created in the namespace. + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +rbac: + create: true + # Specify create: false and serviceAccountName to manually manage the service + # account for this deployment + ## serviceAccountName: "" + +nodeSelector: + beta.kubernetes.io/arch: amd64 + +persistence: + transcode: + # Optionally specify claimName to manually override the PVC to be used for + # the transcode directory. If claimName is specified, storageClass and size + # are ignored. + ## claimName: "plex-transcode-pvc" + # Optionally specify a storage class to be used for the transcode directory. + # If not specified and claimName is not specified, the default storage + # class will be used. + storageClass: "" + # subPath: some-subpath + # The requested size of the volume to be used when creating a + # PersistentVolumeClaim. + size: 20Gi + data: + # Optionally specify claimName to manually override the PVC to be used for + # the data directory. If claimName is specified, storageClass and size are + # ignored. + ## claimName: "plex-data-pvc" + # Optionally specify a storage class to be used for the data directory. + # If not specified and claimName is not specified, the default storage + # class will be used. + storageClass: "" + # subPath: some-subpath + # The requested size of the volume to be used when creating a + # PersistentVolumeClaim. + size: 40Gi + config: + # Optionally specify claimName to manually override the PVC to be used for + # the config directory. If claimName is specified, storageClass and size + # are ignored. + ## claimName: "plex-config-pvc" + # Optionally specify a storage class to be used for the config directory. + # If not specified and claimName is not specified, the default storage + # class will be used. + # subPath: some-subpath + storageClass: "" + # The requested size of the volume to be used when creating a + # PersistentVolumeClaim. + size: 20Gi + accessMode: ReadWriteMany + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +podAnnotations: {} diff --git a/provisioner b/provisioner deleted file mode 120000 index 84d38d3c..00000000 --- a/provisioner +++ /dev/null @@ -1 +0,0 @@ -.submodules/sig-storage-local-static-provisioner/helm/provisioner \ No newline at end of file diff --git a/provisioner/Chart.yaml b/provisioner/Chart.yaml new file mode 100644 index 00000000..e524c013 --- /dev/null +++ b/provisioner/Chart.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +version: 2.3.2 +description: local provisioner chart +name: provisioner +appVersion: 2.3.2 +keywords: + - storage + - local +engine: gotpl +home: https://github.com/kubernetes-sigs/sig-storage-local-static-provisioner/tree/master/helm/provisioner +maintainers: +- name: billimek diff --git a/provisioner/templates/namespace.yaml b/provisioner/templates/namespace.yaml new file mode 100644 index 00000000..77a0b788 --- /dev/null +++ b/provisioner/templates/namespace.yaml @@ -0,0 +1,10 @@ +{{- if .Values.common.createNamespace }} +apiVersion: v1 +kind: Namespace +metadata: + name: {{ .Values.common.namespace | quote }} + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: {{ replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name }} +{{- end }} diff --git a/provisioner/templates/pod-security-policy.yaml b/provisioner/templates/pod-security-policy.yaml new file mode 100644 index 00000000..9e660cf7 --- /dev/null +++ b/provisioner/templates/pod-security-policy.yaml @@ -0,0 +1,35 @@ +{{- if .Values.common.podSecurityPolicy -}} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: local-storage-provisioner-pod-security-policy + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: {{ replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name }} +spec: + allowPrivilegeEscalation: true + allowedHostPaths: + - pathPrefix: /dev + {{- range $classConfig := .Values.classes }} + - pathPrefix: {{ $classConfig.hostDir }} + {{- end }} + fsGroup: + rule: RunAsAny + privileged: true + requiredDropCapabilities: + - ALL + runAsUser: + ranges: + - max: 65535 + min: 1 + rule: MustRunAs + seLinux: + rule: RunAsAny + supplementalGroups: + rule: RunAsAny + volumes: + - configMap + - secret + - hostPath +{{- end }} diff --git a/provisioner/templates/provisioner-cluster-role-binding.yaml b/provisioner/templates/provisioner-cluster-role-binding.yaml new file mode 100644 index 00000000..b58a04c7 --- /dev/null +++ b/provisioner/templates/provisioner-cluster-role-binding.yaml @@ -0,0 +1,124 @@ +{{- if .Values.common.rbac }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: local-storage-provisioner-pv-binding + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: {{ replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name }} +subjects: +- kind: ServiceAccount + name: {{ .Values.daemonset.serviceAccount }} + namespace: {{ .Values.common.namespace }} +roleRef: + kind: ClusterRole + name: system:persistent-volume-provisioner + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: local-storage-provisioner-node-clusterrole + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: {{ replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name }} +rules: +- apiGroups: [""] + resources: ["nodes"] + verbs: ["get"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: local-storage-provisioner-node-binding + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: {{ replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name }} +subjects: +- kind: ServiceAccount + name: {{ .Values.daemonset.serviceAccount }} + namespace: {{ .Values.common.namespace }} +roleRef: + kind: ClusterRole + name: local-storage-provisioner-node-clusterrole + apiGroup: rbac.authorization.k8s.io +{{- if .Values.common.useJobForCleaning }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: local-storage-provisioner-jobs-role + namespace: {{ .Values.common.namespace }} + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: {{ replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name }} +rules: +- apiGroups: + - 'batch' + resources: + - jobs + verbs: + - '*' +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: local-storage-provisioner-jobs-rolebinding + namespace: {{ .Values.common.namespace }} + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: {{ replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name }} +subjects: +- kind: ServiceAccount + name: {{ .Values.daemonset.serviceAccount }} + namespace: {{ .Values.common.namespace }} +roleRef: + kind: Role + name: local-storage-provisioner-jobs-role + apiGroup: rbac.authorization.k8s.io +{{- end }} +{{- if .Values.common.podSecurityPolicy }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: local-storage-provisioner-psp-role + namespace: {{ .Values.common.namespace }} + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: {{ replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name }} +rules: +- apiGroups: + - policy + resources: + - podsecuritypolicies + resourceNames: + - local-storage-provisioner-pod-security-policy + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: local-storage-provisioner-psp-rolebinding + namespace: {{ .Values.common.namespace }} + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: {{ replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name }} +subjects: +- kind: ServiceAccount + name: {{ .Values.daemonset.serviceAccount }} + namespace: {{ .Values.common.namespace }} +roleRef: + kind: Role + name: local-storage-provisioner-psp-role + apiGroup: rbac.authorization.k8s.io +{{- end }} +{{- end }} diff --git a/provisioner/templates/provisioner-service-account.yaml b/provisioner/templates/provisioner-service-account.yaml new file mode 100644 index 00000000..df257b17 --- /dev/null +++ b/provisioner/templates/provisioner-service-account.yaml @@ -0,0 +1,11 @@ +{{- if .Values.common.rbac }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.daemonset.serviceAccount }} + namespace: {{ .Values.common.namespace }} + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: {{ replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name }} +{{- end }} diff --git a/provisioner/templates/provisioner.yaml b/provisioner/templates/provisioner.yaml new file mode 100644 index 00000000..201250d5 --- /dev/null +++ b/provisioner/templates/provisioner.yaml @@ -0,0 +1,218 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Values.common.configMapName }} + namespace: {{ .Values.common.namespace }} + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: {{ replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name }} +data: +{{- if .Values.daemonset.nodeLabels }} + nodeLabelsForPV: | + {{- range $label := .Values.daemonset.nodeLabels }} + - {{$label}} + {{- end }} +{{- end }} +{{- if .Values.common.useAlphaAPI }} + useAlphaAPI: "true" +{{- end }} +{{- if .Values.common.setPVOwnerRef }} + setPVOwnerRef: "true" +{{- end }} +{{- if .Values.common.useJobForCleaning }} + useJobForCleaning: "yes" +{{- end}} +{{- if .Values.common.useNodeNameOnly }} + useNodeNameOnly: "true" +{{- end }} +{{- if .Values.common.minResyncPeriod }} + minResyncPeriod: {{ .Values.common.minResyncPeriod | quote }} +{{- end}} + storageClassMap: | + {{- range $classConfig := .Values.classes }} + {{ $classConfig.name }}: + hostDir: {{ $classConfig.hostDir }} + mountDir: {{ if $classConfig.mountDir }} {{- $classConfig.mountDir -}} {{ else }} {{- $classConfig.hostDir -}} {{ end }} + {{- if $classConfig.blockCleanerCommand }} + blockCleanerCommand: + {{- range $val := $classConfig.blockCleanerCommand }} + - "{{ $val -}}"{{- end}} + {{- end }} + {{- if $classConfig.volumeMode }} + volumeMode: {{ $classConfig.volumeMode }} + {{- end }} + {{- if $classConfig.fsType }} + fsType: {{ $classConfig.fsType }} + {{- end }} + {{- end }} +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ .Values.daemonset.name }} + namespace: {{ .Values.common.namespace }} + labels: + app: local-volume-provisioner + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: {{ replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name }} +spec: + selector: + matchLabels: + app: local-volume-provisioner + template: + metadata: + labels: + app: local-volume-provisioner + spec: + serviceAccountName: {{.Values.daemonset.serviceAccount}} +{{- if .Values.daemonset.priorityClassName }} +{{- if eq .Values.common.namespace "kube-system" }} + priorityClassName: {{.Values.daemonset.priorityClassName}} +{{- else }} + {{- $systemCriticalClasses := list "system-cluster-critical" "system-node-critical" }} + {{- if not (has .Values.daemonset.priorityClassName $systemCriticalClasses) }} + priorityClassName: {{.Values.daemonset.priorityClassName}} + {{- end }} +{{- end }} +{{- end }} +{{- if .Values.daemonset.nodeSelector }} + nodeSelector: +{{ .Values.daemonset.nodeSelector | toYaml | trim | indent 8 }} +{{- end }} +{{- if .Values.daemonset.tolerations }} + tolerations: +{{ .Values.daemonset.tolerations | toYaml | trim | indent 8 }} +{{- end }} + containers: + - image: "{{ .Values.daemonset.image }}" + {{- if .Values.daemonset.imagePullPolicy }} + imagePullPolicy: {{ .Values.daemonset.imagePullPolicy | quote }} + {{- end }} + name: provisioner + securityContext: + privileged: true +{{- if .Values.daemonset.resources }} + resources: +{{ .Values.daemonset.resources | toYaml | trim | indent 12 }} +{{- end }} + env: + - name: MY_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: MY_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: JOB_CONTAINER_IMAGE + value: "{{ .Values.daemonset.image }}" + {{- if .Values.daemonset.kubeConfigEnv }} + - name: KUBECONFIG + value: {{.Values.daemonset.kubeConfigEnv}} + {{- end }} + {{- if .Values.prometheus.operator.enabled }} + ports: + - containerPort: 8080 + name: http + {{- end }} + volumeMounts: + - mountPath: /etc/provisioner/config + name: provisioner-config + readOnly: true + - mountPath: /dev + name: provisioner-dev + {{- range $classConfig := .Values.classes }} + - mountPath: {{ if $classConfig.mountDir }} {{- $classConfig.mountDir -}} {{ else }} {{- $classConfig.hostDir -}} {{ end }} + name: {{ $classConfig.name }} + mountPropagation: "HostToContainer" + {{- end }} + volumes: + - name: provisioner-config + configMap: + name: {{ .Values.common.configMapName }} + - name: provisioner-dev + hostPath: + path: /dev + {{- range $classConfig := .Values.classes }} + - name: {{ $classConfig.name }} + hostPath: + path: {{ $classConfig.hostDir }} + {{- end }} +{{- $release := .Release }} +{{- $chart := .Chart }} +{{- range $val := .Values.classes }} +{{- if $val.storageClass }} +--- +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: {{ $val.name }} + {{- if kindIs "map" $val.storageClass }} + {{- if $val.storageClass.isDefaultClass }} + annotations: + storageclass.kubernetes.io/is-default-class: "true" + {{- end }} + {{- end }} + labels: + heritage: {{ $release.Service | quote }} + release: {{ $release.Name | quote }} + chart: {{ replace "+" "_" $chart.Version | printf "%s-%s" $chart.Name }} +provisioner: kubernetes.io/no-provisioner +volumeBindingMode: WaitForFirstConsumer +{{- if kindIs "map" $val.storageClass }} +reclaimPolicy: {{ $val.storageClass.reclaimPolicy | default "Delete" }} +{{- else }} +reclaimPolicy: Delete +{{- end }} +{{- end }} +{{- end }} +{{- if .Values.prometheus.operator.enabled }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.daemonset.name }} + namespace: {{ .Values.common.namespace }} + labels: + app: local-volume-provisioner + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: {{ replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name }} +spec: + type: ClusterIP + ports: + - port: 8080 + targetPort: 8080 + name: http + selector: + app: local-volume-provisioner +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ .Values.daemonset.name }} + namespace: {{ .Values.prometheus.operator.serviceMonitor.namespace }} + labels: + app: local-volume-provisioner + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: {{ replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name }} + {{- if .Values.prometheus.operator.serviceMonitor.selector }} + {{ toYaml .Values.prometheus.operator.serviceMonitor.selector }} + {{- end -}} +spec: + jobLabel: app + selector: + matchLabels: + app: local-volume-provisioner + release: {{ .Release.Name | quote }} + namespaceSelector: + matchNames: + - {{ .Values.common.namespace }} + endpoints: + - port: http + interval: {{ .Values.prometheus.operator.serviceMonitor.interval }} + scheme: http +{{- end }} diff --git a/provisioner/values.yaml b/provisioner/values.yaml new file mode 100644 index 00000000..2a2eabbe --- /dev/null +++ b/provisioner/values.yaml @@ -0,0 +1,157 @@ +# +# Common options. +# +common: + # + # Defines whether to generate service account and role bindings. + # + rbac: true + # + # Defines the namespace where provisioner runs + # + namespace: default + # + # Defines whether to create provisioner namespace + # + createNamespace: false + # + # Beta PV.NodeAffinity field is used by default. If running against pre-1.10 + # k8s version, the `useAlphaAPI` flag must be enabled in the configMap. + # + useAlphaAPI: false + # + # Indicates if PVs should be dependents of the owner Node. + # + setPVOwnerRef: false + # + # Provisioner clean volumes in process by default. If set to true, provisioner + # will use Jobs to clean. + # + useJobForCleaning: false + # + # Provisioner name contains Node.UID by default. If set to true, the provisioner + # name will only use Node.Name. + # + useNodeNameOnly: false + # + # Resync period in reflectors will be random between minResyncPeriod and + # 2*minResyncPeriod. Default: 5m0s. + # + # minResyncPeriod: 5m0s + # + # Defines the name of configmap used by Provisioner + # + configMapName: "local-provisioner-config" + # + # Enables or disables Pod Security Policy creation and binding + # + podSecurityPolicy: false +# +# Configure storage classes. +# +classes: +- name: fast-disks # Defines name of storage classe. + # Path on the host where local volumes of this storage class are mounted + # under. + hostDir: /mnt/fast-disks + # Optionally specify mount path of local volumes. By default, we use same + # path as hostDir in container. + # mountDir: /mnt/fast-disks + # The volume mode of created PersistentVolume object. Default to Filesystem + # if not specified. + volumeMode: Filesystem + # Filesystem type to mount. + # It applies only when the source path is a block device, + # and desire volume mode is Filesystem. + # Must be a filesystem type supported by the host operating system. + fsType: ext4 + blockCleanerCommand: + # Do a quick reset of the block device during its cleanup. + # - "/scripts/quick_reset.sh" + # or use dd to zero out block dev in two iterations by uncommenting these lines + # - "/scripts/dd_zero.sh" + # - "2" + # or run shred utility for 2 iteration.s + - "/scripts/shred.sh" + - "2" + # or blkdiscard utility by uncommenting the line below. + # - "/scripts/blkdiscard.sh" + # Uncomment to create storage class object with default configuration. + # storageClass: true + # Uncomment to create storage class object and configure it. + # storageClass: + # reclaimPolicy: Delete # Available reclaim policies: Delete/Retain, defaults: Delete. + # isDefaultClass: true # set as default class + +# +# Configure DaemonSet for provisioner. +# +daemonset: + # + # Defines the name of a Provisioner + # + name: "local-volume-provisioner" + # + # Defines Provisioner's image name including container registry. + # + image: quay.io/external_storage/local-volume-provisioner:v2.3.2 + # + # Defines Image download policy, see kubernetes documentation for available values. + # + # imagePullPolicy: Always + # + # Defines a name of the service account which Provisioner will use to communicate with API server. + # + serviceAccount: local-storage-admin + # + # Defines a name of the Pod Priority Class to use with the Provisioner DaemonSet + # + # Note that if you want to make it critical, specify "system-cluster-critical" + # or "system-node-critical" and deploy in kube-system namespace. + # Ref: https://k8s.io/docs/tasks/administer-cluster/guaranteed-scheduling-critical-addon-pods/#marking-pod-as-critical + # + # priorityClassName: system-node-critical + # If configured, nodeSelector will add a nodeSelector field to the DaemonSet PodSpec. + # + # NodeSelector constraint for local-volume-provisioner scheduling to nodes. + # Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector + nodeSelector: {} + # + # If configured KubeConfigEnv will (optionally) specify the location of kubeconfig file on the node. + # kubeConfigEnv: KUBECONFIG + # + # List of node labels to be copied to the PVs created by the provisioner in a format: + # + # nodeLabels: + # - failure-domain.beta.kubernetes.io/zone + # - failure-domain.beta.kubernetes.io/region + # + # If configured, tolerations will add a toleration field to the DaemonSet PodSpec. + # + # Node tolerations for local-volume-provisioner scheduling to nodes with taints. + # Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + tolerations: [] + # + # If configured, resources will set the requests/limits field to the Daemonset PodSpec. + # Ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + resources: {} +# +# Configure Prometheus monitoring +# +prometheus: + operator: + ## Are you using Prometheus Operator? + enabled: false + + serviceMonitor: + ## Interval at which Prometheus scrapes the provisioner + interval: 10s + + # Namespace Prometheus is installed in + namespace: monitoring + + ## Defaults to whats used if you follow CoreOS [Prometheus Install Instructions](https://github.com/coreos/prometheus-operator/tree/master/helm#tldr) + ## [Prometheus Selector Label](https://github.com/coreos/prometheus-operator/blob/master/helm/prometheus/templates/prometheus.yaml#L65) + ## [Kube Prometheus Selector Label](https://github.com/coreos/prometheus-operator/blob/master/helm/kube-prometheus/values.yaml#L298) + selector: + prometheus: kube-prometheus