Helm v3 to deploy PowerDNS over Kubernetes

In the article about PowerDNS on Docker or Podman, easy to run we leave pending its realization on Kubernetes, this is because Kubernetes service structure is much more complex than that Docker or Podman and therefore a completely different approach must be made.

Helm v3 to deploy PowerDNS over Kubernetes 1

Package with Helm v3

The first thing to keep in mind is package applications so that the deployment doesn’t require extensive knowledge about Kubernetes (make life easier for the user, the developer) and the second is that we can have many users on the same environment wishing to raise the same application and we can’t create a package for each one, we must to be able to reuse the package we have created.

In Kubernetes the package standard is Helm , that will allow us to manage deployments easily and be reusable by user, project, etc. The Helm package consists of:

  • Chart.yaml: Where the meta information about the package itself is.
  • templates: Folder where we are going to define the objects that are going to be deployed in Kubernetes, but that will have certain modifications so that they are flexible.
  • values.yaml: In the objects to be deployed there will be a series of variables to be defined (eg servers to access, access codes, databases on a remote server, etc.), in this file we define the predefined values of each variable, later, the user who launches the package can adjust it.
  • NOTES.txt: Is placed within “templates” this file and will contain a message about the result of the package installation, such as the IP obtained or entry URL.
  • _helpers.tpl: This file that we will also find inside the “templates” folder and contains definitions of variables that we can use in the objects, such as the name of the package and will allow us to make multiple deployments of the same application in the same namespace simply by changing the deployment version name.

Helm v3 is the stable version of Helm (at the time of writing these lines Helm goes for version v3.0.2) but it has such interesting capabilities as life cycle management or not requiring integrated services in Kubernetes to deploy packages ( to do something similar in version 2 see How to launch a Helm Chart without install Tiller, which requires a job and a launcher pod with Tiller, which represents a greater complexity).

Using Helm

Once we have arranged our Kubernetes cluster (see Kubernetes: Create a minimal environment for demos or K3s: Simplify Kubernetes) we proceed to download the Helm binary on the master node with:

$ curl -sLS https://get.helm.sh/helm-v3.0.2-linux-amd64.tar.gz|sudo tar --no-overwrite-dir --strip=1 -C /usr/local/sbin/. -xz

And that’s it, we don’t have to install anything and then we can install the packages that we need directly, that is, we must bear in mind that Helm v3 doesn’t automatically create namespaces because is considered that this is not a deployment task but part of infrastructure management.

In the case of Powerdns, whose dependency is a mariadb database and we can optionally attach a dashboard with PowerDNS-Admin, we’ll require this type of packages, because are useful if we want customers to have their own managed DNS server by themselves. In future articles we will see that this server is also integrable with External-DNS, which will allow us to publish in PowerDNS the modifications to the Kubernetes input proxies (for example an Ingress with Traefik).

To create a package with the minimum structure we do:

$ helm create powerdns

That will create an infrastructure with the elements indicated above, such as the PowerDNS solution consisting of a deployment (deployment.yaml) for service availability, a service to publish the API (optional: powerdns-api-service.yaml), a service to publish the Dashboard (optional: powerdnsadmin-service.yaml), a service to publish the DNS service (required: powerdns-dns-service.yaml), a persistent volume request (PVC, optional: mariadb-pvc.yaml) to the database, an access configuration by URL (Ingress, optional: ingress.yaml) and finally the access keys to the PowerDNS API and the database (powerdns-secret.yaml), we have to create those objects in the powerdns / templates folder, in our case the folder is left with the following content:

$ ls -1 powerdns/templates/
deployment.yaml
_helpers.tpl
ingress.yaml
mariadb-pvc.yaml
NOTES.txt
powerdnsadmin-service.yaml
powerdns-api-service.yaml
powerdns-dns-service.yaml
powerdns-secret.yaml

Helm Templates

We can see the objects “service”, “secret”, “ingress”, “pvc” and “deployment”, each of them describes a kubernetes object as if it were a direct deployment, for example, we can define an optional service for PowerDNS-Admin:

{{- if .Values.powerdnsadmin.enabled }}
apiVersion: v1
kind: Service
metadata:
  name: {{ template "powerdns.fullname" . }}-service-admin
  labels:
{{ include "powerdns.labels" . | indent 4 }}
spec:
  type: {{ .Values.powerdnsadmin.service.type }}
  ports:
    - port: {{ .Values.powerdnsadmin.service.port }}
      targetPort: pdns-admin-http
      protocol: TCP
      name: pdns-admin-http
  selector:
    app.kubernetes.io/name: {{ .Release.Name }}
    app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

At first glance it does not look anything like a normal deployment, but we have a number of interesting points: ‘{{template “powerdns.fullname” . }}’ Is going to be the full name of the deployment consisting of powerdns plus a unique identifier of the deployment in the namespace where we are going to deploy, this allows us to have multiple deployments of the same service with different names without need to create a new “yaml”.

The templates include language features such as assignments, loops and conditionals, in this case we can see “{{- if .Values.powerdnsadmin.enabled }}” … “{{- end }}” that will allow us to mark this service as optional, a feature that is managed with the attribute:

powerdnsadmin:
  enabled: 'true'

Which is defined in the root of the Chart within the values.yaml file, this file defines all the predefined values in the Chart in yaml format. In the case of the deployment of powerdns+mariadb+powerdns-admin package are about 60 configuration parameters. It is important to remember that each configuration parameter must be clearly defined in the Chart documentation, in the README.md file

More information about handling these types of templates in https://golang.org/pkg/text/template/ and about the predefined values in https://helm.sh/docs/chart_template_guide/

Chart Deployment for PowerDNS

Once the Chart is packaged with helm package powerdns (which will generate a compressed file with the Chart) we’ll proceed to install it with helm install -n NAMESPACE RELEASE_NAME PACKAGE, in the case of Powerdns we need to create the namespace “powerdns” before and also we need a free PV (or a system of dynamic storage allocation). We’ll do to install:

helm install -n powerdns powerdns https://raw.githubusercontent.com/aescanero/helm-powerdns/master/test/powerdns.tgz

Within the powerdns namespace we will create a series of objects that will launch the services and a PVC that will use a volume for the persistent storage of the solution, in the case of having Traefik, a route / domain will be created for web access to the application.

In this way we have several levels of deployments: Namespaces for different clients, Releases so that each client can launch the services it deems convenient (for example, a DNS service per client domain) and each service has its own persistent storage, their own access services and their own management consoles. Becoming a totally multi-tenant solution from a static solution for a specific need.

Conclusion

The sources of this article are in https://github.com/aescanero/helm-powerdns and they are a demonstrative exercise of the capabilities of Helm v3. Helm is going to be an essential tool in the Kubernetes world.

Scroll to top