Acompanhe os novos blogs no site www.byiorio.com.br


Conteúdo do blog:


Meu maior problema com o JAVA

Tive a oportunidade de configurar o Kubernetes na minha máquina e descrevi todo o processo passo a passo. Se você estiver interessado, pode conferir o guia completo logo abaixo.
 
Além disso, adoraria compartilhar minha experiência com o Java em nuvens e discutir um desafio significativo que enfrentei. Durante essa jornada, encontrei uma possível solução para o problema que quero compartilhar com você.

Pré-requitos
Java jdk17 que está junto do arquivo da GRAALVM
Migrar seu projeto SpringBoot para a versão 3.0.7  (versão 3.1 tinha muito bug)
Baixar o GraalVM graalvm-jdk-17_windows-x64_bin
Configurar a variável de ambiente GRAALVM_HOME com o valor do diretório onde você dezipou o arquivo baixado.
Instalar o DockerDesktop e adicionar o Kubernetes nas configurações
Instalar o Visual Studio Community escolhendo o Workload do C++

Projeto Java
Para migrar meu projeto SpringBoot do 2.7.6 para a versão 3.0.7 foi bem trabalhosa, mas consegui fazer functionar 100% no modo JAR e uns 60% no modo NATIVO. Nesse caso não irei colocar muitods detalhes e sim que isso é necessário para entrar no universo nativo.

Instalação de Visual Studio
Essa parte é bem simples e precisamos somente escolher o WorkLoad do C++ para instalação, iremos utilizar o "X64 native tools command" para compilar o projeto no formato .EXE do Windows.

Abrindo o Native Tools, podemos executar o comando abaixo e verificar se tudo compila normalmente

mvn -Pnative native:compile


Instalação e configuração do Kubernetes
Primeira parte é instalar o Docker Desktop e na parte de configuração (Ícone de Engrenagem), tenho um video demonstrando como instala a primeira parte , veja nesse link

Após a instalação precisaremos configurar a plataforma, e para começar vamos instalar o Dashboard, uma interface para acompanhar tudo que está acontecendo no kubernetes.

Todos os comandos do KUBECTL devem ser executados no powershell ou gitbash.

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml

Vamos acionar o proxy para poder acessar o dashboard nesse momento

kubectl proxy

Como resultado teremos um serviço na porta 8001

$ kubectl proxy
Starting to serve on 127.0.0.1:8001

Uma vez instalado poderemos acessar o Dashboard através do link

http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/#/login

Para poder acessar no modo TOKEN teremos que configurar todo o acesso , e para isso vamos criar dois arquivos:

create-cluster-role-binding.yaml com o conteúdo

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kubernetes-dashboard

create-service-cccount.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kubernetes-dashboard

Uma vez criado vamos executar os seguintes comando no mesmno diretório dos arquivos

kubectl apply -f create-service-cccount.yaml
kubectl apply -f create-cluster-role-binding.yaml

Uma vez criado vamos solicitar a geração do Token atravbés do seguinte comando

kubectl -n kubernetes-dashboard create token admin-user

Como resultado do comando teremos o TOKEN que você pode colar no console de login do Dashboard

$ kubectl -n kubernetes-dashboard create token admin-user
eyJhbGciOiJSUzI1NiIsImtpZCI6InlYenVpSnNEVUlGTWMzZHlBTFpLQjduLWxUbU9wZWRkNGw5QnNrUXd3Q1kifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjg5MTA4MTMyLCJpYXQiOjE2ODkxMDQ1MzIsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsInNlcnZpY2VhY2NvdW50Ijp7Im5hbWUiOiJhZG1pbi11c2VyIiwidWlkIjoiOWUzYjgwZDctNGNjOC00MGQ0LTk5ZmMtOTk0OTQxMzI5NGJkIn19LCJuYmYiOjE2ODkxMDQ1MzIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlcm5ldGVzLWRhc2hib2FyZDphZG1pbi11c2VyIn0.J9mX4CcOV4_oFQboyz-qBfffSddusWrHqndVdYuYO-6oB_e_2QM8OeigAOOK9TRGnAGhcCSfWiMuKgHX4OfVSZTxJI0RXrUjKIGlwX4dbiHM3eeqlUkT7TqNCE-yUAIgD7ioUUKaWcmDtNgp7InA8Nv3Gon0DCwtraxvd4-FH3LJ8nqU86RW5nutjcuXOQ7B1T06VS0akC-4xwn5EsQbTlc9kIB5kkFdwTpj5NsrChhA8uTOxI3Nsiv0_iZnhM7VAIEGD4CkEHUMFtqlUlDrIRkI16bn3ji63LRkw_EVAKjXqqQf_luK_ZItVE1cSsmSITgbvLQF3sDprRBgU71BVg

