Desculpe, OpenShift, nós não gostamos de você o suficiente e não o consideramos garantido

Esta postagem foi escrita porque nossos funcionários tiveram muitas conversas com clientes sobre o desenvolvimento de aplicativos no Kubernetes e sobre as especificidades desse desenvolvimento no OpenShift.







Normalmente começamos com a tese de que Kubernetes é apenas Kubernetes, e OpenShift já é uma plataforma Kubernetes, como Microsoft AKS ou Amazon EKS. Cada uma dessas plataformas tem suas vantagens, direcionadas a um ou outro público-alvo. E depois disso, a conversa já se estende para comparar os pontos fortes e fracos de plataformas específicas.



Em geral, pensamos em escrever esta postagem com uma conclusão como "Ouça, não importa onde executar o código, no OpenShift ou no AKS, no EKS, em alguns Kubernetes personalizados ou em qualquer Kubernetes (para resumir , vamos chamá-lo KUK) é realmente simples, tanto lá quanto lá. "



Em seguida, planejamos pegar o "Hello World" mais simples e, usando seu exemplo, mostrar o que é comum e quais são as diferenças entre o KUK e o Red Hat OpenShift Container Platform (doravante, OCP ou simplesmente OpenShift).



No entanto, enquanto escrevíamos este post, percebemos que nos acostumamos a usar o OpenShift por tanto tempo e tanto que simplesmente não percebemos como ele cresceu e se tornou uma plataforma incrível que se tornou muito mais do que apenas uma distribuição do Kubernetes. Estamos acostumados a considerar a maturidade e a simplicidade do OpenShift como garantidas, enquanto perdemos de vista seu brilho.



Em geral, chegou a hora do arrependimento ativo e agora iremos comparar passo a passo o comissionamento de nosso "Hello World" no KUK e no OpenShift, e faremos isso da forma mais objetiva possível (bem, talvez mostrando às vezes uma atitude pessoal em relação ao assunto). Se você está interessado em uma opinião puramente subjetiva sobre este assunto, você pode lê-la aqui (PT) . Nesta postagem, nos limitaremos a fatos e fatos apenas.



Clusters



Portanto, nosso "Hello World" precisa de clusters. Digamos não a nenhuma nuvem pública, para não pagar por servidores, registros, redes, transferência de dados, etc. Assim, escolhemos um cluster de nó único simples no Minikube (para KUK) e Contêineres Code Ready (para cluster OpenShift). Ambas as opções são realmente fáceis de instalar, mas exigirão muitos recursos do seu laptop.







Montagem em KUK-e



Então vamos.



Etapa 1 - construir nossa imagem de contêiner



Vou começar implantando nosso "Hello World" no minikube. Isso exigirá:



  1. 1. Docker instalado.
  2. 2. Git instalado.
  3. 3. Instale o Maven (na verdade, este projeto usa o binário mvnw, portanto, você pode fazer sem ele).
  4. 4. Na verdade, a própria fonte, ou seja, clone do repositório github.com/gcolman/quarkus-hello-world.git


O primeiro passo é criar um projeto Quarkus. Não se preocupe se você nunca trabalhou com Quarkus.io - é fácil. Basta selecionar os componentes que deseja usar no projeto (RestEasy, Hibernate, Amazon SQS, Camel, etc.), e então o próprio Quarkus, sem sua participação, configura o arquétipo maven e carrega tudo para o github. Ou seja, literalmente, um clique do mouse - e pronto. É por isso que amamos Quarkus.







A maneira mais fácil de construir nosso "Hello World" em uma imagem de contêiner é usar as extensões do Docker quarkus-maven, que farão todo o trabalho. Com o advento do Quarkus, isso se tornou realmente fácil e simples: adicione a extensão container-image-docker e você pode criar imagens com comandos maven.



./mvnw quarkus:add-extension -Dextensions=”container-image-docker”


Por fim, construímos nossa imagem usando o Maven. Como resultado, nosso código-fonte se transforma em uma imagem de contêiner pronta que já pode ser iniciada no tempo de execução do contêiner.







