目录
基本介绍
如何构建ingress controller
nginx容器服务的部署
1. ingress HTTP代理访问
2. ingress HTTPS代理访问
3. Nginx 进行 BasicAuth基础认证
4. Nginx 进行重写
对于我们传统的SVC来说,它只支持四层反向代理,但是如果遇到七层的话,就无法去实现,如下:
假如说,我们有如上的一个集群,我们现在想要对整个集群,或者是Apache进行https的加密访问,也就是我们的客户端想要跟我们的Apache进行HTTPS访问,我们完全不需要在每一台Apache上配置我们的HTTPS,我们只需要在NGINX上开启HTTPS认证即可。。。。当我们的客户访问到NGINX的时候,由于NGINX和客户端之间是加密访问,NGINX因为本地没有数据,它会向后端进行反向代理,反向代理的时候走是HTTPS协议,但是NGINX和Apache都是在一个集群之下,属于内部访问(clusterIp)的形式,所以也没有必要采用HTTPS连接,但是NGINX对外部的话,都是采用HTTPS连接,此时NGINX的作用相当于是HTTPS会话卸载的目的。
如果放在我们的k8s集群之中的话,若仅仅通过svc的方式去实现一个加密访问的话,就需要在每个Apache上配置一个HTTPS加密认证证书,然后在默认的svc上进行所谓的HTTPS连接,这样是不友好的,因为HTTPS加密认证的消耗资源还是挺大的。
先简单介绍一下ingress的方案实现
1. ingress-haproxy
2. ingress-nginx
这里只介绍nginx的实现方案
分析:首先我们的客户端先访问至我们的域名,也就是说对于ingress来说,我们必须要绑定一个域名(或者多个也行),毕竟实现的是一个七层的代理,不同的域名会访问至我们的Nginx软件,Nginx会反向代理或者是负载均衡至后端的服务,这些service会对应我们的容器服务。
上面的流程,我们需要了解个问题,
1. Nginx就是如何跟我们的后端服务(容器)进行连接的?
其实对于Nginx的暴露方案,还是我们的NodePort,这样Nginx就会以内部的服务暴露给外部用户,然后外部用户就可以访问到我们的Nginx,然后Nginx连接不同的service。也就是说我们也需要创建对应容器服务的svc与Nginx进行关联。
ingress修改之后的nginx内部的实现方案
Ingress-Nginx 官方网站:https://kubernetes.github.io/ingress-nginx/
ingress-nginx Gitee地址:https://gitee.com/leechm/k8s-ingress-nginx.git
去ingress-nginx的码云地址下载对应的ingress-nginx版本,就可以去部署了
[root@master1 ingress]# git clone -b nginx-0.25.0 https://gitee.com/leechm/k8s-ingress-nginx.git
[root@master1 static]# pwd
/root/k8s/test/ingress/k8s-ingress-nginx/deploy/static
[root@master1 static]# kubectl apply -f ./
注意,若报错如下:
Failed to list *v1beta1.Ingress: ingresses.networking.k8s.io is forbidden.......
编辑ingress的 mandatory.yaml 在ClusterRole位置添加下述代码然后重新replace -f 即可
- apiGroups:
- "extensions"
- "networking.k8s.io"
resources:
- ingresses
verbs:
- list
- watch
最后部署成功如下:
[root@master1 static]# kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-7995bd9c47-9q2gt 1/1 Running 4 7m47s
[root@master1 static]#
然后为Ingress Controller 创建一个NodePort 类型得Service
[root@master1 static]# kubectl apply -f ./provider/baremetal/service-nodeport.yaml
service/ingress-nginx created
[root@master1 static]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.1.39.237 80:31531/TCP,443:32449/TCP 11s
[root@master1 static]#
这样我们的nginx controller就已经暴露出去了
service-nodeport.yaml文件,这个文件得目的是为Ingress Controller 接入外部得流量,如果没有这个文件,是无法通过外部浏览器访问的。nginx controller部署完成之后,我们进行代理方案的试验,即开始服务的部署。
下面的三种访问方式,其实最主要的区别在于Ingress这个类型的不一样,像Deployment和它对于的Service都是一样的,所以我们可以只创建一次Deployment和Service,但是我下面的步骤,创建了三次,这个可忽略啊。
deployment、Service、Ingress Yaml 文件
[root@master1 ingress]# cat ingress-depl-http.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-dm
spec:
replicas: 2
template:
metadata:
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx:alpine
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
name: nginx
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-test
spec:
rules:
- host: www.leechm.com
http:
paths:
- path: /
backend:
serviceName: nginx-svc
servicePort: 80
[root@master1 ingress]#
[root@master1 ingress]# kubectl get svc -A
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.1.0.1 443/TCP 20h
default myapp ClusterIP 10.1.220.137 80/TCP 17h
default nginx-svc ClusterIP 10.1.57.234 80/TCP 2m52s
ingress-nginx ingress-nginx NodePort 10.1.39.237 80:31531/TCP,443:32449/TCP 11m
kube-system kube-dns ClusterIP 10.1.0.10 53/UDP,53/TCP,9153/TCP 20h
[root@master1 ingress]# kubectl get ingresses -A
NAMESPACE NAME HOSTS ADDRESS PORTS AGE
default nginx-test www.leechm.com 80 13m
我们的nginx-svc是一个ClusterIP 的形式,这个仅供集群内部访问,但是我们这里有一个ingress-nginx与之绑定,并且ingress-nginx是以NodePort 形式。因为我们物理机此时还没有进行域名解析,此时需要去设置一下
C:\Windows\System32\drivers\etc
通过浏览器访问
创建证书,以及 cert 存储方式
[root@master1 https] openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"
[root@master1 https] kubectl create secret tls tls-secret --key tls.key --cert tls.crt
deployment、Service、Ingress Yaml 文件
[root@master1 https]# cat ingress-depl-https.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-dm
spec:
replicas: 2
template:
metadata:
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx:alpine
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
name: nginx
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-test-https
spec:
tls:
- hosts:
- www1.leechm.com
secretName: tls-secret
rules:
- host: www1.leechm.com
http:
paths:
- path: /
backend:
serviceName: nginx-svc
servicePort: 80
[root@master1 https]#
[root@master1 https]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.1.39.237 80:31531/TCP,443:32449/TCP 96m
[root@master1 https]#
添加Windows域名解析
注意:为啥443端口是加密访问,这个得从我们之前部署nginx的时候,对于80端口是HTTP,443端口是HTTPS。
[root@master1 basic-auth]# yum -y install httpd
[root@master1 basic-auth]# htpasswd -c auth foo
New password:
Re-type new password:
Adding password for user foo
[root@master1 basic-auth]# kubectl create secret generic basic-auth --from-file=auth
secret/basic-auth created
[root@master1 basic-auth]#
[root@master1 basic-auth]# kubectl apply -f basic-auth.yaml
deployment.extensions/nginx-dm unchanged
service/nginx-svc unchanged
ingress.extensions/ingress-with-auth created
deployment、Service、Ingress Yaml 文件
[root@master1 basic-auth]# cat basic-auth.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-dm
spec:
replicas: 2
template:
metadata:
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx:alpine
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
name: nginx
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-with-auth
annotations:
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - foo'
spec:
rules:
- host: www2.leechm.com
http:
paths:
- path: /
backend:
serviceName: nginx-svc
servicePort: 80
[root@master1 basic-auth]#
记得添加Windows域名,然后访问一下,输入账号密码即可
[root@master1 basic-auth]# cat basic-auth-rewrite.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-dm
spec:
replicas: 2
template:
metadata:
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx:alpine
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
name: nginx
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-test
annotations:
nginx.ingress.kubernetes.io/rewrite-target: http://www2.leechm.com:31531/
spec:
rules:
- host: www.re.com
http:
paths:
- path: /
backend:
serviceName: nginx-svc
servicePort: 8
[root@master1 basic-auth]#
添加Windows域名关系
192.168.64.150 www.re.com
上面的basic-auth-rewrite.yaml 实现的效果就是通过访问www.re.com:31531,地址跳转到http://www2.leechm.com:31531/
补充:
我们的nginx-ingress-controller这个的作用就是实现反向代理
[root@master1 basic-auth]# kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-7995bd9c47-9q2gt 1/1 Running 5 148m
我们可以进入看看
[root@master1 ingress]# kubectl exec -it nginx-ingress-controller-7995bd9c47-9q2gt -n ingress-nginx bash
www-data@nginx-ingress-controller-7995bd9c47-9q2gt:/etc/nginx$ cat nginx.conf
Ingress Controller 会动态感知集群中的Ingress的规则变化,然后读取,动态生成Nginx的配置文件,最后注入到运行nginx的pod的中,然后会自动reload,配置生效,例如: