K8s服务发现

1 SVC

1.1 Service概念

在这里插入图片描述

  1. 定义了这样一种抽象:一个Pod的逻辑分组,一种可以访问它们的策略 – 通常称为微服务。这一组Pod能够被Service访问到,通常是通过Label Selector标签选的的方式
    在这里插入图片描述
  2. Service能够提供负载均衡的能力,但是在使用上有以下限制:
    1)只提供4层负载均衡能力(只能通过IP+端口转发实现负载均衡),而没有7层功能(默认不能通过主机名或域名方式负载均衡),但有时我们可能需要更多的匹配规则来转发请求,这点上4层负载均衡是不支持的
    2)可以通过ingress方案添加七层负载均衡的能力
  3. SVC基础导图-实现流程
    在这里插入图片描述

1.2 Service的类型

  1. Service在K8s中有以下四种类型
    1.Clusterlp: 默认类型,自动分配一个仅Cluster内部可以访问的虚拟IP
    2.NodePort: 在ClusterlP基础上为Service在每台机器上绑定一个端口, 这样就可以通过NodelP:NodePort来访问该服务
    3.LoadBalancer: 在NodePort的基础上,借助cloud provider创建一 个外部负载均衡器,并将请求转发到NodeIP: NodePort
    4.ExternalName: 把集群外部的服务引入到集群内部来,在集群内部直接使用。没有任何类型代理被创建,这只有kubernetes 1.7或更高版本的kube-dns才支持
  2. Clusterlp类型:other Pod通过集群内部ip访问到后面的pod, 并且实行负载均衡的方案。
    在这里插入图片描述
  3. NodePort类型:在每个物理机上绑定个端口,如果有一个宕机不会影响服务访问
    在这里插入图片描述
  4. LoadBalancer类型:引入云供应商的服务(负载路由器的解决方案)接口即可。需要独立收费
    在这里插入图片描述
  5. ExternalName类型
    在这里插入图片描述

1.3 Service的代理模式分类

  1. 在Kubernetes集群中,每个Node运行一个kube-proxy进程。kube- proxy负责为Service 实现了一种VIP (虚拟IP)的形式,而不是ExternalName的形式。在Kubernetes v1.0版本,代理完全在userspace。

  2. 在Kubernetes v1.1版本,新增了iptables代理,但并不是默认的运行模式。从Kubernetes v1.2起,默认就是iptables代理。在Kubernetes v1.8.0-beta.0中,添加了ipvs代理。在Kubernetes 1.14版本开始默认使用ipvs代理

  3. 在Kubernetes v1.0版本,Service 是“4层”(TCP/UDP overIP)概念。在Kubernetes v1.1版本,新增了Ingress API (beta 版),用来表示“7层”(HTTP) 服务

  4. 为何不使用round-robin DNS? DNS会在系统中进行缓存。。。就起不到负载均衡的效果。。。

  5. userspace代理模式:每次访问都需要kube-proxy进行代理,而且kube-apiserver也监控kube-proxy进行服务更新和端点维护,所以kube-proxy的压力就会很大。
    在这里插入图片描述

  6. iptables代理模式:访问直接由防火墙iptables调度完成,不需要经过kube-proxy调度。大大提升速度,提到kube-proxy的稳定性。
    在这里插入图片描述

  7. ipvs代理模式(现在的标准):kube-proxy 会监视Kubernetes Service 对象和Endpoints,调用netlink 接口以相应地创建ipvs规则并定期与Kubernetes Service对象和Endpoints 对象同步ipvs规则,以确保ipvs状态与期望一致。访问服务时,流量将被重定向到其中一个后端Pod
    1.查看ipvs命令: ipvsadm -Ln
    2.与iptables类似,ipvs 于netfilter的hook功能,但使用哈希表作为底层数据结构并在内核空间中工作。这意味着ipvs可以更快地重定向流量,并且在同步代理规则时具有更好的性能。此外,ipvs为负载均衡算法提供了更多选项,例如:
    1)rr:轮询调度
    2)lc:最小连接数
    3)dh:目标哈希
    4)sh:源哈希
    5)sed:最短期望延迟
    6)nq:不排队调度
    在这里插入图片描述

2 Service讲解

2.1 Service测试

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

2.2 Service之yaml

  1. 创建 myapp-deploy.yaml 文件。 通过Deployment 部署了 3 个 Pod 副本
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      release: stabel
  template:
    metadata:
      labels:
        app: myapp
        release: stabel
        env: test
    spec:
      containers:
      - name: myapp
        image: hub.qnhyn.com/library/myapp
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80
  1. 给Deployment中的pod, 绑定一个Service。配置文件svc.yaml。注意:这里的selector必须和上面depoymnent中的一致。否则匹配不到
apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: default
spec:
  type: ClusterIP
  selector:
    app: myapp
    release: stabel
  ports:
  - name: http
    port: 80
    targetPort: 80
  1. 部署
