<p>I'm using GKE and Helm v3 and I'm trying to create/reserve a static IP address using ComputeAddress and then to create DNS A record with the previously reserved IP address.</p>
<p>Reserve IP address</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: compute.cnrm.cloud.google.com/v1beta1
kind: ComputeAddress
metadata:
  name: ip-address
  annotations:
    cnrm.cloud.google.com/project-id: project-id
spec:
  location: global
</code></pre>
<p>Get reserved IP address</p>
<pre><code>kubectl get computeaddress ip-address -o jsonpath='{.spec.address}'
</code></pre>
<p>Create DNS A record</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: dns.cnrm.cloud.google.com/v1beta1
kind: DNSRecordSet
metadata:
  name: dns-record-a
  annotations:
    cnrm.cloud.google.com/project-id: project-id
spec:
  name: &quot;{{ .Release.Name }}.example.com&quot;
  type: &quot;A&quot;
  ttl: 300
  managedZoneRef:
    external: example-com
  rrdatas:
    - **IP-ADDRESS-VALUE** &lt;----
</code></pre>
<p>Is there a way to reference the IP address value, created by ComputeAddress, in the DNSRecordSet resource?</p>
<p>Basically, I need something similar to the output values in Terraform.</p>
<p>Thanks!</p>

Milan Ilic
<p>It's interesting that something similar exists for GKE Ingress where we can reference reserved IP address and managed SSL certificate using annotations:</p>
<pre><code>annotations:
  kubernetes.io/ingress.global-static-ip-name: my-static-address
</code></pre>
<p>I have no idea why there is not something like this for DNSRecordSet resource. Hopefully, GKE will introduce it in the future.</p>
<p>Instead of running two commands, I've found a workaround by using Helm's hooks.</p>
<p>First, we need to define Job as <strong>post-install</strong> and <strong>post-upgrade</strong> hook which will pick up the reserved IP address when it becomes ready and then create appropriate DNSRecordSet resource with it. The script which retrieves the IP address, and manifest for DNSRecordSet are passed through ConfigMap and mounted to Pod.</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: batch/v1
kind: Job
metadata:
  name: &quot;{{ .Release.Name }}-dns-record-set-hook&quot;
  annotations:
    # This is what defines this resource as a hook. Without this line, the
    # job is considered part of the release.
    &quot;helm.sh/hook&quot;: post-install,post-upgrade
    &quot;helm.sh/hook-delete-policy&quot;: before-hook-creation,hook-succeeded
spec:
  template:
    metadata:
      name: &quot;{{ .Release.Name }}-dns-record-set-hook&quot;
    spec:
      restartPolicy: OnFailure
      containers:
        - name: post-install-job
          image: alpine:latest
          command:  ['sh', '-c', '/opt/run-kubectl-command-to-set-dns.sh']
          volumeMounts:
            - name: volume-dns-record-scripts
              mountPath: /opt
            - name: volume-writable
              mountPath: /mnt
      volumes:
        - name: volume-dns-record-scripts
          configMap:
            name: dns-record-scripts
            defaultMode: 0777
        - name: volume-writable
          emptyDir: {}
</code></pre>
<p>ConfigMap definition with the script and manifest file:</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: v1
kind: ConfigMap
metadata:
  creationTimestamp: null
  name: dns-record-scripts
data:
  run-kubectl-command-to-set-dns.sh: |-
    # install kubectl command
    apk add curl &amp;&amp; \
    curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.15.1/bin/linux/amd64/kubectl &amp;&amp; \
    chmod u+x kubectl &amp;&amp; \
    mv kubectl /bin/kubectl

    # wait for reserved IP address to be ready
    kubectl wait --for=condition=Ready computeaddress/ip-address

    # get reserved IP address
    IP_ADDRESS=$(kubectl get computeaddress ip-address -o jsonpath='{.spec.address}')

    echo &quot;Reserved address: $IP_ADDRESS&quot;
  
    # update IP_ADDRESS in manifest
    sed &quot;s/##IP_ADDRESS##/$IP_ADDRESS/g&quot; /opt/dns-record.yml &gt; /mnt/dns-record.yml
  
    # create DNS record
    kubectl apply -f /mnt/dns-record.yml

  dns-record.yml: |-
    apiVersion: dns.cnrm.cloud.google.com/v1beta1
    kind: DNSRecordSet
    metadata:
      name: dns-record-a
      annotations:
        cnrm.cloud.google.com/project-id: project-id
    spec:
      name: &quot;{{ .Release.Name }}.example.com&quot;
      type: A
      ttl: 300
      managedZoneRef:
        external: example-com
      rrdatas:
        - &quot;##IP_ADDRESS##&quot;
</code></pre>
<p>And, finally, for (default) Service Account to be able to retrieve the IP address and create/update DNSRecordSet, we need to assign some roles to it:</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: dnsrecord-setter
rules:
  - apiGroups: [&quot;compute.cnrm.cloud.google.com&quot;]
    resources: [&quot;computeaddresses&quot;]
    verbs: [&quot;get&quot;, &quot;list&quot;]
  - apiGroups: [&quot;dns.cnrm.cloud.google.com&quot;]
    resources: [&quot;dnsrecordsets&quot;]
    verbs: [&quot;get&quot;, &quot;create&quot;, &quot;patch&quot;]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: dnsrecord-setter
subjects:
  - kind: ServiceAccount
    name: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: dnsrecord-setter

</code></pre>
