一.初始化容器InitContainer
1.定义
initContainers
是 Kubernetes Pod 中的一个功能,用于在主容器启动之前执行初始化任务。initContainers
与主容器的作用不同,它们在主容器启动之前运行,并且可以完成准备工作,如下载依赖、配置文件等。
2.为什么使用InitContainer
initContainers
的作用是执行必要的初始化任务,确保主容器能够在预期的状态下启动。这些任务包括:
准备环境:如下载或解压文件、配置数据等。
执行依赖:如等待外部服务或数据库准备好。
初始化数据:如设置数据库表结构或填充初始数据。
它们在主容器启动之前完成,确保主容器能够在一个稳定的环境中运行。
具体示例:延迟指定时间后启动,修改内核参数,等待依赖服务启动
3.优势
- 隔离初始化任务:将初始化逻辑与主容器的业务逻辑分开,有助于保持主容器的简单性和专注于其核心功能。
- 确保初始化完成:
initContainers
在主容器启动之前完成所有定义的任务。如果初始化失败,Pod 将不会启动主容器,确保主容器不会在不准备好的情况下运行。 - 依赖处理:可以处理主容器所需的外部依赖或前置条件,例如等待数据库就绪或下载配置文件。这些操作可以在主容器之前完成,避免主容器启动后遇到依赖问题。
- 数据共享:通过挂载 Volume,
initContainers
可以创建或初始化共享数据,这些数据可以被主容器使用。这对于数据的预处理或配置文件的准备特别有用。 - 重用:可以使用
initContainers
执行通用的初始化任务,这些任务可以在多个 Pod 中重用,避免重复编写相同的逻辑。 - 灵活性:能够使用不同的镜像和命令来完成初始化任务,提供了更多的灵活性和控制力。
- 清晰的失败处理:如果
initContainers
中的任务失败,Pod 将不会进入运行状态,这有助于提前发现和解决问题,而不是让主容器在错误的环境中启动。
4.实例1——延迟指定时间后启动
(1)创建一个pod,initContainers指定初始化容器,command : [ "sh","-c","sleep 15"] 表示初始化容器需要休眠15秒。
[root@k8s-master ~]# vim init01.yml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: initc01
name: initc01
spec:
terminationGracePeriodSeconds: 0
containers:
- image: nginx:1.7.9
imagePullPolicy: IfNotPresent
name: n1
resources: {}
initContainers:
- name: initc01
image: nginx:1.7.9
imagePullPolicy: IfNotPresent
command: ["sh","-c","sleep 15"]
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
(2)创建pod
[root@k8s-master ~]# ku create -f init01.yml
(3)不断查看15秒后发现pod开启启动
[root@k8s-master ~]# ku get pod
NAME READY STATUS RESTARTS AGE
initc01 0/1 Init:0/1 0 6s
[root@k8s-master ~]# ku get pod
NAME READY STATUS RESTARTS AGE
initc01 1/1 Running 0 22s
5.实例2——使用初始化容器
在容器里修改内核参数,实际上修改的就是物理机的内核参数,为了安全性,一般不允许在容器里修改内核参数,Seccomp代表安全计算(SecureComputing)模式,seccomp控制了容器能做哪些操作,添加securityContext参数之后就可以修改内核参数了。
创建一个pod,initcontainers初始化容器里的securityContext:privileged:true表示该容器具有特权,可以执行命令"sh","-c","/sbin/sysctl -w vm.swappiness=0" vm.swappiness设置为表示尽量少使用swap内存。
(1)编写pod文件
[root@k8s-master ~]# vim init02.yml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: initc02
name: initc02
spec:
terminationGracePeriodSeconds: 0
containers:
- image: nginx:1.7.9
imagePullPolicy: IfNotPresent
name: n1
resources: {}
initContainers:
- name: initc02
image: alpine
imagePullPolicy: IfNotPresent
command: ["sh","-c","/sbin/sysctl -w vm.swappiness=0"]
securityContext:
privileged: true
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
(2)创建pod
[root@k8s-master ~]# ku create -f init02.yml
pod/initc02 created
(3)查看pod的详细信息
[root@k8s-master ~]# ku get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
initc01 1/1 Running 0 8m33s 10.244.140.71 node02 <none> <none>
initc02 1/1 Running 0 11s 10.244.196.135 node01 <none> <none>
(4)到pod所在的节点查看swappiness的值是否为0
[root@node01 images]# cat /proc/sys/vm/swappiness
0
6.示例3——等待依赖服务启动
有时某些服务需要依赖其他组件才能启动,比如后端应用需要数据库启动之后,应用才能正常启动,此时需要检测数据库实例是否正常,等待数据库可以正常使用时,在启动后端应用,此时可以使用初始化容器进行控制。
(1)创建第一个pod
该pod内要依赖两个条件才能启动,分别是利用busybox容器检测redis-service服务和mysql-server服务是否生成
[root@k8s-master ~]# vim myapp.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
initContainers:
- name: init-redis
image: busybox:1.28
command: ['sh', '-c', 'until nslookup redis-service; do echo waiting for nginx01; sleep 2; done;']
- name: init-mysql
image: busybox:1.28
command: ['sh', '-c', 'until nslookup mysql-service; do echo waiting for nginx02; sleep 2; done;']
备注: command: ['sh', '-c', 'until nslookup mysql-service; do echo waiting for nginx02; sleep 2; done;'] 这个命令是一个shell脚本 ,用于持续检查 mysql-service
的 DNS 解析。
sh :shell解释器
-c :后面要执行的命令
until do 直到型循环结构,直到条件成立终止循环
nslookup 查询 DNS(域名系统)记录
(2)创建该pod查看状态
[root@k8s-master ~]# ku create -f myapp.yaml
pod/nginx created
[root@k8s-master ~]# ku get pod
NAME READY STATUS RESTARTS AGE
initc01 1/1 Running 0 23m
initc02 1/1 Running 0 15m
nginx 0/1 Init:0/2 0 5s
(3)创建第一个被依赖的service
编写pod
[root@k8s-master ~]# vim redis-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: redis
name: redis
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- image: redis:5.0
imagePullPolicy: IfNotPresent
name: redis
---
apiVersion: v1
kind: Service
metadata:
labels:
app: redis
name: redis-service
spec:
ports:
- port: 6379
protocol: TCP
targetPort: 6379
selector:
app: redis
type: NodePort
创建pod查看nginx的状态
[root@k8s-master ~]# ku create -f redis-deployment.yaml
deployment.apps/redis created
[root@k8s-master ~]# ku get pod
NAME READY STATUS RESTARTS AGE
initc01 1/1 Running 0 27m
initc02 1/1 Running 0 19m
nginx 0/1 Init:1/2 0 4m40s
redis-56bcf55554-7ngl6 1/1 Running 0 32s
此时发现nginx的STATUS状态栏的值变了,表示已经有一个init启动完成并结束了。
(4)第二个pod
编写pod文件
[root@k8s-master ~]# vim mysql-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: mysql
name: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- env:
- name: MYSQL_ROOT_PASSWORD
value: 'moonfdd'
image: 'mysql:8.0'
imagePullPolicy: IfNotPresent
name: mysql
volumeMounts:
- mountPath: /var/lib/mysql
name: volv
volumes:
- hostPath:
path: /root/k8s/moonfdd/mysql/var/lib/mysql
type: DirectoryOrCreate
name: volv
---
apiVersion: v1
kind: Service
metadata:
labels:
app: mysql
name: mysql-service
spec:
ports:
- port: 3306
protocol: TCP
targetPort: 3306
selector:
app: mysql
type: NodePort
创建pod,查看nginxpod的状态
[root@k8s-master ~]# ku create -f mysql-deployment.yaml
deployment.apps/mysql created
service/mysql-service created
[root@k8s-master ~]# ku get pod
NAME READY STATUS RESTARTS AGE
initc01 1/1 Running 0 31m
initc02 1/1 Running 0 23m
mysql-7f5d669b6c-k4hj2 1/1 Running 0 31s
nginx 1/1 Running 0 8m21s
redis-56bcf55554-7ngl6 1/1 Running 0 4m13s
二.pause容器
1.定义
在 Kubernetes 中,pause
容器通常是用于保持 Pod 的网络和存储环境的稳定性。它是 Kubernetes 中 Pod 的基础容器,负责维持 Pod 的网络和命名空间,确保在 Pod 中的其他容器重启或更换时,网络配置和存储挂载保持不变。
2.特点
在Kubernetes中,Pod是部署和管理容器化应用的基本单位,而Pause(或称为Infra)容器则是Pod中一个非常特殊的容器。Pause容器的特点主要体现在以下几个方面:
1. 轻量级与无业务逻辑
- 镜像非常小:Pause容器的镜像通常非常小,大约在700KB左右,这使得它非常轻量,对系统资源的占用极低。
- 无业务逻辑:Pause容器本身不包含任何业务逻辑,它的主要作用是作为Pod中其他容器的“宿主”或“基础设施”,提供必要的环境和支持。
2. 提供命名空间和资源共享
- 命名空间共享:Pause容器为Pod中的其他容器提供了PID、网络(Network Namespace)、IPC(进程间通信)和UTS(主机名)等命名空间的共享。这意味着Pod中的容器可以看到相同的网络视图、进程ID等,从而简化了容器间的通信和协作。
- 共享存储卷:Pause容器还负责挂载和管理Pod级别的共享存储卷(如emptyDir卷),使得Pod中的容器可以共享文件系统,实现文件和数据的共享。
3. 生命周期管理
- 持续运行:Pause容器在Pod的生命周期中持续运行,即使Pod中的其他容器被重启或替换,Pause容器仍然保持不变。这确保了Pod级别的网络命名空间和共享存储卷的持久性。
- 容器启动顺序:由于Pause容器是Pod中第一个启动的容器,它确保了Pod的网络和存储环境在其他容器启动之前已经准备好。
4. 网络通信支持
- 网络命名空间的主要进程:Pause容器在Pod中充当网络命名空间的主要进程,负责创建和配置Pod的网络环境,如IP地址、网络接口和路由规则等。这使得Pod中的其他容器可以通过与Pause容器共享网络命名空间来实现容器间的通信。
5. 自动生成与管理
- 自动生成:Pause容器是由Kubernetes系统自动生成并注入到每个Pod中的,用户无需在Pod定义中显式定义它。
- 自动管理:Pause容器的生命周期由Kubernetes系统自动管理,包括启动、停止和重启等操作。
综上所述,Pause容器是Kubernetes中Pod的一个重要组成部分,它通过提供命名空间共享、资源共享、生命周期管理和网络通信支持等功能,为Pod中的其他容器提供了一个稳定、可靠的运行环境。
三.临时容器
1.定义
临时容器是Kubernetes(简称K8s)中一个特殊的容器概念,它允许用户在现有的Pod中临时运行一个或多个容器,以便完成用户发起的操作,如故障排查、日志收集、临时测试等。临时容器是一种在Pod中临时运行的容器,它不作为Pod的持久部分,而是在需要时创建,并在任务完成后被删除。
2.临时容器特点
- 无自动重启:临时容器永远不会自动重启,这与其他可能具有重启策略的常规容器不同。
- 临时运行:临时容器在现有Pod中临时运行,以便完成用户发起的操作,如故障排查等。
- 非构建用途:临时容器主要用于检查服务状态,而不是用于构建应用程序。
- 一次性使用:临时容器通常用于一次性任务,如故障排查,完成后即被移除。
- 交互式故障排查:当容器崩溃或容器镜像不包含调试工具而导致kubectl exec命令无用时,临时容器对于交互式故障排查非常有用。
3.作用
故障排查
当Pod中的某个容器出现问题或行为异常时,传统的方法可能包括查看日志、使用kubectl exec
进入容器内部等。然而,在某些情况下,这些方法可能不够直接或有效,特别是当容器镜像不包含必要的调试工具时。临时容器允许用户向Pod中注入一个新的容器,该容器具有访问Pod中其他容器的网络和卷的能力,从而可以执行如查看进程、文件系统、执行诊断命令等任务,以帮助诊断问题。
交互式调试
类似于故障排查,但更侧重于提供一种交互式的方式来调查Pod内部的状态。由于临时容器可以按需启动,用户可以在需要时启动一个包含调试工具的容器,并与之交互,从而更深入地了解Pod的运行情况。
临时任务执行
虽然这不是临时容器的主要设计目标,但在某些情况下,它们也可以被用于在Pod中执行临时的、一次性的任务。这些任务可能包括但不限于数据收集、状态检查、清理工作等。
学习和探索
对于Kubernetes的新手或正在学习其内部工作原理的用户来说,临时容器提供了一个独特的机会来观察Pod内部的运行状况,了解容器之间的交互方式,以及探索Kubernetes的各种功能和特性。
注意事项
- Alpha状态:需要注意的是,临时容器在Kubernetes中目前仍处于Alpha状态,这意味着它们可能在未来的版本中发生重大变化或被完全移除。因此,在生产环境中使用临时容器时应格外小心,并密切关注Kubernetes的更新和变更。
- 安全性:由于临时容器可以访问Pod中的网络和存储资源,因此必须确保它们以安全的方式运行,避免潜在的安全风险。
- 限制:临时容器在创建时有一些限制和约束,例如它们不能拥有自己的端口、生命周期、重启策略等。这些限制是为了确保临时容器不会干扰Pod中其他容器的正常运行。
总的来说,临时容器为Kubernetes提供了一种强大的工具,用于在Pod中执行临时任务、进行故障排查和调试。然而,由于其当前的状态和限制,用户在使用时应谨慎考虑其适用性和安全性。
4.实例
(1)创建一个tomcat的资源清单
[root@k8s-master ~]# vim pod-tomcat.yaml
apiVersion: v1
kind: Pod
metadata:
name: tomcat-test
namespace: default
labels:
app: tomcat
spec:
containers:
- name: tomcat-java
ports:
- containerPort: 8080
image: kubeguide/tomcat-app:v1
imagePullPolicy: IfNotPresent
(2)创建pod
[root@k8s-master ~]# ku create -f pod-tomcat.yaml
pod/tomcat-test created
[root@k8s-master ~]# ku get pod
NAME READY STATUS RESTARTS AGE
tomcat-test 1/1 Running 0 5s
(3)为tomcat 的pod 创建临时容器
[root@k8s-master ~]# ku debug -it tomcat-test --image=busybox:1.28 --target=tomcat-java
Targeting container "tomcat-java". If you don't see processes from this container it may be because the container runtime doesn't support this feature.
Defaulting debug container name to debugger-6hl2d.
If you don't see a command prompt, try pressing enter.
/
(4)查看tomcat-test这个pod是否已有临时容器
ku describe pod tomcat-test
Ephemeral Containers:
debugger-6hl2d:
Container ID: docker://d021890e98a6631665ed7c9d7969df603ddfffe39dc8df35aff298d03eef21ee
Image: busybox:1.28
Image ID: docker://sha256:8c811b4aec35f259572d0f79207bc0678df4c736eeec50bc9fec37ed936a472a
四.自动扩缩容HPA
在集群安装的过程中,我们可以安装一个叫MetricsServer的组件,该组件在集群中负责采集Pod和Node的度量值指标,比如Pod的CPU、内存使用和节点的内存、CPU使用案,而且安装的Dashboard可以展示CPU、内存信息也是依靠MetricsServer的。当然,该组件不仅仅是用来展示数据的,还可以使用Metrics Server提供的数据结合Kubernetes的HPA功能实现Pod的自动扩缩容
1.什么是HPA
- HPA(HorizontalPodAutoscaler,水平Pod自动伸缩器)可以根据观察到的CPU、内存使用率或自定义度量标准来自动扩展或缩容Pod的数量。注意HPA不适用于无法缩放的对象,比如DaemonSet
- HPA控制器会定期调整RC或Deployment的副本数,以使观察到的平均CPU利用率与用户指定的目标相匹配。
- HPA需要MetricsServer获取度量指标,如果已经部署了MetricsServer,本节的实践部就分无须再安装MetricsServe 如果没有安装Metrics eryer 可以参考其他实验文档自行部署
2.为什么使用自动缩容
Horizontal Pod Autoscaler (HPA) 在 Kubernetes 中用于自动扩缩容,主要有以下几个原因:
提高弹性:HPA 根据实时负载自动调整 Pod 数量,确保应用能够应对流量的波动,提高系统的弹性。
优化资源使用:自动调整 Pod 数量有助于在负载高峰时增加资源,在负载低谷时减少资源,从而优化资源的使用效率,降低成本。
简化管理:HPA 减少了手动干预的需要,通过自动化的方式调整容器数量,简化了运维工作。
保持性能:通过动态扩展或缩减 Pod 数量,HPA 能够保持应用性能稳定,避免因负载过高导致的性能下降或服务中断。
3.HPA实践——实现Web服务器的自动伸缩特性
在生产环境中,总会有一些意想不到的事情发生,比如公司网站流量突然升高,此时之前创建的Pod已不足以支撑所有的访问,而运维人员也不可能24小时守着业务服务,这时就可以通过配置HPA,实现负载过高的情况下自动扩容Pod副本数以分摊高并发的流量,当流量恢复正常后,HPA会自动缩减Pod的数量。
实现一个web服务器的自动伸缩特性
(1)首先Deployment启动一个Nginx服务(必须配置requests参数):
[root@k8s-master ~]# vim nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-server
labels:
name: nginx-server
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
resources:
requests:
cpu: 10m
image: nginx:1.7.9
ports:
- name: nginx
containerPort: 80
启动
[root@k8s-master ~]# vim nginx-deployment.yaml
[root@k8s-master ~]# ku create -f nginx-deployment.yaml
deployment.apps/nginx-server created
[root@k8s-master ~]# ku get pod
NAME READY STATUS RESTARTS AGE
nginx-server-6ddcfd4c8f-69z4h 1/1 Running 0 12s
nginx-server-6ddcfd4c8f-dhtzf 1/1 Running 0 12s
(2)配置nginx-server的service
[root@k8s-master ~]# ku expose deployment nginx-server --port=80
service/nginx-server exposed
[root@k8s-master ~]# ku get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-server ClusterIP 10.96.1.192 <none> 80/TCP 30s
(3)使用kubectl autoscale命令创建HPA
[root@k8s-master ~]# ku autoscale deployment nginx-server --cpu-percent=10 --min=1 --max=10
horizontalpodautoscaler.autoscaling/nginx-server autoscaled
此时PHA将根据CPU的使用率自动增加和减少副本数量,上述设置的是CPU使用率超过10%(--cpu-percent参数指定)就会增加Pod的数量,以保持所有Pod的平均CPU利用率为10%,允许最大pod的数量为10(--max),最少数量为1(--min)
(4)查看当前HPA的状态
[root@k8s-master ~]# ku get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-server Deployment/nginx-server 0%/10% 1 10 2 4m56s
因为未对其发送任何请求,所以当前CPU利用率为0%。
(5)查看当前nginx的service地址
[root@k8s-master ~]# ku get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8d
nginx-server ClusterIP 10.96.1.192 <none> 80/TCP 7h37m
(6)压力测试
打开一个新的终端,使用一个“死”循环或其他压测工具模仿访问service,从而增加该pod的负载
[root@k8s-master ~]# while true;do wget -q -o- http://10.96.1.192 >/dev/null;done
(7)查看HPA状态
等待一分钟左右,再次查看HPA,可以看到pod的cpu已经升高
[root@k8s-master ~]# ku get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-server Deployment/nginx-server 520%/10% 1 10 4 11m
查看pod,发现副本数也增加了
[root@k8s-master ~]# ku get pod
NAME READY STATUS RESTARTS AGE
nginx-server-6ddcfd4c8f-2mkk2 1/1 Running 0 29s
nginx-server-6ddcfd4c8f-2tb4z 1/1 Running 0 44s
nginx-server-6ddcfd4c8f-69z4h 1/1 Running 0 7h44m
nginx-server-6ddcfd4c8f-7g7wx 1/1 Running 0 14s
nginx-server-6ddcfd4c8f-9t7qn 1/1 Running 0 29s
nginx-server-6ddcfd4c8f-bjhfw 1/1 Running 0 44s
nginx-server-6ddcfd4c8f-d6lv8 1/1 Running 0 14s
nginx-server-6ddcfd4c8f-pjb7g 1/1 Running 0 29s
nginx-server-6ddcfd4c8f-t2pgl 1/1 Running 0 44s
nginx-server-6ddcfd4c8f-v6kg7 1/1 Running 0 29s
(8)停止压力测试
发现cpu的使用率很快就降下来了
[root@k8s-master ~]# ku get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-server Deployment/nginx-server 0%/10% 1 10 10 15m
pod的副本数量要等几分钟再去查看
[root@k8s-master ~]# ku get pod
NAME READY STATUS RESTARTS AGE
nginx-server-6ddcfd4c8f-69z4h 1/1 Running 0 7h54m