我们使用安装了HAProxy Ingresses的Kubernetes集群。我们希望在 kubernetes 集群之外公开 RabbitMQ。这怎么可能?
要求:这是一个基于 OpenShift 的共享 k8s 集群,其中公开服务的唯一方法是使用入口。
- 管理UI提供了基本的REST端点,不应用于大量数据
- STOMP-Websockets看起来真的没有维护。不仅是协议,还有客户端库
- MQTT-Websockets看起来不像STOMP那么糟糕,但也不是很面向未来。
- 自己的 REST 服务可能需要大量工作
- 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)。
或者,您可以运行入口控制器的多个实例,但使用此方法会产生额外的开销(和复杂性)。