目录
7.3.1.1 ClusterIP中的特殊模式hesdless
8.2.3.4 存储docker registry的认证信息
8.3.4.1 部署一台nfs共享主机并在所有k8s节点中安装nfs-utils
8.3.5.3 存储分配器NFS Client Provisioner
8.3.5.4 部署NFS Client Provisioner
一、Kubernetes简介
在部署应用程序的方式上,主要经历了三个阶段:
传统部署:互联网早期,会直接将应用程序部署在物理机上
-
优点:简单,不需要其它技术的参与
-
缺点:不能为应用程序定义资源使用边界,很难合理地分配计算资源,而且程序之间容易产生影响
虚拟化部署:可以在一台物理机上运行多个虚拟机,每个虚拟机都是独立的一个环境
-
优点:程序环境不会相互产生影响,提供了一定程度的安全性
-
缺点:增加了操作系统,浪费了部分资源
容器化部署:与虚拟化类似,但是共享了操作系统
容器化部署方式给带来很多的便利,但是也会出现一些问题,比如说:
-
一个容器故障停机了,怎么样让另外一个容器立刻启动去替补停机的容器
-
当并发访问量变大的时候,怎么样做到横向扩展容器数量
1.1 容器编排应用
为了解决这些容器编排问题,就产生了一些容器编排的软件:
-
Swarm:Docker自己的容器编排工具
-
Mesos:Apache的一个资源统一管控的工具,需要和Marathon结合使用
-
Kubernetes:Google开源的的容器编排工具
1.2 Kubernetes简介
-
在Docker 作为高级容器引擎快速发展的同时,在Google内部,容器技术已经应用了很多年
-
Borg系统运行管理着成千上万的容器应用。
-
Kubernetes项目来源于Borg,可以说是集结了Borg设计思想的精华,并且吸收了Borg系统中的经验和教训。
-
Kubernetes对计算资源进行了更高层次的抽象,通过将容器进行细致的组合,将最终的应用服务交给用户。
kubernetes的本质是一组服务器集群,它可以在集群的每个节点上运行特定的程序,来对节点中的容器进行管理。目的是实现资源管理的自动化,主要提供了如下的主要功能:
-
自我修复:一旦某一个容器崩溃,能够在1秒中左右迅速启动新的容器
-
弹性伸缩:可以根据需要,自动对集群中正在运行的容器数量进行调整
-
服务发现:服务可以通过自动发现的形式找到它所依赖的服务
-
负载均衡:如果一个服务起动了多个容器,能够自动实现请求的负载均衡
-
版本回退:如果发现新发布的程序版本有问题,可以立即回退到原来的版本
-
存储编排:可以根据容器自身的需求自动创建存储卷
1.3 k8s的设计架构
1.3.1 k8s各个组件的用途
一个kubernetes集群主要是由控制节点(master)、工作节点(node)构成,每个节点上都会安装不同的组件
1、master:集群的控制平面,负责集群的决策
-
ApiServer : 资源操作的唯一入口,接收用户输入的命令,提供认证、授权、API注册和发现等机制
-
Scheduler : 负责集群资源调度,按照预定的调度策略将Pod调度到相应的node节点上
-
ControllerManager : 负责维护集群的状态,比如程序部署安排、故障检测、自动扩展、滚动更新等
-
Etcd :负责存储集群中各种资源对象的信息
2、node:集群的数据平面,负责为容器提供运行环境
-
kubelet:负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理
-
Container runtime:负责镜像管理以及Pod和容器的真正运行(CRI)
-
kube-proxy:负责为Service提供cluster内部的服务发现和负载均衡
1.3.2 k8s各组件之间的调用关系
当我们要运行一个web服务时
-
kubernetes环境启动之后,master和node都会将自身的信息存储到etcd数据库中
-
web服务的安装请求会首先被发送到master节点的apiServer组件
-
apiServer组件会调用scheduler组件来决定到底应该把这个服务安装到哪个node节点上
在此时,它会从etcd中读取各个node节点的信息,然后按照一定的算法进行选择,并将结果告知apiServer
-
apiServer调用controller-manager去调度Node节点安装web服务
-
kubelet接收到指令后,会通知docker,然后由docker来启动一个web服务的pod
-
如果需要访问web服务,就需要通过kube-proxy来对pod产生访问的代理
1.3.3 k8s的常用名词概念
-
Master:集群控制节点,每个集群需要至少一个master节点负责集群的管控
-
Node:工作负载节点,由master分配容器到这些node工作节点上,然后node节点上的
-
Pod:kubernetes的最小控制单元,容器都是运行在pod中的,一个pod中可以有1个或者多个容器
-
Controller:控制器,通过它来实现对pod的管理,比如启动pod、停止pod、伸缩pod的数量等等
-
Service:pod对外服务的统一入口,下面可以维护者同一类的多个pod
-
Label:标签,用于对pod进行分类,同一类pod会拥有相同的标签
-
NameSpace:命名空间,用来隔离pod的运行环境
1.3.4 k8s的分层结构
-
核心层:Kubernetes最核心的功能,对外提供API构建高层的应用,对内提供插件式应用执行环境
-
应用层:部署(无状态应用、有状态应用、批处理任务、集群应用等)和路由(服务发现、DNS解析等)
-
管理层:系统度量(如基础设施、容器和网络的度量),自动化(如自动扩展、动态Provision等)以及策略管理(RBAC、Quota、PSP、NetworkPolicy等)
-
接口层:kubectl命令行工具、客户端SDK以及集群联邦
-
生态系统:在接口层之上的庞大容器集群管理调度的生态系统,可以划分为两个范畴
-
Kubernetes外部:日志、监控、配置管理、CI、CD、Workflow、FaaS、OTS应用、ChatOps等
-
Kubernetes内部:CRI、CNI、CVI、镜像仓库、Cloud Provider、集群自身的配置和管理等
二、k8s集群环境搭建
2.1 k8s中容器的管理方式
K8S 集群创建方式有3种:
centainerd:
默认情况下,K8S在创建集群时使用的方式
docker:
Docker使用的普记录最高,虽然K8S在1.24版本后已经费力了kubelet对docker的支持,但时可以借助cri-docker方式来实现集群创建
cri-o:
CRI-O的方式是Kubernetes创建容器最直接的一种方式,在创建集群的时候,需要借助于cri-o插件的方式来实现Kubernetes集群的创建。
docker 和cri-o 这两种方式要对kubelet程序的启动参数进行设置
2.2 k8s环境部署
K8S中文官网:Kubernetes
实验环境:
主机名 | IP | 角色 |
harbor | 172.25.254.150 | harbor仓库 |
k8s-master | 172.25.254.100 | Master,k8s集群控制节点 |
k8s-node1 | 172.25.254.10 | Worker,k8s集群工作节点 |
k8s-node2 | 172.25.254.20 | Worker,k8s集群工作节点 |
-
所有节点禁用selinux和防火墙
-
所有节点同步时间和解析
-
所有节点安装docker-ce
-
所有节点禁用swap,注意注释掉/etc/fstab文件中的定义
2.2.1 禁用所有swap并配置本地解析
查看开启的swap信息:
[root@k8s-master ~]# swapon -s
关闭掉:
[root@k8s-master ~]# swapoff -a
也可以用mask命令给swap锁住:
[root@k8s-master ~]# systemctl mask (跟上你的swap名称)
[root@k8s-master ~]# free -m
total used free shared buff/cache available
Mem: 1935 1379 154 15 566 555
Swap: 0 0 0
[root@k8s-master ~]# vim /etc/fstab
注释掉开机启动:
#/dev/mapper/rhel-swap none swap defaults 0 0
本地解析:
[root@k8s-master ~]# vim /etc/hosts
172.25.254.100 k8s-master
172.25.254.10 k8s-node1
172.25.254.20 k8s-node2
172.25.254.150 docker-harbor.timingding.org reg.timingding.org
2.2.2 安装docker
可以通过软件仓库的方式下载安装:
[root@k8s-master ~]# vim /etc/yum.repos.d/docker.repo
[docker]
name=docker
baseurl=https://mirrors.aliyun.com/docker-ce/linux/rhel/9/x86_64/stable/
gpgcheck=0
指定镜像下载路径:
[root@k8s-master ~]# vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://reg.timingding.org"]
}
[root@k8s-master ~]# dnf install docker-ce -y
[root@k8s-master ~]# systemctl enable --now docker
所有节点设定docker的资源管理模式为systemd,只有红帽7需要,红帽9默认的就是systemd
[root@k8s-master ~]# vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://reg.westos.org"],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
2.2.3 复制harbor仓库证书并启动docker
创建证书目录:
[root@k8s-master ~]# mkdir -p /etc/docker/certs.d/reg.timingding.org
去harbor主机用scp命令把证书传过来:
[root@docker-harbor ~]# scp /data/certs/timingding.org.crt root@172.25.254.100:/etc/docker/certs.d/reg.timingding.org/ca.crt
登录harbor仓库:
[root@k8s-master ~]# docker login reg.timingding.org
[root@k8s-master ~]# docker info ----- 查看docker信息
2.2.4 安装部署k8s的工具
[root@k8s-master ~]# vim /etc/yum.repos.d/k8s.repo
[k8s]
name=k8s
baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.30/rpm
gpgcheck=0
#安装软件
[root@k8s-master ~]# dnf install kubelet-1.30.0 kubeadm-1.30.0 kubectl-1.30.0 -y
k8s命令补齐工具:
[root@k8s-master ~]# dnf install bash-completion -y
[root@k8s-master ~]# echo "source <(kubectl completion bash)" >> ~/.bashrc
[root@k8s-master ~]# source ~/.bashrc
2.2.5 安装cri-docker
安装cri-docker和它的依赖性:
[root@k8s-master ~]# dnf install libcgroup-0.41-19.e18.x86_64.rpm cri-dockerd-0.3.14-3.e18.x86_64.rpm -y
添加网络插件下载地址:
[root@k8s-master ~]# vim /lib/systemd/system/cri-docker.service
[Service]
Type=notify
ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd:// --network-plugin=cni --pod-infra-container-image=reg.timingding.org/k8s/pause:3.9 ##### 添加网络插件名称及基础容器的镜像
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
2.2.6 在Master节点拉取k8s所需镜像
拉取镜像:
[root@k8s-master ~]# kubeadm config images pull \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.30.0 \
--cri-socket=unix:///var/run/cri-dockerd.sock
#上传镜像到harbor仓库
给镜像打标签:
[root@k8s-master ~]# docker images | awk '/google/{ print $1":"$2}' \
| awk -F "/" '{system("docker tag "$0" reg.timingding.org/k8s/"$3)}'
push上传镜像到harbor仓库:
[root@k8s-master ~]# docker images | awk '/k8s/{system("docker push "$1":"$2)}'
2.2.7 初始化集群
开始初始化一定要确保cri-docker和kubelet处于开启状态。
启动kubelet服务:
[root@k8s-master ~]# systemctl start kubelet.service
查看服务状态:
[root@k8s-master ~]# systemctl status kubelet.service
#执行初始化命令
[root@k8s-master ~]# kubeadm init --pod-network-cidr=10.244.0.0/16 \
--image-repository reg.timingding.org/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
[root@k8s-master ~]# source ~/.bash_profile
#当前节点没有就绪,因为还没有安装网络插件,容器没有运行
[root@k8s-master ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master NotReady control-plane 4m25s v1.30.0
root@k8s-master ~]# kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-647dc95897-2sgn8 0/1 Pending 0 6m13s
kube-system coredns-647dc95897-bvtxb 0/1 Pending 0 6m13s
kube-system etcd-k8s-master 1/1 Running 0 6m29s
kube-system kube-apiserver-k8s-master 1/1 Running 0 6m30s
kube-system kube-controller-manager-k8s-master 1/1 Running 0 6m29s
kube-system kube-proxy-fq85m 1/1 Running 0 6m14s
kube-system kube-scheduler-k8s-master 1/1 Running 0 6m29s
如果生成的集群token找不到了可以重新生成:
这样生成的token不是永久的,24h就会自动删除。
[root@k8s-master ~]# kubeadm token create --print-join-command
可以用kubeadm查看生成过的token:
kubeadm token list
2.2.8 安装flannel网络插件
#下载flannel的yaml部署文件
[root@k8s-master ~]# wget https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
把flannel镜像拉取出来:
[root@k8s-master ~]# docker load -i flannel-0.25.5.tag.gz
[root@k8s-master ~]# docker pull docker.io/flannel/flannel:v0.25.5
[root@k8s-master ~]# docker pull docker.io/flannel/flannel-cni-plugin:v1.5.1-flannel1
打标签并上传镜像到harbor仓库:
[root@k8s-master ~]# docker tag docker.io/flannel/flannel-cni-plugin:v1.5.1-flannel1 reg.timingding.org/flannel/flannel-cni-plugin:v1.5.1-flannel1
[root@k8s-master ~]# docker push reg.timingding.org/flannel/flannel-cni-plugin:v1.5.1-flannel1
#编辑kube-flannel.yml 修改镜像下载位置
[root@k8s-master ~]# vim kube-flannel.yml
#需要修改以下几行
[root@k8s-master ~]# grep -n image kube-flannel.yml
146: image: flannel/flannel:v0.25.5
173: image: flannel/flannel-cni-plugin:v1.5.1-flannel1
184: image: flannel/flannel:v0.25.5
#安装flannel网络插件
[root@k8s-master ~]# kubectl apply -f kube-flannel.yml
此时再查看kubectl:
master是Ready状态就部署成功:
[root@k8s-master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane 35h v1.30.0
就应该全部都是Running,如果不是全部都是Running,就是有问题,删掉重新安装:
[root@k8s-master ~]# kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-flannel kube-flannel-ds-dcchb 1/1 Running 3 (13h ago) 34h
kube-flannel kube-flannel-ds-nnzlg 1/1 Running 4 (13h ago) 34h
kube-flannel kube-flannel-ds-wczj2 1/1 Running 0 48m
kube-system coredns-6cbb5ddd55-c978j 1/1 Running 3 (13h ago) 35h
kube-system coredns-6cbb5ddd55-hbcs4 1/1 Running 3 (13h ago) 35h
kube-system etcd-k8s-master 1/1 Running 3 (13h ago) 35h
kube-system kube-apiserver-k8s-master 1/1 Running 3 (13h ago) 35h
kube-system kube-controller-manager-k8s-master 1/1 Running 3 (13h ago) 35h
kube-system kube-proxy-2rkpf 1/1 Running 3 (13h ago) 34h
kube-system kube-proxy-76q54 1/1 Running 3 (13h ago) 35h
kube-system kube-proxy-7tvhz 1/1 Running 0 48m
kube-system kube-scheduler-k8s-master 1/1 Running 3 (13h ago) 35h
2.2.9 节点扩容
跟上面masater部署差不多,不需要上传镜像,安装k8s,cri-docker。
在所有的worker节点中
1 确认部署好以下内容
2 禁用swap
3 安装:
-
kubelet-1.30.0
-
kubeadm-1.30.0
-
kubectl-1.30.0
-
docker-ce
-
cri-dockerd
4 修改cri-dockerd启动文件添加
-
--network-plugin=cni
-
--pod-infra-container-image=reg.timinglee.org/k8s/pause:3.9
5 启动服务
-
kubelet.service
-
cri-docker.service
以上信息确认完毕后即可加入集群
如果生成的集群token找不到了可以重新生成:
[root@k8s-master ~]# kubeadm token create --print-join-command
master上面生成的token集群到两个进行初始化:
[root@k8s-node1 & 2 ~]# kubeadm join 172.25.254.100:6443 --token y2gkbl.ev9wtxwc2t2p0j2t --discovery-token-ca-cert-hash sha256:9c47c30926de814a4ae59f5275d9cae00b51ab77a1cce1d48ea42ea59efe33ea --cri-socket=unix:///var/run/cri-dockerd.sock
需要所有节点都为Ready状态:
[root@k8s-master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane 35h v1.30.0
k8s-node1 Ready <none> 47m v1.30.0
k8s-node2 Ready <none> 34h v1.30.0
[root@k8s-master ~]# kubectl -n kube-flannel get pods
NAME READY STATUS RESTARTS AGE
kube-flannel-ds-dcchb 1/1 Running 3 (12h ago) 34h
kube-flannel-ds-nnzlg 1/1 Running 4 (12h ago) 33h
kube-flannel-ds-wczj2 1/1 Running 0 2m13s
OK,k8s就已经部署成功了
如果集群出问题了:
删除网络插件及配置文件:
kubectl delete -f kube-flannel.yml
重置初始化
kubeadm reset --cri-socket=unix:///var/run/cri-dockerd.sock
然后再重新初始化。
三、k8s资源管理
3.1 资源管理介绍
-
在kubernetes中,所有的内容都抽象为资源,用户需要通过操作资源来管理kubernetes。
-
kubernetes的本质上就是一个集群系统,用户可以在集群中部署各种服务
-
所谓的部署服务,其实就是在kubernetes集群中运行一个个的容器,并将指定的程序跑在容器中。
-
kubernetes的最小管理单元是pod而不是容器,只能将容器放在
Pod
中, -
kubernetes一般也不会直接管理Pod,而是通过Pod控制器来管理Pod的。
-
Pod中服务服务的访问是由kubernetes提供的
Service
资源来实现。 -
Pod中程序的数据需要持久化是由kubernetes提供的各种
存储
系统来实现
3.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
类型 | 适用环境 | 优点 | 缺点 |
命令式对象管理 | 测试 | 简单 | 只能操作活动对象,无法审计、跟踪 |
命令式对象配置 | 开发 | 可以审计、跟踪 | 项目大时,配置文件多,操作麻烦 |
声明式对象配置 | 开发 | 支持目录操作 | 意外情况下难以调试 |
3.2.1 命令式对象管理
kubectl是kubernetes集群的命令行工具,通过它能够对集群本身进行管理,并能够在集群上进行容器化应用的安装部署
kubectl命令的语法如下:
kubectl [command] [type] [name] [flags]
comand:指定要对资源执行的操作,例如create、get、delete
type:指定资源类型,比如deployment、pod、service
name:指定资源的名称,名称大小写敏感
flags:指定额外的可选参数
# 查看所有pod
kubectl get pod
# 查看某个pod
kubectl get pod pod_name
# 查看某个pod,以yaml格式展示结果
kubectl get pod pod_name -o yaml
3.2.2 资源类型
kubernetes中所有的内容都抽象为资源
kubectl api-resources
常用的类型资源:
kubectl常见命令 :
3.3 基本命令测试
声明式对象配置,生成yaml文件
[root@k8s-master yaml]# kubectl run testpod1 --image nginx --dry-run=client -o yaml > testpod1.yml
查看版本:
[root@k8s-master ~]# kubectl version
Client Version: v1.30.0
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.30.0
[root@k8s-master ~]#
查看所有资源:
[root@k8s-master ~]# kubectl api-resources
创建一个webcluster控制器,控制器中pod数量为2
[root@k8s-master ~]# kubectl create deployment webcluster --image nginx --replicas 2
deployment.apps/webcluster created
[root@k8s-master ~]#
查看控制器:
[root@k8s-master ~]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
webcluster 2/2 2 2 59s
[root@k8s-master ~]#
编辑控制器配置,里面可以修改配置
[root@k8s-master ~]# kubectl edit deployments.apps webcluster
利用补丁更改控制器配置
[root@k8s-master ~]# kubectl patch deployments.apps webcluster -p '{"spec":{"replicas":4}}'
deployment.apps/webcluster patched
[root@k8s-master ~]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
webcluster 4/4 4 4 3m56s
[root@k8s-master ~]#
#删除资源
[root@k8s-master ~]# kubectl delete deployments.apps webcluster
deployment.apps "webcluster" deleted
[root@k8s-master ~]# kubectl get deployments.apps
No resources found in default namespace.
[root@k8s-master ~]#
3.4 运行和调试命令示例
运行pod:
[root@k8s-master ~]# kubectl run ding --image timinglee/myapp:v1
pod/ding created
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
ding 1/1 Running 0 6s
[root@k8s-master ~]#
暴漏端口:
[root@k8s-master ~]# kubectl expose pod ding --port 80 --target-port 80
service/ding exposed
[root@k8s-master ~]#
[root@k8s-master ~]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ding ClusterIP 10.110.78.55 <none> 80/TCP 68s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 37h
[root@k8s-master ~]#
[root@k8s-master ~]# curl 10.110.78.55
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master ~]#
如果想对外暴漏:
[root@k8s-master ~]# kubectl edit service ding
apiVersion: v1
kind: Service
metadata:
creationTimestamp: "2024-09-04T03:55:40Z"
labels:
run: ding
name: ding
namespace: default
resourceVersion: "79784"
uid: d6cdc1b2-8d25-4163-8fd0-4d1b1c032d86
spec:
clusterIP: 10.110.78.55
clusterIPs:
- 10.110.78.55
internalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
run: ding
sessionAffinity: None
type: NodePort -------------- 改为NodePort
status:
loadBalancer: {}
[root@k8s-master ~]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ding NodePort 10.110.78.55 <none> 80:31090/TCP 48m
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 38h
[root@k8s-master ~]#
[root@k8s-master ~]# curl 172.25.254.100:31090
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master ~]#
查看资源详细信息:
[root@k8s-master ~]# kubectl describe pods ding
查看资源日志:
[root@k8s-master ~]# kubectl logs pods/ding
10.244.0.0 - - [04/Sep/2024:03:57:25 +0000] "GET / HTTP/1.1" 200 65 "-" "curl/7.76.1" "-"
10.244.0.0 - - [04/Sep/2024:04:46:29 +0000] "GET / HTTP/1.1" 200 65 "-" "curl/7.76.1" "-"
[root@k8s-master ~]#
运行交互模式的pod:
[root@k8s-master ~]# kubectl run -it testpod --image busyboxplus
If you don't see a command prompt, try pressing enter.
/ #
Ctrl+pq退出不停止
想要再进去:
[root@k8s-master ~]# kubectl attach pods/testpod -it
If you don't see a command prompt, try pressing enter.
/ #
复制文件到pod中
[root@k8s-master ~]# kubectl cp /etc/passwd ding:/
[root@k8s-master ~]#
[root@k8s-master ~]# kubectl exec pods/ding -c ding -it -- /bin/sh
/ # ls
bin etc lib mnt proc run srv tmp var
dev home media passwd root sbin sys usr
/ #
3.5 高级命令示例
利用命令生成yaml模板文件:
[root@k8s-master ~]# kubectl run ding --image timinglee/myapp:v1 --dry-run=client -o yaml > ding.yml
利用命令生成控制器:
[root@k8s-master ~]# kubectl create deployment ding --image timinglee/myapp:v1 --dry-run=client -o yaml > deployment-ding.yml
如何运行:
[root@k8s-master ~]# kubectl apply -f deployment-ding.yml
deployment.apps/ding created
[root@k8s-master ~]# kubectl get deployments.apps ding
NAME READY UP-TO-DATE AVAILABLE AGE
ding 2/2 2 2 13s
[root@k8s-master ~]#
如何删除:
[root@k8s-master ~]# kubectl delete -f deployment-ding.yml
deployment.apps "ding" deleted
[root@k8s-master ~]# kubectl get deployments.apps
No resources found in default namespace.
[root@k8s-master ~]#
管理资源的标签:
[root@k8s-master ~]# kubectl apply -f deployment-ding.yml
deployment.apps/ding created
[root@k8s-master ~]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
ding-5799974786-2fz8p 1/1 Running 0 18s app=ding,pod-template-hash=5799974786
ding-5799974786-bdm88 1/1 Running 0 18s app=ding,pod-template-hash=5799974786
[root@k8s-master ~]# kubectl label pods ding-5799974786-2fz8p app=timingding --overwrite
pod/ding-5799974786-2fz8p labeled
[root@k8s-master ~]#
资源发现名为ding的pod少了一个,会重新建议一个
[root@k8s-master ~]# kubectl label pods ding-5799974786-2fz8p app=timingding --overwrite
pod/ding-5799974786-2fz8p labeled
[root@k8s-master ~]# kubectl label pods ding-5799974786-2fz8p app=ding --overwrite
pod/ding-5799974786-2fz8p labeled
[root@k8s-master ~]#
资源会发现名为ding的多一个,然后就会关掉一个
删除标签:
[root@k8s-master ~]# kubectl label pods ding-5799974786-2fz8p app-
pod/ding-5799974786-2fz8p unlabeled
[root@k8s-master ~]#
四、什么是pod以及pod的管理方式
-
Pod是可以创建和管理Kubernetes计算的最小可部署单元
-
一个Pod代表着集群中运行的一个进程,每个pod都有一个唯一的ip。
-
一个pod类似一个豌豆荚,包含一个或多个容器(通常是docker)
-
多个容器间共享IPC、Network和UTC namespace。
4.1 创建自主式pod
优点:
灵活性高:
-
可以精确控制 Pod 的各种配置参数,包括容器的镜像、资源限制、环境变量、命令和参数等,满足特定的应用需求。
学习和调试方便:
-
对于学习 Kubernetes 的原理和机制非常有帮助,通过手动创建 Pod 可以深入了解 Pod 的结构和配置方式。在调试问题时,可以更直接地观察和调整 Pod 的设置。
适用于特殊场景:
-
在一些特殊情况下,如进行一次性任务、快速验证概念或在资源受限的环境中进行特定配置时,手动创建 Pod 可能是一种有效的方式。
缺点:
管理复杂:
-
如果需要管理大量的 Pod,手动创建和维护会变得非常繁琐和耗时。难以实现自动化的扩缩容、故障恢复等操作。
缺乏高级功能:
-
无法自动享受 Kubernetes 提供的高级功能,如自动部署、滚动更新、服务发现等。这可能导致应用的部署和管理效率低下。
可维护性差:
-
手动创建的 Pod 在更新应用版本或修改配置时需要手动干预,容易出现错误,并且难以保证一致性。相比之下,通过声明式配置或使用 Kubernetes 的部署工具可以更方便地进行应用的维护和更新。
#查看所有pods
[root@k8s-master ~]# kubectl get pods
No resources found in default namespace.
#建立一个名为timingding的pod
[root@k8s-master ~]# kubectl run ding --image nginx
pod/ding created
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
ding 1/1 Running 0 6s
4.2 利用控制器管理pod
高可用性和可靠性:
-
自动故障恢复:如果一个 Pod 失败或被删除,控制器会自动创建新的 Pod 来维持期望的副本数量。确保应用始终处于可用状态,减少因单个 Pod 故障导致的服务中断。
-
健康检查和自愈:可以配置控制器对 Pod 进行健康检查(如存活探针和就绪探针)。如果 Pod 不健康,控制器会采取适当的行动,如重启 Pod 或删除并重新创建它,以保证应用的正常运行。
可扩展性:
-
轻松扩缩容:可以通过简单的命令或配置更改来增加或减少 Pod 的数量,以满足不同的工作负载需求。例如,在高流量期间可以快速扩展以处理更多请求,在低流量期间可以缩容以节省资源。
-
水平自动扩缩容(HPA):可以基于自定义指标(如 CPU 利用率、内存使用情况或应用特定的指标)自动调整 Pod 的数量,实现动态的资源分配和成本优化。
版本管理和更新:
-
滚动更新:对于 Deployment 等控制器,可以执行滚动更新来逐步替换旧版本的 Pod 为新版本,确保应用在更新过程中始终保持可用。可以控制更新的速率和策略,以减少对用户的影ls响。
-
回滚:如果更新出现问题,可以轻松回滚到上一个稳定版本,保证应用的稳定性和可靠性。
声明式配置:
-
简洁的配置方式:使用 YAML 或 JSON 格式的声明式配置文件来定义应用的部署需求。这种方式使得配置易于理解、维护和版本控制,同时也方便团队协作。
-
期望状态管理:只需要定义应用的期望状态(如副本数量、容器镜像等),控制器会自动调整实际状态与期望状态保持一致。无需手动管理每个 Pod 的创建和删除,提高了管理效率。
服务发现和负载均衡:
-
自动注册和发现:Kubernetes 中的服务(Service)可以自动发现由控制器管理的 Pod,并将流量路由到它们。这使得应用的服务发现和负载均衡变得简单和可靠,无需手动配置负载均衡器。
-
流量分发:可以根据不同的策略(如轮询、随机等)将请求分发到不同的 Pod,提高应用的性能和可用性。
多环境一致性:
-
一致的部署方式:在不同的环境(如开发、测试、生产)中,可以使用相同的控制器和配置来部署应用,确保应用在不同环境中的行为一致。这有助于减少部署差异和错误,提高开发和运维效率。
示例:
利用yaml文件创建:
[root@k8s-master ~]# vim deployment-ding.yml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: ding
name: ding
spec:
replicas: 2
selector:
matchLabels:
app: ding
strategy: {}
template:
metadata:
labels:
app: ding
spec:
containers:
- image: timinglee/myapp:v1
name: myapp
[root@k8s-master ~]# kubectl apply -f deployment-ding.yml
deployment.apps/ding created
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
ding-5799974786-8w2xw 1/1 Running 0 6s
ding-5799974786-nzpj2 1/1 Running 0 6s
暴漏端口:
[root@k8s-master ~]# kubectl expose deployment ding --port 80 --target-port 80
service/ding exposed
[root@k8s-master ~]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ding ClusterIP 10.111.191.171 <none> 80/TCP 13s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 44h
查看暴漏端口:
[root@k8s-master ~]# kubectl describe service ding
Name: ding
Namespace: default
Labels: app=ding
Annotations: <none>
Selector: app=ding
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.111.191.171
IPs: 10.111.191.171
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.1.30:80,10.244.4.29:80 ---- 可以做负载均衡
Session Affinity: None
Events: <none>
查看IP:
[root@k8s-master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ding-5799974786-8w2xw 1/1 Running 0 8m1s 10.244.4.29 k8s-node2 <none> <none>
ding-5799974786-nzpj2 1/1 Running 0 8m1s 10.244.1.30 k8s-node1 <none> <none>
[root@k8s-master ~]#
如果这里访问不到80端口,有可能是网络插件挂了,重新删了启动再试
kubectl get pods -n kube-system
查看信息:
[root@k8s-master ~]# curl 10.111.191.171/hostname.html
ding-5799974786-r8krh
[root@k8s-master ~]# curl 10.111.191.171/hostname.html
ding-5799974786-r8krh
[root@k8s-master ~]# curl 10.111.191.171/hostname.html
ding-5799974786-r8krh
[root@k8s-master ~]# curl 10.111.191.171/hostname.html
ding-5799974786-2mrzz
[root@k8s-master ~]# curl 10.111.191.171/hostname.html
ding-5799974786-2mrzz
[root@k8s-master ~]# curl 10.111.191.171/hostname.html
ding-5799974786-r8krh
为ding扩容:
[root@k8s-master ~]# kubectl scale deployment ding --replicas 4
deployment.apps/ding scaled
[root@k8s-master ~]#
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
ding-5799974786-2mrzz 1/1 Running 0 8m28s
ding-5799974786-2tchv 1/1 Running 0 102s
ding-5799974786-2zxq4 1/1 Running 0 102s
ding-5799974786-r8krh 1/1 Running 0 8m28s
为ding缩容:
[root@k8s-master ~]# kubectl scale deployment ding --replicas 2
deployment.apps/ding scaled
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
ding-5799974786-2mrzz 1/1 Running 0 10m
ding-5799974786-r8krh 1/1 Running 0 10m
[root@k8s-master ~]#
###########################################################################################################
手动创建:
[root@k8s-master ~]# kubectl create deployment ding --image timinglee/myapp:v1 --replicas 2
deployment.apps/ding created
[root@k8s-master ~]#
[root@k8s-master ~]#
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
ding-5799974786-5stbs 1/1 Running 0 7s
ding-5799974786-hk8cn 1/1 Running 0 7s
[root@k8s-master ~]# kubectl expose deployment ding --port 80 --target-port 80
service/ding exposed
[root@k8s-master ~]# kubectl get service ding
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ding ClusterIP 10.109.3.193 <none> 80/TCP 7s
[root@k8s-master ~]# kubectl describe service ding
Name: ding
Namespace: default
Labels: app=ding
Annotations: <none>
Selector: app=ding
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.109.3.193
IPs: 10.109.3.193
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.1.39:80,10.244.4.40:80
Session Affinity: None
Events: <none>
[root@k8s-master ~]# curl 10.109.3.193
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master ~]# curl 10.109.3.193/hostname.html
ding-5799974786-5stbs
[root@k8s-master ~]# curl 10.109.3.193/hostname.html
ding-5799974786-hk8cn
[root@k8s-master ~]#
4.3 应用版本的更新
利用控制器建立pod:
[root@k8s-master ~]# kubectl create deployment ding --image timinglee/myapp:v1 --replicas 2
deployment.apps/ding created
[root@k8s-master ~]#
暴漏端口:
[root@k8s-master ~]# kubectl expose deployment ding --port 80 --target-port 80
service/ding exposed
访问服务:
[root@k8s-master ~]# curl 10.109.3.193
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master ~]# curl 10.109.3.193
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master ~]#
查看历史版本:
[root@k8s-master ~]# kubectl rollout history deployment ding
deployment.apps/ding
REVISION CHANGE-CAUSE
1 <none>
[root@k8s-master ~]#
更新控制器镜像版本:
[root@k8s-master ~]# kubectl set image deployments/ding myapp=timinglee/myapp:v2
deployment.apps/ding image updated
再次查看版本:
[root@k8s-master ~]# kubectl rollout history deployment ding
deployment.apps/ding
REVISION CHANGE-CAUSE
1 <none>
2 <none>
[root@k8s-master ~]#
访问测试内容:
[root@k8s-master ~]# curl 10.109.3.193
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
版本回滚:
[root@k8s-master ~]# kubectl rollout undo deployment ding --to-revision 1
再次访问:
[root@k8s-master ~]# curl 10.109.3.193
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master ~]# curl 10.109.3.193
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master ~]# curl 10.109.3.193
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master ~]#
4.4 利用yaml文件部署应用
4.4.1 用yaml文件部署应用有以下优点
声明式配置:
-
清晰表达期望状态:以声明式的方式描述应用的部署需求,包括副本数量、容器配置、网络设置等。这使得配置易于理解和维护,并且可以方便地查看应用的预期状态。
-
可重复性和版本控制:配置文件可以被版本控制,确保在不同环境中的部署一致性。可以轻松回滚到以前的版本或在不同环境中重复使用相同的配置。
-
团队协作:便于团队成员之间共享和协作,大家可以对配置文件进行审查和修改,提高部署的可靠性和稳定性。
灵活性和可扩展性:
-
丰富的配置选项:可以通过 YAML 文件详细地配置各种 Kubernetes 资源,如 Deployment、Service、ConfigMap、Secret 等。可以根据应用的特定需求进行高度定制化。
-
组合和扩展:可以将多个资源的配置组合在一个或多个 YAML 文件中,实现复杂的应用部署架构。同时,可以轻松地添加新的资源或修改现有资源以满足不断变化的需求。
与工具集成:
-
与 CI/CD 流程集成:可以将 YAML 配置文件与持续集成和持续部署(CI/CD)工具集成,实现自动化的应用部署。例如,可以在代码提交后自动触发部署流程,使用配置文件来部署应用到不同的环境。
-
命令行工具支持:Kubernetes 的命令行工具
kubectl
对 YAML 配置文件有很好的支持,可以方便地应用、更新和删除配置。同时,还可以使用其他工具来验证和分析 YAML 配置文件,确保其正确性和安全性。
4.4.2 资源清单
参数名称 | 类型 | 参数说明 |
version | String | 这里是指的是K8S API的版本,目前基本上是v1,可以用kubectl api-versions命令查询 |
kind | String | 这里指的是yaml文件定义的资源类型和角色,比如:Pod |
metadata | Object | 元数据对象,固定值就写metadata |
metadata.name | String | 元数据对象的名字,这里由我们编写,比如命名Pod的名字 |
metadata.namespace | String | 元数据对象的命名空间,由我们自身定义 |
Spec | Object | 详细定义对象,固定值就写Spec |
spec.containers[] | list | 这里是Spec对象的容器列表定义,是个列表 |
spec.containers[].name | String | 这里定义容器的名字 |
spec.containers[].image | string | 这里定义要用到的镜像名称 |
spec.containers[].imagePullPolicy | String | 定义镜像拉取策略,有三个值可选: (1) Always: 每次都尝试重新拉取镜像 (2) IfNotPresent:如果本地有镜像就使用本地镜像 (3) )Never:表示仅使用本地镜像 |
spec.containers[].command[] | list | 指定容器运行时启动的命令,若未指定则运行容器打包时指定的命令 |
spec.containers[].args[] | list | 指定容器运行参数,可以指定多个 |
spec.containers[].workingDir | String | 指定容器工作目录 |
spec.containers[].volumeMounts[] | list | 指定容器内部的存储卷配置 |
spec.containers[].volumeMounts[].name | String | 指定可以被容器挂载的存储卷的名称 |
spec.containers[].volumeMounts[].mountPath | String | 指定可以被容器挂载的存储卷的路径 |
spec.containers[].volumeMounts[].readOnly | String | 设置存储卷路径的读写模式,ture或false,默认为读写模式 |
spec.containers[].ports[] | list | 指定容器需要用到的端口列表 |
spec.containers[].ports[].name | String | 指定端口名称 |
spec.containers[].ports[].containerPort | String | 指定容器需要监听的端口号 |
spec.containers[] ports[].hostPort | String | 指定容器所在主机需要监听的端口号,默认跟上面containerPort相同,注意设置了hostPort同一台主机无法启动该容器的相同副本(因为主机的端口号不能相同,这样会冲突) |
spec.containers[].ports[].protocol | String | 指定端口协议,支持TCP和UDP,默认值为 TCP |
spec.containers[].env[] | list | 指定容器运行前需设置的环境变量列表 |
spec.containers[].env[].name | String | 指定环境变量名称 |
spec.containers[].env[].value | String | 指定环境变量值 |
spec.containers[].resources | Object | 指定资源限制和资源请求的值(这里开始就是设置容器的资源上限) |
spec.containers[].resources.limits | Object | 指定设置容器运行时资源的运行上限 |
spec.containers[].resources.limits.cpu | String | 指定CPU的限制,单位为核心数,1=1000m |
spec.containers[].resources.limits.memory | String | 指定MEM内存的限制,单位为MIB、GiB |
spec.containers[].resources.requests | Object | 指定容器启动和调度时的限制设置 |
spec.containers[].resources.requests.cpu | String | CPU请求,单位为core数,容器启动时初始化可用数量 |
spec.containers[].resources.requests.memory | String | 内存请求,单位为MIB、GIB,容器启动的初始化可用数量 |
spec.restartPolicy | string | 定义Pod的重启策略,默认值为Always. (1)Always: Pod-旦终止运行,无论容器是如何 终止的,kubelet服务都将重启它 (2)OnFailure: 只有Pod以非零退出码终止时,kubelet才会重启该容器。如果容器正常结束(退出码为0),则kubelet将不会重启它 (3) Never: Pod终止后,kubelet将退出码报告给Master,不会重启该 |
spec.nodeSelector | Object | 定义Node的Label过滤标签,以key:value格式指定 |
spec.imagePullSecrets | Object | 定义pull镜像时使用secret名称,以name:secretkey格式指定 |
spec.hostNetwork | Boolean</ |