Esse artigo faz um apanhado do conhecimento, informações e instruções de como implementar o Harbor em um ambiente de containers Docker, orquestrados com Kubernetes.



Introdução



É interessante observar o que diz no site oficial do Harbor:



“Our mission is to be the most secure, performant, scalable, and available cloud native repository for Kubernetes” - Nossa missão é ser o repositório cloud native mais seguro, com melhor desempenho, escalável e disponível para o Kubernetes (Tradução Livre)



Ser um Docker Registry é uma das features mais maduras e mais completas do Harbor, mas suas possibilidades vão além disso! Segundo a documentação, é possível também utiliza-lo como um repositório para Charts Helm (ChartMuseum), fazer replicas em Registries As Service em provedores de Clouds públicas, Criação de Jobs automatizados para Image deletion & garbage collection, RBAC (estrutura de permissões, usuários, grupos e projetos), Integração com ActiveDirectory/LDAP/OIDC, Scan de Vulnerabilidades (Clair) e integrar com diversas soluções de segurança (OPAAqua SecurityHashiCorp Vault, entre outras).



Pretty cool, huh? 🙃



Arquitetura



De todos os que vi, acredito que o diagrama abaixo é o que descreve melhor a atual arquitetura do Harbor. (versão 1.10 até a criação desse artigo)





Assim como a observação na figura, é interessante ressaltar que o Harbor possui diversos componentes OpenSource, havendo a possibilidade de desacoplamento e utilização desses componentes “As Services” nos provedores de cloud.



Instalação



O Harbor disponibiliza um Chart Helm oficial para a sua instalação. O que é possível adicionar ao helm local pelo comando abaixo:



helm repo add harbor https://helm.goharbor.io



É possível encontrar o arquivo values.yaml default no repositório do Chart, mas eu irei comentar abaixo os campos e configurações mais importantes para uma instalação inicial.



Exposição do Serviço



É possível expor o Harbor nas estratégias mais tradicionais do Kubernetes (ingress, clusterIp, nodePort, loadBalancer). Por padrão é utilizando a estratégia de Ingress. Nesse caso é necessário indicar as configurações do Ingress Controller já existente no ambiente, ou um serviço do provedor de Cloud Computing. É possível ajustar essas configurações no bloco “expose:{}” de acordo com a estratégia escolhida.



Caso não utilize a opção “ingress”, será provisionado um Nginx Ingress Controller. É possível customizar as configuração desse serviço no bloco “nginx:{}”, recomendo utilizar o values.yaml padrão como referência.



URLs



Outro ponto fundamental é indicar um valor para “externalURL:{}”. Segundo a documentação, essa URL será utilizada pelo serviço core do Harbor para:



1) populate the docker/helm commands showed on portal
2) populate the token service URL returned to docker/notary client



O formato é bem padrão para URLs:



protocol://domain[:port]



Boas práticas indicadas nas documentações:



1) Se “expose.type” for “ingress”, o “domain” deve ter o valor “expose.ingress.hosts.core”
2) Se “expose.type” for “clusterIP”, o “domain” deve ter o valor “expose.clusterIP.name”
3) Se “expose.type” for “nodePort”, o “domain” deve ter o valor endereço IP do node k8s.



# Se o Harbor for instalado pos trás de um proxy, configure o “domain” como a URL ou IP do proxy.



Também é necessário indicar a URLs para o serviço Notary e Core, irei falar mais sobre eles, mas é necessário indicar as URLs em “expose.ingress.hosts.core:{}” e “expose.ingress.hosts.notary:{}



TLS



Especialmente para o serviço de Registry, a configuração de TLS é fundamental. Caso não exista implementação do TLS em um Ingress Controller próprio, ou utilize um domínio especifico para o Harbor, é necessário indicar um secret que contenha os arquivos *.crt e *.key no campo “expose.tls.secretName:{}



Persistência



O Harbor possui compatibilidade com diversos tipos de storages, sendo possível configurar essas opções no bloco “persistence:{}”, indicando configurações de PVCs para cada serviço que possua persistências (Redis, Registry, Charmuseum e etc).



Data Storage (PVCs/PVs)



Observe que, por padrão, o campo “persistence.resourcePolicy:{}” tem o valor “keep”, para que os PVCs não sejam removidos quando o chart helm for excluído. Isso levanta um ponto importante para a preservação dos dados, nos testes que fiz o valor padrão “keep” para esse campo de fato mantém os PVCs durante a exclusão do Chart. Entretanto, ao fazer a reinstalação do chart, o Helm retorna erro informando que os volumes já existem. A estratégia que adotei foi criar os PVCs na instalação (ou manualmente) e indicar seus respectivos nomes no values.yaml. Desta forma a reinstalação acontece sem problemas e os dados ficam intactos.



Outros tipos de Backends



Também é possível utilizar outros tipos de “backends” de armazenamentos além do padrão, que é o “filesystem” com PVCs. Em “persistence.imageChartStorage:{}” estão os campos para configurar outros backends, como s3, azure, gcs, swift e outros.



