Este post foi escrito porque nossos colaboradores tiveram muitas conversas com clientes sobre o desenvolvimento de aplicações no Kubernetes e as especificidades desse tipo de desenvolvimento no OpenShift.

Geralmente começamos com a tese de que Kubernetes é apenas Kubernetes, enquanto OpenShift é uma plataforma Kubernetes, assim como Microsoft AKS ou Amazon EKS. Cada uma dessas plataformas tem suas vantagens, voltadas para diferentes públicos-alvo. E após isso, a conversa flui para a comparação dos pontos fortes e fracos de cada plataforma específica.
Em geral, estávamos pensando em escrever este post com uma conclusão do tipo: "Olha, não importa onde executar o código, no OpenShift ou no AKS, no EKS, em um Kubernetes personalizado, em qualquer Kubernetes". (para abreviar, chamaremos de KUK) – é realmente simples, tanto lá quanto cá.
Depois, planejávamos pegar o simples "Hello World" e, a partir dele, mostrar o que é comum e quais são as diferenças entre KUK e a Red Hat OpenShift Container Platform (daqui em diante, OCP ou apenas OpenShift).
No entanto, ao longo da redação deste post, percebemos que nos acostumamos tanto a usar o OpenShift que simplesmente não reconhecemos como ele cresceu e se transformou em uma plataforma incrível, que se tornou muito mais do que apenas uma distribuição do Kubernetes. Nos acostumamos a considerar a maturidade e a simplicidade do OpenShift como garantidas, esquecendo de seu esplendor.
Em geral, chegou a hora do arrependimento ativo, e agora vamos comparar passo a passo a implantação do nosso "Hello World" no KUK e no OpenShift, e faremos isso da forma mais objetiva possível (exceto por, às vezes, expressar nosso sentimento sobre o assunto). Se você está interessado em uma opinião puramente subjetiva sobre isso, pode lê-la . E neste post, nos manteremos nos fatos e apenas nos fatos.
Clusters
Então, para o nosso "Hello World", precisamos de clusters. Vamos logo dizer "não" a qualquer nuvem pública, para não pagarmos por servidores, registros, redes, transferência de dados, etc. Portanto, escolhemos um simples cluster de um único nó em (para o KUK) e (para o cluster OpenShift). Ambas as opções são realmente simples de instalar, mas exigirão muitos recursos no seu laptop.

Compilação no KUK
Então, vamos lá.
Passo 1 – vamos compilar nossa imagem de contêiner
Começaremos por implantar nosso "Hello World" no Minikube. Para isso, precisaremos de:
- 1. Docker instalado.
- 2. Git instalado.
- 3. Maven instalado (na verdade, neste projeto, usamos o binário mvnw, então não é necessário).
- 4. O código-fonte propriamente dito, ou seja, o clone do repositório
Primeiramente, precisamos criar um projeto Quarkus. Não se preocupe se você nunca trabalhou com o site Quarkus.io – é fácil. Basta escolher os componentes que deseja usar no projeto (RestEasy, Hibernate, Amazon SQS, Camel, etc.), e o Quarkus irá configurar automaticamente o archetype do maven e disponibilizar tudo no GitHub. Então, literalmente, é um clique do mouse – e está pronto. É por isso que amamos o Quarkus.

A maneira mais simples de compilar nosso 'Hello World' em uma imagem de contêiner é usar a extensão quarkus-maven para Docker, que fará todo o trabalho necessário. Com a chegada do Quarkus, isso se tornou realmente fácil: você adiciona a extensão container-image-docker e pode criar imagens com comandos do maven.
./mvnw quarkus:add-extension -Dextensions="container-image-docker"
E, finalmente, compilamos nossa imagem usando o Maven. Como resultado, nosso código-fonte se transforma em uma imagem de contêiner pronta para ser executada no ambiente de execução de contêineres.

./mvnw -X clean package -Dquarkus.container-image.build=true
E isso é tudo, agora podemos iniciar o contêiner com o comando docker run, mapeando nosso serviço para a porta 8080, para que possa ser acessado.
docker run -i --rm -p 8080:8080 gcolman/quarkus-hello-world

