<?xml version="1.0" encoding="UTF-8" ?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" version="2.0"><channel><title>Joseph Mckulka | CrunchyData Blog</title>
<atom:link href="https://www.crunchydata.com/blog/author/joseph-mckulka/rss.xml" rel="self" type="application/rss+xml" />
<link>https://www.crunchydata.com/blog/author/joseph-mckulka</link>
<image><url>https://www.crunchydata.com/build/_assets/default.png-W4XGD4DB.webp</url>
<title>Joseph Mckulka | CrunchyData Blog</title>
<link>https://www.crunchydata.com/blog/author/joseph-mckulka</link>
<width>256</width>
<height>256</height></image>
<description>PostgreSQL experts from Crunchy Data share advice, performance tips, and guides on successfully running PostgreSQL and Kubernetes solutions</description>
<language>en-us</language>
<pubDate>Thu, 17 Nov 2022 10:00:00 EST</pubDate>
<dc:date>2022-11-17T15:00:00.000Z</dc:date>
<dc:language>en-us</dc:language>
<sy:updatePeriod>hourly</sy:updatePeriod>
<sy:updateFrequency>1</sy:updateFrequency>
<item><title><![CDATA[ Multi-Cloud Strategies with Crunchy Postgres for Kubernetes ]]></title>
<link>https://www.crunchydata.com/blog/multi-cloud-strategies-with-crunchy-postgres-for-kubernetes</link>
<description><![CDATA[ PGO now supports streaming replication between clusters which can be used for disaster recovery or cloud migration. Read about how to set up streaming replication in a declarative cloud-native way. This example includes code samples for setting up two clusters, one in EKS, and one in GKE. ]]></description>
<content:encoded><![CDATA[ <p><a href=https://www.crunchydata.com/products/crunchy-postgresql-for-kubernetes>Crunchy Postgres for Kubernetes</a> can be used for cross-datacenter streaming replication out of the box. With so many folks asking for cross-cloud / cross-datacenter replication, we wanted to give people a large explanation of how that works. For this post, we use streaming replication, and prioritize reducing latency and adding stability.<p>Cross-cloud streaming replication can be used:<ul><li>To enable multi-cloud disaster recovery<li>For moving clusters between cloud providers<li>For moving clusters between on-premises and cloud</ul><p>Given the power of this feature, we decided to incorporate streaming replication directly into <a href=https://access.crunchydata.com/documentation/postgres-operator/latest/quickstart/>PGO</a>. With the <a href=https://access.crunchydata.com/documentation/postgres-operator/5.2.0/releases/5.2.0/>5.2 release</a> this is easily configurable through the <code>postgrescluster</code> spec without the need for manual Postgres configuration to set up the streaming replication.<h2 id=setup-cloud-environments><a href=#setup-cloud-environments>Setup Cloud Environments</a></h2><p>In this sample scenario, we will create <code>postgresclusters</code> in both EKS and GKE clouds. EKS will be used as our primary environment, and GKE will be a standby. PGO will need to be deployed in EKS and GKE to create <code>postgresclusters</code> in both environments.<p>The standby database needs to connect directly to the primary database over the network. This means the primary environment (EKS) needs to be able to create services with an external IP. In this example, we are using the <code>LoadBalancer</code> service type, which is easily configurable through the <code>postgrescluster</code> spec.<p>Both <code>postgresclusters</code> will need copies of the same TLS certificates to allow replication. Please look at the <a href=https://access.crunchydata.com/documentation/postgres-operator/latest/tutorials/day-two/customize-cluster#customize-tls>custom TLS</a> section of our docs for guidance on creating custom cert secrets in the format that PGO expects. This will need to be done in both environments. In this example, we have copies of the <code>cluster-cert</code> and <code>replication-cert</code> secrets in both Kubernetes environments.<h2 id=create-clusters><a href=#create-clusters>Create Clusters</a></h2><p>Now that our cloud environments are configured, we can create the primary and standby clusters. First, we will create the primary cluster and allow it to startup. Then we will have to take note of the external IP that is created for the primary service on the cluster. After we have the IP, we can create our standby cluster.<h3 id=primary><a href=#primary>Primary</a></h3><p>For the primary, we create a <code>postgrescluster</code> with the following spec. We have defined the custom TLS certs that we created in both environments. We also specified that the service that exposes the PostgreSQL primary instance should have the type <code>LoadBalancer</code>.<pre><code class=language-yaml>apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PostgresCluster
metadata:
  name: primary
  namespace: postgres-operator
spec:
  service:
    type: LoadBalancer
  postgresVersion: 14
  customTLSSecret:
    name: cluster-cert
  customReplicationTLSSecret:
    name: replication-cert
  instances:
    - name: instance1
      replicas: 1
      dataVolumeClaimSpec:
        {
          accessModes: [ReadWriteOnce],
          resources: { requests: { storage: 1Gi } },
        }
  backups:
    pgbackrest:
      repos:
        - name: repo1
          volume:
            volumeClaimSpec:
              {
                accessModes: [ReadWriteOnce],
                resources: { requests: { storage: 1Gi } },
              }
</code></pre><p>After you create a <code>postgrescluster</code> with this spec, wait for an initial backup and the cluster to be ready. After that, your primary should be ready, and you can start setting up the standby. Before you switch to the GKE cluster, you will need the external IP from the <code>primary-ha</code> service.<pre><code class=language-bash>$ k get svc
NAME                TYPE           CLUSTER-IP       EXTERNAL-IP                                                               PORT(S)          AGE
primary-ha          LoadBalancer   10.100.4.48      a078e7d173f214d9ca0e7d122052aa5a-1097707392.us-east-1.elb.amazonaws.com   5432:30985/TCP
</code></pre><h3 id=standby><a href=#standby>Standby</a></h3><p>Now that we have the primary cluster, we can create our standby. Here we are using the <code>spec.standby</code> fields in the <code>PostgresCluster</code> spec. When filling out the standby spec, we have a few options. You can provide a <code>host</code>, a <code>repoName</code>, or both. In this scenario, we are using streaming replication and will need to provide a <code>host</code>. The <code>host</code> in the spec below is the external IP we copied from the primary-ha service.<pre><code class=language-yaml>apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PostgresCluster
metadata:
  name: standby
  namespace: postgres-operator
spec:
  standby:
    enabled: true
    host: a2eb494c1f05a414dafb62743c790ba1-2010516878.us-east-1.elb.amazonaws.com
  postgresVersion: 14
  customTLSSecret:
    name: cluster-cert
  customReplicationTLSSecret:
    name: replication-cert
  instances:
    - name: instance1
      replicas: 1
      dataVolumeClaimSpec:
        {
          accessModes: [ReadWriteOnce],
          resources: { requests: { storage: 1Gi } },
        }
  backups:
    pgbackrest:
      repos:
        - name: repo1
          volume:
            volumeClaimSpec:
              {
                accessModes: [ReadWriteOnce],
                resources: { requests: { storage: 1Gi } },
              }
</code></pre><p>The standby cluster will look slightly different from the primary. You can expect the standby to have instance pods (one for every replica defined in the spec) and a repo-host pod. One thing you will not see is an initial backup on the cluster.<p><img alt="multi-cloud streaming replication"loading=lazy src=https://imagedelivery.net/lPM0ntuwQfh8VQgJRu0mFg/f8f0b47d-6646-492e-2af3-d99692a4cf00/public><h2 id=verify-streaming-replication><a href=#verify-streaming-replication>Verify Streaming Replication</a></h2><p>Now that we have a standby using streaming replication, it is a good time to check that replication is configured correctly and working as expected. The first thing you should check is that any data you create is replicated over to the standby. The time this takes will depend on network latency and the size of the data. If you see data from your primary database, streaming replication is active, you are good to go.<p>If you have exec privileges in your Kubernetes cluster, there are a few commands you can use to verify data replication and streaming. In the following two commands, we exec into the standby database, check that the <code>walreciever</code> process is running, and check that we have a streaming status in <code>pg_stat_wal_receiver</code>.<pre><code class=language-bash>$ kubectl exec -it standby-instance1-bkbl-0 -c database -- bash
bash-4.4$ ps -U postgres -x | grep walreceiver
     95 ?        Ss     0:10 postgres: standby-ha: walreceiver streaming 0/A000000bash-4.4$ psql -c "select pid,status,sender_host from pg_stat_wal_receiver;"
bash-4.4$ psql -c "select pid,status,sender_host from pg_stat_wal_receiver;"
 pid |  status   |                               sender_host
-----+-----------+-------------------------------------------------------------------------
  95 | streaming | a078e7d173f214d9ca0e7d122052aa5a-1097707392.us-east-1.elb.amazonaws.com
(1 row
</code></pre><h2 id=promote-the-standby><a href=#promote-the-standby>Promote the standby</a></h2><p>Now that you can see your data being replicated from the primary to the standby, you are ready to promote the standby in a disaster scenario. This is done by updating the spec of the standby cluster so that <code>standby.enabled</code> is false or removing the standby section entirely.<pre><code class=language-yaml>apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PostgresCluster
metadata:
  name: standby
spec:
  standby:
    enabled: true
</code></pre><p>After you promote the standby, it will work as a fully functioning <code>postgrescluster</code> that you can backup, scale and use as you would expect. You can also use the new primary to create another standby cluster!<h2 id=conclusion><a href=#conclusion>Conclusion</a></h2><p>If you've been looking for a solution for streaming replication, you may have come across Brian Pace's article earlier this year on <a href=https://www.crunchydata.com/blog/streaming-replication-across-kubernetes-postgres-clusters>Streaming Replication using pgBackRest</a>. I'm excited that with PGO 5.2., this is even easier to setup. Streaming replication adds another tool into our operator to allow customers to find the <a href=https://access.crunchydata.com/documentation/postgres-operator/v5/tutorial/disaster-recovery/>disaster recovery solutions</a> to meet their needs. ]]></content:encoded>
<category><![CDATA[ Kubernetes ]]></category>
<author><![CDATA[ Joseph.Mckulka@crunchydata.com (Joseph Mckulka) ]]></author>
<dc:creator><![CDATA[ Joseph Mckulka ]]></dc:creator>
<guid isPermalink="false">8ac9a7c58a1ca2513c5fbda65eb5e8cfdac5ecc87bf78f919138e02454c0030c</guid>
<pubDate>Thu, 17 Nov 2022 10:00:00 EST</pubDate>
<dc:date>2022-11-17T15:00:00.000Z</dc:date>
<atom:updated>2022-11-17T15:00:00.000Z</atom:updated></item></channel></rss>