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

一. 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集群的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

在这里插入图片描述

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,必须在启动 kube-proxy 之前确保 IPVS 内核模块已安装。当 kube-proxy 以 IPVS 代理模式启动时,它将验证节点上 IPVS 内核模块是否可用。 如果未检测到 IPVS 内核模块,则 kube-proxy 将退回到以 iptables 代理模式运行。
在这里插入图片描述
可以看到,集群使用的是 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只能被集群内部的应用程序所访问

在这里插入图片描述

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

在这里插入图片描述

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

  • 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 来访问该服务
在这里插入图片描述

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 是供应商提供的,是收费的
服务器必须是云服务器
在这里插入图片描述

4. ExternalName

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

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

在这里插入图片描述

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 层的负载均衡能力下一章

在 `kubectl` 命令行工具中,你可以使用 `--help` 参数来查看命令的帮助文档,包括 YAML 文件的格式要求和示例。例如,使用 `kubectl create --help` 命令可以查看如下内容: ``` Create a resource from a file or from stdin. JSON and YAML formats are accepted. Usage: kubectl create (-f FILENAME | --filename=FILENAME) [options] kubectl create (-k DIRECTORY | --kustomize=DIRECTORY) [options] kubectl create clusterrolebinding NAME --clusterrole=ROLE [--user=USER] kubectl create clusterrole NAME --verb=verb --resource=resource.group [--resource-name=resource.name] kubectl create configmap NAME [--from-literal=key1=value1] [--from-literal=key2=value2] [--from-file=[key=]source] [--dry-run=server|client|none] [--output=wide|yaml|json] [options] kubectl create cronjob NAME --image=image [--schedule=''] --command -- [COMMAND] [args...] [options] kubectl create deployment NAME --image=image [--dry-run=server|client|none] [--output=wide|yaml|json] [options] kubectl create job NAME --image=image --command -- [COMMAND] [args...] [options] kubectl create namespace NAME [--dry-run=server|client|none] [--output=wide|yaml|json] [options] kubectl create secret generic NAME [--from-literal=key1=value1] [--from-literal=key2=value2] [--from-file=[key=]source] [--dry-run=server|client|none] [--output=wide|yaml|json] [options] kubectl create service NAME --tcp=port1,port2,... [--dry-run=server|client|none] [--output=wide|yaml|json] [options] kubectl create serviceaccount NAME [--dry-run=server|client|none] [--output=wide|yaml|json] [options] Examples: # Create a pod using the data in pod.json. kubectl create -f ./pod.json # Create a pod based on the JSON passed into stdin. cat pod.json | kubectl create -f - # Edit the data in EDITOR (default vim). kubectl create configmap my-config --from-file=config.json --edit # Create a new namespace named my-namespace kubectl create namespace my-namespace Options: -f, --filename='': Filename, directory, or URL to files to use to create the resource -k, --kustomize='': Process a kustomization directory. This flag can't be used together with -f or -R. --edit=false: Edit the data in $EDITOR --force=false: Create resource even if it already exists --dry-run='none': Must be "none", "server", or "client". If client strategy, only print the object that would be sent, without sending it. If server strategy, submit server-side request without persisting the resource. -o, --output='': Output format. One of: yaml, json, wide, name, go-template-file, go-template, jsonpath-file, jsonpath. If unspecified, will default to yaml for standalone objects and table for lists. --record=false: Record current kubectl command in the resource annotation. If set to false, do not record the command. If set to true, record the command. If not set, default to updating the existing annotation value only if one already exists. ``` 在这个帮助文档中,你可以看到 `kubectl create` 命令支持不同类型的资源对象,包括 Pod、Deployment、Service、Secret 等。对于每个资源对象类型,文档都提供了示例和参数说明。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值