第五章 Kubernetes进阶之Pod

  Pod

  • 最小部署单元
  • 一组容器的组合
  • 一个Pod中容器共享网络命名空间
  • Pod是短暂的

  Pod容器分类

  Infrastructure Container 基础容器

    维护整个Pod网络空间

  InitContainers 初始化容器

    先于业务容器运行

  Container 业务容器

    并行启动

  镜像拉取策略

  • IfNotPresent:默认值,镜像在宿主机上不存在时才拉取
  • Alway:每次创建Pod都会拉取一次镜像
  • Never:Pod永远不会拉取这个镜像

  查看默认镜像拉取参数是否是IfNotPresent

kubectl get deploy/nginx-deployment -o yaml

 

   没有认证的公共镜像仓库可以直接拉取,搭建私有镜像仓库Habor

  本次搭建的主机为192.168.1.61,之前使用改主机搭建了nginx+keepalived为了不冲突需要关闭该主机的nginx即使用192.168.1.62来产生VIP192.168.1.60

  搭建参考

  https://www.cnblogs.com/minseo/p/8905736.html

  登录Harbor创建一个私有项目project

  默认用户名:admin 密码:Habor123456

 

   私有仓库需要登录才能下载,Harbor不是http提供访问,需要在node 192.168.1.65 192.168.1.66配置可信任

# cat /etc/docker/daemon.json 
{
          "registry-mirrors": ["https://7sl94zzz.mirror.aliyuncs.com"],
          "insecure-registries": ["192.168.1.61"]
}

   node上面登录,输入用户名和密码

docker login 192.168.1.61

 

   查看该node已有的镜像

docker images

   下载一个tomcat镜像用于推送测试

docker pull tomcat

   下载完毕打tag

docker tag tomcat 192.168.1.61/project/tomcat

   查看

   推送至harbor私有仓库

docker push 192.168.1.61/project/tomcat

 

   推送成功在harbor上可以看到

   排错,推送是出现提示,查看haabor该项目是否创建

requested access to the resource is denied

   在另外一台node上拉取该镜像

docker pull 192.168.1.61/project/tomcat

   PS:需要在该node节点至少登录过一次才能下载,否则会出现如下提示

 docker pull 192.168.1.61/project/tomcat
Using default tag: latest
Error response from daemon: pull access denied for 192.168.1.61/project/tomcat, repository does not exist or may require 'docker login': denied: requested access to the resource is denied

   推送至harbor的镜像是私有的,如果是通过k8s部署则是拉取公网的镜像无法拉取到私有的镜像,需要通过配置imagePullSecrets参数才能从私有仓库拉取镜像

  示例

# cat tomcat-deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: tomcat
  name: tomcat
spec:
  replicas: 3
  selector:
    matchLabels:
      run: tomcat
  template:
    metadata:
      labels:
        run: tomcat
    spec:
      containers:
      - image: tomcat
        name: tomcat
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  labels:
    run: tomcat
  name: tomcat-service
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    run: tomcat
  type: NodePort

   该yaml配置文件可以通过以下命令生成

#生成deployment配置文件
 kubectl run tomcat --replicas=3 --image=tomcat --port=8080 --dry-run -o yaml>>tomcat-deployment2.yaml 
#间隔符 多个配置需要间隔,否则创建时候部分不生效
echo "---" >>tomcat-deployment2.yaml
#生成service配置文件
#生成该配置文件需要指定的deployment已经在运行中即要允许了命令 kubectl run tomcat --replicas=3 --image=tomcat --port=8080
#可以先运行再删除该deployment
kubectl expose deployment tomcat --port=8080 --type=NodePort --target-port=8080 --name=nginx-service --dry-run -o yaml >> tomcat-deployment.yaml 

   使用配置文件创建deployment和service

# kubectl create -f tomcat-deployment.yaml 
deployment.apps/tomcat created
service/tomcat-service created

   查看

# kubectl get pod,svc
NAME                         READY   STATUS    RESTARTS   AGE
pod/tomcat-5d6455cc4-lpwht   1/1     Running   0          36s
pod/tomcat-5d6455cc4-wnfsh   1/1     Running   0          36s
pod/tomcat-5d6455cc4-zgvbp   1/1     Running   0          36s

NAME                     TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
service/kubernetes       ClusterIP   10.10.10.1     <none>        443/TCP          6d2h
service/tomcat-service   NodePort    10.10.10.105   <none>        8080:37426/TCP   36s

   通过node ip加NodePort端口即可访问tomcat默认页面

  配置文件指定镜像是从docker hub拉取的,现在改成私有镜像的地址,因为默认的策略是优先拉取本机已有镜像所以拉取镜像策略改成Always

  修改yaml配置文件,修改以下两处

   应用更新

