如何通过 ingress 将服务暴露给外部 Kubernetes 集群?

2023-12-09

我正在努力将 AWS 集群中的服务公开给外部并通过浏览器访问它。自从我的上一个问题还没有得出任何答案,我决定从几个方面简化问题。

首先,我创建了一个无需任何配置即可运行的部署。基于本文, I did

  1. kubectl create namespace tests

  2. 创建的文件probe-service.yaml基于paulbouwer/hello-kubernetes:1.8并部署了它kubectl create -f probe-service.yaml -n tests:

    apiVersion: v1
    kind: Service
    metadata:
      name: hello-kubernetes-first
    spec:
      type: ClusterIP
      ports:
      - port: 80
        targetPort: 8080
      selector:
        app: hello-kubernetes-first
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hello-kubernetes-first
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: hello-kubernetes-first
      template:
        metadata:
          labels:
            app: hello-kubernetes-first
        spec:
          containers:
          - name: hello-kubernetes
            image: paulbouwer/hello-kubernetes:1.8
            ports:
            - containerPort: 8080
            env:
            - name: MESSAGE
              value: Hello from the first deployment!
    
  3. created ingress.yaml并应用它(kubectl apply -f .\probes\ingress.yaml -n tests)

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: hello-kubernetes-ingress
    spec:
      rules:
      - host: test.projectname.org
        http:
          paths:
          - pathType: Prefix
            path: "/test"
            backend:
              service:
                name: hello-kubernetes-first
                port:
                  number: 80
      - host: test2.projectname.org
        http:
          paths:
          - pathType: Prefix
            path: "/test2"
            backend:
              service:
                name: hello-kubernetes-first
                port:
                  number: 80
      ingressClassName: nginx
    

其次,我可以看到 DNS 实际上指向集群并且应用了入口规则:

  • 如果我打开http://test.projectname.org/test或任何不相关的路径(http://test.projectname.org/test3),我看到NET::ERR_CERT_AUTHORITY_INVALID, but
  • 如果我在浏览器中使用“无论如何打开”,则不相关的路径会给出ERR_TOO_MANY_REDIRECTS while http://test.projectname.org/test gives Cannot GET /test

现在,撇开 TLS 问题不谈(这些问题值得单独讨论),为什么我可以得到Cannot GET /test?看起来入口控制器(ingress-nginx)获得了规则(否则它不会区分路径;这就是为什么我不显示 DNS 设置,尽管它们在上一个问题中进行了描述),而是显示了简单的 hello-kubernetes页面位于/test它返回这个简单的 404 消息。这是为什么?可能会出现什么问题?如何调试这个?

一些调试信息:

  • kubectl version --short告诉 Kubernetes 客户端版本是 v1.21.5,服务器版本是 v1.20.7-eks-d88609

  • kubectl get ingress -n tests表明hello-kubernetes-ingress确实存在,与nginx类,2 个预期主机,地址等于 AWS 控制台中负载均衡器显示的地址

  • kubectl get all -n tests shows

    NAME                                          READY   STATUS    RESTARTS   AGE
    pod/hello-kubernetes-first-6f77d8ff99-gjw5d   1/1     Running   0          5h4m
    pod/hello-kubernetes-first-6f77d8ff99-ptwsn   1/1     Running   0          5h4m
    pod/hello-kubernetes-first-6f77d8ff99-x8w87   1/1     Running   0          5h4m
    
    NAME                             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
    service/hello-kubernetes-first   ClusterIP   10.100.18.189   <none>        80/TCP    5h4m
    
    NAME                                     READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/hello-kubernetes-first   3/3     3            3           5h4m
    
    NAME                                                DESIRED   CURRENT   READY   AGE
    replicaset.apps/hello-kubernetes-first-6f77d8ff99   3         3         3       5h4m
    
  • ingress-nginx通过以下图表在我之前安装:

    apiVersion: v2
    name: nginx
    description: A Helm chart for Kubernetes
    type: application
    version: 4.0.6
    appVersion: "1.0.4"
    dependencies:
    - name: ingress-nginx
      version: 4.0.6
      repository: https://kubernetes.github.io/ingress-nginx
    

    并且应用于图表的值覆盖不同于原创的大部分(嗯,这些自安装以来已更新)extraArgs: default-ssl-certificate: "nginx-ingress/dragon-family-com"未联网

