k8s-------(| 二 |)资源对象Namespace,Service

文章目录

  • 一. Namespace(命名空间)
    • Pod跨namespace访问Service服务
  • 二 . Service
      • kube-proxy和service的关系:
    • 一、Service 代理方式
    • 1. userspace
    • 2. iptables
    • 3. ipvs(常用)
    • 二、Service的类型
    • 1. ClusterIp
        • ClusterIP 实例
        • Headless Service(无头服务)
    • 2. nodePort
      • nodePort 实例
    • 3. LoadBalancer
    • 4. ExternalName
    • 三 、ingress-Nginx

一. Namespace(命名空间)

相当于,把pod分组,形成逻辑上分组的不同项目、小组或用户组,便于不同的分组在共享使用整个集群的资源的同时还能被分别管理。

Namespace 是用来做一个集群内部的逻辑隔离的,
它包括鉴权、资源管 理等。Kubernetes 的每个资源,比如刚才讲的 Pod、Deployment、Service 都属于一个 Namespace,同一个 Namespace 中的资源需要命名的唯一 性,不同的 Namespace 中的资源可以重名

定义一个Namespace

apiVersion: v1
kind: Namespace
metadata:
  name: development

定义一个pod指定属于那个Namespace

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: development
spec:
  containers:
  - image: busybox
    command:
      - sleep
      - "3600"
    name: busybox

获取集群中有哪些namespace

 kubectl get ns

集群中默认会有 default 和 kube-system 这两个namespace。

在执行 kubectl 命令时可以使用 -n 指定操作的namespace

  1. 用户的普通应用默认是在 default 下,
  2. 与集群管理相关的为整个集群提供服务的应用一般部署在 kube-system 的namespace下,例

如我们在安装kubernetes集群时部署的 kubedns 、 heapseter 、 EFK 等都是在这个namespace下面。
另外,并不是所有的资源对象都会对应namespace, node 和 persistentVolume 就不属于任何namespace。

Pod跨namespace访问Service服务

参考
通过Service的NAME进行通信,而不是Service的IP
因为每次重启Service,NAME不会改变,而IP是会改变的
需要创建新的service,指定ExternalName

二 . Service

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

ServiceHeadless Services
参考

  • Service 能够提供负载均衡的能力,但是在使用上有以下限制:只提供 4 层负载均衡能力,而没有 7 层功能。但是可以通过增加 Ingress 来添加一个 7 层的负载均衡能力

  • Service 提供了一个或者多个 Pod 实例的稳定访问地址

详细介绍
一个 Deployment 可能有两个甚至更 多个完全相同的 Pod。对于一个外部的用户来讲,访问哪个 Pod 其实都 是一样的,所以它希望做一次负载均衡,在做负载均衡的同时,我只想访 问某一个固定的 VIP,也就是 Virtual IP 地址,而不希望得知每一个具 体的 Pod 的 IP 地址。

对一个外部用户来讲,提供了多个具体的 Pod 地址,这个用户要不停地 去更新 Pod 地址,当这个 Pod 再失败重启之后,我们希望有一个抽象, 把所有 Pod 的访问能力抽象成一个第三方的一个 IP 地址,实现这个的 Kubernetes 的抽象就叫 Service

实现 Service 有多种方式,Kubernetes 支持 Cluster IP,kuber-proxy 的组网,它也支持 nodePort、 LoadBalancer 等其他 的一些访问的能力。
k8s-------(| 二 |)资源对象Namespace,Service_第1张图片

一般常用的有两种:
k8s集群的service:selector指定pod自动创建Endpoints
k8s集群的service:手动创建Endpoints,指定外部服务的ip,端口和协议

kube-proxy和service的关系:

kube-proxy——————> k8s-apiserver
			watch

一、Service 代理方式

在 Kubernetes 集群中,每个 Node 运行一个 kube-proxy 进程。kube-proxy 负责为 Service 实现了一种VIP(虚拟 IP)的形式,而不是 ExternalName 的形式。在 Kubernetes v1.0 版本,代理完全在 userspace。在 Kubernetes v1.1 版本,新增了 iptables 代理,但并不是默认的运行模式。从 Kubernetes v1.2 起,默认就是 iptables 代理。
在 Kubernetes v1.8.0-beta.0 中,添加了 ipvs 代理,
Kubernetes 1.14 版本开始默认使用 ipvs 代理。
在 Kubernetes 集群中,每个 Node 运行一个 kube-proxy 进程

  • apiserver 通过监控 kube-proxy 去进行对服务和端点的监控
  • iptables 是 Service 代理方式的一种,其中保存地址映射及规则,通过 kube-proxy 写入
  • 客户端访问节点时通过 iptables 来实现
  • kube-proxy 通过 pod 的标签(lables)是否匹配去判断这个断点信息是否写入到 Endpoints(包含服务- - 选择器(通过标签匹配)匹配到的所有 Pod 的引用) 里去。
  • kube-proxy 通过不同的负载均衡策略,访问对应的 Pod。

