GVKun编程网logo

将 Kubernetes Ingress 暴露给 LAN 计算机

1

在这篇文章中,我们将带领您了解将KubernetesIngress暴露给LAN计算机的全貌,同时,我们还将为您介绍有关07-kubernetesIngress原理和Ingress-nginx案例、26

在这篇文章中,我们将带领您了解将 Kubernetes Ingress 暴露给 LAN 计算机的全貌,同时,我们还将为您介绍有关07-kubernetes Ingress 原理 和 Ingress-nginx 案例、26.kubernetes(k8s)笔记 Ingress(一) Ingress-nginx、k8s Ingress 统一访问入口:ingress 原理与应用、K8S Ingress控制器两个实现版本(kubernetes-ingress 和 ingress-nginx)的区别的知识,以帮助您更好地理解这个主题。

本文目录一览:

将 Kubernetes Ingress 暴露给 LAN 计算机

将 Kubernetes Ingress 暴露给 LAN 计算机

如何解决将 Kubernetes Ingress 暴露给 LAN 计算机

我在局域网上有计算机 A 和 B: A 在 IP 192.168.0.104 B 在 IP 192.168.0.110

在计算机 B 上,我有一个带入口的 Kubernetes 服务: 路径你好 主机 hello-node.com

minikube ip 是 192.168.49.2 /etc/hosts 有一行: 192.168.49.2 hello-node.com

在 B 上,我看到了对 hello-node.com/hello 的服务响应,但没有看到 192.168.49.2/你好。在 192.168.49.2/hello 我看到来自 Nginx 的 404 错误。

如何从计算机 A 访问 hello-node.com/hello 或 192.168.49.2/hello?

我不想依赖任何第三方服务(负载均衡器等)


信息: minikube 版本:v1.16.0

  1. $ kubectl cluster-info
  2. Kubernetes control plane is running at https://192.168.49.2:8443
  3. KubednS is running at https://192.168.49.2:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

不使用入口但使用 NodePort 公开命令的解决方法。来自@mariusz-k 的链接
  1. kubectl expose deployment/hello-node --type="NodePort" --port 8080
  2. SERVICE_NODE_IP=$(minikube ip)
  3. FORWARD_PORT=8090
  4. SERVICE_NODE_PORT=$(kubectl get services/hello-node -o go-template=''{{(index .spec.ports 0).nodePort}}'')
  5. ssh -i ~/.minikube/machines/minikube/id_rsa docker@$SERVICE_NODE_IP -NL \\*:$FORWARD_PORT:0.0.0.0:$SERVICE_NODE_PORT

解决方法

您需要获取计算机 B 的地址(集群 ip)然后连接到它。

  1. # Get the cluster "master" ip
  2. $ kubectl cluster-info
  3. Kubernetes master is running at https://<the desired ip/DNS record>......:443
  4. # use the above ip to get the content of your service
  5. curl -vsI <ip>/hello

,

您可以按照this github issue中的步骤从另一台机器访问您的 minikube 服务:

  1. service_name=web # This is what you need to replace with your own service
  2. service_port=$(minikube service $service_name --url | cut -d'':'' -f3)
  3. ssh -i ~/.minikube/machines/minikube/id_rsa docker@$(minikube ip) -NL \\*:${service_port}:0.0.0.0:${service_port}

