Search code examples
kuberneteskubernetes-helmapache-kafka-connectkubernetes-secrets

Retrieve and write TLS CRT kubernetes secret to another pod in Helm template


I have a Kubernetes cluster with Elasticsearch currently deployed.

The Elasticsearch coordinator node is accessible behind a service via a ClusterIP over HTTPS. It uses a self-signed TLS certificate.

I can retrieve the value of the CA:

kubectl get secret \
    -n elasticsearch elasticsearch-coordinating-only-crt \
    -o jsonpath="{.data.ca\.crt}" | base64 -d
-----BEGIN CERTIFICATE-----
MIIDIjCCAgqgAwIBAgIRANkAx51S
...
...

I need to provide this as a ca.crt to other app deployments.

Note: The Elasticsearch deployment is an an elasticsearch Kubernetes namespace. New deployments will be in different namespaces.

An example of this is a deployment of kafka that includes a kafka-connect-elasticsearch/ sink. The sink connector uses configuration such as:

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ include "kafka.fullname" . }}-connect
  labels: {{- include "common.labels.standard" . | nindent 4 }}
    app.kubernetes.io/component: connector
data:
  connect-standalone-custom.properties: |-
    bootstrap.servers={{ include "kafka.fullname" . }}-0.{{ include "kafka.fullname" . }}-headless.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }}:{{ .Values.service.port }}
    key.converter.schemas.enable=false
    value.converter.schemas.enable=false
    offset.storage.file.filename=/tmp/connect.offsets
    offset.flush.interval.ms=10000
    key.converter=org.apache.kafka.connect.json.JsonConverter
    value.converter=org.apache.kafka.connect.json.JsonConverter
    plugin.path=/usr/local/share/kafka/plugins
  elasticsearch.properties: |-
    name=elasticsearch-sink
    connector.class=io.confluent.connect.elasticsearch.ElasticsearchSinkConnector
    tasks.max=4
    topics=syslog,nginx
    key.ignore=true
    schema.ignore=true
    connection.url=https://elasticsearch-coordinating-only.elasticsearch:9200
    type.name=kafka-connect
    connection.username=elastic
    connection.password=xxxxxxxx
    elastic.security.protocol=SSL
    elastic.https.ssl.truststore.location=/etc/ssl/certs/elasticsearch-ca.crt
    elastic.https.ssl.truststore.type=PEM

Notice the elastic.https.ssl.truststore.location=/etc/ssl/certs/elasticsearch-ca.crt; that's the file I need to put inside the kafka-based container.

What's the optimal way to do that with Helm templates?

Currently I have a fork of https://github.com/bitnami/charts/tree/master/bitnami/kafka. It adds 3 new templates under templates/:

  • kafka-connect-elasticsearch-configmap.yaml
  • kafka-connect-svc.yaml
  • kafka-connect.yaml

The configmap is shown above. The kafka-connect.yaml Deployment looks like this:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "kafka.fullname" . }}-connect
  labels: {{- include "common.labels.standard" . | nindent 4 }}
    app.kubernetes.io/component: connector
spec:
  replicas: 1
  selector:
    matchLabels: {{- include "common.labels.matchLabels" . | nindent 6 }}
      app.kubernetes.io/component: connector
  template:
    metadata:
      labels: {{- include "common.labels.standard" . | nindent 8 }}
        app.kubernetes.io/component: connector
    spec:
      containers:
        - name: connect
          image: REDACTED.dkr.ecr.REDACTED.amazonaws.com/kafka-connect-elasticsearch
          imagePullPolicy: Always
          command:
            - /bin/bash
            - -ec
            - bin/connect-standalone.sh custom-config/connect-standalone-custom.properties custom-config/elasticsearch.properties
          ports:
            - name: connector
              containerPort: 8083
          volumeMounts:
            - name: configuration
              mountPath: /opt/bitnami/kafka/custom-config
      imagePullSecrets:
        - name: regcred
      volumes:
        - name: configuration
          configMap:
            name: {{ include "kafka.fullname" . }}-connect

How can I modify these Kafka Helm charts to allow them to retrieve the value for kubectl get secret -n elasticsearch elasticsearch-coordinating-only-crt -o jsonpath="{.data.ca\.crt}" | base64 -d and write its content to /etc/ssl/certs/elasticsearch-ca.crt ?


Solution

  • Got this working and learned a few things in the process:

    • Secret resources reside in a namespace. Secrets can only be referenced by Pods in that same namespace. (ref). Therefore, I switched to using a shared namespace for elasticsearch + kafka
    • The secret can be used in a straightforward way as documented at https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets. This is not a Helm-specific but rather core Kubernetes feature

    In my case this looked like:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: {{ include "kafka.fullname" . }}-connect
      labels: {{- include "common.labels.standard" . | nindent 4 }}
        app.kubernetes.io/component: connector
    spec:
      replicas: 1
      selector:
        matchLabels: {{- include "common.labels.matchLabels" . | nindent 6 }}
          app.kubernetes.io/component: connector
      template:
        metadata:
          labels: {{- include "common.labels.standard" . | nindent 8 }}
            app.kubernetes.io/component: connector
        spec:
          containers:
            - name: connect
              image: REDACTED.dkr.ecr.REDACTED.amazonaws.com/kafka-connect-elasticsearch
              imagePullPolicy: Always
              command:
                - /bin/bash
                - -ec
                - bin/connect-standalone.sh custom-config/connect-standalone-custom.properties custom-config/elasticsearch.properties
              ports:
                - name: connector
                  containerPort: 8083
              volumeMounts:
                - name: configuration
                  mountPath: /opt/bitnami/kafka/custom-config
                - name: ca
                  mountPath: /etc/ssl/certs
                  readOnly: true
          imagePullSecrets:
            - name: regcred
          volumes:
            - name: configuration
              configMap:
                name: {{ include "kafka.fullname" . }}-connect
            - name: ca
              secret:
                secretName: elasticsearch-coordinating-only-crt
    

    This gets the kafka-connect pod up and running, and I can validate the certs are written there also:

    $ kubectl exec -it -n elasticsearch kafka-connect-c4f4d7dbd-wbxfq \
        -- ls -1 /etc/ssl/certs
    
    ca.crt
    tls.crt
    tls.key