k8s ingress基础

一、ingress 简介

在k8s集群中,service和pod的ip为内网ip,仅集群内部才可以访问。如果外部应用想要直接访问集群内的服务,就需要把外部请求通过负载均衡转发到service上,然后再由kube-proxy组件将其转发给后端pod。一般service可以通过NodePort和LoadBalancer两种方式对外提供访问,但是这两种方式都有以下缺点

  • NodePort:将service暴露在节点网络上,NodePort背后就是Kube-Proxy,Kube-Proxy是沟通service网络、Pod网络和节点网络的桥梁。
    小集群使用还行,当集群规模较大时,NodePort的端口管理就是个灾难。因为每个端口只能是一种服务,端口范围只能是 30000-32767。

  • LoadBalancer:通过设置LoadBalancer映射到云服务商提供的LoadBalancer地址。这种用法仅用于在公有云服务提供商的云平台上设置 Service 的场景。受限于云平台,且通常在云平台部署LoadBalancer还需要额外的费用。在service提交后,Kubernetes就会调用CloudProvider在公有云上为你创建一个负载均衡服务,并且把被代理的Pod的IP地址配置给负载均衡服务做后端。

基于这种现状,kubernetes提供了Ingress资源对象,Ingress只需要一个NodePort或者一个LB就可以满足暴露多个Service的需求。

什么是ingress

Ingress 是对集群中服务的外部访问进行管理的 API 对象,通过yaml文件来配置,定义请求如何转发到service的规则。ingress通过http或https暴露集群内部service,给service提供外部URL、负载均衡、SSL/TLS能力以及基于域名的反向代理。Ingress相当于一个7层的负载均衡器,它的工作原理类似于Nginx,当在Ingress中建立映射规则,Ingress Controller通过监听这些配置规则并转化成Nginx的反向代理配置 , 然后对外部提供服务。ingress要依靠 ingress-controller 来具体实现以上功能。

ingress组成

  • ingress
通过yaml文件定义的规则集合,一个api对象。
  • 反向负载均衡器
反向代理负载均衡器就是 nginx、apache等中间件,新版k8s已经将Nginx与Ingress Controller合并为一个组件,所以Nginx无需单独部署,只需要部署Ingress Controller即可。在集群中反向代理负载均衡器可以自由部署,可以使用Replication Controller、Deployment、DaemonSet等等方式。常用的负载均衡器有以下几种

1:Kubernetes Ingress作为"官方"控制器,它是由社区基于NGINX Web服务器开发的,并补充了一组用于实现额外功能的Lua插件。
2:NGINX Ingress 这是NGINX开发人员的官方产品,NGINX控制器具有很高的稳定性,持续的向后兼容性,没有任何第三方模块,并且由于消除了Lua代码而保证了较高的速度(与官方控制器相比)
3:Kong Ingress 由Kong Inc开发,并且有两个版本:商业版本和免费版本。Kong Ingress建立在NGINX之上,并增加了扩展其功能的Lua模块。
4:HAProxy Ingress 由HAProxy开发,它提供了“软”配置更新(无流量丢失),基于DNS的服务发现,通过API的动态配置。
5:Traefik 是一个全功能的 ingress 控制器 (Let’s Encrypt,secrets,http2,websocket),并且它也有来自 Containous 的商业支持。
6:Istio 是IBM,Google和Lyft(Envoy的原始作者)的联合项目,它是一个全面的服务网格解决方案。它不仅可以管理所有传入的外部流量(作为Ingress控制器),还可以控制集群内部的所有流量。
  • Ingress Controller
监听apiserver,获取服务新增,删除等变化,并结合ingress规则动态更新到反向代理负载均衡器上,并重载配置使其生效。 
使用watch机制: Service始终watch着后端pod变化。只要pod发生变化,api-server立刻检测到 

实现原理

1:ingress controller通过和kubernetes api交互,动态的去感知集群中ingress规则变化。
2:读取ingress自定义的规则,规则就是写明了那个域名对应哪个service,生成一段nginx配置。
3;写入nginx-ingress-controller的pod里,这个Ingress controller的pod里运行着一个Nginx服务,控制器会把生成的nginx配置写入/etc/nginx/nginx.conf文件中的upstream里面
4:重新加载配置,nginx -s reload一下使配置生效,以此达到分配和动态更新问题。

以nginx为例,流程图如下:
k8s ingress基础_第1张图片
k8s ingress基础_第2张图片
架构图如下:
k8s ingress基础_第3张图片

以上图片来源https://cloud.tencent.com/developer/article/1718482

二、ingress部署

  • 下载ingress yaml文件
通过wget下载需要用到的ingress文件,此次部署用的是1.9.0版本。
[root@node1 ~]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.9.0/deploy/static/provider/baremetal/deploy.yaml
  • 修改yaml配置
