Ingress控制器

Ingress控制器:

工作在7层的负载均衡器,支持http、https、负载均衡、域名。作用与service一样,但是实现效果有区别
功能基于软件实现

工作原理:

image-20220808173442905

客户端请求时,到达ingress-nginx的pod,再调度到ingress控制器,ingress控制器再根据ingress的定义工作模式,访问service,由svc把请求转给pod
ingress-nginx的pod可以按需要选择运行方式

ingress控制器选择

通过ingress类,可在集群中部署任意数量ingress控制器

  • nginx
  • traefik
  • envoy

工作模式:

以nginx为例

  • 虚拟主机方式
  • location的url方式

运行方式:

  • daemonset运行
  • service代理运行
  • 直接绑定物理机端口允许

安装ingress插件:

下载地址: https://codeload.github.com/kubernetes/ingress-nginx/
k8s版本支持记录: https://github.com/kubernetes/ingress-nginx
安装文档: https://kubernetes.github.io/ingress-nginx/deploy/

云平台使用loadbalance暴露控制器端口,裸机使用nodeport暴露端口

可能需要的配置,所有node节点都需要配置

由于直接使用的谷歌的镜像,需要配代理下载镜像,解决方法有:
1、去docker的hub上面去找替代的镜像
2、给containerd加代理
3、本地docker下载需要的镜像并导出,在node节点安装ctd的官方工具nerdctl(兼容docker指令),导入镜像文件

第一种

下载完镜像后,在配置文件中将用到镜像的地方改成这2个即可

docker pull bitnami/nginx-ingress-controller:1.8.1
docker pull jettech/kube-webhook-certgen:v1.5.2

第二种

参考docker实现:https://docs.docker.com/config/daemon/systemd/#httphttps-proxy
containerd:

#配置代理,需要win系统已经运行了代理且开启端口转发,我本地ssr已运行,所有代理地址是:winIP:转发端口
cat > /etc/sysconfig/containerd <<eof
HTTP_PROXY=http://192.168.0.101:1080
HTTPS_PROXY=http://192.168.0.101:1080
#这里是配置不通过代理访问的网络或域名,一定要加上当前集群网络也就是svc网段、pod网段,不然镜像能下载,但下载后回复master的数据就回不来了
NO_PROXY='127.0.0.1,2.2.2.0/24,1.1.1.0/24,192.168.0.0/16,10.20.0.0/16,10.10.0.0/16'
eof

sed -i '/Service/aEnvironmentFile=-/etc/sysconfig/containerd'  `systemctl cat containerd |awk 'NR==1{print $2}'`
systemctl daemon-reload 
systemctl restart containerd.service 
systemctl show --property=EnvironmentFiles containerd

#删除配置
sed -i '/EnvironmentFile/d' /etc/systemd/system/containerd.service
systemctl daemon-reload 
systemctl restart containerd.service

docker:

#docker的代理配置与上面containerd的类似,只用改名字即可,如果是docker 23.0支持 daemon.json中配置
vim /etc/docker/daemon.json
{
   "proxies": {
    "http-proxy": "http://192.168.0.101:1080",
    "https-proxy": "http://192.168.0.101:1080",
    "no-proxy": "127.0.0.1,2.2.2.0/24,1.1.1.0/24,192.168.0.0/16"
  }
}

第三种

#在node节点下载工具,导入镜像,怎么下载镜像上传就不演示了
wget https://github.com/containerd/nerdctl/releases/download/v1.4.0/nerdctl-1.4.0-linux-amd64.tar.gz
tar xf nerdctl-1.4.0-linux-amd64.tar.gz -C /bin/

#加命令重命名,按个人意愿
echo "alias docker='nerdctl'" > /etc/profile.d/nerdctl-alias.sh
. /etc/profile

nerdctl load < 镜像1.tar
nerdctl load < 镜像2.tar

安装方法1:

wget -e 'HTTPS_PROXY=http://192.168.0.101:1080' https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/baremetal/deploy.yaml -O 0-ingress-ngx.yml

#修改配置,单独创建ingress控制器和svc端口暴露
sed -n '/apps\/v1/,/secretName: ingress-nginx-admission/p' 0-ingress-ngx.yml > 1-ingress-dep.yml
sed -i -e '/apps\/v1/,/secretName: ingress-nginx-admission/d' \
-e '/targetPort: http$/a\    nodePort: 30080' \
-e '/targetPort: https$/a\    nodePort: 30443' \
0-ingress-ngx.yml
kubectl apply -f 0-ingress-ngx.yml

