【问题标题】:Bare-metal k8s ingress with nginx-ingress裸机 k8s 入口与 nginx-ingress
【发布时间】:2021-05-16 11:38:24
【问题描述】:

我无法应用入口配置。

我需要通过它的 DNS 访问 jupyter-lab 服务

已部署到 3 节点裸机 k8s 集群

  • node1.local(主)
  • node2.local (worker)
  • node3.local (worker)

Flannel 被安装为网络控制器

我已经为这样的裸机安装了 nginx 入口

  • kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.44.0/deploy/static/provider/baremetal/deploy.yaml

部署时,jupyter-lab pod 位于 node2 上,NodePort 服务从 http://node2.local:30004 正确响应(见下文)

我希望 ingress-nginx 控制器会通过其 DNS 名称公开 ClusterIP 服务......这就是我所需要的,是不是错了?

这是 CIP 服务,使用对称端口 8888 定义尽可能简单(有错吗?)

---
apiVersion: v1
kind: Service
metadata:
  name: jupyter-lab-cip
  namespace: default
spec:
  type: ClusterIP
  ports:
    - port: 8888
      targetPort: 8888
  selector:
    app: jupyter-lab
  • DNS 名称 jupyter-lab.local 解析为集群的 IP 地址范围,但超时无响应。 Failed to connect to jupyter-lab.local port 80: No route to host

  • firewall-cmd --list-all表示每个节点的80端口都是开放的

这是 http 进入集群(任何节点)端口 80 的入口定义。(错了吗?)

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: jupyter-lab-ingress
  annotations:
    # nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io: /
spec:
  rules:
  - host: jupyter-lab.local
    http:                       
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: jupyter-lab-cip
            port:
              number: 80

这是部署

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jupyter-lab-dpt
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: jupyter-lab
  template:
    metadata:
      labels:
        app: jupyter-lab
    spec:
      volumes:
        - name: jupyter-lab-home
          persistentVolumeClaim:
            claimName: jupyter-lab-pvc
      containers:
        - name: jupyter-lab
          image: docker.io/jupyter/tensorflow-notebook
          ports:
            - containerPort: 8888
          volumeMounts:
            - name: jupyter-lab-home
              mountPath: /var/jupyter-lab_home
          env:
            - name: "JUPYTER_ENABLE_LAB"
              value: "yes"

我可以通过它的NodePort http://node2:30004 使用这个定义成功访问jupyter-lab:

---
apiVersion: v1
kind: Service
metadata:
  name: jupyter-lab-nodeport
  namespace: default
spec:
  type: NodePort
  ports:
    - port: 10003
      targetPort: 8888
      nodePort: 30004
  selector:
    app: jupyter-lab

如何在http://jupyter-lab.local 访问我的 jupyter-lab ???

  • 命令kubectl get endpoints -n ingress-nginx ingress-nginx-controller-admission返回:

ingress-nginx-controller-admission 10.244.2.4:8443 15m


我是否错误配置了端口?

我的“selector:appname”定义有错吗?

我错过了一部分吗

如何调试发生了什么?


其他细节

  • 应用入口kubectl apply -f default-ingress.yml时出现此错误

    Error from server (InternalError): error when creating "minnimal-ingress.yml": Internal error occurred: failed calling webhook "validate.nginx.ingress.kubernetes.io": Post "https://ingress-nginx-contr
    oller-admission.ingress-nginx.svc:443/networking/v1beta1/ingresses?timeout=10s": context deadline exceeded
    

    这个命令kubectl delete validatingwebhookconfigurations --all-namespaces 删除了验证 webhook ...这样做有错吗?

  • 我已经在集群中的每个节点上打开了 8443 端口

【问题讨论】:

  • 您是否检查了端口 8443 是否从当前运行入口控制器 Pod 的节点打开?
  • kubectl get endpoints -n ingress-nginx ingress-nginx-controller-admission 是否在 ENDPOINTS 列中显示任何 IP 地址?
  • 我设法通过删除验证 webhook 取得了进展。 kubectl get validatingwebhookconfigurations --all-namespaceskubectl delete validatingwebhookconfigurations但是还是没有反应@jupyter-lab.local集群已经重置,我会试试这些建议
  • @AndD 8443 在所有节点上都打开
  • @Matt 是的,在 ENDPOINTS 列中有一个 ip 地址,(见上文)

标签: kubernetes nginx-ingress ingress-nginx


【解决方案1】:

Ingress 无效,请尝试以下操作:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: jupyter-lab-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: jupyter-lab.local
    http:                       # <- removed the -
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
#            name: jupyter-lab-cip
            name: jupyter-lab-nodeport
            port:
              number: 8888
---
apiVersion: v1
kind: Service
metadata:
  name: jupyter-lab-cip
  namespace: default