PS为了回答Andrew,我确实尝试设置HTTPS,但它似乎没有帮助,所以我没有将我尝试过的内容包含在最初的问题中。然而,这就是我所做的:

  1. 安装了 cert-manager,目前没有自定义图表:kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.5.4/cert-manager.yaml

  2. 基于证书管理器教程 and 所以问题使用以下配置创建了 ClusterIssuer:

    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
      name: letsencrypt-backoffice
    
    spec:
      acme:
        server: https://acme-staging-v02.api.letsencrypt.org/directory
        # use https://acme-v02.api.letsencrypt.org/directory after everything is fixed and works
        privateKeySecretRef: # this secret will be created in the namespace of cert-manager
          name: letsencrypt-backoffice-private-key
        # email: <will be used for urgent alerts about expiration etc>
    
        solvers:
        # TODO: add for each domain/second-level domain/*.projectname.org
        - selector:
            dnsZones:
              - test.projectname.org
              - test2.projectname.org
          # haven't made it to work yet, so switched to the simpler to configure http01 challenge
          # dns01:
          #   route53:
          #     region: ... # that of load balancer (but we also have ...)
          #     accessKeyID: <of IAM user with access to Route53>
          #     secretAccessKeySecretRef: # created that
          #       name: route53-credentials-secret
          #       key: secret-access-key
          #     role: arn:aws:iam::645730347045:role/cert-manager
          http01:
            ingress:
              class: nginx
    

    并通过应用它kubectl apply -f issuer.yaml

  3. 在同一文件中创建 2 个证书并再次应用:

    ---
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: letsencrypt-certificate
    spec:
      secretName: tls-secret
      issuerRef:
        kind: ClusterIssuer
        name: letsencrypt-backoffice
      commonName: test.projectname.org
      dnsNames:
      - test.projectname.org
    ---
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: letsencrypt-certificate-2
    spec:
      secretName: tls-secret-2
      issuerRef:
        kind: ClusterIssuer
        name: letsencrypt-backoffice
      commonName: test2.projectname.org
      dnsNames:
      - test2.projectname.org
    
  4. 确保证书正确颁发(跳过痛苦部分,结果是:kubectl get certificates表明两个证书都有READY = true并且创建了两个 tls 秘密)

  5. 发现我的入口位于另一个命名空间中,并且入口规范中的 tls 的秘密can only在同一名称空间中引用(尚未尝试通配符证书和--default-ssl-certificate选项),因此对于每个将它们复制到tests命名空间:

    1. 打开现有的秘密,比如kubectl edit secret tls-secret-2、复制数据和注释
    2. 在测试中创建了一个空(不透明)秘密:kubectl create secret generic tls-secret-2-copy -n tests
    3. 打开它(kubectl edit secret tls-secret-2-copy -n tests)并插入数据和注释
  6. 在入口处spec,添加了 tls 位:

    tls:
    - hosts:
      - test.projectname.org
      secretName: tls-secret-copy
    - hosts:
      - test2.projectname.org
      secretName: tls-secret-2-copy
    
  7. 我希望这会有所帮助,但实际上这没有什么区别(我明白ERR_TOO_MANY_REDIRECTS对于不相关的路径,从http重定向到https,NET::ERR_CERT_AUTHORITY_INVALID在 https 和Cannot GET /test如果我坚持要访问该页面)


由于您已经使用自己的答案来补充问题,因此我将回答您提出的所有问题,同时提供分而治之的策略来排除 kubernetes 网络故障。

最后我会给你一些nginx和IP的答案

这是对的

- host: test3.projectname.org
http:
  paths:
  - pathType: Prefix
    path: "/"
    backend:
      service:
        name: hello-kubernetes-first
        port:
          number: 80

使用 Ingress 分解故障排除

  1. DNS
  2. Ingress
  3. Service
  4. Pod
  5. 证书

1.DNS

您可以使用命令 dig 来查询 DNS

dig google.com dig result

  1. Ingress

入口控制器不查找 IP,它只查找标头

您可以使用任何可以更改标头的工具强制主机,例如curl