目前国外的镜像源已经不可用,需要修改镜像的源地址,如下:
1:修改ingress-controller的镜像源地址
    - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: LD_PRELOAD
          value: /usr/local/lib/libmimalloc.so
        image: registry.aliyuncs.com/google_containers/nginx-ingress-controller:v1.9.0   ###此处修改为阿里的源 
        imagePullPolicy: IfNotPresent


#############################
2:修改webhook-certgen的镜像源地址(有两处需要修改)
        env:
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        image: registry.aliyuncs.com/google_containers/kube-webhook-certgen:v20230407    #####修改镜像源地址                                                                       
        imagePullPolicy: IfNotPresent



3:修改ingress-controller的网络模式
    spec:               
      hostNetwork: true    #####添加此处配置,修改为主机模式
      containers:       
      - args:           
        - /nginx-ingress-controller
        - --election-id=ingress-nginx-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

  • 启动ingress
[root@node1 ingress]# kubectl apply  -f  deploy.yaml 
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
serviceaccount/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
configmap/ingress-nginx-controller created
service/ingress-nginx-controller created
service/ingress-nginx-controller-admission created
deployment.apps/ingress-nginx-controller created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
[root@node1 ingress]# kubectl get po  -n ingress-nginx 
NAME                                        READY   STATUS              RESTARTS   AGE
ingress-nginx-admission-create-hk2sx        0/1     ContainerCreating   0          3s
ingress-nginx-admission-patch-h6f5d         0/1     ContainerCreating   0          3s
ingress-nginx-controller-548689bbd7-8lzrj   0/1     ContainerCreating   0          3s



[root@node1 ~]# kubectl get po  -n ingress-nginx  -o wide
NAME                                        READY   STATUS      RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
ingress-nginx-admission-create-hk2sx        0/1     Completed   0          43h   172.16.44.4    node2              
ingress-nginx-admission-patch-h6f5d         0/1     Completed   0          43h   172.16.28.8    node3              
ingress-nginx-controller-6c88c85c98-v8mgs   1/1     Running     0          30h   192.168.5.79   node1              
[root@node1 ~]# 
###########以上可以看到ingress-controller的ip使用的是主机的ip。

三、测试http方式

  • 启动nginx和tomcat
1:编写yaml如下:
[root@node1 yaml]# cat  nginx-tomcat.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: docker.io/library/nginx:latest
        imagePullPolicy: IfNotPresent
        ports:
          - containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  selector:
    app: nginx
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  type: ClusterIP

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat
  labels:
    app: tomcat
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tomcat
  template:
    metadata:
      labels:
        app: tomcat
    spec:
      containers:
      - name: tomcat
        image: docker.io/library/tomcat:8.0-alpine   ###测试了好几个镜像,就这个能显示tom 猫
        imagePullPolicy: IfNotPresent
        ports:
          - containerPort: 8080

---            
apiVersion: v1 
kind: Service  
metadata:      
  name: tomcat-svc
spec:          
  selector:    
    app: tomcat 
  ports:       
  - port: 8080
    protocol: TCP
    targetPort: 8080
  type: ClusterIP

[root@node1 yaml]# 

#################################################
2;启动nginx 和tomcat
[root@node1 yaml]# kubectl get po -o wide 
NAME                                      READY   STATUS    RESTARTS        AGE    IP             NODE    NOMINATED NODE   READINESS GATES
nginx-5977dc5756-glczk                    1/1     Running   0               30h    172.16.44.6    node2              
tomcat-656df44d6c-6znd9                   1/1     Running   0               29h    172.16.28.13   node3              
[root@node1 yaml]# kubectl get  svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
nginx-svc    ClusterIP   10.233.43.219           80/TCP     30h
tomcat-svc   ClusterIP   10.233.52.85            8080/TCP   30h


####################################################
3:测试nginx服务没问题
[root@node1 yaml]# curl 10.233.43.219



Welcome to nginx!



Welcome to nginx!

If you see this page, the nginx web server is successfully installed and working. Further configuration is required.

For online documentation and support please refer to nginx.org.
Commercial support is available at nginx.com.

Thank you for using nginx.

[root@node1 yaml]# ################################### 4:测试tomcat 服务 [root@node1 yaml]# curl 10.233.52.85:8080 Apache Tomcat/8.0.53
  • 创建ingress 规则
1:编写ingress yaml
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-test
spec:
  ingressClassName: nginx    ########使用的实际负载均衡器类型
  rules:
  - host: "test.nginx.com"    #########nginx的域名
    http:
      paths:
      - path: "/"
        pathType: Prefix
        backend:
          service:
            name: nginx-svc   ###nginx的svc name
            port:
              number: 80
  - host: "test.tomcat.com"   ######tomcat的域名
    http:
      paths:
      - path: "/"
        pathType: Prefix
        backend:
          service:
            name: tomcat-svc  ###tomcat的svc name
            port:
              number: 8080

###############################################
2:apply创建规则
[root@node1 yaml]# kubectl apply -f ingress.yaml
[root@node1 ~]# 
[root@node1 ~]# kubectl get ingress
NAME           CLASS   HOSTS                            ADDRESS        PORTS   AGE
ingress-test   nginx   test.nginx.com,test.tomcat.com   192.168.5.79   80      29h


