Creating Azure PostgreSQL Instances manually using kubectl (experimental)

This topic describes how to use Services Toolkit to allow Tanzu Application Platform workloads to consume Azure Flexible Server PostgreSQL. This particular topic makes use of Azure Service Operator v2 to manage PostgreSQL instances in Azure.

Create a resource group

First of all, a ResourceGroup for all PSQL Instances to reside in will be created:

cat <<EOF | kubectl apply -f -
---
apiVersion: resources.azure.com/v1beta20200601
kind: ResourceGroup
metadata:
  name: aso-psql
spec:
  location: centralus
EOF

Create a Flexible Server service instance

Next, you will create a Flexible Server PSQL Instance, a Database and a Firewall Rule in Azure as well as a Secret for credentials. In this guide you will leverage the Password API from Carvel’s secretgen controller, which will create the Secrets for you. However, any other mechanism to manage those secrets works too.

Change the .spec.azureName of the FlexibleServer resource below from “aso-psql” to something unique, using only lowercase letters, digits and hyphens. This avoids naming conflicts as Azure has a global naming namespace and this resource may already exist.

cat <<'EOF' | kubectl apply -f -
---
apiVersion: secretgen.k14s.io/v1alpha1
kind: Password
metadata:
  name: aso-psql
spec:
  length: 64
  secretTemplate:
    type: Opaque
    stringData:
      password: $(value)
---
apiVersion: dbforpostgresql.azure.com/v1beta20210601
kind: FlexibleServersDatabase
metadata:
  name: aso-psql
spec:
  azureName: mydb
  owner:
    name: aso-psql
  charset: utf8
---
apiVersion: dbforpostgresql.azure.com/v1beta20210601
kind: FlexibleServersFirewallRule
metadata:
  name: aso-psql
spec:
  owner:
    name: aso-psql
  startIpAddress: 0.0.0.0 #! only allow traffic from azure. See https://docs.microsoft.com/en-us/azure/postgresql/single-server/concepts-firewall-rules#connecting-from-azure. Warning not for production use.
  endIpAddress: 0.0.0.0
---
apiVersion: dbforpostgresql.azure.com/v1beta20210601
kind: FlexibleServer
metadata:
  name: aso-psql
spec:
  location: centralus
  azureName: aso-psql #! CHANGE THIS NAME
  owner:
    name: aso-psql #! the ResourceGroup above
  version: "13" #! only 11,12,13 supported
  sku:
    name: Standard_D4s_v3
    tier: GeneralPurpose
  administratorLogin: myAdmin
  administratorLoginPassword:
    name: aso-psql
    key: password
  storage:
    storageSizeGB: 128
EOF

Create a Binding Specification Compatible Secret

As mentioned in Creating service instances that are compatible with Tanzu Application Platform, in order for Tanzu Application Platform workloads to be able to claim and bind to services such as Azure PostgreSQL, a resource compatible with Service Binding Specification must exist in the cluster. This can take the form of either a ProvisionedService, as defined by the specification, or a Kubernetes Secret with some known keys, also as defined in the specification.

In this guide, you create a Kubernetes secret in the necessary format using the secretgen-controller tooling. You do so by using the SecretTemplate API to extract values from the Azure Service Operator resources and populate a new spec-compatible secret with the values.

Create a ServiceAccount for Secret Templating

As part of using the SecretTemplate API, a Kubernetes ServiceAccount must be provided. The ServiceAccount is used for reading the FlexibleServer resource and the Secret created from the Password resource above.

Create the following Kubernetes resources on your AKS cluster:

cat <<EOF | kubectl apply -f -
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: aso-psql-reader
  namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: aso-psql-reading
  namespace: default
rules:
- apiGroups:
  - ""
  resources:
  - secrets
  verbs:
  - get
  - list
  - watch
  resourceNames:
  - aso-psql
- apiGroups:
  - dbforpostgresql.azure.com
  resources:
  - flexibleservers
  - flexibleserversdatabases
  verbs:
  - get
  - list
  - watch
  resourceNames:
  - aso-psql
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: aso-psql-reader-to-read
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: aso-psql-reading
subjects:
- kind: ServiceAccount
  name: aso-psql-reader
  namespace: default
EOF

Create a SecretTemplate

In combination with the ServiceAccount just created, a SecretTemplate can be used to declaratively create a secret that is compatible with the service binding specification. For more information on this API see the Secret Template Documentation.

Create the following Kubernetes resources on your AKS cluster:

cat <<'EOF' | kubectl apply -f -
---
apiVersion: secretgen.carvel.dev/v1alpha1
kind: SecretTemplate
metadata:
  name: aso-psql-bindable
  namespace: default
spec:
  serviceAccountName: aso-psql-reader
  inputResources:
  - name: server
    ref:
      apiVersion: dbforpostgresql.azure.com/v1alpha1api20210601
      kind: FlexibleServer
      name: aso-psql
  - name: db
    ref:
      apiVersion: dbforpostgresql.azure.com/v1alpha1api20210601
      kind: FlexibleServersDatabase
      name: aso-psql
  - name: creds
    ref:
      apiVersion: v1
      kind: Secret     
      name: "$(.server.spec.administratorLoginPassword.name)"
  template:
    metadata:
      labels:
        app.kubernetes.io/component: aso-psql
        app.kubernetes.io/instance: "$(.server.metadata.name)"
        services.apps.tanzu.vmware.com/class: azure-postgres
    type: postgresql
    stringData:
      type: postgresql
      port: "5432"
      database: "$(.db.status.name)"
      host: "$(.server.status.fullyQualifiedDomainName)"
      username: "$(.server.status.administratorLogin)"
    data:
      password: "$(.creds.data.password)"
EOF

Verify the Service Instance

Firstly wait until the PostgreSQL instance is ready. This may take 5 to 10 minutes.

kubectl wait flexibleservers.dbforpostgresql.azure.com aso-psql -n default --for=condition=Ready --timeout=5m

Next, ensure a bindable Secret was produced by the SecretTemplate. To do so, run:

kubectl wait SecretTemplate -n default aso-psql-bindable --for=condition=ReconcileSucceeded --timeout=5m

kubectl get Secret -n default aso-psql-bindable
check-circle-line exclamation-circle-line close-line
Scroll to top icon