Ingress 定义以及Ingress控制器

编辑/etc/sysconfig/kubelet   使用 KUBE_PROXY_NODE=ipvs 指定service的模式  那么ipvs使用的算法包括 : ip_vs ip_vs_rr ip_vs_sh

如果一个主机没有Cluster IP 那么我们就称为 Headless -->  将serveicename  解析到后端的pod上

k8s 的三个核心资源:   pod    控制器    service

那么service是四层的负载均衡 ,不是七层的,只能是基于 iptables 或者是 ipvs ,如果用户访问的是https 的请求 ,那么对四层来说无法惊醒负载,  如果pod中的应用是HTTP的想要增强成HTTPS的,那么我们可以想一下其中的证书呀,私钥配置在什么地方,如果我们的调度器是lvs ,那么我们想提供HTTP 的服务 ,那么这个HTTP应该配置在那里? 注: 应该配置在后端主机上,不能配置在lvs上,所以我们必须在后端的每个服务器上配置 HTTPS ,配置证书,私钥 ,,等等  ,

无论是ipvs 还是 iptables ,都无法调度七层的应用,因此我们要使用http 或者 https 我们就必须使用七层的调度 ,将客户 -> 调度器 (使用七层) -> 后端  ,  那么现在我们就只能换调度器 , k8s 采用(可以理解为加一层),后端配置的是不加https ,就是明文的htp, 那么我们使用一个独特的调度器,当用户试图访问的时候,我们不让他们到达后端的服务器,而是先到达调度器 (可以定义一个pod资源) , 然后在访问后端的服务器 ,这样原来的明文就可以被https访问到了 。

那么在K8s中我们有特定的方法来解决这个七层的负载的方法:

我们使用一个新的控制器称为 Ingress Controller ,这个和之前说的 DaemonSet ReplicaSet 都不太一样,----> 他们是作为manager来存在的 ,是master上的核心组件之一,而Ingress 是自己独立存在的一组组件pod资源,通常就是一组应用程序,这个应用程序就是拥有七层调度功能的一组应用程序,k8s上的选择有四种: 最不受待见的是HAproxy 默认的是 Nginx  现在服务网格当中Envoy  当前还有其他的,Traefik 所以我们在配置应用的是有三种选择 : Nginx Envoy traefik(为微服务设计而生) ,

但是它们最为调度器而言不止要调度一个后端服务,那么在后端的web服务有多种时(电商、api、..),使用调度器调度的时候我们怎么可以判断调度的究竟是我们想要的服务?      : 1.我们可以考虑在Nginx上怎么调度,首先我们有四组upstream ,然后对客户端而言我们可以做四个虚拟主机 来进行以域名的形式访问。

 

在k8s 上有一类特殊的资源,Ingress资源,Ingress 和 Ingress Controller是两个概念 ,我们定义Ingres  的意义就是说定义我们期望Ingress Controller 如何给我们建一个前端(可能是虚拟主机也可能是url映射)而又给我们定义一个后端(有几个主机 Ingress 是通过srevice得到的),首先我们由一个service对后端的pod进行分类,而后Ingress基于这个分类识别出这几个pod的ip地址 ,然后生成配置信息注入到(以Nginx为例,那就是upstream 中)

 

那么在Igress实现的七层负载的过程是:   最外面的对节点的均衡 Externalname  --->  具体的某一节点上 NodePort ---->  节点上的 Ingresss Controller  --->  调度到具体的Ingress 上 ,因为Ingress 分别管理着一组pod资源 ---->   通过service 对这些pod进行分组传给Ingress 引用

那么下来我们要使用Ingress这个功能,我们要去创建一个Ingress Controller Pod  而后我们要定义后端的service 在将他们之间建立联系。我们下来看一个Ingress怎么定义 ?  Ingress 也是标准的K8s资源 。我们一样使用explain的文档去查看类似的参数的定义,同样在包含的资源的清单中也会有: apiVersion kind metadata spec status

[root@server1 ~]# kubectl explain ingress
KIND:     Ingress
VERSION:  extensions/v1beta1

DESCRIPTION:
     Ingress is a collection of rules that allow inbound connections to reach
     the endpoints defined by a backend. An Ingress can be configured to give
     services externally-reachable urls, load balance traffic, terminate SSL,
     offer name based virtual hosting etc.

FIELDS:
   apiVersion    <string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#resources

   kind    <string>
     Kind is a string value representing the REST resource this object
     represents. Servers may infer this from the endpoint the client submits
     requests to. Cannot be updated. In CamelCase. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

   metadata    <Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata

   spec    <Object>
     Spec is the desired state of the Ingress. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status

   status    <Object>
     Status is the current state of the Ingress. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status


spec字段的定义:

[root@server1 ~]# kubectl explain ingress.spec  
KIND:     Ingress
VERSION:  extensions/v1beta1

RESOURCE: spec <Object>

DESCRIPTION:
     Spec is the desired state of the Ingress. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status

     IngressSpec describes the Ingress the user wishes to exist.

FIELDS:
   backend    <Object>        定义调度的后端的主机 ,正是靠service的定义,找到相关的一组pod资源
     A default backend capable of servicing requests that don't match any rule.
     At least one of 'backend' or 'rules' must be specified. This field is
     optional to allow the loadbalancer controller or defaulting logic to
     specify a global default.

   rules    <[]Object>              定义http的规则
     A list of host rules used to configure the Ingress. If unspecified, or no
     rule matches, all traffic is sent to the default backend.

   tls    <[]Object>
     TLS configuration. Currently the Ingress only supports a single TLS port,
     443. If multiple members of this list specify different hosts, they will be
     multiplexed on the same port according to the hostname specified through
     the SNI TLS extension, if the ingress controller fulfilling the ingress
     supports SNI.

Ingress 有很多种类型,要么是映射的,要么是虚拟主机的,那么下来我们要看一下怎么部署一个Ingress Controller ,对k8s而言Ingress是作为附件存在的 ,整个K8s集群由: master node + 附件组成的。 附件: coredns +  .. + Dashborad + Ingress

那么Ingress是一个集群的核心附件之一,下来我们实际的部署一个Ingress + nginx

第一步:  创建名称空间 

示例:  使用命令创建名称空间:

[root@server1 ~]# kubectl create namespace dev
namespace/dev created

[root@server1 ~]# kubectl get ns
NAME          STATUS    AGE
default       Active    17d
dev           Active    18s
kube-public   Active    17d
kube-system   Active    17d

删除一个名称空间 :   名称空间/名称空间的名字

[root@server1 ~]# kubectl delete ns/dev
namespace "dev" deleted

第二步:  创建一个configmap      作用: 为Nginx 从外部注入配置

第三步:  rbac  我们集群用到了 rbac    作用: 它是用来定义一些 cluster 角色、 授权 (必要的授予一个pod到达不了它本来访问的名称空间的权限)

第四步:  rbac 启用以后,要创建 with-rbac 包括: 使用的镜像

第五步:  我们有可能要为其配置一个tcp-service-configmap 的资源

 

那么git 到本地可能会很慢,我们直接将其配置文件复制到本地 :

1. 创建名称空间 :               方法一:

[root@server1 ~]# kubectl create namespace ingress-nginx
namespace/ingress-nginx created

                                           方法二:

注意: 在git 上将文件托下来的时候,一定要使用 raw 格式的数据,这样下载下来的才是一个原始的代码数据,要不然只能是一个html的页面。

那么我们复制连接的地址:https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/namespace.yaml

[root@server1 ~]# mkdir ingress-nginx
[root@server1 ~]# cd ingress-nginx/
[root@server1 ingress-nginx]# ls

[root@server1 ingress-nginx]# for file in namespace.yaml configmap.yaml  rbac.yaml with-rbac.yaml ; do wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/$file; done

[root@server1 ingress-nginx]# ls
configmap.yaml  namespace.yaml  rbac.yaml  with-rbac.yaml

下载完成以后我们要先执行namespace

[root@server1 ingress-nginx]# kubectl apply -f namespace.yaml
namespace/ingress-nginx created

后面的文件的先后关系没有那么重要   我们期望去按照某种顺序的时候,可以使用for循环

apply是针对目录的,它会自动的引用目录下的所有文件

[root@server1 ingress-nginx]# kubectl apply -f ./
configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
namespace/ingress-nginx configured
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

在查看的时候这个镜像正在下载,那么我们不用直接等待,因为我最初在搭建的时候没有使用代理,所以可能k8s.io上的镜像会托不下来,我们等会来检查一下

[root@server1 ingress-nginx]# kubectl get pods -n ingress-nginx
NAME                                        READY     STATUS              RESTARTS   AGE
nginx-ingress-controller-769d8b56b7-scqh6   0/1       ContainerCreating   0          1m

经过后期的检查发现这个镜像位于github上,完全可以托下来,是严重不用担心

[root@server1 ingress-nginx]# kubectl get pods -n ingress-nginx
NAME                                        READY     STATUS    RESTARTS   AGE
nginx-ingress-controller-769d8b56b7-scqh6   1/1       Running   0          7m

那么我们试着去创建 Ingress ,  为了 ingress 可以显示出来效果,那么我们可以部署一下后端的服务 ,自定义一个配置清单的Ingress Controller的控制器

那么因为资源清单会随着需求创建得越来越多,因此我们在创建资源得清单得时候,我们要做好把我们得配置文件归类得准备

[root@server1 ingress]# pwd
/root/mainfests/ingress

在部署控制器之前,我们得部署一个后端得service 或者pod  为ingress控制器做准备 ,那么在使用Pod控制器创建pod得使用我们要在控制器之上创建一个service ,那么Service得定义我们在官方的文档中查看发现必须是Headlist ,否则无法解析到pod的节点的ip地址。

apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: default
spec:
  selector:
    app: myapp
    release: canary
  ports:
  - name: http
    targetPort: 80

    port: 80

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp

        release: canary
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v2
        ports:
        - name: http
          containerPort: 80

