赞
踩
Pod是Kubernetes中最小的单元,它由一组、一个或多个容器组成
每个Pod还包含了一个Pause容器,Pause容器是Pod的父容器,主要负责僵尸进程的回收管理
通过Pause容器可以使同一个Pod里面的多个容器共享存储、网络、PID、IPC等。
Pod支持横向扩展和复制
Pod的生命周期是短暂的, 用后即焚的实体
Pod不会自愈, 如果Pod运行的Node故障, 或者是调度器本身故障, 这个Pod就会被删除
控制器(Deployment)可以自动创建和管理多个Pod, 提供副本管理, 滚动升级和集群级别的自愈能力
Pod本身是一个逻辑概念,没有具体存在,那究竟是怎么实现的呢?
众所周知,容器之间是通过Namespace隔离的,Pod要想解决上述应用场景,那么就要让Pod里的容器之间高效共享。
具体分为两个部分:网络和存储
kubernetes的解法是这样的:会在每个Pod里先启动一个infra container
小容器,然后让其他的容器连接进来这个网络命名空间,然后其他容器看到的网络试图就完全一样了,即网络设备、IP地址、Mac地址等,这就是解决网络共享问题。在Pod的IP地址就是infra container的IP地址。
比如有两个容器,一个是nginx,另一个是普通的容器,普通容器要想访问nginx里的文件,就需要nginx容器将共享目录通过volume挂载出来,然后让普通容器挂载的这个volume,最后大家看到这个共享目录的内容一样。
例如:
# pod.yaml apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: write image: centos command: ["bash","-c","for i in {1..100};do echo $i >> /data/hello;sleep 1;done"] volumeMounts: - name: data mountPath: /data - name: read image: centos command: ["bash","-c","tail -f /data/hello"] volumeMounts: - name: data mountPath: /data volumes: - name: data emptyDir: {}
上述示例中有两个容器,write容器负责提供数据,read消费数据,通过数据卷将写入数据的目录和读取数据的目录都放到了该卷中,这样每个容器都能看到该目录。
验证:
kubectl apply -f pod.yaml
kubectl logs my-pod -c read -f
在Pod中容器分为以下几个类型:
Pod对象自从其创建开始至终止退出的时间范围称为其生命周期
在这段时间中, Pod会处于多种不同的状态, 并执行一些操作
创建主容器(main container) 为必须的操作
其他可选的操作还包括
上述操作是否执行取决于Pod的定义
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Oix5OSve-1628834816607)(C:\Users\admin\Desktop\截图\k8s\Pod生命周期示意图.png)]
StartupProbe:k8s1.16版本后新加的探测方式,用于判断容器内应用程序是否已经启动。如果配置了startupProbe,就会先禁止其他的探测,直到它成功为止,成功后将不在进行探测。
LivenessProbe:周期性检测,检测未通过时,与该Pod关联的Service,会将该Pod从Service的后端可用端点列表中删除;直接再次就绪,重新添加回来。未定义时,只要容器未终止,即为就绪;
ReadinessProbe:周期性检测,一般用于探测容器内的程序是否健康,它的返回值如果为success,那么就代表这个容器已经完成启动,并且程序已经是可以接受流量的状态。
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: java
image: lizhenliang/java-demo
imagePullPolicy: IfNotPresent
imagePullPolicy 字段有三个可选值:
IfNotPresent:默认值,镜像在宿主机上不存在时才拉取(镜像标签是指定版本时的默认选项)
Always:每次创建 Pod 都会重新拉取一次镜像(镜像标签是latest的默认选项)
Never: Pod 永远不会主动拉取这个镜像
如果拉取公开的镜像,直接按照上述示例即可,但要拉取私有的镜像,是必须认证镜像仓库才可以,即docker login,而在K8S集群中会有多个Node,显然这种方式是很不放方便的!为了解决这个问题,K8s 实现了自动拉取镜像的功能。 以secret方式保存到K8S中,然后传给kubelet。
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
imagePullSecrets:
- name: myregistrykey
containers:
- name: java
image: lizhenliang/java-demo
imagePullPolicy: IfNotPresent
上述中名为 myregistrykey 的secret是由kubectl create secret docker-registry命令创建:
kubectl create secret docker-registry myregistrykey --docker-username=admin --docker-password=Harbor12345 --docker-email=admin@harbor.com --docker-server=192.168.31.70
在K8S部署一个应用的YAML内容大致分为两部分:
控制器定义:定义控制器属性
被控制对象:Pod模板,定义容器属性
具体字段意义:
apiVersion | API版本 |
---|---|
kind | 资源类型 |
metadata | 资源元数据 |
spec | 资源规格 |
replicas | 副本数量 |
selector | 标签选择器 |
template | Pod模板 |
metadata | Pod元数据 |
spec | Pod规格 |
containers | 容器配置 |
很多同学YAML不会写!主要原因还是用的少,里面都是由于各个资源组成,熟悉了每个资源应用,自然就会写了,但也不用等到熟悉各种资源,这里教你几个技巧,帮助快速上手。
用run命令生成部署模板
kubectl create deployment nginx --image=nginx:1.14 -o yaml --dry-run> my-deploy.yaml
用get命令将已有部署的应用yaml导出
kubectl get my-deploy/nginx -o=yaml --export > my-deploy.yaml
如果某个字段单词不记得了,可以通过explain查看更详细的帮助文档获得
kubectl explain pods.spec.containers
apiVersion: v1 # 必选,API的版本号 kind: Pod # 必选,类型Pod metadata: # 必选,元数据 name: nginx # 必选,符合RFC 1035规范的Pod名称 namespace: default # 可选,Pod所在的命名空间,不指定默认为default,可以使用-n指定namespace labels: # 可选,标签选择器,一般用于过滤和区分Pod app: nginx role: frontend # 可以写多个 annotations: # 可选,注释列表,可以写多个 app: nginx spec: # 必选,用于定义容器的详细信息 initContainers: # 初始化容器,在容器启动之前执行的一些初始化操作 - command: - sh - -c - echo "I am InitContainer for init some configuration" image: busybox imagePullPolicy: IfNotPresent name: init-container containers: # 必选,容器列表 - name: nginx # 必选,符合RFC 1035规范的容器名称 image: nginx:latest # 必选,容器所用的镜像的地址 imagePullPolicy: Always # 可选,镜像拉取策略 command: # 可选,容器启动执行的命令 - nginx - -g - "daemon off;" workingDir: /usr/share/nginx/html # 可选,容器的工作目录 volumeMounts: # 可选,存储卷配置,可以配置多个 - name: webroot # 存储卷名称 mountPath: /usr/share/nginx/html # 挂载目录 readOnly: true # 只读 ports: # 可选,容器需要暴露的端口号列表 - name: http # 端口名称 containerPort: 80 # 端口号 protocol: TCP # 端口协议,默认TCP env: # 可选,环境变量配置列表 - name: TZ # 变量名 value: Asia/Shanghai # 变量的值 - name: LANG value: en_US.utf8 resources: # 可选,资源限制和资源请求限制 limits: # 最大限制设置 cpu: 1000m #1核=1000m memory: 1024Mi requests: # 启动所需的资源 cpu: 100m memory: 512Mi startupProbe: # 可选,检测容器内进程是否完成启动。注意三种检查方式同时只能使用一种。 httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。 path: /api/successStart # 检查路径 port: 80 readinessProbe: # 可选,健康检查。注意三种检查方式同时只能使用一种。 httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。 path: / # 检查路径 port: 80 # 监控端口 livenessProbe: # 可选,健康检查 exec: # 执行容器命令检测方式 #command: #- cat #- /health httpGet: # httpGet检测方式 path: /_health # 检查路径 port: 8080 httpHeaders: # 检查的请求头 - name: end-user value: Jason tcpSocket: # 端口检测方式 port: 80 initialDelaySeconds: 60 # 初始化时间 timeoutSeconds: 2 # 超时时间 periodSeconds: 5 # 检测间隔 successThreshold: 1 # 检查成功为2次表示就绪 failureThreshold: 2 # 检测失败1次表示未就绪 lifecycle: postStart: # 容器创建完成后执行的指令, 可以是exec httpGet TCPSocket exec: command: - sh - -c - 'mkdir /data/ ' preStop: httpGet: path: / port: 80 exec: command: - sh - -c - sleep 9 restartPolicy: Always # 可选,默认为Always,容器故障或者没有启动成功,那就自动重启该容器,Onfailure: 容器以不为0的状态终止,自动重启该容器, Never:无论何种状态,都不会重启 nodeSelector: # 可选,指定Node节点 region: subnet7 imagePullSecrets: # 可选,拉取镜像使用的secret,可以配置多个 - name: default-dockercfg-86258 hostNetwork: false # 可选,是否为主机模式,如是,会占用主机端口 volumes: # 共享存储卷列表 - name: webroot # 名称,与上述对应 emptyDir: {} # 挂载目录 hostPath: # 挂载本机目录 path: /etc/hosts
Pod对象自从其创建开始至终止退出的时间范围称为其生命周期
在这段时间中, Pod会处于多种不同的状态, 并执行一些操作
创建主容器(main container) 为必须的操作
其他可选的操作还包括
上述操作是否执行取决于Pod的定义
Infrastructure Container:基础容器,维护整个Pod网络空间,对用户不可见
InitContainers:初始化容器,先于业务容器开始执行,一般用于业务容器的初始化工作
Containers:业务容器,具体跑应用程序的镜像
init-container
apiVersion: v1 kind: Pod metadata: name: init-container-demo namespace: default spec: initContainers: - name: iptables-init image: ikubernetes/admin-box:latest imagePullPolicy: IfNotPresent command: ['/bin/sh','-c'] args: ['iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-port 80'] securityContext: capabilities: add: - NET_ADMIN containers: - name: demo image: ikubernetes/demoapp:v1.0 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80
lifecycle-demo
apiVersion: v1 kind: Pod metadata: name: lifecycle-demo namespace: default spec: containers: - name: demo image: ikubernetes/demoapp:v1.0 imagePullPolicy: IfNotPresent securityContext: capabilities: add: - NET_ADMIN livenessProbe: httpGet: path: '/livez' port: 80 scheme: HTTP initialDelaySeconds: 5 lifecycle: postStart: exec: command: ['/bin/sh','-c','iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-ports 80'] preStop: exec: command: ['/bin/sh','-c','while killall python3; do sleep 1; done'] restartPolicy: Always
也支持三种探针
spec:
containers:
- name: …
image: …
livenessProbe:
exec <Object> # 命令式探针
httpGet <Object> # http GET类型的探针
tcpSocket <Object> # tcp Socket类型的探针
initialDelaySeconds <integer> # 发起初次探测请求的延后时长
periodSeconds <integer> # 请求周期
timeoutSeconds <integer> # 超时时长
successThreshold <integer> # 成功阈值
failureThreshold <integer> # 失败阈值
PS:在一个pod中exec、httpGet、tcpSocket三种探针使用一种即可
StartupProbe:k8s1.16版本后新加的探测方式,用于判断容器内应用程序是否已经启动。如果配置了startupProbe,就会先禁止其他的探测,直到它成功为止,成功后将不在进行探测。便于用户使用同livenessProbe不同参数或阈值;
LivenessProbe:周期性检测,检测未通过时,kubelet会根据restartPolicy的定义来决定是否会重启该容器;未定义时,Kubelet认为只要容器未终止,即为健康;
ReadinessProbe:周期性检测,检测未通过时,与该Pod关联的Service,会将该Pod从Service的后端可用端点列表中删除;直接再次就绪,重新添加回来。未定义时,只要容器未终止,即为就绪;
ExecAction:在容器内执行一个命令,如果返回值为0,则认为容器健康。
TCPSocketAction:通过TCP连接检查容器内的端口是否是正常打开,如果正常打开的就认为容器健康。
HTTPGetAction:向应用程序暴露的API地址发HTTP请求来检测程序是否正常,如果状态码为2xx,3xx则认为容器健康。
例如:
liveness-exec
apiVersion: v1 kind: Pod metadata: name: liveness-exec-demo namespace: default spec: containers: - name: demo image: ikubernetes/demoapp:v1.0 imagePullPolicy: IfNotPresent livenessProbe: exec: command: ['/bin/sh', '-c', '[ "$(curl -s 127.0.0.1/livez)" == "OK" ]'] initialDelaySeconds: 5 timeoutSeconds: 1 periodSeconds: 5
[ “$(curl -s 127.0.0.1/livez)” == “OK” ]:shell判断语句,等值判断,curl -s 127.0.0.1/livez成功则显示OK
liveness-httpget
apiVersion: v1 kind: Pod metadata: name: liveness-httpget-demo namespace: default spec: containers: - name: demo image: ikubernetes/demoapp:v1.0 imagePullPolicy: IfNotPresent livenessProbe: httpGet: path: '/livez' port: 80 scheme: HTTP initialDelaySeconds: 5
scheme: HTTP意思是使用HTTP协议
只以响应码作为容器是否健康的标准,返回的响应码为2xx,3xx为健康
liveness-tcpsocket
apiVersion: v1 kind: Pod metadata: name: liveness-tcpsocket-demo namespace: default spec: containers: - name: demo image: ikubernetes/demoapp:v1.0 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80 livenessProbe: tcpSocket: port: http periodSeconds: 5 initialDelaySeconds: 5
port: http是引用上面ports.name: http,类似于变量的用法
readiness-httpget
apiVersion: v1 kind: Pod metadata: name: readiness-httpget-demo namespace: default spec: containers: - name: demo image: ikubernetes/demoapp:v1.0 imagePullPolicy: IfNotPresent readinessProbe: httpGet: path: '/readyz' port: 80 scheme: HTTP initialDelaySeconds: 15 timeoutSeconds: 2 periodSeconds: 5 failureThreshold: 3 restartPolicy: Always
startup-exec
apiVersion: v1 kind: Pod metadata: name: startup-exec-demo namespace: default spec: containers: - name: demo image: ikubernetes/demoapp:v1.0 imagePullPolicy: IfNotPresent startupProbe: exec: command: ['/bin/sh','-c','test','"$(curl -s 127.0.0.1/livez)"=="OK"'] initialDelaySeconds: 0 failureThreshold: 3 periodSeconds: 5
startup检测成功后,LivenessProbe和ReadinessProbe探针才会启动
sidecar:为主容器提供辅助作用,为了外部环境更好接入主容器,如日志收集,代理服务等
adapater:为主容器的某个功能,能更好的适应外部环境
ambassador:为了让主容器接入外部环境,如代表主容器访问数据
sidecar-container
apiVersion: v1 kind: Pod metadata: name: sidecar-container-demo namespace: default spec: containers: - name: proxy image: envoyproxy/envoy-alpine:v1.14.1 command: ['/bin/sh','-c'] args: ['sleep 5 && envoy -c /etc/envoy/envoy.yaml'] lifecycle: postStart: exec: command: ['/bin/sh','-c','wget -O /etc/envoy/envoy.yaml http://ilinux.io/envoy.yaml'] - name: demo image: ikubernetes/demoapp:v1.0 imagePullPolicy: IfNotPresent env: - name: HOST value: "127.0.0.1" - name: PORT value: "8080"
Pod计算资源配额有两种
request:下阈值;限制配额:容器能使用的最大配置
spec.containers[].resources.limits.cpu
spec.containers[].resources.limits.memory
Limit:上阈值; 申请配额:调度时使用,参考是否有节点满足该配置
spec.containers[].resources.requests.cpu
spec.containers[].resources.requests.memory
计算资源的单位:
resource-requests
apiVersion: v1 kind: Pod metadata: name: stress-pod spec: containers: - name: stress image: ikubernetes/stress-ng command: ["/usr/bin/stress-ng", "-c 1", "-m 1", "--metrics-brief"] resources: requests: memory: "128Mi" cpu: "200m" limits: memory: "512Mi" cpu: "400m"
/usr/bin/stress-ng专门做压力测试的应用程序
resource-limites
apiVersion: v1 kind: Pod metadata: name: memleak-pod labels: app: memleak spec: containers: - name: simmemleak image: ikubernetes/simmemleak imagePullPolicy: IfNotPresent resources: requests: memory: "64Mi" cpu: "1" limits: memory: "64Mi" cpu: "1"
设定requests和limits值相同是强行限制pod的计算资源。
强行限制的pod的计算资源后,如果pod内存不够,启动失败会显示OOMKilled
k8s的退避算法:第一次失败1秒后重启,第二次失败10秒后重启,之后重启时间翻倍,到第7次重启300秒还是失败后,显示CrashLoopBackOff
基本概念
pod过载使用资源的情况下,无法同时满足绑定其上的所有对象以资源满载的方式运行,在内存资源紧缺的情况下。Kubernetes根据Pod中Containers Resource的request和limit的值,把Pod对象归类为Guaranteed、 Burstable、和Best-Effort这3个服务质量类别(QoS )。
apiVersion: v1 #查看版本:kubectl api-version kind: Pod metadata: {…} spec: securityContext: # Pod级别的安全上下文,对内部所有容器均有效 runAsUser <integer> # 以指定的用户身份运行容器进程,默认由镜像中的USER指定 runAsGroup <integer> # 以指定的用户组运行容器进程,默认使用的组随容器运行时 supplementalGroups <[]integer> # 为容器中1号进程的用户添加的附加组; fsGroup <integer> # 为容器中的1号进程附加的一个专用组,其功能类似于sgid runAsNonRoot <boolean> # 是否以非root身份运行 seLinuxOptions <Object> # SELinux的相关配置 sysctls <[]Object> # 应用到当前Pod上的网络名称空间级别的sysctl参数设置列表 windowsOptions <Object> # Windows容器专用的设置 containers: #容器级别的安全上下文 - name: … image: … securityContext: # 容器级别的安全上下文,仅生效于当前容器 runAsUser <integer> # 以指定的用户身份运行容器进程 runAsGroup <integer> # 以指定的用户组运行容器进程 runAsNonRoot <boolean> # 是否以非root身份运行 allowPrivilegeEscalation <boolean> # 是否允许特权升级 capabilities <Object> # 于当前容器上添加(add)或删除(drop)的内核能力 add <[]string> # 添加由列表定义的各内核能力 drop <[]string> # 移除由列表定义的各内核能力 privileged <boolean> # 是否运行为特权容器,若设定为true,就等于是宿主机上的用户,若以管理员身份运行,可直接操作宿主机的内核,不建议使用 procMount <string> # 设置容器的procMount类型,默认为DefaultProcMount; readOnlyRootFilesystem <boolean> # 是否将根文件系统设置为只读模式 seLinuxOptions <Object> # SELinux的相关配置 windowsOptions <Object> # windows容器专用的设置
指定运行容器的用户和组:securitycontext-runasuser-demo
apiVersion: v1 kind: Pod metadata: name: securitycontext-runasuser-demo namespace: default spec: containers: - name: demo image: ikubernetes/demoapp:v1.0 imagePullPolicy: IfNotPresent env: - name: PORT value: "8080" securityContext: runAsUser: 1001 runAsGroup: 1001
PS:普通用户(1001)没有权限监听1024以内的特权端口,所以加了env,把端口改成8080
添加禁止容器的内核功能:securitycontext-capabilities-demo
apiVersion: v1 kind: Pod metadata: name: securitycontext-capabilities-demo namespace: default spec: containers: - name: demo image: ikubernetes/demoapp:v1.0 imagePullPolicy: IfNotPresent command: ["/bin/sh","-c"] #改变镜像启动为容器时,镜像内设置默认要启动的命令,自定义运行的程序 args: ["/sbin/iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-port 80 && /usr/bin/python3 /usr/local/bin/demo.py"] #向自定义command命令传递的参数 securityContext: capabilities: add: ['NET_ADMIN'] drop: ['CHOWN']
常用的capabilities:
修改容器的内核参数:securitycontext-sysctls-demo
apiVersion: v1 kind: Pod metadata: name: securitycontext-sysctls-demo namespace: default spec: securityContext: sysctls: - name: kernel.shm_rmid_forced value: "0" - name: net.ipv4.ip_unprivileged_port_start value: "0" containers: - name: demo image: ikubernetes/demoapp:v1.0 imagePullPolicy: IfNotPresent securityContext: runAsUser: 1001 runAsGroup: 1001
Pod内可安全使用的内核参数只有三个:
若需要添加不被允许的内核参数,需要添加如下文件:
vim /etc/default/kubelet
KUBELET_EXTRA_ARGS='需要添加的内核参数'
PS:且每一个节点都需要修改,且修改后要重启kubelet后才能生效
all-in-one
apiVersion: v1 kind: Pod metadata: name: all-in-one namespace: default spec: initContainers: - name: iptables-init image: ikubernetes/admin-box:latest imagePullPolicy: IfNotPresent command: ['/bin/sh','-c'] args: ['iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-port 80'] securityContext: capabilities: add: - NET_ADMIN containers: - name: sidecar-proxy image: envoyproxy/envoy-alpine:v1.13.1 command: ['/bin/sh','-c'] args: ['sleep 3 && envoy -c /etc/envoy/envoy.yaml'] lifecycle: postStart: exec: command: ['/bin/sh','-c','wget -O /etc/envoy/envoy.yaml http://ilinux.io/envoy.yaml'] livenessProbe: tcpSocket: port: 80 initialDelaySeconds: 5 readinessProbe: tcpSocket: port: 80 initialDelaySeconds: 5 - name: demo image: ikubernetes/demoapp:v1.0 imagePullPolicy: IfNotPresent env: - name: PORT value: '8080' livenessProbe: httpGet: path: '/livez' port: 8080 initialDelaySeconds: 5 readinessProbe: httpGet: path: '/readyz' port: 8080 initialDelaySeconds: 15 securityContext: runAsUser: 1001 runAsGroup: 1001 resources: requests: cpu: 0.5 memory: "64Mi" limits: cpu: 2 memory: "1024Mi" securityContext: supplementalGroups: [1002, 1003] fsGroup: 2000
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。