我的 ingress yaml 文件或流程有错误吗?

Mistakes in my ingress yaml file or process?

我正在尝试 kubernetes 并取得了一些进展,但在尝试公开我的 hello world 应用程序时,我 运行 遇到了入口问题。

部署和服务成功

我创建了一个简单的 hello world 类型的 nodejs 应用程序并将图像推送到我的 docker 中心 johnlai2004/swarm2。我使用此 yaml 文件成功创建了部署和服务:

nodejs.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodejs-hello
  labels:
    app: nodejs-hello
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nodejs-hello
  template:
    metadata:
      labels:
        app: nodejs-hello
    spec:
      containers:
      - name: nodejs-hello
        image: johnlai2004/swarm2
        ports:
        - containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
  name: nodejs-hello-service
spec:
  selector:
    app: nodejs-hello
  type: LoadBalancer
  ports:
    - protocol: TCP
      port: 3000
      targetPort: 3000
      nodePort: 30000

我将这些文件上传到 VPS 并安装了 ubuntu 20.04、minikube、kubectl 和 docker.

我运行下面的命令得到了我想要的结果:

minikube start --driver=docker
kubectl apply -f nodejs.yaml
minikube service nodejs-hello-service
|-----------|----------------------|-------------|---------------------------|
| NAMESPACE |         NAME         | TARGET PORT |            URL            |
|-----------|----------------------|-------------|---------------------------|
| default   | nodejs-hello-service |        3000 | http://192.168.49.2:30000 |
|-----------|----------------------|-------------|---------------------------|

当我执行 wget http://192.168.49.2:30000 时,我得到一个 index.html 文件,上面写着 hello from nodejs-hello-556dc868-6lrdz at 12/19/2021, 10:29:56 PM。这太完美了。

进入失败

接下来,我想使用 ingress 以便我可以看到位于 http://website.example.com 的页面(将 website.example.com 替换为指向我的服务器的实际域)。我把这个文件放在我的服务器上:

nodejs-ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nodejs-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
    - host: website.example.com
      http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: nodejs-hello-service
              port:
                number: 3000

我运行命令

minikube addons enable ingress
kubectl apply -f nodejs-ingress.yaml
kubectl get ingress
NAME             CLASS    HOSTS                   ADDRESS     PORTS   AGE
nodejs-ingress   <none>   website.example.com     localhost   80      15m

但是当我用浏览器访问http://website.example.com时,浏览器说无法连接。使用 wget http://website.example.com 出现相同的连接问题。

谁能指出我做错了什么?


更新

我 运行 这些命令是因为我认为它表明我没有以正确的名称安装 ingress-controller space?

kubectl get pod -n ingress-nginx
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create--1-tqsrp     0/1     Completed   0          4h25m
ingress-nginx-admission-patch--1-sth26      0/1     Completed   0          4h25m
ingress-nginx-controller-5f66978484-tmx72   1/1     Running     0          4h25m

kubectl get pod -n default
NAME                          READY   STATUS    RESTARTS   AGE
nodejs-hello-556dc868-6lrdz   1/1     Running   0          40m

这是否意味着我的 nodejs 应用的名称 space 无法访问入口控制器?


更新 2

我也试着按照 this guide 一步一步来。 我注意到的一个区别是当我 运行 命令 kubectl get ingress 时,ADDRESSlocalhost。但是在指南中,它说它应该是 172.17.0.15

这种差异重要吗?我在名为 linode.com 的云 vps 中托管东西。这会改变我做事的方式吗?

能不能试试kubectl get ingress nodejs-ingress看ingress资源是否创建成功

然后用 curl -H 'HOST: <replace with HOSTS from the output of get ingress command>' http://<ADDRESS from the output of get ingress command>:<PORTS from the output of get ingress command>

卷曲

您的行为符合预期。让我解释一下为什么。一点一滴地讲,最后我会提出我的建议。

首先,我认为有必要介绍一下 minikube 架构。我假设您已经使用默认驱动程序 docker 安装了 minikube,因为您的地址 192.168.49.2docker driver.

的标准地址

图层是:

  • 你的虚拟机 Ubuntu 20.04
  • Kubernetes 集群由 minikube 设置,它是 docker VM 上地址为 192.168.49.2 的容器

