02kubernetes-POD控制器

POD相关命令

## 1.查看所有的node,所有节点
[root@db01 ~]# kubectl get nodes
NAME   STATUS   ROLES    AGE   VERSION
db01   Ready    master   58m   v1.19.3
db02   Ready    <none>   54m   v1.19.3
db03   Ready    <none>   54m   v1.19.3

## 2.给node打标签
# 加标签
kubectl label nodes <node名> node-role.kubenetes.io/node=
# 减标签
kubectl label nodes <node名> node-role.kubenetes.io/node-

## 3.查看所有pod,默认是default名称空间
[root@db01 ~]# kubectl get pods

## 4.指定名称空间查看pod
[root@db01 ~]# kubectl -n get pods kube-system

## 5.输出所有详细信息
# 输出所有pod的详细信息
[root@db01 ~]# kubectl -n kube-system get pods -o wide
# 输出所有节点的详细信息
[root@db01 ~]# kubectl -n kube-system get nodes -o wide

# 6.进入容器
[root@db01 ~]# kubectl exec -it pod名 -c 容器名 -- cmd

# 7.查看日志
[root@db01 ~]# kubectl logs -f pod pod名 

# 8.查看pod创建过程
[root@db01 ~]# kubectl describe pod pod名

POD沉浸式体验

创建pod两种方式

1.清单,yaml文件
2.命令行

清单

# yml文件
nginx_pod.yaml
apiVersion: v1                               ## 版本
kind: Pod                                 ## controller
metadata:                                    ## 元数据
  name: nginx-lw                            ## POD名
  labels:                                    ## 标签
    app: nginx-v1                             ## app: nginx-v1 标签名
spec:                                         ## 容器详细信息
  containers:                                 ## 第一个容器
  - image: nginx:alpine                       ## 容器的镜像
    imagePullPolicy: IfNotPresent             ## 镜像拉取规则,always(默认)
    name: nginx                             ## 容器名字

## 创建容器
kubectl create -f 

## 查看帮助
kubectl explain pods
kubectl explain pods.spec
kubectl explain pods.spec.containers

K8S官方:https://kubernetes.io/docs/reference/config-api/apiserver-audit.v1/

黑科技:https://k8s.mybatis.io/v1.19/

命令行

## 2.命令行
[root@db01 ~]# kubectl create deployment nginx-v1 --image=nginx:alpine

# 查看pod创建流程详细信息
[root@db01 ~]# kubectl describe pods nginx-v1-xxx

# 进入pod
[root@db01 ~]# kubectl exec -it nginx-v1-5b6b969d55-wlfg4 /bin/sh

### 未来版本使用
[root@db01 ~]# kubectl exec -it nginx-v1-5b6b969d55-wlfg4 -- /bin/sh

## 容器名字的组成
k8s_nginx_nginx-lw_default_f55bc7be-69e9-4efe-bafc-3d997b075cc3_0
k8s前缀_容器名_POD名_名称空间_随机值_0后缀

标签的设置与使用

# 1.查看node标签
[root@db01 ~]# kubectl get nodes --show-labels

# 2.给node打标签
## 语法:
kubectl label <操作对象nodes|pods> <对应对象名> 标签名=标签值
[root@db01 ~]# kubectl label nodes db02 CPU=Xeon
[root@db01 ~]# kubectl label nodes db03 Disk=Flash

# 3.根据指定标签查找node
参数: -l
[root@db01 ~]# kubectl get nodes --show-labels -l CPU=Xeon

# 4.删除标签
## 语法
kubectl label <操作对象nodes|pods> <对应对象名> 标签名-
[root@db01 ~]# kubectl label nodes db02 CPU-

## 清单中指定node标签
cat > nginx_pod.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx-v5
  labels:
    app: nginx-v4
spec:
  containers:
  - image: nginx:alpine
    imagePullPolicy: IfNotPresent
    name: nginx-v4
  nodeSelector:     # node节点 
    Disk: Flash     # 指定Flash标签
EOF

# 1.查看pod标签
[root@db01 ~]# kubectl get pods --show-labels

