第五章 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 密码:Harbor12345
私有仓库需要登录才能下载,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"] }
设置可信任之后需要重启docker否则下面操作无法登录
systemctl restart docker
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已经在运行中即要已经运行了命令启动了delpoyment
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...]