我们使用安装了 HAProxy Ingress 的 kubernetes 集群。我们希望将 RabbitMQ 暴露在 kubernetes 集群之外。这怎么可能?
需求:这是一个基于OpenShift的共享k8s集群,暴露服务的唯一方法是使用入口。
我无法想象我们是第一个需要连接到 Kubernetes 托管的 RabbitMQ 的人?!?
客户端需要基于.net
只需为要在集群外部公开的每个组件定义一个
Service
类型 NodePort
即可。
默认情况下,您必须将组件的端口“映射”到 [32000-32767] 范围内的端口,并且您将能够使用这些端口访问您的组件
基本上,NodePort 服务将使集群的每个节点侦听该服务的端口,并将流量路由到正确端口上的正确 Pod。对于入口/路由没有协议限制。
[已更新]
这根本不能回答问题,因为要求“公开服务的唯一方法是使用入口。”
我研究了 Traefik 和 NGINX 的 RabbitMQ 外部访问用例。对于 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 Operator(如有必要)
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
创建集群 - 测试集群.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 类型的服务来通过 Ingress 公开管理门户和 AMQP,我们将公开端口 5672、15672(如果您想公开 prometheus 指标端点,则公开端口 15692)。端口 5671 将用于 AMQP TLS。
集群服务.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
安装 ingress-nginx 控制器(如有必要)
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
这处理公开 AMQP 的 TCP 端口,它将这些端口映射到我们之前创建的服务端口 - 值.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的rabbitmq.test主机条目(或您分配的任何IP,或分配给NGINX Ingress)
sudo -- sh -c "echo '$(minikube ip) rabbitmq.test' >> /etc/hosts"
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
验证我们通过 ingress 获取 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,要将入口暴露给主机以便您可以从 Web 浏览器访问管理门户,请执行以下操作。然后在虚拟机管理程序中将 80(主机)端口映射到 8080(虚拟机) -
# 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章)。
或者,您可以运行入口控制器的多个实例,但使用这种方法会产生额外的开销(和复杂性)。