# 2.给pod打标签
[root@db01 ~]# kubectl label pods nginx-lw test=label
pod/nginx-lw labeled
[root@db01 ~]# kubectl get pods --show-labels

# 3.删除pod标签
[root@db01 ~]# kubectl label pods nginx-lw test-

# 4.查找指定标签的pods
[root@db01 ~]# kubectl get pods --show-labels -l app=nginx-v3

## 在清单中打标签
apiVersion: v1
kind: Pod
metadata:
  name: nginx-v5
  labels:
    app: nginx-v4    # 标签
    name: lw         # 标签

[root@db01 ~]# kubectl create -f nginx_pod.yaml 
pod/nginx-v6 created
# 查看pods标签
[root@db01 ~]# kubectl get pods --show-labels
NAME                        READY   STATUS    RESTARTS   AGE     LABELS
nginx-v1-5b6b969d55-wlfg4   1/1     Running   0          82m     app=nginx-v1,pod-template-hash=5b6b969d55
nginx-v2                    1/1     Running   0          9m35s   app=nginx-v2
nginx-v3                    1/1     Running   0          8m25s   app=nginx-v3
nginx-v4                    1/1     Running   0          5m50s   app=nginx-v4
nginx-v5                    1/1     Running   0          5m32s   app=nginx-v4
nginx-v6                    1/1     Running   0          7s      app=nginx-v4,name=lw
nginx-lw                   1/1     Running   0          70m     app=nginx-v1

# 查看指定标签为app=nginx-v4的pods
[root@db01 ~]# kubectl get pods --show-labels -l app=nginx-v4
NAME       READY   STATUS    RESTARTS   AGE     LABELS
nginx-v4   1/1     Running   0          6m6s    app=nginx-v4
nginx-v5   1/1     Running   0          5m48s   app=nginx-v4
nginx-v6   1/1     Running   0          23s     app=nginx-v4,name=lw

## 删除pod
[root@db01 ~]# kubectl delete pods nginx-v2

## 根据标签删除
[root@db01 ~]# kubectl delete pods -l app=nginx-v4

## 一个pod启动多个容器
apiVersion: v1
kind: Pod
metadata:
  name: nginx-redis01
  labels:
    app: nginx-redis
spec:
  containers:
  - image: nginx:alpine
    imagePullPolicy: IfNotPresent
    name: nginx-web01

  - image: redis
    imagePullPolicy: IfNotPresent
    name: redis-db01

# vim 8-14行复制移动到15行
:8,14t15

重新认识pod

共享网络

file

POD内的容器使用Container模式共享根容器的网络
容器看到的网络设备信息和根容器完全相同
POD内的多个容器可以使用localhost进行网络通讯
POD内的多个容器不能绑定相同的端口
POD的生命周期和根容器一样,如果根容器退出了,POD就退出了

# 测试一个pod中运行两个容器
apiVersion: v1
kind: Pod
metadata:
  name: web
  labels:
    app: nginx
spec:
  containers:
  - image: nginx:alpine
    imagePullPolicy: IfNotPresent
    name: nginx-web01
    ports:
    - containerPort: 80

  - image: nginx:alpine
    imagePullPolicy: IfNotPresent
    name: nginx-web02
    ports:
    - containerPort: 8080  # 只是对外暴露8080端口

# 查看日志
[root@db01 ~]# kubectl logs  -f web nginx-web02

## 查看日志
kubectl logs -f nginx nginx2

## 指定node节点
nodeName: node1

## 验证所有机器是否连接根容器
docker inspect

## 进入pod
kubectl exec -it pod名 /bin/bash
kubectl exec -it pod名 -c 容器名 /bin/bash

共享文件

file

默认情况下一个POD内的容器文件系统是互相隔离的
如果想让一个POD容器共享文件那么只需要定义一个Volume,然后两个容器分别挂载到这个Volume中

即:共享存储

cat > nginx_pod.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  nodeName: node2
  volumes:
    - name: nginxlog
      hostPath:
        path: /var/log/nginx  #容器内部需要挂载的路径

  containers:
  - name: nginx-1
    image: nginx
    volumeMounts:
    - name: nginxlog
      mountPath: /var/log/nginx

  - name: tail-log
    image: busybox
    args: [/bin/sh, -c, 'tail -f /var/log/nginx/access.log']
    volumeMounts:
    - name: nginxlog
      mountPath: /var/log/nginx