之后,您的服务将在 ` 下可用:

07-kubernetes Ingress 原理 和 Ingress-nginx 案例

07-kubernetes Ingress 原理 和 Ingress-nginx 案例

[TOC]

Service 类型

  1. ClusterIP 只在集群内部访问,无法跨越集群边界
  2. NodePort 提供集群外部流量进入到集群内部
  3. LoadBalancer 集群部署在公有云或私有云之上,提供给公有云或私有云的负载均衡中间使用
  4. ExternelName 把集群外部的服务映射给集群内部使用, 是一个 FQDN 的名称,一个 CNAME 名称,这个 CNAM 指向公网的 FQDN

No ClusterIP 成为 Headless Sercie

ServiceName -> PodIP

Service 是一个四层调度器

也就是说,当请求为HTTPS请求的时候,则无法卸载证书。

namespace 名称空间

; 创建 namespace 如下:

[root@master manifests]# kubectl create namespace dev
namespace/dev created
[root@master manifests]# kubectl get ns
NAME              STATUS   AGE
default           Active   20d
dev               Active   4s       # 新创建的namespace
kube-node-lease   Active   20d
kube-public       Active   20d
kube-system       Active   20d

删除 namespace 如下:

[root@master manifests]# kubectl delete ns/dev
namespace "dev" deleted
[root@master manifests]# kubectl get ns
NAME              STATUS   AGE
default           Active   20d
kube-node-lease   Active   20d
kube-public       Active   20d
kube-system       Active   20d

Ingress Controller

举例

当kubernetes集群有上千甚至跟多个节点的时候,此时需要特有的web七层代理
如在集群其中的四个节点上打上污点,这四个节点上只运行web七层代理所对应的Pod
由此Pod来代理集群内部的Service,Service再把流量转发给集群内部对应的Pod。

这就叫做 Ingress Controller

Ingress Controller 是基于 DaemonSet 控制器来实现。

DaemonSet 是实现保证集群内部每个节点上都运行一个指定的 Pod。

Kubernetes 中三种常用七层代理:

  1. Nginx # 常规代理
  2. Traefik # 微服务前段负载均衡
  3. Envoy # 微服务代理负载均衡,使用的多

Ingress

IngressIngress Controller 是两回事。

Ingress 原理

Ingress 启动一个独立的 Pod 来运行七层代理,可以是 NginxTraefik 或者是 Envoy,此时 ingress Pod 会直接代理 后端运行服务的 Pod,为了能监听后端 Pod 的变化,需要一个 无头 Service Headless Sercie 通过标签选择器来选择后端指定的 Pod,并收集到后端 Pod 对应的 IP,而此 Service 不会被使用,它主要是用于被 Ingress Pod 来监听后端 Pod 的变化,而一旦后端 Pod 产生变化,无头 Service 会知道,此时被 Ingress Pod 发现后,会自动根据变化来更改配置文件,并重载。

如果此时使用的是 Nginx 类型的 Ingress Pod ,则每次变化后修改配置文件后都会自动重新 reload。
但如果使用 Traefik 或者是 Envoy 天生就是为微服务开发的,更友好的支持。

Ingress-nginx 进行测试

可以在 GitHub 上找到 Ingress-nginx

本次使用的是相对简单部署 ingress-nginx 的配置清单。

ingress-nginx 单独的详情页面

因为是直接在物理机上直接安装的 kubernetes 集群,所以需要两个配置清单。

[root@master ingress]#  kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
namespace/ingress-nginx created
configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
serviceaccount/nginx-ingress-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-role created
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
deployment.apps/nginx-ingress-controller created

还需要一个 Ingress-name 名称空间中创建的 NodePort Service,以便引入集群外流量

需要根据实际情况修改一下:

[root@master ingress]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/baremetal/service-nodeport.yaml
[root@master ingress]# cat service-nodeport.yaml 
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: 30080       # 手动指定node对外的http端口
    - name: https
      port: 443
      targetPort: 443
      protocol: TCP
      nodePort: 30443       # 手动指定node对外的https端口
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

[root@master ingress]#kubectl apply -f service-nodeport.yaml
service/ingress-nginx created

查看创建的 ingress-nginx Pod

[root@master ingress]# kubectl get pods -n ingress-nginx -o wide
NAME                                        READY   STATUS    RESTARTS   AGE   IP            NODE                NOMINATED NODE   READINESS GATES
nginx-ingress-controller-7995bd9c47-b4fzh   1/1     Running   0          34s   10.244.1.27   node03.kubernetes   <none>           <none>
[root@master ingress]# kubectl get svc -n ingress-nginx     # 这里是第二次执行在Ingress-name名称空间中创建的NodePort Service,以便引入集群外流量
NAME            TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx   NodePort   10.111.201.108   <none>        80:30080/TCP,443:30443/TCP   44s

创建对应的后端 Pod 和 Service

查看创建的 ingress-myapp

[root@master ingress]# cat myapp-deplay.yaml 
apiVersion: v1
kind: Service
metadata:
  name: myapp       # Service 名称
  namespace: default
spec:
  selector:
    app: myapp
    release: canary
  ports:
  - name: http
    targetPort: 80      # 指定容器端口
    port: 80            # Service 自己开房的端口
    
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      release: canary
  template:
    metadata:
      labels:
        app: myapp
        release: canary
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v2
        ports:
        - name: http
          containerPort: 80
[root@master ingress]# kubectl apply -f myapp-deplay.yaml 
service/myapp created
deployment.apps/myapp-deploy unchanged

查看

[root@master ingress]# kubectl get pods
NAME                            READY   STATUS    RESTARTS   AGE
myapp-deploy-55b78d8548-b4c2c   1/1     Running   0          42h
myapp-deploy-55b78d8548-gpdw8   1/1     Running   0          42h
myapp-deploy-55b78d8548-hr6vx   1/1     Running   0          42h
[root@master ingress]# kubectl get svc
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP   22d
myapp        ClusterIP   10.111.44.7   <none>        80/TCP    6s

创建 Ingress

[root@master ingress]# cat ingress-myapp.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-myapp
  namespace: default
  annotations:
    kubernetes.io/ingress.class: "nginx"        # 自动生成 nginx 相关的匹配和修改规则
spec:
  rules:
  - host: myapp.sijiayong.com       # 使用 host 主机模式来访问
    http:
      paths:
      - path:
        backend:
          serviceName: myapp        # 这里指定刚刚创建的后端Pod对应的Service名称
          servicePort: 80
[root@master ingress]# kubectl apply -f ingress-myapp.yaml 
ingress.extensions/ingress-myapp created
[root@master ingress]# kubectl get ing
NAME            HOSTS                 ADDRESS   PORTS   AGE
ingress-myapp   myapp.sijiayong.com             80      6s

查看 Ingress-controller 对应的 Pod 配置信息

上面一系列都配置完成之后,此时在看查看 Ingress-controller 的 Pod 中 nginx 的配置信息包含如下:

[root@master ingress]# kubectl exec -n ingress-nginx -it nginx-ingress-controller-7995bd9c47-b4fzh -- /bin/sh
	server {
		server_name myapp.sijiayong.com ;
		listen 80;
		
		set $proxy_upstream_name "-";
		set $pass_access_scheme $scheme;
		set $pass_server_port $server_port;
		set $best_http_host $http_host;
		set $pass_port $pass_server_port;
		location / {
			
			set $namespace      "default";
			set $ingress_name   "ingress-myapp";
			set $service_name   "myapp";
			set $service_port   "80";
			set $location_path  "/";

... ...
... ...

访问测试

此时在集群外部访问测试:

注意,临时测试,上面使用的 host 模式来访问,所以在测试的集群外部机器上手动添加 hosts 记录

[root@xinguan-test-node1 ~]# grep myapp /etc/hosts
10.0.20.20 myapp.sijiayong.com
[root@xinguan-test-node1 ~]# curl myapp.sijiayong.com:30080
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
[root@xinguan-test-node1 ~]# curl myapp.sijiayong.com:30080/hostname.html
myapp-deploy-55b78d8548-hr6vx

模拟测试 Ingress 后端 Tomcat 访问

还是基于上面的配置,一切都不动,增加 tomcat 后端 Pod 和 Service 以及 Ingress

创建 tomcat 的 Pod 和 Service

[root@master ingress]# cat tomcat-deploy.yaml 
apiVersion: v1
kind: Service
metadata:
  name: tomcat
  namespace: default
spec:
  selector:
    app: tomcat
    release: canary
  ports:
  - name: http
    targetPort: 8080
    port: 8080
  - name: ajp
    targetPort: 8009
    port: 8009
    
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-depoly
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: tomcat
      release: canary
  template:
    metadata:
      labels:
        app: tomcat
        release: canary
    spec:
      containers:
      - name: tomcat
        image: tomcat:8.5.32-jre8-alpine
        ports:
        - name: http
          containerPort: 8080
        - name: ajp
          containerPort: 8009

创建和查看

[root@master ingress]# kubectl apply -f tomcat-deploy.yaml 
service/tomcat created
deployment.apps/tomcat-depoly created
[root@master ingress]# kubectl get pods -o wide
NAME                             READY   STATUS    RESTARTS   AGE   IP            NODE                NOMINATED NODE   READINESS GATES
myapp-deploy-55b78d8548-b4c2c    1/1     Running   0          43h   10.244.3.29   node01.kubernetes   <none>           <none>
myapp-deploy-55b78d8548-gpdw8    1/1     Running   0          43h   10.244.1.26   node03.kubernetes   <none>           <none>
myapp-deploy-55b78d8548-hr6vx    1/1     Running   0          43h   10.244.2.22   node02.kubernetes   <none>           <none>
tomcat-depoly-579d97b849-66wrh   1/1     Running   0          7s    10.244.3.30   node01.kubernetes   <none>           <none>
tomcat-depoly-579d97b849-rh5r6   1/1     Running   0          7s    10.244.1.28   node03.kubernetes   <none>           <none>
tomcat-depoly-579d97b849-sd49w   1/1     Running   0          7s    10.244.2.23   node02.kubernetes   <none>           <none>
[root@master ingress]# kubectl get svc
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)             AGE
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP             22d
myapp        ClusterIP   10.111.44.7    <none>        80/TCP              76m
tomcat       ClusterIP   10.106.39.78   <none>        8080/TCP,8009/TCP   3m18s

创建 tomcat-ingress

[root@master ingress]# cat ingress-tomcat.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-tomcat
  namespace: default
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: tomcat.sijiayong.com
    http:
      paths:
      - path:
        backend:
          serviceName: tomcat
          servicePort: 8080

创建和查看

[root@master ingress]# kubectl apply -f ingress-tomcat.yaml 
ingress.extensions/ingress-tomcat created
[root@master ingress]# kubectl get ing
NAME             HOSTS                  ADDRESS   PORTS   AGE
ingress-myapp    myapp.sijiayong.com              80      53m
ingress-tomcat   tomcat.sijiayong.com             80      4s

测试访问 tomcat

注意,同样写 Hosts 之后进行测试

[root@xinguan-test-node1 ~]# grep tomcat /etc/hosts
10.0.20.20 myapp.sijiayong.com tomcat.sijiayong.com
[root@xinguan-test-node1 ~]# curl tomcat.sijiayong.com:30080



<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>Apache Tomcat/8.5.32</title>
        <link href="favicon.ico" rel="icon" type="image/x-icon" />
        <link href="favicon.ico" rel="shortcut icon" type="image/x-icon" />
        <link href="tomcat.css" rel="stylesheet" type="text/css" />
    </head>

    <body>
        <div id="wrapper">
            <div id="navigation" class="curved container">
                <span id="nav-home"><a href="http://tomcat.apache.org/">Home</a></span>
                <span id="nav-hosts"><a href="/docs/">Documentation</a></span>
                <span id="nav-config"><a href="/docs/config/">Configuration</a></span>
                <span id="nav-examples"><a href="/examples/">Examples</a></span>
                <span id="nav-wiki"><a href="http://wiki.apache.org/tomcat/FrontPage">Wiki</a></span>
                <span id="nav-lists"><a href="http://tomcat.apache.org/lists.html">Mailing Lists</a></span>
                <span id="nav-help"><a href="http://tomcat.apache.org/findhelp.html">Find Help</a></span>
                <br class="separator" />
            </div>
            <div id="asf-box">
                <h1>Apache Tomcat/8.5.32</h1>
            </div>
... ...
... ...

模拟测试 Https

模拟测试 通过 Ingress 的七层代理,访问 Https,通过 Ingress 卸载证书后访问后端

所有先需要手动自签 SSL 证书

自签 SSL 证书

[root@master https]# openssl genrsa -out tls.key 2048 
Generating RSA private key, 2048 bit long modulus
...............................+++
.....................................................................................................................................+++
e is 65537 (0x10001)
[root@master https]# openssl req -new -x509 -key tls.key -out tls.crt -subj /C=CN/ST=BeiJing/L=BeiJing/O=DefOps/CN=tomcat.sijiayong.com
[root@master https]# ll
total 8
-rw-r--r-- 1 root root 1302 Aug  1 11:33 tls.crt
-rw-r--r-- 1 root root 1675 Aug  1 11:31 tls.key

自签证书完成

创建 secret

注意,此证书不能直接帖进去,需要先创建成 secret,才能应用到 Ingress 中

[root@master https]# kubectl create secret tls tomcat-ingress-secret --cert=tls.crt --key=tls.key 
secret/tomcat-ingress-secret created
[root@master https]# kubectl get secret
NAME                    TYPE                                  DATA   AGE
default-token-bc86p     kubernetes.io/service-account-token   3      22d
tomcat-ingress-secret   kubernetes.io/tls                     2      10s
[root@master https]# kubectl describe secret tomcat-ingress-secret
Name:         tomcat-ingress-secret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  kubernetes.io/tls

Data
====
tls.key:  1675 bytes
tls.crt:  1302 bytes

创建 tls 的 https 清单文件

[root@master https]# cat ingress-tomcat-tls.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-tomcat-tls
  namespace: default
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  tls:
  - hosts:
    - tomcat.sijiayong.com
    secretName: tomcat-ingress-secret       # 这里指定刚刚创建的secret名称
  rules:
  - host: tomcat.sijiayong.com
    http:
      paths:
      - path:
        backend:
          serviceName: tomcat
          servicePort: 8080

创建和查看

[root@master https]# kubectl apply -f ingress-tomcat-tls.yaml 
ingress.extensions/ingress-tomcat-tls created
[root@master https]# kubectl get ing
NAME                 HOSTS                  ADDRESS   PORTS     AGE
ingress-myapp        myapp.sijiayong.com              80        174m
ingress-tomcat       tomcat.sijiayong.com             80        121m
ingress-tomcat-tls   tomcat.sijiayong.com             80, 443   4s          # 这里看到被创建成功
[root@master https]# kubectl describe ingres-tomcat-tls
error: the server doesn''t have a resource type "ingres-tomcat-tls"
[root@master https]# kubectl describe ingress ingress-tomcat-tls
Name:             ingress-tomcat-tls
Namespace:        default
Address:          
Default backend:  default-http-backend:80 (<none>)
TLS:
  tomcat-ingress-secret terminates tomcat.sijiayong.com
Rules:
  Host                  Path  Backends
  ----                  ----  --------
  tomcat.sijiayong.com  
                           tomcat:8080 (10.244.1.28:8080,10.244.2.23:8080,10.244.3.30:8080)
Annotations:
  kubectl.kubernetes.io/last-applied-configuration:  {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{"kubernetes.io/ingress.class":"nginx"},"name":"ingress-tomcat-tls","namespace":"default"},"spec":{"rules":[{"host":"tomcat.sijiayong.com","http":{"paths":[{"backend":{"serviceName":"tomcat","servicePort":8080},"path":null}]}}],"tls":[{"hosts":["tomcat.sijiayong.com"],"secretName":"tomcat-ingress-secret"}]}}

  kubernetes.io/ingress.class:  nginx
Events:
  Type    Reason  Age   From                      Message
  ----    ------  ----  ----                      -------
  Normal  CREATE  26s   nginx-ingress-controller  Ingress default/ingress-tomcat-tls

测试访问

此时就已经完成,可以测试访问

因前面测试 hosts 已经写好

26.kubernetes(k8s)笔记 Ingress(一) Ingress-nginx

26.kubernetes(k8s)笔记 Ingress(一) Ingress-nginx

前言:

什么是Ingress?

官方的解释是:
Ingress 是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。
Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。

Ingress简介
Ingress对象,其实就是对“反向代理”的一种抽象,简单的说就是一个全局的负载均衡器,可以通过访问URL定位到后端的Service
有了Ingress这个抽象,K8S就不需要关心Ingress的细节了,实际使用时,只需要选择一个具体的Ingress Controller部署就行了,业界常用的反向代理项目有:Nginx、HAProxy、Envoy、Traefik 都已经成为了K8S专门维护的Ingress Controller
一个Ingress对象的主要内容,就类似Nginx的配置文件描述,对应的转发规则就是ingressRule,
有了Ingress这个对象,用户就可以根据自己的需求选择Ingress Controller,例如,如果应用对代理服务的中断非常敏感,可以使用Treafik这样的Ingress Controller

Ingress工作在七层,Service工作在四层,当想要在Kubernetes里为应用进行TLS配置等HTTPS相关操作时,都必须通过Ingress来进行

  • ingress-nginx 简单的理解就是你原来需要改 Nginx 配置,然后配置各种域名对应哪个 Service,现在把这个动作抽象出来,变成一个 Ingress 对象,你可以用 yaml 创建,每次不要去改 Nginx 了,直接改 yaml 然后创建/更新就行了;那么问题来了:”Nginx 该怎么处理?”
  • Ingress Controller 这东西就是解决 “Nginx 的处理方式” 的;Ingress Controoler 通过与 Kubernetes API 交互,动态的去感知集群中 Ingress 规则变化,然后读取他,按照他自己模板生成一段 Nginx 配置,再写到 Nginx Pod 里,最后 reload 一下,工作流程如下图:

  • 实际上Ingress也是Kubernetes API的标准资源类型之一,它其实就是一组基于DNS名称(host)或URL路径把请求转发到指定的Service资源的规则。用于将集群外部的请求流量转发到集群内部完成的服务发布。我们需要明白的是,Ingress资源自身不能进行“流量穿透”,仅仅是一组规则的集合,这些集合规则还需要其他功能的辅助,比如监听某套接字,然后根据这些规则的匹配进行路由转发,这些能够为Ingress资源监听套接字并将流量转发的组件就是Ingress Controller
  • Ingress 两种路由方式
    1.虚拟主机
    2.URL 路径

Ingree-nginx部署

  • ingress-nginx 很多全局配置或修改默认配置都是通过annotations 注释来加载配置文件具体参数详细解释可
    参考官方文档:

    https://kubernetes.github.io/...
  • 选择NodePort部署方式

    https://kubernetes.github.io/...
  • extensions/v1beta1 Ingress资源规范 1.22+版本后会被彻底弃用
apiVersion: extensions/v1betal #资源所属的API群组和版本
Kind: Ingress#资源类型标识符
metadata: #元数据
  name <string> #资源名称
  annotationsl #资源注解,v1betal使用下面的注解来指定要解析该资源的控制器类型
    kubernetes.io/ingress.class: <string> #适配的Ingress控制器类别
  namespace <string> #名称空间
spec:
  rules <[]Object> #Ingress规则列表;
  - host <string>  #虚拟主机的FQDN,支持“*"前缀通配,不支持IP,不支持指定端口
    http <object>
      paths<[]0bject>#虚拟主机PATH定义的列表,由path和backend组成
      - path <string> #流量匹配的HTTP PATH,必须以/开头
        pathType <string> #匹配机制,支持Exact、_Prefix和ImplementationSpecific
        backend <object> #匹配到的流量转发到的目标后端
          resource <Object> #引用的同一名称空间下的资源,与下面两个字段互斥
          serviceName <string>#引用的Service资源的名称
          servicePort <string># Service用于提供服务的端口
  tls <[]object> #TLS配置,用于指定上rules中定义的哪些host需要工作HTTPS模式
  - hosts <[]string>  #使用同一组证书的主机名称列表
    secretName <string>  #保存于数字证书和私钥信息的secret资源名称
  backend <object>   #默认backend的定义,可嵌套字段及使用格式跟rules字段中的相同
  ingressClassName <string> #ingress类名称,用于指定适配的控制器
  • v1 Ingress资源规范
apiVersion: networking.k8s.io/v1 #资源所属的API群组和版本
kind: Ingress #资源类型标识符
metadata: #元数据
  name <string> #资源名称
  annotations: #资源注解,vlbetal使用下面的注解来指定要解析该资源的控制器类型
    kubernetes.io/ingress.class:<string> #适配的Ingress控制器类别
  namespace <string>  #名称空间
spec:
  rules <[]object> #Ingress规则列表
  - host <string>  #虚拟主机的FQDN,支持“*"前缀通配,不支持IP,不支持指定端口
    http <object>
      paths <[]object>#虚拟主机PATH定义的列表,由path和backend组成
      - path <string> #流量匹配的HTTP PATH,必须以/开头
        pathType <string> #支持Exact、Prefix和ImplementationSpecific,必选
        backend <Object>#匹配到的流量转发到的目标后端
          resource <object>  #引用的同一名称空间下的资源,与下面两个字段互斥
          service <object> #关联的后端Service对象
            name <string> #后端Service的名称
            port bject> #后端Service上的端口对象
              name <string> #端口名称
              number <integer>  #端口号
  tls <[]object>  #TLS配置,用于指定上rules中定义的哪些host需要工作HTTPS模式
  - hosts <[]string>  #使用同一组证书的主机名称列表
    secretName <string> #保存于数字证书和私钥信息的secret资源名称
  backend <object>  #默认backend的定义,可嵌套字段及使用格式跟rules字段中的相同
  ingressClassName <string> #ingress类名称,用于指定适配的控制器
  • 添加externalIPs:节点3 IP非必须步骤,方便记忆使用 而不是记忆NodePort端口 NodePort与externalIPs可同时访问
[root@k8s-master Ingress]# vim deploy.yaml
...
---
# Source: ingress-nginx/templates/controller-service.yaml
apiVersion: v1
kind: Service
metadata:
  annotations:
  labels:
    helm.sh/chart: ingress-nginx-4.0.1
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 1.0.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: controller
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  type: NodePort
  externalIPs: [192.168.54.173]   #添加externalIPs字段 固定访问IP
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: http
      appProtocol: http
    - name: https
      port: 443
      protocol: TCP
      targetPort: https
      appProtocol: https
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/component: controller
...
  • 部署Ingress-nginx
[root@k8s-master Ingress]# kubectl apply -f deploy.yaml 
namespace/ingress-nginx unchanged
serviceaccount/ingress-nginx unchanged
configmap/ingress-nginx-controller configured
clusterrole.rbac.authorization.k8s.io/ingress-nginx unchanged
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx unchanged
role.rbac.authorization.k8s.io/ingress-nginx unchanged
rolebinding.rbac.authorization.k8s.io/ingress-nginx unchanged
service/ingress-nginx-controller-admission unchanged
service/ingress-nginx-controller configured
deployment.apps/ingress-nginx-controller configured
ingressclass.networking.k8s.io/nginx unchanged
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission configured
serviceaccount/ingress-nginx-admission unchanged
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission unchanged
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission unchanged
role.rbac.authorization.k8s.io/ingress-nginx-admission unchanged
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission unchanged
job.batch/ingress-nginx-admission-create unchanged
job.batch/ingress-nginx-admission-patch unchanged
[root@k8s-master Ingress]# kubectl get pod
NAME                              READY   STATUS    RESTARTS   AGE
etcd-operator-646cbffdb6-brbn6    1/1     Running   0          19h
example-etcd-cluster-5fb5d9d6n8   1/1     Running   0          49m
example-etcd-cluster-nc8pdgjrjr   1/1     Running   0          19h
example-etcd-cluster-svgdngq28k   1/1     Running   0          48m
[root@k8s-master Ingress]# kubectl get svc -n ingress-nginx
NAME                                 TYPE        CLUSTER-IP     EXTERNAL-IP      PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.109.24.78   192.168.54.173   80:32493/TCP,443:30239/TCP   120m
ingress-nginx-controller-admission   ClusterIP   10.110.72.52   <none>           443/TCP                      120m

示例1:创建 Ingress-nginx虚拟主机

  • 创建 Deployment 和与之对应的SVC
[root@k8s-master Ingress]# cat deployment-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-demo
  namespace: default
spec:
  replicas: 4
  selector:
    matchLabels:
      app: demoapp
      release: stable
  template:
    metadata:
      labels :
        app: demoapp
        release: stable
    spec:
      containers:
      - name: demoapp
        image: ikubernetes/demoapp:v1.1
        ports:
        - containerPort: 80
          name: http

---
apiVersion: v1
kind: Service
metadata:
  name: demoapp-deploy
  namespace: default
spec:
  selector:
    app: demoapp
    release: stable
  ports:
  - name: http
    port: 80
    targetPort: 80
  • 创建 ingress-nginx
[root@k8s-master Ingress]# cat  demoapp-ingress.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-demo
  annotations:
    kubernetes.io/ingress.class: "nginx"
  namespace: default
spec:
  rules:
  - host: www.ik8s.io  #虚拟主机
    http:
      paths:
      - path: /
        pathType: Prefix  #前缀匹配
        backend:
          service:
            name: demoapp-deploy
            port:
              number: 80

[root@k8s-master Ingress]# kubectl apply -f deployment-demo.yaml
[root@k8s-master Ingress]# kubectl apply -f demoapp-ingress.yaml

[root@k8s-master Ingress]# kubectl get svc -n ingress-nginx
NAME                                 TYPE        CLUSTER-IP     EXTERNAL-IP      PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.109.24.78   192.168.54.173   80:32493/TCP,443:30239/TCP   5h50m
ingress-nginx-controller-admission   ClusterIP   10.110.72.52   <none>           443/TCP                      5h50m

[root@k8s-master Ingress]# kubectl get ingress
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
NAME           CLASS    HOSTS         ADDRESS         PORTS   AGE
ingress-demo   <none>   www.ik8s.io   192.168.4.171   80      3h11m
  • 访问测试
[root@bigyong ~]# cat /etc/hosts   
# ::1        localhost localhost.localdomain localhost6 localhost6.localdomain6
127.0.0.1    localhost localhost.localdomain localhost4 localhost4.localdomain4

...
192.168.54.173   www.ik8s.io   #写hosts

[root@bigyong ~]# curl 192.168.54.173  #直接访问只能到ingress-nginx 没到转发到后端
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
[root@bigyong ~]# curl -H  "Host:www.ik8s.io" 192.168.54.173  #访问成功
iKubernetes demoapp v1.1 !! ClientIP: 192.168.113.37, ServerName: deployment-demo-867c7d9d55-gw6qp, ServerIP: 192.168.113.39
[root@bigyong ~]# curl -H  "Host:www.ik8s.io" 192.168.54.173
iKubernetes demoapp v1.1 !! ClientIP: 192.168.113.37, ServerName: deployment-demo-867c7d9d55-9lnpq, ServerIP: 192.168.12.39!
[root@bigyong ~]# curl -H  "Host:www.ik8s.io" 192.168.54.173
iKubernetes demoapp v1.1 !! ClientIP: 192.168.113.37, ServerName: deployment-demo-867c7d9d55-2zcr5, ServerIP: 192.168.51.61!
[root@bigyong ~]# curl -H  "Host:www.ik8s.io" 192.168.54.173
iKubernetes demoapp v1.1 !! ClientIP: 192.168.113.37, ServerName: deployment-demo-867c7d9d55-9lnpq, ServerIP: 192.168.12.39!

示例2:创建TLS Ingress HTTPS

[root@k8s-master Ingress]# cat   demoapp-ingress.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-demo
  annotations:
    kubernetes.io/ingress.class: "nginx"
  namespace: default
spec:
  rules:
  - host: www.ik8s.io
    http:
      paths:
      - path: /
        pathType: Prefix  #前缀匹配
        backend:
          service:
            name: demoapp-deploy
            port:
              number: 80
  tls:  #添加tls
  - hosts:
    - www.ik8s.io
    secretName: ik8s-tls
    
[root@k8s-master Ingress]# kubectl  apply -f demoapp-ingress.yaml 
ingress.networking.k8s.io/ingress-demo configured

[root@k8s-master Ingress]# kubectl describe ingress ingress-demo
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
Name:             ingress-demo
Namespace:        default
Address:          192.168.4.171
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
TLS:
  ik8s-tls terminates www.ik8s.io
Rules:
  Host         Path  Backends
  ----         ----  --------
  www.ik8s.io  
               /   demoapp-deploy:80 (192.168.113.39:80,192.168.12.39:80)
Annotations:   kubernetes.io/ingress.class: nginx
Events:
  Type    Reason  Age                   From                      Message
  ----    ------  ----                  ----                      -------
  Normal  Sync    113s (x3 over 6h36m)  nginx-ingress-controller  Scheduled for sync
  • 创建tls自签证书
[root@k8s-master Ingress]# (umask 077); openssl  genrsa -out tls.key 2048
Generating RSA private key, 2048 bit long modulus
............................+++
.......................+++
e is 65537 (0x10001)
[root@k8s-master Ingress]# openssl req -new -x509 -key tls.key -out tls.crt -subj "/CN=www.ik8s.io" -days 365
[root@k8s-master Ingress]# ls
demoapp-ingress.yaml    deployment-demo.yaml  tls.crt
deploy-externalIP.yaml  deploy.yaml           tls.key
  • 创建Secret
[root@k8s-master Ingress]# kubectl create secret tls ik8s-tls --cert=./tls.crt --key=./tls.key
secret/ik8s-tls created
  • 访问测试
[root@k8s-master Ingress]# curl -H  "Host:www.ik8s.io" 192.168.54.173   #308已经被重定向
<html>
<head><title>308 Permanent Redirect</title></head>
<body>
<center><h1>308 Permanent Redirect</h1></center>
<hr><center>nginx</center>
</body>
</html>

#通过https访问  提示证书无效不被信任
[root@k8s-master Ingress]# curl -H  "Host:www.ik8s.io" https://192.168.54.173 
curl: (60) Issuer certificate is invalid.
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn''t adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you''d like to turn off curl''s verification of the certificate, use
 the -k (or --insecure) option.
  • 忽略风险 访问成功
[root@k8s-master Ingress]# curl -k -H  "Host:www.ik8s.io" https://192.168.54.173  
iKubernetes demoapp v1.1 !! ClientIP: 192.168.113.37, ServerName: deployment-demo-867c7d9d55-9lnpq, ServerIP: 192.168.12.39!

示例3:为dashboard 添加ingress

https://kubernetes.github.io/...

[root@k8s-master Ingress]# cat ingress-kubernetes-dashboard.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: dashboard
  annotations:
    kubernetes.io/ingress.class: "nginx" #指定控制器
    ingress.kubernetes.io/ssl-passthrough: "true"   #tcp代理 因为后端dashboard必须通过https访问  这里通过4层转发直接转发到后端Pod
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" #后端直接通过https协议访问
    nginx.ingress.kubernetes.io/rewrite-target: /$2 #重写标记 path:/dashboard(/|$)(.*) 这里的第2部分
  namespace: kubernetes-dashboard
spec:  #这里没有配置host 相当于*号通配所有主机 
  rules:
  - http:
      paths:
      - path: /dashboard(/|$)(.*)
        backend:
          serviceName: kubernetes-dashboard
          servicePort: 443

[root@k8s-master Ingress]# kubectl apply -f ingress-kubernetes-dashboard.yaml 
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
ingress.extensions/dashboard created

[root@k8s-master Ingress]# kubectl describe ingress dashboard -n kubernetes-dashboard
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
Name:             dashboard
Namespace:        kubernetes-dashboard
Address:          192.168.4.171
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
  Host        Path  Backends
  ----        ----  --------
  *           
              /dashboard(/|$)(.*)   kubernetes-dashboard:443 (192.168.51.64:8443)  #后端pod
Annotations:  ingress.kubernetes.io/ssl-passthrough: true
              kubernetes.io/ingress.class: nginx
              nginx.ingress.kubernetes.io/backend-protocol: HTTPS
              nginx.ingress.kubernetes.io/rewrite-target: /$2
Events:
  Type    Reason  Age                   From                      Message
  ----    ------  ----                  ----                      -------
  Normal  Sync    103s (x2 over 2m41s)  nginx-ingress-controller  Scheduled for sync
  • 访问测试

注意:https://192.168.54.173/dashbo... 一定要带上最后的/ $2为/后面部分 不然无法访问

示例4:longhorn添加ingress-nginx basic认证

参考官方文档

https://longhorn.io/docs/1.2....
  • 默认longhorn没有登录认证暴露到公网会存在风险 首先添加basic认证
[root@k8s-master Ingress]# kubectl get pod -n longhorn-system 
NAME                                        READY   STATUS    RESTARTS   AGE
....
longhorn-manager-cc8sp                      1/1     Running   0          149m
longhorn-manager-fs5tx                      1/1     Running   2          149m
longhorn-manager-vwbzn                      1/1     Running   1          149m
longhorn-ui-79f8976fbf-c44ct                1/1     Running   1          149m
[root@k8s-master Ingress]# kubectl get svc  -n longhorn-system 
NAME                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)     AGE
csi-attacher        ClusterIP   10.108.190.205   <none>        12345/TCP   142m
csi-provisioner     ClusterIP   10.99.216.181    <none>        12345/TCP   142m
csi-resizer         ClusterIP   10.96.161.192    <none>        12345/TCP   141m
csi-snapshotter     ClusterIP   10.101.216.72    <none>        12345/TCP   141m
longhorn-backend    ClusterIP   10.108.67.31     <none>        9500/TCP    149m
longhorn-frontend   ClusterIP   10.107.71.176    <none>        80/TCP      149m

[root@k8s-master Ingress]# USER=user.com; PASSWORD=passwd.com; echo "${USER}:$(openssl passwd -stdin -apr1 <<< ${PASSWORD})" >> auth
[root@k8s-master Ingress]# ls
auth                  deploy-externalIP.yaml  deploy.yaml                        tls.crt
demoapp-ingress.yaml  deployment-demo.yaml    ingress-kubernetes-dashboard.yaml  tls.key

[root@k8s-master Ingress]# kubectl -n longhorn-system create secret generic basic-auth --from-file=authsecret/basic-auth created

[root@k8s-master Ingress]# cat longhorn-ui-ingress.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: longhorn-ingress
  namespace: longhorn-system
  annotations:
    kubernetes.io/ingress.class: "nginx"   #指定控制器
    # type of authentication
    nginx.ingress.kubernetes.io/auth-type: basic  #认证类型
    # prevent the controller from redirecting (308) to HTTPS
    nginx.ingress.kubernetes.io/ssl-redirect: ''false''     #http通信
    # name of the secret that contains the user/password definitions
    nginx.ingress.kubernetes.io/auth-secret: basic-auth    #secret名称
    # message to display with an appropriate context why the authentication is required
    nginx.ingress.kubernetes.io/auth-realm: ''Authentication Required ''   #输入提示
    # custom max body size for file uploading like backing image uploading
    nginx.ingress.kubernetes.io/proxy-body-size: 10000m
    nginx.ingress.kubernetes.io/rewrite-target: /$2 
spec:
  rules:
  - http:
      paths:
      - pathType: Prefix
        path: /longhorn(/|$)(.*)
        backend:
          service:
            name: longhorn-frontend
            port:
              number: 80

[root@k8s-master Ingress]# kubectl apply -f longhorn-ui-ingress.yaml 
ingress.networking.k8s.io/longhorn-ingress configured
  • 访问 http://IP/longhorn/ #最后的 "/" 一定要加
  • 以下图片IP 重新部署后的服务IP

k8s Ingress 统一访问入口:ingress 原理与应用

k8s Ingress 统一访问入口:ingress 原理与应用

一、前言:service

      kubenrnets的service定义了这样一种抽象:一个pod的逻辑分组,一种可以访问他们的策略--通常别称为微服务。这一组pod能够被service访问到,通常是通过 label selector。我们说k8s 的服务(service)时说暴露了service的四种方式:

        1)ClusterIp:默认类型,自动分配一个仅cluster内部可以访问的虚拟IP地址
        2)NodePort:在clusterip的基础上为Service在每台机器上绑定一个端口,这样就可以通过<NodeIp>:nodeport来访问服务
        3)LoadBalancer:在nodeport的基础上,借助cloud provider创建一个外部负载均衡器,并将请求转发到<nodeip>:nodeport
        4)  ExternalName:把集群外部的服务引入到集群内部来,在集群内部直接使用没有任何类型的代理被创建,这只有kubernetes1.7或者更高版本的kube-dns才支持。

        在kubenetes集群中,每个Node运行一个kube-proxy进程。kube-proxy负责service实现了一种Vip(虚拟ip)的形式。而不是ExternalName的形似。但并不是默认的运行模式。从k8s1.2起,默认就是iptables代理,在k8s-1.8-beta.0,添加了ipvs代理:

  • 在k8ds1.4版本中开始默认使用ipvs代理
  • 在k8s1.0版本,service是四层(tcp/udp overip)概念。在k8s1.1版本,新增了ingressAPI(beta版),用来表示七层(http)服务

        clusterip主要在每个node节点使用ipvs,将发向clusterip对应端口的数据,转发到kube-proxy中,然后kube-proxy自己内部有实现负载均衡的办法,并可以查询到这个service下对应pod的地址和端口,进而把数据转发给对应的pod的地址和端口
        为了实现上图的功能,主要需要一下几个组件的协同工作:
            1)apiserver用户通过kubectl命令向apiserver发送创建service的命令,apiserver接收到请求后将数据存储到etcd中
            2)kube-proxy k8s的每个节点中都有一个叫做kube-proxy的进程,这个进程负责感知service,pod的变化,并将变化的信息写入本地的ipvs规则中
            3)ipvs使用nat将virtualip的流量转至endpoint中

        ClusterIP、NodePort与LoadBalance,这几种方式都是在service的维度提供的,service的作用体现在两个方面,对集群内部,它不断跟踪pod的变化,更新endpoint中对应pod的对象,提供了ip不断变化的pod的服务发现机制,对集群外部,他类似负载均衡器,可以在集群内外部对pod进行访问。但是,单独用service暴露服务的方式,在实际生产环境中不太合适:

  • ClusterIP的方式只能在集群内部访问。
  • 只能提供4层负载均衡能力,而没有七层功能,但是我们可以通过更多的匹配规则来请求转发,这点上4层负载均衡是不支持的
  • NodePort方式的话,测试环境使用还行,当有几十上百的服务在集群中运行时,不支持虚拟路径,受端口范围限制,后期维护困难,端口管理是灾难。
  • Service LoadBlancer: 没有过滤、路由等。这意味着您可以发送几乎任何类型的流量,如 HTTP,TCP,UDP,Websockets,gRPC 或其他;最大的缺点是,需要云厂商支持且您使用 LoadBalancer 公开的每项服务都将获得自己的 IP 地址,并且您必须为每个暴露的服务使用一个 LoadBalancer,这可能会付出比较大的代价!
  • Ingress: 灵活,无依赖,生产环境用的比较多的方式,一般在云环境下是 LB + Ingress Ctroller 方式对外提供服务,这样就可以在一个 LB 的情况下根据域名路由到对应后端的 Service,有点类似于 Nginx 反向代理,只不过在 k8s 集群中,这个反向代理是集群外部流量的统一入口。

    所幸k8s还提供了一种集群维度暴露服务的方式,也就是ingress。ingress可以简单理解为service的service,他通过独立的ingress对象来制定请求转发的规则,把请求路由到一个或多个service中。这样就把服务与请求规则解耦了,可以从业务维度统一考虑业务的暴露,而不用为每个service单独考虑。
举个例子,现在集群有api、文件存储、前端3个service,可以通过一个ingress对象来实现图中的请求转发:

ingress规则是很灵活的,可以根据不同域名、不同path转发请求到不同的service,并且支持https/http。

二、ingress与ingress-controller

Ingress 是 k8s 资源对象,用于对外暴露服务,该资源对象定义了不同主机名(域名)及 URL 和对应后端 Service(k8s Service)的绑定,根据不同的路径路由 http 和 https 流量。而 Ingress Contoller 是一个 pod 服务,封装了一个 web 前端负载均衡器,同时在其基础上实现了动态感知 Ingress 并根据 Ingress 的定义动态生成 前端 web 负载均衡器的配置文件,比如 Nginx Ingress Controller 本质上就是一个 Nginx,只不过它能根据 Ingress 资源的定义动态生成 Nginx 的配置文件,然后动态 Reload。个人觉得 Ingress Controller 的重大作用是将前端负载均衡器和 Kubernetes 完美地结合了起来,一方面在云、容器平台下方便配置的管理,另一方面实现了集群统一的流量入口,而不是像 nodePort 那样给集群打多个孔。

所以,总的来说要使用 Ingress,得先部署 Ingress Controller 实体(相当于前端 Nginx),然后再创建 Ingress (相当于 Nginx 配置的 k8s 资源体现),Ingress Controller 部署好后会动态检测 Ingress 的创建情况生成相应配置。Ingress Controller 的实现有很多种:有基于 Nginx 的,也有基于 HAProxy的,还有基于 OpenResty 的 Kong Ingress Controller 等

要理解ingress,需要区分两个概念,ingress和ingress-controller:

  • ingress对象:
    指的是k8s中的一个api对象,一般用yaml配置。作用是定义请求如何转发到service的规则,可以理解为配置模板。

    通常情况下,Service 和 Pod 的 IP 仅可在集群内部访问。集群外部的请求需要通过负载均衡转发到 Service 在 Node 上暴露的 NodePort 上,然后再由 kube-proxy 通过边缘路由器 (edge router) 将其转发给相关的 Pod 或者丢弃。而 Ingress 就是为进入集群的请求提供路由规则的集合

    Ingress 可以给 Service 提供集群外部访问的 URL、负载均衡、SSL 终止、HTTP 路由等。为了配置这些 Ingress 规则,集群管理员需要部署一个 Ingress Controller,它监听 Ingress 和 Service 的变化,并根据规则配置负载均衡并提供访问入口。

  • ingress-controller:
    具体实现反向代理及负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发。

简单来说,ingress-controller才是负责具体转发的组件,通过各种方式将它暴露在集群入口,外部对集群的请求流量会先到ingress-controller,而ingress对象是用来告诉ingress-controller该如何转发请求,比如哪些域名哪些path要转发到哪些服务等等。

2.1 ingress-controller

     ingress-controller并不是k8s自带的组件,实际上ingress-controller只是一个统称,用户可以选择不同的ingress-controller实现,目前,由k8s维护的ingress-controller只有google云的GCE与ingress-nginx两个,其他还有很多第三方维护的ingress-controller,具体可以参考官方文档。但是不管哪一种ingress-controller,实现的机制都大同小异,只是在具体配置上有差异。一般来说,ingress-controller的形式都是一个pod,里面跑着daemon程序和反向代理程序。daemon负责不断监控集群的变化,根据ingress对象生成配置并应用新配置到反向代理,比如nginx-ingress就是动态生成nginx配置,动态更新upstream,并在需要的时候reload程序应用新配置。为了方便,后面的例子都以k8s官方维护的nginx-ingress为例。

2.2 ingress

      ingress是一个API对象,和其他对象一样,通过yaml文件来配置。ingress通过http或https暴露集群内部service,给service提供外部URL、负载均衡、SSL/TLS能力以及基于host的方向代理。ingress要依靠ingress-controller来具体实现以上功能。

       与其他k8s对象一样,ingress配置也包含了apiVersion、kind、metadata、spec等关键字段。有几个关注的在spec字段中,tls用于定义https密钥、证书。rule用于指定请求路由规则。这里值得关注的是metadata.annotations字段。在ingress配置中,annotations很重要。前面有说ingress-controller有很多不同的实现,而不同的ingress-controller就可以根据"kubernetes.io/ingress.class:"来判断要使用哪些ingress配置,同时,不同的ingress-controller也有对应的annotations配置,用于自定义一些参数。列如上面配置的''nginx.ingress.kubernetes.io/use-regex: "true"'',最终是在生成nginx配置中,会采用location ~来表示正则匹配。

三、ingress初体验

虽然 minikube 支持 LoadBalancer 类型的服务,但它并不会创建外部的负载均衡器,而是为这些服务开放一个 NodePort。这在使用 Ingress 时需要注意。

本节展示如何在 minikube 上开启 Ingress Controller 并创建和管理 Ingress 资源。

3.1 启动 Ingress Controller

minikube 已经内置了 ingress addon,只需要开启一下即可

$ minikube addons enable ingress

稍等一会,nginx-ingress-controller 和 default-http-backend 就会起来

$ kubectl get pods -n kube-system
NAME                             READY     STATUS    RESTARTS   AGE
default-http-backend-5374j       1/1       Running   0          1m
kube-addon-manager-minikube      1/1       Running   0          2m
kube-dns-268032401-rhrx6         3/3       Running   0          1m
kubernetes-dashboard-xh74p       1/1       Running   0          2m
nginx-ingress-controller-78mk6   1/1       Running   0          1m

3.2 创建 Ingress

首先启用一个 echo server 服务

$ kubectl run echoserver --image=gcr.io/google_containers/echoserver:1.4 --port=8080
$ kubectl expose deployment echoserver --type=NodePort
$ minikube service echoserver --url
http://192.168.64.36:31957

然后创建一个 Ingress,将 http://mini-echo.io  http://mini-web.io/echo 转发到刚才创建的 echoserver 服务上

$ cat <<EOF | kubectl create -f -
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: echo
  annotations:
    ingress.kubernetes.io/rewrite-target: /
spec:
  backend:
    serviceName: default-http-backend
    servicePort: 80
  rules:
  - host: mini-echo.io
    http:
      paths:
      - path: /
        backend:
          serviceName: echoserver
          servicePort: 8080
  - host: mini-web.io
    http:
      paths:
      - path: /echo
        backend:
          serviceName: echoserver
          servicePort: 8080
EOF

为了访问 mini-echo.io  mini-web.io 这两个域名,手动在 hosts 中增加一个映射

$ echo "$(minikube ip) mini-echo.io mini-web.io" | sudo tee -a /etc/hosts

然后,就可以通过 http://mini-echo.io  http://mini-web.io/echo 来访问服务了。

3.3 使用 xip.io

前面的方法需要每次在使用不同域名时手动配置 hosts,借助 xip.io 可以省掉这个步骤。

xip.io的原理很简单,就是一个泛域名dns解析网站,可以说是一个特别好用的网站测试辅助工具,比如你需要测试一个web服务器,但是你还没申请域名,本地测试大多的办法是host大法,host映射域名到一个IP主机地址,现在有了xip就不用host了。

          10.0.0.1.xip.io   resolves to   10.0.0.1
      www.10.0.0.1.xip.io   resolves to   10.0.0.1
   mysite.10.0.0.1.xip.io   resolves to   10.0.0.1
  foo.bar.10.0.0.1.xip.io   resolves to   10.0.0.1
类似这样的格式都解析为 10.0.0.1
http://域名+地址+xip.io,将解析到对应地址。

先删掉上面的 ingress:

kubectl delete -n default ingress echo

按下面配置重建一个:

cat <<EOF | kubectl create -f -
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: echo
  annotations:
    ingress.kubernetes.io/rewrite-target: /
spec:
  backend:
    serviceName: default-http-backend
    servicePort: 80
  rules:
  - host: mini-echo.io.$(minikube ip).xip.io

    http:
      paths:
      - path: /
        backend:
          serviceName: echoserver
          servicePort: 8080
  - host: mini-web.io.$(minikube ip).xip.io
    http:
      paths:
      - path: /echo
        backend:
          serviceName: echoserver
          servicePort: 8080
EOF

然后 curl mini-echo.io.$(minikube ip).xip.io 和 mini-web.io.$(minikube ip).xip.io 试试。

Refer:

[0] Kubernetes Ingress

[1] minikube Ingress 启动、创建与使用

https://feisky.gitbooks.io/kubernetes/content/practice/minikube-ingress.html

[2] 在 Minikube 环境中使用 NGINX Ingress 控制器配置 Ingress  -- 提供在线 minikube 集群实践

https://kubernetes.io/zh/docs/tasks/access-application-cluster/ingress-minikube/

[3] 【k8s】——ingress原理和应用

[4] K8S镜像下载报错解决方案(使用阿里云镜像去下载kubeadm需要的镜像文件)

[5] 入门级实操教程!从概念到部署,全方位了解K8S Ingress!

[6] k8s ingress原理及ingress-nginx部署测试

K8S Ingress控制器两个实现版本(kubernetes-ingress 和 ingress-nginx)的区别

K8S Ingress控制器两个实现版本(kubernetes-ingress 和 ingress-nginx)的区别

K8s 有2个基于 Nginx 的 Ingress 控制器实现版本: 一个是 nginx实现版本 nginxinc/kubernetes-ingress, 另一个是 k8s实现版本 kubernetes/ingress-nginx. 在这篇文章里, 我们将介绍两者实现的核心差异. 这些信息可以帮助你根据需要选择恰当的实现, 或者从其中一个迁移至另外一个.

我当前用的哪个?

如果你不确定你当前在使用的是哪个实现版本, 可以检查当前在运行的 Ingress 控制器的容器镜像来查看. 其中 nginxinc/kubernetes-ingress 实现版本的 Docker 镜像是发布在 DockerHub 的 nginx/nginx-ingress.

[译者补充] 我们可以通过如下命令查看:

$ sudo docker images | grep ingress
[sudo] password for faceless:
nginx/nginx-ingress                                                        1.5.5               1e674eebb1af        9 months ago        161MB

上面的输出显示我们当前使用的 nginx/nginx-ingress 实现.

核心差异

下面的表格总结了两个 Ingress 控制器实现的核心差异. 注意这个表格右边两列都是关于nginx实现版本的控制器, 他们是分别针对 Nginx 和 Nginx Plus的. 有关更多 Nginx Plus 相关的 Nginx实现版本的信息, 可以查看这里.

特性 K8S 实现版本 Nginx 实现版本 (NGINX) Nginx 实现版本 (NGINX Plus)
基础 -- -- --
作者 K8S 社区 Nginx 公司和社区 Nginx 公司和社区
Nginx版本 包含一些三方模块的定制的 Nginx 版本 Nginx 官方版本 Nginx Plus
商业支持 N/A N/A 包含
通过Ingress资源配置负载均衡 -- -- --
合并同一host的Ingress规则 支持 通过 Mergeable Ingresses 支持 通过 Mergeable Ingresses 支持
HTTP负载均衡扩展 -- 注解方式 见 K8S 支持的注解 见 Nginx 支持的注解 见 Nginx 支持的注解
HTTP负载均衡扩展 -- ConfigMap 方式 见 K8S 支持的 ConfigMap 主键 见 Nginx 支持的 ConfigMap 主键 见 Nginx 支持的 ConfigMap 主键
TCP/UDP 通过 ConfigMap 支持 通过 ConfigMap (原生 NGINX 配置) 支持 通过 ConfigMap (原生 NGINX 配置) 支持
Websocket 支持 通过注解支持 通过注解支持
TCP SSL Passthrough 通过 ConfigMap 支持 不支持 不支持
JWT 验证 不支持 不支持 支持
Session 持久化 通过三方库支持 不支持 支持
金丝雀测试 (通过 header, cookie, weight) 通过注解支持 通过定制的资源支持 通过定制的资源支持
配置模板 *1 见 模板 见 模板 见 模板
通过定制化资源配置负载均衡配置 -- -- --
HTTP负载均衡 不支持 见 VirtualServer 和 VirtualServerRoute 资源 见 VirtualServer 和 VirtualServerRoute 资源
部署 -- -- --
命令行参数 *2 见 K8S 版 参数列表 见 Nginx 版 参数列表 同左
默认 Server 的 TLS 证书和秘钥 必需(命令行参数) / 自动生成 必需(命令行参数) 必需(命令行参数)
Helm Chart 支持 支持 支持
运维 -- -- --
上报 Ingress 控制器的 IP地址到Ingress资源 支持 支持 支持
扩展的状态 通过三方模块支持 不支持 支持
Prometheus 整合 支持 支持 支持
动态配置 endpoints (无需重新加载配置) 通过三方模块支持 不支持 支持

注释:

*1 -- 用于 Ingress 控制器生成 Nginx 配置的配置模板是不同的. 造成的结果是, 对与同样的 Ingress 资源, 不同的控制器生成的配置文件是不同的. 这就意味着在某种情况下, Nginx的行为也可能不一样.

*2 -- 因为命令行参数是不一样的, 所以也就无法使用同一个部署清单来部署 Ingress 控制器.

如何切换 Ingress 控制器

如果你决定切换 Ingress 控制器的实现版本, 做好处理在上文中提到的差异. 至少, 你需要使用一个不同的部署清单.

翻译说明

本文翻译至: Differences Between nginxinc/kubernetes-ingress and kubernetes/ingress-nginx Ingress Controllers, 有细节补充.

翻译日期: 2020/06/07.

今天关于将 Kubernetes Ingress 暴露给 LAN 计算机的分享就到这里,希望大家有所收获,若想了解更多关于07-kubernetes Ingress 原理 和 Ingress-nginx 案例、26.kubernetes(k8s)笔记 Ingress(一) Ingress-nginx、k8s Ingress 统一访问入口:ingress 原理与应用、K8S Ingress控制器两个实现版本(kubernetes-ingress 和 ingress-nginx)的区别等相关知识,可以在本站进行查询。

本文标签: