如何将 Kubernetes 托管的 RabbitMQ 暴露给外部



我们使用安装了HAProxy Ingresses的Kubernetes集群。我们希望在 kubernetes 集群之外公开 RabbitMQ。这怎么可能?

要求:这是一个基于 OpenShift 的共享 k8s 集群,其中公开服务的唯一方法是使用入口。

  1. 管理UI提供了基本的REST端点,不应用于大量数据
  2. STOMP-Websockets看起来真的没有维护。不仅是协议,还有客户端库
  3. MQTT-Websockets看起来不像STOMP那么糟糕,但也不是很面向未来。
  4. 自己的 REST 服务可能需要大量工作
  5. AMQP无法通过HAProxy公开

我无法想象我们是第一个需要连接到托管在 Kubernetes 中的 RabbitMQ 的人?!?

客户端需要基于.net

只需为要在群集外部公开的每个组件定义类型为NodePort类型的Service

默认情况下,您必须将端口从组件"映射"到 [32000-32767] 范围内的端口,并且您将能够使用这些端口访问您的组件

基本上,NodePort 服务将使集群的每个节点侦听来自服务的端口,并将流量路由到正确端口上的正确 Pod。入口/路由没有协议限制。

K8S 服务

节点端口上的 OCP 文档

[UPDATE]
这根本没有回答问题,因为">公开服务的唯一方法是使用入口。">

我已经查看了RabbitMQ外部访问用例的Traefik和NGINX。对于RabbitMQ,NGINX Ingress最终成为我通过TCP公开AMQP协议的更简单的选择。它也是minikube的默认入口提供程序(如果启用它),这很有用。如果有人有类似的Traefik例子,我会对它感兴趣。

请注意,没有什么能阻止您在集群上使用多个入口控制器用于不同的目的/用例。

设置

启动集群,如果使用 minikube -

minikube delete && minikube start --kubernetes-version=v1.23.0 --memory=4g --bootstrapper=kubeadm --extra-config=kubelet.authentication-token-webhook=true --extra-config=kubelet.authorization-mode=Webhook --extra-config=scheduler.bind-address=0.0.0.0 --extra-config=controller-manager.bind-address=0.0.0.0 --extra-config=etcd.listen-metrics-urls=http://0.0.0.0:2381 --driver=docker

在我们有一个 kubernetes 集群之后,我们需要一个 rabbitmq 集群。我正在使用 rabbitmq 运算符来配置 -

安装最新的 RabbitMQ 运算符(如有必要)

kubectl apply -f "https://github.com/rabbitmq/cluster-operator/releases/latest/download/cluster-operator.yml"

等待操作员准备就绪

watch kubectl get pods -n rabbitmq-system

RabbitMQ 测试集群的命名空间

kubectl create ns test-rabbitmq

创建群集 - test-cluster.yaml

apiVersion: rabbitmq.com/v1beta1
kind: RabbitmqCluster
metadata:
name: test-cluster
namespace: test-rabbitmq
spec:
replicas: 1
kubectl apply -f test-cluster.yaml

等待集群准备就绪

watch kubectl get pods -n test-rabbitmq

接下来,您需要 ClusterIP 类型的服务来通过入口公开管理门户和 AMQP,我们将公开端口 5672、15672(如果要公开 Prometheus 指标终结点,则公开端口 15692)。端口 5671 将用于 AMQP TLS。

cluster-service.yaml

apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/component: rabbitmq
app.kubernetes.io/name: cluster-service
app.kubernetes.io/part-of: rabbitmq
name: cluster-service
namespace: test-rabbitmq
spec:
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
# - appProtocol: amqp
#   name: amqp-tls
#   port: 5671
#   protocol: TCP
#   targetPort: 5671
- appProtocol: amqp
name: amqp
port: 5672
protocol: TCP
targetPort: 5672
- appProtocol: http
name: management
port: 15672
protocol: TCP
targetPort: 15672
- appProtocol: prometheus.io/metrics
name: prometheus
port: 15692
protocol: TCP
targetPort: 15692
selector:
app.kubernetes.io/name: test-cluster
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}
kubectl apply -f cluster-service.yaml