1. userspace

k8s-------(| 二 |)资源对象Namespace,Service_第2张图片

2. iptables

详细
k8s-------(| 二 |)资源对象Namespace,Service_第3张图片

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,必须在启动 kube-proxy 之前确保 IPVS 内核模块已安装。当 kube-proxy 以 IPVS 代理模式启动时,它将验证节点上 IPVS 内核模块是否可用。 如果未检测到 IPVS 内核模块,则 kube-proxy 将退回到以 iptables 代理模式运行。
k8s-------(| 二 |)资源对象Namespace,Service_第4张图片
可以看到,集群使用的是 ipvs 的代理方式

[root@k8s-master01 yaml]# ipvsadm -Ln
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.96.0.1:443 rr
  -> 192.168.66.10:6443           Masq    1      3          0

[root@k8s-master01 yaml]# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   21d

二、Service的类型

1. ClusterIp

默认类型,自动分配一个仅 Cluster 内部可以访问的虚拟 ip只能被集群内部的应用程序所访问

k8s-------(| 二 |)资源对象Namespace,Service_第5张图片

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

k8s-------(| 二 |)资源对象Namespace,Service_第6张图片

为了实现图上的功能,主要需要以下几个组件的协同工作:

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

ClusterIP 实例

  1. 创建一个 Deployment(后面几种 Service 类型都使用的这个 Deployment),先写一个 svc-deployment.yaml 资源清单:
apiVersion: apps/v1
kind: Deployment
metadata:
 name: myapp-deploy		# Deployment 名称
 namespace: default
spec:
 replicas: 3
 selector:
   matchLabels:
     app: myapp
     release: stable
 template:
   metadata:
     name: myapp	# Pod 名
     labels:
       app: myapp
       release: stable
   spec:
     containers:
     - name: myapp						# 容器名
       image: wangyanglinux/myapp:v2	# nginx
       imagePullPolicy: IfNotPresent
       ports:
       - name: http
         containerPort: 80

  1. 创建 Service 资源清单,来代理上面创建的三个 Pod。myapp-svc.yaml:
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc       # Service名称
spec:
  type: ClusterIP		# Service 类型,不写默认就是 ClusterIP
  selector:             # 用于匹配后端的 Pod 资源对象,需和上面 Pod 的标签一致
    app: myapp
    release: stable
  ports:
  - name: http
    port: 80            # Service端口号
    targetPort: 80      # 后端 Pod 端口号
    protocol: TCP       # 使用的协议

3.访 问

]# kubectl get deployment -o wide
								3/3
]# kubectl get pod -o wide
NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
myapp-deploy-6998f78dfc-nt28j   1/1     Running   0          11m   10.244.1.29   k8s-node01   <none>           <none>
myapp-deploy-6998f78dfc-p9bkc   1/1     Running   0          11m   10.244.1.30   k8s-node01   <none>           <none>
myapp-deploy-6998f78dfc-xqwbk   1/1     Running   0          11m   10.244.2.25   k8s-node02   <none>           <none>

# svc 是 service 的简写,使用 kubectl get service 也可
]# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
myapp-svc    ClusterIP   10.101.140.64   <none>        80/TCP    6s

# 可以看到负载均衡策略是轮询
]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.101.140.64:80 rr
  -> 10.244.1.29:80               Masq    1      0          2
  -> 10.244.1.30:80               Masq    1      0          3
  -> 10.244.2.25:80               Masq    1      0          3

# 多访问几次也可以看到负载均衡策略是轮询
]# curl 10.101.140.64/hostname.html
myapp-deploy-6998f78dfc-nt28j

Headless Service(无头服务)

有时不需要或不想要负载均衡,以及单独的 Service IP 。遇到这种情况,可以通过指定 ClusterIP(spec.clusterIP)的值为 “None” 来创建 Headless Service 。这类 Service 并不会分配 Cluster IP, kube-proxy 不会处理它们,而且平台也不会为它们进行负载均衡和路由。
主要用来解决 Hostname 与 Podname 变化问题。在创建 StatefulSet 时,必须先创建一个 Headless Service。