Depois que a instância do contêiner for iniciada, resta apenas verificar com o comando curl se nosso serviço está funcionando:
![]()
Assim, tudo está funcionando e foi realmente fácil.
Passo 2 – enviamos nosso contêiner para o repositório de imagens de contêiner
Até agora, a imagem que criamos está armazenada localmente, em nosso repositório local de contêineres. Se quisermos usar essa imagem em nosso ambiente K8s, precisamos colocá-la em algum outro repositório. No Kubernetes, não há tais funcionalidades, então usaremos o dockerhub. Porque, em primeiro lugar, é gratuito, e em segundo lugar, (quase) todos fazem isso.
Isso também é muito simples, e só precisamos de uma conta no dockerhub.
Então, configuramos o dockerhub e enviamos nossa imagem para lá.

Passo 3 – iniciamos o Kubernetes
Existem muitas maneiras de montar a configuração do Kubernetes para executar nosso 'Hello World', mas usaremos a mais simples, somos assim...
Para começar, iniciamos o cluster minikube:
minikube start
Passo 4 – implantamos nossa imagem de contêiner
Agora precisamos converter nosso código e a imagem do contêiner em configurações do Kubernetes. Em outras palavras, precisamos da definição de pod e deployment, apontando para nossa imagem de contêiner no Docker Hub. Uma das maneiras mais simples de fazer isso é rodar o comando create deployment, especificando nossa imagem:

kubectl create deployment hello-quarkus --image=gcolman/quarkus-hello-world:1.0.0-SNAPSHOT
Com este comando, dissemos ao nosso K8S para criar uma configuração de deployment que deve conter a especificação do pod para nossa imagem de contêiner. Este comando também aplicará essa configuração ao nosso cluster minikube, criando um deployment que baixará nossa imagem de contêiner e iniciará o pod no cluster.
Passo 5 – abrindo o acesso ao nosso serviço
Agora que temos a imagem de contêiner implantada, é hora de pensar em como configurar o acesso externo a este serviço Restful, que está, na verdade, programado em nosso código.
Existem várias maneiras de fazer isso. Por exemplo, podemos usar o comando expose para criar automaticamente os componentes do Kubernetes necessários, como services e endpoints. E é exatamente isso que faremos, executando o comando expose para nosso objeto de deployment:
kubectl expose deployment hello-quarkus --type=NodePort --port=8080
Vamos parar um momento para discutir a opção "--type" do comando expose.
Quando fazemos o expose e criamos os componentes necessários para executar nosso serviço, precisamos que, entre outras coisas, seja possível acessar o serviço hello-quarkus que está dentro da nossa rede programável. E o parâmetro tipo nos permite criar e conectar coisas como balanceadores de carga para direcionar o tráfego para essa rede.
Por exemplo, especificando type=LoadBalancer, automaticamente inicializamos um balanceador de carga na nuvem pública, para nos conectar ao nosso cluster Kubernetes. Isso, claro, é ótimo, mas precisamos entender que essa configuração ficará rigidamente presa a uma nuvem pública específica e será mais difícil de migrar entre instâncias de Kubernetes em diferentes ambientes.
No nosso exemplo type=NodePort, ou seja, a chamada ao nosso serviço é feita pelo IP do nó e pelo número da porta. Esta opção permite não usar nenhuma nuvem pública, mas requer uma série de etapas adicionais. Primeiro, você precisa do seu próprio balanceador de carga, então vamos implementar um balanceador de carga NGINX em nosso cluster.
Passo 6 – Instalando o balanceador de carga
O minikube possui uma série de funcionalidades de plataforma que facilitam a criação dos componentes necessários para acesso externo, como os controladores de ingress. O Minikube vem com um controlador de ingress Nginx, e só precisamos ativá-lo e configurá-lo.
minikube addons enable ingress
Agora, com um único comando, criaremos o controlador de ingress Nginx que funcionará dentro do nosso cluster minikube:
ingress-nginx-controller-69ccf5d9d8-j5gs9 1/1 Rodando 1 33m
Passo 7 – Configurando o ingress
Agora precisamos configurar o controlador de ingress Nginx para que ele possa processar as requisições hello-quarkus.


