Kubernetes,集群中应用程序的 http 访问

Kubernetes,集群中应用程序的 http 访问

我对 kubernetes 还很陌生。我需要一些关于如何访问部署在集群中的应用程序的建议。

我有一个包含 Django 应用程序和 Gunicorn 的 docker 镜像来运行 .wsgi。我使用此镜像在包含 3 个节点的集群中部署容器(用于学习 k8s 的环境,1 个主节点 2 个从节点)。如果我使用 nodePort 公开服务并使用 curl <node'sIP>:[port],从未包含的服务器到集群,我就可以访问该应用程序。

但现在我想要一个单一的入口点,它可以与任何副本连接。

我考虑过创建另一台机器,不将其包含在安装了 Nginx 或 HAproxy 的集群中,但我找不到如何将外部反向代理与 kubernetes 服务连接起来的任何解决方案。

您能给我提供更好的解决方案,或者建议我如何继续我的想法吗?

答案1

总结

在类似的托管 Kubernetes 集群中GKEEKSAKS可以向云提供商请求服务的 IP 地址。

例如,Virtualbox使用创建的 Kubernetes 集群 都需要额外的工具才能获取服务。kubespraykubeadmExternal-IP

您可以在非云提供商管理的集群中使用metallbExternal-IP请查看官方网站:

在这种情况下,公开应用程序的步骤如下:

  • 部署应用程序 pod
  • 创建service附加到 Pod 的
  • 部署metallb并配置
  • 通过以下方式公开应用程序:
    • 创建类型服务LoadBalancer
    • 创建Ingress资源

免责声明!

创建Ingress资源需要Ingress控制器。我已在下面附上其中一个控制器的链接。

metallb我在下面提供了一个示例和更多解释,说明如何使用和在 Virtualbox 中创建的集群中公开您的应用程序nginx-ingress-controller


这是一个示例,展示了如何在 Virtualbox 中创建的 Kubernetes 集群上公开应用程序:

  • metallb
  • nginx-ingress-controller

我把这个答案分为两部分:

  • 虚拟盒
  • Kubernetes

虚拟盒

在 Virtualbox 中创建时,VM's您可以通过多种方式配置网络。其中一些是:

  • Bridged networking- 将你的 Kubernetes 集群连接到物理网络
  • Host-only- 允许单个适配器连接到节点,主机允许网络连接。此解决方案需要另一个可访问 Internet 的适配器或连接相同Host-only网络适配器的网关(例如 PfSense)。

此示例使用客户端和 3 个带有Bridged适配器的节点:

  • clientIP 地址:192.168.0.2
  • masterIP 地址:192.168.0.117
  • worker1IP 地址:192.168.0.118
  • worker2IP 地址:192.168.0.119

为了确保此示例在主机之外有效,我使用了同一网络中的另一台设备。

请确保节点之间具有完全连接,并且您的主机对它们具有完全访问权限。

Kubernetes

假设:

  • 集群配置正确并可以访问互联网
  • 您拥有该集群的完全访问权限
  • 您可以从任何其他主机“ping”每个节点
  • 你的 pod 在你选择的端口上响应请求(例如8000

脚步:

  • 使用以下方式创建一个 Podgunicorn
  • gunicorn为pod创建服务定义
  • 部署Metallb
  • 使用以下类型的服务公开应用程序LoadBalancer
  • 公开带有Ingress资源的应用程序

使用以下方式创建一个 Podgunicorn

我用的是下面部署定义创建一个响应请求的 pod:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: gunicorn
spec:
  selector:
    matchLabels:
      app: gunicorn
  replicas: 1
  template:
    metadata:
      labels:
        app: gunicorn
    spec:
      containers:
      - name: gunicorn
        image: ubuntu
        command:
        - sleep
        - "infinity"

我使用了ubuntu我将要进入的图像exec并运行以下命令:

  • $ apt update && apt install -y python3 python3-pip
  • $ pip3 install gunicorn

我使用的示例代码myapp.py

def app(environ, start_response):
    data = b"Hello, World!\n"
    start_response("200 OK", [
        ("Content-Type", "text/plain"),
        ("Content-Length", str(len(data)))
    ])
    return iter([data])
  • $ gunicorn -w 1 -b 0.0.0.0 myapp:app &

上面的例子基于:

完成这些步骤后你的 pod 应该会在端口上做出8000响应Hello, World!

gunicorn为pod创建服务定义

pod的服务定义gunicorn

apiVersion: v1
kind: Service
metadata:
  name: gunicorn-service
spec:
  selector:
    app: gunicorn
  ports:
    - name: gunicorn-port
      port: 8000
      targetPort: 8000
  type: NodePort

部署Metallb

遵循官方Metallb文档:Metallb.universe.tf:安装

  • 编辑以将模式从kube-proxy更改为: strictARPfalsetrue
    • $ kubectl edit configmap -n kube-system kube-proxy
  • $ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/namespace.yaml
  • $ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/metallb.yaml
  • $ kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)

您还需要添加一个configMap来告诉metallb他可以为服务分配哪些 IP 地址:

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 192.168.0.240-192.168.0.250

请具体看以下部分:

      addresses:
      - 192.168.0.240-192.168.0.250

请确保该地址范围不与网络中使用的任何地址重叠,并且与节点和客户端位于同一网络中。

此后,您应该能够创建LoadBalancer获取 IP 地址的服务类型。

使用以下类型的服务公开应用程序LoadBalancer

您应该能够运行:

  • $ kubectl expose deployment gunicorn --type=LoadBalancer --port=8000

输出$ kubectl get services应该显示:

NAME               TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)          AGE
gunicorn           LoadBalancer   10.233.43.104   192.168.0.240   8000:32591/TCP   3s
gunicorn-service   NodePort       10.233.34.96    <none>          8000:30862/TCP   73s
kubernetes         ClusterIP      10.233.0.1      <none>          443/TCP          23h

如您所见,gunicorn服务具有的,EXTERNAL-IP192.168.0.240位于的 IP 池中metallb

本例中使用的物理网络是192.168.0.0/24

您可以运行:curl 192.168.0.240:8000并获得:Hello, World!

公开带有Ingress资源的应用程序

Ingress在公开应用程序之前,您需要部署控制器。您可以nginx-ingress-controller通过运行以下命令进行部署:

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

Ingress控制器将附加一个服务类型LoadBalancer,这将是入口点针对该请求。

您可以通过调用以下命令获取其 IP 地址$ kubectl get svc -n ingress-nginx

NAME                                 TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.233.52.8     192.168.0.241   80:31380/TCP,443:30066/TCP   29m
ingress-nginx-controller-admission   ClusterIP      10.233.37.255   <none>          443/TCP                      29m

以下是Ingress将流量从控制器路由到你的 pod 的定义:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: gunicorn-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: 
    http:
      paths:
      - path: /
        backend:
          serviceName: gunicorn-service
          servicePort: gunicorn-port

应用后,您应该能够:

  • curl 192.168.0.241并得到以下回应gunicorn

答案2

您缺少一些基本的 Kubernetes 概念,我建议您看一下:

  1. 服务- 这些为您的 Pod 提供了抽象,并提供了一种在多个副本之间平衡流量负载的方法。这些可以在内部使用,也可以在外部公开
  2. 入口- 这允许您在集群内部设置 Ingress 控制器(如 Nginx),并让其将您的流量反向代理到适当的服务。这比在集群外部创建 Nginx 实例要好得多,因为 Ingress 控制器将自动拾取您在集群中创建的任何新入口。

相关内容