第一种:自主选择权,有时候 client 想自己来决定使用哪个 Real Server,可以通过查询 DNS 来获取 Real Server 的信息。
第二种:Headless Services 还有一个用处(PS:也就是我们需要的那个特性)。Headless Service 的对应的每一个 Endpoints,即每一个 Pod,都会有对应的 DNS 域名。当删除 Pod 时,Pod 的 IP 会变,但是 Pod 的名字不会改变,这样各 Pod 之间就可以通过 Pod 名来互相访问

  1. 创建一个 Headless Service,还是匹配上面创建的 Deployment(ClusterIP 实例) 下的 Pod
apiVersion: v1
kind: Service
metadata:
  name: myapp-headless    #service对象名
spec:
  clusterIP: None    #将ClusterIP字段设置为None,即表示为headless类型的service资源对象
  selector:
    app: myapp    #匹配上面定义的pod资源
  ports:
  - port: 80    #service端口
    targetPort: 80    #后端pod端口
    protocol: TCP    #协议

  1. 查案svc
# 可以看到,Cluster-IP 对应位置的值为 None
[root@k8s-master01 yaml]# kubectl get svc
NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
myapp-headless   ClusterIP   None            <none>        80/TCP    8s

  1. 在dns中查看 A记录
# 查看 k8s coredns 的ip
[root@k8s-master01 yaml]# kubectl get pod -n kube-system -o wide
NAME                                   READY   STATUS    RESTARTS   AGE   IP              NODE           NOMINATED NODE   READINESS GATES
coredns-5c98db65d4-5ztqn               1/1     Running   6          21d   10.244.0.11     k8s-master01   <none>           <none>
coredns-5c98db65d4-pc62t               1/1     Running   6          21d   10.244.0.10     k8s-master01   <none>           <none>

# 使用 dig 解析域名(没有 dig 要安装:yum -y install bind-utils):dig -t A 域名 @DNS服务器IP
# DNS服务器IP:上面获取的两个 coredns ip 中选取一个
# 默认域名:SVC_NAME.NAMESPACE.svc.cluster.local

[root@k8s-master01 yaml]# dig -t A myapp-headless.default.svc.cluster.local. @10.244.0.11
;; ANSWER SECTION:
myapp-headless.default.svc.cluster.local. 30 IN	A 10.244.1.30
myapp-headless.default.svc.cluster.local. 30 IN	A 10.244.1.29
myapp-headless.default.svc.cluster.local. 30 IN	A 10.244.2.25 
# 可以看到解析的结果和前面创建的 Pod 是对应的,因此可以通过域名访问这几个 Pod

2. nodePort

在 ClusterIP 基础上为 Service 在每台机器上绑定一个端口,这样就可以通过 NodeIp:NodePort 来访问该服务
k8s-------(| 二 |)资源对象Namespace,Service_第7张图片

nodePort 实例

创建一个 NodePort Service,匹配 ClusterIP 实例中创建的 Deployment

apiVersion: v1
kind: Service
metadata:
  name: myapp       #service对象名
spec:
  type: NodePort        #这里指定使用ClusterIP,默认也是ClusterIP,这里可有可无
  selector:
    app: myapp          #匹配上面定义的pod资源
    release: stable
  ports:
  - port: 80            #service端口
    targetPort: 80      #后端pod端口
    nodePort: 30001     #节点端口,物理机上暴露出来的端口
    protocol: TCP       #协议

查看svc

]# kubectl get svc
NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
myapp            NodePort    10.97.100.171   <none>        80:30001/TCP   7s

在这里插入图片描述

3. LoadBalancer

loadBalancer 和 nodePort 其实是同一种方式。区别在于 loadBalancer 在 nodePort 的基础上,借助 cloud provider 创建了 LB 来向节点导流(外部负载均衡器),并将请求转发到 NodeIp:NodePort

LB 是供应商提供的,是收费的
服务器必须是云服务器
k8s-------(| 二 |)资源对象Namespace,Service_第8张图片

4. ExternalName

把集群外部的服务引入到集群内部来,在集群内部直接使用。没有任何类型代理被创建,这只有 kubernetes 1.7 或更高版本的 kube-dns 才支持

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

k8s-------(| 二 |)资源对象Namespace,Service_第9张图片

ExternalName 实例

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

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

[root@k8s-master01 yaml]# kubectl get svc
NAME             TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
my-service-1     ExternalName   <none>          hub.qcq.com   <none>         19s

[root@k8s-master01 yaml]# dig -t A my-service-1.default.svc.cluster.local. @10.244.0.11
;; ANSWER SECTION:
my-service-1.default.svc.cluster.local.	30 IN CNAME hub.qcq.com.

三 、ingress-Nginx

7 层的负载均衡能力: 下一章

你可能感兴趣的:(k8s,k8s)