1. Service

1.1. Service 介绍

Pod控制器实现了对一组pod的版本、副本数和配置的控制,但是Pod本身被创建和消除会导致IP地址不断变化,Service为一组pod提供了一个固定的VIP,所有通过该VIP地址的请求都会被转发到后端的pod上。Service是工作在四层网络之上的,支持三种工作模式。在 Kubernetes v1.0 版本,代理完全在 userspace。在 Kubernetes v1.1 版本,新增了 iptables 代理,但并不是默认的运行模式。 从 Kubernetes v1.2 起,默认就是 iptables 代理。在Kubernetes v1.8.0-beta.0中,添加了ipvs代理。在未来,EBPF 将会成为更高性能的SVC工作模式,但是目前还不够成熟。

1.1.1.userspace模式

客户端请求到内核空间后,由iptables规则将其转发到用户空间的 kube-proxy,kube-proxy 将其调度到各个node上的目标Pod。这种模式需要多次切换用户空间和内核空间,性能很差,生产环境不再使用。
03-4-服务发现 - 图1

1.1.2. iptables模式

iptables模式中,客户端的请求进入内核态后,直接由iptables将请求转发到各个pod上,这种模式中随着iptables规则的增加,性能越来越差,而且iptables规则查看和管理难度很大,生产环境中尽量少用。
03-4-服务发现 - 图2

1.1.3. ipvs模式

ipvs模式中,客户端的请求进入内核态后,直接由ipvs规则将请求转发到各个pod上,这种模式相当于内嵌一套lvs集群,性能比iptables强大,更重要的是支持lvs中调度算法,生产环境中ipvs模式优先考虑使用。ipvs内部时使用ipset维护映射关系,由于是hash链表,因此查询速度远远大于iptables的遍历速度。
03-4-服务发现 - 图3

1.2. 模板

  1. apiVersion: v1
  2. kind: Service
  3. metadata
  4. name <string> # 在一个名称空间不能重复
  5. namespace <string> # 指定名称空间,默认defalut
  6. labels <map[string]string> # 标签
  7. annotations <map[string]string> # 注释
  8. spec
  9. selector <map[string]string> # 仅支持key/value方式定义选择器
  10. type <string> # service暴露方式
  11. # ClusterIP: 通过集群的VIP方式,这种方式下仅能在集群内部访问,默认值
  12. # NodePort: 通过暴露node端口来将流量路由到clusterIP,从而实现从集群外部访问service功能,且需要宿主机开启监听端口,容易出现端口冲突
  13. # LoadBalancer: 使用云提供商的负载均衡器,可以向外部暴露服务。外部的负载均衡器可以路由到NodePort服务和ClusterIP服务
  14. # ExternalName: 通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容
  15. clusterIP <string> # 定义集群VIP地址
  16. # 当指定确定IP地址时,会以该IP地址为准
  17. # 当指定为None时,为 headless service
  18. ports <[]Object> # 指定端口映射
  19. name <string> # 端口名称
  20. port <integer> -required-# 指定service端口
  21. targetPort <string> # 指定pod端口
  22. nodePort <integer> # 指定node端口,仅在NodePort类型使用.3000-29999之间
  23. sessionAffinity <string> # 是否启用粘性会话,

1.3. 案例

为了测试方便,先部署测试使用的 deployment :

# deploy-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  namespace: default
spec:
  replicas: 5
  selector:
    matchLabels:
      app: nginx
      release: stable
      tier: slb
      partition: website
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: nginx
        release: stable
        tier: slb
        partition: website
        version: v1.12
    spec:
      containers:
      - name: nginx-pod
        image: linuxduduniao/nginx:v1.0.3

1.3.1. 不指定VIP的service

这种模式是生产中使用最多的,由集群内部访问时通过service域名解析得到cluster IP,客户端访问cluster IP时,系统会通过iptable或者ipvs将流量负载均衡到后端Pod上。

# svc-no-vip.yaml
apiVersion: v1
kind: Service
metadata:
  name: slb-s1
  namespace: default
