无法访问 Spring 通过 AWS 上的 Kubernetes 集群 运行 上的 nginx 入口控制器公开的引导微服务
Unable to access Spring Boot microservice exposed via nginx ingress controller on Kubernetes cluster running on AWS
我在 AWS 上使用 kube-up.sh 脚本在本演练之后启动了一个 3 节点 Kubernetes 集群(版本:1.5.8):
https://ryaneschinger.com/blog/building-a-kubernetes-cluster-on-aws/
我能够成功访问集群并查看 UI。 kubectl cluster-info
命令的输出:
我写了一个简单的Spring启动微服务:
@RestController
public class AddCustomerController {
private static final String template = "Customer %s is added.";
@RequestMapping("/addcustomer")
public Message addcustomer(@RequestParam(value="name") String name) {
//Retrieve the hostname of the "node"/"container"
String hostname = null;
try {
hostname = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
e.printStackTrace();
}
return new Message(ThreadLocalRandom.current().nextLong(),
String.format(template, name),
hostname);
}
}
并在 Gradle 构建后将其打包到 Docker 容器中,并且能够在本地成功使用它。我已将图像推送到 DockerHub。
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ADD build/libs/*.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
现在我正在使用 Helm Charts 将此应用程序部署到 Kubernetes。
部署描述符:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: add-customer-deployment
spec:
replicas: 3
template:
metadata:
name: add-customer-microservice
labels:
app: add-customer
spec:
containers:
- image: {{ .Values.dockerHubUsername }}/add-customer-microservice:latest
name: add-customer-microservice
imagePullPolicy: Always
ports:
- containerPort: 8080
服务描述符:
apiVersion: v1
kind: Service
metadata:
name: add-customer-service
spec:
selector:
app: add-customer
ports:
- port: 1000
protocol: TCP
targetPort: 8080
name: access-port
type: NodePort
我对其他 3 个类似的 Spring 引导微服务执行了相同的过程。
入口描述符:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: quantiphi-poc-ingress-dns
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: crud.qdatalabs.com
http:
paths:
- path: /service1
backend:
serviceName: add-customer-service
servicePort: 1000
- path: /service1/*
backend:
serviceName: add-customer-service
servicePort: 1000
- path: /service2
backend:
serviceName: get-customer-service
servicePort: 2000
- path: /service2/*
backend:
serviceName: get-customer-service
servicePort: 2000
- path: /service3
backend:
serviceName: update-customer-service
servicePort: 3000
- path: /service3/*
backend:
serviceName: update-customer-service
servicePort: 3000
- path: /service4
backend:
serviceName: delete-customer-service
servicePort: 4000
- path: /service4/*
backend:
serviceName: delete-customer-service
servicePort: 4000
首先,我使用 Helm Charts 在我的集群上安装了 nginx 控制器:
helm install --name my-release stable/nginx-ingress
然后我使用以下方法安装我的 Chart:
helm install folder-conataining-helm-chart/
然后我将 crud.qdatalabs.com(类型 A)的别名从 Route53 指向 Ingress 资源生成的 ELB。
URL crud.qdatalabs.com/healthz
给出 200 OK 响应
当我尝试使用 URL crud.qdatalabs.com/service1/addcustomer?name=starman
访问微服务时
我收到了 WhiteLabel 错误页面:
我想我犯了一些配置错误,但无法确定。请帮助我任何方向。我很乐意提供更多详细信息。谢谢。
正如我在 中所述,您遇到的最可能的问题是,当您使用此入口时,您附加的 URI 与直接访问(/service1/ vs /)不同,因此您的应用是丢失并且没有该 uri 的内容。
使用 Nginx Ingress Controller,您可以使用 ingress.kubernetes.io/rewrite-target: / 注释来缓解这种情况,并确保即使在入口路径中有子文件夹时也可以访问 /。
因此,您要么需要使用正确的重写注释,要么支持您在服务内部入口中使用的路径。
我在 AWS 上使用 kube-up.sh 脚本在本演练之后启动了一个 3 节点 Kubernetes 集群(版本:1.5.8):
https://ryaneschinger.com/blog/building-a-kubernetes-cluster-on-aws/
我能够成功访问集群并查看 UI。 kubectl cluster-info
命令的输出:
我写了一个简单的Spring启动微服务:
@RestController
public class AddCustomerController {
private static final String template = "Customer %s is added.";
@RequestMapping("/addcustomer")
public Message addcustomer(@RequestParam(value="name") String name) {
//Retrieve the hostname of the "node"/"container"
String hostname = null;
try {
hostname = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
e.printStackTrace();
}
return new Message(ThreadLocalRandom.current().nextLong(),
String.format(template, name),
hostname);
}
}
并在 Gradle 构建后将其打包到 Docker 容器中,并且能够在本地成功使用它。我已将图像推送到 DockerHub。
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ADD build/libs/*.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
现在我正在使用 Helm Charts 将此应用程序部署到 Kubernetes。
部署描述符:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: add-customer-deployment
spec:
replicas: 3
template:
metadata:
name: add-customer-microservice
labels:
app: add-customer
spec:
containers:
- image: {{ .Values.dockerHubUsername }}/add-customer-microservice:latest
name: add-customer-microservice
imagePullPolicy: Always
ports:
- containerPort: 8080
服务描述符:
apiVersion: v1
kind: Service
metadata:
name: add-customer-service
spec:
selector:
app: add-customer
ports:
- port: 1000
protocol: TCP
targetPort: 8080
name: access-port
type: NodePort
我对其他 3 个类似的 Spring 引导微服务执行了相同的过程。
入口描述符:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: quantiphi-poc-ingress-dns
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: crud.qdatalabs.com
http:
paths:
- path: /service1
backend:
serviceName: add-customer-service
servicePort: 1000
- path: /service1/*
backend:
serviceName: add-customer-service
servicePort: 1000
- path: /service2
backend:
serviceName: get-customer-service
servicePort: 2000
- path: /service2/*
backend:
serviceName: get-customer-service
servicePort: 2000
- path: /service3
backend:
serviceName: update-customer-service
servicePort: 3000
- path: /service3/*
backend:
serviceName: update-customer-service
servicePort: 3000
- path: /service4
backend:
serviceName: delete-customer-service
servicePort: 4000
- path: /service4/*
backend:
serviceName: delete-customer-service
servicePort: 4000
首先,我使用 Helm Charts 在我的集群上安装了 nginx 控制器:
helm install --name my-release stable/nginx-ingress
然后我使用以下方法安装我的 Chart:
helm install folder-conataining-helm-chart/
然后我将 crud.qdatalabs.com(类型 A)的别名从 Route53 指向 Ingress 资源生成的 ELB。
URL crud.qdatalabs.com/healthz 给出 200 OK 响应
当我尝试使用 URL crud.qdatalabs.com/service1/addcustomer?name=starman
访问微服务时我收到了 WhiteLabel 错误页面:
我想我犯了一些配置错误,但无法确定。请帮助我任何方向。我很乐意提供更多详细信息。谢谢。
正如我在
使用 Nginx Ingress Controller,您可以使用 ingress.kubernetes.io/rewrite-target: / 注释来缓解这种情况,并确保即使在入口路径中有子文件夹时也可以访问 /。
因此,您要么需要使用正确的重写注释,要么支持您在服务内部入口中使用的路径。