06 kubernetes Service

一、Service 定义

1、Service 的概念

Kubernetes Service 定义了这样一种抽象:一个 Pod 的逻辑分组,一种可以访问它们的策略 —— 通常称为微
服务。 这一组 Pod 能够被 Service 访问到,通常是通过 Label Selector

在这里插入图片描述
Service能够提供负载均衡的能力,但是在使用上有以下限制:
只提供 4 层负载均衡能力,而没有 7 层功能,但有时我们可能需要更多的匹配规则来转发请求,这点上 4 层负载均衡是不支持的

2、Service 的类型

Service 在 K8s 中有以下四种类型

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

二、代理模式的分类

1、userspace 代理模式

在这里插入图片描述

2、iptables 代理模式

在这里插入图片描述

3、ipvs 代理模式

这种模式,kube-proxy 会监视 Kubernetes Service 对象和 Endpoints ,调用 netlink 接口以相应地创建 ipvs 规则并定期与 Kubernetes Service 对象和 Endpoints 对象同步 ipvs 规则,以确保 ipvs 状态与期望一致。访问服务时,流量将被重定向到其中一个后端 Pod 与 iptables 类似,ipvs 于 netfilter 的 hook 功能,但使用哈希表作为底层数据结构并在内核空间中工作。这意味着 ipvs 可以更快地重定向流量,并且在同步代理规则时具有更好的性能。此外,ipvs 为负载均衡算法提供了更多选项,例如:

  • rr :轮询调度
  • lc :最小连接数
  • dh :目标哈希
  • sh :源哈希
  • sed :最短期望延迟
  • nq : 不排队调度

注意: ipvs 模式假定在运行 kube-proxy 之前在节点上都已经安装了 IPVS 内核模块。当 kube-proxyipvs代理模式启动时,kube- proxy将验证节点上是否安装了 ipvs 模块,如果未安装,则 kube-proxy将回退到 iptables代理模式
在这里插入图片描述

查看 ipvs 规则
10.96.0.1 443 被映射到 192.168.1.80:6443