EOF

POD的生命周期

POD创建流程

file

生命周期

file

init container
初始化容器是指,在主容器启动之前,我们可以让他做一些准备工作。
比如:
1.两个容器做了共享存储,那么我们可以让它先启动一个容器,来对目录进行更改用户和授权
2.容器需要连接数据库,那么可以让初始化容器检测数据库是否可以正常连接,如果可以再启动主容器

hook
PostStart:在容器启动创建后,立即执行,但时间不能太长,否则容器不会是running状态
PreStop:在容器停止前,执行一些命令,主要用于优雅关闭程序

liveness probe
存活探针,用于定义容器内,应用是否满足探针指定状态
readiness probe
就绪探针,指定何时允许容器进入流量

POD对容器的封装和应用

那么我们在工作中,一个pod究竟要放几个容器?

在实际工作中我们除了完成任务以外还需要考虑以后扩容的问题,就拿wordpress举例,有以下两种方案:

第一种:全部放一个pod里

file

第二种: WordPress和MySQL分开

file

那么如何扩容呢?如果第一种方案大家会发现没有办法很好的扩容,因为数据库和wordpress已经绑定成一个整体了,扩容wordpress就得扩容mysql。而第二种方案就要灵活的多。

file

初始化容器

apiVersion: v1
kind: Pod
metadata:
  name: nginx-init
spec:
  nodeName: node2

  volumes: 
  - name: nginx-index
    emptyDir: {}           # 临时创建目录挂载

  initContainers:
  - name: init
    image: busybox
    imagePullPolicy: IfNotPresent
    args: [/bin/sh, -c, 'echo k8s >> /usr/share/nginx/html/index.html']
    args:
    - /bin/sh
    - -c
    - 'echo k8s >> /usr/share/nginx/html/index.html'

    volumeMounts:
    - name: nginx-index
      mountPath: "/usr/share/nginx/html"

  containers:
  - name: nginx
    image: nginx:alpine
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
    volumeMounts:
    - name: nginx-index
      mountPath: "/usr/share/nginx/html"

hook

postStart

apiVersion: v1
kind: Pod
metadata:
  name: nginx-hook
spec:
  nodeName: node2

  containers:
  - name: nginx
    image: nginx:alpine
    lifecycle:
      postStart:
        exec:
          command: [/bin/sh, -c, 'echo k8s > /usr/share/nginx/html/index.html']
    ports:
    - containerPort: 80

preStop

apiVersion: v1
kind: Pod
metadata:
  name: nginx-hook
spec:
  volumes: 
  - name: nginxlog
    hostPath: 
      path: /var/log/nginx/

  containers:
  - name: nginx
    image: nginx:alpine
    lifecycle:
      postStart:
        exec:
          command: [/bin/sh, -c, 'echo postStart and preStop > /usr/share/nginx/html/index.html']
      preStop:
        exec:
          command: [/bin/sh, -c, 'echo bye > /var/log/nginx/stop.log']
    ports:
    - containerPort: 80

    volumeMounts:
    - name: nginxlog
      mountPath: /var/log/nginx/

POD健康检查

存活探针

存活探针简单来说就是用来检测容器的应用程序是否还正常工作,如果应用程序不正常,即使容器还活着也没有意义了,所以这时候就可以使用存活探针来探测,如果应用程序不正常,就重启POD。

## 使用exec方法
apiVersion: v1
kind: Pod
metadata:
  name: liveness-pod
spec:
  nodeName: node2

  volumes: 
  - name: nginx-html
    hostPath: 
      path: /usr/share/nginx/html/

  containers:
  - name: liveness
    image: nginx 
    imagePullPolicy: IfNotPresent

    lifecycle:
      postStart:
        exec:
          command: [/bin/sh, -c, 'echo k8s > /usr/share/nginx/html/index.html']

    livenessProbe:
      exec:
        command:
        - cat
        - /usr/share/nginx/html/index.html
      initialDelaySeconds: 3
      periodSeconds: 1

    volumeMounts:
    - name: nginx-html
      mountPath: /usr/share/nginx/html/

 ## 使用getHttp方法
 apiVersion: v1
