使用 microk8s 从主机简单进入?

Simple ingress from host with microk8s?

我想用 MicroK8s 做两件事:

  1. 将主机(Ubuntu 18.04)端口 80/443 路由到 Microk8s
  2. 使用类似于 kubernetes.io 文档中定义的简单入口的东西

我的最终目标是创建一个位于 Ubuntu 主机上的单节点 Kubernetes 集群,然后使用入口将不同的域路由到服务内部各自的 pods。

过去几天我一直在尝试用 Microk8s 来做这件事,但我无法理解它。

作为示例,一旦启用入口加载项,这将在 Minikube 上运行,此示例显示群集 IP 上端口 80 的基本 Nginx 服务器映像:

# ingress-service.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-service
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
    # - host: nginx.ioo
    - http:
        paths:
          - path: /
            backend:
              serviceName: nginx-cluster-ip-service
              servicePort: 80
# nginx-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: nginx
  template:
    metadata:
      labels:
        component: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80
# nginx-cluster-ip-service

apiVersion: v1
kind: Service
metadata:
  name: nginx-cluster-ip-service
spec:
  type: ClusterIP
  selector:
    component: nginx
  ports:
    - port: 80
      targetPort: 80

如果我对您的理解正确,您可能会看到几种方法。

一个是你已经提到的MetalLB

MetalLB provides a network load-balancer implementation for Kubernetes clusters that do not run on a supported cloud provider, effectively allowing the usage of LoadBalancer Services within any cluster.

你可以阅读详细实现A pure software solution: MetalLB

另一种方式是Over a NodePort Service

This approach has a few other limitations one ought to be aware of:

  • Source IP address

Services of type NodePort perform source address translation by default. This means the source IP of a HTTP request is always the IP address of the Kubernetes node that received the requestfrom the perspective of NGINX.

你也可以使用host network

In a setup where there is no external load balancer available but using NodePorts is not an option, one can configure ingress-nginx Pods to use the network of the host they run on instead of a dedicated network namespace. The benefit of this approach is that the NGINX Ingress controller can bind ports 80 and 443 directly to Kubernetes nodes' network interfaces, without the extra network translation imposed by NodePort Services.

你还要记住,如果你在POD里面编辑配置,如果Pod重启或者崩溃,它就会消失。

我希望这可以帮助您确定采用哪种方式来实现您的想法。

当使用 LoadBalancer(又名 metallb)时,几乎所有文档中都缺少一个重要步骤:

ingress-controller 需要暴露给 metallb LoadBalancer。

kubectl expose deploy nginx-deployment --port 80 --type LoadBalancer

这也可以通过 yaml 来完成,但使用 cli 更容易。

经过几天的谷歌搜索,我终于看到了这个让我大开眼界的教程视频。

https://www.youtube.com/watch?v=xYiYIjlAgHY

语句“到目前为止我得到的最好的是使用 MetalLB 创建负载平衡器。”是错的。您必须使用入口层进行主机流量路由。

在裸机环境中,您需要配置 MetalLB 以允许从主机到 k8s 的传入连接。

首先我们需要一个测试:

curl -H "Host: nginx.ioo" http://HOST_IP

结果如何?

  1. 网络错误
  2. 错误 404 或 503
  3. 有效!!

如果网络错误,那么你需要 MetalLB

microk8s.enable metallb:$(curl ipinfo.io/ip)-$(curl ipinfo.io/ip) 

运行再次测试

如果网络错误,那么你有问题。检查主机连接。

如果错误 404(有时是 503),那么您需要一个入口规则。

# ingress-service.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-service
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
    - host: nginx.ioo
    - http:
        paths:
          - path: /
            backend:
              serviceName: nginx-cluster-ip-service
              servicePort: 80

上次测试。它应该有效。

现在您可以使用入口将不同的域路由到服务内部各自的 pods。

如果您需要通过 HTTPS 和身份验证 public 公开服务,这可能会变得相当复杂,因为您需要配置 a) 入口,b) TLS 证书服务 - 即使用 Lets Encrypt,c) 身份验证代理,d) 在您的应用中实施用户授权。

如果您的 K8S 集群 运行 在没有 public IP 的服务器上,这会带来额外的复杂性,因为您需要穿透 NAT。

https://github.com/gwrun/tutorials/tree/main/k8s/pod 演示了如何使用 Kubernetes 在没有 public IP 的 microk8s 集群上安全地公开 k8s 服务 运行 作为 public 具有 OAuth 身份验证和授权的可访问 HTTPS仪表板作为示例服务。

TLDR

更新注释为kubernetes.io/ingress.class: public

为什么

对于 MicroK8s v1.21,运行

microk8s enable ingress

将在 ingress 命名空间中创建一个名为 nginx-ingress-microk8s-controllerDaemonSet

如果你检查一下,有一个标志来设置入口 class:

      - args:
        ... omitted ... 
        - --ingress-class=public
        ... omitted ... 

因此,为了在线处理大多数示例,您需要

  1. 删除 --ingress-class=public 参数,使其默认为 nginx
  2. 更新注释kubernetes.io/ingress.class: nginx 设为 kubernetes.io/ingress.class: public

ingress.classnginx 更改为 public 建议 并设置 DNS 条目(使用我的外部提供商的控制台)从 * 到我的 public IP(不是主机名)是复制 Openshift 风格 route(又名“基于名称的虚拟主机”)的两个充分条件 microk8s 安装在金属上。

  • 更多信息

尽管没有安装 MetalLB,但所有 pod 副本之间的负载平衡工作正常(从 gcr.io/google-samples/hello-app 的输出中可以看出)。由于入口控制器自动生成的自签名证书,即使 HTTPS 也可以开箱即用。

使用 Microk8s 1.21+ 时,Ingress 配置在 运行 microk8s enable ingress:

之后应该是这样的
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: frontend-ingress
spec:
  rules:
    - host: staging.resplendentdata.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frontend-service
                port:
                  number: 80

  ingressClassName: public

要安装 nginx 使其与 ingressClass=nginx 一起使用,请使用:

#https://kubernetes.github.io/ingress-nginx/deploy/
helm upgrade --install ingress-nginx ingress-nginx \
  --repo https://kubernetes.github.io/ingress-nginx \
  --namespace ingress-nginx --create-namespace