可以看到address为ingress-controller pod所在节点的物理地址,port为80


##################################################
3:进入ingress-controller pod里面,查看更新的规则
[root@node1 ~]# kubectl exec -it ingress-nginx-controller-6c88c85c98-v8mgs  -n ingress-nginx   bash 
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
bash-5.1$ 
bash-5.1$ cat /etc/nginx/nginx.conf
## start server test.nginx.com
	server {
		server_name test.nginx.com ;   ###ingress中定义的host
		
		listen 80  ;   ###container port
		listen [::]:80  ;   
		listen 443  ssl http2 ;
		listen [::]:443  ssl http2 ;
		
		set $proxy_upstream_name "-";
		
		ssl_certificate_by_lua_block {
			certificate.call()
		}
		
		location / {
			
			set $namespace      "default";   ###命名空间
			set $ingress_name   "ingress-test";  ###ingress 名称
			set $service_name   "nginx-svc";   ###nginx svc名称
			set $service_port   "80";
			set $location_path  "/";
			set $global_rate_limit_exceeding n;



#############下面是tomcat的配置
## start server test.tomcat.com
	server {
		server_name test.tomcat.com ;
		
		listen 80  ;
		listen [::]:80  ;
		listen 443  ssl http2 ;
		listen [::]:443  ssl http2 ;
		
		set $proxy_upstream_name "-";
		
		ssl_certificate_by_lua_block {
			certificate.call()
		}
		
		location / {
			
			set $namespace      "default";
			set $ingress_name   "ingress-test";
			set $service_name   "tomcat-svc";
			set $service_port   "8080";
			set $location_path  "/";
			set $global_rate_limit_exceeding n;
			

  • 浏览器测试
windows 机器添加host解析
文件位置:C:\WINDOWS\System32\drivers\etc\hosts
192.168.5.79  test.nginx.com test.tomcat.com

访问nginx界面
k8s ingress基础_第4张图片
访问tomcat界面
k8s ingress基础_第5张图片

四、测试https模式

  • 创建secret
1:生成证书
[root@node1 cert]# openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/C=CN/ST=BJ/L=BJ/O=nginx/CN=test.com"  ###注意此处的域名
Generating a RSA private key
.........................................................+++++
...+++++
writing new private key to 'tls.key'
-----
[root@node1 cert]# ll
total 8
-rw-r--r-- 1 root root 1261 Nov 10 16:55 tls.crt
-rw------- 1 root root 1704 Nov 10 16:55 tls.key
[root@node1 cert]# 

2:创建secret
[root@node1 cert]# kubectl create secret tls tls-secret --key tls.key --cert tls.crt
secret/tls-secret created
[root@node1 cert]# kubectl get secret  | grep tls-secret
tls-secret                    kubernetes.io/tls    2      19s
[root@node1 cert]# 
  • 创建带tls的ingress
1:编辑yaml文件
[root@node1 yaml]# cat ingress-https.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-test
spec:
  tls:
    - hosts:
        - nginx.test.com     ###制定使用tls的主机
        - tomcat.test.com
      secretName: tls-secret   ###指定secret
  ingressClassName: nginx
  rules:
  - host: "nginx.test.com"
    http:
      paths:
      - path: "/"
        pathType: Prefix
        backend:
          service:
            name: nginx-svc
            port:
              number: 80
  - host: "tomcat.test.com"
    http:
      paths:
      - path: "/"
        pathType: Prefix
        backend:
          service:
            name: tomcat-svc
            port:
              number: 8080

[root@node1 yaml]# 


########################################
2:创建ingress,如下可以看到ports 多了个443端口
[root@node1 yaml]# kubectl apply -f  ingress-https.yaml 
ingress.networking.k8s.io/ingress-test created
[root@node1 yaml]# kubectl get ingress
NAME           CLASS   HOSTS                            ADDRESS   PORTS     AGE
ingress-test   nginx   nginx.test.com,tomcat.test.com             80, 443   7s
[root@node1 yaml]# kubectl get ingress
NAME           CLASS   HOSTS                            ADDRESS        PORTS     AGE
ingress-test   nginx   nginx.test.com,tomcat.test.com   192.168.5.79   80, 443   43s

  • 浏览器测试
windows 机器添加host解析
文件位置:C:\WINDOWS\System32\drivers\etc\hosts
192.168.5.79  nginx.test.com tomcat.test.com

访问nginx,如下:
k8s ingress基础_第6张图片
k8s ingress基础_第7张图片
访问tomcat,如下:
k8s ingress基础_第8张图片
k8s ingress基础_第9张图片
注意:如果显示以下问题,可以在当前浏览器页面,直接敲键盘输入thisisunsafe就可以了
k8s ingress基础_第10张图片

你可能感兴趣的:(k8s,k8s)