spec:
  selector:
    app: nginx
    release: stable
    partition: website
    tier: slb
  ports:
  - name: http
    port: 80
    targetPort: 80
[root@duduniao nginx-01]# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
slb-s1       ClusterIP   10.100.138.11   <none>        80/TCP    51m

# 在node节点查看 IPVS 规则
[root@master_01_vm_160_10 ~]# ipvsadm -ln
TCP  10.100.138.11:80 rr
  -> 10.200.3.10:80               Masq    1      0          0
  -> 10.200.4.8:80                Masq    1      0          0
  -> 10.200.4.9:80                Masq    1      0          0
  -> 10.200.5.10:80               Masq    1      0          0
  -> 10.200.5.11:80               Masq    1      0          0

[root@duduniao yaml]# kubectl describe svc slb-s1
Name:              slb-s1
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx,partition=website,release=stable,tier=slb
Type:              ClusterIP
IP Families:       <none>
IP:                10.100.138.11
IPs:               10.100.138.11
Port:              http  80/TCP
TargetPort:        80/TCP
Endpoints:         10.200.3.10:80,10.200.4.8:80,10.200.4.9:80 + 2 more...
Session Affinity:  None
Events:            <none>
# 在node节点使用VIP访问测试
[root@master_01_vm_160_10 ~]# curl 10.100.138.11/info
2021-10-13T07:24:43+00:00|v1.0.3|nginx-deploy-699fdd685d-8nb5w|ok
[root@master_01_vm_160_10 ~]# curl 10.100.138.11/info
2021-10-13T07:24:45+00:00|v1.0.3|nginx-deploy-699fdd685d-ffswz|ok

# 在pod中测试域名解析
[root@nginx-deploy-699fdd685d-4zgtx /]# curl -s http://slb-s1.default.svc.cluster.local/info  # 全域名
2021-10-13T07:28:19+00:00|v1.0.3|nginx-deploy-699fdd685d-lsv9q|ok
[root@nginx-deploy-699fdd685d-4zgtx /]# curl -s http://slb-s1/info  # 短域名
2021-10-13T07:27:57+00:00|v1.0.3|nginx-deploy-699fdd685d-ffswz|ok

1.3.2. 指定VIP的service

大部分情况下,不需要指定vip,因为内部pod通过域名的方式访问service,此处只是作为演示。

# svc-vip.yaml
apiVersion: v1
kind: Service
metadata:
  name: slb-s2
  namespace: default
spec:
  selector:
    app: nginx
    release: stable
    partition: website
    tier: slb
  clusterIP: 10.100.138.12
  ports:
  - name: http
    port: 80
    targetPort: 80
[root@duduniao nginx-01]# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.100.0.1      <none>        443/TCP   13d
slb-s1       ClusterIP   10.100.138.11   <none>        80/TCP    64m
slb-s2       ClusterIP   10.100.138.12   <none>        80/TCP    7s

[root@duduniao nginx-01]# kubectl describe svc slb-s2
Name:              slb-s2
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx,partition=website,release=stable,tier=slb
Type:              ClusterIP
IP Families:       <none>
IP:                10.100.138.12
IPs:               10.100.138.12
Port:              http  80/TCP
TargetPort:        80/TCP
Endpoints:         10.200.3.10:80,10.200.4.8:80,10.200.4.9:80 + 2 more...
Session Affinity:  None
Events:            <none>

1.3.3. 使用NodePort的service

这种Service会占用宿主机的端口,默认可用的端口范围在 30000-32767 之间,可以在安装apiserver时修改。
NodePort使用场景是将集群内部服务暴露给集群外面使用的一种方案,在生产集群中,其实对集群外暴露的服务非常少,并且向外暴露服务由两种方案:NodePort 和 Ingress。
NodePort主要用于Ingress不能满足的场景,比如TCP/UDP 服务暴露到集群,或者涉及复杂的http rewriete 规则,使用Ingress过于复杂。

