Kubernetes nginx 入口控制器作为负载均衡器获取随机端口
Kubernetes nginx ingress controller as loadbalancer gets random ports
我正在尝试通过单个主裸机集群上的入口公开公开 kubernetes 仪表板。问题是我正在使用的 LoadBalancer(nginx 入口控制器)服务没有打开我希望它打开的 80/443 端口 open/use。相反,它采用 30-32k 范围内的一些随机端口。我知道我可以用 --service-node-port-range
设置这个范围,但我很确定一年前我不必在另一台服务器上这样做。我在这里遗漏了什么吗?
目前这是我的 stack/setup(Ubuntu 16.04 的全新安装):
- Nginx 入口控制器(通过 helm 安装)
- 金属LB
- Kubernetes 仪表板
- Kubernetes Dashboard Ingress 在
<domain>
上公开部署
- Cert-Manager(通过 helm 安装)
k8s-仪表板-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
# add an annotation indicating the issuer to use.
cert-manager.io/cluster-issuer: letsencrypt-staging
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/secure-backends: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
name: kubernetes-dashboard-ingress
namespace: kubernetes-dashboard
spec:
rules:
- host: <domain>
http:
paths:
- backend:
serviceName: kubernetes-dashboard
servicePort: 443
path: /
tls:
- hosts:
- <domain>
secretName: kubernetes-dashboard-staging-cert
这是我的 kubectl get svc -A
的样子:
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cert-manager cert-manager ClusterIP 10.101.142.87 <none> 9402/TCP 23h
cert-manager cert-manager-webhook ClusterIP 10.104.104.232 <none> 443/TCP 23h
default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6d6h
ingress-nginx nginx-ingress-controller LoadBalancer 10.100.64.210 10.65.106.240 80:31122/TCP,443:32697/TCP 16m
ingress-nginx nginx-ingress-default-backend ClusterIP 10.111.73.136 <none> 80/TCP 16m
kube-system kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 6d6h
kubernetes-dashboard cm-acme-http-solver-kw8zn NodePort 10.107.15.18 <none> 8089:30074/TCP 140m
kubernetes-dashboard dashboard-metrics-scraper ClusterIP 10.96.228.215 <none> 8000/TCP 5d18h
kubernetes-dashboard kubernetes-dashboard ClusterIP 10.99.250.49 <none> 443/TCP 4d6h
这里有更多例子正在发生的事情:
curl -D- http://<public_ip>:31122 -H 'Host: <domain>'
- returns 308,因为协议是 http 而不是 https。这是预期的
curl -D- http://<public_ip> -H 'Host: <domain>'
curl: (7) Failed to connect to <public_ip> port 80: Connection refused
- 端口 80 已关闭
curl -D- --insecure https://10.65.106.240 -H "Host: <domain>"
- 通过内部 IP 访问仪表板显然有效,我得到了正确的 k8s-dashboard html。
--insecure
是因为 let's encrypt 还没有工作,因为端口 80 上的 acme 挑战无法访问。
所以回顾一下,我如何让 2.
工作?例如。通过 80/443 获得服务?
编辑:Nginx 入口控制器 .yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: "2020-02-12T20:20:45Z"
labels:
app: nginx-ingress
chart: nginx-ingress-1.30.1
component: controller
heritage: Helm
release: nginx-ingress
name: nginx-ingress-controller
namespace: ingress-nginx
resourceVersion: "1785264"
selfLink: /api/v1/namespaces/ingress-nginx/services/nginx-ingress-controller
uid: b3ce0ff2-ad3e-46f7-bb02-4dc45c1e3a62
spec:
clusterIP: 10.100.64.210
externalTrafficPolicy: Cluster
ports:
- name: http
nodePort: 31122
port: 80
protocol: TCP
targetPort: http
- name: https
nodePort: 32697
port: 443
protocol: TCP
targetPort: https
selector:
app: nginx-ingress
component: controller
release: nginx-ingress
sessionAffinity: None
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 10.65.106.240
编辑 2:metallb configmap yaml
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 10.65.106.240-10.65.106.250
更新:
我在写这个答案时没有看到问题的 edit 部分。鉴于提供的附加信息,这没有意义。请无视
原文:
显然,您现在使用的集群通过 node-port
类型服务而不是 load-balancer
设置了入口控制器。为了获得所需的行为,您需要更改入口控制器的配置。请参阅 nginx ingress controller documentation for metalLB cases 如何执行此操作。
所以,要解决第二个问题,正如我所建议的,您可以使用 hostNetwork: true
参数将容器端口映射到它所在的主机 运行。请注意,这不是推荐的做法,您应该始终避免这样做,除非您有理由。
示例:
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
hostNetwork: true
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
hostPort: 80 # this parameter is optional, but recommended when using host network
name: nginx
当我部署这个 yaml 时,我可以检查 pod 的位置 运行 并卷曲该主机的端口 80。
root@v1-16-master:~# kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 105s 10.132.0.50 v1-16-worker-2 <none> <none>
注意:现在我知道 pod 在工作节点 2 上 运行。我只需要它的 IP 地址。
root@v1-16-master:~# kubectl get no -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
v1-16-master Ready master 52d v1.16.4 10.132.0.48 xxxx Ubuntu 16.04.6 LTS 4.15.0-1052-gcp docker://19.3.5
v1-16-worker-1 Ready <none> 52d v1.16.4 10.132.0.49 xxxx Ubuntu 16.04.6 LTS 4.15.0-1052-gcp docker://19.3.5
v1-16-worker-2 Ready <none> 52d v1.16.4 10.132.0.50 xxxx Ubuntu 16.04.6 LTS 4.15.0-1052-gcp docker://19.3.5
v1-16-worker-3 Ready <none> 20d v1.16.4 10.132.0.51 xxxx Ubuntu 16.04.6 LTS 4.15.0-1052-gcp docker://19.3.5
root@v1-16-master:~# curl 10.132.0.50 2>/dev/null | grep title
<title>Welcome to nginx!</title>
root@v1-16-master:~# kubectl delete po nginx
pod "nginx" deleted
root@v1-16-master:~# curl 10.132.0.50
curl: (7) Failed to connect to 10.132.0.50 port 80: Connection refused
当然,如果我在浏览器上访问 public IP,它也能正常工作。
我正在尝试通过单个主裸机集群上的入口公开公开 kubernetes 仪表板。问题是我正在使用的 LoadBalancer(nginx 入口控制器)服务没有打开我希望它打开的 80/443 端口 open/use。相反,它采用 30-32k 范围内的一些随机端口。我知道我可以用 --service-node-port-range
设置这个范围,但我很确定一年前我不必在另一台服务器上这样做。我在这里遗漏了什么吗?
目前这是我的 stack/setup(Ubuntu 16.04 的全新安装):
- Nginx 入口控制器(通过 helm 安装)
- 金属LB
- Kubernetes 仪表板
- Kubernetes Dashboard Ingress 在
<domain>
上公开部署
- Cert-Manager(通过 helm 安装)
k8s-仪表板-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
# add an annotation indicating the issuer to use.
cert-manager.io/cluster-issuer: letsencrypt-staging
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/secure-backends: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
name: kubernetes-dashboard-ingress
namespace: kubernetes-dashboard
spec:
rules:
- host: <domain>
http:
paths:
- backend:
serviceName: kubernetes-dashboard
servicePort: 443
path: /
tls:
- hosts:
- <domain>
secretName: kubernetes-dashboard-staging-cert
这是我的 kubectl get svc -A
的样子:
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cert-manager cert-manager ClusterIP 10.101.142.87 <none> 9402/TCP 23h
cert-manager cert-manager-webhook ClusterIP 10.104.104.232 <none> 443/TCP 23h
default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6d6h
ingress-nginx nginx-ingress-controller LoadBalancer 10.100.64.210 10.65.106.240 80:31122/TCP,443:32697/TCP 16m
ingress-nginx nginx-ingress-default-backend ClusterIP 10.111.73.136 <none> 80/TCP 16m
kube-system kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 6d6h
kubernetes-dashboard cm-acme-http-solver-kw8zn NodePort 10.107.15.18 <none> 8089:30074/TCP 140m
kubernetes-dashboard dashboard-metrics-scraper ClusterIP 10.96.228.215 <none> 8000/TCP 5d18h
kubernetes-dashboard kubernetes-dashboard ClusterIP 10.99.250.49 <none> 443/TCP 4d6h
这里有更多例子正在发生的事情:
curl -D- http://<public_ip>:31122 -H 'Host: <domain>'
- returns 308,因为协议是 http 而不是 https。这是预期的
curl -D- http://<public_ip> -H 'Host: <domain>'
curl: (7) Failed to connect to <public_ip> port 80: Connection refused
- 端口 80 已关闭
curl -D- --insecure https://10.65.106.240 -H "Host: <domain>"
- 通过内部 IP 访问仪表板显然有效,我得到了正确的 k8s-dashboard html。
--insecure
是因为 let's encrypt 还没有工作,因为端口 80 上的 acme 挑战无法访问。
所以回顾一下,我如何让 2.
工作?例如。通过 80/443 获得服务?
编辑:Nginx 入口控制器 .yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: "2020-02-12T20:20:45Z"
labels:
app: nginx-ingress
chart: nginx-ingress-1.30.1
component: controller
heritage: Helm
release: nginx-ingress
name: nginx-ingress-controller
namespace: ingress-nginx
resourceVersion: "1785264"
selfLink: /api/v1/namespaces/ingress-nginx/services/nginx-ingress-controller
uid: b3ce0ff2-ad3e-46f7-bb02-4dc45c1e3a62
spec:
clusterIP: 10.100.64.210
externalTrafficPolicy: Cluster
ports:
- name: http
nodePort: 31122
port: 80
protocol: TCP
targetPort: http
- name: https
nodePort: 32697
port: 443
protocol: TCP
targetPort: https
selector:
app: nginx-ingress
component: controller
release: nginx-ingress
sessionAffinity: None
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 10.65.106.240
编辑 2:metallb configmap yaml
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 10.65.106.240-10.65.106.250
更新:
我在写这个答案时没有看到问题的 edit 部分。鉴于提供的附加信息,这没有意义。请无视
原文:
显然,您现在使用的集群通过 node-port
类型服务而不是 load-balancer
设置了入口控制器。为了获得所需的行为,您需要更改入口控制器的配置。请参阅 nginx ingress controller documentation for metalLB cases 如何执行此操作。
所以,要解决第二个问题,正如我所建议的,您可以使用 hostNetwork: true
参数将容器端口映射到它所在的主机 运行。请注意,这不是推荐的做法,您应该始终避免这样做,除非您有理由。
示例:
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
hostNetwork: true
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
hostPort: 80 # this parameter is optional, but recommended when using host network
name: nginx
当我部署这个 yaml 时,我可以检查 pod 的位置 运行 并卷曲该主机的端口 80。
root@v1-16-master:~# kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 105s 10.132.0.50 v1-16-worker-2 <none> <none>
注意:现在我知道 pod 在工作节点 2 上 运行。我只需要它的 IP 地址。
root@v1-16-master:~# kubectl get no -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
v1-16-master Ready master 52d v1.16.4 10.132.0.48 xxxx Ubuntu 16.04.6 LTS 4.15.0-1052-gcp docker://19.3.5
v1-16-worker-1 Ready <none> 52d v1.16.4 10.132.0.49 xxxx Ubuntu 16.04.6 LTS 4.15.0-1052-gcp docker://19.3.5
v1-16-worker-2 Ready <none> 52d v1.16.4 10.132.0.50 xxxx Ubuntu 16.04.6 LTS 4.15.0-1052-gcp docker://19.3.5
v1-16-worker-3 Ready <none> 20d v1.16.4 10.132.0.51 xxxx Ubuntu 16.04.6 LTS 4.15.0-1052-gcp docker://19.3.5
root@v1-16-master:~# curl 10.132.0.50 2>/dev/null | grep title
<title>Welcome to nginx!</title>
root@v1-16-master:~# kubectl delete po nginx
pod "nginx" deleted
root@v1-16-master:~# curl 10.132.0.50
curl: (7) Failed to connect to 10.132.0.50 port 80: Connection refused
当然,如果我在浏览器上访问 public IP,它也能正常工作。