Ingress
在Kubernetes中,服务和Pod的IP地址仅可以在集群网络内部使用,对于集群外的应用是不可见的。为了使外部的应用能够访问集群内的服务,在Kubernetes中目前提供了以下几种方案:
NodePort
LoadBalancer
Ingress
NodePort:简单的来说就是通过Service资源对象,为后端的Pod提供一个统一的访问入口,然后将Service的统一访问接口映射到集群节点上,最终实现client通过映射到集群节点上的端口访问到后端Pod提供的服务
但是,这种方法有个弊端,就是当新生成一个pod服务就需要创建对应的service将其映射到节点端口,当运行的pod过多时,我们节点暴露给client端的端口也会随之增加,这样我们整个k8s群集的危险系数就会增加,因为我们在搭建群集之处,官方明确指出,必须关闭firewalld防火墙及清空iptables规则,现在我们又暴露了那么多端口给client,安全系数可想而知
Ingress就解决了这个弊端:
简单的理解:原先暴露的service,现在给定一个统一的访问入口
Ingress资源对象的组成:
Ingress-nginx-controller:
将新加入的Ingress转化为反向代理服务器的配置文件,并使之生效(动态的感知k8s集群内Ingress资源的变化,通过lua脚本实现)
Ingress:
将反向代理服务器抽象成一个Ingress对象,每添加一个新的服务,只需要写一个新的Ingress的yaml文件即可,或修改已经存在的Ingress规则的yaml
在k8s集群前边部署一个反向代理服务器,这个服务器代理着k8s集群内部的service资源
Ingress-nginx可以解决什么问题:
动态的配置服务
如果按照传统方式, 当新增加一个服务时, 我们可能需要在流量入口加一个反向代理指向我们新的k8s服务. 而如果用了Ingress-nginx, 只需要配置好这个服务, 当服务启动时, 会自动注册到Ingress的中, 不需要而外的操作
减少不必要的端口暴露
配置过k8s的都清楚, 第一步是要关闭防火墙的, 主要原因是k8s的很多服务会以NodePort方式映射出去, 这样就相当于给宿主机打了很多孔, 既不安全也不优雅. 而Ingress可以避免这个问题, 除了Ingress自身服务可能需要映射出去, 其他服务都不要用NodePort方式
Ingress-nginx工作原理:
1)Ingress controller通过和kubernetes api交互,动态的去感知集群中Ingress规则变化,
2)然后读取它,按照自定义的规则,规则就是写明了哪个域名对应哪个service,生成一段nginx配置,
3)再写到nginx-ingress-controller的pod里,这个Ingress controller的pod里运行着一个Nginx服务,控制器会把生成的nginx配置写入/etc/nginx.conf文件中,
4)然后reload一下使配置生效。以此达到域名分别配置和动态更新的问题
基于Nginx的Ingress controller根据不同的开发公司,又分为两种:
k8s社区版的:Ingress-nginx
nginx公司自己开发的:nginx-ingress
Ingress-nginx配置实例:
1)创建一个web服务,用deployment资源,用httpd奖项,然后创建一个service资源与之关联
[root@master ~]# vim deploy_1.yaml
apiVersion: v1
kind: Namespace
metadata:
name: bdqn-ns
labels:
name: bdqn-ns
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: httpd-deploy
namespace: bdqn-ns
spec:
replicas: 2
template:
metadata:
labels:
app: bdqn-ns
spec:
containers:
- name: httpd
image: httpd
---
apiVersion: v1
kind: Service
metadata:
name: httpd-svc
namespace: bdqn-ns
spec:
type: NodePort
selector:
app: bdqn-ns
ports:
- name: httpd-port
port: 80
targetPort: 80
nodePort: 31033
[root@master ~]# kubectl apply -f deploy_1.yaml
namespace/bdqn-ns created
deployment.extensions/httpd-deploy created
service/httpd-svc created
[root@master ~]# kubectl get svc -n bdqn-ns
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
httpd-svc NodePort 10.97.86.190 <none> 80:31033/TCP 3m31s
[root@master ~]# kubectl get pod -n bdqn-ns
NAME READY STATUS RESTARTS AGE
httpd-deploy-966699d76-25wkn 1/1 Running 0 3m33s
httpd-deploy-966699d76-6cdwf 1/1 Running 0 3m34s
[root@master ~]# kubectl get deployments. -n bdqn-ns
NAME READY UP-TO-DATE AVAILABLE AGE
httpd-deploy 2/2 2 2 3m37s
[root@master ~]# kubectl describe svc -n bdqn-ns
Selector: app=bdqn-ns
Type: NodePort
IP: 10.97.86.190
Port: httpd-port 80/TCP
TargetPort: 80/TCP
NodePort: httpd-port 31033/TCP
Endpoints: 10.244.1.2:80,10.244.2.2:80
Session Affinity: None
External Traffic Policy: Cluster
2)创建一个web服务,用deployment资源,用tomcat镜像,然后创建一个service资源与之关联
[root@master ~]# vim deploy_2.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: tomcat-deploy
namespace: bdqn-ns
spec:
replicas: 2
template:
metadata:
labels:
app: bdqn-tomcat
spec:
containers:
- name: tomcat
image: tomcat:8.5.45
---
apiVersion: v1
kind: Service
metadata:
name: tomcat-svc
namespace: bdqn-ns
spec:
type: NodePort
selector:
app: bdqn-tomcat
ports:
- name: tomcat-port
port: 8080
targetPort: 8080
nodePort: 32033
[root@master ~]# kubectl apply -f deploy_2.yaml
deployment.extensions/tomcat-deploy created
service/tomcat-svc created
[root@master ~]# kubectl get deployments. -n bdqn-ns
NAME READY UP-TO-DATE AVAILABLE AGE
httpd-deploy 2/2 2 2 9m58s
tomcat-deploy 2/2 2 2 58s
[root@master ~]# kubectl get pod -n bdqn-ns
NAME READY STATUS RESTARTS AGE
httpd-deploy-966699d76-25wkn 1/1 Running 0 10m
httpd-deploy-966699d76-6cdwf 1/1 Running 0 10m
tomcat-deploy-759dc8c885-9wgqw 1/1 Running 0 70s
tomcat-deploy-759dc8c885-9xmhj 1/1 Running 0 70s
[root@master ~]# kubectl get svc -n bdqn-ns
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
httpd-svc NodePort 10.97.86.190 <none> 80:31033/TCP 10m
tomcat-svc NodePort 10.98.122.36 <none> 8080:32033/TCP 75s
3)创建Ingress -nginx-controller
[root@master ~]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.29.0/deploy/static/mandatory.yaml
//将yaml文件下载下来
在yaml文件中添加:hostNetwork: true
spec: //在212行的spec字段下添加
hostNetwork: true //添加这行就行
# wait up to five minutes for the drain of connections
[root@master ~]# kubectl apply -f mandatory.yaml
[root@master ~]# kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-5954d475b6-xtzbc 1/1 Running 0 16m
hostNetwork: true
在deployment资源中,如果添加了此字段,意味着Pod中运行的应用可以直接使用node节点的端口,这样node节点主机所在网络的其他主机,就可以通过访问该端口访问此应用。(类似于docker映射到宿主机的端口)
4)创建Ingress资源:(定义Ingress规则)
[root@master ~]# vim ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: bdqn-ingress
namespace: bdqn-ns
annotations:
nginx.ingress.kubernetes.io/rewrite-target: / #这个千万不要写错,不然后面无法访问
spec:
rules:
- host: ingress.bdqn.com
http:
paths:
- path: /
backend:
serviceName: httpd-svc
servicePort: 80
- path: /tomcat
backend:
serviceName: tomcat-svc
servicePort: 8080
[root@master ~]# kubectl apply -f ingress.yaml
ingress.extensions/bdqn-ingress created
[root@master ~]# kubectl describe ingresses. -n bdqn-ns bdqn-ingress
Rules:
Host Path Backends
---- ---- --------
ingress.bdqn.com
/ httpd-svc:80 (10.244.1.5:80,10.244.2.4:80)
/tomcat httpd-tomcat:8080 (10.244.1.4:8080,10.244.2.5:8080)
//如果没有这个信息说明Ingress创建的有问题
[root@master ~]# kubectl exec -it -n ingress-nginx nginx-ingress-controller-5954d475b6-wkqr2 sh
/etc/nginx $ cat nginx.conf
//没创建Ingress之前这些值都是空的,这就是动态的感知,然后写入配置文件
location / {
set $namespace "bdqn-ns";
set $ingress_name "bdqn-ingress";
set $service_name "httpd-svc";
set $service_port "80";
set $location_path "/";
location ~* "^/tomcat" {
set $namespace "bdqn-ns";
set $ingress_name "bdqn-ingress";
set $service_name "tomcat-svc";
set $service_port "8080";
set $location_path "/tomcat";
因为域名是自定义的,所以要配置域名解析,修改windows的host文件,将IP与域名绑定
//查看Ingress-controller运行在哪个节点,IP 是 ingress-controller Pod运行所在的节点
[root@master ~]# kubectl get pod -n ingress-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-ingress-controller-5954d475b6-wkqr2 1/1 Running 1 44h 192.168.1.50 node01 <none> <none>
//找到host文件,进行修改
C:\Windows\System32\drivers\etc
192.168.1.50 ingress.bdqn.com
现在已经达到了我们想要的功能,现在可以通过ingress.bdqn.com访问httpd服务,通过ingress.bdqn.com/tomcat访问tomcat服务
在上面的访问测试中,虽然访问到了对应的服务,但是有一个弊端,就是在做DNS解析的时候,只能指定Ingress-nginx容器所在的节点IP。而指定k8s集群内部的其他节点IP(包括master)都是不可以访问到的,如果这个节点一旦宕机,Ingress-nginx容器被转移到其他节点上运行(不考虑节点标签的问题,其实保持Ingress-nginx的yaml文件中默认的标签的话,那么每个节点都是有那个标签的)。随之还要我们手动去更改DNS解析的IP(要更改为Ingress-nginx容器所在节点的IP,通过命令“kubectl get pod -n ingress-nginx -o wide”可以查看到其所在节点),很是麻烦
所以就要为ingress资源对象创建一个Service(NodePort),这样在配置DNS解析的时候,就可以通过Ingress.bdqn.com 所有node节点,包括master节点的IP来配置,很方便
5)创建service资源:
[root@master ~]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.29.0/deploy/static/provider/baremetal/service-nodeport.yaml
[root@master ~]# kubectl apply -f service-nodeport.yaml
[root@master ~]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.100.167.12 <none> 80:32756/TCP,443:30501/TCP 2m7s
Service-Nodeport
因为Ingress-nginx-controller运行在了集群内的其中一个节点,为了保证即使这个节点宕机,我们对应的域名仍然能够正常的访问服务,所以我们将Ingress-nginx-controller也暴露为一个service资源
至此,这个域名就可以和集群中任意节点的 32756/30501端口进行绑定了