AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / server / Perguntas / 1156016
Accepted
Jo Colina
Jo Colina
Asked: 2024-03-10 22:33:39 +0800 CST2024-03-10 22:33:39 +0800 CST 2024-03-10 22:33:39 +0800 CST

K3S: entendendo o modelo de rede e aplicando certificados TLS

  • 772

Para aprender um pouco mais sobre o K8S, comecei a executar um cluster K3S de servidor/nó único como um laboratório doméstico. Mas acredito que cheguei a um impasse na minha compreensão do modelo de rede, talvez específico do K3S.

Até aí tudo bem, exceto que eu queria aplicar um certificado TLS a alguns serviços + entradas que configurei.

Em um deles configurei um certificado TLS como segredo e apliquei no Ingress associado ao serviço, porém sempre consigo o TRAEFIK DEFAULT CERT, que você pode ver aqui .

Pelo que entendi, o K3S vem com Traefik e ServiceLB pré-empacotados para não depender de balanceadores de carga externos de serviços em nuvem (AWS etc). Meu primeiro palpite foi que o Traefik iria "descobrir" as rotas configuradas em meu Ingress e fazer proxy do tráfego TLS, usando assim o certificado que configurei. Claramente, este não é o caso, então suponho que preciso configurar um certificado TLS para a própria instância do Traefik.

Minhas perguntas são então

  • Como posso configurar este certificado no K3S e preciso de um certificado curinga se pretendo ter vários projetos/domínios atingindo este cluster? (Eu preferiria gerenciar os certificados por projeto)
  • Quais são as funções do ServiceLB e do Traefik no modelo de rede K3S? Se o Traefik estiver obtendo o tráfego 80 e 443, ele está apenas encaminhando o tráfego para o ServiceLB, que o encaminhará para o recurso Ingress?

Caso seja necessário, aqui está minha configuração de entrada/serviço


resource kubernetes_service_v1 snitch_service {
  metadata {
    name = "snitch"
    namespace = module.namespace.name
  }


  spec {
    selector = {
      app = "snitch"
    }

    type = "LoadBalancer"

    port {
      name = "main"
      port = 3010
      target_port = 3000
      node_port = 30003
    }
  }
}



resource kubernetes_secret_v1 tls_secret {
  metadata {
    name = "snitch-tls-cert"
    namespace = "my-namespace"
  }

  type = "kubernetes.io/tls"

  data = {
    "tls.crt" = base64encode(my_certificate)
    "tls.key" = base64encode(my_certificate_private_key)
  }
}


resource kubernetes_ingress_v1 snitch_ingress {
  metadata {
    name = "snitch"
    namespace = "my-namespace"

    annotations = {
      "ingress.kubernetes.io/ssl-redirect" = "false"
    }
  }

  spec {
    tls {
      hosts = [local.subdomain]
      secret_name = "snitch-tls-cert"
    }

    rule {
      host = local.subdomain

      http {
        path {
          path = "/"
          path_type = "Prefix"

          backend {
            service {
              name = "snitch"
              port {
                number = 3010
              }
            }
          }
        }
      }
    }
  }
}

Obrigado!

load-balancing
  • 2 2 respostas
  • 81 Views