所以...您不能只 运行 curl 在 VM 上使用 localhost 地址连接到服务。 The localhost is referring to the device that you are making curl request (so your VM),不是 docker 容器。这就是为什么您需要使用 192.168.49.2 地址。

你可以输入docker ps -a,你会看到容器是一个真正的Kubernetes集群。您可以使用 docker exec 命令执行它,然后使用 运行 curl 命令和本地主机地址:

user@example-ubuntu-minikube-template-1:~$ curl -H "Host: hello-world.info" localhost
curl: (7) Failed to connect to localhost port 80: Connection refused
user@example-ubuntu-minikube-template-1:~$ docker ps -a
CONTAINER ID   IMAGE                                 COMMAND                  CREATED      STATUS      PORTS                                                                                                                                  NAMES
1a4ba3895990   gcr.io/k8s-minikube/kicbase:v0.0.28   "/usr/local/bin/entr…"   4 days ago   Up 4 days   127.0.0.1:49157->22/tcp, 127.0.0.1:49156->2376/tcp, 127.0.0.1:49155->5000/tcp, 127.0.0.1:49154->8443/tcp, 127.0.0.1:49153->32443/tcp   minikube
user@example-ubuntu-minikube-template-1:~$ docker exec -it 1a sh
# curl -H "Host: hello-world.info" localhost
Hello, world!
Version: 1.0.0
Hostname: web-79d88c97d6-nl4c7

请记住,您只能从托管此容器的 VM 访问此容器。如果没有任何进一步的配置,您不能只从其他 VM 访问它。可以,但不推荐。

很好的解释在minikube FAQ:

How can I access a minikube cluster from a remote network?

minikube’s primary goal is to quickly set up local Kubernetes clusters, and therefore we strongly discourage using minikube in production or for listening to remote traffic. By design, minikube is meant to only listen on the local network.

However, it is possible to configure minikube to listen on a remote network. This will open your network to the outside world and is not recommended. If you are not fully aware of the security implications, please avoid using this.

For the docker and podman driver, use --listen-address flag:

minikube start --listen-address=0.0.0.0

所以我会避免它。我会在答案的最后提出一个更好的可能解决方案。

您问的是:

But when I visit http://website.example.com with my browser, the browser says it can't connect. Using wget http://website.example.com gave the same connection issue.

Can someone point out what I may have done wrong?

您的计算机不知道它是什么website.example.com。它不知道您的 Ingress 使用了此名称。如果您的计算机在 hosts file 中找不到此名称,它将开始通过 Internet 查找此名称。

所以你有一些可能的解决方案:

  • 使用 curl -H 'HOST: website.example.com' http://192.168.49.2:80 - 它只适用于 minikube
  • 所在的虚拟机
  • add host to the hosts file - 类似于 192.168.49.2 website.example.com - 它只能在 minikube
  • 所在的虚拟机上运行
  • 设置裸机集群(总结部分有更多详细信息)并将域地址指向 VM 地址。在 GCP 和 AWS 中,您可以使用 Google Cloud DNS or Amazon Route 53. On linode cloud maybe this one - DNS Manager ?

编辑: 你写道你有一个指向服务器的域,所以请检查我的答案的总结部分。

你还问了:

I ran these commands because I think it shows I didn't install ingress-controller in the right name space?

So does this mean my nodejs app is in a name space that doesn't have access to the ingress controller?

It's absolutely normal:

It will install the controller in the ingress-nginx namespace, creating that namespace if it doesn't already exist.

还有:

I also tried following this guide step by step: https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/

One difference I noticed was when I ran the command kubectl get ingress, ADDRESS says localhost. But in the guide, it says it is supposed to be 172.17.0.15

Does this difference matter? I'm hosting things in a cloud vps called linode.com. Does that change the way I do things?

将 minikube 与 docker 驱动程序一起使用时,这也是正常和预期的。

总结/其他技巧:

  • Minkube 适合本地测试;您可以使用主机轻松访问应用程序和服务 - 检查 Accessing apps
  • 但是,要将其暴露在网络之外,您应该考虑使用 kubeadm or kubespray for cluster setup + MetalLB for LoadBalancer solution. Check "Bare-metal considerations" and Exposing a Kubernetes service on a bare-metal cluster over the external network architecture
  • 等解决方案
  • 如果您打算将服务与入口一起使用,请不要使用 LoadBalancer 类型。用ClusterIP就可以了