前面已经提到,Service对集群之外暴露服务的主要方式有两种:NodePort和LoadBalancer,但是这两种方式,都有一定的缺点:
基于这种现状,kubernetes提供了Ingress资源对象,Ingress只需要一个NodePort或者一个LB就可以满足暴露多个service的需求。工作机制如下:
实际上,Ingress相当于一个7层的负载均衡器,是kubernetes对反向代理的一个抽象,它的工作原理类似于Nginx,可以理解成在Ingress 里建立诸多映射规则,Ingress Controller通过监听这些配置规则并转化成Nginx
Ingress(以Nginx为例)的工作原理如下
# 创建文件夹
[root@master ~]# mkdir ingress-controller
[root@master ~]# cd ingress-controller/
# 获取ingress-nginx
[root@master ingress-controller]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
[root@master ingress-controller]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml
[root@master ingress-controller]# ls
mandatory.yaml service-nodeport.yaml
[root@master ingress-controller]#
# 创建ingress-nginx
[root@master ingress-controller]# kubectl apply -f ./
namespace/ingress-nginx created
configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
serviceaccount/nginx-ingress-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-role created
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
deployment.apps/nginx-ingress-controller created
limitrange/ingress-nginx created
service/ingress-nginx created
# 查看ingress-nginx
[root@master ingress-controller]# kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-7f74f657bd-c2zwl 1/1 Running 0 3m16s
# 查看service
# 这里可以看到80对应的http端口(外部是30692), 443对应的https端口(外部是30254)
[root@master ingress-controller]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.97.146.1 <none> 80:31586/TCP,443:32714/TCP 4m6s
为例后面的实验方便,创建如下图所示的模型
创建tomcat-nginx.yaml
---
apiVersion: apps/v1 #版本号
kind: Deployment #类型
metadata: #元数据
name: nginx-deployment #rs名称
namespace: dev #所属命名空间
spec: #详情
replicas: 3 #副本数量3
selector: #选择器,通过它指定该控制器管理哪些pod
matchLabels: #labels匹配规则,用于匹配template
app: nginx-pod
template: #模板,当副本数量不足时,会根据模板创建pod副本
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.17.1
ports:
- containerPort: 80
---
apiVersion: apps/v1 #版本号
kind: Deployment #类型
metadata: #元数据
name: tomcat-deployment #rs名称
namespace: dev #所属命名空间
spec: #详情
replicas: 3 #副本数量3
selector: #选择器,通过它指定该控制器管理哪些pod
matchLabels: #labels匹配规则,用于匹配template
app: tomcat-pod
template: #模板,当副本数量不足时,会根据模板创建pod副本
metadata:
labels:
app: tomcat-pod
spec:
containers:
- name: tomcat
image: tomcat:8.5-jre10-slim
ports:
- containerPort: 8080
---
apiVersion: v1 #版本号
kind: Service #类型
metadata: #元数据
name: nginx-service #svc名称
namespace: dev #所属命名空间
spec: #详情
selector: #选择器,通过它指定该控制器管理哪些pod
app: nginx-pod
clusterIP: None # 将clusterIP设置为None,即可创建headliness Service
type: ClusterIP
ports:
- port: 80 #Service端口
targetPort: 80 #pod端口
---
apiVersion: v1 #版本号
kind: Service #类型
metadata: #元数据
name: tomcat-service #svc名称
namespace: dev #所属命名空间
spec: #详情
selector: #选择器,通过它指定该控制器管理哪些pod
app: tomcat-pod
clusterIP: None # 将clusterIP设置为None,即可创建headliness Service
type: ClusterIP
ports:
- port: 8080 #Service端口
targetPort: 8080
# 创建 pod和service
[root@master ~]# kubectl create -f tomcat-nginx.yaml
deployment.apps/nginx-deployment created
deployment.apps/tomcat-deployment created
service/nginx-service created
service/tomcat-service created
# 查看service
[root@master ~]# kubectl get svc -n dev
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-service ClusterIP None <none> 80/TCP 13s
tomcat-service ClusterIP None <none> 8080/TCP 13s
创建ingress-http.yaml
apiVersion: extensions/v1beta1 #版本号
kind: Ingress #类型
metadata: #元数据
name: ingress-http #svc名称
namespace: dev #所属命名空间
spec: #详情
rules:
- host: nginx.abc.com
http:
paths:
- path: /
backend:
serviceName: nginx-service
servicePort: 80
- host: tomcat.abc.com
http:
paths:
- path: /
backend:
serviceName: tomcat-service
servicePort: 8080
# 创建ingress
[root@master ~]# kubectl create -f ingress-http.yaml
ingress.extensions/ingress-http created
# 查看ingress
[root@master ~]# kubectl get ing ingress-http -n dev
NAME HOSTS ADDRESS PORTS AGE
ingress-http nginx.abc.com,tomcat.abc.com 80 17s
# 查看ingress详情
[root@master ~]# kubectl describe ing ingress-http -n dev
Name: ingress-http
Namespace: dev
Address:
Default backend: default-http-backend:80 (<none>)
Rules:
Host Path Backends
---- ---- --------
nginx.abc.com
/ nginx-service:80 (10.244.1.108:80,10.244.2.178:80,10.244.2.179:80)
tomcat.abc.com
/ tomcat-service:8080 (10.244.1.107:8080,10.244.1.109:8080,10.244.2.180:8080)
Annotations:
Events: <none>
[root@master ~]#
配置host域名
192.168.88.100 nginx.abc.com
192.168.88.100 tomcat.abc.com
打开浏览器访问http://nginx.abc.com:31586/和http://tomcat.abc.com:31586/,(端口请查看ingress-nginx的80对应的端口)
[root@master ~]# kubectl get svc ingress-nginx -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.97.146.1 <none> 80:31586/TCP,443:32714/TCP 12m
[root@master ~]#
# 生成证书
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/C=CN/ST=BJ/L=BJ/O=nginx/CN=abc.com"
# 创建密钥
kubectl create secret tls tls-secret --key tls.key --cert tls.crt
创建ingress-https.yaml
apiVersion: extensions/v1beta1 #版本号
kind: Ingress #类型
metadata: #元数据
name: ingress-https #svc名称
namespace: dev #所属命名空间
spec: #详情
tls:
- hosts:
- nginx.abc.com
- tomcat.abc.com
secretName: tls-secret #指定密钥
rules:
- host: nginx.abc.com
http:
paths:
- path: /
backend:
serviceName: nginx-service
servicePort: 80
- host: tomcat.abc.com
http:
paths:
- path: /
backend:
serviceName: tomcat-service
servicePort: 8080
# 生成证书
[root@master ~]# openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/C=CN/ST=BJ/L=BJ/O=nginx/CN=abc.com"
Generating a 2048 bit RSA private key
.....................................................................................+++
.............+++
writing new private key to 'tls.key'
-----
# 创建密钥
[root@master ~]# kubectl create secret tls tls-secret --key tls.key --cert tls.crt
secret/tls-secret created
[root@master ~]# vim ingress-https.yaml
# 创建sevice
[root@master ~]# kubectl create -f ingress-https.yaml
ingress.extensions/ingress-https created
# 查看ingress
[root@master ~]# kubectl get ing ingress-https -n dev
NAME HOSTS ADDRESS PORTS AGE
ingress-https nginx.abc.com,tomcat.abc.com 80, 443 15s
# 查看ingress详情,可以看到describe有一个TLS,表示https配置成功
[root@master ~]# kubectl describe ing ingress-https -n dev
Name: ingress-https
Namespace: dev
Address:
Default backend: default-http-backend:80 (<none>)
TLS:
tls-secret terminates nginx.abc.com,tomcat.abc.com
Rules:
Host Path Backends
---- ---- --------
nginx.abc.com
/ nginx-service:80 (10.244.1.118:80,10.244.2.195:80,10.244.2.197:80)
tomcat.abc.com
/ tomcat-service:8080 (10.244.1.116:8080,10.244.1.117:8080,10.244.2.196:8080)
Annotations:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal CREATE 30s nginx-ingress-controller Ingress dev/ingress-https
[root@master ~]#
打开浏览器访问https://nginx.abc.com:32714/和https://tomcat.abc.com:32714/,(端口请查看ingress-nginx的443对应的端口)
[root@master ~]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.97.146.1 <none> 80:31586/TCP,443:32714/TCP 38m
[root@master ~]#
浏览器一直空转
排查发现ingress-http的镜像下载失败,使用官方镜像即可。
如果七牛的镜像无法下载,请使用官方镜像。
# 七牛镜像(可能不可靠)
quay-mirror.qiniu.com/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0
修改使用官方镜像:
# 官方镜像(默认)
quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0