#等待这个job创建出secret后再创建pod
kubectl logs -n ingress-nginx pods/ingress-nginx-admission-create-
#等一会后再创建
kubectl apply -f 1-ingress-dep.yml
kubectl get pods -n ingress-nginx

image-20230701171558285

image-20230701172129291

安装方法2:

wget -e 'HTTPS_PROXY=http://192.168.0.101:1080' https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/baremetal/deploy.yaml -O ingress-ngx.yml

sed -i -e '/targetPort: http$/a\    nodePort: 30080' \
-e '/targetPort: https$/a\    nodePort: 30443' \
ingress-ngx.yml
kubectl apply -f ingress-ngx.yml

#让ingress控制器的pod等待一段时间再启动
kubectl wait --namespace ingress-nginx \
  --for=condition=ready pod \
  --selector=app.kubernetes.io/component=controller \
  --timeout=180s

测试使用:

kubectl create deployment demo --image=httpd --port=80
kubectl expose deployment demo

kubectl port-forward -n ingress-nginx service/ingress-nginx-controller 8080:80

#curl高级用法,直接指定解析ip地址,不用在hosts添加记录
#用法:--resolve 请求域名:请求端口:解析ip 域名
curl --resolve demo.localdev.me:8080:127.0.0.1 http://demo.localdev.me:8080
Kubectl delete deploy demo
kubectl delete svc demo

image-20230701172501210

配置语法:

kubectl explain ing

apiVersion: networking.k8s.io/v1
kind: Igress
metadata:
	annotations:		#不同ingress支持不同的注解,当前ngx的注解官方文档:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/
		kubernetes.io/ingress.class: "nginx"		#指定ingress控制器的类型,在注解指定的时候优先级高于spec.ingressClassName处指定。1.22版本之前有效,新版本不能用
		nginx.ingress.kubernetes.io/rewrite-target: /$1 		#重定向URI,v0.22.0后的版本不兼容以前的版本,用法和nginx的正则重写一样,用$1等位置变量
		nginx.ingress.kubernetes.io/ssl-redirect: 布尔值	#是否只能通过SSL访问(当 Ingress 包含证书时默认为 True)
		nginx.ingress.kubernetes.io/force-ssl-redirect: 布尔值		#未启用 TLS,也强制重定向到 HTTPS
		nginx.ingress.kubernetes.io/app-root: str			#控制器必须重定向的应用程序根(如果它位于 / 上下文中)
		nginx.ingress.kubernetes.io/use-regex: 布尔值		#是否使用正则表达式
		nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"	#代理连接超时
		nginx.ingress.kubernetes.io/proxy-send-timeout: "600"		#向后端发送请求数据的超时时间
		nginx.ingress.kubernetes.io/proxy-read-timeout: "600"		#读取后端数据时的超时时间
		nginx.ingress.kubernetes.io/proxy-body-size: "50m"			#客户端上传文件大小限制,默认还是原来的20m
		nginx.ingress.kubernetes.io/app-root: /index.html			#配置index文件
spec:
	defaultBackend <Object>		#未定义规则时,交给默认后端
		resource <Object>
		service <Object>		#定义访问的后端service
			name <str>			#svc名称
			port <Object>		#端口
				name
				number
	ingressClassName: "nignx"		#代替旧的的注解kubernetes.io/ingress.class,但注解和此字段同时存在,注解覆盖此。当使用IngressClass来管理ingrees时,在配置
	rules <Object>		#定义规则,工作模式
	- host: 域名			#主机名方式
		#*.hj.com,可用通配符匹配,但:www.test.hj.com、hj.com这种不会匹配到,因为只匹配当前dns域,4级子域和2级域不在内
	  http			#url路径方式
	  	paths <Object>	
		- path <str>		#location的url
		  pathType:匹配规则	#location匹配规则
			#ImplementationSpecific ,混合下面两种
			#Prefix,模糊匹配,区分大小写
			#Exact,精准匹配,区分大小写
	  	  backend <Object>		#定义ngx的upstream
			service <Object>
				name		#代理pod的svc名称
				port:
					name
					number: 端口
			resource <Object>		#资源和后端只能取一
				apiGroup
				kind
				name
	tls <Object>
		hosts					#tls的虚拟主机
		secretName		#证书名称

pathType字段3种类型的匹配

image-20230701135708488

例1: ing+svc+nginx POD

1)先创建svc与后端nginx
apiVersion: v1
kind: Service
metadata:
  name: ngx-svc
