Introdução: Por que implantar C++ no Kubernetes?
\n\nC++ continua sendo uma das linguagens de programação mais performáticas, especialmente em áreas de sistemas de alta carga, servidores de jogos, aplicações financeiras e IoT. No entanto, no mundo moderno da computação em nuvem, apenas escrever código rápido não é suficiente — é preciso saber implantá-lo de forma confiável, escalá-lo e atualizá-lo sem tempo de inatividade. É aqui que o Kubernetes (K8s) entra em ação — um sistema de orquestração de contêineres que automatiza a implantação, o escalonamento e o gerenciamento de aplicações.
\n\nNeste guia, vamos analisar passo a passo o processo de implantação de uma aplicação C++ simples em um cluster Kubernetes. Você aprenderá como empacotar código C++ em uma imagem Docker, escrever os manifestos Kubernetes necessários e executar sua aplicação na nuvem. O artigo é voltado para iniciantes, portanto, não vamos nos aprofundar em configurações complexas, mas focar em um pipeline básico e funcional.
\n\n1. Preparação: Aplicação C++ e conteinerização Docker
\n\nAntes de falar sobre Kubernetes, precisamos preparar nossa aplicação C++ para funcionar em um contêiner. A conteinerização é o empacotamento da aplicação junto com todas as suas dependências em um ambiente isolado. Para C++, isso é criticamente importante, pois o binário compilado pode depender de versões específicas de bibliotecas (libc, libstdc++, etc.) na máquina de destino.
\n\n1.1. Aplicação C++ simples para implantação
\n\nVamos criar o arquivo main.cpp — um servidor HTTP simples que responderá a requisições. Para simplificar, não usaremos bibliotecas externas, mas escreveremos um servidor TCP primitivo.
// main.cpp\n#include <iostream>\n#include <string>\n#include <cstring>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <unistd.h>\n\nint main() {\n int server_fd, new_socket;\n struct sockaddr_in address;\n int opt = 1;\n int addrlen = sizeof(address);\n char buffer[1024] = {0};\n const char* hello = "HTTP/1.1 200 OK\\nContent-Type: text/plain\\nContent-Length: 12\\n\\nHello, K8s!\\n";\n\n // Criação do socket\n if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {\n perror("socket failed");\n exit(EXIT_FAILURE);\n }\n\n // Vinculação à porta 8080\n if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {\n perror("setsockopt");\n exit(EXIT_FAILURE);\n }\n address.sin_family = AF_INET;\n address.sin_addr.s_addr = INADDR_ANY;\n address.sin_port = htons(8080);\n\n if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) {\n perror("bind failed");\n exit(EXIT_FAILURE);\n }\n\n if (listen(server_fd, 3) < 0) {\n perror("listen");\n exit(EXIT_FAILURE);\n }\n\n std::cout << "Server listening on port 8080" << std::endl;\n\n while(true) {\n if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) {\n perror("accept");\n exit(EXIT_FAILURE);\n }\n read(new_socket, buffer, 1024);\n send(new_socket, hello, strlen(hello), 0);\n close(new_socket);\n }\n return 0;\n}\n\n\n1.2. Compilação do binário estático
\n\nPara que nosso contêiner seja mínimo e não dependa das bibliotecas do sistema host, é melhor compilar um binário estaticamente vinculado. Execute o comando:
\n\ng++ -static -o server main.cpp -lpthread\n\nA flag -static inclui todas as bibliotecas necessárias diretamente no arquivo executável. A flag -lpthread é necessária para trabalhar com threads (embora em nosso exemplo simples não seja obrigatória, será útil para projetos reais).
1.3. Dockerfile para aplicação C++
\n\nAgora vamos criar o Dockerfile. Usaremos uma compilação em vários estágios (multi-stage build): primeiro compilamos o código em uma imagem grande com o compilador, depo