一、 pod介绍
在kubernetes的世界中,k8s并不直接处理容器,而是使用多个容器共存的理念,这组容器就叫做pod。
pod是k8s中可以创建和管理的最小单元,是资源对象模型中由用户创建或部署的最小资源对象模型,其他的资源对象都是用来支撑pod对象功能的,比如,pod控制器就是用来管理pod对象的,service或者imgress资源对象是用来暴露pod引用对象的,persistentvolume资源是用来为pod提供存储等等,简而言之,k8s不会直接处理容器,而是pod,pod才是k8s中可以创建和管理的最小单元,也是基本单元。
二、pod的特点
- 每个pod就像一个独立的逻辑机器,k8s会为每个pod分配一个集群内部唯一的IP地址,所以每个pod都拥有自己的IP地址、主机名、进程等;
- 一个pod可以包含1个多多个容器,1个容器一般被设计成只运行1个进程,1个pod只可能运行在单个节点上,即不可能1个pod跨节点运行,pod的生命周期是短暂的,也就是说pod可能随时被消亡(如节点异常,pod异常等情况);
- 每个pod都有一个特殊的被称为"根容器"的pause容器,也称为info容器,pause容器对应的镜像属于k8s平台的一部分,除了pause容器,每个pod还包含了一个或多个跑业务相关组件的容器;
- 一个pod中的容器共享network命名空间;
- 一个pod里的多个容器共享pod IP,这就意味着1个pod里面的多个容器的进程所占用的端口不能相同,否则在这个pod里面就会产生端口冲突,既然每个pod都有自己的IP和端口空间,那么对不同的pod来说就不可能存在端口冲突;
- 应该就应用程序组织到多个pod中,而每个pod只包含紧密相关的组件或进程;
- pod是k8s扩容,缩容的基本单位,也就是说k8s中扩容缩容是针对pod而言而并非容器。
pod共享存储实现机制:引入数据卷volume,使用数据卷进行持久化存储。
三、pod背后的根本原理
一个容器一般被设计一个进程,除非进程本身产生子进程,由于不能将多个进程聚集在同一个单独的容器中,所有需要一种更高级的结构容器绑定在一起,并将它们作为一个单元进行管理,这就是pod背后原理。
四、命令行创建pod、查看pod
#注意:kubectl run 在旧版本中创建的是deployment,但在本书的版本中创建的是pod
创建pod
kubectl run nginx --image=nginx --labels="app=nginx" --port=80
- kubectl run nginx 创建一个pod,pod名称为nginx
- --image=nginx 容器镜像为nginx:latest
- --labels="app=nginx" 设置一个标签app=nginx
- --port=80 声明pod的服务端口为80
查看pod
kubectl get pod -n default
bash
# kubectl get pod -n default
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 98s
- -n default 指定资源所属的命名空间,默认是default
查看pod运行在哪个节点上
kubectl get pod -n default -o wide
bash
# kubectl get pod -n default -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 4m9s 192.168.69.212 k8s-worker02 <none> <none>
kubectl desc 命令查看pod的详细信息
kubectl describe pod nginx
bash
# kubectl describe pod nginx
Name: nginx # pod 名称
Namespace: default # 所属命名空间
Priority: 0 # 这个参数是优先级
Node: k8s-worker02/192.168.44.155 # pod所在节点及节点IP地址
Start Time: Thu, 22 Feb 2024 10:41:11 +0800 # pod启动时间
Labels: app=nginx # pod 标签
Annotations: cni.projectcalico.org/containerID: 4d32f0fa5e998cbc78194c118e73353731dd1c7b93f6a61b4b3e9e6d6948938c
cni.projectcalico.org/podIP: 192.168.69.212/32
cni.projectcalico.org/podIPs: 192.168.69.212/32 # Annotations 是注释
Status: Running # pod 运行状态
IP: 192.168.69.212 # pod IP地址
IPs:
IP: 192.168.69.212
Containers: # 容器部分,一个pod可以跑多个容器
nginx:
Container ID: docker://f3e553dbfdb1b77773ee07f35024cdb77b1d32d55c13d10ee4fcb445e25a6b54 # 容器ID
Image: nginx # 镜像
Image ID: docker-pullable://nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31 #镜像ID
Port: 80/TCP # pod服务端口
Host Port: 0/TCP
State: Running # 容器状态
Started: Thu, 22 Feb 2024 10:41:28 +0800 # 容器启动时间
Ready: True # 是否准备就绪
Restart Count: 0 # 重启次数
Environment: <none> # 环境变量
Mounts: # 容器挂载点
/var/run/secrets/kubernetes.io/serviceaccount from default-token-2jswl (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-2jswl:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-2jswl
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events: # pod 启动的事件,在这里可以排查pod异常的原因
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 6m15s default-scheduler Successfully assigned default/nginx to k8s-worker02
Normal Pulling 6m14s kubelet, k8s-worker02 Pulling image "nginx"
Normal Pulled 5m58s kubelet, k8s-worker02 Successfully pulled image "nginx" in 15.560370431s
Normal Created 5m58s kubelet, k8s-worker02 Created container nginx
Normal Started 5m58s kubelet, k8s-worker02 Started container nginx
查看pod的yaml文件
kubectl get pod nginx -o yaml
bash
# kubectl get pod nginx -o yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
cni.projectcalico.org/containerID: 4d32f0fa5e998cbc78194c118e73353731dd1c7b93f6a61b4b3e9e6d6948938c
cni.projectcalico.org/podIP: 192.168.69.212/32
cni.projectcalico.org/podIPs: 192.168.69.212/32
creationTimestamp: "2024-02-22T02:41:11Z"
labels:
app: nginx
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:labels:
.: {}
f:app: {}
f:spec:
f:containers:
k:{"name":"nginx"}:
.: {}
f:image: {}
f:imagePullPolicy: {}
f:name: {}
f:ports:
.: {}
k:{"containerPort":80,"protocol":"TCP"}:
.: {}
f:containerPort: {}
f:protocol: {}
f:resources: {}
f:terminationMessagePath: {}
f:terminationMessagePolicy: {}
f:dnsPolicy: {}
f:enableServiceLinks: {}
f:restartPolicy: {}
f:schedulerName: {}
f:securityContext: {}
f:terminationGracePeriodSeconds: {}
manager: kubectl-run
operation: Update
time: "2024-02-22T02:41:11Z"
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
.: {}
f:cni.projectcalico.org/containerID: {}
f:cni.projectcalico.org/podIP: {}
f:cni.projectcalico.org/podIPs: {}
manager: calico
operation: Update
time: "2024-02-22T02:41:12Z"
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:status:
f:conditions:
k:{"type":"ContainersReady"}:
.: {}
f:lastProbeTime: {}
f:lastTransitionTime: {}
f:status: {}
f:type: {}
k:{"type":"Initialized"}:
.: {}
f:lastProbeTime: {}
f:lastTransitionTime: {}
f:status: {}
f:type: {}
k:{"type":"Ready"}:
.: {}
f:lastProbeTime: {}
f:lastTransitionTime: {}
f:status: {}
f:type: {}
f:containerStatuses: {}
f:hostIP: {}
f:phase: {}
f:podIP: {}
f:podIPs:
.: {}
k:{"ip":"192.168.69.212"}:
.: {}
f:ip: {}
f:startTime: {}
manager: kubelet
operation: Update
time: "2024-02-22T02:41:28Z"
name: nginx
namespace: default
resourceVersion: "795586"
selfLink: /api/v1/namespaces/default/pods/nginx
uid: 814ff88b-a5ec-4bb1-9393-4c2b75807cf6
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
ports:
- containerPort: 80
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: default-token-2jswl
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
nodeName: k8s-worker02
preemptionPolicy: PreemptLowerPriority
priority: 0
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
volumes:
- name: default-token-2jswl
secret:
defaultMode: 420
secretName: default-token-2jswl
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2024-02-22T02:41:11Z"
status: "True"
type: Initialized
- lastProbeTime: null
lastTransitionTime: "2024-02-22T02:41:28Z"
status: "True"
type: Ready
- lastProbeTime: null
lastTransitionTime: "2024-02-22T02:41:28Z"
status: "True"
type: ContainersReady
- lastProbeTime: null
lastTransitionTime: "2024-02-22T02:41:11Z"
status: "True"
type: PodScheduled
containerStatuses:
- containerID: docker://f3e553dbfdb1b77773ee07f35024cdb77b1d32d55c13d10ee4fcb445e25a6b54
image: nginx:latest
imageID: docker-pullable://nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
lastState: {}
name: nginx
ready: true
restartCount: 0
started: true
state:
running:
startedAt: "2024-02-22T02:41:28Z"
hostIP: 192.168.44.155
phase: Running
podIP: 192.168.69.212
podIPs:
- ip: 192.168.69.212
qosClass: BestEffort
startTime: "2024-02-22T02:41:11Z"
对外暴露服务、测试访问
以上我们创建了一个名为nginx的pod,但是这个pod还不能被外部客户端连接访问,我们还需要做一步就是对外暴露pod,让外部客户端能访问k8s集群的pod服务,所有我们需要创建一个service,并将pod内容器的服务端口映射到节点IP的端口,如下所示:
kubectl expose pod nginx -n default --port=8088 --target-port=80 --type=NodePort --name=nginx
- --port=8088 表示集群内节点访问的端口
- --target=80 表示pod里面容器的应该程序的端口
查看service和pod
kubectl get svc,pod nginx
bash
# kubectl get svc,pod nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/nginx NodePort 10.98.244.33 <none> 8088:32765/TCP 2m58s
NAME READY STATUS RESTARTS AGE
pod/nginx 1/1 Running 1 30m
- 创建了一个nginx service资源对象,并且有一个固定的IP10.98.244.33,并将访问节点端口 32765 的流量转发到 nginx service 的8088端口。service 又将访问8088端口的流量转发到 pod容器内部服务的端口 80
- 确保防火墙开通了32765 的入方向
- 所有节点都监听 32765 端口,访问任意节点IP + 32765 都能访问到服务
编辑service
如果需要修改外部访问端口或者需要修改一下刚开定义的service,这时我们可以使用kubectl edit
编辑刚才创建的service,如下:
kubectl edit service nginx
bash
# kubectl edit service nginx
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
kind: Service
metadata:
creationTimestamp: "2024-02-22T03:08:49Z"
labels:
app: nginx
name: nginx
namespace: default
resourceVersion: "799626"
selfLink: /api/v1/namespaces/default/services/nginx
uid: fc4a5900-1e80-41dc-838b-79d2fc68e640
spec:
clusterIP: 10.98.244.33
externalTrafficPolicy: Cluster
ports:
- nodePort: 30005 # 修改一下对外暴露的端口为30005,注意:端口是有范围的,NodePort端口范围默认是30000-32767,可以通过修改`kube-apiserver`的参数来进行调整
port: 8088
protocol: TCP
targetPort: 80
selector:
app: nginx
sessionAffinity: None
type: NodePort
status:
loadBalancer: {}
保存后,再次查看service 和 pod
kubectl get pod,svc nginx
bash
# kubectl get pod,svc nginx
NAME READY STATUS RESTARTS AGE
pod/nginx 1/1 Running 1 48m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/nginx NodePort 10.98.244.33 <none> 8088:30005/TCP 20m
可以看出节点端口已经变成30005了
访问测试:
参考放到最下面,大部分都是借鉴,做了少部分的补充:
https://blog.csdn.net/MssGuo/article/details/122894684