侧边栏壁纸
博主头像
cn2linux博主等级

行动起来,活在当下

  • 累计撰写 127 篇文章
  • 累计创建 1 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

K8S


容器

当我们创建一个容器的时候,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 相关的服务

cri-containerd-cni-1.5.7-linux-amd64.tar.gz 是相对完整的

  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种命名空间

  1. Mount namespace:用于隔离文件系统挂载点,每个 mount namespace 都有自己的根文件系统和挂载点列表。

  2. UTS namespace:用于隔离主机名和域名,每个 UTS namespace 都有自己的主机名和域名。

  3. IPC namespace:用于隔离 System V IPC 和 POSIX 消息队列等进程间通信机制。

  4. PID namespace:用于隔离进程 ID,每个 PID namespace 都有自己的进程 ID。

  5. Network namespace:用于隔离网络栈,每个 network namespace 都有自己的网络设备、IP 地址、路由表和防火墙等配置。

  6. User namespace:用于隔离用户和用户组 ID,每个 user namespace 都有自己的用户和用户组 ID,从而实现用户和权限的隔离。

  7. 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 通常由以下部分组成:

  1. 服务名(Service name):服务的名称,与 Kubernetes 服务对象的名称相同。

  2. 命名空间(Namespace):服务所属的命名空间。

  3. 集群域(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

0
  • ${post.likes!0}

评论区