Ingress简介
通常情况下,service和pod仅在集群内部网络中可以通过ip地址访问,集群外的网络无法访问。使用service的NodePort类型,虽然可以打开外部访问渠道,但集群内的服务过多时会导致node上的服务端口过多,不利于管理。
Ingress可以理解为K8S集群边界上的代理’nginx’,可以给Ingress配置各种基于URL、SSL、域名等实现的转发规则,使外部最终能访问到集群内部的service资源。
这样就能只使用一个端口,实现集群中的多个服务对外暴露
ingress由两个组件组成:ingress controller和ingress服务。
ingress controller的本质是一个运行负载均衡器的Pod
,主要有两种:基于nginx服务的ingress controller和基于traefik的ingress controller。
工作原理
ingress服务用于接收并存储用户定义的转发规则,并通知K8S的api-server。
ingress controller与K8S的api-server实时交互,动态感知ingress服务中转发规则的变化并读取新的转发规则,然后按负载均衡器的配置格式写入到负载均衡器中的配置文件,并reload使其新配置能够生效。
ingress用于设定转发规则,ingress controller为pod应用这些规则。ingress controller建议设置为daemonset控制器部署,这些Pod设置NodePort类型的Service
Ingress的类型
单Service Ingress
通过创建没有rules直接将后端的默认Service向集群外部暴露。
默认Service的定义字段spec.backend
,举例如下
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
spec:
backend:
serviceName: testsvc
servicePort: 80
基于URL路径进行流量转发
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
spec:
rules: ##列表rules是一个列表,保存多条转发规则
- http: ##定义一条转发规则
paths:
- path: /test ##针对此url进行转发至后端服务,后端服务上需要有此path,否则需要rewrite处理。下面会再举例
backend: ##定义后端服务
serviceName: test ##后端提供服务的service的name
servicePort: 80 ##后端提供服务的service的port
后端服务没有对应的路径test
先做rewrite处理
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
annotations: #注解信息
nginx.ingress.kubernetes.io/configuration-snippet: |
rewrite /test /hostname.html break;
spec:
rules: ##列表rules是一个列表,保存多条转发规则
- http: ##定义一条转发规则
paths:
- path:
backend: ##定义后端服务
serviceName: test ##后端提供服务的service的name
servicePort: 80 ##后端提供服务的service的port
基于主机名称的虚拟主机
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
rules: ##列表rules是一个列表,保存多条转发规则
- host: myapp.magedu.com
http: ##定义一条转发规则
paths:
- path:
backend: ##定义后端服务
serviceName: test ##后端提供服务的service的name
servicePort: 80 ##后端提供服务的service的port
部署Ingress controller
架构如图
部署后端服务
提供后端服务的Pod、保证后端服务访问入口稳定的是service;所以需要同时新建pod和service。注意后端服务无需使用ingress-nginx的名称空间
,定义清单如下
apiVersion: v1
kind: Service
metadata:
name: ngx-service
spec:
selector:
app: ngx
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: deployment
metadata:
name: ngx-deployment
labels:
app: ngx
spec:
replicas: 2
selector:
matchLabels:
app: ngx
template:
metadata:
labels:
app: ngx
spec:
containers:
- name: ngxv2
image: 192.168.80.146:5000/my_ngx:v2
查看创建后的结果并先验证
[root@k8s-master ingress-nginx]# kubectl get pod
NAME READY STATUS RESTARTS AGE
ngx-deployment-58d847f49c-9tbwh 1/1 Running 0 1d
ngx-deployment-58d847f49c-vvnrj 1/1 Running 0 1d
[root@k8s-master ingress-nginx]# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 9d
ngx-service ClusterIP 10.106.74.134 <none> 80/TCP 1d
部署ingress controller
部署ingress controller的service
通过ingress-controller对外提供服务,现在还需要手动给ingress-controller建立一个NodePort类型的service
,接收集群外部流量。配置清单如下
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
nodePort: 30081
- name: https
port: 443
targetPort: 443
protocol: TCP
nodePort: 30443
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
查看创建后的结果并先验证
[root@k8s-master ingress-nginx]# kubectl get -n ingress-nginx services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.102.208.10 <none> 80:30081/TCP,443:30443/TCP 2h
部署ingress
即配置ingress controller的转发规则
apiVersion: extensions/v1beta1 #api版本
kind: Ingress #清单类型
metadata: #元数据
name: ingress-myapp #ingress的名称
namespace: default #所属名称空间
annotations: #注解信息
nginx.ingress.kubernetes.io/configuration-snippet: |
rewrite /test /hostname.html break;
kubernetes.io/ingress.class: "nginx"
spec: #规格
rules: #定义后端转发的规则
- host: myapp.magedu.com
http:
paths:
- path: #配置访问路径,如果通过url进行转发,需要修改;空默认为访问的路径为"/"
backend: #配置后端服务
serviceName: ngx-service
servicePort: 80
查看创建后的结果并先验证
[root@k8s-master ingress-nginx]# kubectl get -n ingress-nginx pods
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-5c54df76f6-qktts 1/1 Running 0 2h
##进入ingress controller的Pod内部查看nginx配置文件
[root@k8s-master ingress-nginx]# kubectl exec -n ingress-nginx -it nginx-ingress-controller-5c54df76f6-qktts /bin/bash
www-data@nginx-ingress-controller-5c54df76f6-qktts:/etc/nginx$ cat nginx.conf
.....
## start server myapp.magedu.com
server {
server_name myapp.magedu.com ;
listen 80;
set $proxy_upstream_name "-";
location / {
set $namespace "default";
set $ingress_name "ingress-myapp";
set $service_name "myapp";
set $service_port "80";
set $location_path "/";
.....
使用tls
为转发规则配置使用https,可在spec.tls中指定hosts和使用的secretName;
先创建secretName用于存放证书
kubectl create secret tls tls-myapp --key tls.key --cert tls.crt
tls:
- hosts:
- myapp.magedu.com
secretName: tls-myapp
总结
集群外的集群发起访问进行验证,先修改本地的hosts文件
[root@192-168-80-114 ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.80.147 k8s-node2 myapp.magedu.com
192.168.80.140 k8s-node1 myapp.magedu.com
[root@192-168-80-114 ~]# curl myapp.magedu.com:30081
ngx-deployment-58d847f49c-vvnrj
[root@192-168-80-114 ~]# curl myapp.magedu.com:30081
ngx-deployment-58d847f49c-9tbwh