# svc-node-port.yaml
apiVersion: v1
kind: Service
metadata:
  name: slb-s3
  namespace: default
spec:
  selector:
    app: nginx
    release: stable
    partition: website
    tier: slb
  type: NodePort
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30012
[root@duduniao nginx-01]# kubectl get svc |grep slb-s3
slb-s3       NodePort    10.100.218.132   <none>        80:30012/TCP   48s
[root@duduniao nginx-01]# kubectl describe svc slb-s3
Name:                     slb-s3
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 app=nginx,partition=website,release=stable,tier=slb
Type:                     NodePort
IP Families:              <none>
IP:                       10.100.218.132
IPs:                      10.100.218.132
Port:                     http  80/TCP
TargetPort:               80/TCP
NodePort:                 http  30012/TCP
Endpoints:                10.200.3.10:80,10.200.4.8:80,10.200.4.9:80 + 2 more...
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

[root@master_01_vm_160_10 ~]# netstat -lntp | grep 30012  # 在宿主机上开启3080端口,实现了集群外访问,注意避免端口冲突
tcp        0      0 0.0.0.0:30012           0.0.0.0:*               LISTEN      10808/kube-proxy

[root@duduniao nginx-01]# curl http://10.0.160.30:30012/info # 集群外访问测试
2021-10-13T07:51:09+00:00|v1.0.3|nginx-deploy-699fdd685d-8nb5w|ok

1.3.4. Headless service

Headless service并不对外提供Cluster IP能力,它提供的是服务发现功能,通过dns解析svc域名,得到对应的endpoint的Pod地址。最终由客户端自行决定如何处理这些Pod地址。
除此之外,Headless service 后端Pod每个都具备对应的域名,可以直接通过域名来相互访问,因此在 statefulset 中用这种service

# svc-headless.yaml
apiVersion: v1
kind: Service
metadata:
  name: slb-s4
  namespace: default
spec:
  selector:
    app: nginx
    release: stable
    partition: website
    tier: slb
  clusterIP: None
  ports:
  - name: http
    port: 80
    targetPort: 80
[root@master_01_vm_160_10 ~]# dig +short -t A slb-s1.default.svc.cluster.local @10.100.0.2
10.100.138.11
[root@master_01_vm_160_10 ~]# dig +short -t A slb-s4.default.svc.cluster.local @10.100.0.2
10.200.4.9
10.200.4.8
10.200.5.10
10.200.5.11
10.200.3.10

1.3.5. SVC代理集群外服务

像MySQL集群这种对性能要求很高的有状态应用,并不是很推荐在Kuberentes中部署,业务程序想要使用集群外部的MySQL实例可以通过配置文件或者环境变量指定MySQL地址。
为了统一集群内服务访问方式,部分公司会使用Kubernetes中SVC去代理集群外中间件流量,这样访问集群外中间件就如同访问集群的中间件。实现方式很简单,只需要指定SVC和对应Endpoint,并且Endpoint的后端节点为集群外的中间件访问地址和端口。

---
apiVersion: v1
kind: Service
metadata:
  name: rds-devops-01
  namespace: default
spec:
  ports:
  - name: mysql
    port: 3306
---
apiVersion: v1
kind: Endpoints
metadata:
  # Endpoints 的name必须和Service一致,这样才能关联上
  name: rds-devops-01
  namespace: default
subsets:
- addresses:
  - ip: 10.0.160.11
  ports:
  - name: mysql
    port: 3306
---
# 用于作为MySQL客户端进行测试
apiVersion: apps/v1
kind: Deployment
metadata:
  name: rds-client
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: rds-client
  template:
    metadata:
      labels:
        app: rds-client
    spec:
      containers:
      - name: mysql
        image: mysql:5.7
        command: ["sleep", "600"]
# 验证是否可以通过SVC去连接集群外部的数据库
[root@duduniao nginx-01]# kubectl exec -it rds-client-85d97ddb97-sp24g -- bash
root@rds-client-85d97ddb97-sp24g:/# mysql -u root -p -h rds-devops-01 -e "select version();"
Enter password:
+-----------+
| version() |
+-----------+
| 5.7.35    |
+-----------+