2 respostas

  • Voted
  1. Best Answer
    larsks
    2024-03-14T20:35:08+08:002024-03-14T20:35:08+08:00

    O serviço de entrada geralmente é onde ocorrem as terminações de TLS - ou seja, quando você tem um cliente como um navegador da Web acessando uma https://URL que aponta para seu cluster Kubernetes, o cliente está se conectando ao serviço de entrada, que negocia a conexão segura e, em seguida, faz proxy a conexão com seu serviço de back-end (muitos servidores de entrada têm suporte para tls de "passagem", onde a terminação realmente acontece no back-end, mas geralmente é mais fácil e com melhor desempenho ter a terminação tratada pelo serviço de entrada).

    Da documentação do Kubernetes :

    O Ingress expõe rotas HTTP e HTTPS de fora do cluster para serviços dentro do cluster. O roteamento de tráfego é controlado por regras definidas no recurso Ingress.

    k3s usa traefik como serviço de entrada, então você precisa configurar seus certificados SSL no traefik.

    Configurando o certificado padrão

    Na ausência de um certificado tls específico de entrada, o traefik usará um certificado padrão para proteger o tráfego tls. Pronto para uso, o traefik usará um certificado autoassinado. Supondo que meu cluster k3s esteja disponível no hostname k3s.virt, podemos vê-lo assim:

    $ openssl s_client -showcerts -connect k3s.virt:443 < /dev/null 2> /dev/null | openssl x509 -noout -subject -issuer
    subject=CN = TRAEFIK DEFAULT CERT
    issuer=CN = TRAEFIK DEFAULT CERT
    

    Podemos seguir as instruções deste artigo para substituir o certificado padrão. Se a maioria dos nossos serviços for hospedada no mesmo domínio, faz sentido usar um certificado curinga. Se eu criar um novo certificado *.example.come configurar TLSStoreconforme descrito no artigo vinculado, podemos ver que o Traefik agora está usando o certificado atualizado:

    $ openssl s_client -showcerts -connect k3s.virt:443 < /dev/null 2> /dev/null | openssl x509 -noout -subject -issuer -ext subjectAltName
    subject=CN = default-router.example.com
    issuer=CN = default-router.example.com
    X509v3 Subject Alternative Name: 
        DNS:*.example.com
    

    Se eu implantar um pod, serviço e entrada, assim:

    apiVersion: v1
    kind: Service
    metadata:
      labels:
        app: whoami
      name: whoami
    spec:
      ports:
      - name: http
        port: 80
        targetPort: http
      selector:
        app: whoami
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: whoami
      name: whoami
    spec:
      selector:
        matchLabels:
          app: whoami
      template:
        metadata:
          labels:
            app: whoami
        spec:
          containers:
          - image: docker.io/traefik/whoami:latest
            name: whoami
            ports:
            - containerPort: 80
              name: http
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      labels:
        app: whoami
      name: example
    spec:
      ingressClassName: traefik
      rules:
      - host: whoami.example.com
        http:
          paths:
          - backend:
              service:
                name: whoami
                port:
                  name: http
            path: /
            pathType: Prefix
    

    Então (assumindo que isso whoami.example.comresolve para o cluster) veremos que a entrada está usando o certificado padrão:

    $ curl -sk -vvI https://whoami.example.com
    ...
    * Server certificate:
    *  subject: CN=default-router.example.com
    *  start date: Mar 14 12:02:54 2024 GMT
    *  expire date: Mar 12 12:02:54 2034 GMT
    *  issuer: CN=default-router.example.com
    ...
    

    Configurando certificados por Ingress

    Se não quisermos depender do certificado padrão (por exemplo, se precisarmos usar um nome de host que não faça parte do domínio coberto pelo curinga), podemos configurar um certificado exclusivo para nosso serviço. Isso está descrito na documentação de entrada do traefik .

    Primeiro, precisamos criar um certificado e colocá-lo em um segredo do Kubernetes. Então precisamos atualizar nosso Ingress para fazer referência ao certificado adicionando uma spec.tlsseção:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      labels:
        app: whoami
      name: example
    spec:
      ingressClassName: traefik
      rules:
      - host: whoami.example.com
        http:
          paths:
          - backend:
              service:
                name: whoami
                port:
                  name: http
            path: /
            pathType: Prefix
      tls:
      - secretName: whoami-certificate
    

    Com esse recurso implementado, vemos que o ingresso não está mais usando o certificado padrão:

    $ curl -sk -vvI https://whoami.example.com
    ...
    * Server certificate:
    *  subject: CN=whoami.example.com
    *  start date: Mar 14 12:07:16 2024 GMT
    *  expire date: Mar 12 12:07:16 2034 GMT
    *  issuer: CN=whoami.example.com
    ...
    

    Espero que isso esclareça um pouco as coisas. Os links de documentação que forneci aqui cobrem as coisas com muito mais detalhes.

    Coloquei todos os manifestos que usei para testar esta configuração neste repositório .


    Respondendo aos seus comentários:

    ServiceLB é o que monitora os serviços type: LoadBalancere expõe essas portas diretamente nos nós do cluster (consulte, por exemplo, estes documentos ). Por exemplo, Traefik como um serviço no kube-systemnamespace semelhante a este:

    ports:
      - name: web
        port: 80
        protocol: TCP
        targetPort: web
      - name: websecure
        port: 443
        protocol: TCP
        targetPort: websecure
    type: LoadBalancer
    

    Portanto, o ServiceLB mapeia as portas 80 e 443 nos nós do cluster para este serviço.

    • 1
  2. Jo Colina
    2024-03-16T14:49:45+08:002024-03-16T14:49:45+08:00

    Consegui fazer o TLS funcionar em parte graças à resposta de @larsks, isso me levou a entender que a configuração do K8S está brincando com a instância do Traefik e, portanto, consegui encontrar os logs e ver o problema.

    Estou escrevendo uma resposta caso ela seja útil para outra pessoa no futuro.

    Essencialmente, quando você adiciona/modifica um Ingressrecurso, o K8S informa ao controlador do Ingress para se "configurar". No nosso caso, a instância Traefik lança uma configuração em si mesma dependendo do definido Ingress(ou seja: adicionando rotas), e se houver TLS definido ela tenta adicionar o certificado no segredo ao seu TLSStore.

    Como a instância do Traefik está aplicando uma nova configuração, muitas informações necessárias podem ser encontradas nos logs. No meu caso, houve diversos problemas que impediram que o certificado fosse adicionado ao TLSStore . O que significa que o Traefik só tinha o "DEFAULT TLS CERT" disponível para encerrar. Eu esperava que ele usasse tudo o que eu colocasse no segredo, mesmo que fossem strings aleatórias.

    Para K3S, você pode acompanhar os logs com:

    kubectl logs -f <the_traefik_pod_id> -n kube-system
    

    A criação de um certificado autoassinado me permitiu validar a teoria, pois agora meu tráfego HTTPS estava sendo encerrado por esse certificado autoassinado e não pelo certificado padrão. A resposta do @larsks validou que minha configuração fazia sentido. Caso seja útil para alguém, você pode criar um certificado autoassinado e uma nova chave com este comando:

    openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
    

    Como toque final, vários tutoriais falaram sobre inserir os "certificados codificados em base64" no segredo, o que significa apenas inseri-los no formato PEM, e não na codificação base64 do próprio PEM (que contém um bloco b64 dentro). Os logs do Traefik também me permitiram detectar esse problema. Você pode ver na pergunta original que eu estava usando base64encodeo segredo. E se acontecer de você usar o Let's Encrypt, você pode concatenar o issuer_pem e o Certificate_pem para criar a cadeia (no meu caso, certificate_pem + issuer_pemessa ordem faz o trabalho).

    • 0