curl --header 'Host: test3.projectname.com' http://123.123.123.123(您的公共IP)

  1. Service

您可以通过创建 ubuntu/centos pod 来确保您的服务正在运行,使用kubectl exec -it podname -- bash并尝试在集群内卷曲您的服务表单

  1. Pod

你得到这个

192.168.14.57 - - [14/Nov/2021:12:02:58 +0000] "GET /test2 HTTP/2.0" 404 144
 "-" "<browser's user-agent header value>" 448 0.002

这部分GET /test2意味着请求从 DNS 获取地址,从互联网一路发送,找到您的集群,找到您的入口控制器,通过服务并到达您的 pod。恭喜!你的入口正在工作!

但是为什么会返回404呢?

传递到服务以及从服务到 pod 的路径是 /test2

你有 nginx 可以提供的名为 test2 的文件吗?你的 nginx 中是否有一个带有 test2 前缀的上游配置?

这就是为什么,您从 nginx 而不是从入口控制器获得 404。

这些 IP 是内部的,请记住,互联网流量在集群边界结束,现在您位于内部网络中。这是正在发生的事情的粗略草图

假设您正在从笔记本电脑访问它。您的笔记本电脑的 IP 为 192.168.123.123,但您的家庭地址为 7.8.9.1,因此当您的请求到达集群时,集群会看到 7.8.9.1 请求 test3.projectname.com。

集群寻找入口控制器,入口控制器找到合适的配置并将请求传递给服务,服务再将请求传递给 Pod。

So,

your router can see your private IP (192.168.123.123)
Your cluster(ingress) can see your router's IP (7.8.9.1)
Your service can see the ingress's IP (192.168.?.?)
Your pod can see the service's IP (192.168.14.57)

这是一个传递的游戏。 如果您想在 nginx 日志中查看公共 IP,则需要对其进行自定义以获取 X-Real-IP 标头,该标头通常是负载均衡器/入口/大使/代理放置实际请求者公共 IP 的位置。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何通过 ingress 将服务暴露给外部 Kubernetes 集群? 的相关文章