# kubectl apply -f tomcat-deployment.yaml 
deployment.apps/tomcat configured
service/tomcat-service unchanged

 

   查看pod事件

kubectl describe pod tomcat-78876547c6-jn7c4

 

   需要配置凭据才能拉取

  在已经docker login过的node上面获取

cat /root/.docker/config.json | base64 -w0

 

   复制这串字符编辑配置文件

#cat registry-pull-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: registry-pull-secret
data:
  .dockerconfigjson: ewoJImF1dGhzIjogewoJCSIxOTIuMTY4LjEuNjEiOiB7CgkJCSJhdXRoIjogIllXUnRhVzQ2U0dGeVltOXlNVEl6TkRVPSIKCQl9Cgl9LAoJIkh0dHBIZWFkZXJzIjogewoJCSJVc2VyLUFnZW50IjogIkRvY2tlci1DbGllbnQvMTkuMDMuNiAobGludXgpIgoJfQp9
type: kubernetes.io/dockerconfigjson

   应用

# kubectl create -f registry-pull-secret.yaml 
secret/registry-pull-secret created

   查看已经生成secret

# kubectl get secret
NAME                   TYPE                                  DATA   AGE
default-token-pw8st    kubernetes.io/service-account-token   3      6d2h
registry-pull-secret   kubernetes.io/dockerconfigjson        1      22s

   修改tomcat-deployment.yaml增加认证

   修改后完整的yaml文件如下

# cat tomcat-deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: tomcat
  name: tomcat
spec:
  replicas: 3
  selector:
    matchLabels:
      run: tomcat
  template:
    metadata:
      labels:
        run: tomcat
    spec:
      imagePullSecrets: 
      - name: registry-pull-secret
      containers:
      - image: 192.168.1.61/project/tomcat
        imagePullPolicy: Always
        name: tomcat
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  labels:
    run: tomcat
  name: tomcat-service
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    run: tomcat
  type: NodePort

   应用更改

kubectl apply -f tomcat-deployment.yaml

   查看

# kubectl get pod,svc
NAME                          READY   STATUS    RESTARTS   AGE
pod/tomcat-68c76b858d-5lq22   1/1     Running   0          4m41s
pod/tomcat-68c76b858d-ckrqr   1/1     Running   0          4m45s
pod/tomcat-68c76b858d-dctgt   1/1     Running   0          4m43s

NAME                     TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
service/kubernetes       ClusterIP   10.10.10.1     <none>        443/TCP          6d3h
service/tomcat-service   NodePort    10.10.10.105   <none>        8080:37426/TCP   29m

   因为镜像拉取策略是Always所以从pod的运行时间即可看出是否拉取了私有仓库的镜像

  登录Harbor查看也可以看到本次拉取镜像是从私有仓库拉取

 

   拍错:访问tomcat出现404错误提示,原因是tomcat镜像根目录没有文件,解决办法

#分别进入容器
kubectl exec -it tomcat-68c76b858d-5lq22 -c tomcat bash
kubectl exec -it tomcat-68c76b858d-ckrqr -c tomcat bash
kubectl exec -it tomcat-68c76b858d-dctgt -c tomcat bash
#复制根目录文件,默认webapps为空
cd /usr/local/tomcat
rm -rf webapps
mv webapps.dist/ webapps

  资源限制

  为了防止某个Pod占用资源过多影响宿主机需要对Pod进行资源限制

  Pod中的每个容器都可以指定一下一个或者多个值

spec.containers[].resources.limits.cpu
spec.containers[].resources.limits.memory
spec.containers[].resources.requests.cpu
spec.containers[].resources.requests.memory

   示例,该示例可以在官方复制https://kubernetes.io/zh/docs/concepts/configuration/manage-compute-resources-container/

  以下 Pod 有两个容器。每个容器的请求为 0.25 cpu 和 64MiB(226 字节)内存,每个容器的限制为 0.5 cpu 和 128MiB 内存。您可以说该 Pod 请求 0.5 cpu 和 128 MiB 的内存,限制为 1 cpu 和 256MiB 的内存。

# cat pod2.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: db
    image: mysql
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: "password"
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
  - name: wp
    image: wordpress
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

   查看该pod分配到那一台node

kubectl describe pod frontend

 

   查看资源限制是否生效