./mvnw -X clean package -Dquarkus.container-image.build=true


Isso, na verdade, é tudo, agora você pode iniciar o contêiner com o comando docker run, tendo mapeado nosso serviço para a porta 8080 para que você possa acessá-lo.



docker run -i — rm -p 8080:8080 gcolman/quarkus-hello-world








Após o início da instância do contêiner, resta apenas verificar com o comando curl se nosso serviço está em execução:







Então tudo funcionou e foi muito fácil e simples.



Etapa 2 - enviar nosso contêiner para o repositório de imagens de contêiner



Até agora, a imagem que criamos está armazenada localmente, em nosso armazenamento de contêiner local. Se quisermos usar esta imagem em nosso ambiente KUK, ela deve ser colocada em algum outro repositório. O Kubernetes não tem esses recursos, então usaremos o dockerhub. Porque, em primeiro lugar, é gratuito e, em segundo lugar, (quase) toda a gente o faz.



Isso também é muito simples e você só precisa de uma conta do dockerhub.



Então, instalamos o dockerhub e enviamos nossa imagem para lá.







Etapa 3 - iniciar Kubernetes



Existem muitas maneiras de construir a configuração do kubernetes para executar nosso "Hello World", mas usaremos a mais simples delas, somos o tipo de pessoa que somos ...



Primeiro, inicie o cluster do minikube:



minikube start


Etapa 4 - implantação de nossa imagem de contêiner



Agora precisamos transformar nosso código e a imagem do contêiner na configuração do kubernetes. Em outras palavras, precisamos de uma definição de pod e implantação com uma indicação de nossa imagem de contêiner no dockerhub. Uma das maneiras mais fáceis de fazer isso é executar o comando create deployment apontando para nossa imagem:







kubectl create deployment hello-quarkus — image =gcolman/quarkus-hello-world:1.0.0-SNAPSHOT


Com esse comando, pedimos a nosso KUK para criar uma configuração de implantação que deveria conter a especificação de pod para nossa imagem de contêiner. Este comando também aplicará esta configuração ao nosso cluster minikube e criará uma implantação que baixa nossa imagem de contêiner e inicia o pod no cluster.



Etapa 5 - acesso aberto ao nosso serviço



Agora que temos uma imagem de contêiner implantada, é hora de pensar em como configurar o acesso externo a esse serviço Restful, que, na verdade, está programado em nosso código.



Existem muitos caminhos. Por exemplo, você pode usar o comando expose para criar automaticamente os componentes Kubernetes apropriados, como serviços e endpoints. Na verdade, isso é o que faremos executando o comando expose para nosso objeto de implantação:



kubectl expose deployment hello-quarkus — type=NodePort — port=8080


Vamos nos deter na opção "- type" do comando expor por um momento.



Quando expomos e criamos os componentes necessários para executar nosso serviço, queremos, entre outras coisas, ser capazes de nos conectar de fora ao serviço hello-quarkus que fica dentro de nosso SDN. E o parâmetro type nos permite criar e conectar coisas como balanceadores de carga para rotear o tráfego para essa rede.



Por exemplo, escrevendo type = LoadBalancer, inicializaremos automaticamente o balanceador de carga na nuvem pública para se conectar ao nosso cluster Kubernetes. Isso, é claro, é ótimo, mas você precisa entender que essa configuração estará rigidamente ligada a uma nuvem pública específica e será mais difícil transferi-la entre instâncias do Kubernetes em ambientes diferentes.



Em nosso exemplo, type = NodePort , ou seja, a chamada para nosso serviço passa pelo endereço IP do nó e pelo número da porta. Esta opção permite que você não use nenhuma nuvem pública, mas requer uma série de etapas adicionais. Primeiro, você precisa de seu próprio balanceador de carga, portanto, implantaremos um balanceador de carga NGINX em nosso cluster.



Etapa 6 - instalar o balanceador de carga



O Minikube tem várias funções de plataforma que facilitam a criação de componentes necessários para acesso externo, como controladores de ingresso. O Minikube vem com o controlador de entrada Nginx e só precisamos habilitá-lo e configurá-lo.



