一、k8s简介及部署方法
1、k8s简介
kubernetes的本质是一组服务器集群,它可以在集群的每个节点上运行特定的程序,来对节点中的容器进行管理。目的是实现资源管理的自动化,主要提供了如下的主要功能:
自我修复:一旦某一个容器崩溃,能够在1秒中左右迅速启动新的容器
弹性伸缩:可以根据需要,自动对集群中正在运行的容器数量进行调整
服务发现:服务可以通过自动发现的形式找到它所依赖的服务
负载均衡:如果一个服务起动了多个容器,能够自动实现请求的负载均衡
版本回退:如果发现新发布的程序版本有问题,可以立即回退到原来的版本
存储编排:可以根据容器自身的需求自动创建存储卷
2、k8s的设计架构
一个kubernetes集群主要是由控制节点(master)、工作节点(node)构成,每个节点上都会安装不同的组件
2.1、k8s-master节点组件
apiserver:不需要登录到每台服务器,只需调用接口,就可以接收命令,进行操作
scheduler:不用进入每台服务器查看cpu和内存,就可以进行集群资源调度,将pod调度到相应节点
controller manager:维护集群状态,不需要手动去创建关闭服务
etcd:存储集群资源信息
2.2、k8s-node节点组件
- kubelet:管理和监控pod,创建和销毁容器,同时负责管理资源卷和网络
- pod:资源调度的最小单元
- kube-proxy:将外部请求转发至pod,提供容器内部服务发现和负载均衡
- container runtime:容器运行时组件
2.3、k8s各组件之间的调用关系
当我们要运行一个服务时
- k8s环境启动后,master和nide都会将自身的信息存储到etcd数据库中
- web服务的安装请求会首先被发送到master节点的apiServer组件
- apiServer组件会调用scheduler组件来决定应该把这个服务安装到哪一个node节点,scheduler组件会从etcd数据库中读取各个node节点的信息,然后按照一定的算法进行选择,并将结果返回apiServer
- apiServer调用controller-manager去调度Node节点安装对应服务
- kubelet接收到指令后,会通知docker,然后由docker启动一个对应服务的pod
- 如果需要访问web服务,就需要通过kube-proxy来对pod产生访问的代理
2.4、k8s的常用名词
- master:集群控制节点,每个集群需要至少一个master节点负责集群的管控
- node:工作节点,由master分配容器到这个node工作节点上
- pod:k8s的最小控制单元,容器都是运行在pod中,一个pod可有一个或多个容器
- controller:控制器,通过它实现对pod的管理,如启动pod,停止pod,伸缩pod数量等
- service:微服务,pod对外服务的统一入口,下面可以维护同一类的多个pod
- label:标签,用于对pod进行分类,同一类的pod拥有相同的标签
- nameSpace:命名空间,用来隔离pod的运行环境
3、k8s集群环境搭建
3.1、集群环境规划
主机名 | IP | 角色 |
www.yjun.com | 192.168.220.100 | harbor仓库 |
k8s-master | 192.168.220.10 | k8s集群控制节点 |
k8s-node1 | 192.168.220.20 | k8s集群工作节点 |
k8s-node2 | 192.168.220.30 | k8s集群工作节点 |
3.2、集群环境初始化
所有节点关闭selinux和防火墙,并将其上锁防止其他服务将其打开
systemctl stop firewalld.service
systemctl disabled firewalld.service
systemctl mask firewalld.service
grubby --update-kernel ALL --args selinux=0
所有节点在每次开启的时候禁用交换分区
#查看交换运行的交换分区
[root@www ~]# swapon -s
Filename Type Size Used Priority
/dev/dm-1 partition 4108284 41984 -2
vim /etc/rc.d/rc.local
swapoff /dev/dm-1
chmod +x /etc/rc.d/rc.local
所有节点做好dns解析
[root@k8s-master ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.220.10 k8s-master
192.168.220.20 k8s-node1
192.168.220.30 k8s-node2
192.168.220.100 www.yjun.com
所有节点安装docker
#配置docker的yum仓库
[root@k8s-master ~]# cat /etc/yum.repos.d/docker.repo
[docker]
name=docker
baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/rhel/9/x86_64/stable/
gpgcheck=0
#下载docker
yum install docker-ce -y
所有节点复制harbor仓库中的证书并启动docker
#创建证书存放目录
[root@k8s-master ~]# mkdir -p /etc/docker/certs.d/www.yjun.com
#把harbor仓库中的证书拷贝到k8s所有的节点
scp /data/cert/yjun.com.crt root@192.168.220.10:/etc/docker/certs.d/www.yjun.com/
#启动docker
systemctl enable --now docker
登录并查看harbor仓库的认证
#登录harbor
[root@k8s-master ~]# docker login www.yjun.com
Authenticating with existing credentials...
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/#credential-stores
Login Succeeded
#查看认证
[root@k8s-master ~]# docker info
Client: Docker Engine - Community
Version: 27.2.1
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.16.2
Path: /usr/libexec/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v2.29.2
Path: /usr/libexec/docker/cli-plugins/docker-compose
Server:
Containers: 34
Running: 16
Paused: 0
Stopped: 18
Images: 15
Server Version: 27.2.1
Storage Driver: overlay2
Backing Filesystem: xfs
Supports d_type: true
Using metacopy: false
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: systemd
Cgroup Version: 2
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 7f7fdf5fed64eb6a7caf99b3e12efcf9d60e311c
runc version: v1.1.14-0-g2c9f560
init version: de40ad0
Security Options:
seccomp
Profile: builtin
cgroupns
Kernel Version: 5.14.0-162.6.1.el9_1.x86_64
Operating System: Red Hat Enterprise Linux 9.1 (Plow)
OSType: linux
Architecture: x86_64
CPUs: 2
Total Memory: 3.543GiB
Name: k8s-master
ID: 35ee361d-0286-4227-8971-46729c61148c
Docker Root Dir: /var/lib/docker
Debug Mode: false
Experimental: false
Insecure Registries:
127.0.0.0/8
Registry Mirrors:
https://www.yjun.com/ #认证成功
Live Restore Enabled: false
3.3、安装k8s部署工具
在所有节点配置k8s的yum源
[root@k8s-master ~]# cat /etc/yum.repos.d/k8s.repo
[k8s]
name=k8s
baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.30/rpm
gpgcheck=0
在所有节点下载部署工具
yum install kubelet-1.30.0 kubeadm-1.30.0 kubectl-1.30.0 -y
在所有节点设置kubectl命令补齐功能
[root@k8s-master ~]# yum install bash-completion -y
[root@k8s-master ~]# echo "source <(kubectl completion bash)" >> ~/.bashrc
[root@k8s-master ~]# source ~/.bashrc
在所有节点安装cri-docker
dnf install libcgroup-0.41-19.el8.x86_64.rpm cri-dockerd-0.3.14-3.el8.x86_64.rpm -y
指定网络插件名称以及基础容器镜像
[root@k8s-master ~]# cat /lib/systemd/system/cri-docker.service
[Unit]
Description=CRI Interface for Docker Application Container Engine
Documentation=https://docs.mirantis.com
After=network-online.target firewalld.service docker.service
Wants=network-online.target
Requires=cri-docker.socket
[Service]
Type=notify
ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd:// --network-plugin=cni --pod-infra-container-image=www.yjun.com/k8s/pause:3.9
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
# Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229.
# Both the old, and new location are accepted by systemd 229 and up, so using the old location
# to make them work for either version of systemd.
StartLimitBurst=3
# Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.
# Both the old, and new name are accepted by systemd 230 and up, so using the old name to make
# this option work for either version of systemd.
StartLimitInterval=60s
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Comment TasksMax if your systemd version does not support it.
# Only systemd 226 and above support this option.
TasksMax=infinity
Delegate=yes
KillMode=process
[Install]
WantedBy=multi-user.target
[root@k8s-master ~]# systemctl daemon-reload
[root@k8s-master ~]# systemctl start cri-docker
在master节点拉取k8s所需镜像并上传镜像到harbor仓库
#拉取所需镜像
[root@k8s-master ~]# kubeadm config images pull --image-repository registry.aliyuncs.com/google_contaniers --kubernetes-version v1.30.0 --cri-socket=unix:///var/run/cri-dockerd.sock
#镜像重命名
[root@k8s-master ~]# docker images | awk '/google/{ print $1":"$2}' | awk -F "/" '{system("docker tag "$0" www.yjun.com/k8s/"$3)}'
#上传至harbor之间需要在harbor中建立对应的项目k8s
#上传镜像至harbor
[root@k8s-master ~]# docker images | awk '/k8s/{system("docker push "$1":"$2)}'
3.4、集群初始化
启动kubelet服务
[root@k8s-master ~]# systemctl enable --now kubelet
[root@k8s-master ~]# systemctl status kubelet.service
● kubelet.service - kubelet: The Kubernetes Node Agent
Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled)
Drop-In: /usr/lib/systemd/system/kubelet.service.d
└─10-kubeadm.conf
Active: active (running) since Wed 2024-10-09 20:25:22 CST; 1h 28min ago
Docs: https://kubernetes.io/docs/
Main PID: 939 (kubelet)
Tasks: 12 (limit: 22946)
Memory: 111.5M
CPU: 1min 1.293s
CGroup: /system.slice/kubelet.service
执行初始化命令
[root@k8s-master ~]# kubeadm init --pod-network-cidr=10.244.0.0/16 --image-repository www.yjun.com/k8s --kubernetes-version v1.30.0 --cri-socket=unix:///var/run/cri-dockerd.sock
指定集群配置文件变量
[root@k8s-master ~]# echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
安装flannel网络插件
# 下载flannel的yaml部署文件
wget https://github.com/flanne7.io/flannel/releases/latest/download/kube-flannel.yml
#拉取镜像
docker pull docker.io/flannel/flannel:v0.25.5
docekr docker.io/flannel/flannel-cni-plugin:v1.5.1-flannel1
#上传镜像
docker tag flannel/flannel:v0.25.5 www.yjun.com/flannel/flannel:v0.25.5
docker tag flannel/flannel-cni-plugin:v1.5.1-flannel1 www.yjun.com/flannel/flannel-cni-plugin:v1.5.1-flannel
docker push www.yjun.com/flannel/flannel:v0.25.5
docker push www.yjun.com/flannel/flannel-cni-plugin:v1.5.1-flannel
#修改flannel的yml文件,更改镜像下载位置
vim kube-flannel.yml
...
image: flannel/flannel:v0.25.5
image: flannel/flannel-cni-plugin:v1.5.1-flannel1
image: flannel/flannel:v0.25.5
...
#安装flannel网络插件
kubectl apply -f kube-flannel.yml
增加工作节点
#生成加入集群指令
[root@k8s-master ~]# kubeadm token create --print-join-command
kubeadm join 192.168.220.10:6443 --token 0kyf9x.5x69jlkby5eaq0s2 --discovery-token-ca-cert-hash sha256:8bd45b603a176204de3bfeeabbd1433b783f61848985a83289bcd76e7b40aa3f
[root@k8s-node1 ~]# kubeadm join 192.168.220.10:6443 --token 0kyf9x.5x69jlkby5eaq0s2 --discovery-token-ca-cert-hash sha256:8bd45b603a176204de3bfeeabbd1433b783f61848985a83289bcd76e7b40aa3f --cri-socket=unix:///var/run/cri-dockerd.sock
#在master上验证,ready则说明配置完成
[root@k8s-master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane 13d v1.30.5
k8s-node1 Ready <none> 13d v1.30.5
k8s-node2 Ready <none> 13d v1.30.5
二、kubernetes中pod的管理及优化
1、kubernetes中的资源
1.1、资源介绍管理
在kubernetes中,所有的内容都抽象为资源,用户需要通过操作资源来管理kubernetes。
kubernetes的本质上就是一个集群系统,用户可以在集群中部署各种服务
所谓的部署服务,其实就是在kubernetes集群中运行一个个的容器,并将指定的程序跑在容器中。
kubernetes的最小管理单元是pod而不是容器,只能将容器放在
Pod
中kubernetes一般也不会直接管理Pod,而是通过
Pod控制器
来管理Pod的。Pod中服务服务的访问是由kubernetes提供的
Service
资源来实现。Pod中程序的数据需要持久化是由kubernetes提供的各种
存储
系统来实现
1.2、资源管理方式
- 命令式对象管理:直接使用命令去操作kubernetes资源
kubectl run nginx-pod --image=nginx:latest --port=80
- 命令式对象配置:通过命令配置和配置文件去操作kubernetes资源
kubectl create/patch -f nginx-pod.yaml
- 声明式对象配置:通过apply命令和配置文件去操作kubernetes资源
kubectl apply -f nginx-pod.yaml
类型 | 适用环境 | 优点 | 缺点 |
命令式对象管理 | 测试 | 简单 | 只能操作活动对象,无法审计、跟踪 |
命令式对象配置 | 开发 | 可以审计、跟踪 | 项目大时,配置文件多,操作麻烦 |
声明式对象配置 | 开发 | 支持目录操作 | 意外情况下难以调试 |
1.2.1、命令式对象管理
语法:kubectl [command] [type] [name] [flags]
command:指定要对资源执行的操作,例如create、get、delete
type:指定资源类型,比如deployment、pod、service
name:指定资源的名字,名称大小写敏感
flags:指定额外的可选参数
例:
kubectl get all #查看默认命名空间内所有内容
kubectl get pod pod_name #查看某个pod
kubectl get pod pod_name -o yaml #查看某个pod,以yaml格式展示结果
1.2.2、基本命令
#显示所有的资源
kubectl api-resources
#显示集群版本
kubectl version
#显示集群信息
kubectl cluster-info
#创建控制器
kubectl create deployment webcluster --image nginx --replicas 2
#查看控制器
kubectl get deployment.app
#查看资源帮助
kubectl explain resources_name
#编辑控制器配置(相当于修改yaml文件)
kubectl edit deployment.app webcluster
#利用补丁更改控制器配置
kubectl patch deployment.app webcluster -p '{"spec":{"replicas":4}}'
#删除资源
kubectl delete deployment.app webcluster
#运行pod
kubectl run nginx --image nginx
#查看pod详细信息
kubectl get pods -o wide
#端口暴露
kubectl expose pod nginx --port 80 --target-port 80
#查看端口暴露
kubectl get services -o wide
#查看资源详细信息
kubectl describe pods nginx
#查看资源日志
kubectl logs pods/nginx
#运行交互pod
kubectl run test -it --image busybox
#退出不停止交互pod
ctil + p + q
#进入到已经运行的容器,且容器由交互环境
kubectl attach pods/nginx -it
#在已经运行的pod中运行指定命令
kubectl exec -it pods/nginx /bin/bash
#把宿主机文件传送到pod中
kubectl cp test nginx:/
#复制pod中的文件到宿主机
kubectl cp nginx:/test test
#利用命令生成yaml模板文件
kubectl create deployment webcluster --image nginx --dry-run=client -o yaml > webcluster.yaml
#利用yaml文件生成资源
kubectl apply -f webcluster.yaml
#删除yaml文件生成的资源
kubectl delete -f webcluster.yaml
#查看资源标签
kubectl get pods --show-labels
#更改资源标签
kubectl label pods nginx app=webcluster --overwrite
#删除标签
kubectl label pods nginx app-
2、pod
- pod是可以创建和管理kubernetes计算的最小可部署单元
- 一个pod代表着集群中运行的一个进程,每个pod都有一个唯一的ip
- 一个pod类似一个豌豆荚,包含一个或多个容器
- 多个容器共享IPC、Network和UTC namespace
2.1、创建自主式pod(生产不推荐)
优点
- 灵活性高:可以精确控制pod的各种配置参数,包括容器的镜像、资源限制、环境变量、命令和参数等,满足特定的应用需求
- 学习和调试方便:对于学习K8S的原理和机制非常有帮助,通过手动创建Pod可以深入了解Pod的结构和配置方式。在调试问题时,可以更直接地观察和调整Pod的设置
- 适用于特殊场景:如进行一次性任务,快速验证概念或在资源受限的环境中进行特点配置时,手动创建Pod可能时一种有效的方式
缺点
- 管理复杂:如果需要管理大量的Pod,手动创建和维护会变得非常繁琐和耗时。难以实现自动化的扩缩容,故障恢复等操作
- 缺乏高级功能:无法自动享受k8s提供的高级功能,像自动部署、滚动更新、服务发现等。会导致应用的部署和管理效率低下
- 可维护性差:手动创建的Pod在更新应用版本或修改配置时需要手动干预,容易出现错误,并且难以保证一致性。相比之下,通过声明式配置或使用k8s的部署工具可以更方便地进行应用地维护和更新
2.2、通过控制器管理Pod
高可用和可靠性
- 自动故障恢复:如果一个Pod失败或被删除,控制器会自动创建新的Pod来维持期望地副本数量。确保应用始终处于可用状态,减少因单个Pod故障导致地服务中断
- 健康检查和自愈:可以配置控制器对Pod进行健康检查(存活指针和就绪指针)如果Pod不健康,控制器回采取适当地行动,如重启Pod或删除并重新创建它,以保证应用地正常运行。
可扩展性:
- 轻松扩缩容:可以通过简单地命令或配置更改来减少或增加Pod地数量,以满足不同的工作负载需求。
- 水平自动扩缩容(HPA)可以基于自定义指标(如CPU利用率,内存使用情况或应用特定的指标)自动调整Pod的数量,实现动态的资源分配和成本优化
版本管理和更新
- 滚动更新:对于Deployment等控制器,可以执行滚动更新来逐步替换旧版本的Pod为新版本,确保应用在更新过程中始终保持可用。可以控制更新的速率和策略,以减少对用户的影响
- 回滚:如果更新出现问题,可轻松回滚到上一个稳定版本,保证应用的稳定性和可靠性
声明式配置
- 简洁的配置方式:使用YAML或JSON格式的声明式配置文件来定义应用的部署要求,这种方式使得配置易于理解、维护和版本控制,同时也方便团队协作。
- 期望状态管理:只需要定义应用的期望状态(如副本数量,容器镜像等)控制器回自动调整实际状态与期望状态保持一致。无需手动管理每个Pod的创建和删除,提高了管理效率
服务发现和负载均衡
- 自动注册和发现:k8s中的服务(service)可以自动发现有控制器管理的Pod,并将流量路由到它们。这使得应用的服务发现和负载均衡变得简单和可靠,无需手动配置负载均衡器
- 流量分发:可以根据不同的策略(如轮询,随机等)将请求分发到不同的Pod,提高英语的性能和可用性
多环节一致性:
- 一致的部署方式:在不同的环境(如开发、测试、生产)中,可以使用相同的控制器和配置来部署应用,确保应用在不同环境中的行为一致。这有助于减少部署差异和错误,提高开发和运维效率
建立控制器并自动运行Pod
[root@k8s-master ~]# kubectl create deployment test --image www.yjun.com/yjun/nginx:latest --replicas 2
deployment.apps/test created
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test-d8887d5d9-62vr8 1/1 Running 0 6m49s
test-d8887d5d9-vpdsr 1/1 Running 0 6m49s
通过该控制器扩缩容
[root@k8s-master ~]# kubectl scale deployment test --replicas 4
deployment.apps/test scaled
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test-d8887d5d9-2jtm4 1/1 Running 0 5s
test-d8887d5d9-62vr8 1/1 Running 0 7m6s
test-d8887d5d9-vpdsr 1/1 Running 0 7m6s
test-d8887d5d9-wp44n 1/1 Running 0 5s
[root@k8s-master ~]# kubectl scale deployment test --replicas 1
deployment.apps/test scaled
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test-d8887d5d9-vpdsr 1/1 Running 0 7m21s
2.3、应用版本的更新
利用控制器建立Pod
kubectl create deployment yjun --image www.yjun.com/yjun/myapp:v1 --replicas 2
暴露端口
kubectl expose deployment yjun --port 80 --target-port 80
[root@k8s-master ~]# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 14d
yjun ClusterIP 10.101.243.88 <none> 80/TCP 8s
访问服务
[root@k8s-master ~]# curl 10.101.243.88
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
查看历史版本
[root@k8s-master ~]# kubectl rollout history deployment yjun
deployment.apps/yjun
REVISION CHANGE-CAUSE
1 <none>
更改控制器镜像版本
[root@k8s-master ~]# kubectl set image deployment/yjun myapp=www.yjun.com/yjun/myapp:v2
deployment.apps/yjun image updated
查看历史版本
[root@k8s-master ~]# kubectl rollout history deployment yjun
deployment.apps/yjun
REVISION CHANGE-CAUSE
1 <none>
2 <none>
访问服务
[root@k8s-master ~]# curl 10.101.243.88
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
版本回滚
[root@k8s-master ~]# kubectl rollout undo deployment yjun --to-revision 1
deployment.apps/yjun rolled back
查看历史版本
[root@k8s-master ~]# kubectl rollout history deployment yjun
deployment.apps/yjun
REVISION CHANGE-CAUSE
2 <none>
3 <none>
访问服务
[root@k8s-master ~]# curl 10.101.243.88
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
2.4、利用yaml文件部署应用
优点
- 声明式配置:
- 清晰表达期望状态:以声明式的方式描述应用的部署需求,包括副本数量、容器配置、网络设置等。这使得配置易于理解和维护,并且可以方便地查看应用的预期状态。
- 可重复性和版本控制:配置文件可以被版本控制,确保在不同环境中的部署一致性。可以轻松回滚到以前的版本或在不同环境中重复使用相同的配置。
- 团队协作:便于团队成员之间共享和协作,大家可以对配置文件进行审查和修改,提高部署的可靠性和稳定性。
- 灵活性和可扩展性
丰富的配置选项:可以通过 YAML 文件详细地配置各种 Kubernetes 资源,如 Deployment、Service、ConfigMap、Secret 等。可以根据应用的特定需求进行高度定制化。
组合和扩展:可以将多个资源的配置组合在一个或多个 YAML 文件中,实现复杂的应用部署架构。同时,可以轻松地添加新的资源或修改现有资源以满足不断变化的需求。
与工具集成
与 CI/CD 流程集成:可以将 YAML 配置文件与持续集成和持续部署(CI/CD)工具集成,实现自动化的应用部署。例如,可以在代码提交后自动触发部署流程,使用配置文件来部署应用到不同的环境。
命令行工具支持:Kubernetes 的命令行工具
kubectl
对 YAML 配置文件有很好的支持,可以方便地应用、更新和删除配置。同时,还可以使用其他工具来验证和分析 YAML 配置文件,确保其正确性和安全性。
编写示例
运行简单的单个容器pod
[root@k8s-master ~]# kubectl run test --image www.yjun.com/yjun/myapp:v1 --dry-run=client -o yaml > pod.yaml
[root@k8s-master ~]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: test
name: test
spec:
containers:
- image: www.yjun.com/yjun/myapp:v1
name: test
dnsPolicy: ClusterFirst
restartPolicy: Always
[root@k8s-master ~]# kubectl apply -f pod.yaml
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test 1/1 Running 0 24s
运行多个容器Pod(多个容器共享资源的同时也会相互干扰,比如端口)
[root@k8s-master ~]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: test
name: test
spec:
containers:
- image: www.yjun.com/yjun/myapp:v1
name: test1
- image: www.yjun.com/yjun/myapp:v1
name: test2
[root@k8s-master ~]# kubectl apply -f pod.yaml
pod/test created
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test 2/2 Running 1 (3s ago) 6s
pod间的网络整合
[root@k8s-master ~]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: test
name: test
spec:
containers:
- image: www.yjun.com/yjun/myapp:v1
name: myapp1
- image: www.yjun.com/yjun/busyboxplus:latest
name: busyboxplus
command: ["/bin/sh", "-c","sleep 1000000"]
[root@k8s-master ~]# kubectl apply -f pod.yaml
pod/test unchanged
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test 2/2 Running 0 50s
[root@k8s-master ~]# kubectl exec test -c busyboxplus -- curl -s localhost
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
端口映射
[root@k8s-master ~]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: test
name: test
spec:
containers:
- image: www.yjun.com/yjun/myapp:v1
name: myapp1
ports:
- name: http
containerPort: 80
hostPort: 80
protocol: TCP
[root@k8s-master ~]# kubectl apply -f pod.yaml
pod/test created
[root@k8s-master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test 1/1 Running 0 10s 10.244.1.14 k8s-node1 <none> <none>
[root@k8s-master ~]# curl k8s-node1
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
如何设定环境变量
[root@k8s-master ~]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: test
name: test
spec:
containers:
- image: www.yjun.com/yjun/busybox:latest
name: busybox
command: ["/bin/sh","-c","echo $TARGET;sleep 1000"]
env:
- name: TARGET
value: Hello World
[root@k8s-master ~]# kubectl apply -f pod.yaml
pod/test created
[root@k8s-master ~]# kubectl logs pods/test busybox
Hello World
资源限制
资源限制会影响pod的Qos Class资源优先级,资源优先级分为Guaranteed > Burstable > BestEffort
BestEffort:资源限制未设定
Burstable:资源限制最高限制和资源使用限制不一致
Guaranteed:资源限制最高限制和资源使用限制一致
[root@k8s-master ~]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: test
name: test
spec:
containers:
- image: www.yjun.com/yjun/myapp:v1
name: myappv1
resources:
limits:
cpu: 0.5
memory: 100M
requests:
cpu: 0.5
memory: 100M
[root@k8s-master ~]# kubectl apply -f pod.yaml
pod/test created
[root@k8s-master ~]# kubectl describe pods test
Name: test
Namespace: default
Priority: 0
Service Account: default
Node: k8s-node1/192.168.220.20
Start Time: Fri, 11 Oct 2024 20:25:20 +0800
Labels: run=test
Annotations: <none>
Status: Running
IP: 10.244.1.16
IPs:
IP: 10.244.1.16
Containers:
myappv1:
Container ID: docker://2837196844c897cef04863d00fc387fadf171d35e538401d56dd9a4038f1d4a7
Image: www.yjun.com/yjun/myapp:v1
Image ID: docker-pullable://www.yjun.com/yjun/myapp@sha256:9eeca44ba2d410e54fccc54cbe9c021802aa8b9836a0bcf3d3229354e4c8870e
Port: <none>
Host Port: <none>
State: Running
Started: Fri, 11 Oct 2024 20:25:21 +0800
Ready: True
Restart Count: 0
Limits:
cpu: 500m
memory: 100M
Requests:
cpu: 500m
memory: 100M
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-jrcwn (ro)
Conditions:
Type Status
PodReadyToStartContainers True
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-jrcwn:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: Guaranteed
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 16s default-scheduler Successfully assigned default/test to k8s-node1
Normal Pulled 15s kubelet Container image "www.yjun.com/yjun/myapp:v1" already present on machine
Normal Created 15s kubelet Created container myappv1
Normal Started 15s kubelet Started container myappv1
容器启动管理
[root@k8s-master ~]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: test
name: test
spec:
restartPolicy: Always
containers:
- image: www.yjun.com/yjun/myapp:v1
name: myappv1
[root@k8s-master ~]# kubectl apply -f pod.yaml
pod/test created
[root@k8s-master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test 1/1 Running 0 23s 10.244.1.17 k8s-node1 <none> <none>
选择运行节点
[root@k8s-master ~]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: test
name: test
spec:
nodeSelector:
kubernetes.io/hostname: k8s-node2
containers:
- image: www.yjun.com/yjun/myapp:v1
name: myappv1
[root@k8s-master ~]# kubectl apply -f pod.yaml
pod/test created
[root@k8s-master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test 1/1 Running 0 8s 10.244.2.14 k8s-node2 <none> <none>
共享宿主机网络
[root@k8s-master ~]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: test
name: test
spec:
hostNetwork: true
nodeSelector:
kubernetes.io/hostname: k8s-node2
containers:
- image: www.yjun.com/yjun/busybox:latest
name: busybox
command: ["/bin/sh","-c","sleep 1000"]
[root@k8s-master ~]# kubectl apply -f pod.yaml
pod/test created
[root@k8s-master ~]# kubectl exec -it pods/test -c busybox -- /bin/sh
/ #
/ # ifconfig
cni0 Link encap:Ethernet HWaddr EE:3A:1C:1A:BF:B3
inet addr:10.244.2.1 Bcast:10.244.2.255 Mask:255.255.255.0
inet6 addr: fe80::ec3a:1cff:fe1a:bfb3/64 Scope:Link
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:139 errors:0 dropped:0 overruns:0 frame:0
TX packets:40 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:9290 (9.0 KiB) TX bytes:3545 (3.4 KiB)
docker0 Link encap:Ethernet HWaddr 02:42:03:FA:EF:74
inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
eth0 Link encap:Ethernet HWaddr 00:0C:29:0D:4F:66
inet addr:192.168.220.30 Bcast:192.168.220.255 Mask:255.255.255.0
inet6 addr: fe80::d2ab:3908:c98b:1e39/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:38426 errors:0 dropped:0 overruns:0 frame:0
TX packets:27367 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:16798653 (16.0 MiB) TX bytes:3171954 (3.0 MiB)
flannel.1 Link encap:Ethernet HWaddr 26:E3:05:A9:50:05
inet addr:10.244.2.0 Bcast:0.0.0.0 Mask:255.255.255.255
inet6 addr: fe80::24e3:5ff:fea9:5005/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1
RX packets:14 errors:0 dropped:0 overruns:0 frame:0
TX packets:10 errors:0 dropped:18 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:897 (897.0 B) TX bytes:1138 (1.1 KiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:284 errors:0 dropped:0 overruns:0 frame:0
TX packets:284 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:22475 (21.9 KiB) TX bytes:22475 (21.9 KiB)
3、pod的生命周期
3.1、探针
probe (探针)是由 kubelet 对容器执行的定期诊断
探针的四种检查机制
- exec:在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。
- grpc:使用 gRPC 执行一个远程过程调用。 目标应该实现 gRPC 健康检查。 如果响应的状态是 "SERVING",则认为诊断成功。
- httpGet:对容器的 IP 地址上指定端口和路径执行 HTTP
GET
请求。如果响应的状态码大于等于 200 且小于 400,则诊断被认为是成功的。- tcpSocket:对容器的 IP 地址上的指定端口执行 TCP 检查。如果端口打开,则诊断被认为是成功的。 如果远程系统(容器)在打开连接后立即将其关闭,这算作是健康的。
NOTE:和其他机制不同,
exec
探针的实现涉及每次执行时创建/复制多个进程。 因此,在集群中具有较高 pod 密度、较低的initialDelaySeconds
和periodSeconds
时长的时候, 配置任何使用 exec 机制的探针可能会增加节点的 CPU 负载。 这种场景下,请考虑使用其他探针机制以避免额外的开销。
探针的三种探测结果
Success
(成功)容器通过了诊断。Failure
(失败)容器未通过诊断。Unknown
(未知)诊断失败,因此不会采取任何行动。每次探测都将获得上述三种结果之一
探针类型
- livenessProbe(生存探针)检测容器是否正在运行。如果存活态探测失败,则 kubelet 会杀死容器, 并且容器将根据其重启策略决定未来。如果容器不提供存活探针, 则默认状态为
Success
。- readinessProbe(就绪探针)检测容器是否准备好为请求提供服务。如果就绪态探测失败, 端点控制器将从与 Pod 匹配的所有服务的端点列表中删除该 Pod 的 IP 地址。 初始延迟之前的就绪态的状态值默认为
Failure
。 如果容器不提供就绪态探针,则默认状态为Success
。- startupProbe(启动探针)检测容器中的应用是否已经启动。如果提供了启动探针,则所有其他探针都会被禁用,直到此探针成功为止。如果启动探测失败,
kubelet
将杀死容器, 而容器依其重启策略进行重启。 如果容器没有提供启动探测,则默认状态为Success
。
ReadinessProbe 与 LivenessProbe 的区别
ReadinessProbe 当检测失败后,将 Pod 的 IP:Port 从对应的 EndPoint 列表中删除
LivenessProbe 当检测失败后,将杀死容器并根据 Pod 的重启策略来决定作出对应的措施
StartupProbe 与 ReadinessProbe、LivenessProbe 的区别
如果三个探针同时存在,先执行 StartupProbe 探针,其他两个探针将会被暂时禁用,直到 pod 满足 StartupProbe 探针配置的条件,其他 2 个探针启动,如果不满足按照规则重启容器。
另外两种探针在容器启动后,会按照配置,直到容器消亡才停止探测,而 StartupProbe 探针只是在容器启动后按照配置满足一次后,不在进行后续的探测。
何时该使用存活态探针?
- 如果容器中的进程能够在遇到问题或不健康的情况下自行崩溃,则不一定需要存活态探针;
kubelet
将根据 Pod 的restartPolicy
自动执行修复操作。- 如果你希望容器在探测失败时被杀死并重新启动,那么请指定一个存活态探针, 并指定
restartPolicy
为 "Always
" 或 "OnFailure
"
3.2、Init容器
每个 Pod 中可以包含多个容器, 应用运行在这些容器里面,同时 Pod 也可以有一个或多个先于应用容器启动的 Init 容器。
Init 容器与普通的容器非常像,除了如下两点:
- 它们总是运行到完成。
- 每个都必须在下一个启动之前成功完成。
如果 Pod 的 Init 容器失败,kubelet 会不断地重启该 Init 容器直到该容器成功为止。 然而,如果 Pod 对应的
restartPolicy
值为 "Never",并且 Pod 的 Init 容器失败, 则 Kubernetes 会将整个 Pod 状态设置为失败。常规的 Init 容器不支持
livenessProbe readinessProbe
或startupProbe
字段。
Init容器的优势
Init 容器可以包含一些安装过程中应用容器中不存在的实用工具或个性化代码。 例如,没有必要仅为了在安装过程中使用类似
sed
、awk
、python
或dig
这样的工具而去FROM
一个镜像来生成一个新的镜像。应用镜像的创建者和部署者可以各自独立工作,而没有必要联合构建一个单独的应用镜像。
与同一 Pod 中的多个应用容器相比,Init 容器能以不同的文件系统视图运行。因此,Init 容器可以被赋予访问应用容器不能访问的 Secret 的权限。
由于 Init 容器必须在应用容器启动之前运行完成,因此 Init 容器提供了一种机制来阻塞或延迟应用容器的启动,直到满足了一组先决条件。 一旦前置条件满足,Pod 内的所有的应用容器会并行启动。
Init 容器可以安全地运行实用程序或自定义代码,而在其他方式下运行这些实用程序或自定义代码可能会降低应用容器镜像的安全性。 通过将不必要的工具分开,你可以限制应用容器镜像的被攻击范围。
下面是Init容器的一些示例
#下面的例子定义了一个具有 2 个 Init 容器的简单 Pod。 第一个等待 /test1 创建, 第二个等待 /test2 创建。 一旦这两个 Init 容器都启动完成,Pod 将启动 spec 节中的应用容器。
[root@k8s-master ~]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
name: initpod
name: initpod
spec:
containers:
- image: www.yjun.com/yjun/myapp:v1
name: myapp
initContainers:
- name: init-busybox1
image: www.yjun.com/yjun/busybox:latest
command: ["sh","-c","until test -e /test1;do echo wating for myservice; sleep 2;done"]
- name: init-busybox2
image: www.yjun.com/yjun/busybox:latest
command: ["sh","-c","until test -e /test2;do echo wating for myservice; sleep 2;done"]
#启动pod
[root@k8s-master ~]# kubectl apply -f pod.yaml
#输出类似于:
pod/initpod created
#使用下面的命令检查其状态:
[root@k8s-master ~]# kubectl get -f pod.yaml
#输出类似于:
NAME READY STATUS RESTARTS AGE
initpod 0/1 Init:0/2 0 3m26s
#第一个/test1 创建后
[root@k8s-master ~]# kubectl exec pods/initpod -c init-busybox1 -- /bin/sh -c "touch /test1"
[root@k8s-master ~]# kubectl get -f pod.yaml
NAME READY STATUS RESTARTS AGE
initpod 0/1 Init:1/2 0 5m41s
#第二个 /test2创建后
[root@k8s-master ~]# kubectl exec pods/initpod -c init-busybox2 -- /bin/sh -c "touch /test2"
[root@k8s-master ~]# kubectl get -f pod.yaml
NAME READY STATUS RESTARTS AGE
initpod 1/1 Running 0 6m31s
三、控制器的使用
控制器也是管理pod的一种手段
自主式pod:pod退出或意外关闭后不会被重新创建
控制器管理的 Pod:在控制器的生命周期里,始终要维持 Pod 的副本数目
Pod控制器是管理pod的中间层,使用Pod控制器之后,只需要告诉Pod控制器,想要多少个什么样的Pod就可以了,它会创建出满足条件的Pod并确保每一个Pod资源处于用户期望的目标状态。如果Pod资源在运行中出现故障,它会基于指定策略重新编排Pod
当建立控制器后,会把期望值写入etcd,k8s中的apiserver检索etcd中我们保存的期望状态,并对比pod的当前状态,如果出现差异代码自驱动立即恢复
1、控制器常用类型
Deployment:(也间接包括 ReplicaSet) 是在集群上运行应用的最常见方式。Deployment 适合在集群上管理无状态应用工作负载, 其中 Deployment 中的任何 Pod 都是可互换的,可以在需要时进行替换。 (Deployment 替代原来的 ReplicationController API)。
- StatefulSet:允许你管理一个或多个运行相同应用代码、但具有不同身份标识的 Pod。 StatefulSet 与 Deployment 不同。Deployment 中的 Pod 预期是可互换的。 StatefulSet 最常见的用途是能够建立其 Pod 与其持久化存储之间的关联。 例如,你可以运行一个将每个 Pod 关联到 PersistentVolume 的 StatefulSet。如果该 StatefulSet 中的一个 Pod 失败了,Kubernetes 将创建一个新的 Pod, 并连接到相同的 PersistentVolume。
- DaemonSet:定义了在特定节点上提供本地设施的 Pod, 例如允许该节点上的容器访问存储系统的驱动。当必须在合适的节点上运行某种驱动或其他节点级别的服务时, 你可以使用 DaemonSet。DaemonSet 中的每个 Pod 执行类似于经典 Unix / POSIX 服务器上的系统守护进程的角色。DaemonSet 可能对集群的操作至关重要, 例如作为插件让该节点访问集群网络, 也可能帮助你管理节点,或者提供增强正在运行的容器平台所需的、不太重要的设施。 你可以在集群的每个节点上运行 DaemonSets(及其 Pod),或者仅在某个子集上运行 (例如,只在安装了 GPU 的节点上安装 GPU 加速驱动)。
- job:执行批处理任务,仅执行一次任务,保证任务的一个或多个Pod成功结束
- cronjob:Cron Job 创建基于时间调度的 Jobs。
2、ReplicaSet
2.1、功能
ReplicaSet 是下一代的 Replication Controller,官方推荐使用ReplicaSet
ReplicaSet和Replication Controller的唯一区别是选择器的支持,ReplicaSet支持新的基于集合的选择器需求
ReplicaSet 确保任何时间都有指定数量的 Pod 副本在运行
虽然 ReplicaSets 可以独立使用,但今天它主要被Deployments 用作协调 Pod 创建、删除和更新的机制
2.2、示例
[root@k8s-master ~]# cat replicaset.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: replicaset
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: www.yjun.com/yjun/myapp:v1
#运行该控制器
[root@k8s-master ~]# kubectl apply -f replicaset.yaml
#查看该控制器信息
[root@k8s-master ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
replicaset 2 2 2 28s
#查看控制器的详细信息
[root@k8s-master ~]# kubectl describe replicasets.apps replicaset
Name: replicaset
Namespace: default
Selector: app=myapp
Labels: <none>
Annotations: <none>
Replicas: 2 current / 2 desired
Pods Status: 2 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
Labels: app=myapp
Containers:
myapp:
Image: www.yjun.com/yjun/myapp:v1
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
Node-Selectors: <none>
Tolerations: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 9m53s replicaset-controller Created pod: replicaset-nmnck
Normal SuccessfulCreate 9m53s replicaset-controller Created pod: replicaset-rtghk
#查看控制器控制的Pod的信息
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
replicaset-nmnck 1/1 Running 0 11m
replicaset-rtghk 1/1 Running 0 11m
#查看控制器控制的Pod的标签
[root@k8s-master ~]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
replicaset-nmnck 1/1 Running 0 13m app=myapp
replicaset-rtghk 1/1 Running 0 13m app=myapp
#控制器是通过匹配标签来控制Pod
#控制器自动控制Pod的数量,Pod可以自愈
3、deployment
3.1、介绍
deployment控制器
为了更好的解决服务编排的问题,kubernetes在V1.2版本开始,引入了Deployment控制器。
Deployment控制器并不直接管理pod,而是通过管理ReplicaSet来间接管理Pod
Deployment管理ReplicaSet,ReplicaSet管理Pod
Deployment 为 Pod 和 ReplicaSet 提供了一个申明式的定义方法
在Deployment中ReplicaSet相当于一个版本
典型的应用场景
用来创建Pod和ReplicaSet
滚动更新和回滚
扩容和缩容
暂停与恢复
3.2、示例
#生成yaml文件
[root@k8s-master ~]# kubectl create deployment deployment --image www.yjun.com/yjun/myapp:v1 --dry-run=client -o yaml > deployment.yaml
[root@k8s-master ~]# cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: deployment
name: deployment
spec:
replicas: 4
selector:
matchLabels:
app: deployment
template:
metadata:
labels:
app: deployment
spec:
containers:
- image: www.yjun.com/yjun/myapp:v1
name: myapp
#建立Pod
[root@k8s-master ~]# kubectl apply -f deployment.yaml
deployment.apps/deployment created
#查看pod信息
[root@k8s-master ~]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
deployment-77567fbdbd-2mnfw 1/1 Running 0 31s app=deployment,pod-template-hash=77567fbdbd
deployment-77567fbdbd-6s6p4 1/1 Running 0 31s app=deployment,pod-template-hash=77567fbdbd
deployment-77567fbdbd-kwfpn 1/1 Running 0 31s app=deployment,pod-template-hash=77567fbdbd
deployment-77567fbdbd-phmlb 1/1 Running 0 31s app=deployment,pod-template-hash=77567fbdbd
3.2.1、版本迭代
#版本迭代之前
[root@k8s-master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
deployment-77567fbdbd-2mnfw 1/1 Running 0 80s 10.244.1.21 k8s-node1 <none> <none>
deployment-77567fbdbd-6s6p4 1/1 Running 0 80s 10.244.2.17 k8s-node2 <none> <none>
deployment-77567fbdbd-kwfpn 1/1 Running 0 80s 10.244.1.20 k8s-node1 <none> <none>
deployment-77567fbdbd-phmlb 1/1 Running 0 80s 10.244.2.16 k8s-node2 <none> <none>
[root@k8s-master ~]# curl 10.244.2.16
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
#修改yaml文件中镜像版本为v2
[root@k8s-master ~]# cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: deployment
name: deployment
spec:
replicas: 4
selector:
matchLabels:
app: deployment
template:
metadata:
labels:
app: deployment
spec:
containers:
- image: www.yjun.com/yjun/myapp:v2
name: myapp
#重新应用
[root@k8s-master ~]# kubectl apply -f deployment.yaml
deployment.apps/deployment configured
#版本迭代之后
[root@k8s-master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
deployment-75748c9fc-22r6d 1/1 Running 0 46s 10.244.1.22 k8s-node1 <none> <none>
deployment-75748c9fc-5npf8 1/1 Running 0 46s 10.244.2.18 k8s-node2 <none> <none>
deployment-75748c9fc-6k28j 1/1 Running 0 44s 10.244.2.19 k8s-node2 <none> <none>
deployment-75748c9fc-z5tzc 1/1 Running 0 45s 10.244.1.23 k8s-node1 <none> <none>
[root@k8s-master ~]# curl 10.244.1.23
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
3.2.2、滚动更新策略
[root@k8s-master ~]# cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: deployment
name: deployment
spec:
minReadySeconds: 5 #最小就绪时间,指定pod每隔多久更新一次
replicas: 4
strategy: #指定更新策略
rollingUpdate:
maxSurge: 1 #Pod比定义的最多多几个
maxUnavailable: 0 #Pod比定义的最少少几个
selector:
matchLabels:
app: deployment
template:
metadata:
labels:
app: deployment
spec:
containers:
- image: www.yjun.com/yjun/myapp:v2
name: myapp
[root@k8s-master ~]# kubectl apply -f deployment.yaml
3.2.3、暂停及恢复
在实际生产环境中我们做的变更可能不止一处,我们期望的触发时当我们把所有修改都搞定后一次触发,所以暂停,避免触发不必要的线上更新
#修改之前的yaml
[root@k8s-master ~]# cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: deployment
name: deployment
spec:
minReadySeconds: 5
replicas: 4
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: deployment
template:
metadata:
labels:
app: deployment
spec:
containers:
- image: www.yjun.com/yjun/myapp:v1
name: myapp
#创建pod
[root@k8s-master ~]# kubectl apply -f deployment.yaml
deployment.apps/deployment create
#验证查看
[root@k8s-master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
deployment-77567fbdbd-284n5 1/1 Running 0 6m18s 10.244.2.2 k8s-node2 <none> <none>
deployment-77567fbdbd-clnvm 1/1 Running 0 6m18s 10.244.2.3 k8s-node2 <none> <none>
deployment-77567fbdbd-dc7hk 1/1 Running 0 6m18s 10.244.1.7 k8s-node1 <none> <none>
deployment-77567fbdbd-jlrx2 1/1 Running 0 6m18s 10.244.1.6 k8s-node1 <none> <none>
[root@k8s-master ~]# curl 10.244.2.2
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
#暂停触发更新
[root@k8s-master ~]# kubectl rollout pause deployment deployment
#修改之后的yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: deployment
name: deployment
spec:
minReadySeconds: 5
replicas: 4
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: deployment
template:
metadata:
labels:
app: deployment
spec:
containers:
- image: www.yjun.com/yjun/myapp:v2
name: myapp
resources:
limit:
cpu: 0.5
memory: 200Mi
requests:
cpu: 0.5
memory: 200Mi
#更新deployment
[root@k8s-master ~]# kubectl apply -f deployment.yaml
deployment.apps/deployment configured
#查看pods(与上次无异)
[root@k8s-master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
deployment-77567fbdbd-284n5 1/1 Running 0 9m47s 10.244.2.2 k8s-node2 <none> <none>
deployment-77567fbdbd-clnvm 1/1 Running 0 9m47s 10.244.2.3 k8s-node2 <none> <none>
deployment-77567fbdbd-dc7hk 1/1 Running 0 9m47s 10.244.1.7 k8s-node1 <none> <none>
deployment-77567fbdbd-jlrx2 1/1 Running 0 9m47s 10.244.1.6 k8s-node1 <none> <none>
[root@k8s-master ~]# curl 10.244.2.2
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
#取消暂停
[root@k8s-master ~]# kubectl rollout resume deployment deployment
#第三次查看pod(创建时间和curl都不同了)
[root@k8s-master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
deployment-bc6fdd4f-d76hm 1/1 Running 0 26s 10.244.1.8 k8s-node1 <none> <none>
deployment-bc6fdd4f-hwdqn 1/1 Running 0 8s 10.244.2.5 k8s-node2 <none> <none>
deployment-bc6fdd4f-kl8t6 1/1 Running 0 14s 10.244.1.9 k8s-node1 <none> <none>
deployment-bc6fdd4f-ql6r5 1/1 Running 0 20s 10.244.2.4 k8s-node2 <none> <none>
[root@k8s-master ~]# curl 10.244.1.8
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
4、daemonset控制器
4.1、功能
DaemonSet 确保全部(或者某些)节点上运行一个 Pod 的副本。当有节点加入集群时, 也会为他们新增一个 Pod ,当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod
典型用法:
在每个节点上运行集群存储 DaemonSet,例如 glusterd、ceph。
在每个节点上运行日志收集 DaemonSet,例如 fluentd、logstash。
在每个节点上运行监控 DaemonSet,例如 Prometheus Node Exporter、zabbix agent等
一个简单的用法是在所有的节点上都启动一个 DaemonSet,将被作为每种类型的 daemon 使用
一个稍微复杂的用法是单独对每种 daemon 类型使用多个 DaemonSet,但具有不同的标志, 并且对不同硬件类型具有不同的内存、CPU 要求
4.2、示例
daemonset控制器会在每一个节点上运行一个pod任务,除了有NoSchedule等之类的不工作标记,而我们也可以使用tolerations使daemonset在NoSchedule节点上照样运行pod
#查看master节点,默认就是不调度
[root@k8s-master ~]# kubectl describe nodes k8s-master
...
Taints: node-role.kubernetes.io/control-plane:NoSchedule
#我们现在希望daemonSet控制器也在master节点上创建pod
[root@k8s-master ~]# cat daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: daemonset
spec:
selector:
matchLabels:
app: DaemonSet
template:
metadata:
labels:
app: DaemonSet
spec:
tolerations: #对于污点节点的容忍
- effect: NoSchedule
operator: Exists
containers:
- image: www.yjun.com/yjun/nginx:latest
name: nginx
#创建pod
[root@k8s-master ~]# kubectl apply -f daemonset.yaml
#查看pods详细信息
[root@k8s-master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
daemonset-nqv8j 1/1 Running 0 37s 10.244.0.4 k8s-master <none> <none>
daemonset-x5gpm 1/1 Running 0 37s 10.244.1.10 k8s-node1 <none> <none>
daemonset-z7zjg 1/1 Running 0 37s 10.244.2.6 k8s-node2 <none> <none>
#如上,daemonset在每一个节点都布置了一个pod
5、job控制器
Job,主要用于负责批量处理(一次要处理指定数量任务)短暂的一次性(每个任务仅运行一次就结束)任务
特点:
当Job创建的pod执行成功结束时,Job将记录成功结束的pod数量
当成功结束的pod达到指定的数量时,Job将完成执行
示例
[root@k8s-master ~]# cat job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: job
spec:
completions: 6 #一共要完成6个任务
parallelism: 2 #一次完成两个任务
backoffLimit: 4 #最多失败四个任务
template:
spec:
containers:
- image: www.yjun.com/yjun/perl:latest
name: job
command: ["perl","-Mbignum=bpi","-wle","print bpi(2000)"]
restartPolicy: Never
#创建pod
[root@k8s-master ~]# kubectl apply -f job.yaml
#完成过程
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
job-6fp5k 0/1 Completed 0 6s
job-bbz4f 0/1 Completed 0 6s
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
job-6fp5k 0/1 Completed 0 9s
job-bbz4f 0/1 Completed 0 9s
job-rtl8v 1/1 Running 0 3s
job-slbs8 1/1 Running 0 3s
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
job-6fp5k 0/1 Completed 0 15s
job-6ptxs 1/1 Running 0 3s
job-bbz4f 0/1 Completed 0 15s
job-j2b84 1/1 Running 0 3s
job-rtl8v 0/1 Completed 0 9s
job-slbs8 0/1 Completed 0 9s
[root@k8s-master ~]# kubectl get jobs.batch
NAME STATUS COMPLETIONS DURATION AGE
job Complete 6/6 18s 30s
重启策略
- onFailure:job会在pod出现故障的时候重启容器,fail次数不变
- Never:job会在pod出现故障的时候创建一个新的pod,并且故障pod也不会消失,也不会重启,然后fail次数+1
- Always:job会在pod出现故障的时候一直重启容器,意味着job任务会重复去执行
6、cronjob
6.1、功能
Cron Job 创建基于时间调度的 Jobs。
CronJob控制器以Job控制器资源为其管控对象,并借助它管理pod资源对象,
CronJob可以以类似于Linux操作系统的周期性任务作业计划的方式控制其运行时间点及重复运行的方式。
CronJob可以在特定的时间点(反复的)去运行job任务。
6.2、示例
#生成cronjob的yaml文件
[root@k8s-master ~]# kubectl create cronjob cronjob --image www.yjun.com/yjun/busybox --schedule='1 * * * *' --dry-run=client -o yaml > cronjob.yaml
[root@k8s-master ~]# cat cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: cronjob
spec:
schedule: "* * * * *"
jobTemplate:
metadata:
name: cronjob
spec:
template:
spec:
containers:
- image: www.yjun.com/yjun/busybox:latest
name: busybox
command: ["/bin/sh","-c","date;echo Hello from the kubernetes cluster"]
restartPolicy: Never
#创建pod
[root@k8s-master ~]# kubectl apply -f cronjob.yaml
#查看pod 每分钟一个
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
cronjob-28811968-vplnw 0/1 Completed 0 92s
cronjob-28811969-w2rws 0/1 Completed 0 32s
#查看pod的日志
[root@k8s-master ~]# kubectl logs cronjob-28811968-vplnw
Sat Oct 12 07:28:00 UTC 2024
Hello from the kubernetes cluster