AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 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:了解网络模型并应用TLS证书

  • 772

为了更多地了解 K8S,我开始运行单个服务器/节点 K3S 集群作为家庭实验室。但我相信我对网络模型的理解已经陷入僵局,也许是针对 K3S 的。

到目前为止一切顺利,除了我想将 TLS 证书应用于我设置的一些服务+入口。

在其中一个中,我将 TLS 证书配置为机密并将其应用到与该服务关联的 Ingress,但是我总是得到TRAEFIK DEFAULT CERT,您可以在此处查看。

据我了解,K3S 附带了预先打包的 Traefik 和 ServiceLB,以便不依赖云服务的外部负载均衡器(AWS 等)。我的第一个猜测是 Traefik 会“发现”我的 Ingress 中设置的路由并代理 TLS 流量,从而使用我设置的证书。显然情况并非如此,所以我想我需要为 Traefik 实例本身设置一个 TLS 证书。

我的问题是

  • 如何在 K3S 中设置此证书?如果我计划让多个项目/域访问此集群,我是否需要通配符证书?(我更喜欢管理每个项目的证书)
  • ServiceLB和Traefik在K3S网络模型中的作用是什么?如果 Traefik 收到 80 和 443 流量,是否只是将流量转发到 ServiceLB,然后由 ServiceLB 将其转发到 Ingress 资源?

如果需要,这是我的入口/服务配置


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
              }
            }
          }
        }
      }
    }
  }
}

谢谢你!

load-balancing
  • 2 2 个回答
  • 81 Views

2 个回答

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

    入口服务通常是 TLS 终止发生的地方 - 也就是说,当您有一个客户端(例如 Web 浏览器)访问https://指向您的 kubernetes 集群的 url 时,该客户端将连接到入口服务,该服务会协商安全连接,然后进行代理与后端服务的连接(许多入口服务器确实支持“直通”tls,其中终止实际上发生在后端,但由入口服务处理终止通常更容易、更高效)。

    来自kubernetes 文档:

    Ingress 将 HTTP 和 HTTPS 路由从集群外部公开到集群内的服务。流量路由由入口资源上定义的规则控制。

    k3s 使用 traefik 作为入口服务,因此您需要在 traefik 中配置您的 ssl 证书。

    配置默认证书

    如果没有特定于入口的 tls 证书,traefik 将使用默认证书来保护 tls 流量。traefik 将立即使用自签名证书。假设我的 k3s 集群在主机名上可用k3s.virt,我们可以看到如下:

    $ 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
    

    我们可以按照本文的说明来替换默认证书。如果我们的大多数服务将托管在同一域中,则使用通配符证书是有意义的。如果我按照链接文章中的描述创建新证书*.example.com并设置证书TLSStore,我们可以看到 Traefik 现在正在使用更新后的证书:

    $ 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
    

    如果我部署一个 pod、服务和入口,如下所示:

    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
    

    然后(假设whoami.example.com解析到集群)我们将看到入口正在使用默认证书:

    $ 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
    ...
    

    配置每个 Ingress 证书

    如果我们不想依赖默认证书(例如,如果我们需要使用不属于通配符所覆盖域的主机名),我们可以为我们的服务配置唯一的证书。traefik ingress 文档对此进行了描述。

    首先,我们需要创建一个证书并将其填充到 kubernetes 密钥中。然后我们需要通过添加以下部分来更新 Ingress 以引用证书spec.tls:

    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
    

    有了这个资源,我们看到入口不再使用默认证书:

    $ 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
    ...
    

    希望这能让事情变得更清楚一些。我在这里提供的文档链接涵盖了更详细的内容。

    我已将用于测试此配置的所有清单放置在此存储库中。


    回复您的评论:

    ServiceLB 是监视服务的东西type: LoadBalancer,并直接在集群节点上公开这些端口(例如参见这些文档)。例如,Traefik 作为kube-system命名空间中的服务,如下所示:

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

    因此,ServiceLB 将集群节点上的端口 80 和 443 映射到此服务。

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

    我已经成功地使 TLS 工作,部分感谢 @larsks 的回答,它让我了解到 K8S 配置与 Traefik 实例一起使用,因此能够找到日志并查看问题。

    我正在写一个答案,以防它将来对其他人有帮助。

    本质上,当您添加/修改Ingress资源时,K8S 会告诉 Ingress 控制器“配置”自身。在我们的例子中,Traefik 实例根据定义(即:添加路由)自行启动配置Ingress,如果定义了 TLS,它会尝试将密钥中的证书添加到其 TLSStore。

    由于 Traefik 实例正在应用新配置,因此可以在日志中找到大量必要信息。就我而言,存在不同的问题阻止将证书添加到 TLSStore。这意味着 Traefik 只有“DEFAULT TLS CERT”可用于终止。我期望它使用我放入秘密中的任何内容,即使它们是随机字符串。

    对于 K3S,您可以通过以下方式跟踪日志:

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

    创建自签名证书使我能够验证该理论,因为现在我的 HTTPS 流量是由该自签名证书而不是默认证书终止的。@larsks 的回答验证了我的配置是有意义的。如果它对任何人都有帮助,您可以使用以下命令创建自签名证书和新密钥:

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

    作为最后的接触,多个教程讨论了将“base64 编码证书”输入到密钥中,这仅意味着以 PEM 格式输入它们,而不是对 PEM 本身进行 Base64 编码(内部包含 b64 块)。Traefik 日志也让我能够检测到这个问题。base64encode您可以在我在秘密上使用的原始问题中看到。如果您碰巧使用 Let's Encrypt,则可以连接 issueser_pem 和certificate_pem 以创建链(在我的例子中,certificate_pem + issuer_pem按照该顺序完成工作)。

    • 0

相关问题

  • 网络负载平衡服务器无法相互通信

  • 用于网络监控的路由/代理 SNMP 陷阱(或 Netflow、通用 UDP 等)的解决方案?

  • 防止拒绝服务攻击的最佳技术是什么?

  • 添加备份互联网连接需要哪些硬件?

  • 什么是最有效的 Windows 负载平衡解决方案?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

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

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve