Kubernetes入门 十二、网络之Ingress

目录

  • 概述
  • 安装 Ingress
  • 使用 Ingress
    • 准备工作
    • 部署Ingress
    • 设置默认后端
    • Ingress 中的 nginx 的全局配置
    • 限流
    • 路径重写
    • 基于 Cookie 的会话保持技术
    • 配置 SSL

概述

通常情况下,service 和 pod 的 IP 仅可在集群内部访问。

Service 可以也使用 NodePort 暴露集群外访问端口,集群外部的请求需要通过负载均衡转发到 service 在 Node 上暴露的 NodePort 上,然后再由 kube-proxy 通过边缘路由器 (edge router) 将其转发给相关的 Pod 或者丢弃。但是这样性能低、不安全并且端口的范围有限。

Service 缺少七层(OSI 网络模型)的统一访问入口,负载均衡能力很低,不能做限流、验证非法用户、链路追踪等等。

而 Ingress 就是为进入集群的请求提供路由规则的集合,如下图所示:

Kubernetes入门 十二、网络之Ingress_第1张图片

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

可以说,Ingress更像是取代了传统nginx,或者说nginx是Ingress的实现之一。

安装 Ingress

Ingress 正常工作需要集群中运行 Ingress Controller。Ingress Controller 与其他作为 kube-controller-manager 中的在集群创建时自动启动的 controller 成员不同,需要用户选择最适合自己集群的 Ingress Controller,或者自己实现一个。

Ingress Controller 以 Kubernetes Pod 的方式部署,以 daemon 方式运行,保持 watch Apiserver 的 /ingress 接口以更新 Ingress 资源,以满足 Ingress 的请求。

K8提供的Controller有很多,具体可以到官网看。

下面以ingress nginx 为例。它是 k8s 官方出品的,会及时更新一些特性,性能很高,被广泛采用。

  1. 安装helm

Helm是Kubernetes的包管理器,类似于Python的pip centos的yum,主要用来管理 Charts。后面还会有专门章节介绍。

下载二进制文件

https://get.helm.sh/helm-v3.2.3-linux-amd64.tar.gz

解压:

tar -zxvf helm-v3.10.2-linux-amd64.tar.gz

我是Mac,直接使用brew安装也可以:

brew install helm
  1. 添加仓库
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx

查看仓库列表

helm repo list

搜索 ingress-nginx

helm search repo ingress-nginx
  1. 下载安装包
helm pull ingress-nginx/ingress-nginx

将下载好的安装包解压

tar xf ingress-nginx-xxx.tgz
  1. 配置参数

解压后,进入解压完成的目录

cd ingress-nginx

修改 values.yaml
镜像地址:修改为国内镜像

