{"id":95322,"date":"2020-09-28T07:42:39","date_gmt":"2020-09-28T05:42:39","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/kratkij-obzor-operatorov-postgresql-dlya-kubernetes-nash-vybor-i-opyt"},"modified":"2020-09-28T07:42:39","modified_gmt":"2020-09-28T05:42:39","slug":"kratkij-obzor-operatorov-postgresql-dlya-kubernetes-nash-vybor-i-opyt","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/kratkij-obzor-operatorov-postgresql-dlya-kubernetes-nash-vybor-i-opyt","title":{"rendered":"Vis\u00e3o geral dos operadores PostgreSQL para Kubernetes, nossa escolha e experi\u00eancia","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Vis\u00e3o geral dos operadores PostgreSQL para Kubernetes, nossa escolha e experi\u00eancia\" src=\"\/wp-content\/uploads\/2020\/09\/23b2db49941fa5bd5000358c8ffb991b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCada vez mais, recebemos solicita\u00e7\u00f5es dos clientes como: \"Queremos algo como o Amazon RDS, mas mais barato\"; \"Queremos algo como o RDS, mas em qualquer infraestrutura\". Para realizar uma solu\u00e7\u00e3o gerenciada semelhante no Kubernetes, analisamos o estado atual dos operadores mais populares para PostgreSQL (Stolon, operadores da Crunchy Data e da Zalando) e fizemos nossa escolha.<\/p>\n<p>Este artigo \u00e9 nossa experi\u00eancia adquirida tanto do ponto de vista te\u00f3rico (revis\u00e3o de solu\u00e7\u00f5es) quanto do lado pr\u00e1tico (o que foi escolhido e o que resultou disso). Mas, antes de tudo, vamos definir quais s\u00e3o os requisitos para uma poss\u00edvel substitui\u00e7\u00e3o do RDS...<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>O que \u00e9 o RDS?<\/h2>\n<p>\nQuando as pessoas falam sobre RDS, pela nossa experi\u00eancia, elas se referem a um servi\u00e7o gerenciado (managed) de SGBD que:<\/p>\n<ol>\n<li>\u00e9 f\u00e1cil de configurar;<\/li>\n<li>tem a capacidade de trabalhar com snapshots e se recuperar deles (preferencialmente com suporte a <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Point-in-time_recovery\">PITR<\/a><\/noindex>);<\/li>\n<li>permite criar topologias master-slave;<\/li>\n<li>tem uma lista rica de extens\u00f5es;<\/li>\n<li>oferece auditoria e gest\u00e3o de usu\u00e1rios\/acessos.<\/li>\n<\/ol>\n<p>\nDe maneira geral, as abordagens para a implementa\u00e7\u00e3o da tarefa proposta podem ser bastante variadas, no entanto, o caminho com o condicional Ansible n\u00e3o nos agrada. (Os colegas da 2GIS chegaram a uma conclus\u00e3o semelhante ap\u00f3s <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/509926\/\">sua tentativa<\/a><\/noindex> de criar \"uma ferramenta para a r\u00e1pida implanta\u00e7\u00e3o de um cluster tolerante a falhas baseado em Postgres\".)<\/p>\n<p>Os operadores s\u00e3o a abordagem amplamente aceita para resolver tarefas semelhantes no ecossistema Kubernetes. Mais detalhes sobre eles em rela\u00e7\u00e3o a bancos de dados executados dentro do Kubernetes j\u00e1 foram abordados pelo diretor t\u00e9cnico da \"Flanta\", <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/users\/distol\/\" class=\"user_link\">distol<\/a><\/noindex>, neste teste de 2015 <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/431500\/\">em uma de suas apresenta\u00e7\u00f5es<\/a><\/noindex>.<\/p>\n<p><i><strong>NB<\/strong><\/i><i>: Para a cria\u00e7\u00e3o r\u00e1pida de operadores simples, recomendamos prestar aten\u00e7\u00e3o \u00e0 nossa ferramenta Open Source <\/i><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/shell-operator\"><i>shell-operator<\/i><\/a><\/noindex><i>. Usando-a, \u00e9 poss\u00edvel fazer isso sem conhecimento de Go, utilizando m\u00e9todos mais familiares para administradores de sistema: em Bash, Python, etc.<\/i><\/p>\n<p>Existem v\u00e1rios operadores populares para K8s no PostgreSQL:<\/p>\n<ul>\n<li>Stolon;<\/li>\n<li>Crunchy Data PostgreSQL Operator;<\/li>\n<li>Zalando Postgres Operator.<\/li>\n<\/ul>\n<p>\nVamos analis\u00e1-los mais de perto.<\/p>\n<h2>Escolha do operador<\/h2>\n<p>\nAl\u00e9m das importantes funcionalidades j\u00e1 mencionadas, n\u00f3s \u2014 como engenheiros de opera\u00e7\u00e3o de infraestrutura no Kubernetes \u2014 tamb\u00e9m esper\u00e1vamos dos operadores o seguinte:<\/p>\n<ul>\n<li> deploy a partir do Git e com <noindex><a rel=\"nofollow\" href=\"https:\/\/kubernetes.io\/docs\/concepts\/extend-kubernetes\/operator\/#deploying-operators\">Custom Resources<\/a><\/noindex>;<\/li>\n<li> suporte \u00e0 anti-affinity de pods;<\/li>\n<li> instala\u00e7\u00e3o de node affinity ou node selector;<\/li>\n<li> instala\u00e7\u00e3o de tolerances;<\/li>\n<li> possibilidade de tunning;<\/li>\n<li> tecnologias compreens\u00edveis e at\u00e9 mesmo comandos.<\/li>\n<\/ul>\n<p>\nSem entrar em detalhes sobre cada um dos pontos (perguntem nos coment\u00e1rios se houver d\u00favidas ap\u00f3s a leitura de todo o artigo), gostaria de ressaltar que esses par\u00e2metros s\u00e3o necess\u00e1rios para uma descri\u00e7\u00e3o mais precisa da especializa\u00e7\u00e3o dos n\u00f3s do cluster, permitindo que sejam encomendados de acordo com aplica\u00e7\u00f5es espec\u00edficas. Assim, podemos alcan\u00e7ar um equil\u00edbrio ideal entre desempenho e custo.<\/p>\n<p>Agora, vamos aos operadores do PostgreSQL.<\/p>\n<h3>1. Stolon<\/h3>\n<p>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/sorintlab\/stolon\">Stolon<\/a><\/noindex> da empresa italiana Sorint.lab em <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/431500\/\">no j\u00e1 mencionado relat\u00f3rio<\/a><\/noindex> foi considerado um padr\u00e3o entre os operadores para SGBDs. \u00c9 um projeto bastante antigo: seu primeiro lan\u00e7amento p\u00fablico ocorreu em novembro de 2015(!), e o reposit\u00f3rio do GitHub pode se orgulhar de quase 3000 estrelas e mais de 40 contribuidores.<\/p>\n<p>E realmente, o Stolon \u00e9 um excelente exemplo de uma arquitetura bem pensada:<\/p>\n<p><img decoding=\"async\" alt=\"Vis\u00e3o geral dos operadores PostgreSQL para Kubernetes, nossa escolha e experi\u00eancia\" src=\"\/wp-content\/uploads\/2020\/09\/a34625c130bfd29c5645cf2417042de2.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nOs detalhes sobre este operador podem ser encontrados no relat\u00f3rio ou <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/sorintlab\/stolon\/blob\/master\/doc\/architecture.md\">documenta\u00e7\u00e3o do projeto<\/a><\/noindex>. De modo geral, pode-se dizer que ele realiza tudo o que foi descrito: failover, proxy para acesso transparente dos clientes, backups... E o proxy fornece acesso atrav\u00e9s de um \u00fanico endpoint de servi\u00e7o \u2014 ao contr\u00e1rio das outras duas solu\u00e7\u00f5es que ser\u00e3o discutidas a seguir (as quais t\u00eam dois servi\u00e7os para acesso ao banco).<\/p>\n<p>No entanto, o Stolon <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/sorintlab\/stolon\/issues\/463#issuecomment-379666733\">n\u00e3o possui Recursos Customizados<\/a><\/noindex>, o que impossibilita sua implementa\u00e7\u00e3o de uma maneira simples e r\u00e1pida \u2014 \"como p\u00e3ezinhos quentes\" \u2014 para criar inst\u00e2ncias de SGBD no Kubernetes. A gest\u00e3o \u00e9 feita atrav\u00e9s da utilidade <code>stolonctl<\/code>, a implanta\u00e7\u00e3o \u2014 atrav\u00e9s do Helm chart, e os usu\u00e1rios definem as configura\u00e7\u00f5es no ConfigMap.<\/p>\n<p>Por um lado, parece que o operador n\u00e3o \u00e9 realmente um operador (j\u00e1 que n\u00e3o utiliza CRD). Mas, por outro lado, \u00e9 um sistema flex\u00edvel que permite configurar recursos no K8s de acordo com suas necessidades.<\/p>\n<p>Resumindo, para n\u00f3s, n\u00e3o parecia ideal criar um chart separado para cada banco de dados. Portanto, come\u00e7amos a procurar alternativas.<\/p>\n<h3>2. Crunchy Data PostgreSQL Operator<\/h3>\n<p>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/CrunchyData\/postgres-operator\">O operador da Crunchy Data<\/a><\/noindex>, uma jovem startup americana, parecia uma alternativa l\u00f3gica. Sua hist\u00f3ria p\u00fablica come\u00e7a com o primeiro lan\u00e7amento em mar\u00e7o de 2017, desde ent\u00e3o o reposit\u00f3rio do GitHub recebeu pouco menos de 1300 estrelas e mais de 50 contribuidores. O \u00faltimo lan\u00e7amento de setembro foi testado para funcionar com Kubernetes 1.15\u20141.18, OpenShift 3.11+ e 4.4+, GKE e VMware Enterprise PKS 1.3+.<\/p>\n<p>A arquitetura do Crunchy Data PostgreSQL Operator tamb\u00e9m atende aos requisitos declarados:<\/p>\n<p><img decoding=\"async\" alt=\"Vis\u00e3o geral dos operadores PostgreSQL para Kubernetes, nossa escolha e experi\u00eancia\" src=\"\/wp-content\/uploads\/2020\/09\/343cd0494abae42fcf5b47c5bb4eb310.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nA gest\u00e3o ocorre atrav\u00e9s da utilidade <code>pgo<\/code>, no entanto, ele por sua vez gera Recursos Personalizados para Kubernetes. Portanto, n\u00f3s, como potenciais usu\u00e1rios, ficamos satisfeitos com o operador:<\/p>\n<ul>\n<li> h\u00e1 gerenciamento via CRD;<\/li>\n<li> gerenciamento conveniente de usu\u00e1rios (tamb\u00e9m via CRD);<\/li>\n<li> integra\u00e7\u00e3o com outros componentes <noindex><a rel=\"nofollow\" href=\"https:\/\/access.crunchydata.com\/documentation\/crunchy-postgres-containers\/4.3.1\/\">Crunchy Data Container Suite<\/a><\/noindex> \u2014 uma cole\u00e7\u00e3o especializada de imagens de cont\u00eaineres para PostgreSQL e utilit\u00e1rios para trabalhar com ela (incluindo pgBackRest, pgAudit, extens\u00f5es do contrib, etc.).<\/li>\n<\/ul>\n<p>\nNo entanto, as tentativas de come\u00e7ar a usar o operador da Crunchy Data revelaram alguns problemas:<\/p>\n<ul>\n<li>N\u00e3o havia possibilidade de toler\u00e2ncias \u2014 apenas o nodeSelector estava dispon\u00edvel.<\/li>\n<li>Os pods criados faziam parte do Deployment, mesmo que estiv\u00e9ssemos implantando uma aplica\u00e7\u00e3o stateful. Ao contr\u00e1rio do StatefulSet, os Deployments n\u00e3o conseguem criar discos.<\/li>\n<\/ul>\n<p>\nEssa \u00faltima desvantagem leva a momentos curiosos: no ambiente de teste, foi poss\u00edvel iniciar 3 r\u00e9plicas com um \u00fanico disco <i>armazenamento local<\/i>, resultando em o operador relatar que 3 r\u00e9plicas estavam em funcionamento (embora isso n\u00e3o fosse verdade).<\/p>\n<p>Outra caracter\u00edstica deste operador \u00e9 sua integra\u00e7\u00e3o pronta com v\u00e1rios sistemas auxiliares. Por exemplo, \u00e9 f\u00e1cil instalar o pgAdmin e o pgBounce, enquanto <noindex><a rel=\"nofollow\" href=\"https:\/\/access.crunchydata.com\/documentation\/postgres-operator\/4.4.0\/installation\/other\/ansible\/installing-metrics\/\">documenta\u00e7\u00e3o<\/a><\/noindex> a pr\u00e9-configura\u00e7\u00e3o do Grafana e Prometheus est\u00e1 sendo considerada. No recente <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/CrunchyData\/postgres-operator\/releases\/tag\/v4.5.0-beta.1\">lan\u00e7amento 4.5.0-beta1<\/a><\/noindex> destaca-se a melhoria na integra\u00e7\u00e3o com o projeto <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/CrunchyData\/pgmonitor\">pgMonitor<\/a><\/noindex>, permitindo que o operador ofere\u00e7a uma visualiza\u00e7\u00e3o clara das m\u00e9tricas PgSQL \"out of the box\".<\/p>\n<p>No entanto, a escolha estranha dos recursos do Kubernetes gerados nos levou \u00e0 necessidade de encontrar outra solu\u00e7\u00e3o.<\/p>\n<h3>3. Zalando Postgres Operator<\/h3>\n<p>\nOs produtos Zalando s\u00e3o conhecidos por n\u00f3s h\u00e1 muito tempo: temos experi\u00eancia com o Zalenium e, claro, tentamos <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/patroni\">Patroni<\/a><\/noindex> \u2014 sua popular solu\u00e7\u00e3o HA para PostgreSQL. Sobre a abordagem da empresa para criar o <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/postgres-operator\">Postgres Operator<\/a><\/noindex> falou um de seus autores \u2014 Alexey Klyukin \u2014 no ar <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/479438\/\">Postgres Tuesday n\u00ba 5<\/a><\/noindex>, e n\u00f3s gostamos.<\/p>\n<p>Esta \u00e9 a solu\u00e7\u00e3o mais recente entre as consideradas no artigo: o primeiro lan\u00e7amento ocorreu em agosto de 2018. No entanto, mesmo com um n\u00famero relativamente pequeno de lan\u00e7amentos formais, o projeto percorreu um longo caminho, j\u00e1 superando em popularidade a solu\u00e7\u00e3o da Crunchy Data com mais de 1300 estrelas no GitHub e o maior n\u00famero de colaboradores (70+).<\/p>\n<p>\"Por baixo do cap\u00f4\" deste operador, s\u00e3o usadas solu\u00e7\u00f5es testadas pelo tempo:<\/p>\n<ul>\n<li> Patroni e <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/spilo\">Spilo<\/a><\/noindex> para gerenciamento,<\/li>\n<li> <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/wal-e\/wal-e\">WAL-E<\/a><\/noindex> \u2014 para backups,<\/li>\n<li> <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/pgbouncer\/pgbouncer\">PgBouncer<\/a><\/noindex> \u2014 como pool de conex\u00f5es.<\/li>\n<\/ul>\n<p>\nVeja como a arquitetura do operador da Zalando \u00e9 apresentada:<\/p>\n<p><img decoding=\"async\" alt=\"Vis\u00e3o geral dos operadores PostgreSQL para Kubernetes, nossa escolha e experi\u00eancia\" src=\"\/wp-content\/uploads\/2020\/09\/c66f10c1a818592ecaacd2db4ce5ace5.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nO operador \u00e9 completamente gerenciado por meio de Recursos Personalizados, cria automaticamente um StatefulSet a partir de cont\u00eaineres, que podem ser personalizados adicionando diferentes sidecars ao pod. Tudo isso \u00e9 uma vantagem significativa em compara\u00e7\u00e3o com o operador da Crunchy Data.<\/p>\n<p>Uma vez que escolhamos a solu\u00e7\u00e3o da Zalando entre as 3 op\u00e7\u00f5es consideradas, a descri\u00e7\u00e3o de suas funcionalidades ser\u00e1 apresentada abaixo, junto com a pr\u00e1tica de aplica\u00e7\u00e3o.<\/p>\n<h2>Pr\u00e1tica com o Postgres Operator da Zalando<\/h2>\n<p>\nO deploy do operador \u00e9 muito simples: basta baixar a vers\u00e3o mais recente do GitHub e aplicar os arquivos YAML do diret\u00f3rio <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/postgres-operator\/tree\/master\/manifests\">manifests<\/a><\/noindex>. Como alternativa, voc\u00ea tamb\u00e9m pode usar <noindex><a rel=\"nofollow\" href=\"https:\/\/operatorhub.io\/operator\/postgres-operator\">OperatorHub<\/a><\/noindex>.<\/p>\n<p>Ap\u00f3s a instala\u00e7\u00e3o, \u00e9 necess\u00e1rio configurar <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/postgres-operator\/blob\/master\/docs\/reference\/operator_parameters.md#aws-or-gcp-interaction\">armazenamentos para logs e backups<\/a><\/noindex>. A configura\u00e7\u00e3o \u00e9 feita atrav\u00e9s do ConfigMap <code>postgres-operator<\/code> no namespace onde voc\u00ea instalou o operador. Quando os armazenamentos est\u00e3o configurados, \u00e9 poss\u00edvel implantar o primeiro cluster PostgreSQL.<\/p>\n<p>Por exemplo, o deploy padr\u00e3o que temos \u00e9 o seguinte:<\/p>\n<pre><code class=\"plaintext\">apiVersion: acid.zalan.do\/v1\nkind: postgresql\nmetadata:\n name: staging-db\nspec:\n numberOfInstances: 3\n patroni:\n   synchronous_mode: true\n postgresql:\n   version: \"12\"\n resources:\n   limits:\n     cpu: 100m\n     memory: 1Gi\n   requests:\n     cpu: 100m\n     memory: 1Gi\n sidecars:\n - env:\n   - name: DATA_SOURCE_URI\n     value: 127.0.0.1:5432\n   - name: DATA_SOURCE_PASS\n     valueFrom:\n       secretKeyRef:\n         key: password\n         name: postgres.staging-db.credentials\n   - name: DATA_SOURCE_USER\n     value: postgres\n   image: wrouesnel\/postgres_exporter\n   name: prometheus-exporter\n   resources:\n     limits:\n       cpu: 500m\n       memory: 100Mi\n     requests:\n       cpu: 100m\n       memory: 100Mi\n teamId: staging\n volume:\n   size: 2Gi\n<\/code><\/pre>\n<p>\nEste manifesto implanta um cluster de 3 inst\u00e2ncias com sidecar na forma de <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/wrouesnel\/postgres_exporter\">postgres_exporter<\/a><\/noindex>, do qual coletamos m\u00e9tricas da aplica\u00e7\u00e3o. Como voc\u00ea pode ver, tudo \u00e9 muito simples, e se desejar, \u00e9 poss\u00edvel criar virtualmente um n\u00famero ilimitado de clusters.<\/p>\n<p>Vale a pena prestar aten\u00e7\u00e3o tamb\u00e9m na <b>interface da web para administra\u00e7\u00e3o<\/b> \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/postgres-operator\/blob\/master\/docs\/operator-ui.md\">postgres-operator-ui<\/a><\/noindex>. Ela \u00e9 fornecida junto com o operador e permite criar e excluir clusters, al\u00e9m de trabalhar com os backups que o operador gera.<\/p>\n<p><img decoding=\"async\" alt=\"Vis\u00e3o geral dos operadores PostgreSQL para Kubernetes, nossa escolha e experi\u00eancia\" src=\"\/wp-content\/uploads\/2020\/09\/2e9ae033a9817d101c843ce061aafdb5.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Lista de clusters PostgreSQL<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Vis\u00e3o geral dos operadores PostgreSQL para Kubernetes, nossa escolha e experi\u00eancia\" src=\"\/wp-content\/uploads\/2020\/09\/74a65f7f301da14a0cb7bea6d5ef84ec.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Gerenciamento de backups<\/i><\/p>\n<p>Outra caracter\u00edstica interessante \u00e9 o suporte ao <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/postgres-operator\/blob\/master\/docs\/user.md#teams-api-roles\">Teams API<\/a><\/noindex>. Este mecanismo cria automaticamente <b>fun\u00e7\u00f5es no PostgreSQL<\/b>, com base na lista de nomes de usu\u00e1rios recebida. Depois disso, a API permite retornar a lista de usu\u00e1rios para os quais as fun\u00e7\u00f5es s\u00e3o criadas automaticamente.<\/p>\n<h3>Problemas e suas solu\u00e7\u00f5es<\/h3>\n<p>\nEntretanto, o uso do operador logo revelou algumas desvantagens significativas:<\/p>\n<ol>\n<li> a falta de suporte ao nodeSelector;<\/li>\n<li> impossibilidade de desativar backups;<\/li>\n<li> ao usar a fun\u00e7\u00e3o de cria\u00e7\u00e3o de bancos, as permiss\u00f5es padr\u00e3o n\u00e3o aparecem;<\/li>\n<li> periodicamente falta documenta\u00e7\u00e3o ou ela est\u00e1 desatualizada.<\/li>\n<\/ol>\n<p>\nFelizmente, muitos desses problemas podem ser resolvidos. Vamos come\u00e7ar pelo fim \u2014 problemas com <strong>documenta\u00e7\u00e3o<\/strong>. <\/p>\n<p>\u00c9 prov\u00e1vel que voc\u00ea se depare com a dificuldade de entender como configurar backups e como conectar o bucket de backup \u00e0 interface do Operator. Isso \u00e9 mencionado brevemente na documenta\u00e7\u00e3o, enquanto a descri\u00e7\u00e3o real est\u00e1 em <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/postgres-operator\/pull\/481\">PR<\/a><\/noindex>:<\/p>\n<ol>\n<li>\u00e9 necess\u00e1rio criar um segredo;<\/li>\n<li>pass\u00e1-lo ao operador como par\u00e2metro <code>pod_environment_secret_name<\/code> no CRD com as configura\u00e7\u00f5es do operador ou no ConfigMap (depende de como voc\u00ea decidiu instalar o operador).<\/li>\n<\/ol>\n<p>\nNo entanto, como se descobriu, atualmente isso n\u00e3o \u00e9 poss\u00edvel. \u00c9 por isso que reunimos <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/postgres-operator\">nossa vers\u00e3o do operador<\/a><\/noindex> com algumas contribui\u00e7\u00f5es adicionais de terceiros. Mais detalhes sobre isso - veja abaixo.<\/p>\n<p>Se voc\u00ea passar par\u00e2metros para o operador para o backup, nomeadamente \u2014 <code>wal_s3_bucket<\/code> e as chaves de acesso no AWS S3, ent\u00e3o ele <strong>far\u00e1 backup de tudo<\/strong>: n\u00e3o apenas de bancos em produ\u00e7\u00e3o, mas tamb\u00e9m de staging. Isso n\u00e3o nos agradou.<\/p>\n<p>Na descri\u00e7\u00e3o dos par\u00e2metros do Spilo, que \u00e9 a camada Docker b\u00e1sica para PgSQL ao usar o operador, descobriu-se que voc\u00ea pode passar o par\u00e2metro <code>WAL_S3_BUCKET<\/code> vazio, desativando assim os backups. Al\u00e9m disso, para nossa grande alegria, foi encontrado um <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/postgres-operator\/pull\/908\">PR pronto<\/a><\/noindex>, que aceitamos imediatamente em nosso fork. Agora \u00e9 suficiente apenas adicionar <code>enableWALArchiving: false<\/code> ao recurso do cluster PostgreSQL.<\/p>\n<p>Sim, havia a possibilidade de fazer isso de outra forma, executando 2 operadores: um para staging (sem backups) e outro - para produ\u00e7\u00e3o. Mas assim conseguimos nos sair bem com um s\u00f3.<\/p>\n<p>Ok, n\u00f3s aprendemos a conceder acesso ao S3 nos bancos e os backups come\u00e7aram a ser enviados para o armazenamento. Como ativar as p\u00e1ginas de backups na interface do Operator?<\/p>\n<p><img decoding=\"async\" alt=\"Vis\u00e3o geral dos operadores PostgreSQL para Kubernetes, nossa escolha e experi\u00eancia\" src=\"\/wp-content\/uploads\/2020\/09\/46169b53707b0bbb686798c655022f40.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNa interface do Operator, voc\u00ea precisar\u00e1 adicionar 3 vari\u00e1veis:<\/p>\n<ul>\n<li> <code>SPILO_S3_BACKUP_BUCKET<\/code><\/li>\n<li> <code>AWS_ACCESS_KEY_ID<\/code><\/li>\n<li> <code>AWS_SECRET_ACCESS_KEY<\/code><\/li>\n<\/ul>\n<p>\nDepois disso, a gest\u00e3o dos backups estar\u00e1 dispon\u00edvel, o que no nosso caso simplificar\u00e1 o trabalho com staging, permitindo enviar c\u00f3pias da produ\u00e7\u00e3o sem scripts adicionais.<\/p>\n<p>Como um ponto adicional, mencionou-se o trabalho com a API Teams e as amplas possibilidades de cria\u00e7\u00e3o de bancos e fun\u00e7\u00f5es por meio do operador. No entanto, os <strong>pap\u00e9is criados n\u00e3o tinham permiss\u00f5es padr\u00e3o.<\/strong>Consequentemente, o usu\u00e1rio com permiss\u00f5es de leitura n\u00e3o conseguia acessar novas tabelas.<\/p>\n<p>Por que isso? Apesar de que no c\u00f3digo <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/postgres-operator\/blob\/master\/pkg\/cluster\/database.go#L42\">tem<\/a><\/noindex> necess\u00e1rio <code>GRANT<\/code>, eles n\u00e3o s\u00e3o aplicados sempre. Existem 2 m\u00e9todos: <code>syncPreparedDatabases<\/code> e <code>syncDatabases<\/code>. No <code>syncPreparedDatabases<\/code> \u2014 apesar de a se\u00e7\u00e3o <code>preparedDatabases<\/code> <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/postgres-operator\/blob\/master\/manifests\/complete-postgres-manifest.yaml#L26\">tem<\/a><\/noindex> ter uma condi\u00e7\u00e3o <code>defaultRoles<\/code> e <code>defaultUsers<\/code> para criar fun\u00e7\u00f5es, \u2014 as permiss\u00f5es padr\u00e3o n\u00e3o s\u00e3o aplicadas. Estamos preparando um patch para que essas permiss\u00f5es sejam aplicadas automaticamente.<\/p>\n<p>E o \u00faltimo ponto nas melhorias relevantes para n\u00f3s \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/postgres-operator\/pull\/975\">patch<\/a><\/noindex>, adicionando Node Affinity no StatefulSet criado. Nossos clientes frequentemente preferem reduzir custos usando inst\u00e2ncias spot, e claramente n\u00e3o \u00e9 prudente hospedar servi\u00e7os de banco de dados nelas. Essa quest\u00e3o poderia ser resolvida atrav\u00e9s de tolera\u00e7\u00f5es, mas a presen\u00e7a de Node Affinity proporciona maior seguran\u00e7a.<\/p>\n<h3>O que conseguimos?<\/h3>\n<p>\nComo resultado da resolu\u00e7\u00e3o dos problemas mencionados, n\u00f3s bifurcamos o Postgres Operator da Zalando para <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/postgres-operator\">o nosso reposit\u00f3rio<\/a><\/noindex>, onde ele \u00e9 constru\u00eddo com patches t\u00e3o \u00fateis. E para maior conveni\u00eancia, tamb\u00e9m <noindex><a rel=\"nofollow\" href=\"https:\/\/hub.docker.com\/r\/flant\/postgres-operator\">imagem Docker<\/a><\/noindex>.<\/p>\n<p>Lista de PRs aceitos na bifurca\u00e7\u00e3o:<\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/postgres-operator\/pull\/1066\">constru\u00e7\u00e3o de uma imagem leve e segura em Docker para o operador<\/a><\/noindex>;<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/postgres-operator\/pull\/908\">desativa\u00e7\u00e3o de backups<\/a><\/noindex>;<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/postgres-operator\/pull\/1121\">atualiza\u00e7\u00e3o das vers\u00f5es dos recursos para vers\u00f5es atuais do k8s<\/a><\/noindex>;<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/postgres-operator\/pull\/975\">implementa\u00e7\u00e3o de Node Affinity<\/a><\/noindex>.<\/li>\n<\/ul>\n<p>\nSeria \u00f3timo se a comunidade apoiasse esses PRs para que eles fossem inclu\u00eddos na upstream com a pr\u00f3xima vers\u00e3o do operador (1.6).<\/p>\n<h2>B\u00f4nus! Hist\u00f3ria de sucesso com a migra\u00e7\u00e3o de produ\u00e7\u00e3o<\/h2>\n<p>\nSe voc\u00ea usa o Patroni, pode migrar uma produ\u00e7\u00e3o ativa para o operador com um m\u00ednimo de tempo de inatividade.<\/p>\n<p>Spilo permite fazer clusters de standby atrav\u00e9s do armazenamento S3 com <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/wal-e\/wal-e\">Wal-E<\/a><\/noindex>, quando o log bin\u00e1rio do PgSQL \u00e9 primeiro salvo no S3 e depois extra\u00eddo pela r\u00e9plica. Mas o que fazer se voc\u00ea <i>n\u00e3o<\/i> est\u00e1 usando Wal-E em uma infraestrutura antiga? A solu\u00e7\u00e3o para esse problema j\u00e1 <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/true_engineering\/blog\/437318\/\">foi proposta<\/a><\/noindex> no Habr.<\/p>\n<p>A l\u00f3gica de replica\u00e7\u00e3o do PostgreSQL vem ao nosso socorro. No entanto, n\u00e3o vamos entrar em detalhes sobre como criar publica\u00e7\u00f5es e assinaturas, porque\u2026 nosso plano falhou.<\/p>\n<p>O problema \u00e9 que o banco de dados tinha v\u00e1rias tabelas sobrecarregadas com milh\u00f5es de linhas, que, al\u00e9m disso, eram constantemente preenchidas e deletadas. <noindex><a rel=\"nofollow\" href=\"https:\/\/postgrespro.ru\/docs\/postgrespro\/12\/sql-createsubscription\">A simples assinatura<\/a><\/noindex> com <code>copy_data<\/code>, em que uma nova r\u00e9plica copia todo o conte\u00fado do mestre, simplesmente n\u00e3o conseguia acompanhar o mestre. A c\u00f3pia do conte\u00fado funcionou por uma semana, mas n\u00e3o conseguiu alcan\u00e7ar o mestre. No final, conseguimos resolver o problema com a ajuda <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/avitotech\/recovery-use-cases-for-logical-replication-in-postgresql-10-a1e6bab03072\">artigo<\/a><\/noindex> de colegas da Avito: \u00e9 poss\u00edvel transferir dados usando <code>pg_dump<\/code>. Vou descrever nossa (um pouco aprimorada) vers\u00e3o desse algoritmo.<\/p>\n<p>A ideia \u00e9 criar uma assinatura desligada, ligada a um slot de replica\u00e7\u00e3o espec\u00edfico, e depois corrigir o n\u00famero da transa\u00e7\u00e3o. Replcas estavam dispon\u00edveis para o funcionamento da produ\u00e7\u00e3o. Isso \u00e9 importante, pois a r\u00e9plica ajudar\u00e1 a criar um dump consistente e continuar recebendo mudan\u00e7as do mestre.<\/p>\n<p>Nos comandos subsequentes que descrevem o processo de migra\u00e7\u00e3o, ser\u00e3o usados os seguintes termos para os hosts:<\/p>\n<ol>\n<li><i>master<\/i> \u2014 servidor de origem;<\/li>\n<li><i>replica1<\/i> \u2014 r\u00e9plica de streaming do antigo production;<\/li>\n<li><i>replica2<\/i> \u2014 nova r\u00e9plica l\u00f3gica.<\/li>\n<\/ol>\n<p><\/p>\n<h3>Plano de migra\u00e7\u00e3o<\/h3>\n<p>\n1. Vamos criar no mestre uma assinatura para todas as tabelas no esquema <code>public<\/code> do banco <code>dbname<\/code>:<\/p>\n<pre><code class=\"bash\">psql -h master -d dbname -c \"CREATE PUBLICATION dbname FOR ALL TABLES;\"\n<\/code><\/pre>\n<p>\n2. Vamos criar um slot de replica\u00e7\u00e3o no mestre:<\/p>\n<pre><code class=\"bash\">psql -h master -c \"select pg_create_logical_replication_slot('repl', 'pgoutput');\"\n<\/code><\/pre>\n<p>\n3. Vamos parar a replica\u00e7\u00e3o na antiga r\u00e9plica:<\/p>\n<pre><code class=\"bash\">psql -h replica1 -c \"select pg_wal_replay_pause();\"\n<\/code><\/pre>\n<p>\n4. Vamos obter o n\u00famero da transa\u00e7\u00e3o do mestre:<\/p>\n<pre><code class=\"bash\">psql -h master -c \"select replay_lsn from pg_stat_replication where client_addr = 'replica1';\"\n<\/code><\/pre>\n<p>\n5. Vamos fazer o dump da antiga r\u00e9plica. Faremos isso em v\u00e1rias threads, o que ajudar\u00e1 a acelerar o processo:<\/p>\n<pre><code class=\"bash\">pg_dump -h replica1 --no-publications --no-subscriptions -O -C -F d -j 8 -f dump\/ dbname\n<\/code><\/pre>\n<p>\n6. Vamos carregar o dump no novo servidor:<\/p>\n<pre><code class=\"bash\">pg_restore -h replica2 -F d -j 8 -d dbname dump\/\n<\/code><\/pre>\n<p>\n7. Ap\u00f3s carregar o dump, a replica\u00e7\u00e3o pode ser iniciada na r\u00e9plica de streaming:<\/p>\n<pre><code class=\"bash\">psql -h replica1 -c \"select pg_wal_replay_resume();\"\n<\/code><\/pre>\n<p>\n7. Vamos criar uma assinatura na nova r\u00e9plica l\u00f3gica:<\/p>\n<pre><code class=\"bash\">psql -h replica2 -c \"create subscription oldprod connection 'host=replica1 port=5432 user=postgres password=secret dbname=dbname' publication dbname with (enabled = false, create_slot = false, copy_data = false, slot_name='repl');\"\n<\/code><\/pre>\n<p>\n8. Vamos obter <code>oid<\/code> da assinatura:<\/p>\n<pre><code class=\"bash\">psql -h replica2 -d dbname -c \"select oid, * from pg_subscription;\"\n<\/code><\/pre>\n<p>\n9. Suponha que foi obtido <code>oid=1000<\/code>. Vamos aplicar o n\u00famero da transa\u00e7\u00e3o \u00e0 assinatura:<\/p>\n<pre><code class=\"bash\">psql -h replica2 -d dbname -c \"select pg_replication_origin_advance('pg_1000', 'AA\/AAAAAAAA');\"\n<\/code><\/pre>\n<p>\n10. Vamos iniciar a replica\u00e7\u00e3o:<\/p>\n<pre><code class=\"bash\">psql -h replica2 -d dbname -c \"alter subscription oldprod enable;\"\n<\/code><\/pre>\n<p>\n11. Vamos verificar o status da assinatura; a replica\u00e7\u00e3o deve estar funcionando:<\/p>\n<pre><code class=\"bash\">psql -h replica2 -d dbname -c \"select * from pg_replication_origin_status;\"\npsql -h master -d dbname -c \"select slot_name, restart_lsn, confirmed_flush_lsn from pg_replication_slots;\"\n<\/code><\/pre>\n<p>\n12. Depois que a replica\u00e7\u00e3o for iniciada e os bancos estiverem sincronizados, a troca pode ser realizada.<\/p>\n<p>13. Ap\u00f3s desligar a replica\u00e7\u00e3o, \u00e9 necess\u00e1rio corrigir as sequ\u00eancias. Isso est\u00e1 bem descrito <noindex><a rel=\"nofollow\" href=\"https:\/\/wiki.postgresql.org\/wiki\/Fixing_Sequences\">no artigo em wiki.postgresql.org<\/a><\/noindex>.<\/p>\n<p>Com esse plano, a troca ocorreu com m\u00ednimas interrup\u00e7\u00f5es.<\/p>\n<h2>Conclus\u00e3o<\/h2>\n<p>\nOs operadores Kubernetes simplificam v\u00e1rias a\u00e7\u00f5es, reduzindo-as \u00e0 cria\u00e7\u00e3o de recursos K8s. No entanto, ao alcan\u00e7ar uma automa\u00e7\u00e3o not\u00e1vel com eles, \u00e9 importante lembrar que isso pode trazer uma s\u00e9rie de nuances inesperadas, portanto, escolha os operadores com sabedoria.<\/p>\n<p>Ap\u00f3s considerar os tr\u00eas operadores Kubernetes mais populares para PostgreSQL, escolhemos o projeto da Zalando. Embora tenhamos encontrado algumas dificuldades, o resultado realmente nos agradou, e planejamos expandir essa experi\u00eancia para algumas outras instala\u00e7\u00f5es PgSQL. Se voc\u00ea tiver experi\u00eancia com solu\u00e7\u00f5es semelhantes, adorar\u00edamos ver os detalhes nos coment\u00e1rios!<\/p>\n<h2>P.S.<\/h2>\n<p>\nConfira tamb\u00e9m em nosso blog:<\/p>\n<ul>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/431500\/\">Bancos de dados e Kubernetes (vis\u00e3o geral e v\u00eddeo da apresenta\u00e7\u00e3o)<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/479438\/\">Postgres-ter\u00e7a n\u00ba 5: PostgreSQL e Kubernetes. CI\/CD. Automatiza\u00e7\u00e3o de testes<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/480722\/\">Uma hist\u00f3ria com o operador Redis no K8s e uma breve an\u00e1lise das ferramentas para an\u00e1lise de dados deste banco de dados<\/a><\/noindex>\u00bb.<\/li>\n<\/ul>\n<p>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/520616\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412\u0441\u0451 \u0447\u0430\u0449\u0435 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u044e\u0442 \u0442\u0430\u043a\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b: \u00ab\u0425\u043e\u0442\u0438\u043c \u043a\u0430\u043a Amazon RDS, \u043d\u043e \u0434\u0435\u0448\u0435\u0432\u043b\u0435\u00bb; \u00ab\u0425\u043e\u0442\u0438\u043c \u043a\u0430\u043a RDS, \u043d\u043e \u0432\u0435\u0437\u0434\u0435, \u0432 \u043b\u044e\u0431\u043e\u0439 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435\u00bb. \u0427\u0442\u043e\u0431\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0435 managed-\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 Kubernetes, \u043c\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u0434\u043b\u044f PostgreSQL (Stolon, \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u043e\u0442 Crunchy Data \u0438 Zalando) \u0438 \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0441\u0432\u043e\u0439 \u0432\u044b\u0431\u043e\u0440. \u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u2014 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u043d\u0430\u043c\u0438 \u043e\u043f\u044b\u0442 \u0438 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":95323,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-95322","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.4 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0412\u0441\u0451 \u0447\u0430\u0449\u0435 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/kratkij-obzor-operatorov-postgresql-dlya-kubernetes-nash-vybor-i-opyt\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"pt_PT\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041a\u0440\u0430\u0442\u043a\u0438\u0439 \u043e\u0431\u0437\u043e\u0440 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 PostgreSQL \u0434\u043b\u044f Kubernetes, \u043d\u0430\u0448 \u0432\u044b\u0431\u043e\u0440 \u0438 \u043e\u043f\u044b\u0442 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0412\u0441\u0451 \u0447\u0430\u0449\u0435 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/kratkij-obzor-operatorov-postgresql-dlya-kubernetes-nash-vybor-i-opyt\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-09-28T05:42:39+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-09-28T05:42:39+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Vis\u00e3o geral dos operadores PostgreSQL para Kubernetes, nossa escolha e experi\u00eancia | ProHoster","description":"Cada vez mais de clientes.","canonical_url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/kratkij-obzor-operatorov-postgresql-dlya-kubernetes-nash-vybor-i-opyt","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pt_PT","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041a\u0440\u0430\u0442\u043a\u0438\u0439 \u043e\u0431\u0437\u043e\u0440 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 PostgreSQL \u0434\u043b\u044f Kubernetes, \u043d\u0430\u0448 \u0432\u044b\u0431\u043e\u0440 \u0438 \u043e\u043f\u044b\u0442 | ProHoster","og:description":"\u0412\u0441\u0451 \u0447\u0430\u0449\u0435 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432.","og:url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/kratkij-obzor-operatorov-postgresql-dlya-kubernetes-nash-vybor-i-opyt","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-09-28T05:42:39+00:00","article:modified_time":"2020-09-28T05:42:39+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"95322","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 11:08:22","updated":"2022-09-30 21:12:08","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/95322","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/comments?post=95322"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/95322\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media\/95323"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media?parent=95322"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/categories?post=95322"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/tags?post=95322"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}