2. Ingress

2.1. Ingress/IngressController

Service虽说是为集群内部pod访问一组微服务提供固定接入点,其实NodePort、LoadBalancer方式可以通过在Node上配置端口映射实现外部集群访问内部service。这种方式存在以下问题:

  • 仅支持L4调度,不支持域名和Loctation方式分发流量
  • 对于SSL会话卸载,需要在pod内部完成,比较复杂
  • 当业务数量增加时,容易出现端口冲突

Ingress 是 Kubernetes 的一种 API 对象,是实现HTTP/HTTPS、基于路径和域名进行流量转发的一组规则,实现了将集群外部七层流量转发到集群内部。IngressController是将Ingress规则实现的一种负载均衡器Pod,如Nginx、Traefik、HAProxy等。

IngressController有两种部署方式:一种是采用DaemonSet方式部署,一种是Deployment方式部署。为了降低复杂度,一般都采用DaemonSet方式部署。如下图所示:

  • ingress-controller 采用DaemonSet方式部署在各个node节点之上
  • 集群外部部署一个七层负载均衡,如Nginx。Nginx负责做流量转发和SSL会话卸载
  • ingress-controller根据ingress规则将流量调度到指定的service上
  • 各service再将流量转发到各个pod上

image.png

2.2. 安装IngressController

2.2.1. 选型

image.png

2.2.2. 安装Traefik

2.2.2.1. 使用yaml文件

参考: https://www.yuque.com/duduniao/k8s/tr3hch#x7V9z
参考: https://www.yuque.com/duduniao/k8s/togtwi#htVt7
上述部署方式比较陈旧,推荐使用 helm 部署。

2.2.2.2. 使用helm部署

  1. 安装 heml

helm 安装方式可以参考官方文档

  1. 安装traefik ```yaml

    values.yaml

    image.tag: “v2.5.3”

deployment: kind: DaemonSet additionalVolumes:

- name: traefik-access-log
  hostPath:
    path: /data/logs/traefik
    type: DirectoryOrCreate

初始化容器,用来修改日志目录的权限

initContainers:

- name: volume-permissions
  image: busybox:1.31.1
  command: ["sh", "-c", "chmod -Rv 755 /data/ && chown -R 65532.65532 /data/"]
  volumeMounts:
    - name: traefik-access-log
      mountPath: /data

ingressClass: enabled: true isDefaultClass: true fallbackApiVersion: “v1”

推荐使用域名访问

ingressRoute.dashboard.enabled: false

additionalVolumeMounts:

  • name: traefik-access-log mountPath: /var/log/traefik

logs: general.level: WARN

访问日志配置

access: enabled: true

# 缓冲的行数
bufferingSize: 100
# 指定哪些日志被记录
# 目前不支持过滤掉内部健康检查的日志,并且日志自定义能力很弱,
# 如果前端有LB,那么还得通过 proxyprotocol 获取客户端IP,很麻烦
# 流量下,如果前端有一个Nginx作为LB,甚至可以考虑关闭traefik的日志
filters: 
  statuscodes: "100,300-302,400-404,500-505"    # 状态码范围
  retryattempts: true                           # 是否重试
  minduration: 10ms                             # 响应超过10ms

globalArguments:

  • “—global.checknewversion”
  • “—global.sendanonymoususage”

    从traefik到后端pod的访问中,不校验pod中的TLS证书,这对自签证书的pod很管用

  • “—serversTransport.insecureSkipVerify=true”

    指定访问日志的写入路径,可以用来让 filebeat 采集

    日志轮转是需要cronjob定时发送 USR1 信号给traefik

  • “—accesslog.filepath=/var/log/traefik/access.log”

    访问日志中的时间戳以容器时区为准

  • “—accesslog.fields.names.StartUTC=drop”

env:

指定traefik的时区

  • name: TZ value: Asia/Shanghai

想要性能更高,甚至可以直接使用节点的网络空间

ports: traefik: port: 9000

# 生产环境不推荐暴露9000端口
expose: false
exposedPort: 9000
protocol: TCP

web: port: 8000 hostPort: 80 expose: true exposedPort: 80 protocol: TCP

# redirectTo: websecure

websecure: port: 8443 hostPort: 443 expose: true exposedPort: 443 metrics: port: 9100 expose: false exposedPort: 9100 protocol: TCP

service: type: ClusterIP

resources: requests: cpu: “100m” memory: “512Mi” limits: cpu: “1000m” memory: “1024Mi”

针对指定的 node 才部署 traefik

nodeSelector: ingressControllerNode: “yes” ingressController: “traefik”

```yaml
[root@duduniao ~]# kubectl get node
NAME          STATUS                     ROLES    AGE   VERSION
10.0.160.10   Ready,SchedulingDisabled   master   12d   v1.20.10
10.0.160.13   Ready                      node     12d   v1.20.10
10.0.160.30   Ready,SchedulingDisabled   master   12d   v1.20.10
10.0.160.32   Ready                      node     12d   v1.20.10
10.0.160.50   Ready,SchedulingDisabled   master   12d   v1.20.10
10.0.160.51   Ready                      node     12d   v1.20.10

