Copiar objetos de um bucket para outro é trivial. O que não é trivial é fazer isso entre provedores diferentes, de forma repetível, sem deixar chave estática em disco, sem dar permissão de tenancy inteira para uma tarefa que precisa de um bucket só, e sabendo de antemão quanto a conta vai crescer.
Este texto descreve o caminho de OCI Object Storage para Amazon S3. A direção inversa muda os nomes das primitivas, não o raciocínio.
Por que atravessar a nuvem
A durabilidade de mídia anunciada pelos provedores não é o risco que a cópia entre nuvens cobre. Ela existe para cobrir o que a durabilidade não cobre: credencial administrativa comprometida, exclusão em massa feita por automação própria, conta suspensa, erro de política que apagou o que o ciclo de vida deveria ter mantido. Tudo isso acontece dentro da fronteira da conta, e replicação dentro da mesma conta herda a fronteira.
A regra é a mesma que separa cópia de espelho: o destino não pode obedecer a quem controla a origem. Já tratamos dessa distinção em backup não é sincronização.
O desenho mínimo
Três peças: uma identidade de leitura na origem, uma identidade de escrita no destino, e um processo que roda em algum lugar. A decisão mais importante é onde esse processo roda, porque ela define qual das duas credenciais pode ser uma identidade de máquina e qual vai ser, inevitavelmente, uma chave estática.
- Worker na origem (OCI). Leitura por instance principal — sem segredo em arquivo. A chave estática passa a ser a da AWS, com permissão de escrita no destino.
- Worker no destino (AWS). Escrita por IAM role da instância. A chave estática passa a ser a do OCI, com permissão de leitura na origem.
Não existe opção sem chave estática nenhuma, a menos que você use federação entre os dois provedores. Existe escolha sobre qual vazamento você prefere. Chave de leitura vazada expõe o conteúdo do bucket de origem. Chave de escrita vazada alcança o destino — e é por isso que o destino precisa de Object Lock e de uma identidade que não possa apagar, assunto de backup imutável com Object Lock.
Passo a passo
1. Inventariar a origem. Namespace do Object Storage, compartimento, região, nome exato do bucket. Quantidade aproximada de objetos e distribuição de tamanho. Se o bucket tem versionamento, decidir se você copia só a versão corrente ou o histórico — são projetos diferentes de esforço e de custo.
2. Criar a identidade de leitura, com escopo de bucket. No OCI, a política se escreve
por compartimento, mas aceita condição de recurso. O formato é
allow group BackupLeitura to read objects in compartment <nome> where target.bucket.name='<bucket>'.
Sem a condição where, você acabou de dar leitura de todos os buckets do compartimento para
uma tarefa que precisa de um. Em ambiente de MSP isso é o bastante para um cliente alcançar
o dado de outro — tema de
como impedir que o backup de um cliente toque no de outro.
3. Decidir entre API nativa e compatibilidade S3. O OCI expõe uma API compatível com S3, o que deixa você usar ferramentas que já falam S3 dos dois lados. O preço é que essa via depende de customer secret key — par de chaves estático ligado a um usuário — e tem diferenças de implementação em relação à API nativa. O SDK nativo aceita instance principal e dispensa segredo, ao custo de código próprio para listar e ler. Consulte a documentação do Object Storage do OCI antes de escolher.
4. Preparar o destino. Bucket dedicado, um por cliente. Versionamento ligado. Object Lock
habilitado — decidir na criação é o caminho mais simples; habilitar depois é possível em
bucket versionado, e o procedimento atual está na
documentação do Object Lock no S3.
Política de bucket amarrando o Principal ao ARN exato da role ou do usuário que grava, e
negando s3:DeleteObject, s3:DeleteObjectVersion e, se houver retenção configurada,
s3:PutObjectRetention e s3:PutObjectLegalHold para esse principal. Em bucket versionado,
negar apenas s3:DeleteObject não impede a exclusão de versões. Quem escreve não apaga. As
roles do IAM resolvem a
parte de identidade de máquina; a política de bucket resolve a parte de escopo.
5. Transferir. Em bucket com milhões de objetos pequenos, o gargalo quase nunca é banda: é a listagem e a contagem de requisições. Paralelize por prefixo, use multipart só acima de um limiar que faça sentido, e mantenha um índice próprio do que já foi copiado — reler a origem inteira a cada ciclo é o que transforma um backup barato em caro. O efeito do volume de arquivos pequenos sobre a fatura está em custo de backup de milhões de arquivos pequenos.
6. Verificar. Comparar tamanho é necessário e insuficiente. O ETag de objeto enviado em multipart não é o MD5 do conteúdo, então comparar ETag entre provedores produz falso negativo. Calcule e grave um checksum próprio por objeto no seu índice, ou use os campos de checksum adicionais que o S3 oferece. A documentação de integridade de objetos do Amazon S3 descreve quais algoritmos podem ser enviados junto do objeto.
7. Agendar e observar. Ciclo com relatório de objetos novos, objetos alterados e falhas. Backup que não reporta falha é backup que você acredita ter.
As armadilhas
Egresso é cobrado na origem. A estrutura típica envolve cobrança por requisição (LIST, GET, PUT contam separado), cobrança por volume de saída de dados e cobrança por armazenamento na classe escolhida. Classes frias somam duas cláusulas que pegam gente desprevenida: mínimo de dias de retenção faturados e multa por exclusão antecipada. Não repito preço aqui porque tabela muda; abra a página de preços da região exata do seu bucket e some os três componentes antes de ligar o primeiro ciclo. O que costuma sumir da conta está em o que some da conta de um armazenamento barato.
A credencial de origem precisa de escrita se houver restauração de volta. Esta armadilha
aparece no dia do incidente, não na configuração. Você configurou leitura na origem, escrita
no destino, tudo com privilégio mínimo — e no dia do incidente descobre que ninguém pode
gravar de volta no bucket de origem. A saída não é dar escrita à identidade de backup. É
criar uma segunda identidade, de restauração, com manage objects no bucket de origem e
nenhuma permissão no destino além de leitura, mantida desativada em operação normal e
habilitada por procedimento explícito. Quem aprova a reativação não deveria ser quem opera o
backup. E o procedimento precisa ter sido executado em treino, senão é documento, não
capacidade.
Metadado não atravessa sozinho. Classe de armazenamento, tags, ACLs, pre-authenticated requests, regras de ciclo de vida e configuração do bucket não são objetos. Cópia de objeto não é backup de configuração — essa parte mora em infraestrutura como código, versionada em repositório.
Chaves esquisitas. Objetos de zero byte terminados em barra, chaves com #, ?, acento
ou espaço, e profundidade de prefixo maior que a que o sistema de arquivos de destino aceita,
caso você passe por disco. Trate chave como sequência de bytes opaca, nunca como caminho.
Restauração fria leva tempo. Gravar em classe de arquivamento no destino é o que faz a conta fechar, e o custo disso é o tempo de resgate. Vale ler restauração no Deep Archive na prática e por que o restore é a parte que ninguém antes de prometer RTO ao cliente.
O que este artigo não prova
Não há aqui nenhuma medição de desempenho. Nenhum número de throughput, de tempo de listagem ou de custo mensal — porque tabela de preço e limite de API mudam por região e por conta, e número errado em texto técnico é pior que número nenhum.
E o conselho não vale para todo mundo:
- Bucket pequeno e único. Se são alguns gigabytes num bucket só,
rcloneem um cron com chave bem guardada costuma ser suficiente. A arquitetura descrita acima só se paga quando há muitos clientes, muitos buckets e necessidade de provar escopo. - Ameaça é falha de infraestrutura, não ação humana. Nesse caso, replicação dentro da mesma nuvem é mais simples, mais barata e mais rápida de restaurar. Atravessar provedor é cobertura contra perda de controle da conta — se esse risco não está no seu modelo de ameaça, você está pagando egresso à toa.
- RTO curto. Cópia entre nuvens, especialmente em classe fria, é pior em tempo de recuperação que replicação regional. Quem precisa de minutos precisa das duas coisas, não de uma.
- Equipe pequena. Duas identidades por cliente, rotação de chave estática e procedimento de break-glass são custo operacional contínuo. Automação mal mantida aqui gera mais incidente do que previne.
Checklist
- Permissão de leitura com condição por nome de bucket, nunca por compartimento inteiro.
- Identidade de máquina na ponta onde o worker roda; chave estática só na outra, com rotação agendada e guarda em cofre.
- Bucket de destino dedicado, versionado, com Object Lock habilitado — na criação é o caminho mais simples; em bucket versionado dá para habilitar depois, conferindo o procedimento atual na documentação do S3.
- Identidade de escrita sem permissão de exclusão de objeto nem de versão, amarrada por política de bucket.
- Índice próprio com checksum, sem depender de ETag entre provedores.
- Identidade de restauração separada, com escrita na origem, desativada por padrão.
- Configuração de bucket versionada em IaC, à parte dos objetos.
- Restauração cronometrada ao menos uma vez, com as identidades reais.
O NubliVault é o produto de backup da Nublify: empacota milhões de arquivos pequenos e os guarda numa nuvem diferente da de origem. Como funciona · Segurança