对于负载均衡和外网代理的解决方案,云上环境,我们使用SLB;传统环境,我们会选Haproxy、LVS,但在kubernetes体系中,我只会选择ingress(controllers)!
Kubernetes暴露服务的方式目前只有三种:
- LadBlancer Service
LadBlancer Service 是Kubernetes深度结合云平台的一个组件;当使用LoadBlancer Service 暴露服务时,实际上是通过向底层云平台申请创建一个负载均衡器来向外暴露服务;目前LoadBlancer Service支持的云平台已经相对完善,比如国外的GCE、DigitalOcean,国内的阿里云,私有云(Openstack)等等,由于LoadBlancer Service深度结合了云平台,所以只能在一些云平台上使用- NodePort Service
NodePort Service顾名思义,实质上就是通过在集群的每个Node上暴露一个端口,然后将这个端口映射到某个具体的Service来实现的,虽然每个Node的端口有很多(0~65535),但是由于安全性和易用性(服务多了就乱了,端口冲突问题)实际使用可能并不多- Ingress
Ingress 是在Kubernetes 1.2后出现的,通过Ingress用户可以实现使用Nginx等开源的反向代理负载均衡实现对外暴露服务,以下详细说一下Ingress。
ingress是一个管理kubernetes集群南北流量的api 对象,典型的有HTTP。
并且可以提供:LB负载均衡的能力。
注意:
1. 南北流量和东西流量是服务网格中的经常描述网络流量的术语。
南北流量(NORTH-SOUTH traffic):集群外部->集群内部
东西流量(EAST-WEST traffic):集群内部相互访问
2. ingress仅是一段配置,你可以理解为SLB的配置信息片段。
实例化SLB能力的话,你还需要一个ingress controller。
Ingress Controller是一种能读懂ingress配置,并将其翻译成自己配置文件的应用程序。
比较常见的有ingress-nginx、kong、traefik、istio、envoy等
Ingress Controller:
将ingress配置信息转换为自身配置的应用程序
Ingress:
只定义流量转发和调度的通用格式的配置信息
如果你刚接触kubernetes,并且只是为了学习,建议直接使用ingress-nginx。
这张图我画的是基于ingress-nginx的技术栈,并通过nodeport类型的service,将ingress服务暴露到集群外,供客户端的访问。
你需要记住的是:
1.ingress controllers是实际的应用程序
2.ingress只是转发的配置信息,通过ingress controllers实例化,并且通过lua语言,在ingress-nginx的pod中,实例化成一个基础的nginx配置文件而已,和传统的nginx并无太大的差异。
1、首先,下载ingress-nginx的配置清单,修改images地址为阿里云(否则会被墙):registry.aliyuncs.com/google_containers/nginx-ingress-controller:0.26.1
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
2、使用apply -f mandatory.yaml启动配置清单,并查看Pod是否运行成功
[root@centos-1 dingqishi]# kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-dc55d4998-zxnrd 1/1 Running 0 20m
3、接着,编辑nginx-ingress-service.yaml配置文件
apiVersion: v1
kind: Service
metadata:
name: nginx-ingress-controller
namespace: ingress-nginx
spec:
type: NodePort
ports:
- port: 80 #Service端口
name: http
nodePort: 30080 #本机端口
- port: 443
name: https
nodePort: 30443
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
4、然后,apply -f配置文件,并观察。
你可以对比我上面的图,此时基于nodeport类型的nginx-ingress-controller的service已经部署成功。
[root@centos-1 dingqishi]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-ingress-controller NodePort 10.108.188.111 <none> 80:30080/TCP,443:30443/TCP 12m
此时,你可以通过访问任意一台虚拟机的30080端口,便能够访问到Nginx404页面
5、接下来,我们编辑myapp-svc.yaml和myapp-ingress.yaml,并通过apply -f创建。
我们期望将Deployment暴露到集群外,供客户端进行访问。
提示:
当你使用多个ingress-controllers的时候,可以通过kubernetes.io/ingress.class: "nginx"来申明使用哪一个controller
# myapp-svc.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: myns
spec:
replicas: 2
selector:
matchLabels:
app: myapp
rel: beta
template:
metadata:
namespace: myns
labels:
app: myapp
rel: beta
spec:
containers:
- name: myapp
image: registry.cn-hangzhou.aliyuncs.com/aaron89/myapp:v1
---
apiVersion: v1
kind: Service
metadata:
name: myapp
namespace: myns
spec:
selector:
app: myapp
rel: beta
ports:
- name: http
port: 80
targetPort: 80
#myapp-ingress.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: myapp
namespace: myns
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
kubernetes.io/ingress.class: "nginx" #当有多种ingress-controller的时候,用这个参数区分使用哪个controller
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /
backend:
serviceName: myapp
servicePort: 80
6、此时,修改本机hosts并访问foo.bar.com:30080`,可以成功
192.168.0.104 foo.bar.com
1、首先,编辑tomcat-svc-ingress.yaml,并apply -f生成。配置文件中的信息,应该可以一目了然。
apiVersion: v1
kind: Namespace
metadata:
name: eshop
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: tomcat
namespace: eshop
spec:
replicas: 2
selector:
matchLabels:
app: tomcat
rel: beta
template:
metadata:
namespace: eshop
labels:
app: tomcat
rel: beta
spec:
containers:
- name: tomcat
image: tomcat:alpine
---
apiVersion: v1
kind: Service
metadata:
name: tomcat
namespace: eshop
spec:
selector:
app: tomcat
rel: beta
ports:
- name: http
port: 8080
targetPort: 8080 #tomcat(Pod)端口
- name: ajp
port: 8009
targetPort: 8009 #tomcat(Pod)端口
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: tomcat
namespace: eshop
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
kubernetes.io/ingress.class: "nginx" #当有多种ingress-controller的时候,用这个参数区分使用哪个controller
spec:
rules:
- host: eshop.foo.com
http:
paths:
- path: /
backend:
serviceName: tomcat
servicePort: 8080
2、观察集群资源生成情况
[root@centos-1 dingqishi]# kubectl get all -n eshop
NAME READY STATUS RESTARTS AGE
pod/tomcat-6b6fb9c8f6-jq9w2 1/1 Running 0 4m33s
pod/tomcat-6b6fb9c8f6-qz8z6 1/1 Running 0 4m33s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/tomcat ClusterIP 10.110.148.61 <none> 8080/TCP,8009/TCP 4m33s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/tomcat 2/2 2 2 4m33s
NAME DESIRED CURRENT READY AGE
replicaset.apps/tomcat-6b6fb9c8f6 2 2 2 4m33s
3、观察ingress条目生成情况
[root@centos-1 dingqishi]# kubectl get ingress -n eshop
NAME HOSTS ADDRESS PORTS AGE
tomcat eshop.foo.com 80 5m23s
[root@centos-1 dingqishi]#kubectl describe ingress tomcat -n eshop
Name: tomcat
Namespace: eshop
Address:
Default backend: default-http-backend:80 (<none>)
Rules:
Host Path Backends
---- ---- --------
eshop.foo.com
/ tomcat:8080 (10.244.1.51:8080,10.244.2.34:8080)
4、进入ingress-nginx,查看配置文件生成情况。你会发现lua脚本已经将相关配置信息,读取了进来。
kubectl exec -it pod/nginx-ingress-controller-dc55d4998 -zxnrd -n ingress-nginx -- /bin/sh
more /etc/nginx/nginx.conf
## start server eshop.foo.com
server {
server_name eshop.foo.com ;
listen 80;
set $proxy_upstream_name "-";
location / {
set $namespace "eshop";
set $ingress_name "tomcat";
set $service_name "tomcat";
set $service_port "8080";
set $location_path "/";
rewrite_by_lua_block {
balancer.rewrite()
}
5、新增Mac本机Hosts文件,并测试,至此部署已经完成
192.168.0.11 eshop.foo.com
dingqishideMacBook-Pro:~ dingqishi$ curl -I eshop.foo.com:30080
HTTP/1.1 200
Server: nginx/1.15.5
Date: Tue, 03 Dec 2019 10:47:23 GMT
Content-Type: text/html;charset=UTF-8
Connection: keep-alive
Vary: Accept-Encoding
最新的安装地址请看:https://kubernetes.github.io/ingress-nginx/deploy/