设置入口(仅限迷你库贝!

minikube addons enable ingress
#kubectl patch configmap tcp-services -n ingress-nginx --patch '{"data":{"5671":"test-rabbitmq/cluster-service:5671"}}'
kubectl patch configmap tcp-services -n ingress-nginx --patch '{"data":{"5672":"test-rabbitmq/cluster-service:5672"}}'
spec:
template:
spec:
containers:
- name: controller
ports:
#         - containerPort: 5671
#           hostPort: 5671   
- containerPort: 5672
hostPort: 5672
kubectl patch deployment ingress-nginx-controller --patch "$(cat ingress-nginx-controller-patch.yaml)" -n ingress-nginx
# after the ingress pod is back up and running
telnet $(minikube ip) 5672
# Ctrl+] then quit

设置入口(掌舵)

安装入口-nginx控制器(如有必要)

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

这处理了 AMQP 的 TCP 端口的公开,它将这些端口映射到我们之前创建的服务端口 - values.yaml

controller:
replicaCount: 1
service:
loadBalancerIP: "192.168.1.251" # IP reserved for ingress. If you omit, you'll be assigned an IP in the avaiable range. Better to specify one.
tcp:
#5671: test-rabbitmq/cluster-service:5671
5672: test-rabbitmq/cluster-service:5672
udp: {}

创建我们的 nginx 入口控制器

helm upgrade -i ingress-nginx ingress-nginx/ingress-nginx -f values.yaml -n ingress-nginx --create-namespace

一旦 nginx 集群 Pod 启动 -

watch kubectl get pods -n ingress-nginx
telnet $(minikube ip) 5672
# Ctrl+] then quit

让我们公开我们的 HTTP 入口 - Rabbitmq-ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rabbitmq-ingress
namespace: test-rabbitmq
spec:
ingressClassName: nginx
rules:
- host: rabbitmq.test
http:
paths:    
- backend:
service:
name: cluster-service
port:
number: 15692
path: /metrics  # optional
pathType: Exact  
- backend:
service:
name: cluster-service
port:
number: 15672
path: /
pathType: Prefix
defaultBackend:
service:
name: cluster-service
port:
number: 15672
status:
loadBalancer: {}
kubectl apply -f rabbitmq-ingress.yaml

等待将外部地址分配给入口

watch kubectl get ingress -n test-rabbitmq

注意:您可以调整入口以支持 TLS/HTTPS,但这超出了此示例的范围。

主机入口

添加映射到 192.168.1.251(或您分配或分配给 NGINX 入口的任何 IP)的 Rabbitmq.test hosts 条目

如果使用迷你库贝

sudo -- sh -c "echo '$(minikube ip)  rabbitmq.test' >> /etc/hosts"

如果使用 Helm 安装的入口控制器

sudo -- sh -c "echo $(kubectl get ingress -n test-rabbitmq -o=jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}'  rabbitmq.test >> /etc/hosts"

示例主机条目 -

192.168.1.251  rabbitmq.test

验证我们通过入口获取 HTML 和统计信息

curl rabbitmq.test
curl rabbitmq.test/metrics # bonus

获取 RabbitMQ 管理门户用户/密码(如果在创建群集时未明确指定)

kubectl get secret test-cluster-default-user -n test-rabbitmq -o jsonpath='{.data.username}' | base64 --decode
kubectl get secret test-cluster-default-user -n test-rabbitmq -o jsonpath='{.data.password}' | base64 --decode

你应该能够从 Web 浏览器使用这些凭据连接到管理门户

http://rabbitmq.test
http://rabbitmq.test/metrics

Minikube 向主机公开入口

如果在 VM 中运行 Minikube,若要向主机公开入口以便可以从 Web 浏览器访问管理门户,请执行以下操作。然后在虚拟机管理程序中将映射 80(主机)移植到 8080(vm) -

# we forward to 8080 because 80 is a privileged port
kubectl port-forward --address 0.0.0.0 deployment/ingress-nginx-controller 8080:80 --namespace ingress-nginx
# following for TLS
#kubectl port-forward --address 0.0.0.0 deployment/ingress-nginx-controller 8443:443 --namespace ingress-nginx

从 .NET 客户端,现在可以使用主机条目或入口 IP 测试与 TCP 端口 5672 的连接。如果将 .NET 客户端从主机运行到 VM (minikube),请端口转发 TCP 5672:5672

这是应该做的。我已经在minikube中验证了这一点,并在使用helm进行nginx入口的实际集群上做了同样的事情。

多集群注意事项

注意:如果您要托管多个 rabbitmq 集群(来自单个 kubernetes 集群),则必须映射到同一入口 IP 上的不同外部可用端口(例如 5782 -> test-rabbitmq-2/cluster-service:5672)。

或者,您可以运行入口控制器的多个实例,但使用此方法会产生额外的开销(和复杂性)。

最新更新