registry: [registry.cn-hangzhou.aliyuncs.com](http://registry.cn-hangzhou.aliyuncs.com)
image: google_containers/nginx-ingress-controller

# 注意下面还有一个
registry: [registry.cn-hangzhou.aliyuncs.com](http://registry.cn-hangzhou.aliyuncs.com)
image: google_containers/kube-webhook-certgen

修改tag:

# 也有两个地方修改
tag: v1.3.0

还有如下配置修改:

hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet

# 修改部署配置的 
kind: DaemonSet
nodeSelector:
 ingress: "true" # 增加选择器,如果 node 上有 ingress=true 就部署
# 将 admissionWebhooks.enabled 修改为 false
admissionWebhooks.enabled: false
# 将 service 中的 type 由 LoadBalancer 修改为 ClusterIP,如果服务器是云平台才用 LoadBalancer
service:
	type: ClusterIP
  1. 为 ingress 专门创建一个 namespace

    kubectl create ns ingress-nginx
    
  2. 为需要部署 ingress 的节点上加标签

    kubectl label node k8s-node1 ingress=true
    
  3. 安装 ingress-nginx

    helm install ingress-nginx ./ingress-nginx -n ingress-nginx
    
  4. 检查

kubectl get po -n  ingress-nginx
# 结果如下
NAME                             READY   STATUS    RESTARTS   AGE
ingress-nginx-controller-9kp22   1/1     Running   0          116m

使用 Ingress

参考:https://www.yuque.com/fairy-era/yg511q/ed952r#a708d224

准备工作

为了后面的实验比较方便,创建如下图所示的模型:

Kubernetes入门 十二、网络之Ingress_第2张图片

创建实验所需的 Service 以及 Pod 等:

vi k8s-prepare.yaml

内容如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  namespace: default
  labels:
    app: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.20.2
          resources:
            requests:
              cpu: 100m
              memory: 100Mi
            limits:
              cpu: 250m
              memory: 500Mi
          ports:
            - containerPort: 80
              name: nginx
          volumeMounts:
            - name: localtime
              mountPath: /etc/localtime
      volumes:
        - name: localtime
          hostPath:
            path: /usr/share/zoneinfo/Asia/Shanghai
      restartPolicy: Always

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-deploy
  namespace: default
  labels:
    app: tomcat
spec:
  selector:
    matchLabels:
      app: tomcat
  replicas: 3
  template:
    metadata:
      labels:
        app: tomcat
    spec:
      containers:
        - name: tomcat
          image: tomcat:9-jre8
          env:
            - name: JAVA_OPTS
              value: "-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap"
          resources:
            requests:
              cpu: 500m
              memory: 256Mi
            limits:
              cpu: 500m
              memory: 500Mi
          ports:
            - containerPort: 8080
              name: tomcat
          volumeMounts:
            - name: localtime
              mountPath: /etc/localtime
      volumes:
        - name: localtime
          hostPath:
            path: /usr/share/zoneinfo/Asia/Shanghai
      restartPolicy: Always

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

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

部署:

kubectl apply -f k8s-prepare.yaml

部署Ingress

Ingress基本配置如下:

  • 语法:
apiVersion: networking.k8s.io/v1
kind: Ingress 
metadata:
  name: ingress-http
  namespace: default
  annotations: 
    kubernetes.io/ingress.class: "nginx"
spec:
  rules: # 规则
  - host: it.nginx.com # 指定的监听的主机域名,相当于 nginx.conf 的 server { xxx }
    http: # 指定路由规则
      paths:
      - path: /
        pathType: Prefix # 匹配规则,Prefix 前缀匹配 it.nginx.com/* 都可以匹配到
        backend: # 指定路由的后台服务的 service 名称
          service:
            name: nginx-svc # 服务名
            port:
              number: 80 # 服务的端口

pathType说明:

    • Prefix:基于以 / 分隔的 URL 路径前缀匹配。匹配区分大小写,并且对路径中的元素逐个完成。 路径元素指的是由 / 分隔符分隔的路径中的标签列表。 如果每个 p 都是请求路径 p 的元素前缀,则请求与路径 p 匹配。
    • Exact:精确匹配 URL 路径,且区分大小写。
    • ImplementationSpecific:对于这种路径类型,匹配方法取决于 IngressClass。 具体实现可以将其作为单独的 pathType 处理或者与 Prefix 或 Exact 类型作相同处理。

注意:ingress 规则会生效到所有安装了 IngressController 的机器的 nginx 配置。

  • 示例:
vi k8s-ingress.yaml

部署:

apiVersion: networking.k8s.io/v1
kind: Ingress 
metadata:
  name: ingress-http
  namespace: default
  annotations: 
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTP"  
spec:
  rules: # 规则
  - host: nginx.xudaxian.com # 指定的监听的主机域名,相当于 nginx.conf 的 server { xxx }
    http: # 指定路由规则
      paths:
      - path: /
        pathType: Prefix # 匹配规则,Prefix 前缀匹配 nginx.xudaxian.com/* 都可以匹配到
        backend: # 指定路由的后台服务的 service 名称
          service:
            name: nginx-svc # 服务名
            port:
              number: 80 # 服务的端口
  - host: tomcat.xudaxian.com # 指定的监听的主机域名,相当于 nginx.conf 的 server { xxx }
    http: # 指定路由规则
      paths:
      - path: /
        pathType: Prefix # 匹配规则,Prefix 前缀匹配 tomcat.xudaxian.com/* 都可以匹配到
        backend: # 指定路由的后台服务的 service 名称
          service:
            name: tomcat-svc # 服务名
            port:
              number: 8080 # 服务的端口
kubectl apply -f k8s-ingress.yaml

示例的示意图:

Kubernetes入门 十二、网络之Ingress_第3张图片

  • 测试示例(后面有更简单的测试方法):

  • 第一种方案:

    • ① 在 win 中的 hosts(C:\Windows\System32\drivers\etc\hosts) 文件中添加如下的信息:
# 用来模拟 DNS ,其中 192.168.65.101 是 ingress 部署的机器,nginx.xudaxian.com 和 tomcat.xudaxian.com 是 ingress 文件中监听的域名
192.168.65.101 nginx.xudaxian.com
192.168.65.101 tomcat.xudaxian.com
    • ② 在 win 中使用 curl 命令:

Kubernetes入门 十二、网络之Ingress_第4张图片

为什么这么干?因为我使用了科学上网,网络出现了问题。

  • 第二种方案:

    • ① 重新建立一个虚拟机(安装有 CentOS7 系统,并且带有桌面),在 hosts (/etc/hosts)文件中添加如下的内容:
# 用来模拟 DNS ,其中 192.168.65.101 是 ingress 部署的机器,nginx.xudaxian.com 和 tomcat.xudaxian.com 是 ingress 文件中监听的域名
192.168.65.101 nginx.xudaxian.com
192.168.65.101 tomcat.xudaxian.com
    • ② 通过浏览器访问:

Kubernetes入门 十二、网络之Ingress_第5张图片

  • 证明:ingress 规则会生效到所有安装了 IngressController 的机器的 nginx 配置
cat nginx.conf |  grep nginx.xudaxian.com -A 20

Kubernetes入门 十二、网络之Ingress_第6张图片

设置默认后端

  • 示例:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-http
  namespace: default
  annotations: 
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTP"  
spec:
  defaultBackend: # 指定所有未匹配的默认后端
    service:
      name: nginx-svc
      port:
        number: 80
  rules: 
    - host: tomcat.com 
      http: 
        paths:
          - path: /abc
            pathType: Prefix 
            backend: 
              service:
                name: tomcat-svc
                port:
                  number: 8080

效果:

  • tomcat.com 域名的 非 /abc 开头的请求,都会转到 defaultBackend 。

  • 非 tomcat.com 域名下的所有请求,也会转到 defaultBackend 。

Ingress 中的 nginx 的全局配置

官方文档

  • 方式一:在安装的时候,添加配置。
apiVersion: v1
data:
  allow-snippet-annotations: "true" # Nginx 的全局配置
kind: ConfigMap
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.1.2
    helm.sh/chart: ingress-nginx-4.0.18
  name: ingress-nginx-controller
  namespace: ingress-nginx
  • 方式二:编辑 cm :
kubectl edit cm ingress-nginx-controller -n ingress-nginx
# 配置项加上 
data:
  map-hash-bucket-size: "128" # Nginx 的全局配置
  ssl-protocols: SSLv2

限流

官方文档

  • 示例:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: rate-ingress
  namespace: default
  annotations: # https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#rate-limiting
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTP"  
    nginx.ingress.kubernetes.io/limit-rps: "1" # 限流
spec:
  rules:
  - host: nginx.xudaxian.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-svc
            port:
              number: 80

路径重写

官方文档

路径重写,经常用于前后端分离。

Kubernetes入门 十二、网络之Ingress_第7张图片

  • 示例:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-rewrite
  namespace: default
  annotations:
   nginx.ingress.kubernetes.io/rewrite-target: /$2 # 路径重写
spec:
  ingressClassName: nginx
  rules:
  - host: baidu.com
    http:
      paths:
      - path: /api(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: nginx-svc
            port:
              number: 80

基于 Cookie 的会话保持技术

Service 只能基于 ClientIP,但是 ingress 是七层负载均衡,可以基于 Cookie 实现会话保持。

  • 示例:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: rate-ingress
  namespace: default
  annotations: # https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#rate-limiting
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTP"  
    nginx.ingress.kubernetes.io/affinity: "cookie"
spec:
  rules:
  - host: nginx.xudaxian.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-svc
            port:
              number: 80

配置 SSL

官方地址

  • 生成证书语法:
$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ${KEY_FILE} -out ${CERT_FILE} -subj "/CN=${HOST:baidu.com}/O=${HOST:baidu.com}"
kubectl create secret tls ${CERT_NAME:baidu-tls} --key ${KEY_FILE:tls.key} --cert ${CERT_FILE:tls.cert}
  • 示例:生成证书
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.cert -subj "/CN=xudaxian.com/O=xudaxian.com"
kubectl create secret tls xudaxian-tls --key tls.key --cert tls.cert

Kubernetes入门 十二、网络之Ingress_第8张图片

  • 示例:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-tls
  namespace: default
  annotations: 
    kubernetes.io/ingress.class: "nginx"  
spec:
  tls:
  - hosts:
      - nginx.xudaxian.com # 通过浏览器访问 https://nginx.xudaxian.com
      - tomcat.xudaxian.com # 通过浏览器访问 https://tomcat.xudaxian.com
    secretName: xudaxian-tls
  rules:
  - host: nginx.xudaxian.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-svc
            port:
              number: 80
  - host: tomcat.xudaxian.com 
    http: 
      paths:
      - path: /
        pathType: Prefix 
        backend:
          service:
            name: tomcat-svc 
            port:
              number: 8080

注意:实际开发的时候,需要自己购买证书。

你可能感兴趣的:(K8S入门与实战,kubernetes,容器,云原生)