0X01Pod原理
Pod是Kubernetes项目中最小的API对象,也是最小部署单元。因此可以简化为
Pod是Kubernetes项目的原子调度单位
与Docker相比,一个Pod就像是一个分享namespace和volume文件卷的Docker容器组群。Pod里的所有容器,共享的是同一个Network Namespace,并且可以声明共享一个Volume,因此该Pod也可因通过如下docker命令来实现
docker run --net=B --volumes-from=B --name=A image-A
同时,要保证容器不像上面命令一样先启动容器B再启动容器A从而将Pod的对等关系更改成拓扑关系,因此Kubernetes需要使用一个中间容器——Infra。在这个Pod中,Infra永远都是第一个创建的容器,而其他容器则是用Join Network Namespace的方式加入到Infra容器中,类似于下图
运行一个Pod程序的yaml文件为
apiVersion: v1
kind: Pod
metadata:
name: website
labels:
app: website
role: frontend
spec:
containers:
- name: website
image: nginx
ports:
- containerPort: 80
使用命令kubectl apply -f pod.yaml 既可以看到一个Pod被成功启动
kubectl get pod
NAME READY STATUS RESTARTS AGE
website 1/1 Running 0 3m2s
同时docker image上也能看到镜像的产生,如果docker ps看不到对应的镜像,则可以使用命令eval $(minikube -p minikube docker-env),之后使用docker ps查看
Pod是Kubernetes项目中最小的编排单位,将这个设计落实到API对象上。同时Pod扮演的是传统部署环境“虚拟机”的角色。这样的设计,是为了使用户从传统环境(虚拟机环境)向 Kubernetes(容器环境)的迁移,更加平滑,凡是调度、网络、存储,以及安全相关的属性,基本上是Pod级别。对于Pod的生命周期来说,Pod被认为是相对临时性的整体,如果一个节点卡死掉,那么调度到该节点的Pod也被计划在给定超时期限结束后删除。
使用6443操控API
笔者使用Docker-Desktop启动的K8S,因此config文件位于~/.kube/config下,使用命令
- grep 'client-key-data' ~/.kube/config | head -n 1 | awk '{print $2}' | base64 -d > ./client-key.pem
- grep client-cert ~/.kube/config| head -n 1 | awk '{print $2}' | base64 -d > ./client.pem
- grep certificate-authority-data ~/.kube/config | head -n 1 | awk '{print $2}' | base64 -d > ./ca.pem
保存密匙值,之后即可以调用API操控kubectl
curl --cert ./client.pem --key ./client-key.pem --cacert ./ca.pem https://127.0.0.1:6443/api/v1/pods
各种API的使用可以参考Python kubernetes的使用列表https://github.com/kubernetes-client/python/tree/master/kubernetes
0X02 Pod, Deployment与StatefulSets
Deployment
Pod学习之后就是Deployment,Deployment常用来提供Pod和ReplicaSets,ResplicaSets则用于设置Pod的集群数量replicas参数。Demo如下
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
securityContext:
privileged: true
ports:
- containerPort: 80
protocol: TCP
如果我们需要增加Deployment的集群,则可以直接使用命令kubectl scale deployment nginx-deployment --replicas=2 来对replicas进行设置,即“滚动更新”,之后我们便得到了两个pod
kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-775f89ff7f-59ff6 1/1 Running 0 16m
nginx-deployment-775f89ff7f-tjjnp 1/1 Running 0 49m
执行命令访问主页端口得到
根据官网上的选择,使用Deployment有如下几个场景:
- 为了使用ReplicaSet集群
- 需要申明一个新状态的Pod
- 需要回退到更早的一个Deploymeny修正版
- 促进Deploymeny更好地扩展
- 暂停一个Deploymeny的推出
- 清除老的Replicasets
StatefulSets
对于StatfulSet,其主要作用为管理Pod集群中的Deployment和scaling,并且提供了Pod名字唯一的保证。与Deployment类似,StatfulSet管理基于相同容器规范的Pod,但是不同的是StatefulSet为每一个Pod维护一个长久的唯一身份ID。我们可以使用如下demo创建一个StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
name: web
当我们对yaml文件进行apply之后得到的返回为
kubectl get pod
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 8m8s
当我们把集群更改为2的时候得到如下显示
kubectl get pod
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 11m
web-1 1/1 Running 0 2m53s
可以看到pod的命令都自增的ID,不像Deployment那样使用随机字符命名。因此在Deployment与StatefulSet之间,如果满足如下条件,可以选择StatefulSet
- 稳定的、唯一的网络识别
- 稳定的、持久的存储
- 有序的、优雅地部署和伸缩
- 有序地、优雅的删除和停止
- 有序地、自动的滚动更新
0X03 使用Helm管理Kubernetes应用
如果我们K8S上要使用的yaml文件过于庞大,那么就无法很好地保证每一个yaml文件和Pod都是有效地被执行。因此我们需要使用Helm来对资源进行一个有效地管理。此处先放着,学习笔记后面再补