kubernetes-Ingress 资源未按预期工作,无法使用子域公开 2 个应用程序

kubernetes-Ingress resource is not working as expected to expose 2 apps using subdomains

我想在 kubernetes 上有 2 个应用程序 运行 使用入口资源指向同一端口中的每个应用程序。

我应该能够在 app1.localhost:8181/cxf 访问 app1 版本,在 app2.localhost:8181/cxf

访问 app2 版本

我正在使用 docker 与 kubernetes,mysql 和 karaf 与 kar。我正在本地 (localhost) 进行测试。

我尝试了很多在互联网上搜索的方法,包括向主机添加 ip + 主机名,但没有成功。发生的事情是它总是显示相同的应用程序,与我插入的主机名无关。

在分享我的 yaml 之前,我有一些问题:

1: 我在想也许我应该有 2 个节点?一个带有 mysql 和 app1,另一个带有 mysql 和 app2?所以在其中一个我可以访问 app1.localhost/cxf 服务,在另一个 app2.localhost/cxf 服务中……也许没有多大意义……我读到我需要 kubeadm,但没有在 windows 上安装它的方法。我想我必须改用 minikube 吗?

2: 我不应该能够创建另一个 loadBalancer 吗?我想要,所以选择器将是那个 loadBalancer 中的 app2,但由于我已经有一个,所以新的只保留 <pending> 直到我删除第一个。 但是当我安装 nginx-ingress 控制器时,它带有一个 loadBalancer 类型,如果我创建一个具有相同内容的 yaml,更改端口它将工作并且不会保持挂起...为什么?

3: 如果我有 2 个 app1 副本和 2 个 app2 副本,每个应用程序应该有一个 loadBalancer 对吗?

4: 我应该为 mysql 添加一个 loadBalancer 吗?拥有 mysql 个副本有意义吗?

5: 因为当我安装 nginx-controller 时,当我检查我的 kubernetes 仪表板时,它附带了一个 loadBalancer。可以编辑并添加我的 karaf 端口以公开服务吗?

请注意,我使用 helm 安装了 nginx ingress-controller,因为 ingress-resource 否则将无法工作,至少我是这么读的。我为此使用了头盔:https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md#using-helm

注意:mysql 工作正常,所以我没有在这里发布 yaml,这样它就不会太长。

这些是我的 yaml:

负载均衡器:(我可以代替nginx负载均衡器吗?)

apiVersion: v1
kind: Service
metadata:
  name: lb-service
spec:
  type: LoadBalancer
  selector:
    app: app1
  ports:
  - protocol: TCP
    name: app1
    port: 3306
    targetPort: 3306
  - protocol: TCP
    name: app1-8080
    port: 8080
    targetPort: 8080
  - protocol: TCP
    name: app1-8101
    port: 8101
    targetPort: 8101
  - protocol: TCP
    name: app1-8181
    port: 8181
    targetPort: 8181
status:
  loadBalancer:
    ingress:
      - hostname: localhost

app1:

apiVersion: v1
kind: Service
metadata:
  name: app1-service
spec:
  ports:
  - port: 8101
  selector:
    app: app1
  clusterIP: None
---
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: app1-deployment
spec:
  selector:
    matchLabels:
      app: app1
  replicas: 1
  template:
    metadata:
      labels:
        app: app1
    spec:
      containers:
      - name: app1
        image: app1:latest

app2: 与 app1 相同,但版本不同(较旧的服务)

ingress-resource:(这不起作用)

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: apps-ingress
  #annotations:
    #nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: app1.localhost
    http:
      paths:
      - path: /
        backend:
          serviceName: app1-service
          servicePort: 8181
  - host: app2.localhost
    http:
      paths:
      - path: /
        backend:
          serviceName: app2-service
          servicePort: 8181

嗯,我在这里遗漏了一些东西...

感谢您的宝贵时间!

编辑:

我想我发现了问题,我现在正在努力解决它。 似乎入口仅在 80 端口适用于 http,我使用 cxf 在端口 8181 下列出我的服务,而 8080 用于 soap 服务。 所以我想我必须公开那些端口,我会没事的?试试看

编辑 2:我试过了,但没有用,我遵循了这个例子:https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/

该示例工作正常,但是当我更改入口以使用我的应用程序时它不起作用。 我需要访问 :8181/cxf 才能让我的应用程序正常工作,有什么办法可以做到这一点吗? 由于入口使用端口 80,当我输入 app1.localhost 时,它与 app1.localhost:80 相同,对吧?。问题是,我需要 app1.localhost:8181/cxf 才能访问我的服务。但我想这会被翻译成:app1.localhost:80:8181/cxf ??