随机推荐

  • Lua关闭/程序执行结束回调

    我正在为 Lua 编写一个模块 关闭 lua 解释器时 即使用户忘记隐式调用关闭例程 它也必须运行清理例程 该模块主要是用 C 编写的 我应该使用 Lua C Api 中的哪个回调来检测程序执行结束 我唯一的想法是在代表我的模块的表上使用
  • Angular 7 滤波器阵列

    我有以下角度组件 private json JsonResponseDTO constructor private dtoService PoolDTOServiceService ngOnInit this dtoService setJ
  • 如何使用 apt 安装指定版本的 Ruby

    我尝试安装指定版本 2 5 1 的 Ruby 该版本只是示例 并尝试执行以下脚本 但出现如下错误 是否可以使用 apt 安装来安装 Ruby 版本 以便我可以处理 Ruby 版本依赖性问题 sudo apt update sudo apt
  • rxjava:我可以使用 retry() 但有延迟吗?

    我在 Android 应用程序中使用 rxjava 来异步处理网络请求 现在我想仅在经过一定时间后重试失败的网络请求 有没有办法在 Observable 上使用 retry 但仅在一定延迟后重试 有没有办法让 Observable 知道当前
  • 为什么我收到“没有为复数定义排序关系”错误?

    See 这个问题一些背景 我在该问题上的主要问题已解决 建议我向另一个问题询问我遇到的第二个问题 print cubic 1 2 3 4 Correct solution about 1 65 if x gt 0 TypeError no
  • 如何在 django 模板中迭代查询集列表

    有没有办法在模板中迭代这个查询集列表
  • 解析 Prolog 中的表达式并返回抽象语法

    我必须编写 parse Tkns T 它接受标记列表形式的数学表达式并找到 T 并返回表示抽象语法的语句 尊重操作顺序和关联性 例如 parse num 3 plus num 2 star num 1 T T add integer 3 m
  • javascript - 在 html 中使用函数调用 - 坏还是好?

    使用 Angular 会带来很多奇怪的代码风格 比如我一直以为这个
  • 使用 PHP 和 Apache 路由 URL 路径

    我正在尝试为我的网站创建一个漂亮的网址结构 我的路由器类仅在 url 的样式为 something value 时才起作用 我如何得到它 它的工作方式如下 something value 在我的 htaccess 中我有 Options F
  • 修改默认的 HTML5 视频控件

    我有一个相当不寻常的问题要问你们 这可能很愚蠢 但我是这个领域的新手 我真的很感激一些帮助 正如标题所示 我想知道是否有一种方法可以禁用默认浏览器控件中的特定按钮HTML5 video 我知道每个浏览器都有自己独特的一组控件 所以我认为我不
  • 有没有办法在 TextStream 文件中向后导航?

    我已经开始使用 fso 对象来克服 VBA 的 2GB 限制 一切看起来都符合我的目的 只是我找不到路要走向后在文本流文件中 为了继续前进 我使用了读取 字符数 和跳过 字符数 有办法这样做吗 我遇到了同样令人沮丧的限制 这是一个包装本机
  • 无法加载文件或程序集 HRESULT:0x80131515(将控制器添加到网络驱动器上具有程序集引用的 MVC 项目时)

    我见过这个 VSTS 2010 SGEN 错误 无法加载文件或程序集 HRESULT 异常 0x80131515 并且所有答案都不起作用 当我构建或执行任何操作时它也不会出现 我可以正常运行该项目 当我尝试添加实体框架模板化控制器时会发生这
  • 如何创建一个防止新头出现的水银钩?

    我有几个从 SVN 转换而来的存储库 并且我们希望确保当人们推送到存储库时他们无法创建额外的头 里面有几个钩子提示和技巧 wiki 页面如果有多个头 则可以防止推动 但是我如何构建一个防止推动的钩子new heads 似乎正确的方法是比较修
  • 如何为 Kubernetes 中托管的多个应用程序选择 Kafka 事务 ID?

    我有一个经典的微服务架构 所以 有不同的应用 每个应用程序可能有1 N实例 该系统部署到Kubernetes 所以 我们有很多不同PODs 可以随时启动和停止 我想实施读 处理 写模式 所以我需要 Kafka 事务 要配置交易 我需要设置一
  • 我在哪里对我的密码进行加盐和哈希处理?在客户端还是在主机?

    我认为直接在客户端计算机上对密码进行加盐和哈希处理会更明智 原因是 我实际上从来不想获取用户的密码 这个字符串应该对他保密 而不是对我们俩保密 现在有人争论说 你想对盐保密 所以你不能通过通道以明文形式发送它 显然 事实并非如此 所以现在我
  • 如何将行号投影到 Linq 查询结果中

    如何将行号投影到 linq 查询结果集上 而不是说 字段 1 字段 2 字段 3 字段 1 字段 2 字段 3 我想 1 字段1 字段2 字段3 2 字段1 字段2 字段3 这是我的尝试 public List
  • 如何在 Customer.create 之后解析 Stripe JSON 响应?

    我读过使用此版本 Stripe API 的其他线程 但实际解析嵌套 JSON 的问题从未得到解答 例如 创建信用卡后如何解析 Stripe JSON 响应 或标记为重复 例如 如何读取 stripe webhook 响应 通过 重复的起源
  • 事件句柄和可见

    好的 我正在为我的班级做一个项目 我必须将所有内容都放在一页上 并在顶部有一个菜单 菜单中应该有新建 打开 来自 Html 保存和退出 我已经完成了除了 From HTML 之外的所有操作 我有点困惑 当用户单击 来自 HTML 时 需要将
  • java和python之间传递数据

    如果我的问题很菜鸟 我很抱歉 我正在运行 Django 1 2 和 pgsql 8 4 我需要在获取用户的输入后运行 Java 程序 进行一些计算并将结果返回给用户 我可以知道在 Java 和 Python Django 之间传递数据的最佳
  • 如何通过 ingress 将服务暴露给外部 Kubernetes 集群?

    我正在努力将 AWS 集群中的服务公开给外部并通过浏览器访问它 自从我的上一个问题还没有得出任何答案 我决定从几个方面简化问题 首先 我创建了一个无需任何配置即可运行的部署 基于本文 I did kubectl create namespa