kubectl describe nodes 192.168.1.66

 

   Pod重启策略

  restartPolicy

  • Always:当容器终止退出后,总是重启容器,默认策略
  • OnFailure:当容器异常退出(退出状态码非0)时,才重启容器
  • Never:当容器终止退出,从不重启容器

  查看

kubectl edit pods nginx-7cdbd8cdc9-ngpgr

 

   示例

# cat pod3.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: foo
spec:
  containers:
  - name: busybox
    image: busybox
    args:
    - /bin/sh
    - -c
    - sleep 30 ; exit 3

   该yaml执行进入容器后等待30秒退出

  应用

kubectl apply -f pod3.yaml

   查看pod会从running状态,到退出会提示错误状态,因为策略是Always所以又重启一次 

 

   修改

apiVersion: v1
kind: Pod
metadata:
  name: foo
spec:
  containers:
  - name: busybox
    image: busybox
    args:
    - /bin/sh
    - -c
    - sleep 10
  restartPolicy: Never

   删除再应用

kubectl delete -f pod3.yaml
kubectl apply -f pod3.yaml 

   查看状态,容器运行10秒以后正常退出了,策略为Never所以不再新启动一个pod 状态显示完成状态

   健康检查

  Probe有以下两种类型

  livenessProbe

  如果检查失败,将杀死容器,根据Pod的restartPolicy来操作

  readinessProbe 

  如果检查失败,Kubernetes会把Pod从service endpoint中剔除

  查看endpoint使用命令

# kubectl get ep
NAME             ENDPOINTS                                            AGE
kubernetes       192.168.1.63:6443,192.168.1.64:6443                  6d4h
tomcat-service   172.17.41.4:8080,172.17.55.2:8080,172.17.55.5:8080   131m

   Probe支持以下三种检查方法

  HttpGet

  发送HTTP请求,返回200-400范围状态码为成功

  exec

  执行shell命令返回状态码是0为成功

  tcpSocket

  发起TCP Socket建立成功

  官方示例 下载地址https://kubernetes.io/zh/docs/concepts/configuration/manage-compute-resources-container/

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    image: busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      #启动延时5秒以后开始健康检查
      initialDelaySeconds: 5
      #健康检查周期是5秒
      periodSeconds: 5

   应用

kubectl apply -f pod4.yaml

   启动后创建了健康检查文件,等待30秒以后,删除了健康检查文件,健康检查没有发现该文件就重启容器了

   查看pod的描述日志

   企业生产环境中需要配置健康检查

  Pod调度约束

  可以让Pod放在指定节点上,例如A部门创建的Pod放在一台node,B部门创建的Pod放在另一台node

  用户创建Pod过程

   nodeName用于将Pod调度到指定的Node名称上

  nodeSelector用于将Pod调度到匹配Label的Node上

#cat pod5.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-example
  labels:
    app: nginx
spec:
  nodeName: 192.168.1.65
  containers:
  - name: nginx
    image: nginx

 

   设置标签

#设置标签
kubectl label nodes 192.168.1.65 team=a
kubectl label nodes 192.168.1.66 team=b
#查看标签
kubectl get nodes --show-labels

  删除标签

#在标签后加-号即可删除标签
kubectl label nodes 192.168.1.65 team-
kubectl label nodes 192.168.1.66 team-

 

   在yaml文件里面设置标签

# cat pod6.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-example
  labels:
    app: nginx
spec:
  nodeSelector:
    team: b
  containers:
  - name: nginx
    image: nginx

   应用

kubectl apply -f pod6.yaml

   查看

   PS:如果调度约束配置不正确Pod会出现Pending状态查看描述会出现以下错误提示

Warning  FailedScheduling  27s (x2 over 27s)  default-scheduler  0/2 nodes are available: 2 node(s) didn't match node selector.

   故障排查

值  描述
Pending Pod创建已经提交k8s,但是因为,某种原因不能顺利创建。例如下载镜像慢,调度不成功
Running Pod已经绑定到一个节点,并且已经创建了所有容器。至少有一个容器在运行,或正在启动或重启
Suceeded Pod中所有容器都已成功终止,不会重新启动
Failed Pod中所有容器已终止,且至少有一个容器已在故障中终止,也就是说,容器要么已非零状态退出,要么被系统终止
Unknown 由于某种原因apiserver无法获取Pod的状态,通常是由于master与pod所在主机kubelet通信时出错

  故障排查命令

#查看pod事件
kubectl describe TYPE/NAME
#查看pod日志
kubectl logs TYPE/NAME 
#登录容器查看
kubectl exec POD [-c CONTAINER] -- COMMAND [args...]

  

  

原文地址:https://www.cnblogs.com/minseo/p/12411241.html