容器
当我们创建一个容器的时候,docker daemon 并不能直接帮我们创建了,而是请求containerd 来创建容器,containerd 收到请求后,也不会直接去操作容器而是去创建一个叫 containerd-shim的进程,让这个进程去操作容器,我们指定容器进程需要父进程来做状态收集 维持stdin 等fd打开等工作,假如这个父进程就是 containerd,那如果containerd 挂掉的话,整个宿主机所有的容器都退出了,而引入 containerd-shim 这个垫片就可以规避这个问题了。
然后创建容器需要做些 namespaces 和 cgrous的配置,以及挂载root 文件系统操作
真正启动容器是通过 containerd-shim 去调用 runc 来启动容器的,runc 在容器启动后会自动退出 containerd-shim 则称为容器进程的父进程,负责搜集容器进程的状态,上报给containerd,并在容器中pid 为1进程退出后接管容器中的子进程进行清理,确保不会出现僵尸进程。
CRI 定义主要包含两个gRPC服务,ImageService 和 RuntimeService , ImageSerivce 主要包含拉取镜像 查看和删除镜像,RuntimeSerivce 则是用来管理Pod和容器的生命周期,以及与容器交互的调用(exec/attach/port-forward)等操作,可以通过kubelet 中的标志 --container-runtime-endpoint 和images-service-endpoint 来配置这两个服务的套接字。
containerd 基本使用
安装
Centos
dnf install libseccomp libseccomp-devel -y
Ubuntu
apt install libseccomp2 -y
关于 containerd-1.5.7-linux-amd64.tar.gz 仅仅只有containerd 相关的服务
wget https://github.com/containerd/containerd/releases/download/v1.5.7/cri-containerd-cni-1.5.7-linux-amd64.tar.gz
tar xf cri-containerd-cni-1.5.7-linux-amd64.tar.gz -C /
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
systemctl enable containerd --now
ctr 就是containerd cli 工具 = docker cli
查看版本
ctr version
crictl 用于 k8s 管理pod 的工具
查看插件列表
ctr plugin ls
containerd 持久化保存的数据
root = "/var/lib/containerd"
拉取镜像
ctr image pull docker.io/library/nginx:latest
查看镜像
ctr image ls
ctr image ls -q # 只打印镜像名称
将镜像内容挂载到宿主机
mkdir /data/ctrdemo -p
ctr image mount docker.io/library/nginx:latest /data/ctrdemo/
#取消挂载
ctr image unmount /data/ctrdemo/
创建容器
create 只是创建声明并不是运行时候的状态
containerd 与docker 有不一样的地方就是task 的概念
需要运行用到task 用于配置 网卡 监控
ctr c create docker.io/library/nginx:latest nginx
查看的容器
ctr c ls
查看容器的信息
ctr c info nginx
删除容器
ctr c rm nginx
启动容器完整启动流程
ctr c create docker.io/library/nginx:latest nginx
ctr task start -d nginx
查看容器状态
ctr task ls
进入正在运行的容器
ctr task exec --exec-id=1 -t nginx /bin/sh
暂停容器
ctr task pause nginx
恢复容器
ctr task resume nginx
docker 没有 stop 这一概念只有kill
查看容器详细信息
ctr task metrics nginx
ctr task ps nginx # ctr task id 为宿主机进程id
创建命名空间
注:containerd namespace 跟k8s中的namespace 不是一个
ctr ns create test
ctr ns ls
根据命名空间拉取镜像
ctr -n test i pull docker.io/library/nginx:alpine
使用nerdctl 构建镜像需要
https://github.com/moby/buildkit/releases/download/v0.11.6/buildkit-v0.11.6.linux-amd64.tar.gz
nerdctl
更友好的 containerd cli 工具
安装nerdctl 工具
wget https://github.com/containerd/nerdctl/releases/download/v0.12.1/nerdctl-0.12.1-linux-amd64.tar.gz
tar xf nerdctl-0.12.1-linux-amd64.tar.gz
mv nerdctl /usr/local/bin/
运行容器
nerdctl run -d -p 80:80 --name nginx docker.io/library/nginx:latest
关于docker 构建
docker build
命令实际上是将构建过程分为两个步骤。第一步是在本地构建Docker镜像,这一步是通过Docker daemon(dockerd
)执行的。docker build
会将Dockerfile
解析为一系列指令,然后将它们发送到Docker daemon以执行构建操作。第二步是将构建好的Docker镜像保存到本地或推送到远程Docker镜像仓库。这一步是通过
docker push
命令实现的,它将构建好的镜像推送到指定的远程仓库中。但是,docker push
命令并不会执行构建过程,它只会将本地构建好的镜像上传到远程仓库。因此,您可以将
docker build
命令看作是客户端,而dockerd
是服务端。客户端向服务端发送构建请求,并将Dockerfile解析为一系列指令。服务端执行这些指令,构建镜像,并将构建好的镜像返回给客户端,以便保存到本地或上传到远程仓库。这种模式类似于C/S结构,客户端和服务端通过网络进行通信。同样 nerdctl 也是需要后端
安装构建nerdctl 构建后段
wget https://github.com/moby/buildkit/releases/download/v0.11.6/buildkit-v0.11.6.linux-amd64.tar.gz
tar xf buildkit-v0.11.6.linux-amd64.tar.gz
cd bin/
mv buildkitd buildctl buildkit-runc /usr/local/bin/
[Unit]
Description=Buildkit # 服务的描述信息,用于简要说明服务的用途。
[Service]
ExecStart=/usr/local/bin/buildkitd --oci-worker=false --containerd-worker=true # 服务启动命令,指定要执行的二进制文件和参数。
[Install]
WantedBy=multi-user.target # 指定系统启动时应启动的服务目标,multi-user.target 表示多用户模式下启动该服务。
sudo systemctl daemon-reload # 加载最新的systemd服务配置文件
sudo systemctl start buildkitd # 启动buildkitd服务
sudo systemctl enable buildkitd # 设置buildkitd服务在系统启动时自动启动
nerdctl build -t nginx:nerd -f Dockerfile .
容器底层
Cgroup
Linux control group,限制一组进程使用的资源(CPU 内存等)上线,是Containerd容器技术的核心实现原理之一
task 在cgroup中,可以理解是一个进程,但是这个进程和一般意义的系统进程不太一样,实际上是进程id和线程id
hierarchy: cgroup 的层级组织关系,cgroup以树形层级组织,每个cgroup子节点默认继承其父cgroup节点的配置属性,这样hierarchy在初始化会有 root cgroup
subsystem:子系统,具有具体的资源配置,如cpu使用内存占用等,subsystem附加到 hierarchy 上后可用
Cgroup支持子系统包含以下几类,即为每种可以控制的资源定义了一个子系统:
Cpuset 为 cgroup 中的进程分配单独的CPU节点,即可以绑定到特定CPU
CPU限制Cgroup 中进程使用CPU使用份额
cpuacct 统计cgroup 中进程cpu 使用情况
memory 限制cgroup中进程的内存使用,并能报告内存使用情况
devices 控制cgroup中进程能访问哪些文件设备(设备文件的创建、读写)
freezer:挂起或恢复 cgroup中的task
net_cls 可以标记 cgroups 中的进程网络数据包,然后可以使用tc模块(traffic contro)对数据包进行控制
Blkio 限制cgroup中的块设备IO
perf_event:监控cgroup中进程的perf时间对于性能调优
hugetlb: hugetlb的资源功能
pids:限制cgroup中可以创建进程数
cgroup 可以控制的资源有:CPU、内存、IO文件设备等。Cgroups 以下几个特点:
Cgroups 的API 以一个文件系统(/sys/fs/cgroup/)的实现方式,用户的程序可以通过系统实现Cgroup的组建管理 (文件挂载的方式实现的)
Cgroup 的组建管理操作单元颗粒细度可以到线程级别,用户可以创建和销毁Cgroups,从而实现资源载分配和在利用
资源管理功能是以子系统(cpu,cpuset这些)的方式实现,接口统一子任务创建之初与其父任务处于同一个Cgroups 的控制组
查看Linux 支持cgroup 子系统信息
cat /proc/cgroups
列出已经挂载的cgroup
mount --type cgroup
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,rdma)
Cgroup限制CPU
生成python测试脚本
vim cgroup.py
while True:
pass
创建 一个 python.test
的 cpu 的 cgroup
mkdir /sys/fs/cgroup/cpu/python.test
cd /sys/fs/cgroup/cpu/python.test
echo 98235 > tasks
echo 10000 > cpu.cfs_quota_us
使用 echo 命令将进程的 PID(例如,PID 98235)添加到 tasks 文件中,这样这个进程就属于 "python.test" Cgroup。最后,使用 echo 命令将 CPU 时间限制为 10000 微秒/秒(即 10% CPU),通过修改 cpu.cfs_quota_us 文件实现。
这个命令序列可以用于限制在 "python.test" Cgroup 中运行的进程的 CPU 使用率,确保这些进程不会占用过多的 CPU 资源,从而提高系统的稳定性和性能。需要注意的是,这里只是对单个进程进行了限制,如果有多个进程属于同一个 Cgroup,需要对整个 Cgroup 进行 CPU 使用限制才能有效控制资源的使用。
删除手动创建的Cgroup
直接删除手动创建的 Cgroup 资源组是不行的,需要借助 libcgroup 工具进行删除
安装 libcgroup
dnf -y install libcgroup libcgroup-tools
删除手动创建的cgroup
cgdelete cpu:python.test
Namespace
命名空间,是Linux为我们提供用于隔离进程树、网络接口、挂载点以及进程通信等资源的方法
Cgroup namespace 是 Linux 内核中的一种命名空间(namespace),它提供了一种隔离 cgroup 层次结构的机制,使得每个进程都可以拥有自己的 cgroup 层次结构,从而实现对进程资源的隔离和限制。
在 Cgroup namespace 中,每个进程都有自己的根 cgroup,进程只能访问和管理它自己的 cgroup 层次结构,无法访问和管理其他进程的 cgroup 层次结构。这种隔离机制可以防止进程之间相互干扰,保证资源的独立性和安全性。
Linux 7种命名空间
Mount namespace:用于隔离文件系统挂载点,每个 mount namespace 都有自己的根文件系统和挂载点列表。
UTS namespace:用于隔离主机名和域名,每个 UTS namespace 都有自己的主机名和域名。
IPC namespace:用于隔离 System V IPC 和 POSIX 消息队列等进程间通信机制。
PID namespace:用于隔离进程 ID,每个 PID namespace 都有自己的进程 ID。
Network namespace:用于隔离网络栈,每个 network namespace 都有自己的网络设备、IP 地址、路由表和防火墙等配置。
User namespace:用于隔离用户和用户组 ID,每个 user namespace 都有自己的用户和用户组 ID,从而实现用户和权限的隔离。
Cgroup namespace:用于隔离 cgroup 控制组层次结构,每个 cgroup namespace 都有自己的 cgroup 层次结构,从而实现资源的隔离和限制。
查看命名空间
lsns
容器的本质也就是宿主机上面的一个进程,是有cgroup 跟 namespace 进行资源限制
Kubernetes
master 主节点
etc 负责持久化存储
API Server 整个集群通讯
scheduler负责集群调度
controller manager 负责整个集群维护状态
bubectl 是 kubernetes 的集群工具命令行客户端工具集,通过该命令对API server进行操作
controller manager 包括
replication Controler
node controller
ResourceQuota Controller
Namespace Controller
ServiceAccount Controller
Token Controller
Service Controller
Endpoint Controller
kube-proxy
Kube-proxy 解决同一宿主机相同服务端口冲突,还提供Service 转发服务端口对外提供服务的能力
Pod
是一组紧密关联的容器结合,共享PID、IPC、Network、UTS namespace,是Kubernetes 调度的基本单位。Pod的设计的理念是多个容器在一个Pod中共享网络文件和文件系统,可以通过进程通信和文件共享这种简单高效的方式完成服务。我们知道容的本质是进程,那么Pod实际上是进程组了,只是这一组进程作为一个整体来进行调度。
Label 标签
是识别Kubernetes 对象标签,以K/V方式附加到对象上(最长不能超过63字节。value可以为空,也可以不超过253的字节字符串),Label不提供唯一性,并且很多对象都是用相同的Label 标志具体的应用,Label定义好后其它对象可以使用 Label Selector 来选择一组相同的Label 对象
Label selector 支持一下几种方式:
等式: app=nginx 和 env!=production
集合: env in (production,qa)
多个Label 为AND 关系,如app=nginx,env=test
Namespace
命名空间,是对一组资源和对象的抽象集合,可以用来将系统内部对象划分成不同项目组或者用户组,常见的pods services deployments 等都属于一个NameSpace的(默认是default)
Node、PersitenVolumes等资源不属于任何Namespace 是全局的。
注:该Namespace 不是Linux Namespace 二者没有任何关系。只是Kubernetes划分不同的工作空间的一个逻辑单位。
Deployment
用来确保任意时间都有指定数量的Pod副本在运行。如果为某个Pod创建了Deployment并指定3个副本,他会创建3个Pod,并持续监控他们。如果某个Pod无响应,那么Deployment会替换掉。始终保持总数为3
当无响应Pod恢复后,就为4 那么deployment会终止其中一个保持总数为3.如果在运行中将副本改成5.deploy会立刻启动新的两个Pod,保证总数为5。持回滚和滚动升级。
deployment 可以创建滚动更新,创建副本不是deployment 所做的事情。
创建deployment需要指定:
Pod 模版: 用来创建Pod副本的模版 Label 标签:Deployment 需要监控的Pod标签
Service
需要将Pod暴露出去就需要Service资源对象,Service是应用服务的抽象,通过Labels为应用提供负载均衡到这些Endpoints上。
每个Service 都会自动分配一个cluster IP (仅在集群内部可以访问的虚拟地址)和DNS名,其它容器可以通过DNS来访问服务,而不需要了解容器运行。
环境准备
单个主部署,每个节点需要添加host 集群所对应的host 信息
安装containerd
加载模块
modprobe overlay
modprobe br_netfilter
vi /etc/modules-load.d/modules.conf
overlay
br_netfilter
内核
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward=1
安装依赖
dnf -y erase podman buildah
dnf -y install iproute-tc
安装 kubelet kubeadm kubectl
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF
安装最新
dnf install -y kubelet kubeadm kubectl
安装1.24.13
dnf install -y kubelet-1.24.13-0 kubeadm-1.24.13-0 kubectl-1.24.13-0
安装 1.22.2
dnf install -y kubelet-1.22.2 kubeadm-1.22.2 kubectl-1.22.2
systemctl enable --now kubelet
初始化
生成init 文件
kubeadm config print init-defaults --component-configs KubeletConfiguration > kubeadm.yaml
kubeadm 信息
apiVersion: kubeadm.k8s.io/v1beta3
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 10.0.0.101
bindPort: 6443
nodeRegistration:
criSocket: /var/run/containerd/containerd.sock
imagePullPolicy: IfNotPresent
name: k8s-master-01
taints:
- effect: "NoSchedule"
key: "node-role.kubernetes.io/master"
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: k8s.gcr.io
kind: ClusterConfiguration
kubernetesVersion: 1.22.2
networking:
dnsDomain: cluster.local
serviceSubnet: 10.96.0.0/12
podSubnet: 10.244.0.0/16
scheduler: {}
---
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
anonymous:
enabled: false
webhook:
cacheTTL: 0s
enabled: true
x509:
clientCAFile: /etc/kubernetes/pki/ca.crt
authorization:
mode: Webhook
webhook:
cacheAuthorizedTTL: 0s
cacheUnauthorizedTTL: 0s
cgroupDriver: systemd
clusterDNS:
- 10.96.0.10
clusterDomain: cluster.local
cpuManagerReconcilePeriod: 0s
evictionPressureTransitionPeriod: 0s
fileCheckFrequency: 0s
healthzBindAddress: 127.0.0.1
healthzPort: 10248
httpCheckFrequency: 0s
imageMinimumGCAge: 0s
kind: KubeletConfiguration
logging: {}
memorySwap: {}
nodeStatusReportFrequency: 0s
nodeStatusUpdateFrequency: 0s
rotateCertificates: true
runtimeRequestTimeout: 0s
shutdownGracePeriod: 0s
shutdownGracePeriodCriticalPods: 0s
staticPodPath: /etc/kubernetes/manifests
streamingConnectionIdleTimeout: 0s
syncFrequency: 0s
volumeStatsAggPeriod: 0s
查看所需的镜像
kubeadm config images list
kubeadm init --config kubeadm.yaml --v 5
安装网络插件
安装网络插件
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
查看网络插件
kubectl get pods -n kube-flannel
移除containerd网络插件
mv /etc/cni/net.d/10-containerd-net.conflist /etc/cni/net.d/10-containerd-net.conflist.bak
重建 kube-flannel 插件
所有节点都要执行
kubectl delete pod coredns-78fcd69978-8zpdt coredns-78fcd69978-rhkbc -n kube-system
故障问题:
status为:ContainerCreating
kubectl get pod -n kube-system -o wide
NAME READY STATUS RESTARTS AGE IP NODE
coredns-78fcd69978-vhbtv 0/1 ContainerCreating 0 4m41s <none> k8s-slave-01
coredns-78fcd69978-zxkct 0/1 ContainerCreating 0 4m41s <none> k8s-slave-01
查看pod 详细日志
kubectl describe pod -n kube-system coredns-78fcd69978-vhbtv
输出:
Warning FailedCreatePodSandBox 27s (x17 over 4m39s) kubelet (combined from similar events): Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox "f9599e590f5c35685920646f5ebfc0397529470e991215d55b0154dab6231e65": failed to delegate add: failed to set bridge addr: "cni0" already has an IP address different from 10.244.1.1/24
在对应服务pod 节点上执行
ip link delete cni0
ip link delete flannel.1
systemctl restart kubelet
重新获取token join
kubeadm token create --print-join-command
资源清单
查看示例
kubectl explain deployment
查看示例
kubectl explain deployment.metadata
Pod 基本原理
生命周期
init container
Main container --> post start hook --> liveness probe readiness probe --> pre stop hook
CGroup CPU资源单位换算
1CPU = 1000 millicpu (1 Core = 1000m)
0.5CPU = 500 millicpu (0.5 Core = 500m)
m 单位是毫秒,Kubernetes 集群每个节点可以通过操作系统命令来确认节点CPU内核数量,然后将这个数量 core * 1000 = 总节点CPU毫秒
如果一个CPU 是4000m 使用0.5 那么就是 4000 * 0.5 = 2000m
。在Pod里面我们可以通过下面两个参数来限制CPU 资源数
spec.containers[].resources.limits.cpu
:CPU 上线值,可以暂时超过,容器也不会停止
spec.containers[].requests.cpu
:CPU请求值,Kubernetes 调度算法里的依据值。可以超过
示例
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: nginx
resources:
requests:
memory: "50Mi"
cpu: "50m"
# 容器上线是100 Mb 超过Mb 会OOM
limits:
memory: "100Mi"
cpu: "100m"
ports:
- containerPort: 80
这里CPU给的是50m,也就是 0.5core 相当于占用cpu的5%的资源时间,资源限制给的是100m,但这里需要注意CPU资源是可压缩资源,也就是容器达到这个设定上限后,容器性能会下降,但不会终止退出。比如我们直接创建上面的这个Pod
静态Pod
在kubernetes 集群中除了普通Pod外,还有一种特殊的Pod,叫Static Pod,也就是静态Pod 静态Pod直接有Kubelet 进程来管理,由Kubelet 进程自己监控,当Pod 崩溃时会重启该Pod,kubelet 也无法对他们进行健康检查。静态Pod 使用绑定在某个一个Kubelet上,并且使用运行在一个节点上。kubelet 会自动为每一个静态Pod 在Kubernetes的apiserver 上创建一个镜像Pod,因此可以在apiserver 查询该Pod但无法通过apiserver 进行控制
创建静态Pod有两种方式: 配置文件和HTTP两种方式
配置文件
配置文件就是放在特定目录下的标准JSON或YAML格式的Pod定义文件。用Kubelet --pod-mainifest-path=<the directory> 来启动kubelet进程,kubelet定期会扫描这个目录,根据这个目录出现或消失的YAML/JSON文件来创建和删除Pod
当使用kubeadm 方式安装集群配置环境,Kubelet 静态Pod 路径是
/etc/kubernetes/manifest
,
downwardAPI
downwardAPI 不是为了存放容器的数据也不是用来进行宿主机的数据交换的,而是让Pod里的容器能够直接获取到Pod对象本身的一些信息。
将Pod的信息注入到容器内部的两种方式:
环境变量: 单个变量。可以将Pod信息和容器信息直接注入容器内部 Volume 挂载:将Pod信息生成文件,直接挂载到容器内部中去
环境变量 示例:
apiVersion: v1
kind: Pod
metadata:
name: env-pod
namespace: kube-system
spec:
containers:
- name: env-pod
image: busybox
command: ["/bin/sh","-c","env"]
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
获取环境变量
kubectl logs -n kube-system env-pod
可以通过上面示例方式来设置env 值 valueFrom,由于Pod 的name 和namespace 属于原数据,在Pod创建之前就已经定义了,所以我们可以使用meta就可以获取到,对于Pod的IP则不同,Pod IP 是不固定的,Pod 重建就变了,他属于状态数据,所以我们使用status着恶搞属性去获取。另外除了使用fieldRef 获取Pod的基本信息外,还可以通过resourceFieldRef 去获取容器的资源请求和资源限制信息。
Downward 除了提供环境变量方式之外,还提供了通过 Volume 挂载的方式获取Pod的基本信息。 通过Downward API 将Pod 的Label、Annotation 等信息通过Volume挂载到容器某个文件中去,在容器打印出该文件值来验证。
Volume挂载 示例:
apiVersion: v1
kind: Pod
metadata:
name: voluem-pod
namespace: kube-system
labels:
k8s-app: test-volume
node-env: test
annotations:
own: youdianzhishi
build: test
spec:
volumes:
- name: podinfo
downwardAPI:
items:
- path: labels
fieldRef:
fieldPath: metadata.labels
- path: annotations
fieldRef:
fieldPath: metadata.annotations
containers:
- name: voluem-pod
image: busybox
args:
- sleep
- "3600"
volumeMounts:
- name: podinfo
mountPath: /etc/podinfo
查看环境变量
kubectl exec -n kube-system -it voluem-pod sh
cd /etc/podinfo
cat annotations
输出信息
build="test"
kubernetes.io/config.seen="2023-05-06T08:44:40.974202050-04:00"
kubernetes.io/config.source="api
注: Downward API 能够获取到的信息,一定是Pod里容器进程启动之前就能确定下来的信息,如果你想要获取运行之后的信息比如 容器的PID,就无法使用Downward API 了,通过在Pod里定义一个 sidecar容器获取了。
在实际应用中,如果你的应用有获取Pod的基本信息需求,一般我们就可以利用 Downward API 来获取基本信息,然后编写一个启动脚本或者利用 initContainer 将Pod信息注入到我们的容器中去,在应用中就可以处理相关逻辑。
除了通过downward API 可以获取 Pod 本身信息之外的,同样可以通过映射其它资源对象来获取对应的信息,比如Secret,ConfigMap 资源对象,可以通过环境变量和挂载Volume的方式来获取信息,但通过环境变量获取信息方式不具备自动更新能力,一般情况下,都建议使用Volume文件的方式获取信息,因为通过Volume的方式挂载的文件在Pod中会进行热更新。
控制器:ReplicaSet
ReplicaSet 控制器负责维护集群中运行的Pod 数量;Node控制负责监控节点的状态并在节点出现故障及时做出响应,在Kubernetes中,每个控制器负责某种类型的特定资源。
主要功能(RS)主要功能就是位置一组Pod副本的运行,保证一定数量的Pod在集群中正常运行,ReplicaSet 控制器会持续监听 控制这些Pod的运行状态,Pod发送故障数量减少或者增加时会触发调节过程,始终保持副本数量一致
示例:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx-rs
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
控制器:Deployment
实现了 Pod 滚动更新
可以指定滚动更新 启动数量和杀掉数量
还可以等待设置时间后进行升级。如果没有设置改值,kubernets 会假设该容器起来后就提供服务。
可以添加 --record 参数来记录每次操作命令
示例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
revisionHistoryLimit: 10 #保留副本数量
strategy:
# 滚动更新参数
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx # 只是对容器命名
image: nginx:latest
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: 80 # 只是声明
查看滚动更新状态
kubectl rollout status deployment/nginx
暂停更新
kubectl rollout pause deployment/nginx
继续更新
kubectl rollout resume deployment/nginx
查看滚动更新
kubectl rollout history deployment/nginx
查看某个版本滚动更新详细信息
kubectl rollout history deployment/nginx --revision=4
回滚到上一个版本
kubectl rollout undo deployment nginx
回滚到指定版本
kubectl rollout undo deployment nginx --to-revision=3
可以通过 revisionHistoryLimit 保留滚动更新的历史记录
控制器:StatefulSet
对于有状态服务,需要考虑细节很多,容器化应用程序是最困难的任务之一,就是设计有状态分布式组件的部署体系结构。由于无状态组件没有与定义的启动顺序、集群要求、点对点TCP连接、唯一的网络标识符、正常的启动和终止要求等,由此可以很容易的分布式体系结构,因此很容易进行容器化。
诸如数据库、大数据分析系统、分布式Key/value存储、消息中间件需要有复杂的分布式体系结构。都有可能会用到上去功能。为此需要引入 StatefulSet 这种资源对象来支持这种负责的需求,StateDulSet 类似于ReplicaSet,但他可以处理Pod的启动顺序,为保留每个Pod的状态设置唯一标识,具备以下几种功能特征:
稳定的唯一网络的标识符 稳定的持久化的存储 有序优雅的部署和缩放 有序的自动滚动更新
Headless Service
在学习StatefulSet 对象之前,了解新的概念:Headless Service。Service 是应用服务的抽象,通过Labels为应用提供负载均衡和服务发现,每个Service都会自动分配一个 Cluster IP 或 DNS名,在集群内部可以通过该地址或者通过FQDN(Fully Qualified Domain Name)的形式来访问服务。
在 Kubernetes(K8s)中,FQDN(Fully Qualified Domain Name)是一个完全限定域名,用于唯一地表示集群内的各个服务。FQDN 通常由以下部分组成:
服务名(Service name):服务的名称,与 Kubernetes 服务对象的名称相同。
命名空间(Namespace):服务所属的命名空间。
集群域(Cluster domain):默认情况下,Kubernetes 集群的域名为
cluster.local
。将这些部分组合起来,您将得到一个 FQDN,例如:
my-service.my-namespace.svc.cluster.local
。这里,my-service
是服务名,my-namespace
是命名空间,svc.cluster.local
是集群域。在 Kubernetes 集群中,您可以使用这个 FQDN 访问相应的服务。
对于DNS这种方式有两种情况
第一种就是普通Service,通过集群中的DNS服务解析到 mysvc 这个Service 的Cluster IP
第二种 就是Headless Service ,域名是直接解析到mysvc 代理的某一个具体的Pod IP地址,中间少了cluster IP 转发。
Headless Service 不需要分配一个VIP,而是可以直接以DNS方式解析到Pod的地址。
示例:
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: default
labels:
app: nginx
spec:
selector:
app: nginx # Pod 做关联
ports:
- name: http
port: 80
clusterIP: None
实际上Headless Service 定义和普通Service几乎一致,只是
ClusterIP=None
,所以,这个Service 呗创建并不会被分配一个cluster IP,而是会以DNS记录方式暴露出它所有的代理Pod。
使用 Headless Service 代理的DNS记录如下
<pod-name>.<svc-name>.<namespace>.svc.cluster.local
DNS记录正式Cabernets集群为Pod分配的唯一标识,只要我们知道Pod的名字,以及对应的Service名字,就可以组装一条这样的DNS记录访问到Pod IP地址。
创建测试环境:
vim pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv001
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /tmp/pv001
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv002
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /tmp/pv002
创建Pv卷
kubectl apply -f pv.yaml
查看创建的Pv卷
kubectl get pv
创建 statefulset 服务
vim sts.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
namespace: default
spec:
selector:
matchLabels:
app: nginx
serviceName: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
创建
kubectl apply -f sts.yaml
[root@k8s-master-01 kuadm]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 24s
web-1 1/1 Running 0 14s
[root@k8s-master-01 kuadm]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
www-web-0 Bound pv001 1Gi RWO 28s
www-web-1 Bound pv002 1Gi RWO 18s
[root@k8s-master-01 kuadm]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 1Gi RWO Retain Bound default/www-web-0 27m
pv002 1Gi RWO Retain Bound default/www-web-1 27m
添加index.html
for i in 0 1 ; do kubectl exec web-$i -- sh -c 'echo hello $(hostname) > /usr/share/nginx/html/index.html'; done
使用busybox 容器进行测试 以DNS的方式访问 headless Service,
kubectl run -it --image busybox:1.28.3 test --restart=Never --rm /bin/sh
nslookup nginx
删除
kubectl delete sts web
要删除已经挂载的PV卷需要先删除PVC
kubectl delete pvc www-web-0 www-web-1 -n default
kubectl delete -f pv.yaml
控制器:DaemonSet
用来部署守护进程,用于在每个Kubernetes节点中将守护进程的副本作为后台进行运行,就是在每个节点部署一个Pod副本,当节点加入到Kubernetes集群中,Pod会被调度到该节点上运行,当节点从集群被移除后,那么该节点的Pod也会被移除,如果删除DaemonSet,和所有跟这个对象相关的Pods 都会被删除。
适合场景:
集群存储守护程序,如glusterd、ceph 要部署在每个节点都以提供持久存储 节点监控守护进程,如Prometheus 监控集群,可以在每个节点上运行一个node-exporter 进程来收集监控节点信息; 日志守护进程守护程序,如fluentd或者logstash,在每个节点上运行一收集容器的日志 节点网络插件,如:flannel、calico,在每个节点上运行为Pod提供网络服务。
特别说明 DaemonSet 运行的Pod 调度问题,正常情况下,Pod运行在那个节点上是由Kubernetes 的调度器策略来决定的,然后由DaemonSet 控制器创建的Pod,实际上提前已经确定在那个节点上了(Pod创建是指定
.spec.nodeName
):DaemonSet并不关心一个节点的 unshedulable 字段 DaemonSet 可以创建Pod,及时调度器还没有启动
apiVersion: apps/v1
kind: DeamonSet
metadata:
name: nginx
namespace: deafult
spec:
selector:
matchLabels:
k8s-app: nginx
template:
metadata:
labels:
k8s-app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- name: http
containerPort: 80
控制器:Job 与 CronJob
当需要进行批量数据处理和分析或者按时间来调度工作,Kubernetes 提供了 Job和CronJob两种资源对象来应对需求
Job负责处理任务,即仅执行一次任务,他保证批量处理任务的一个或者多个Pod成功结束。而CronJob则就是在Job上加上时间调度。
示例:
vim job-demo.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: job-demo
spec:
template:
spec:
containers:
- name: counter
image: busybox
command: ["bin/sh", "-c", "for i in 9 8 7 6 5 4 3 2 1; do echo $i; done"]
restartPolicy: Never
运行
apply -f job-demo.yaml
查看详细
kubectl describe pod job-demo
查看输出
kubectl logs job-demo--1-jsc9n -n default
默认情况下,restartPolicy 为never 时 创建成功了不会重启,当创建失败时候会重新创建,但可以通过
backoffLimit
限制失败次数,默认是6
仅测试不运行
apply --dry-run=client -f job-demo.yaml
控制器:HPA
Horizontal Pod Autoscaling (Pod 水平自动伸缩) ,简称HPA
通过监控分析一些控制器控制所有Pod的负载变化情况来确定Pod副本数量
通过
kubectl autoscale
命令创建一个HPA 资源对象,HPA Controller 默认30 秒轮询一次(可以通过kube-controller-manager
的--horizontal-pod-autoscaler-sync-period
参数进行设置),查询指定的资源的Pod资源使用率,并且创建是设定的值和指标对比,从而实现自动伸缩功能。在HPA的第一个版本中,我们需要 heapster(废弃) 提供CPU和内存指标,在HPAv2过后 需要安装 Metris Server ,Metrics server 可以通过标准 kubernetes API 吧数据暴露出来,可以通过标准的Kubernetes API 来访问想要的监控数据。
https://10.96.0.1/apis/metrics.k8s.io/v1beta1/namespaces/<namespace-name>/pods/<pod-name>
该地址用来获取Pod 资源数据
这些数据其实来源于 kubelet的summary API 采集而来,通过标准的API来获取数据并不是因为 Metrics server 是 API server 的一部分,而是通过Kubernetes 提供Aggregator 汇聚插件来实现的,是独立APIServer 之外运行的。
聚合API
Aggregator 运行开发人员编写自己的服务,把该服务注册到Kubernetes 的APIServer 里面去,可以像原生的APIServer 提供的API使用自己的API,把自己的服务运行在Kubernetes集群里面,然后Kubernetes的Aggregator 通过 Service名称就可以转发到自己写的Service里面去。这样聚合层带来的好处:
增加API扩展性。开发人员可以编写自己的API服务来暴露想要的API 丰富了API,核心Kubernetes 团队阻止了很多新的API提案,通过允许开发人员将他们的API作为单独的服务公开,这样无需社区繁杂的审核。 开发分阶试验性API,新的API可以单独聚合服务中开发,当稳定在合并APIServer 很容易, 确保新API遵循Kubernetes约定,如果没有这里提出的机制,社区成员会被迫退出自己的东西,这样很容易造成社区成员约定不一致。
安装HPA
需要在集群中 安装 metrics server 服务,就需要开启 Aggregator。因为 Metrics Server 就是通过该代理进行扩展的。通过kubeadm搭建的,默认是已经开启的,如果是二进制安装需要单独配置。
wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.5.2/components.yaml
vim components.yaml
- args:
- --cert-dir=/tmp
- --secure-port=4443
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --kubelet-use-node-status-port
- --kubelet-insecure-tls
- --metric-resolution=15s #添加改参数
执行
kubectl apply -f components.yaml
获取 nodes 信息
kubectl top nodes
kubectl top pods
kubectl autoscale deployment hpa-demo --cpu-percent=10 --min=1 --max=10
CPU使用百分之10 最小副本是1 最大是10
要使用HPA 必要在pod中添加resources 参数
resources:
limits:
memory: "128Mi"
cpu: "500m"
VPA 适合垂直扩容
控制器:Admission
准入控制器,在对象持久化之前用于对 Kubernetes API Server 的请求进行拦截的代码段,在请求经过身份验证之后放行通过,准入控制器可能正在 validating、mutating 或者都在执行,mutating 控制器可以修改他们出来的资源对象,validating 控制器不会,如果任何阶段的任何控制器拒绝请求,则会立刻拒绝整个请求,并将错误返回最终的用户。
这意味着,有一些特殊的控制器可以拦截 Kubernetes API请求,并根据自动的逻辑修改或者拒绝它们,Kubernetes 有自己实现的控制器列表,当然也可自己编写控制器,虽然这些控制功能强大,但这些控制器需要被编译进kube-apiserver,并且能在apiserver 启动时启动。
1.22 之后已经默认就开启了
admission webhook
在Kubernetes apiserver 中包含特殊的准入控制器: MutatingAdmissionWebhook 和ValidatingAdmissionWebhook,这两个控制器将发送准入请求到外部HTTP回调服务并接收一个准入请求,如果启动了这两个准入控制器,Kubernetes管理员可以在集群中创建和配置一个admission webhook
控制器: CRD
Custom Resource Define 简称 CRD。为提高可扩展性,让开发者去自定义资源的一种方式。CRD资源可以动态注册到集群中,注册完毕后,用户可以通过kubectl 来创建访问这个自定义的资源对象,类似于操作Pod一样。不过要注意的是CRD仅仅是资源的定义而已,需要一个COntroller 去监听CRD 的各种事件来添加自定义的业务逻辑。
定义
如果说只是对CRD资源本身进行CRUD操作的话,不需要Controller也是可以实现的,相当于就是只有数据存入etcd中,而没有对这个数据相关操作而已
Service
readiness探针:用于验证后端Pod可以正常工作避免将流量通过kube-proxy发送到已失败的Pod中。
获取客户端IP
调度管理
污点与容忍度
污点(taints) 定义在node节点上的键值,主要作用是让节点拒绝Pod,尤其不符合node规则的Pod
容忍度(tolerations) 定义在pod上 用于配置可容忍的污点,调度器将其调度至污点的节点上或者无污点的节点
污点类型分:默认和自定义
###
Helm
helm客户端:用于负责和k8s APIserver通信
chart:就是helm的一个整合后的chart包。
repository: 用于发布和存储chart包的仓库,类似yum的仓库或docker 仓库
release:用chart包部署的一个实例,通过chart在k8s中部署的应用都会产生一个唯一的release,同一个chart部署多次就会产生多个release。
helm 安装
wget https://get.helm.sh/helm-v3.8.2-linux-amd64.tar.gz
tar xf helm-v3.8.2-linux-amd64.tar.gz
mv linux-amd64/helm /usr/local/bin/
chmod 700 /usr/local/bin/helm
生成环境变量
helm completion bash
helm 基本操作
添加 repo
helm repo add stable https://charts.helm.sh/stable
查看已添加的repo
helm repo list
删除repo
helm repo remove stable
update repo
helm repo update
serivce install and uninstall
helm install <name>
helm uninstall <name>
List serivices
helm list
show status service
helm status <name>
自定义chart
create chart
helm create chart <name>
Chart 模版详解
|-- Chart.yaml #当前chart 属性信息
|-- charts
|-- templates # 模版目录
| |-- NOTES.txt
| |-- _helpers.tpl
| |-- deployment.yaml
| |-- hpa.yaml
| |-- ingress.yaml
| |-- service.yaml
| |-- serviceaccount.yaml
| `-- tests
`-- values.yaml # 全局变量
[root@k8s-master-01 ~]# helm install stable/mysql --generate-name
NAME: mysql-1683697838
LAST DEPLOYED: Wed May 10 01:50:39 2023
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: mysql
CHART VERSION: 9.9.1
APP VERSION: 8.0.33
** Please be patient while the chart is being deployed **
Tip:
Watch the deployment status using the command: kubectl get pods -w --namespace default
Services:
echo Primary: mysql-1683697838.default.svc.cluster.local:3306
Execute the following to get the administrator credentials:
echo Username: root
MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace default mysql-1683697838 -o jsonpath="{.data.mysql-root-password}" | base64 -d)
To connect to your database:
1. Run a pod that you can use as a client:
kubectl run mysql-1683697838-client --rm --tty -i --restart='Never' --image docker.io/bitnami/mysql:8.0.33-debian-11-r7 --namespace default --env MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD --command -- bash
2. To connect to primary service (read/write):
mysql -h mysql-1683697838.default.svc.cluster.local -uroot -p"$MYSQL_ROOT_PASSWORD"
AIzaSyDrceS1WxdQYT4vhfjkx3U7nW08oCnH6Fw
ingress-nginx
helm upgrade --install nginx ingress-nginx/ingress-nginx --namespace ingress-nginx -f values.yaml
longhorn分布存储部署
特性:
可以将longhorn卷作为Kubernetes集群中分布式有状态应用程序的持久卷
跨多个节点和数据中心复制块存储以提高可用性
将备份数据存储在NFS或者AWS S3等外部存储中
创建跨集群灾难恢复卷,以便可以从第二个kubernetes集群备份快速恢复主Kubernetes集群中的数据
调度一个卷的快照,并将备份调度到NFS或S3兼容的二级存储
从备份还原卷
不中断持久卷的情况下升级longhorn
要求:
docker版本v1.13+ or containerd v1.3.7+ 安装open-iscsi,并且iscsid 守护进程在所有节点运行,这是必要的。(因为longhorn依赖主机上的iscsiadm为Kubernetes提供持久卷) RWX支持需要每个节点都拿装NFSv4客户端 宿主机文件系统支持file extents 功能来存储数据。目前我们支持:ext4 与 xfs bash curl findmnt grep awk blkid lsblk 等工具必须安装 mount propagation 必须启用,它允许将一个容器挂载的卷与同一pod中的其他容器共享,甚至可以与同一节点的其他pod 共享
检查是否支持安装
HOST_URL=https://raw.githubusercontent.com/longhorn/longhorn/v1.4.2/scripts/environment_check.sh
curl -sSfL "${HOST_URL}" | bash
安装依赖
dnf install -y iscsi-initiator-utils
systemctl start iscsid
dnf install nfs-utils -y
卸载longhorn
kubectl -n longhorn-system edit settings.longhorn.io deleting-confirmation-flag
helm uninstall longhorn -n longhorn-system
helm install bitnami bitnami/kafka --namespace longhorn-system --create-namespace --version 1.2.6
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: longhorn-ingress
namespace: longhorn-system
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: 'false'
nginx.ingress.kubernetes.io/proxy-body-size: 10000m
spec:
ingressClassName: nginx
rules:
- host: whatsapp.web.test.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: longhorn-frontend
port:
number: 80
日志监控
单机版
kubeadm init --kubernetes-version=v1.24.13 \
--pod-network-cidr=10.244.0.0/16 \
--service-cidr=10.96.0.0/12 \
--token-ttl=0 \
--cri-socket unix:///run/cri-dockerd.sock \
--upload-certs
集群版
kubeadm init --control-plane-endpoint="kubeapi.wang.org" \
--kubernetes-version=v1.24.13 \
--pod-network-cidr=10.244.0.0/16 \
--service-cidr=10.96.0.0/12 \
--token-ttl=0 \
--cri-socket unix:///run/cri-dockerd.sock \
--upload-certs
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
kubeadm join 172.20.66.175:6443 --token u7d14y.hqfqorraa85iwnl9 \
--discovery-token-ca-cert-hash sha256:f7d25e9f9237ca559dce48c02d6a12d4a58ff7a7e16be269e0c00b3b560eb31c \
--cri-socket unix:///run/cri-dockerd.sock
输出
[root@k8s-master-01 ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master-01 NotReady control-plane 10m v1.24.13
k8s-slave-01 NotReady <none> 19s v1.24.13
k8s-slave-02 NotReady <none> 16s v1.24.13
NotReady 是因为需要一个网络插件
安装网络插件(仅在master 执行)
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
kubectl get pods -n kube-system
命令操作
设置配置补全命令
echo "source <(kubectl completion bash)" >> ~/.bashrc
echo "source <(kubeadm completion bash)" >> ~/.bashrc
source ~/.bashrc
删除节点并重新加入
master
kubectl delete node k8s-master-01
slave执行
kubeadm reset
rm -f /etc/cni/net.d/*
systemctl restart kubelet docker cri-docker
kubeadm join 172.20.66.175:6443 --token u7d14y.hqfqorraa85iwnl9 \
--discovery-token-ca-cert-hash sha256:f7d25e9f9237ca559dce48c02d6a12d4a58ff7a7e16be269e0c00b3b560eb31c \
--cri-socket unix:///run/cri-dockerd.sock
kubectl get ns kube-flannel # 获取命名空间为 kube-flannel
kubectl get no k8s-master-01 -o yaml # 输出方式 [yaml|json|wide]
查看Kubernetes 控制平面组件的健康状况的命令
kubectl get cs
查看账号
kubectl get sa
查看pod 日志
kubectl get pod -n kube-system
kubectl -n kube-system logs kube-proxy-9n69w
kubectl create deployment my-nginx --image=nginx:latest
# 查看获取 deploy 状态
kubectl get deploy
# 查看 默认 namspace pod
kubectl get pod -o wide
默认情况下无法 集群创建的服务是无法在外部访问的所以需要用到 service 服务
# 创建 service服务暴露 80端口
kubectl expose deployment my-nginx --port=80
# 查看 service
kubectl get svc
# 展示 my-nginx service 详细信息
kubectl describe service my-nginx
# 删除 svc
kubectl delete svc my-nginx
kubectl expose deployment my-nginx --port=80 --type=NodePort
kubectl get svc
NodePort 会在集群的所有节点上开放端口
# 查看pod容器日志
kubectl logs my-nginx-66cd8855c6-2bbq5 -f
资源对象扩容缩容
# 扩容缩容指定数量
kubectl scale deploy my-nginx --replicas=2
更新 nginx 镜像容器
kubectl set image deployment my-nginx nginx=nginx:1.24.0
删除资源对象
kubectl delete svc/my-nginx deploy/my-nginx
进入容器内部
kubectl exec -it my-nginx-66cd8855c6-2bbq5 -- /bin/bash
示例:
[root@k8s-master-01 ~]# kubectl exec -it my-nginx-66cd8855c6-2bbq5 -- /bin/bash
root@my-nginx-66cd8855c6-2bbq5:/# env
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_PORT=443
HOSTNAME=my-nginx-66cd8855c6-2bbq5
PWD=/
PKG_RELEASE=1~bullseye
HOME=/root
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
NJS_VERSION=0.7.11
TERM=xterm
SHLVL=1
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PORT=443
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NGINX_VERSION=1.23.4
_=/usr/bin/env
查看service地址
env |grep _HOST
节点清理过程
# 冻结节点
kubectl cordon k8s-slave-01
# 驱离节点
kubectl drain k8s-slave-01 --force=true --ignore-daemonsets=true --delete-emptydir-data=true
# 删除节点
kubectl delete nodes k8s-slave-01
# 清理环境 (清理节点工作)
kubeadm reset
# 清理遗留信息
rm -f /etc/cni/net.d/*
# 如果是 master 需要执行
rm -rf ~/.kube/*
# 重启主机
reboot
查看docker
docker history nginx:latest
配置kubernetes dashboard
获取token
kubectl create serviceaccount dashboard-admin -n kube-system
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')
kubectl create token dashboard-admin -n kube-system
eyJhbGciOiJSUzI1NiIsImtpZCI6IlEzYVpfaTFySFhNSFRKWE81dnBZTnpUbUtWalNWTl9kNTdONGpjVDNxdlUifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjgyNjkzNjMxLCJpYXQiOjE2ODI2OTAwMzEsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsInNlcnZpY2VhY2NvdW50Ijp7Im5hbWUiOiJkYXNoYm9hcmQtYWRtaW4iLCJ1aWQiOiJhZjJmYzM0Yy1jNGI1LTQyN2ItOWQ3YS1jZDdmYjI4MDJmZDYifX0sIm5iZiI6MTY4MjY5MDAzMSwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmRhc2hib2FyZC1hZG1pbiJ9.dASD1S99sjGpQWz3Bticq2rLjoHa93ACbf8FSBGwZsigyn7kt1yX0CEPwqk1_3GZXdciSkNJ_abIGF93BOyEwNuVL866zD3v6WNiIFdhhrabOA9BOc6t7d1HRUFLiz7-yf3ITBMXikVFrrdEdaNJ_v59RaxccI-ax3-gsDgo0KJ3GavahCQOpvWYPCVHxr3Z8mxFNhiaUPonGeWrjTCf_G0EdhEfL-CkY0DRxx6IUkZXxFYjvCGoQUuz43Wk_h_CIjd-YZ1NkTH2NgdbbdkgMbKL6sy_oD5eIYwcRuDRHiGhV0bbMfx4syloi8G5zZqAde2B7cWN_AldspG09ZqWGw
配置解读
/etc/kubernets/manifests #只要是这个文件里面的会自动创建 不会受到普通k8s 权限管理 有相关配置文件会自动创建
静态pod 静态pod 的优先级高于普通pod 的优先级
查看污点信息
kubectl describe nodes k8s-master-01
通过 taints 字段查看
集群添加相关表示不让主参与node角色工作 需要添加为污点信息
Taints: node-role.kubernetes.io/control-plane:NoSchedule
node-role.kubernetes.io/master:NoSchedule
kubectl get pod -n kube-system # 该网络服务依赖于 网络插件
资源清单
deployment 是创建
service 是用于访问
资源缩写
资源对象全称 | 缩写 |
---|---|
pod/pods | po |
node/nodes | no |
replication controllers | rc |
Replica sets | rs |
deployment | deploy |
services | svc |
Horizontal pod autoscalers | hpa |
Persistent volume | pv |
persistent volume claims | pvc |
namespaces | ns |
storage classes | sc |
config maps | cm |
daemon sets | ds |
endpoints | ep |
events | ev |
imgresses | ing |
添加slave节点
sudo kubeadm token create --print-join-command
添加污点
kubectl label nodes <new-node-name> nginx-ingress=true
kubectl taint nodes <new-node-name> dedicated=nginx-ingress:NoSchedule
安装 Docker
yum -y erase podman buildah
# 添加 Docker Repo
dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo
# 更新源
dnf update -y
# 安装 Docker
dnf install -y docker-ce
# 启动 Docker 服务
systemctl start docker
# 设置开机自启动
systemctl enable docker
# 安装docker compose
wget https://github.com/docker/compose/releases/download/v2.16.0/docker-compose-linux-x86_64
mv docker-compose-linux-x86_64 /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
安装 docker CRI
部署go [可选]
wget https://go.dev/dl/go1.20.2.linux-amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.20.2.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
安装 cir docker
git clone https://github.com/Mirantis/cri-dockerd.git
cd cri-dockerd
mkdir bin
go build -o bin/cri-dockerd
install -o root -g root -m 0755 bin/cri-dockerd /usr/local/bin/cri-dockerd
cp -a packaging/systemd/* /etc/systemd/system
sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service
systemctl daemon-reload
systemctl enable cri-docker.service
systemctl enable --now cri-docker.socket
System
ExecStart=/usr/local/bin/cri-dockerd --container-runtime-endpoint fd:// --network-plugin=cni --pod-infra-container-image=kubebiz/pause:3.8
controller:
kind: DaemonSet
daemonset:
useHostPort: true
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
nodeSelector:
nginx-ingress: "true"
tolerations:
- key: "dedicated"
operator: "Equal"
value: "nginx-ingress"
effect: "NoSchedule"
controller:
kind: DaemonSet
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
daemonset:
useHostPort: true
评论区