有人可以帮忙吗? :( 当我说端口 8181 时,我想我可以使用另一个使用 nodePort: 的端口,这基本上是端口转发对吧?但是如果我这样做的问题是,当我想部署我的第二个应用程序以在 app2.localhost 中访问时,如果我放置相同的 nodePort 它将以错误结束,因为我希望端口相同,但是不同的主机名。

回答 post 中的问题:

1: I was thinking that maybe I should have 2 nodes? one with mysql and app1 and the other one with mysql and app2? so in one I could access app1.localhost/cxf services and in the other app2.localhost/cxf services... maybe doesn't make much sense... and I was reading that I need kubeadm for that, and there is no way to install it on windows. I think I must use minikube for that instead?

您不需要有 2 个节点。您可以使用单节点 Kubernetes 安装,例如 minikube 或 Docker 桌面(使用 Kubernetes)来生成您的 app1app2mysql。我将包括该指南,以公开您在本答案末尾提到的示例应用程序。

至于kubeadm:

kubeadm performs the actions necessary to get a minimum viable cluster up and running. By design, it cares only about bootstrapping, not about provisioning machines.

Kubernetes.io: kubeadm

简而言之,kubeadm 用于机器(bare-metal、虚拟机)到 运行 配置 Kubernetes 集群的步骤(假设安装了 OS,配置等)

A tip!

minikube is using kubeadm to provision it's single node cluster.


2: shouldn't I be able to create another loadBalancer? I wanted to, so the selector would be app2 in that loadBalancer, but since I already have one, the new one just stays until I remove the first one. But when I installed the nginx-ingress controller it came with a type loadBalancer, and if I create an yaml with the same content, changing the ports it will work and wont stay pending...why?

我们需要在这里区分 2 个术语:

  • LoadBalancer 类型的服务 - 用于使用云提供商的负载平衡器向外部公开您的应用程序。在像 minikubedocker 这样的解决方案中,它通常映射到 VM 的 IP (minikube) 或本地主机你的机器 (Docker)

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

根据我的经验,LoadBalancer 类型的服务主要使用 Layer4,其中 Ingress 资源在 Layer7 上运行。 LoadBalancer 不会根据 Host header 路由您的流量。它将根据您的服务和 Deployment 的标签和选择器进行路由。 Ingress 资源旨在为 HTTP/HTTPS 流量提供服务。它将包含根据 Host header.

路由您的流量的工具

这是公开您的应用程序的 2 种不同方式,应区别对待。

A tip!

nginx-ingress is using service of type LoadBalancer to route the traffic to nginx-ingress-controller. From there it's analyzed and sent to the specific destinations (according to Ingress resource)!

您在 External-IP 列中有 Pending 的事实可能与 LoadBalancer 类型服务中使用的端口已被使用的事实有关(port 参数).


3: if I have 2 replicas of app1, and 2 replicas of app2, there should be a loadBalancer for each app right?

对于每个应用程序,您需要有一个 LoadBalancer。您的应用有多少个副本并不重要(甚至可以是 100 个)。基于上一句:

  • app1 - LoadBalancer
  • 类型的第一个服务
  • app2 - LoadBalancer
  • 类型的第二项服务

我尝试在暴露应用程序时像下面这样想(真的很简单):

  • 我公开的流量 不是 HTTP/HTTPS - LoadBalancer
  • 类型的服务
  • 我正在展示一些示例 app/apps,我需要具有 Ingress 的功能(Host 基于路由、重写、SSL 等)- Ingress资源

Disclaimer!

You don't need to use service of type LoadBalancer when exposing apps with Ingress resource.


4: Should I include a loadBalancer for mysql? does it make sense having mysql replicas?

有很多关于在 Kubernetes 中部署 mysql 的有用指南。要让 app1app2 可以访问 mysql pod,您可以使用 ClusterIPheadlessService 类型的服务。 mysql 的多个副本肯定会增加多节点集群的容错能力,但它需要已经包含某种复制逻辑。

您可以通过以下链接阅读更多内容:


5: Since when I install nginx-controller, when I check my kubernetes dashboard there is a loadBalancer that came with it. Its ok to edit and add my karaf ports to expose the service?

配置 ingress-nginx-controller 时创建的 LoadBalancer 类型的服务专门为 ingress-nginx-controller 创建。

如果您想公开您的 karaf 您可以选择:

  • 根据您的 Ingress 资源的规范,用 ingress-nginx-controller 公开它。
  • 通过TCP/UDP servicesnginx-ingress-controller暴露它(它不会有Ingress资源的特性):
  • 用另一个 LoadBalancer
  • 类型的服务示例公开它


本指南适用于 Docker Desktop 安装了 Kubernetes

假设您想要:

I should be able to access app1 version in app1.localhost:8181/cxf, and app2 version in app2.localhost:8181/cxf

假设您的 Docker 桌面有一个可用的 Kubernetes 实例,您将需要遵循以下示例:

  • 安装nginx-ingress
  • Spawn hello-one 示例应用程序和与之关联的服务
  • Spawn hello-two 示例应用程序和与之关联的服务
  • 编辑 LoadBalancer
  • 类型的 nginx-ingress 服务
  • 创建并应用 Ingress 资源
  • 进行一些 DNS 更改
  • 测试

安装nginx-ingress

运行:

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

Disclaimer!

  1. There could be differences when trying to follow this steps between Windows and Mac based environments
  2. There could be differences when trying to follow this steps on minikube instances

安装页面:


Spawn hello-one 示例应用程序和与之关联的服务

这是 hello-one 应用程序的定义:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-one
spec:
  selector:
    matchLabels:
      app: hello-one
      version: 1.0.0
  replicas: 1
  template:
    metadata:
      labels:
        app: hello-one
        version: 1.0.0
    spec:
      containers:
      - name: hello
        image: "gcr.io/google-samples/hello-app:1.0" # <-- notice the 1.0
        env:
        - name: "PORT"
          value: "50001"

这是 hello-one 应用的服务定义:

apiVersion: v1
kind: Service
metadata:
  name: hello-one-service
spec:
  type: NodePort
  selector:
    app: hello-one
    version: 1.0.0
  ports:
  - name: hello-one-port
    protocol: TCP
    port: 80
    targetPort: 50001

Spawn hello-two 示例应用程序和与之关联的服务

这是 hello-two 应用程序的定义:

apps/v1
kind: Deployment
metadata:
  name: hello-two
spec:
  selector:
    matchLabels:
      app: hello-two
      version: 2.0.0
  replicas: 1
  template:
    metadata:
      labels:
        app: hello-two
        version: 2.0.0
    spec:
      containers:
      - name: hello
        image: "gcr.io/google-samples/hello-app:2.0" # <-- notice the 2.0
        env:
        - name: "PORT"
          value: "50001"

这是 hello-two 应用的服务定义:

apiVersion: v1
kind: Service
metadata:
  name: hello-two-service
spec:
  type: NodePort
  selector:
    app: hello-two
    version: 2.0.0
  ports:
  - name: hello-two-port
    protocol: TCP
    port: 80
    targetPort: 50001

编辑 nginx-ingress 类型的服务 LoadBalancer

您需要编辑 nginx-ingress-controller 类型 LoadBalancer 的服务以支持 80443 以外的端口。

  • $ kubectl edit service -n ingress-nginx ingress-nginx-controller

负责路由的部分:

  ports:
  - name: http
    nodePort: 32202
    port: 80 # <-- CHANGE HERE FOR 8181!
    protocol: TCP
    targetPort: http
  - name: https
    nodePort: 31130
    port: 443 # <-- CHANGE HERE FOR 8182!
    protocol: TCP
    targetPort: https

创建并应用 Ingress 资源

您需要使用以下 Ingress 资源才能访问您的应用:

  • hello-one.kubernetes.local:8181/cxf
  • hello-two.kubernetes.lcoal:8181/cxf
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: hello-ingress 
spec:
  rules:
  - host: hello-one.kubernetes.docker.internal
    http:
      paths:
      - path: /
        backend:
          serviceName: hello-one-service 
          servicePort: hello-one-port
  - host: hello-two.kubernetes.docker.internal
    http:
      paths:
      - path: /
        backend:
          serviceName: hello-two-service 
          servicePort: hello-two-port

Disclaimer!

This Ingress doesn't have the /cxf path configured. You can look here for more resources:


进行一些 DNS 更改

您需要编辑主机的 DNS 设置以支持新创建的 host 名称。这部分将取决于您使用的OS。要添加的行:

127.0.0.1 hello-one.kubernetes.docker.internal
127.0.0.1 hello-two.kubernetes.docker.internal

测试

您可以通过 curl 或您的网络浏览器测试您的设置:

  • $ curl hello-one.kubernetes.docker.internal:8181
Hello, world!
Version: 1.0.0
Hostname: hello-one-696db54c4d-5fqt8
  • $ curl hello-two.kubernetes.docker.internal:8181
Hello, world!
Version: 2.0.0
Hostname: hello-two-664ddf4cf6-4jhfr