ingress官方:https://kubernetes.github.io/ingress-nginx/deploy/
Kubernetes 暴露服务的方式目前只有三种:LoadBlancer Service、NodePort Service、Ingress
ini
要理解ingress,需要区分两个概念,ingress和ingress-controller:
ingress对象:
指的是k8s中的一个api对象,一般用yaml配置。作用是定义请求如何转发到service的规则,可以理解为配置模板。
ingress-controller:
具体实现反向代理及负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发。
简单来说,ingress-controller才是负责具体转发的组件,通过各种方式将它暴露在集群入口,外部对集群的请求流量会先到ingress-controller,而ingress对象是用来告诉ingress-controller该如何转发请求,比如哪些域名哪些path要转发到哪些服务等等。
ini
service 的表现形式为IP:PORT,即工作在第四层传输层(TCP/IP层),对于不同的URL地址经常对应用不同的后端服务或者虚拟服务器,这些应用层的转发机制仅通过kubernetes的service机制是无法实现的,这种情况我么可以使用ingress策略定义和一个具体的ingress Controller.
Ingress提供七层负载均衡能力,可以通过 Ingress 配置提供外部可访问的 URL、负载均衡、SSL、基于名称的虚拟主机等。作为集群流量接入层,Ingress 的高可靠性显得尤为重要。
-
这个负载均衡是基于nginx七层反向代理来实现的,ingress工作原理如下图:
-
外部客户端通过访问负载均衡器,然后调度到service上,然后在调度到IngressController,IngressController通过Ingress规则(域名或虚拟主机)访问到后端pod,而在Ingress规则当中对应的主机是由service分组来设定的,可以看到,这幅图有2种service,最上面的service是用来对外提供服务的,而下面2个service仅仅是用来分pod组的
ini
Kubernetes 并没有自带 Ingress Controller,实际上ingress-controller只是一个统称,具体实现有多种,需要自己单独安装,目前,由k8s维护的ingress-controller只有google云的GCE与ingress-nginx两个,常用的是 Ingress-nginx Controller.
ini
Ingress 一般由三个组件组成:
1. Nginx 反向代理负载均衡器
2. Ingress Controller 可以理解为控制器,它通过不断的跟 Kubernetes API 交互,实时获取后端 Service、Pod 等的变化,比如新增、删除等,然后结合 Ingress 定义的规则生成配置,然后动态更新上边的 Nginx 负载均衡器,并刷新使配置生效,来达到服务自动发现的作用。
3. Ingress 则是定义规则,通过它定义某个域名的请求过来之后转发到集群中指定的 Service。它可以通过 Yaml 文件定义,可以给一个或多个 Service 定义一个或多个 Ingress 规则。
如何创建 Ingress 资源
- Ingress 中的spec字段是Ingress资源的核心组成部分,主要包含以下3个字段:
- rules:用于定义当前Ingress资源的转发规则列表;由rules定义规则,或没有匹配到规则时,所有的流量会转发到由backend定义的默认后端。
- backend:默认的后端;是Service 和端口名称的组合。定义Ingress资源时,必须要定义backend或rules两者之一,该字段用于让负载均衡器指定一个全局默认的后端。
- tls:TLS配置,目前仅支持通过默认端口443提供服务,如果要配置指定的列表成员指向不同的主机,则需要通过SNI TLS扩展机制来支持该功能。
部署 Ingress 控制器
-
下载 ingress controller
-
ini
如果下载不下来,记得本机解析github地址 [root@master ~]# cat /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.116.138 master 192.168.116.130 node1 192.168.116.131 node2 199.232.28.133 raw.githubusercontent.com
-
Ingress-Nginx GitHub地址
inihttps://github.com/kubernetes/ingress-nginx
ini
[root@master mnt]# wget https://github.com/kubernetes/ingress-nginx/archive/refs/tags/controller-v1.3.0.zip #下载压缩包
[root@master mnt]# unzip ingress-nginx-controller-v1.3.0.zip
[root@master mnt]# cd ingress-nginx-controller-v1.3.0/deploy/static/provider/cloud/
[root@master cloud]# vim deploy.yaml
1、下载ingress controller
ini
[root@k8s-master ~]# cd /mnt/
[root@k8s-master mnt]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.3.0/deploy/static/provider/cloud/deploy.yaml
[root@k8s-master mnt]# cp deploy.yaml /root/
[root@k8s-master mnt]# cd
[root@k8s-master ~]# vim deploy.yaml #修改配置文件,并替换成阿里云的镜像
找到已下apiserver的版本:
---
apiVersion: apps/v1
kind: DaemonSet #将原来的Deployment修改为DaemonSet
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.3.0
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
minReadySeconds: 0
revisionHistoryLimit: 10
selector:
matchLabels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
template:
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
spec:
hostNetwork: true #添加共享到主机网络
containers:
- args:
- /nginx-ingress-controller
- --publish-service=$(POD_NAMESPACE)/ingress-nginx-controller
- --election-id=ingress-controller-leader
- --controller-class=k8s.io/ingress-nginx
- --ingress-class=nginx
- --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
- --validating-webhook=:8443
- --validating-webhook-certificate=/usr/local/certificates/cert
- --validating-webhook-key=/usr/local/certificates/key
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: LD_PRELOAD
value: /usr/local/lib/libmimalloc.so
image: registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.3.0@sha256:d1707ca76d3b044ab8a28277a2466a02100ee9f58a86af1535a3edf9323ea1b5 #将原来的镜像替换成阿里云仓库的镜像
imagePullPolicy: IfNotPresent
lifecycle:
preStop:
exec:
command:
- /wait-shutdown
livenessProbe:
failureThreshold: 5
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
name: controller
ports:
- containerPort: 80
name: http
protocol: TCP
- containerPort: 443
name: https
protocol: TCP
- containerPort: 8443
name: webhook
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
resources:
requests:
cpu: 100m
memory: 90Mi
securityContext:
allowPrivilegeEscalation: true
capabilities:
add:
- NET_BIND_SERVICE
drop:
- ALL
runAsUser: 101
volumeMounts:
- mountPath: /usr/local/certificates/
name: webhook-cert
readOnly: true
dnsPolicy: ClusterFirst
nodeSelector:
custom/ingress-controller-ready: "true" #指定运行ingress的node标签
serviceAccountName: ingress-nginx
terminationGracePeriodSeconds: 300
volumes:
- name: webhook-cert
secret:
secretName: ingress-nginx-admission
---
#注意:一共有两个镜像需要替换成阿里云仓库的镜像:
[root@master ~]# cat deploy.yaml | grep image
image: registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.3.0@sha256:d1707ca76d3b044ab8a28277a2466a02100ee9f58a86af1535a3edf9323ea1b5
imagePullPolicy: IfNotPresent
image: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.1.1@sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660
imagePullPolicy: IfNotPresent
image: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.1.1@sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660
imagePullPolicy: IfNotPresent
需要修改的地方:
kind: DaemonSet:
官方原始文件使用的是deployment,replicate 为 1,这样将会在某一台节点上启动对应的nginx-ingress-controller pod。外部流量访问至该节点,由该节点负载分担至内部的service。测试环境考虑防止单点故障,改为DaemonSet然后删掉replicate ,配合亲和性部署在制定节点上启动nginx-ingress-controller pod,确保有多个节点启动nginx-ingress-controller pod,后续将这些节点加入到外部硬件负载均衡组实现高可用性。
hostNetwork: true:
添加该字段,暴露nginx-ingress-controller pod的服务端口(80)
nodeSelector:
增加亲和性部署,有custom/ingress-controller-ready 标签的节点才会部署该DaemonSet
为需要部署nginx-ingress-controller的节点设置lable
给两个node节点设置lable
ini
[root@k8s-master ~]# kubectl label nodes k8s-node1 custom/ingress-controller-ready=true
[root@k8s-master ~]# kubectl label nodes k8s-node2 custom/ingress-controller-ready=true
同时在两个node节点下载镜像
[root@k8s-node1 ~]# docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.3.0
[root@k8s-node1 ~]# docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.1.1
创建ingress-controller
ini
[root@k8s-master ~]# kubectl apply -f deploy.yaml
查看ingress-controller资源
[root@k8s-master ~]# kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-s8vnl 1/1 Running 0 98m
nginx-ingress-controller-ztxz4 1/1 Running 0 97m
测试ingress
创建两个应用和service
ini
[root@k8s-master ~]# vim my-apache.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-apache
spec:
selector:
matchLabels:
run: my-apache
replicas: 2
template:
metadata:
labels:
run: my-apache
spec:
containers:
- name: my-apache
image: daocloud.io/library/httpd:2.4
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: my-apache
labels:
run: my-apache
spec:
#type: NodePort
ports:
- port: 80
targetPort: 80
#nodePort: 30002
selector:
run: my-apache
[root@k8s-master ~]# cat my-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: daocloud.io/library/nginx:1.7.9
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
#type: NodePort
ports:
- port: 80
targetPort: 80
#nodePort: 30001
selector:
run: my-nginx
创建pod和service
[root@k8s-master ~]# kubectl apply -f my-apache.yaml
[root@k8s-master ~]# kubectl apply -f my-nginx.yaml
查看资源
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
my-apache-d49c8b95c-8z8l9 1/1 Running 0 125m
my-apache-d49c8b95c-d9q5s 1/1 Running 0 125m
my-nginx-5fdc96f9b4-bmf6s 1/1 Running 0 124m
my-nginx-5fdc96f9b4-qfw8c 1/1 Running 0 124m
[root@k8s-master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 20d
my-apache NodePort 10.99.178.186 <none> 80/TCP 125m
my-nginx NodePort 10.97.171.188 <none> 80/TCP 124m
配置ingress转发文件
ini
查看annotations注解
https://github.com/kubernetes/ingress-nginx/blob/main/docs/examples/rewrite/README.md
ini
[root@k8s-master ~]# cat ingress-test.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
namespace: default
annotations: #可选字段,如果需要重定向那就添加该字段
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx #指定ingress的类型
rules: #定义转发规则
- host: test.apache.ingress #指定域名方式
http:
paths:
- path: / #指定访问的路径
pathType: Prefix #定义路径的类型
backend: #定义转发后端的服务
service: #定义转发的service
name: my-apache
port:
number: 80
- host: test.nginx.ingress
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-nginx
port:
number: 80
[root@k8s-master ~]# kubectl apply -f ingress-test.yaml
[root@k8s-master ~]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
test-ingress <none> test.apache.ingress,test.nginx.ingress 80 119m
nginx-ingress-controller运行在node1,node2两个节点上。
如果网络中有dns服务器,在dns中把这两个域名映射到nginx-ingress-controller运行的任意一个节点上,如果没有dns服务器只能修改host文件了。
任意一个节点上操作:(客户端解析)
我这里有两个节点部署了控制器,ip分别为172.16.229.5,172.16.229.6 ,如果有多个,可以随便选。
在wind电脑设置本地解析
ini
172.16.229.5 test.nginx.ingress
172.16.229.6 test.apache.ingress