# 部署Deployment
kubectl create -f svc-deployment.yaml
# 直接访问deployment中的某个pod
kubectl get pod -o wide
curl 10.244.1.40
# 部署svc 服务可靠维稳访问
kubectl create -f svc.yaml
kubectl get svc
curl 10.110.67.225
ipvsadm -Ln

在这里插入图片描述

2.3 Cluster-Headless Service

  1. 有时不需要或不想要负载均衡,以及单独的 Service IP,遇到这种情况,可以通过指定 Cluster IP(spec.clusterIP)的值为 None 来创建 Headless Service 。
  2. 这类 Service 并不会分配 Cluster IP,kube-proxy 不会处理它们,而且平台也不会为它们进行负载均衡。
  3. Headless Service 也是后面StatefulSet 的基础。它可以用来解决cluster name和pod name的绑定问题。
  4. svc-none.yaml
  5. svc的创建会有一个主机名会被写入到coreDNS,写入的格式体就是 svc的名称+命名空间的名称+当前集群的域名
apiVersion: v1
kind: Service
metadata:
  name: myapp-headless
  namespace: default
spec:
  selector:
    app: myapp
  clusterIP: "None"
  ports:
  - port: 80
    targetPort: 80

操作

kubectl create -f svc-none.yaml
# 查看发现Cluster Ip为空
kubectl get svc
# 安装包 使用dig命令
yum -y install bind-utils
# 查看coredns的ip
kubectl get pod -n kube-system -o wide
# 对于 Service 一旦创建成功会写入到 CoreDNS 中去 通过命令查看
# 意味着在无头服务中,虽然它没有ip了,但可以通过访问域名的方案依然可以访问服务下的pod
dig -t A myapp-headless.default.svc.cluster.local. @10.244.2.40

2.4 NodePort

  1. nodePort的原理在于在node上开了一个端口,将向该端口的流量导入到kube-proxy,然后由kube-proxy进一步到给对应的pod,这里依然是iptables类型
  2. 这里我们可以发现一组Pod可以对应多个服务。多对多的模式
  3. vim myapp-service .yaml
apiVersion: v1 
kind: Service 
metadata:
  name: myapp 
  namespace: default 
spec:
  type: NodePort 
  selector:
    app: myapp 
    release: stabel 
  ports:
  - name: http 
    port: 80 
    targetPort: 80

  1. 操作
kubectl create -f myapp-service.yaml
# 查看svc 
kubectl get svc
# 查看各个Node上端口有没有开启成功
netstat -anpt | grep 31217
# iptables查询流程  iptables -t nat -nvL KUBE-NODEPORTS
# 我们实验中使用的是ipvs负载均衡
ipvsadm -Ln

  1. 每个Node都会开启这个映射的随机端口
    在这里插入图片描述

2.5 LoadBalancer

  1. loadBalancer和nodePort 其实是同一种方式。区别在于 loadBalancer 比nodePort多了一步,就是可以调用cloud provider【云供应商】 去创建LB【负载均衡】来向节点导流
    在这里插入图片描述

2.6 LoadBalancer测试

  1. 这种类型的 Service 通过返回 CNAME和它的值,可以将服务映射到externalName字段的内容(例如: hub.qnhyn.com)。ExternalName Service 是Service的特例,它没有 selector,也没有定义任何的端口和Endpoint。
  2. 相反的,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务
  3. externalname.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-service
  namespace: default
spec:
  type: ExternalName
  externalName: hub.qnhyn.com
  1. 当查询主机 my-service.defalut.svc.cluster.local(SVC_NAME.NAMESPACE.svc.cluster.local)时,集群的DNS 服务将返回一个值my.database.example.com的CNAME记录。访问这个服务的工作方式和其他的相同,唯一不同的是重定向发生在DNS层,而且不会进行代理或转发。
kubectl apply -f externalname.yaml  
kubectl get pod -n kube-system -o wide
kubectl get svc
# 解析这个服务 
dig -t A my-service-1.default.svc.cluster.local. @10.244.1.39

3 Service Ingress

3.1 Service Ingress

  1. 对于k8s传统的svc来说 它仅支持4层代理,如果遇到7层代理的话,是没有办法去实现的
  2. k8s官方在1.11中推出了ingress api接口,通过ingress达到7层代理的效果。
  3. 对于ingress来说,必须要绑定一个域名,因为它是基于7层代理的
  4. Ingress现在已经非常成熟啦
    1.Ingress-Nginx github 地址:https://github.com/kubernetes/ingress-nginx
    2.Ingress-Nginx 官方网站:https://kubernetes.github.io/ingress-nginx/
    3.安装指导:https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md
  5. 创建了一个Nginx的NodePort的部署方案,暴露给外部用户。无需手写Nginx的配置文件,它是通过自动添加的
    在这里插入图片描述
    client->NodePort->svc->pod
    在这里插入图片描述
  6. 暴露方案执行【此处选择裸机暴露方案,就是以svc暴露】(不用这种方式安装,用下面helm管理安装)
    kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.34.1/deploy/static/provider/baremetal/deploy.yaml
  7. Helm管理安装
    1.安装Helm:https://github.com/helm/helm/releases 通过脚本快一点
    2.helm list
    3.helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
    4.helm install my-release ingress-nginx/ingress-nginx
    5.由于Nginx Ingress的service缺省采用"type: LoadBalancer",为了外部访问,修改为"type: NodePort",顺便设置固定的nodePort。
    1)helm install my-release nginx-stable/nginx-ingress --set controller.service.type=NodePort
  8. 验证是否完成(由于版本问题和视频中安装不一样)
    1.kubectl get pods -n ingress-nginx -l 2.app.kubernetes.io/name=ingress-nginx --watch
  9. kubectl get svc -n ingress-nginx
    如果安装错删除之前安装:
    1.第一种:kubectl delete -f deploy.yaml
    2.helm删除:helm delete nginx-ingress