E, finalmente, precisamos aplicar essa configuração.

kubectl apply -f ingress.yml
![]()
Como estamos fazendo tudo isso em nosso computador, basta adicionar o IP do seu nó ao arquivo /etc/hosts, para direcionar as requisições http ao nosso minikube no balanceador de carga NGINX.
192.168.99.100 hello-quarkus.info
Pronto! Agora nosso serviço minikube está acessível externamente através do controlador de ingress Nginx.

Então, foi fácil, não? Ou não tão fácil assim?

Executando no OpenShift (Code Ready Containers)
Agora vamos ver como isso é feito na Red Hat OpenShift Container Platform (OCP).
Assim como no caso do minikube, escolhemos o esquema de um cluster de nó único OpenShift na forma de Code Ready Containers (CRC). Antes, isso era conhecido como minishift e era baseado no projeto OpenShift Origin, agora é CRC e construído na plataforma OpenShift da Red Hat.
Aqui, desculpe, não podemos deixar de dizer: "OpenShift é maravilhoso!"
Inicialmente, pensamos em escrever que o desenvolvimento no OpenShift não é diferente do desenvolvimento no Kubernetes. E, em essência, é verdade. Mas, ao escrever este post, lembramos quantas etapas desnecessárias são necessárias quando você não tem o OpenShift, e por isso, reafirmamos, ele é maravilhoso. Nós adoramos quando tudo é fácil, e a maneira como nosso exemplo é implantado e iniciado no OpenShift em comparação com o minikube é, na verdade, o que nos motivou a escrever este post.
Vamos dar uma olhada no processo e ver o que precisaremos fazer.
Então, no exemplo com minikube, começamos com o Docker... Espere, não precisamos mais que o Docker esteja instalado na máquina.
E o git local não é necessário.
E o Maven também não é necessário.
E não é necessário criar manualmente a imagem do container.
E não é preciso procurar por algum repositório de imagens de containers.
E não é necessário instalar o controlador de ingress.
E também não é preciso configurar o ingress.
Vocês entenderam, certo? Para implantar e executar nosso aplicativo no OpenShift, não é necessário nada do que foi mencionado acima. E o processo é o seguinte.
Passo 1 – Inicie seu cluster OpenShift
Estamos usando o Code Ready Containers da Red Hat, que na verdade é o mesmo Minikube, mas com um cluster OpenShift de nó único completo.
crc start
Passo 2 – Realize a construção e implantação do aplicativo no cluster OpenShift
É neste passo que a simplicidade e conveniência do OpenShift se manifestam plenamente. Assim como em todas as distribuições do Kubernetes, temos várias maneiras de iniciar um aplicativo no cluster. E, como no caso do K8S, escolhemos deliberadamente a abordagem mais simples.
O OpenShift sempre foi construído como uma plataforma para criar e executar aplicativos em containers. A construção de containers sempre foi uma parte essencial dessa plataforma, portanto, aqui existem muitos recursos adicionais do Kubernetes para as tarefas correspondentes.
Usaremos o processo Source 2 Image (S2I) do OpenShift, que possui várias maneiras de pegar nosso código-fonte (código ou arquivos binários) e transformá-lo em uma imagem de container que pode ser executada no cluster OpenShift.
Para isso, precisaremos de duas coisas:
- Nosso código-fonte em um repositório git
- A imagem do Builder, a partir da qual a construção será realizada.
Existem muitas dessas imagens, suportadas tanto pela Red Hat quanto pela comunidade, e usaremos a imagem do OpenJDK, já que estou construindo um aplicativo Java.
Iniciar a construção S2I pode ser feito tanto pela interface gráfica do OpenShift Developer quanto pela linha de comando. Usaremos o comando new-app, especificando de onde pegar a imagem do builder e nosso código-fonte.