[root@k8s-master01 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.96.0.1:443 rr
  -> 192.168.1.80:6443            Masq    1      3          0         
TCP  10.96.0.10:53 rr
  -> 10.244.0.43:53               Masq    1      0          0         
  -> 10.244.0.44:53               Masq    1      0          0         
TCP  10.96.0.10:9153 rr
  -> 10.244.0.43:9153             Masq    1      0          0         
  -> 10.244.0.44:9153             Masq    1      0          0         
TCP  10.96.245.238:80 rr
TCP  10.102.154.249:80 rr
UDP  10.96.0.10:53 rr
  -> 10.244.0.43:53               Masq    1      0          0         
  -> 10.244.0.44:53               Masq    1      0          0         
[root@k8s-master01 ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP   147d

三、ClusterIP 案例

clusterIP 主要在每个 node 节点使用 iptables,将发向 clusterIP 对应端口的数据,转发到 kube-proxy 中。然
后 kube-proxy 自己内部实现有负载均衡的方法,并可以查询到这个 service 下对应 pod 的地址和端口,进而把
数据转发给对应的 pod 的地址和端口

在这里插入图片描述
为了实现图上的功能,主要需要以下几个组件的协同工作:

  • apiserver 用户通过kubectl命令向apiserver发送创建service的命令,apiserver接收到请求后将数据存储到etcd中
  • kube-proxy kubernetes的每个节点中都有一个叫做kube-porxy的进程,这个进程负责感知service,pod的变化,并将变化的信息写入本地的iptables规则中
  • iptables 使用NAT等技术将virtualIP的流量转至endpoint中

创建 svc-deployment.yaml 文件

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: wangyanglinux/myapp:v2
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80

创建svc.yaml文件

apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: default
spec:
  type: ClusterIP
  selector:
    app: myapp
    release: stabel
  ports:
  - name: http
    port: 80
    targetPort: 80

查看svc以及svc规则。

[root@k8s-master01 ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP   147d
myapp        ClusterIP   10.111.236.216   <none>        80/TCP    9s
[root@k8s-master01 ~]# curl 10.111.236.216
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
[root@k8s-master01 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.96.0.1:443 rr
  -> 192.168.1.80:6443            Masq    1      3          0         
TCP  10.96.0.10:53 rr
  -> 10.244.0.43:53               Masq    1      0          0         
  -> 10.244.0.44:53               Masq    1      0          0         
TCP  10.96.0.10:9153 rr
  -> 10.244.0.43:9153             Masq    1      0          0         
  -> 10.244.0.44:9153             Masq    1      0          0         
TCP  10.111.236.216:80 rr
  -> 10.244.1.96:80               Masq    1      0          0         
  -> 10.244.1.97:80               Masq    1      0          0         
  -> 10.244.2.109:80              Masq    1      0          1         
UDP  10.96.0.10:53 rr
  -> 10.244.0.43:53               Masq    1      0          0         
  -> 10.244.0.44:53               Masq    1      0          0     

无头服务 Headless Service

有时不需要或不想要负载均衡,以及单独的 Service IP 。遇到这种情况,可以通过指定 Cluster IP(spec.clusterIP) 的值为 “None” 来创建 Headless Service 。这类 Service 并不会分配 Cluster IP, kubeproxy 不会处理它们,而且平台也不会为它们进行负载均衡和路由

安装 di

yum -y install bind-utils

查看 coredns

kubectl get pod -n kube-system -o wide
apiVersion: v1
kind: Service
metadata:
  name: myapp-headless
  namespace: default
spec:
  selector:
    app: myapp
  clusterIP: "None"
  ports:
  - port: 80
    targetPort: 80
dig -t A myapp-headless.default.svc.cluster.local. @10.244.0.46

四、NodePort 案例

nodePort 的原理在于在 node 上开了一个端口,将向该端口的流量导入到 kube-proxy,然后由 kube-proxy 进一步到给对应的 pod

apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: default
spec:
  type: NodePort
  selector:
    app: myapp
    release: stabel
  ports:
  - name: http
    port: 80
    targetPort: 80

查看下svc,访问主机节点的32557端口,浏览会转发到pod。

[root@k8s-master01 ~]# kubectl get svc
NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes       ClusterIP   10.96.0.1        <none>        443/TCP        148d
myapp            NodePort    10.111.236.216   <none>        80:32557/TCP   22h
myapp-headless   ClusterIP   None             <none>        80/TCP         20m
[root@k8s-master01 ~]# curl http://192.168.1.80:32557/hostname.html
myapp-deploy-6cc7c66999-4k84p

[root@k8s-master01 ~]# netstat -anpt | grep 32557
tcp6       0      0 :::32557                :::*                    LISTEN      3298/kube-proxy   
[root@k8s-master01 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  172.17.0.1:32557 rr
  -> 10.244.1.98:80               Masq    1      0          0         
  -> 10.244.1.99:80               Masq    1      0          0         
  -> 10.244.2.110:80              Masq    1      0          0         
TCP  192.168.1.80:32557 rr
  -> 10.244.1.98:80               Masq    1      0          0         
  -> 10.244.1.99:80               Masq    1      0          0         
  -> 10.244.2.110:80              Masq    1      0          0         
TCP  10.244.0.0:32557 rr
  -> 10.244.1.98:80               Masq    1      0          0         
  -> 10.244.1.99:80               Masq    1      0          0         
  -> 10.244.2.110:80              Masq    1      0          0         
TCP  10.244.0.1:32557 rr
  -> 10.244.1.98:80               Masq    1      0          0         
  -> 10.244.1.99:80               Masq    1      0          0         
  -> 10.244.2.110:80              Masq    1      0          0         
TCP  127.0.0.1:32557 rr
  -> 10.244.1.98:80               Masq    1      0          0         
  -> 10.244.1.99:80               Masq    1      0          0         
  -> 10.244.2.110:80              Masq    1      0          0         

五、LoadBalancer

loadBalancer 和 nodePort 其实是同一种方式。区别在于 loadBalancer 比 nodePort 多了一步,就是可以调用 cloud provider 去创建 LB 来向节点导流
在这里插入图片描述

六、ExternalName

这种类型的 Service 通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容( 例如:hub.atguigu.com )。ExternalName Service 是 Service 的特例,它没有 selector,也没有定义任何的端口和 Endpoint。相反的,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务。
也就是说在容器中访问 my-service-1 和访问 hub.atguigu.com 是等效的。

apiVersion: v1
kind: Service
metadata:
  name: my-service-1
  namespace: default
spec:
  type: ExternalName
  externalName: hub.atguigu.com

当查询主机 my-service.defalut.svc.cluster.local (SVC_NAME.NAMESPACE.svc.cluster.local )时,集群的 DNS 服务将返回一个值 my.database.example.com 的 CNAME 记录。访问这个服务的工作方式和其他的相同,唯一不同的是重定向发生在 DNS 层,而且不会进行代理或转发

[root@k8s-master01 ~]# dig -t A my-service-1.default.svc.cluster.local. @10.244.0.46

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7_9.5 <<>> -t A my-service-1.default.svc.cluster.local. @10.244.0.46
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62618
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;my-service-1.default.svc.cluster.local.	IN A

;; ANSWER SECTION:
my-service-1.default.svc.cluster.local.	30 IN CNAME hub.atguigu.com.

;; Query time: 43 msec
;; SERVER: 10.244.0.46#53(10.244.0.46)
;; WHEN: Tue Aug 24 06:02:30 CST 2021
;; MSG SIZE  rcvd: 134

七、ingress

1、ingess 简介

Ingress-Nginx github 地址:https://github.com/kubernetes/ingress-nginx
Ingress-Nginx 官方网站:https://kubernetes.github.io/ingress-nginx/
在这里插入图片描述

在这里插入图片描述

2、部署 Ingress-Nginx

以下两个文件需要到ingess官网下载。随着版本更新,官网不再提供以下文件的下载。

kubectl apply -f mandatory.yaml
kubectl apply -f service-nodeport.yaml

切换到安装插件的目录

cd /usr/loacl/install-k8s/plugin
mkdir ingress
cd ingess

在master节点上保存nginx-ingress-controller的镜像

#将镜像保存为文件
docker save -o ingress.contr.tar quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.25.0

#压缩下镜像文件
tar -zcvf ingress.contr.tar.gz ingress.contr.tar

#将文件从虚拟机下载到宿主机
sz ingress.contr.tar.gz

在node节点上导入nginx-ingress-controller的镜像

#将文件从宿主机,传到虚拟机。
rz

#导入镜像
docker load -i ingress.contro.tar

在master执行部署nginx-ingress-controller。

kubectl apply -f mandatory.yaml

# 查看pod
kubectl get pod -n ingress-nginx

# 创建ingress的service
kubectl apply -f service-nodeport.yaml

注意:在部署 mandatory.yaml 时会报错,kind为ClusterRole的第58行后加上,以下几段,重新kubectl apply -f mandatory.yaml,即可

  - apiGroups:
      - extensions
      - networking.k8s.io
    resources:
      - ingresses
    verbs:
      - list
      - watch

这里如果想访问 80 端口,则访问的就是 31345 端口。
如果想访问的是 443 端口,则访问的就是 31802 端口。
在这里插入图片描述

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

3、Ingress HTTP 代理访问

首先部署一个应用的deployment和svc

kubectl apply -f ingress.http1.yaml

ingress.http1.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: myapp-dm-1
spec:
  replicas: 2
  template:
    metadata:
      labels:
        name: myapp-1
    spec:
      containers:
      - name: myapp-1
        image: wangyanglinux/myapp:v1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-1
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    name: myapp-1

运行一个ingress的服务,通过这个ingress来将请求转发到应用pod的服务上。

kubectl apply -f ingress1.yaml

nginx-svc

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx-svc-1
spec:
  rules:
  - host: www1.atguigu.com
    http:
      paths:
      - path: /
        backend:
          serviceName: myapp-svc-1
          servicePort: 80

设置dns

192.168.1.80 www1.atguigu.com

查看ingress-nginx

在这里插入图片描述

访问查看

在这里插入图片描述

部署第二个应用

可以部署一个myapp:v2pod、svc和ingress。然后ingresshost设置为www2.atguigu.com,这样就可以通过不同域名访问到不同的应用服务。

4、Ingress HTTPS 代理访问

创建证书,以及 cert 存储方式

openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"

kubectl create secret tls tls-secret --key tls.key --cert tls.crt

deployment、Service、Ingress Yaml 文件

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx-test
spec:
  tls:
    - hosts:
      - www1.atguigu.com
      secretName: tls-secret
  rules:
    - host: www1.atguigu.com
      http:
        paths:
        - path: /
          backend:
            serviceName: myapp-svc-1
            servicePort: 80

5、Nginx 进行 BasicAuth

可以设置认证的账号密码。

yum -y install httpd
htpasswd -c auth foo
kubectl create secret generic basic-auth --from-file=auth
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.atguigu.com
    http:
      paths:
      - path: /
        backend:
          serviceName: myapp-svc-1
          servicePort: 80

设置dns

192.168.1.80 auth.atguigu.com

6、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上定义的路径是否使用正则表达式布尔

当访问re.atguigu.com时,可以重定向到http://www2.atguigu.com:31983。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx-test
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: http://www2.atguigu.com:31983
spec:
  rules:
  - host: re.atguigu.com
    http:
      paths:
      - path: /
        backend:
          serviceName: myapp-svc-1
          servicePort: 80

设置dns

192.168.1.80 re.atguigu.com
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值