# 标记作为IngressController的节点, 之所以增加IngressController=traefik,是后续可能会部署多个ingress controller
[root@duduniao ~]# kubectl label nodes 10.0.160.10 ingressControllerNode=yes ingressController=traefik
[root@duduniao ~]# kubectl label nodes 10.0.160.30 ingressControllerNode=yes ingressController=traefik
[root@duduniao ~]# kubectl label nodes 10.0.160.50 ingressControllerNode=yes ingressController=traefik

[root@duduniao ~]# kubectl create namespace traefik

[root@duduniao ~]# helm repo add traefik https://helm.traefik.io/traefik
[root@duduniao ~]# helm repo update

[root@duduniao ~]# helm install -n traefik traefik traefik/traefik -f /tmp/values.yaml

[root@duduniao ~]# kubectl get pod -n traefik -o wide
NAME            READY   STATUS    RESTARTS   AGE   IP            NODE          NOMINATED NODE   READINESS GATES
traefik-2mdzt   1/1     Running   0          13h   10.200.1.18   10.0.160.10   <none>           <none>
traefik-42k4f   1/1     Running   0          13h   10.200.2.17   10.0.160.50   <none>           <none>
traefik-kg7v6   1/1     Running   0          13h   10.200.0.17   10.0.160.30   <none>           <none>
  1. 配置负载均衡器

一般使用ingress controller监听在节点的80后者443端口,80负责HTTP流量,443负责HTTPS流量。用户从集群外面访问集群内业务的API,从安全角度考虑,建议强制走HTTPS协议到达负载均衡器,从负载均衡器到后端ingress controller,可以走HTTP或者HTTPS,推荐在做好安全工作的前提下,推荐走HTTP。针对需要走HTTPS的流量,在负载均衡器上使用更高优先级的虚拟机主机,将流量转发到 ingress controller 的https接口。

# /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
pid /run/nginx.pid;

