一. Pod介绍与容器分类
1.Pod的特性
• 最小部署单元
• 一组容器的集合,紧密关联的容器考虑放到一个pod中
• 一个Pod中的容器共享网络命名空间
• Pod是短暂的
2. Pod容器分类
1). 基础容器
Infrastructure Container 基础容器, 维护整个Pod网络空间,这容器对用户是透明的,在node节点docker ps可以看到,node节点的kubelet配置也会指定基础容器镜像,由配置文件--pod-infra-container-image参数指定,可将此镜像指定为自己的私有镜像。
# cat /opt/kubernetes/cfg/kubelet
KUBELET_OPTS="--logtostderr=false \
--log-dir=/opt/kubernetes/logs/kubelet \
--v=4 \
--hostname-override=10.40.6.210 \
--kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig \
--bootstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig \
--config=/opt/kubernetes/cfg/kubelet.config \
--cert-dir=/opt/kubernetes/ssl \
--pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0"
2). 初始化容器
InitContainers 初始化容器,先于业务容器开始执行
https://kubernetes.io/zh/docs/concepts/workloads/pods/init-containers/
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox
command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
- name: init-mydb
image: busybox
command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
3). 业务容器
Containers 业务容器,并行启动
二. Pod 镜像拉取
1. 镜像拉取策略(imagePullPolicy)
• IfNotPresent:默认值,镜像在宿主机上不存在时才拉取
kubectl get deploy/nginx-deployment -o yaml |grep imagePullPolicy
• Always:每次创建 Pod 都会重新拉取一次镜像
• Never: Pod 永远不会主动拉取这个镜像
apiVersion: v1
kind: Pod
metadata:
name: foo
namespace: awesomeapps
spec:
containers:
- name: foo
image: janedoe/awesomeapp:v1
imagePullPolicy: IfNotPresent
2. 拉取私有镜像仓库镜像
镜像库有些私有镜像需要登录验证后才能拉取镜像,也就是需要凭据才能下载镜像。
apiVersion: v1
kind: Pod
metadata:
name: foo
namespace: awesomeapps
spec:
containers:
-name: foo
image: janedoe/awesomeapp:v1
imagePullSecrets: ##配置拉取镜像凭据,凭据名为myregistrykey
-name: myregistrykey
1). 生成私有镜像仓库凭据 secret
kubernetes登录私有镜像仓库凭据生成: node节点使用授权用户登录私有镜像,在node本机会生成 ~/.docker/config.json文件,此文件就是登录Harbor的验证信息。然后用Base64编码:cat ~/.docker/config.json |base64 -w 0 ,这个可理解为连接token。在master 节点创建yaml资源管理文件,通过yaml 文件创建secret资源, 用于管理登录私有镜像仓库凭据。
# docker pull 10.40.6.165/project/nginx:v2
Error response from daemon: Get https://10.40.6.165/v2/: dial tcp 10.40.6.165:443: connect: connection refused
# docker login 10.40.6.165
Username: liuzhousheng
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
# cat ~/.docker/config.json
{
"auths": {
"10.40.6.165": {
"auth": "bGl1emhvdXNoZW5nOlpob3UmJjEwMTI="
}
},
"HttpHeaders": {
"User-Agent": "Docker-Client/18.09.6 (linux)"
}
# cat ~/.docker/config.json |base64 -w 0
ewoJImF1dGhzIjogewoJCSIxMC40MC42LjE2NSI6IHsKCQkJImF1dGgiOiAiYkdsMWVtaHZkWE5vWlc1bk9scG9iM1VtSmpFd01UST0iCgkJfQoJfSwKCSJIdHRwSGVhZGVycyI6IHsKCQkiVXNlci1BZ2VudCI6ICJEb2NrZXItQ2xpZW50LzE4LjA5LjYgKGxpbnV4KSIKCX0KfQ==
# cat registry-pull-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: registry-pull-secret ## 凭据名
data:
.dockerconfigjson: ewoJImF1dGhzIjogewoJCSIxMC40MC42LjE2NSI6IHsKCQkJImF1dGgiOiAiYkdsMWVtaHZkWE5vWlc1bk9scG9iM1VtSmpFd01UST0iCgkJfQoJfSwKCSJIdHRwSGVhZGVycyI6IHsKCQkiVXNlci1BZ2VudCI6ICJEb2NrZXItQ2xpZW50LzE4LjA5LjYgKGxpbnV4KSIKCX0KfQ==
type: kubernetes.io/dockerconfigjson
# kubectl create -f registry-pull-secret.yaml
# kubectl get secret
NAME TYPE DATA AGE
default-token-qmpxc kubernetes.io/service-account-token 3 4d3h
registry-pull-secret kubernetes.io/dockerconfigjson 1 2m17s
2). yaml配置文件指定凭据
修改deployment 控制器yaml资源配置文件,拉取私有镜像:
# cat nginx-deployment_service.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
imagePullSecrets: ##添加拉取镜像凭据
- name: registry-pull-secret ##镜像凭据名
containers:
- name: nginx
#image: nginx:1.15.4
image: 10.40.6.165/project/nginx:v2
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
labels:
app: nginx
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
selector:
app: nginx
执行:
# kubectl apply -f nginx-deployment_service.yaml
# kubectl get pods ## 可以看到pod滚动更新
# kubectl describe pod POD_NAME ## 可以看到镜像来自私有仓库镜像
三. Pod 资源限制
Pod和Container的资源请求和限制:
• spec.containers[].resources.limits.cpu
• spec.containers[].resources.limits.memory
• spec.containers[].resources.requests.cpu
• spec.containers[].resources.requests.memory
limits: 对pod的资源总限制
requests: 创建pod时,请求调度node资源满足条件
例如:
https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/
# 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" ##0.25核 ,设置数字1,表示1核,1.5表示1.5核
limits:
memory: "128Mi"
cpu: "500m" ##0.5核
- name: wp
image: wordpress
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
创建:
# kubectl apply -f pod2.yaml
查看node节点资源使用情况:
# kubectl describe nodes 10.40.6.210
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits
--------- ---- ------------ ---------- --------------- -------------
default frontend 500m (12%) 1 (25%) 128Mi (1%) 256Mi (3%)
default nginx-deployment-5cdc94fdc8-bhgwk 0 (0%) 0 (0%) 0 (0%) 0 (0%)
kube-system kubernetes-dashboard-774f47666c-97c86 50m (1%) 100m (2%) 100Mi (1%) 300Mi (3%)
查看命名空间:
# kubectl get ns
NAME STATUS AGE
default Active 4d7h
kube-public Active 4d7h
kube-system Active 4d7h
四. Pod重启策略(restartPolicy)
重启策略表示一个pod出现故障时需要做的动作
• Always:当容器终止退出后,总是重启容器,默认策略。
• OnFailure:当容器异常退出(退出状态码非0)时,才重启容器。
• Never::当容器终止推出,从不重启容器。
例如:
apiVersion: v1
kind: Pod
metadata:
name: foo
namespace: awesomeapps
spec:
containers:
- name: foo
image: janedoe/awesomeapp:v1
restartPolicy: Always ###表示总是重启
五. Pod健康检查(Probe)
1. pod探针类型
Probe有以下两种类型:
①.livenessProbe:存活探针,如果检查失败,将杀死容器,根据Pod的restartPolicy重启策略操作。
②.readinessProbe:就绪探针,如果检查失败,Kubernetes会把Pod从service endpoints中剔除。
service有个对用户透明对控制器endpoints控制器,查看service的endpoints控制器中的pod IP和端口
# kubectl get ep
NAME ENDPOINTS AGE
kubernetes 10.40.6.201:6443,10.40.6.209:6443 4d8h
nginx-service 172.17.31.3:80,172.17.59.2:80,172.17.59.3:80 97m
2. 探针方法
Probe支持以下三种检查方法:
①.httpGet:发送HTTP请求,返回200-400范围状态码为成功。
②.exec:执行Shell命令返回状态码是0为成功。
③.tcpSocket:发起TCP Socket建立成功。
例如:https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/
exec 检查:
# cat pod3.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: k8s.gcr.io/busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessProbe: ## livenessProbe检查类型
exec: ##exec检查方法
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5 ##容器启动5秒后才做检查
periodSeconds: 5 ## 每隔5秒检查一次
httpGet检查:
# cat pod4.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-http
spec:
containers:
- name: liveness
image: k8s.gcr.io/liveness
args:
- /server
livenessProbe: ## livenessProbe类型
httpGet: ## httpGet检查方法
path: /healthz
port: 8080
httpHeaders:
- name: Custom-Header
value: Awesome
initialDelaySeconds: 3
periodSeconds: 3
tcpSocket检查:
apiVersion: v1
kind: Pod
metadata:
name: goproxy
labels:
app: goproxy
spec:
containers:
- name: goproxy
image: k8s.gcr.io/goproxy:0.1
ports:
- containerPort: 8080
readinessProbe: ##readinessProbe检查类型
tcpSocket: ##tcpSocket检查方法
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe: ##livenessProbe检查类型
tcpSocket: ##tcpSocket检查方法
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
六. Pod调度约束
1. pod创建过程
Kubernetes调度器根据特定的算法与策略将pod调度到工作节点上。在默认情况下,Kubernetes调度器可以满足绝大多数需求,例如调度pod到资源充足的节点上运行,或调度pod分散到不同节点使集群节点资源均衡等。但一些特殊的场景,默认调度算法策略并不能满足实际需求,例如使用者期望按需将某些pod调度到特定硬件节点(数据库服务部署到SSD硬盘机器、CPU/内存密集型服务部署到高配CPU/内存服务器),或就近部署交互频繁的pod(例如同一机器、同一机房、或同一网段等)。
创建pod流程如下:
kubernetes 每个组件之间协作是基于watch机制来实现:
① 用户创建pod请求到apiserver,apiserver将pod状态属性写入etcd存储中;
② schedule调度器通过watch机制获取etcd中要创建新pod的状态属性,调度器根据调度算法,选出创建pod应该调度到哪个node节点上,将新创建的pod绑定到具体某个node节点,最后通过apiserver更新到etcd中;
③ kubelet 通过watch机制获取etcd中新建pod绑定node节点信息,然后通过docker run 将容器启动,启动之后将pod的状态信息通过apiserver更新到etcd中,节点的pod状态信息会周期性上报到etcd中;
④ 通过kubectl get 获取资源信息请求到apiserver中,然后apiserver 到etcd中获取,然后返回给用户;
APIServer 在这里起到协助的作用,etcd主要存储资源状态信息。
2. Pod调度约束字段
调度约束可以通过两个字段约束:
• nodeName: 用于将Pod调度到指定的Node名称上
• nodeSelector: 用于将Pod调度到匹配Label的Node上
通过nodeName指定到具体某个节点:
# cat pod5.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-example
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
nodeName: 10.40.6.210 ##通过nodeName指定到10.40.6.210 node节点上,这是节点名
# kubectl create -f pod5.yaml
# kubectl get pod -o wide
# kubectl describe pod pod-example 可以看到直接跳过了调度器
通过nodeSelector指定到具体某个节点:
# kubectl label nodes 10.40.6.210 disktype=ssd 给10.40.6.210节点打标签disktype=ssd
# kubectl label nodes 10.40.6.213 disktype=sas 给10.40.6.210节点打标签disktype=sas
# kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
10.40.6.210 Ready <none> 4d4h v1.12.1 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/hostname=10.40.6.210
10.40.6.213 Ready <none> 4d4h v1.12.1 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=sas,kubernetes.io/hostname=10.40.6.213
# cat pod6.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-example
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
nodeSelector:
disktype: ssd
# kubectl apply -f pod6.yaml
# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
pod-example 1/1 Running 0 3m2s 172.17.31.4 10.40.6.210 <none>
# kubectl describe pod pod-example
七. 故障排查
Pod状态值 | 描述 |
---|---|
Pending | Pod创建已经提交到Kubernetes。但是因为某种原因而不能顺利创建。例如下载镜像慢,调度不成功。 |
Running | Pod已经绑定到一个节点,并且已经创建了所有容器。至少有一个容器正在运行中,或正在启动或重新启动。 |
Succeeded | Pod中的所有容器都已成功终止,不会重新启动。 |
Failed | Pod的所有容器均已终止,且至少有一个容器已在故障中终止。也就是说,容器要么以非零状态退出,要么被系统终止。 |
Unknown | 由于某种原因apiserver无法获得Pod的状态,通常是由于Master与Pod所在主机kubelet通信时出错。 |
kubectl describe TYPE/NAME 查看pod事件Events
kubectl logs TYPE/NAME [-c CONTAINER] 查看pod日志
kubectl exec POD [-c CONTAINER] -- COMMAND [args...] 进入pod
# kubectl describe pod pod-example
.....
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 8m26s default-scheduler Successfully assigned default/pod-example to 10.40.6.210
Normal Pulling 8m25s kubelet, 10.40.6.210 pulling image "nginx"
Normal Pulled 8m25s kubelet, 10.40.6.210 Successfully pulled image "nginx"
Normal Created 8m25s kubelet, 10.40.6.210 Created container
Normal Started 8m25s kubelet, 10.40.6.210 Started container