oc new-app registry.access.redhat.com/ubi8/openjdk-11:latest~https://github.com/gcolman/quarkus-hello-world.git
Pronto, nosso aplicativo está criado. Nesse processo, o S2I executou as seguintes tarefas:
- Criou um pod de build auxiliar para todas as tarefas relacionadas à construção do aplicativo.
- Criou a configuração de Build do OpenShift.
- Baixou a imagem do builder para o registro docker interno do OpenShift.
- Clonou 'Hello World' no repositório local.
- Vi um que havia um maven pom, então compilei o aplicativo usando maven.
- Criei uma nova imagem de contêiner contendo o aplicativo Java compilado e armazenei esta imagem no registro de contêineres interno.
- Criei um Deployment do Kubernetes com as especificações do pod, serviço, etc.
- Iniciei o deploy da imagem do contêiner.
- Removi o pod de build temporário.
Esta lista tem muitas informações, mas o principal é que toda a construção ocorre exclusivamente dentro do OpenShift, o registro Docker interno está dentro do OpenShift, e o processo de construção cria todos os componentes do Kubernetes e os inicia no cluster.
Se você acompanhar visualmente a execução do S2I no console, poderá ver como o pod de build é iniciado durante a construção.

Agora vamos olhar os logs do pod builder: primeiro, é possível ver como o maven faz seu trabalho e baixa as dependências para construir nosso aplicativo java.

Depois que a construção do maven é concluída, a construção da imagem do contêiner é iniciada, e então essa imagem construída é enviada para o repositório interno.

Tudo pronto, o processo de construção foi concluído. Agora vamos garantir que os pods e serviços do nosso aplicativo foram iniciados no cluster.
oc get service
![]()
E é isso. E tudo com um único comando. Agora, só precisamos expor este serviço para acesso externo.
Passo 3 – Expondo o serviço para acesso externo
Assim como no caso do KUK, na plataforma OpenShift, nosso 'Hello World' também precisa de um roteador para direcionar o tráfego externo ao serviço dentro do cluster. No OpenShift, isso é feito de forma muito simples. Primeiro, há um componente de roteamento HAProxy instalado por padrão no cluster (que pode ser trocado pelo mesmo NGINX). Em segundo lugar, existem recursos especiais e altamente configuráveis que se chamam Routes e lembram objetos Ingress no bom e velho Kubernetes (na verdade, os Routes do OpenShift influenciaram bastante o design dos objetos Ingress, que agora também podem ser usados no OpenShift), mas para o nosso 'Hello World', assim como na maioria dos outros casos, um Route padrão sem configuração adicional será suficiente.
Para criar um FQDN roteável para 'Hello World' (sim, no OpenShift há um DNS próprio para roteamento por nomes de serviços), basta executar o expose para o nosso serviço:

oc expose service quarkus-hello-world
Se você olhar o Route recém-criado, poderá encontrar o FQDN e outras informações sobre roteamento:
oc get route
![]()
E finalmente, acessamos nosso serviço a partir do navegador:

Agora sim, isso foi realmente fácil!
Nós amamos Kubernetes e tudo o que essa tecnologia permite, assim como amamos a simplicidade e a facilidade. Kubernetes foi criado para simplificar incrivelmente a operação de contêineres escaláveis e distribuídos, mas, para trazer aplicativos online, essa simplicidade já não é suficiente hoje. É aqui que entra o OpenShift, que está em sintonia com os tempos e oferece um Kubernetes orientado principalmente para o desenvolvedor. Muitos esforços foram investidos para moldar a plataforma OpenShift especificamente para desenvolvedores, incluindo a criação de ferramentas como S2I, ODI, Developer Portal, OpenShift Operator Framework, integração com IDEs, Catálogos de Desenvolvedores, integração com Helm, monitoramento e muitos outros.
Esperamos que este artigo tenha sido interessante e útil para você. Recursos adicionais, materiais e outras coisas úteis para o desenvolvimento na plataforma OpenShift podem ser encontrados no portal .
Fonte: habr.com