spec:
  selector:
    app: ngx
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ngx-dep
spec:
  selector:
    matchLabels:
      app: ngx
  template:
    metadata:
      labels:
        app: ngx
    spec:
      containers:
      - name: ngx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
2)再创建ingress访问入口

可以直接访问主机名,不用在nginx内部配置域名
可多个域名,第二个就不演示了

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
    name: ngx-ing
    annotations:
      nginx.ingress.kubernetes.io/use-regex: "true"
      nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
      nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
      nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
      nginx.ingress.kubernetes.io/proxy-body-size: "50m"
      nginx.ingress.kubernetes.io/app-root: /index.html
spec:
  ingressClassName: nginx
  rules:
  - host: www.hj.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: ngx-svc
            port:
              number: 80
3)配置外部nginx(作为负载均衡器)

由于没有负载均衡器,只能用ngx模拟,将请求域名的的流量转给ingress

yum install -y nginx

cat > /etc/nginx/nginx.conf <<eof
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
    worker_connections 1024;
}
http {
    log_format  main  '\$remote_addr - \$remote_user [\$time_local] "\$request" '
                      '\$status \$body_bytes_sent "\$http_referer" '
                      '"\$http_user_agent" "\$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;
    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;
    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;
    include /etc/nginx/conf.d/*.conf;
}
stream {
  upstream k8s {
    server 2.2.2.15:30080;
    server 2.2.2.25:30080;
    server 2.2.2.35:30080;
    server 2.2.2.45:30080;
  }
  server {
    listen 80;
    proxy_pass k8s;    	 	#仅tcp层面将访问80端口的请求都转给k8s入口控制器处理,由它控制器处理http协议 
  }
}
eof

systemctl start nginx
4)验证状态

检车rules是否匹配到域名

kubectl describe ing ingress-ngx
curl -L --resolve www.hj.com:80:127.0.0.1 www.hj.com

image-20230701195725201

image-20230701195409523

例2: ing绑定多域名、基于url转发

1)创建ing,可基于案例1清单文件做
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
    name: ngx-ing
    annotations:
      nginx.ingress.kubernetes.io/use-regex: "true"
      nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
      nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
      nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
      nginx.ingress.kubernetes.io/proxy-body-size: "50m"
      nginx.ingress.kubernetes.io/app-root: /index.html
spec:
  ingressClassName: nginx
  rules:
  - host: www.hj.com
    http:
      paths:
      - path: /app1
        pathType: Prefix
        backend:
          service:
            name: ngx-svc
            port:
              number: 80
      - path: /app2
        pathType: Prefix
        backend:
          service:
            name: ngx-svc
            port:
              number: 80
  - host: admin.hj.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: ngx-svc-2
            port:
              number: 80

3)测试访问

curl --resolve www.hj.com:80:127.0.0.1 www.hj.com/app1
curl --resolve admin.hj.com:80:127.0.0.1 admin.hj.com

image-20230708201403795

例3: 在ingress加上https

1)继续使用之前的tomat POD和svc
2)为tomcat创建证书,并基于kubectl自动导入
#查看绑定的nginx虚拟主机
kubectl describe ingress ingress-tomcat

#创建证书
mkdir ca ;cd ca
openssl genrsa -out tls.key 2048
openssl req -new -x509 -key tls.key -out tls.crt -subj /C=CN/ST=WH/L=WH/O=dev/CN=*.hj.com

#自动导入,配置证书
kubectl create secret tls www.hj.com-cert --cert=tls.crt --key=tls.key
kubectl get secrets
3)创建新的ingress配置
apiVersion: v1
kind: Service
metadata:
  name: ngx-svc
spec:
  selector:
    app: ngx
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ngx-dep
spec:
  selector:
    matchLabels:
      app: ngx
  template:
    metadata:
      labels:
        app: ngx
    spec:
      containers:
      - name: ngx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
    name: ngx-ing
    annotations:
      nginx.ingress.kubernetes.io/use-regex: "true"
      nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
      nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
      nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
      nginx.ingress.kubernetes.io/proxy-body-size: "50m"
      nginx.ingress.kubernetes.io/app-root: /index.html
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - www.hj.com
    secretName: www.hj.com-cert 
  rules:
  - host: www.hj.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: ngx-svc
            port:
              number: 80
4)访问
curl -Lk --resolve https://www.hj.com:30443:127.0.0.1 https://www.hj.com:30443

image-20230708205657262

posted @ 2022-09-02 15:30  suyanhj  阅读(280)  评论(0)    收藏  举报