minikube addons enable ingress


Agora, com apenas um comando, criaremos um controlador de entrada Nginx que funcionará dentro de nosso cluster minikube:



ingress-nginx-controller-69ccf5d9d8-j5gs9 1/1 Running 1 33m


Etapa 7 - Configurando o Ingress



Agora precisamos configurar o controlador de entrada Nginx para aceitar solicitações de hello-quarkus.











Finalmente, precisamos aplicar esta configuração.







kubectl apply -f ingress.yml








Como fazemos tudo isso em nosso computador, simplesmente adicionamos o endereço IP de nosso nó ao arquivo / etc / hosts para rotear solicitações http para nosso minikube para o balanceador de carga NGINX.



192.168.99.100 hello-quarkus.info


É isso, agora nosso serviço de minikube pode ser acessado de fora por meio do controlador de entrada Nginx.







Bem, isso foi fácil, certo? Ou realmente não?









Lançar no OpenShift (Code Ready Containers)



Agora vamos ver como tudo isso é feito no Red Hat OpenShift Container Platform (OCP).



Tal como acontece com o minikube, escolhemos um esquema com um cluster OpenShift de nó único na forma de Code Ready Containers (CRC). Ele costumava ser chamado de minishift e era baseado no projeto OpenShift Origin, mas agora é um CRC e é construído na plataforma OpenShift Container da Red Hat.



Aqui nós, desculpe, não podemos deixar de dizer: "OpenShift é ótimo!"



Inicialmente, pensamos em escrever que o desenvolvimento no OpenShift não é diferente do desenvolvimento no Kubernetes. E de fato é assim. Mas, no processo de escrever este post, nos lembramos de quantos movimentos desnecessários você precisa realizar quando não tem o OpenShift e, portanto, novamente, é maravilhoso. Adoramos quando tudo é fácil, e como é fácil em comparação com o minikube, nosso exemplo é implantado e executado no OpenShift, na verdade, isso nos levou a escrever este post.



Vamos analisar o processo e ver o que precisamos fazer.



Portanto, no exemplo do minikube, começamos com o Docker ... Pare, não precisamos mais do Docker instalado na máquina.



E não precisamos de um git local.

E Maven não é necessário.

E você não precisa criar uma imagem de contêiner com as mãos.

E não há necessidade de procurar qualquer repositório de imagens de contêiner.

E você não precisa instalar um controlador de entrada.

E você também não precisa configurar o ingresso.




Você entendeu, certo? Você não precisa de nenhum dos itens acima para implantar e executar nosso aplicativo no OpenShift. E o próprio processo se parece com isso.



Etapa 1 - Iniciando seu cluster OpenShift



Usamos Code Ready Containers da Red Hat, que é essencialmente o mesmo Minikube, mas apenas com um cluster Openshift de nó único completo.



crc start


Etapa 2 - Construir e implantar o aplicativo no cluster OpenShift



É nesta etapa que a simplicidade e conveniência do OpenShift se manifestam em toda a sua glória. Assim como em todas as distribuições do Kubernetes, temos muitas maneiras de executar um aplicativo em um cluster. E, como no caso do KUK, escolhemos deliberadamente o mais simples.



O OpenShift sempre foi construído como uma plataforma para construir e executar aplicativos em contêineres. A construção de contêineres sempre foi parte integrante dessa plataforma, então há vários recursos adicionais do Kubernetes para tarefas relacionadas.



Estaremos usando o processo OpenShift Source 2 Image (S2I), que tem várias maneiras diferentes de pegar nosso código-fonte (código ou binários) e transformá-lo em uma imagem de contêiner que roda em um cluster OpenShift.



Para isso, precisamos de duas coisas:



  • Nosso código-fonte no repositório git
  • Imagem do construtor, com base na qual a construção será executada.


Existem muitas dessas imagens por aí, mantidas pela Red Hat e no nível da comunidade, e usaremos a imagem OpenJDK, já que estou construindo um aplicativo Java.



