相当于,把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
。
普通
应用默认是在 default 下,管理
相关的为整个集群提供服务的应用一般部署在 kube-system 的namespace下,例如我们在安装kubernetes集群时部署的 kubedns 、 heapseter 、 EFK 等都是在这个namespace下面。
另外,并不是所有的资源对象都会对应namespace, node 和 persistentVolume 就不属于任何namespace。
参考
通过Service的NAME
进行通信,而不是Service的IP
因为每次重启Service,NAME不会改变,而IP是会改变的
需要创建新的service,指定ExternalName
Kubernetes Service 定义了这样一种抽象:一个 Pod 的逻辑分组,一种可以访问它们的策略 —— 通常称为微服务
。通过 Label Selector 这一组 Pod 能够被 Service 访问到
Service
和Headless 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——————> k8s-apiserver
watch
在 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
来实现lables
)是否匹配去判断这个断点信息是否写入到 Endpoints(包含服务- - 选择器(通过标签匹配)匹配到的所有 Pod 的引用) 里去。负载均衡策略
,访问对应的 Pod。详细
这种模式,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
默认类型,自动分配一个仅 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
中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
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
有时不需要
或不想要负载均衡
,以及单独的 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 名来互相访问
。
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 #协议
# 可以看到,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
# 查看 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
在 ClusterIP 基础上为 Service 在每台机器上绑定一个端口,这样就可以通过 NodeIp: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
loadBalancer 和 nodePort 其实是同一种方式。区别在于 loadBalancer 在 nodePort 的基础上,借助 cloud provider 创建了 LB 来向节点导流(外部负载均衡器),并将请求转发到 NodeIp:NodePort
把集群外部的服务引入到集群内部来,在集群内部直接使用。没有任何类型代理被创建,这只有 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.
7 层的负载均衡能力: 下一章