ingress
一、ingress相关简介
1.ingress概述
Ingress公开了从集群外部到集群内服务的HTTP和HTTPS路由。流量路由由Ingress资源上定义的规则控制。
下面是一个将所有流量都发送到同一Service的简单Ingress示例:
可以将Ingress配置为服务提供外部可访问的URL、负载均衡流量、终止SSL/TLS,以及提供基于名称的虚拟主机等能力。Ingress控制器通常负责通过负载均衡器来实现Ingress,尽管它也可以配置边缘路由器或其他前端来帮助处理流量。
Ingress不会公开任意端口或协议。将HTTP和HTTPS以外的服务公开到Internet时,通常使用Service.Type=NodePort或Service.Type=LoadBalancer类型的服务。
在Kubernetes中,服务和Pod的IP地址仅可以在集群网络内部使用,对于集群外的应用是不可见的。为了使外部的应用能够访问集群内的服务,Kubernetes目前提供了以下几种方案:
NodePort
LoadBalancer(负载均衡)
Ingress(入口)
2.Ingress组成
ingress controller:将新加入的Ingress转化成Nginx的配置文件并使之生效。
3.ingress服务
将Nginx的配置抽象成一个Ingress对象,每添加一个新的服务只需写一个新的Ingress的yaml文件即可。
4.Ingress工作原理
(1)ingress controller通过和kubernetes api交互,动态的去感知集群中ingress规则变化;
(2)然后读取它,按照自定义的规则,规则就是写明了哪个域名对应哪个service,生成一段nginx配置;
(3)再写到nginx-ingress-controller的pod里,这个Ingress controller的pod里运行着一个Nginx服务,控制器会把生成的nginx配置写入/etc/nginx.conf文件中;
(4)然后reload一下使配置生效。以此达到域名分配配置和动态更新的问题;
5.Ingress可以解决以下问题
(1)动态配置服务
如果按照传统方式,当新增加一个服务时,我们可能需要在流量入口加一个反向代理指向我们新的k8s服务.而如果用了Ingress,只需要配置好这个服务,当服务启动时,会自动注册到Ingress中,不需要额外的操作.
(2)减少不必要的端口暴露
配置过k8s的都清楚,第一步是要关闭防火墙的,主要原因是k8s的很多服务会以NodePort方式映射出去,这样就相当于给宿主机打了很多孔,既不安全也不优雅.而Ingress可以避免这个问题,除了Ingress自身服务可能需要映射出去,其他服务都不需要用NodePort方式。
6.实验要求
创建2个Deployment
第一个:nginx镜像,replicas:3;
第二个:httpd镜像,replicas:4;
创建2个SVC资源
第一个和第一个Deploy绑定;
第二个和第二个Deploy绑定;
(1)创建deploy-svc1.yaml文件和deploy-svc2.yaml 文件
[root@master ingress]# vim deploy-svc1.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: deploy1
spec:
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: deploy1
image: nginx
---
kind: Service
apiVersion: v1
metadata:
name: svc1
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
[root@master ingress]# vim deploy-svc2.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: deploy2
spec:
replicas: 4
template:
metadata:
labels:
app: httpd
spec:
containers:
- name: deploy1
image: httpd
---
kind: Service
apiVersion: v1
metadata:
name: svc2
spec:
selector:
app: httpd
ports:
- protocol: TCP
port: 80
targetPort: 80
[root@master ingress]# kubectl apply -f deploy-svc1.yaml
deployment.extensions/deploy1 created
service/svc1 created
[root@master ingress]# kubectl apply -f deploy-svc2.yaml
deployment.extensions/deploy2 created
service/svc2 created
[root@master ingress]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 39d
svc1 ClusterIP 10.104.24.77 <none> 80/TCP 59s
svc2 ClusterIP 10.99.246.13 <none> 80/TCP 55s
[root@master ingress]# kubectl get pod
NAME READY STATUS RESTARTS AGE
deploy1-5f7dd597c-jj5bd 1/1 Running 0 61s
deploy1-5f7dd597c-lhwwc 1/1 Running 0 61s
deploy1-5f7dd597c-rkcg7 1/1 Running 0 61s
deploy2-bf5d8d7b9-4p4ff 1/1 Running 0 57s
deploy2-bf5d8d7b9-74tgj 1/1 Running 0 57s
deploy2-bf5d8d7b9-lt79w 1/1 Running 0 57s
deploy2-bf5d8d7b9-z5rc4 1/1 Running 0 57s
(2)下载部署的Ingress:0.35.0版本,镜像是国外镜像,可以提前准备deploy.yaml
编辑文件启用hostNetwork网络,我们只需在deploy.yaml文件添加hostNetwork: true即可。 如果在Pod中使用hostNetwork:true配置网络,那么Pod中运行的应用程序可以直接使用node节点的端口,这样node节点主机所在网络的其他主机,都可以通过该端口访问到此应用程序。
[root@master ingress]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.35.0/deploy/static/provider/baremetal/deploy.yaml
[root@master ingress]# ls
deploy-svc1.yaml deploy.yaml
deploy-svc2.yaml
[root@master ingress]# vim deploy.yaml
...
spec:
hostNetwork: true #这里添加字段
dnsPolicy: ClusterFirst
containers:
- name: controller
...
[root@master ingress]# kubectl apply -f deploy.yaml
[root@master ingress]# kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-kz6xn 0/1 Completed 0 43s
ingress-nginx-admission-patch-mh2qq 0/1 Completed 1 43s
ingress-nginx-controller-674c958759-89hp8 1/1 Running 0 53s
[root@master ingress]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller NodePort 10.98.192.225 <none> 80:30045/TCP,443:32531/TCP 89s
ingress-nginx-controller-admission ClusterIP 10.110.144.179 <none> 443/TCP 89s
(3)查看Ingress-nginx-controller容器内部详情。可以看到现在已经有一个模板,用来描述Ingress资源能够收集到的信息了。
[root@master ingress]# kubectl exec -it -n ingress-nginx ingress-nginx-controller-674c958759-89hp8 bash
bash-5.0$ ls
fastcgi.conf mime.types scgi_params
fastcgi.conf.default mime.types.default scgi_params.default
fastcgi_params modsecurity template
fastcgi_params.default modules uwsgi_params
geoip nginx.conf uwsgi_params.default
koi-utf nginx.conf.default win-utf
koi-win opentracing.json
lua owasp-modsecurity-crs
bash-5.0$ cat nginx.conf
...
location / {
set $namespace "";
set $ingress_name "";
set $service_name "";
set $service_port "";
set $location_path "/";
...
(4)创建对应的ingress规则
[root@master ingress]# vim ingress.yaml
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: bdqn-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: ingress.bdqn.com
http:
paths:
- path: /nginx
backend:
serviceName: svc1
servicePort: 80
- path: /httpd
backend:
serviceName: svc2
servicePort: 80
[root@master ingress]# kubectl apply -f ingress.yaml
[root@master ingress]# kubectl get ingresses.
NAME HOSTS ADDRESS PORTS AGE
bdqn-ingress ingress.bdqn.com 80 19s
[root@master ingress]# kubectl get ingresses.
NAME HOSTS ADDRESS PORTS AGE
bdqn-ingress ingress.bdqn.com 80 19s
[root@master ingress]# kubectl describe ingresses. bdqn-ingress
Name: bdqn-ingress
Namespace: default
Address: 192.168.229.210
Default backend: default-http-backend:80 (<none>)
Rules:
Host Path Backends
---- ---- --------
ingress.bdqn.com
/nginx svc1:80 (10.244.1.21:80,10.244.1.22:80,10.244.2.22:80)
/httpd svc2:80 (10.244.1.23:80,10.244.1.24:80,10.244.2.23:80 + 1 more...)
...
[root@master ingress]# kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-kz6xn 0/1 Completed 0 14m
ingress-nginx-admission-patch-mh2qq 0/1 Completed 1 14m
ingress-nginx-controller-674c958759-89hp8 1/1 Running 0 14m
[root@master ingress]# kubectl exec -it -n ingress-nginx ingress-nginx-controller-674c958759-89hp8 bash
bash-5.0$ cat nginx.conf
...
location ~* "^/nginx" {
set $namespace "default";
set $ingress_name "bdqn-ingress";
set $service_name "svc1";
set $service_port "80";
set $location_path "/nginx";
...
location ~* "^/httpd" {
set $namespace "default";
set $ingress_name "bdqn-ingress";
set $service_name "svc2";
set $service_port "80";
set $location_path "/httpd";
...
(5)修改本机的域名解析,进行浏览器访问。
[root@master ingress]# kubectl get pod -n ingress-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ingress-nginx-admission-create-kz6xn 0/1 Completed 0 17m 10.244.1.25 node1 <none> <none>
ingress-nginx-admission-patch-mh2qq 0/1 Completed 1 17m 10.244.2.25 node2 <none> <none>
ingress-nginx-controller-674c958759-89hp8 1/1 Running 0 17m 192.168.229.210 node2 <none> <none>
zhangjiedeMacBook-Pro:~ zhangjie$ sudo vim /etc/hosts
192.168.229.210 ingress.bdqn.com
[root@master ingress]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller NodePort 10.98.192.225 <none> 80:30045/TCP,443:32531/TCP 26m
ingress-nginx-controller-admission ClusterIP 10.110.144.179 <none> 443/TCP 26m
(6)浏览器访问
http://ingress.bdqn.com/nginx:30045
http://ingress.bdqn.com/httpd:30045
7.基于http实现虚拟主机的访问
前提:ingress-nginx-controller服务已经在集群中完成部署
[root@master vhost]# kubectl get pod -n ingress-nginx
编辑ingress1.bdqn.io域名所需的Deployment和svc资源
[root@master vhost]# vim deploy-svc1.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: deploy1
spec:
replicas: 2
template:
metadata:
labels:
version: v1
spec:
containers:
- name: httpd1
image: 192.168.1.10:5000/httpd:v1
---
kind: Service
apiVersion: v1
metadata:
name: svc1
spec:
selector:
version: v1
ports:
- protocol: TCP
port: 80
targetPort: 80
[root@master vhost]# kubectl apply -f deploy-svc1.yaml
[root@master vhost]# vim deploy-svc2.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: deploy2
spec:
replicas: 2
template:
metadata:
labels:
version: v2
spec:
containers:
- name: httpd2
image: 192.168.1.10:5000/httpd:v2
---
kind: Service
apiVersion: v1
metadata:
name: svc2
spec:
selector:
version: v2
ports:
- protocol: TCP
port: 80
targetPort: 80
[root@master vhost]# kubectl apply -f deploy-svc2.yaml
访问各svc资源的ClusterIP验证服务
[root@master vhost]# kubectl get svc
[root@master vhost]# curl 10.244.1.25
[root@master vhost]# curl 10.244.2.25
创建对应的ingress规则
[root@master vhost]# vim ingress.yaml
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: ingress1
spec:
rules:
- host: ingress1.bdqn.io
http:
paths:
- path: /
backend:
serviceName: svc1
servicePort: 80
---
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: ingress2
spec:
rules:
- host: ingress2.bdqn.io
http:
paths:
- path: /
backend:
serviceName: svc2
servicePort: 80
[root@master vhost]# kubectl apply -f ingress.yaml
[root@master vhost]# kubectl describe ingresses. ingress1
[root@master vhost]# kubectl describe ingresses. ingress2
在本机上做域名解析之后,用浏览器访问验证。
8.基于https的访问
创建证书
[root@master https]# openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"
[root@master https]# ls
tls.crt tls.key
创建secret资源,将证书保存到k8s集群中。
[root@master https]# kubectl create secret tls tls-secret --key=tls.key --cert=tls.crt
创建新的deploy5.yaml
[root@master https]# vim deploy5.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: deploy5
spec:
replicas: 2
template:
metadata:
labels:
app: nginx5
spec:
containers:
- name: nginx5
image: nginx
---
kind: Service
apiVersion: v1
metadata:
name: svc5
spec:
selector:
app: nginx5
ports:
- protocol: TCP
port: 80
targetPort: 80
创建对应的ingress规则
[root@master https]# vim ingress5.yaml
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: https
spec:
tls:
- hosts:
- ingress5.bdqn.com
secretName: tls-secret
rules:
- host: ingress5.bdqn.com
http:
paths:
- path: /
backend:
serviceName: svc5
servicePort: 80
本机编写域名解析并使用浏览器访问验证。