include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 65535;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    log_format access '$time_local|$http_x_real_ip|$remote_addr|$http_x_forwarded_for|$upstream_addr|$upstream_connect_time|$upstream_response_time|'
                      '$request_method|$server_protocol|$host|$request_uri|$http_referer|$http_user_agent|$proxy_host|$status' ;

    access_log  /var/log/nginx/http-access.log  main;
    error_log /var/log/nginx/http-error.log error;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 4096;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    include /etc/nginx/conf.d/http/*.conf;
}

stream {
    log_format stream '$time_local|$remote_addr|$protocol|$bytes_sent|$bytes_received|$upstream_addr|$upstream_connect_time|$status'

    access_log  /var/log/nginx/stream-access.log  stream;
    error_log /var/log/nginx/stream-error.log error;

    include /etc/nginx/conf.d/stream/*.conf;
}
# 配置默认的转发规则
# /etc/nginx/conf.d/http/default.conf
server {
    listen 0.0.0.0:80 backlog=2048 ;
    server_name *.huanle.com ;
    access_log /var/log/nginx/http-k8s-local-01.log access ;
    rewrite (.*) https://$host$1 redirect ;
}

server {
    listen 0.0.0.0:443 ssl backlog=2048 ;
    server_name *.huanle.com ;
    access_log /var/log/nginx/http-k8s-local-01.log access ;
    keepalive_timeout 100s ;
    keepalive_requests 200 ;
    ssl_certificate ssl_key/huanle.crt ;
    ssl_certificate_key ssl_key/huanle.key ;
    ssl_ciphers HIGH:!aNULL:!MD5 ;
    ssl_session_cache shared:SSL:30m ;  ## 设置SSL session缓存
    ssl_session_timeout 10m ;
    location / {
        proxy_pass http://k8s-local-01-http ;
        proxy_connect_timeout 3 ;
        proxy_read_timeout    10 ;
        proxy_send_timeout    10 ;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr ;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ;
    }
}
# /etc/nginx/conf.d/http/upstream.conf
upstream k8s-local-01-http {
    server 10.0.160.10:80 max_fails=2 fail_timeout=3s;
    server 10.0.160.30:80 max_fails=2 fail_timeout=3s;
    server 10.0.160.50:80 max_fails=2 fail_timeout=3s;
}

upstream k8s-local-01-https {
    server 10.0.160.10:443 max_fails=2 fail_timeout=3s;
    server 10.0.160.30:443 max_fails=2 fail_timeout=3s;
    server 10.0.160.50:443 max_fails=2 fail_timeout=3s;
}

2.3. 模板

apiVersion: extensions/v1beta1
kind: Ingress
metadata
    name        <string>            # 在一个名称空间不能重复
    namespace   <string>            # 指定名称空间,默认defalut
    labels      <map[string]string> # 标签
    annotations <map[string]string> # 注释
spec
    backend                     <Object>                # 后端pod对应的服务,仅在集群中仅单个service暴露时使用
        serviceName             <string> -required-     # 服务名
        servicePort             <string> -required-     # 服务接入端口
    rules                       <[]Object>              # 流量转发规则
        host                    <string>                # 基于server name进行转发
        http                    <Object>                # 基于path路径转发
            paths               <[]Object> -required-   # 指定转发的path路径和后端service
                path            <string>                # 指定path        
                backend         <Object> -required-     # 后端pod对应的服务
                    serviceName <string> -required-     # 服务名
                    servicePort <string> -required-     # 服务接入端口

新版本中, Ingress 的API发生了变化:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata
  name        <string>            # 在一个名称空间不能重复
  namespace   <string>            # 指定名称空间,默认defalut
  labels      <map[string]string> # 标签
  annotations <map[string]string> # 注释
spec
    defaultBackend    <Object>              # 指定默认的后端资源
    resource        <Object>              # 指定的资源对象,和service二选一
      apiGroup      <string>
      kind          <string> -required-
      name          <string> -required-
    service         <Object>              # 指定的svc对象,和service二选一
      name          <string> -required-   # service名称
      port          <Object>              # 指定端口,可以说svc中端口名称,也可以是数字
        name        <string>
        number      <integer>
  ingressClassName  <string>              # 指定使用哪个ingress controller,用于取代注释中的kubernetes.io/ingress.class
  rules             <[]Object>            # 指定路由规则
    host            <string>              # 指定域名,可以使用通配符
    http            <Object>              # 指定http请求转发规则
      paths         <[]Object> -required- # path路径转发规则列表
        backend     <Object> -required-   # 指定后端资源
          resource  <Object>              # 指定的资源对象,和service二选一
          service   <Object>              # 指定的svc对象,和service二选一
        path        <string>              # 指定路径
        pathType    <string>              # path匹配方式
                                          #   Exact: 精准匹配; Prefix: 前缀匹配; ImplementationSpecific: 由ingress Controller决定
  tls               <[]Object>            # 指定TLS配置
    hosts           <[]string>            # 使用TLS加密的主机名
    secretName      <string>              # 指定证书的secret

2.4. 案例

为了演示方便,先部署简单的测试用例的svc:

# deploy-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  namespace: default
spec:
  replicas: 5
  selector:
    matchLabels:
      app: nginx
      release: stable
      tier: slb
      partition: website
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: nginx
        release: stable
        tier: slb
        partition: website
        version: v1.12
    spec:
      containers:
      - name: nginx-pod
        image: linuxduduniao/nginx:v1.0.3
---
# svc-demo.yaml
apiVersion: v1
kind: Service
metadata:
  name: slb-s1
  namespace: default
spec:
  selector:
    app: nginx
    release: stable
    partition: website
    tier: slb
  ports:
  - name: http
    port: 80
    targetPort: 80

2.4.1. http请求

  • 配置Ingress配置http代理:

    # ingree-demo-http.yaml
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: slb-s1
    namespace: default
    annotations:
      # 因为安装traefik时候创建了 ingressClass 资源,因此不需要依赖注释中的 kubernetes.io/ingress.class
      # kubernetes.io/ingress.class: traefik
      traefik.ingress.kubernetes.io/router.entrypoints: web
    spec:
    ingressClassName: traefik
    rules:
    - host: slb-s1-http.huanle.com
      http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: slb-s1
              port:
                name: http
    
  • 测试

    # 通过LB的VIP 10.0.160.252 去访问测试的ingress域名
    [root@duduniao yaml]# curl -L http://10.0.160.252/info -H 'Host: slb-s1-http.huanle.com'
    2021-10-13T06:40:02+00:00|v1.0.3|nginx-deploy-699fdd685d-mqw4m|ok
    [root@duduniao yaml]# curl -Lk https://10.0.160.252/info -H 'Host: slb-s1-http.huanle.com'
    2021-10-13T06:40:24+00:00|v1.0.3|nginx-deploy-699fdd685d-mqw4m|ok
    

    2.4.2. https请求

    ```yaml


apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: slb-s1-https namespace: default annotations:

# kubernetes.io/ingress.class: traefik
# 使用https,走websecure,必须要指定router.tls: true
traefik.ingress.kubernetes.io/router.tls: "true"
traefik.ingress.kubernetes.io/router.entrypoints: websecure

spec: ingressClassName: traefik rules:

  • host: slb-s1-https.huanle.com http: paths:
    • path: / pathType: Prefix backend: service:
      name: slb-s1
      port:
        name: http
      
      tls:
  • hosts:
    • slb-s1-https.huanle.com secretName: huanle-com-tls

TLS 证书, 证书和私钥必须是 base64 编码之后的文本

apiVersion: v1 kind: Secret metadata: name: huanle-com-tls namespace: default data: tls.key: “” tls.crt: “”

```
[root@duduniao yaml]# curl -k https://10.0.160.10/info -H 'Host: slb-s1-https.huanle.com'
2021-10-13T06:49:29+00:00|v1.0.3|nginx-deploy-699fdd685d-ffswz|ok

2.5. Traefik简单使用

2.5.1. 配置Dashboard

  1. 部署Dashboard

    # 配置dashboard
    apiVersion: traefik.containo.us/v1alpha1
    kind: IngressRoute
    metadata:
    name: traefik-dashboard
    namespace: traefik
    spec:
    entryPoints:
    - web
    routes:
    - match: Host(`traefik-k8s-local-01.huanle.com`)
     kind: Rule
     services:
     - name: api@internal
       kind: TraefikService
    
  2. 配置DNS解析

配置域名解析到LB的VIP即可

  1. 测试访问

image.png

2.5.2. IP透传


image.png