[root@server1 ingress]# kubectl apply  -f deploy-demo.yaml
service/myapp created
deployment.apps/myapp-deploy unchanged

[root@server1 ingress]# kubectl get svc             查看 svc的ClusterIP的类型,那么在现在的我们看到的是并不是无头的,那么使用这个我们来测试一下(我记得之前没有指定就是ClusterIP )
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP    17d
myapp        ClusterIP   10.105.120.214   <none>        80/TCP     29s
myapp-svc    ClusterIP   None             <none>        80/TCP     10d
redis        ClusterIP   10.97.97.97      <none>        6379/TCP   10d
[root@server1 ingress]#

 

那么我们来回顾一下刚才的github上面的文件,里面有一个叫作: mandatory.yaml  这个文件是将所有的文件拼在一mandatory.yaml个文件当中,使用这一个文件我们就可以创建ingress的全部的事情。比手动的拼凑要更简单一些

 

下来我们要为我们的Ingress Controller创建一个 service NodePort ,否则 Ingress Controller是无法被集群外部的客户访问的 :

但是网上有现成的NodePort的资源配置清单,因此我们直接下载下来就可以了

[root@server1 ingress]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/provider/baremetal/service-nodeport.yaml

apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
spec:
  type: NodePort
  ports:
    - name: http
      port: 80       
      targetPort: 80
      protocol: TCP
      nodePort: 30080                我们指定的节点暴露的端口
    - name: https
      port: 443
      targetPort: 443                后端的nginx的端口
      protocol: TCP
      nodePort: 30443               指定Nginx暴露的端口
  selector:
      app: ingress-nginx
---

[root@server1 ingress]# kubectl apply -f ./
service/myapp unchanged
deployment.apps/myapp-deploy unchanged
service/ingress-nginx created

[root@server1 ingress]# kubectl get svc -n ingress-nginx
NAME            TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx   NodePort   10.105.174.166   <none>        80:30080/TCP,443:30443/TCP   4m

现在我们就可以在集群的外部尝试访问一下我们的Ingress 的服务 :

但是按理来说应该出现正常的调度:  出现的应该是  default  backed - 404   但是却出现的是根本就访问不了这个30080的端口 ,提示:端口不能正常的访问,  那 继续向下  ,看看这个问题到后面能不能解决 ?

 

下来我们将我们的myapp关联到nginx上 :

[root@server1 ingress-nginx]# kubectl describe svc myapp
Name:              myapp
Namespace:         default
Labels:            <none>
Annotations:       kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"myapp","namespace":"default"},"spec":{"ports":[{"name":"http","port":80,"targe...
Selector:          app=myapp,release=canary
Type:              ClusterIP
IP:                10.105.120.214
Port:              http  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.1.102:80,10.244.1.103:80,10.244.2.99:80
Session Affinity:  None
Events:            <none>

 

[root@server1 ingress]# vim ingress-myapp.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-myapp
  namespace: default
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: myapp.magedu.com
    http:
      paths:
      - path:
        backend:
          serviceName: myapp
          servicePort: 80

[root@server1 ingress]# kubectl apply -f ingress-myapp.yaml
ingress.extensions/ingress-myapp created

[root@server1 ingress]# kubectl get ingress
NAME            HOSTS              ADDRESS   PORTS     AGE
ingress-myapp   myapp.magedu.com             80        13s

[root@server1 ingress]# kubectl describe ingress ingress-myapp           这个ingress一旦创建了以后会自动的注入到 ingress Controller中去, 会自动的转换成nginx的配置文件
Name:             ingress-myapp
Namespace:        default
Address:          
Default backend:  default-http-backend:80 (<none>)
Rules:
  Host              Path  Backends
  ----              ----  --------
  myapp.magedu.com  
                       myapp:80 (<none>)
Annotations:
  kubectl.kubernetes.io/last-applied-configuration:  {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{"kubernetes.io/ingress.class":"nginx"},"name":"ingress-myapp","namespace":"default"},"spec":{"rules":[{"host":"myapp.magedu.com","http":{"paths":[{"backend":{"serviceName":"myapp","servicePort":80},"path":null}]}}]}}

  kubernetes.io/ingress.class:  nginx
Events:
  Type    Reason  Age   From                      Message
  ----    ------  ----  ----                      -------
  Normal  CREATE  49s   nginx-ingress-controller  Ingress default/ingress-myapp
[root@server1 ingress]#

[root@server1 ingress]# kubectl exec  -n ingress-nginx -it  nginx-ingress-controller-769d8b56b7-scqh6 -- /bin/sh
$ cat nginx.conf                   使用交互式的命令进入到pod内部去,查看nginx的配置文件中有没有我们定义的

# Configuration checksum: 3855965695233399109

    server {
        server_name myapp.magedu.com ;
        
        listen 80;
        


注意:nginx的负载是以域名进行负载的,因此我们必须要注意解析到本地的节点,

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


更多精彩内容