Agora vamos executar um comando para escolher o namespace padrão para instalar o nosso projeto

kubectl config set-context --current --namespace=default

Próximo passo é instalar o módulo que vai controlar as entradas nos nossos serviços e eu escolhi usar o ingress-nginx

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.0/deploy/static/provider/cloud/deploy.yaml

Vamos gerar a imagem com o JAR e outra com o NATIVO

Para gerar uma imagem com o seu protejto compilado na forma nativa, vamos executar o comando

mvn -Pnative spring-boot:build-image

Para gerar uma imagem no formato JAR, vou usar o seguinte arquivo Dockerfile

FROM openjdk:17-jdk-slim
EXPOSE 8080
COPY target/*.jar byiorio.jar
ENTRYPOINT ["java","-jar","/byiorio.jar"]

Vou executar o comando no mesmo diretório que está o arquivo Dockerfile.

docker build -t byiorio-normal:0.1.7 -f ./Dockerfile .

Com isso eu fiquei com duas imagens no meu Docker, imagem do nativo e outra imagem com o JAR

byiorio-api:0.1.7
byiorio-normal:0.1.7

Agora basta instalarmos no Kubernetes e para isso criei dois arquivos de instalação

byiorio-normal.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: byiorio-normal-deployment
  labels:
    app: byiorio-normal
spec:
  replicas: 1
  selector:
    matchLabels:
      app: byiorio-normal
  template:
    metadata:
      labels:
        app: byiorio-normal
    spec:
      containers:
      - name: byiorio-normal
        image: byiorio-normal:0.1.7
        ports:
        - containerPort: 8080
        resources:
          requests:
            memory: "512Mi"
            cpu: "500m"
          limits:
            memory: "512Mi"
            cpu: "500m"

byiorio-native.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: byiorio-native-deployment
  labels:
    app: byiorio-native
spec:
  replicas: 1
  selector:
    matchLabels:
      app: byiorio-native
  template:
    metadata:
      labels:
        app: byiorio-native
    spec:
      containers:
      - name: byiorio-native
        image: byiorio-api:0.1.7
        ports:
        - containerPort: 8080
        resources:
          requests:
            memory: "512Mi"
            cpu: "500m"
          limits:
            memory: "512Mi"
            cpu: "500m"

Agora vamos executar a instalação das imagens no Kubernetes

kubectl apply -f byiorio-native.yaml
kubectl apply -f byiorio-normal.yaml

Nesse momento conseguiremos ver os PODS instalados no kubernetes. Lembrando que estou aqui passando os comandos mínimos, caso queira ver com mais detalhes me mande uma mensagem.

Chegou o momento de criar o serviço, é ele que dará acesso ao nosso projeto e também fazer o balanceamento das requisições:

kubectl expose deployment byiorio-native-deployment --name=byiorio-nativo-service --type=NodePort --port=8080 --target-port=8080
kubectl expose deployment byiorio-normal-deployment --name=byiorio-normal-service --type=NodePort --port=8080 --target-port=8080

Vamos agora criar as entradas externas para as duas instalações,  e para isso vamos executar os comandos abaixo:

kubectl create ingress byiorio-nativo-ingress --class=nginx --rule="byiorio-native/*=byiorio-nativo-service:8080"
kubectl create ingress byiorio-normal-ingress --class=nginx --rule="byiorio-normal/*=byiorio-normal-service:8080"

Com esses comandos eu precisei colocar alguns endereços no arquivo HOST do windows

127.0.0.1 byiorio-normal
127.0.0.1 byiorio-native

Configurando Escala Automática
Para funcionar a escala automática precisaremos instalar um plugin para verificar as métricas do processador, para isso iremos criar 3 arquivos.

metrics.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    k8s-app: metrics-server
    rbac.authorization.k8s.io/aggregate-to-admin: "true"
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
    rbac.authorization.k8s.io/aggregate-to-view: "true"
  name: system:aggregated-metrics-reader
rules:
- apiGroups:
  - metrics.k8s.io
  resources:
  - pods
  - nodes
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    k8s-app: metrics-server
  name: system:metrics-server
rules:
- apiGroups:
  - ""
  resources:
  - nodes/metrics
  verbs:
  - get
- apiGroups:
  - ""
  resources:
  - pods
  - nodes
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server-auth-reader
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server:system:auth-delegator
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    k8s-app: metrics-server
  name: system:metrics-server
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:metrics-server
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
spec:
  ports:
  - name: https
    port: 443
    protocol: TCP
    targetPort: https
  selector:
    k8s-app: metrics-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
spec:
  selector:
    matchLabels:
      k8s-app: metrics-server
  strategy:
    rollingUpdate:
      maxUnavailable: 0
  template:
    metadata:
      labels:
        k8s-app: metrics-server
    spec:
      containers:
      - args:
        - --cert-dir=/tmp
        - --secure-port=4443
        - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
        - --kubelet-use-node-status-port
        - --metric-resolution=15s
        - --kubelet-insecure-tls
        image: registry.k8s.io/metrics-server/metrics-server:v0.6.3
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 3
          httpGet:
            path: /livez
            port: https
            scheme: HTTPS
          periodSeconds: 10
        name: metrics-server
        ports:
        - containerPort: 4443
          name: https
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /readyz
            port: https
            scheme: HTTPS
          initialDelaySeconds: 20
          periodSeconds: 10
        resources:
          requests:
            cpu: 100m
            memory: 200Mi
        securityContext:
          allowPrivilegeEscalation: false
          readOnlyRootFilesystem: true
          runAsNonRoot: true
          runAsUser: 1000
        volumeMounts:
        - mountPath: /tmp
          name: tmp-dir
      nodeSelector:
        kubernetes.io/os: linux
      priorityClassName: system-cluster-critical
      serviceAccountName: metrics-server
      volumes:
      - emptyDir: {}
        name: tmp-dir
---
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
  labels:
    k8s-app: metrics-server
  name: v1beta1.metrics.k8s.io
spec:
  group: metrics.k8s.io
  groupPriorityMinimum: 100
  insecureSkipTLSVerify: true
  service:
    name: metrics-server
    namespace: kube-system
  version: v1beta1
  versionPriority: 100

metrics-service.yaml

 apiVersion: extensions/v1beta1
 kind: Deployment
 metadata:
   name: metrics-server
   namespace: kube-system
   labels:
     k8s-app: metrics-server
 spec:
   selector:
     matchLabels:
       k8s-app: metrics-server
   template:
     metadata:
       name: metrics-server
       labels:
         k8s-app: metrics-server
     spec:
       serviceAccountName: metrics-server
       volumes:
       # mount in tmp so we can safely use from-scratch images and/or read-only containers
       - name: tmp-dir
         emptyDir: {}
       containers:
       - command:
         - /metrics-server
         - --metric-resolution=30s
         - --kubelet-insecure-tls
         - --kubelet-preferred-address-types=InternalIP
         name: metrics-server
         image: k8s.gcr.io/metrics-server-amd64:v0.3.1
         imagePullPolicy: Always
         volumeMounts:
         - name: tmp-dir
           mountPath: /tmp

metrics-svc.yaml

 apiVersion: v1
 kind: ServiceAccount
 metadata:
   name: metrics-server
   namespace: kube-system

Agora vamos executar os 3 arquivos

kubectl apply -f metrics.yaml
kubectl apply -f metrics-service.yaml
kubectl apply -f metrics-svc.yaml


Estamos chegando ao fim de nossa configuração , agora vamos criar a escala automática para cada projeto, para subir automaticamente os PODS quando forem chamados:

kubectl autoscale deployment byiorio-native-deployment  --cpu-percent=50 --min=1 --max=3
kubectl autoscale deployment byiorio-normal-deployment  --cpu-percent=50 --min=1 --max=3

 

kubernetes; java ; problema; nuvem; cloud; escala;




Redirecionar para https://www.byiorio.com.br/blog/4