spec:
  type: ClusterIP
  ports:
    - port: 8888
      targetPort: 8888
  selector:
    app: jupyter-lab

如果我理解正确,您正在尝试通过入口 nginx 代理公开 jupyternb 并使其可通过端口 80 访问。

运行以下命令检查 nginx 入口服务使用的节点端口:

$ kubectl get svc -n ingress-nginx ingress-nginx-controller
NAME                       TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller   NodePort   10.96.240.73   <none>        80:30816/TCP,443:31475/TCP   3h30m

在我的例子中是端口 30816(用于 http)和 31475(用于 https)。

使用 NodePort 类型,您只能使用 30000-32767 范围内的端口(k8s 文档:https://kubernetes.io/docs/concepts/services-networking/service/#nodeport)。您可以使用 kube-apiserver 标志 --service-node-port-range 更改它,然后将其设置为例如80-32767 然后在你的 ingress-nginx-controller 服务集中 nodePort: 80

apiVersion: v1
kind: Service
metadata:
  annotations: {}
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/version: 0.44.0
    helm.sh/chart: ingress-nginx-3.23.0
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: http
    nodePort: 80         # <- HERE
  - name: https
    port: 443
    protocol: TCP
    targetPort: https
    nodePort: 443         # <- HERE
  selector:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
  type: NodePort

虽然一般不建议更改 service-node-port-range,因为如果您使用节点上已经打开的端口(例如,kubelet 在每个节点上打开的端口 10250),您可能会遇到一些问题。


更好的解决方案是使用MetalLB


编辑:

如何在http://jupyter-lab.local 访问我的 jupyter-lab ???

假设您不需要容错解决方案,请下载 https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.44.0/deploy/static/provider/baremetal/deploy.yaml 文件并更改部署对象的 ports: 部分,如下所示:

  ports:
    - name: http
      containerPort: 80
      hostPort: 80         # <- add this line
      protocol: TCP
    - name: https
      containerPort: 443
      hostPort: 443        # <- add this line
      protocol: TCP
    - name: webhook
      containerPort: 8443
      protocol: TCP

并应用更改:

kubectl apply -f deploy.yaml

现在运行:

$ kubectl get po -n ingress-nginx ingress-nginx-controller-<HERE PLACE YOUR HASH>  -owide
NAME                                        READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
ingress-nginx-controller-67897c9494-c7dwj   1/1     Running   0          97s   172.17.0.6   <node_name>   <none>           <none>

注意 NODE 列中的 。这是调度 pod 的节点名称。现在获取此节点 IP 并将其添加到您的 /etc/hosts 文件中。

它现在应该可以工作了(去http://jupyter-lab.local检查它),但是这个解决方案是脆弱的,如果 nginx 入口控制器 pod 被重新安排到其他节点,它将停止工作(并且它会保持这种状态,直到你更改 ip在 /etc/hosts 文件中)。通常也不建议使用hostPort: 字段,除非您有充分的理由这样做,所以不要滥用它。


如果您需要容错解决方案,请使用 MetalLB 并为 nginx 入口控制器创建 LoadBalancer 类型的服务。

我尚未对其进行测试,但假设您正确配置了 MetalLB,以下应该可以完成工作:

kubectl delete svc -n ingress-nginx ingress-nginx-controller
kubectl expose deployment -n ingress-nginx ingress-nginx-controller --type LoadBalancer

【讨论】:

  • 我已经尝试过了,但我从 curl 获得了 Failed to connect to jupyter-lab.local port 80: No route to host。 DNS 正在将 jupyter-lab.local 解析为我所有的节点 IP 地址。这是防火墙问题吗,我需要在所有节点上打开端口 80 吗?
  • 你是如何设置你的 dns 的?它指向什么?当您直接将 curl 与 -H "Host: jupyter-lab.local" 和 IP 地址一起使用而不使用域名时,它是否有效? (通过 work 我的意思是返回一些 html,而不是错误)
  • 查看我的编辑。另请阅读有关k8s servicesk8s dns 的更多信息,因为我不确定您是否正确理解了所有概念。
  • 回答你的第三个问题:是的,你可以从命令中创建一个 yaml。要从中获取 yaml,请使用 --dry-run=client -oyaml flags 运行命令
  • 负载均衡器应该指向入口控制器,配置入口对象的入口控制器指向 CIP 服务,CIP 服务指向 jupyter。所以是的,你需要所有这些。
猜你喜欢
  • 2019-07-29
  • 1970-01-01
  • 2019-03-24
  • 1970-01-01
  • 2020-10-18
  • 2019-08-12
  • 2019-11-16
  • 2021-03-04
  • 2021-06-07
相关资源
最近更新 更多