Kubernetes Pod编排笔记

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来对资源进行一个有效地管理。此处先放着,学习笔记后面再补

 

 

0XFF Reference