ingress-nginx简介
为了使Kubernetes外部的用户能够访问集群内的服务,Kubernetes 目前提供了以下几种方案:
- NodePort:最简单,用命令
kubectl expose deployment [deply_name] --type=NodePort
直接配置就可以 - LoadBalancer:详见https://blog.csdn.net/lic95/article/details/125076060
- Ingress:k8s推荐用ingress-nginx,下面详细介绍ingress-nginx
ingress-nginx组成
- ingress controller:将新加入的Ingress转化成Nginx的配置文件并使之生效
- ingress服务:将Nginx的配置抽象成一个Ingress对象,每添加一个新的服务只需写一个新的Ingress的yaml文件即可
ingress-nginx工作原理
- ingress controller通过和kubernetes api交互,动态的去感知集群中ingress规则变化,然后读取它;
- 按照自定义的规则,规则就是写明了哪个域名对应哪个service,生成一段nginx配置;
- 写到nginx-ingress-control的pod里,这个Ingress controller的pod里运行着一个Nginx服务;
- 控制器会把生成的nginx配置写入/etc/nginx.conf文件中,然后reload一下使配置生效。
- 达到域名分配置和动态更新的问题。
解决问题
- 动态配置服务
如果按照传统方式, 当新增加一个服务时, 我们可能需要在流量入口加一个反向代理指向我们新的k8s服务. 而如果用了Ingress, 只需要配置好这个服务, 当服务启动时, 会自动注册到Ingress的中, 不需要额外的操作。 - 减少不必要的端口暴露
配置过k8s的都清楚, 第一步是要关闭防火墙的, 主要原因是k8s的很多服务会以NodePort方式映射出去, 这样就相当于给宿主机打了很多孔, 既不安全也不优雅. 而Ingress可以避免这个问题, 除了Ingress自身服务可能需要映射出去, 其他服务都不要用NodePort方式
部署
mkdir -p nginx-ingress
cd nginx-ingress
curl -O https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.0/deploy/static/provider/cloud/deploy.yaml
因为里面的2个镜像在k8s.gcr.io上,需要科学上网才能正常下载,否则无法正常安装k8s.gcr.io/ingress-nginx/controller:v1.2.0
k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1
kubectl apply -f deploy.yaml
测试
-
部署测试应用
kubectl create deploy echoserver --image=cilium/echoserver --replicas=2
echoserver会简单输出hostname,本次只使用到这一功能
-
部署service
# 创建svc,默认以ClusterIP模式创建,只允许集群内部访问
kubectl expose deployment echoserver --port=80
#查看服务,正常两个hostname随机显示
curl http://ClusterIP
-
查看ingress-nginx svc
[root@cka-1 ingress-nginx]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.109.134.0 <pending> 80:32456/TCP,443:32350/TCP 12m
ingress-nginx-controller-admission ClusterIP 172.18.162.225 <none> 443/TCP 12m
使用NodePort测试,`kubectl edit svc -n ingress-nginx ingress-nginx-controller修改LoadBalancer为NodePort
-
生成nginx策略
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-echoserver-test
spec:
rules:
- host: echoserver.test # 域名
http:
paths:
- path: / # 代理目录
pathType: Prefix #path类型,下面
backend:
service:
name: echoserver # 对应service名称
port:
number: 80 # service 端口
ingressClassName: nginx # 指定选择的 Ingress Controller
ingress支持的path类型:
ImplementationSpecific:对于这种path类型,匹配取决于IngressClass。可以将其视为一个单独的pathType或者将其认为和Prefix或者Exact路径类型一样。
Exact:精确匹配URL路径,并且区分大小写
Prefix:根据URL中的,被/分割的前缀进行匹配。匹配区分大小写并且按照元素对路径进行匹配。path元素指的是路径中由/分隔符分隔的标签列表。
注意:如果路径的最后一个元素是请求路径中最后一个元素的子字符串,那么这个是不匹配的。
【举例:/foo/bar匹配/foo/bar/baz,但是不匹配/foo/barbaz】
kubectl apply -f ingress-echoserver-test.yaml
kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-echoserver-test nginx echoserver.test 10.109.134.0 80 20s
-
结果
curl -H "Host: echoserver.test" http://192.168.3.30:32217
Hostname: echoserver-8585bfb456-f859x
此时还是虽然已经具备nginx规则,但还是需要加上端口,下一篇使用LoadBalancer解决这个问题