Você pode iniciar a construção S2I a partir do console gráfico do OpenShift Developer e da linha de comando. Usaremos o comando new-app para informar onde obter a imagem do construtor e nosso código-fonte.







oc new-app registry.access.redhat.com/ubi8/openjdk-11:latest~https://github.com/gcolman/quarkus-hello-world.git


É isso, nosso aplicativo foi criado. Ao fazer isso, o processo S2I fez o seguinte:



  • Criou um pod de construção de serviço para todos os tipos de coisas relacionadas à construção do aplicativo.
  • Criou a configuração do OpenShift Build.
  • Baixou a imagem do construtor para o registro docker interno do OpenShift.
  • Clonado "Hello World" no repositório local.
  • Vi que havia um maven pom lá e compilei o aplicativo com o maven.
  • Criou uma nova imagem de contêiner contendo o aplicativo Java compilado e colocou essa imagem no registro de contêiner interno.
  • Criou a implantação do Kubernetes com especificações de pod, serviço etc.
  • Implementação de imagem de contêiner iniciada.
  • Removido o pod de compilação de serviço.


Há muitas coisas nesta lista, mas o principal é que toda a compilação ocorre exclusivamente no OpenShift, o registro interno do Docker está dentro do OpenShift e o processo de compilação cria todos os componentes do Kubernetes e os executa no cluster.



Se você rastrear visualmente o lançamento de S2I no console, poderá ver como o pod de compilação é iniciado durante a compilação.







Agora vamos dar uma olhada nos logs do pod builder: em primeiro lugar, ele mostra como o maven faz seu trabalho e baixa as dependências para construir nosso aplicativo java.







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







É isso, o processo de montagem está completo. Agora vamos ter certeza de que os pods e serviços de nosso aplicativo estão sendo executados no cluster.



oc get service








Isso é tudo. E apenas uma equipe. Só temos que expor este serviço para acesso externo.



Etapa 3 - expor o serviço para acesso externo



Como no caso do KUK, na plataforma OpenShift, nosso "Hello World" também precisa de um roteador para direcionar o tráfego externo para um serviço dentro do cluster. O OpenShift torna isso muito fácil. Em primeiro lugar, o componente de roteamento HAProxy é instalado no cluster por padrão (pode ser alterado para o mesmo NGINX). Em segundo lugar, existem recursos especiais e altamente configuráveis ​​chamados Routes, que se assemelham a objetos Ingress no bom e velho Kubernetes (na verdade, os Routes do OpenShift influenciaram muito o design de objetos Ingress, que agora podem ser usados ​​no OpenShift) , mas para o nosso "Hello World", e em quase todos os outros casos, a rota padrão sem configuração adicional é suficiente para nós.



Para criar um FQDN roteável para "Hello World" (sim, OpenShiift tem seu próprio DNS para roteamento por nome de serviço), simplesmente expomos nosso serviço:







oc expose service quarkus-hello-world


Se você olhar a rota recém-criada, poderá encontrar o FQDN e outras informações de roteamento lá:



oc get route








Finalmente, acessamos nosso serviço a partir do navegador:







Agora foi muito fácil!



Amamos o Kubernetes e tudo o que a tecnologia nos permite fazer, e também amamos a simplicidade e a leveza. O Kubernetes foi criado para torná-lo incrivelmente fácil de operar em contêineres distribuídos e escalonáveis, mas sua simplicidade não é mais suficiente para implementar aplicativos. E é aí que entra o OpenShift, que acompanha o tempo e oferece o Kubernetes, focado principalmente no desenvolvedor. Muito esforço foi investido para adaptar a plataforma OpenShift especificamente para o desenvolvedor, incluindo a criação de ferramentas como S2I, ODI, Portal do desenvolvedor, OpenShift Operator Framework, integração IDE, catálogos de desenvolvedor, integração Helm, monitoramento e muitos outros.



Esperamos que este artigo seja interessante e útil para você. E para encontrar recursos, materiais e outras coisas úteis adicionais para desenvolvimento na plataforma OpenShift, visite o portal de desenvolvedores Red Hat .



All Articles