kind: Pod
metadata:
  name: liveness-pod
spec:
  nodeName: node2

  volumes: 
  - name: nginx-html
    hostPath: 
      path: /usr/share/nginx/html/

  containers:
  - name: liveness
    image: nginx 
    imagePullPolicy: IfNotPresent

    lifecycle:
      postStart:
        exec:
          command: [/bin/sh, -c, 'echo k8s > /usr/share/nginx/html/index.html']

    livenessProbe:
      #exec:
      #  command:
      #  - cat
      #  - /usr/share/nginx/html/index.html
      httpGet:
        path: /index.html
        port: 80
      initialDelaySeconds: 3
      periodSeconds: 3

    volumeMounts:
    - name: nginx-html
      mountPath: /usr/share/nginx/html/

配置解释

livenessProbe:
  httpGet:                                  #基于http请求探测
    path: /index.html          #请求地址,如果这个地址返回的状态码在200-400之间正常
    port: 80                                #请求的端口
  initialDelaySeconds: 3        #第一次启动探测在容器启动后3秒开始
  periodSeconds: 3                  #容器启动后每隔3秒检查一次

就绪探针

有时候我们Pod本身已经起来了,但是pod的容器还没有完全准备好对外提供服务,那么这时候流量进来就会造成请求失败的情况出现,针对这种情况k8s有一种探针叫就绪探针,他的作用就是让k8s知道你的Pod内应用是否准备好为请求提供服务。只有就绪探针ok了才会把流量转发到pod上。

有时候,应用程序会暂时性的不能提供通信服务。 例如,应用程序在启动时可能需要加载很大的数据或配置文件,或是启动后要依赖等待外部服务。 在这种情况下,既不想杀死应用程序,也不想给它发送请求。 Kubernetes 提供了就绪探测器来发现并缓解这些情况。 容器所在 Pod 上报还未就绪的信息,并且不接受通过 Kubernetes Service 的流量。

apiVersion: v1
kind: Pod
metadata:
  name: liveness-pod
spec:
  containers:
  - name: liveness-pod
    image: nginx
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo ok > /usr/share/nginx/html/health.html"]
    readinessProbe:
      httpGet:
        path: /actuator/health
        port: 8080
      initialDelaySeconds: 5
      timeoutSeconds: 3
      periodSeconds: 3
      successThreshold: 3
      failureThreshold: 3
    livenessProbe:
      httpGet:
        path: /health.html
        port: 80
      initialDelaySeconds: 3
      periodSeconds: 3

配置解释

initialDelaySeconds :   第一次执行探针需要在容器启动后等待的时候时间periodSeconds :         容器启动后每隔多少秒执行一次存活探针
timeoutSeconds:         探针超时时间,黑t认1秒,最小1秒
successThreshold:       探针失败后最少连续探测成功多少次才被认定成功,默认1次,如果是liveness必须为1
failureThreshold:       探针成功后被视为失败的探测的最小连续失败次数。默认3次。最小值为1

POD资源限制

在学习Docker的时候我们知道容器可以使用Linux系统的CGroup技术限制内存和CPU的使用率,那么POD里应该如何限制容器的CPU和内存资源呢?

apiVersion: v1
kind: Pod
metadata:
  name: resource-demo
spec:
  containers:
  - name: resource-demo
    image: nginx
    ports:
    - containerPort: 80
    resources:
      requests:
        memory: 50Mi
        cpu: 1500m
      limits:
        memory: 100Mi
        cpu: 2000m

参数解释:

requests :节点所需的最小计算资源量,k8s调度的时候的依据值
limits :限制允许的最大计算资源量,真正的资源限制参数

数值的转换:

1 CPU = 1000m
0.5 CPU = 500m
1 Mib = 1024 Kib
1 MB = 1000 KB

查看验证:

docker inspect 容器ID|grep CgroupParent
cd /sys/fs/cgroup/cpu/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podxxxx.slice
cat cpu.cfs_quota_us

山林不向四季起誓 荣枯随缘