relate perguntas

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Você pode passar usuário/passar para autenticação básica HTTP em parâmetros de URL?

    • 5 respostas
  • Marko Smith

    Ping uma porta específica

    • 18 respostas
  • Marko Smith

    Verifique se a porta está aberta ou fechada em um servidor Linux?

    • 7 respostas
  • Marko Smith

    Como automatizar o login SSH com senha?

    • 10 respostas
  • Marko Smith

    Como posso dizer ao Git para Windows onde encontrar minha chave RSA privada?

    • 30 respostas
  • Marko Smith

    Qual é o nome de usuário/senha de superusuário padrão para postgres após uma nova instalação?

    • 5 respostas
  • Marko Smith

    Qual porta o SFTP usa?

    • 6 respostas
  • Marko Smith

    Linha de comando para listar usuários em um grupo do Windows Active Directory?

    • 9 respostas
  • Marko Smith

    O que é um arquivo Pem e como ele difere de outros formatos de arquivo de chave gerada pelo OpenSSL?

    • 3 respostas
  • Marko Smith

    Como determinar se uma variável bash está vazia?

    • 15 respostas
  • Martin Hope
    Davie Ping uma porta específica 2009-10-09 01:57:50 +0800 CST
  • Martin Hope
    kernel O scp pode copiar diretórios recursivamente? 2011-04-29 20:24:45 +0800 CST
  • Martin Hope
    Robert ssh retorna "Proprietário incorreto ou permissões em ~/.ssh/config" 2011-03-30 10:15:48 +0800 CST
  • Martin Hope
    Eonil Como automatizar o login SSH com senha? 2011-03-02 03:07:12 +0800 CST
  • Martin Hope
    gunwin Como lidar com um servidor comprometido? 2011-01-03 13:31:27 +0800 CST
  • Martin Hope
    Tom Feiner Como posso classificar a saída du -h por tamanho 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich O que é um arquivo Pem e como ele difere de outros formatos de arquivo de chave gerada pelo OpenSSL? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent Como determinar se uma variável bash está vazia? 2009-05-13 09:54:48 +0800 CST

Hot tag

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve