[K8S系列四] K8S核心组件与核心概念(Pod、Deployment、Service)

发布时间 2023-04-04 11:13:11作者: qq366830352

[K8S系列四] K8S核心组件与核心概念(Pod、Deployment、Service)

1. 核心组件与核心概念

K8S集群分为Master节点和Node节点,Master节点负责调度分配任务,Node节点接受Master调度进行工作。

1.1 Master节点组件

1. API Server

集群的统一入口,各组件协调者,以RESTful API方式提供接口服务,所有对象资源的增删查改和监听操作都交给API Server处理后再提交给Etcd存储。

2. Controller Manager
负责维护集群的状态,比如故障检测、自动扩展、滚动更新等。一个资源对应一个控制器,而Controller Manager就是负责管理这些控制器的。

3. Scheduler
负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上。

4.etcd
分布式键值存储系统,用于保存群集状态数据,比如Pod、Service等对象信息。

1.2 Node组件

1. kubelet
kubelet是Master在Node节点上的Agent,管理本机运行容器的生命周期,比如创建容器、Pod挂载数据卷、下载secret、获取容器和节点状态等工作。kubelet将每个Pod转换成一组容器。

2. kube-proxy
责为Service提供cluster内部的服务发现和负载均衡。

2. 核心概念

2.1 Pod

Pod是一个逻辑概念,是一组共享了某些资源的容器。Pod在K8S中是调度的最基本单位,以便容器互相依赖时,可以同时调度。
Pod 里的所有容器,共享的是同一个 Network Namespace,并且可以声明共享同一个 Volume。每个Pod中都有一个Pause(Infra)容器,Pause容器是Kubernetes基础设施的一部分,Kubernetes管理的所有pod里,pause容器是第一个启动的,而其他用户定义的容器,则通过 Join Network Namespace 的方式,与 pause容器关联在一起。

对于 Pod 里的容器 A 和容器 B 来说:

  • 它们可以直接使用 localhost 进行通信;
  • 它们看到的网络设备跟 Pause容器看到的完全一样;
  • 一个 Pod 只有一个 IP 地址,也就是这个 Pod 的 Network Namespace 对应的 IP 地址;
  • 当然,其他的所有网络资源,都是一个 Pod 一份,并且被该 Pod 中的所有容器共享;
  • Pod 的生命周期只跟 Infra 容器一致,而与容器 A 和 B 无关。
 
image.png
2.2 Controller

1.ReplicaSet
确保预期的Pod副本数量,很少直接使用,需要被Deployment管理。

2.Deployment
作用于一组Pod的创建和运行,控制pod应用的升级、回滚,当然也能控制pod的数量。

 

 

3.Service
在K8S中,一方面Pod有伸缩与重新部署的需求,Pod的IP大多数情况是不固定的,另一方面,同一组Pod之间也有负载均衡的需要。因此,一组Pod被抽象成一个Service统一向外暴露。Service与其后端Pod副本集群之间则是通过Label Selector实现关联。

 

Service有以下三种类型:
ClusterIP:提供一个集群内部的虚拟IP(clusterIP),以便在集群内部通过clutserIP:port访问;
NodePort:在每个节点上打开一个端口,在集群外部可以通过nodeIP:nodePort访问,在内部依然可以通过clutserIP:port 访问;
LoadBalancer:通过外部的负载均衡器来访问,多用于公有云上。

 
ClusterIP
 
NodePort

Service vs Deployment

  • Service是从网络角度的抽象概念,类似于Nginx做负载均衡提供的统一网络入口;
  • Pod是最终的应用部署实体;
  • Deoplyment 负责创建和保持pod运行状态。

3. 示例

3.1 deployment
#  whomai-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami-deployment
  labels:
    app: whoami
spec:
  replicas: 3
  selector:
    matchLabels:
      app: whoami
  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
      - name: whoami
        image: jwilder/whoami
        ports:
        - containerPort: 8000
# kubectl get pods -o wide
whoami-deployment-8886867c8-67d4f   1/1     Running   0              45m   10.244.80.206   w2     <none>           <none>
whoami-deployment-8886867c8-hgvmb   1/1     Running   0              45m   10.244.80.205   w2     <none>           <none>
whoami-deployment-8886867c8-pc67z   1/1     Running   0              45m   10.244.190.88   w1     <none>           <none>

# curl 10.244.80.206:8000
I'm whoami-deployment-8886867c8-67d4f
# curl 10.244.80.205:8000
I'm whoami-deployment-8886867c8-hgvmb
# curl 10.244.190.88:8000
I'm whoami-deployment-8886867c8-pc67z
3.2 Service

1. ClusterIP
whoami-clusterip.yaml

apiVersion: v1
kind: Service
metadata:
  name: whoami-clusterip
spec:
  type: ClusterIP
  selector:
    app: whoami
  ports:
    - protocol: TCP
      port: 8080 # 集群的8080端口
      targetPort: 8000 # Pod的8000端口
# kubectl apply -f whoami-clusterip.yaml
# kubectl get svc -o wide
NAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE   SELECTOR
kubernetes         ClusterIP   10.96.0.1       <none>        443/TCP    34d   <none>
whoami-clusterip   ClusterIP   10.98.191.167   <none>        8080/TCP   8s    app=whoami

# curl 10.98.191.167:8080
I'm whoami-deployment-8886867c8-hgvmb
# curl 10.98.191.167:8080
I'm whoami-deployment-8886867c8-67d4f
# curl 10.98.191.167:8080
I'm whoami-deployment-8886867c8-67d4f
# curl 10.98.191.167:8080
I'm whoami-deployment-8886867c8-hgvmb
# curl 10.98.191.167:8080
I'm whoami-deployment-8886867c8-pc67z

#  kubectl describe  svc whoami-clusterip
Name:              whoami-clusterip
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=whoami
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.98.191.167
IPs:               10.98.191.167
Port:              <unset>  8080/TCP
TargetPort:        8000/TCP
Endpoints:         10.244.190.88:8000,10.244.80.205:8000,10.244.80.206:8000
Session Affinity:  None
Events:            <none>

这种Service在集群外部是无法访问的,因为它是基于每个集群节点上配置的iptables中的虚拟IP地址实现的,并没有真实的网络设备存在。 通过 iptables-save可以看到如下规则,这条 iptables 规则的含义是:凡是目的地址是 10.98.191.167、目的端口是 8080 的 IP 包,都应该跳转到另外一条名叫 KUBE-SVC-XYYCMFLZLJQGYLMQ 的 iptables 链进行处理。

而我们前面已经看到,10.98.191.167正是这个 Service 的 VIP。所以这一条规则,就为这个 Service 设置了一个固定的入口地址。并且,由于 10.98.191.167只是一条 iptables 规则上的配置,并没有真正的网络设备,所以你 ping 这个地址,是不会有任何响应的。

KUBE-SVC-XYYCMFLZLJQGYLMQ 它是一组规则的集合,如下所示,这三条链指向的最终目的地,其实就是这个 Service 代理的三个 Pod。所以这一组规则,就是 Service 实现负载均衡的位置。

#  iptables-save
-A KUBE-SERVICES -d 10.98.191.167/32 -p tcp -m comment --comment "default/whoami-clusterip cluster IP" -m tcp --dport 8080 -j KUBE-SVC-XYYCMFLZLJQGYLMQ
-A KUBE-SVC-XYYCMFLZLJQGYLMQ -m comment --comment "default/whoami-clusterip" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-SZWRSKR7UEYM347Q
-A KUBE-SVC-XYYCMFLZLJQGYLMQ -m comment --comment "default/whoami-clusterip" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-GXJY2AW3O6IJVNJZ
-A KUBE-SVC-XYYCMFLZLJQGYLMQ -m comment --comment "default/whoami-clusterip" -j KUBE-SEP-3NPGKIHQFRDXBA2I

2. NodePort
whoami-nodeport.yaml

apiVersion: v1
kind: Service
metadata:
  name: whoami-nodeport
spec:
  type: NodePort
  selector:
    app: whoami
  ports:
    - protocol: TCP
      port: 8080. # service 端口
      targetPort: 8000 # Pod端口
      nodePort: 30000 # 可以指定对外暴露的随机端口。一般30000-32627之间的一个端口就可以
# kubectl apply -f whoami-nodeport.yaml
service/whoami-nodeport created
# kubectl get svc -o wide
NAME              TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE   SELECTOR
whoami-nodeport   NodePort    10.111.44.34   <none>        8080:30000/TCP   8s    app=whoami

通过lsof可以发现在物理机上开辟30000端口

# lsof -i tcp:30000
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
kube-prox 3600 root   12u  IPv4 874479      0t0  TCP *:ndmps (LISTEN)

在集群内通过clusterIP:port访问service

# curl 10.111.44.34:8080
I'm whoami-deployment-8886867c8-pc67z
# curl 10.111.44.34:8080
I'm whoami-deployment-8886867c8-67d4f
# curl 10.111.44.34:8080
I'm whoami-deployment-8886867c8-hgvmb

在集群外通过nodeIP:nodePort 访问, nodeIP就是集群物理机的IP,这里是92.168.0.51、92.168.0.61、92.168.0.62。