Database (PostgreSQL / Redis)



O Harbor necessita armazenar os metadados relacionados aos seus objetos, como projetos, usuários, funções, políticas de replicação, políticas de retenção de tags, scanners, gráficos e imagens. Para tal é utilizado o PostgreSQL. O chart contempla a instalação de uma imagem própria (“goharbor/harbor-db”) do PostgreSQL pelo controller Statefullset. É possível customizar suas configurações dentro do bloco “database:{}”, sendo possível também a utilização de um banco externo, bastando indicar o valor “external” em “database.type{}” e passar os dados de acesso dentro do bloco “database.external{}”.



É possível fazer o mesmo com o Redis, dentro do bloco “redis:{}”.



Serviços Fundamentais



Conforme comentei na abordagem da arquitetura, o Harbor possui alguns serviços internos, eles são responsáveis por funcionalidades especificas e possuem blocos de configuração dentro do values.yaml.



O Core é um serviço responsável por Autenticação, gerenciamento de configuração, de cotas, de projetos e dentre muitas outras features. Mas não é possível configurar nada disso pelo Chart Helm, apenas na interface após a instalação do Harbor. Isso me preocupa um tanto por questões de resiliência, pois as configurações estarão dentro do banco de dados, sendo necessário redobrar atenção sobre ele.



É possível realizar configurações básicas, quanto a implementação do core, dentro do bloco “core:{}” no values.yaml



Assim como o core, o mesmo vale para os demais serviços. As configurações possíveis no values.yaml são básicas, voltadas apenas para a implementação das aplicações.



Interface Gráfica



Um dos pontos mais interessantes do Harbor é disponibilizar uma interface gráfica bem completa, o que entrega ao usuário maior autonomia e confiança durante o uso das features.







Harbor e Imagens Docker





A interação com o Harbor via CLI funciona como qualquer registry docker (Docker Hub por exemplo), com as possibilidade de PUSH e PULL tradicionais. Os pontos de atenção ficam para as features de gestão e segurança das imagens hospedadas nele.



Assim que uma imagem é adicionada ao Harbor, ela passar por Scans de Segurança que relacionam CVE abertas para vulnerabilidades encontradas na imagem. O Harbor faz uso de soluções pré-disponíveis na instalação, como o Clair e/ou Trivy.





Scans de Vulnerabilidade (Clair / Trivy / Notary)



Clair é um projeto Open Source da CoreOS para a análise estática de vulnerabilidades em containers appc e docker.



Trivy (tri-pronunciado como trigger, vy pronunciado como envy) é um scanner de vulnerabilidade simples e abrangente para containers. Atualmente o Trivy faz parte da stack da Aqua Security, mas é possível utiliza-lo individualmente, ou embarcado em soluções como o Harbor.



Tanto o Clair quanto o Trivy detectam vulnerabilidades de pacotes de SO (Alpine, RHEL, CentOS etc.) e dependências de aplicativos (Bundler, Composer, npm, yarn etc.).



No canal oficial do Harbor tem uma demonstração sobre o uso desse Scans.





Imagens Docker Assinadas (Notary)



Uma estratégia importante é “Docker Content Trust”, ela é citada na documentação do docker sob a indicação de uso com o Notary. O Notary é uma ferramenta para entregar e gerenciar coleções de conteúdos confiáveis. A premissa é que uma imagem seja assinada digitalmente e quem a consuma pode verificar a integridade e a origem do conteúdo. Esse recurso é desenvolvido em uma interface direta de gerenciamento e assinatura de chaves para criar coleções assinadas e configurar editores confiáveis.



A operação mais básica é listar as tags assinadas em um repositório. A documentação do Docker mostra um exemplo básico, onde é possível correlacionar algumas imagens presentes no Docker Hub com assinaturas que já existem no servidor Notary público.





É possível entender melhor a arquitetura desse serviço pela documentação, é uma boa leitura.



Conclusão



Existem muitas soluções interessantes para repositório de imagens, mas o Harbor se apresenta como um dos mais completos. Sua estrutura, instalação e as ferramentas que o compõe refletem uma natureza Cloud Native, sem reinventar a roda, utilizando soluções consolidadas no mercado para tarefas de armazenamento e segurança. Isso ajuda muito para traçar uma estratégia de gestão e alta disponibilidade em cima do Harbor.



 Autor: Bruno S. Brasil





Social

Fale conosco

Almeda Campinas 802, CJ 12, Jardim Paulista,

São Paulo - SP, 01404-001

Faça parte do time

Nossos conteúdos

Social

Fale conosco

Almeda Campinas 802, CJ 12, Jardim Paulista,

São Paulo - SP, 01404-001

Faça parte do time

Nossos conteúdos

Social

Fale conosco

Almeda Campinas 802, CJ 12, Jardim Paulista,

São Paulo - SP, 01404-001

Faça parte do time

Nossos conteúdos