3.2 Ingress HTTP代理访问配置

  1. Deployment 和 Service 文件。vim ingress.http.yaml
  2. 部署后访问,Cluster IP 看是否能访问服务
    1.kubectl get svc
    2.curl 10.110.29.160
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-dm
spec:
  selector:
    matchLabels:
      app: nginx-dm
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx-dm
    spec:
      containers:
      - name: nginx-dm
        image: hub.qnhyn.com/library/myapp
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  type: ClusterIP
  selector:
    app: nginx-dm
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  1. Ingress: kubectl apply -f ingress.yaml。通过域名(七层)访问,在host中加入域名解析两个node http://www.qnhyn1.com:31807
apiVersion: extensions/v1beta1
kind: Ingress 
metadata:
  name: nginx-test 
spec:
  rules:
    - host:www.qnhyn1.com
      http:
        paths:
          - path: / 
            backend:
              serviceName: nginx-svc
              servicePort: 80
  1. 我们可以根据下图创建,两个(多)服务,通过ingress通过两(多)个不同的域名管理。
    在这里插入图片描述

3.3 Ingress HTTPS代理访问配置

  1. 先创建证书,以及 cert 存储方式 mkdir https && cd https
    1.openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj “/CN=nginxsvc/O=nginxsvc”
    2.kubectl create secret tls tls-secret --key tls.key --cert tls.crt
  2. 创建deployment和service服务 deployment3.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-dm3
spec:
  selector:
    matchLabels:
      app: nginx-dm3
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx-dm3
    spec:
      containers:
      - name: nginx-dm3
        image: hub.qnhyn.com/library/myapp
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc3
spec:
  type: ClusterIP
  selector:
    app: nginx-dm3
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  1. ingress.yaml 这里使用域名+443对应的端口。https://www.qnhyn3.com:31015
apiVersion: extensions/v1beta1
kind: Ingress 
metadata:
  name: nginx-https 
spec:
  tls:
    - hosts:
      - www.qnhyn3.com
      secretName: tls-secret
  rules:
    - host: www.qnhyn3.com
      http:
        paths:
          - path: / 
            backend:
              serviceName: nginx-svc3
              servicePort: 80

3.4 Nginx 进行 BasicAuth

  1. 安装依赖包
yum -y install httpd
htpasswd -c auth foo # 设置用户名foo的密码
kubectl create secret generic basic-auth --from-file=auth
  1. 配置auth_ingress.yaml。 网址输入后弹出账号密码:输入用户foo 和 自己设置的密码可以访问服务。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-with-auth
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: "Authentication Required - foo"
spec:
  rules:
    - host: auth.qnhyn.com
      http:
        paths:
          - path: /
            backend:
              serviceName: svc-1
              servicePort: 80

3.5 Nginx 进行重写

名称描述
nginx.ingress.kubernetes.io/rewrite-target必须重定向流量的目标URI 字符串
nginx.ingress.kubernetes.io/ssl-redirect指示位置部分是否仅可访问SSL (当Ingress包含证书时默认为True)布尔值
nginx.ingress.kubernetes.io/force-ssl-redirect即使Ingress末启用TLS,也强制重定向到HTTPS布尔值
nginx.ingress.kubernetes.io/app-root定义Controller必须重定向的应用程序根,如果它在/上下文中字符串
nginx.ingress.kubernetes.io/use-regex指示Ingress上定义的路径是否使用正则表达式布尔值

在这里插入图片描述

  1. 重定向的re.yaml 访问re.qnhyn3.com跳转到https://www.qnhyn3.com:3180
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx-redirect
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: https://www.qnhyn3.com:31802
spec:
  rules:
  - host: re.qnhyn3.com
    http:
      paths:
        - path: /
          backend:
            serviceName: svc-3
            servicePort: 80
  1. Traefik没有nginx的性能高,大概能达到nginx性能的80%吧

Helm部署ingress-nginx

helm upgrade --install ingress-nginx ingress-nginx \
  --repo https://kubernetes.github.io/ingress-nginx \
  --namespace ingress-nginx --create-namespace

否则

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.0/deploy/static/provider/cloud/deploy.yaml

iptables详解
ipvs详解
LVS详解

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值