尚硅谷云原生实战学习笔记

尚硅谷云原生实战学习笔记

我不会设置仅粉丝可见,不需要你关注我,仅仅希望我的踩坑经验能帮到你。如果有帮助,麻烦点个 👍 吧,这会让我创作动力+1 😁。我发现有的时候会自动要求会员才能看,可以留言告诉我,不是我干的!😠

写在前面

1. 引入

  1. 云平台核心

    没有一种云计算类型适用于所有人。多种不同的云计算模型、类型和服务已得到发展,可以满足组织快速变化的技术需求。

    部署云计算资源有三种不同的方法:公共云、私有云和混合云。采用的部署方法取决于业务需求。

    1. 为什么用云平台

      • 环境统一
      • 按需付费
      • 即开即用
      • 稳定性强

      国内常见的云平台:阿里云、百度云、腾讯云、华为云、青云。。。

      国外常见云平台:亚马逊AWS、微软Azure、。。。

    2. 公有云:购买云服务商提供的公共服务器

      公有云优势:

      • 成本更低
      • 无需维护
      • 近乎无限制的缩放性
      • 高可靠性
    3. 私有云:自己搭建云平台,或者购买

  2. 云平台操作

    • 安全组:防火墙相关的度端口设置,如果不开端口,也无法外网访问

    • 入方向规则中需要手动添加目的端口,才能访问

    • VPC:更多是进行隔离,比如开发和生产分别在不同的VPC网络下,不同的VPC之间是完全隔离的

      在这里插入图片描述

2. Docker基础

  1. Docker基本概念

    1. 解决的问题

      1. 统一标准

        • 应用构建
          • java、C++、js
          • 打成软件包
          • .exe
          • docker build…镜像
        • 应用分享
          • 所有软件的镜像放到一个指定地方 docker hub
          • 安卓,应用市场
        • 应用运行
          • 统一标准的镜像
          • docker run

        容器化时代

      2. 虚拟化技术

        1. 基础镜像GB级别
        2. 创建使用稍微复杂
        3. 隔离性强
        4. 启动速度慢
        5. 移植与分享不方便
      3. 容器化技术

        1. 基础镜像MB级别
        2. 创建简单
        3. 隔离性强
        4. 启动速度秒级
        5. 移植与分享方便
    2. 资源隔离:

      • cpu、memory资源隔离与限制
      • 访问设备隔离与限制
      • 网络隔离与限制
      • 用户、用户组隔离限制
    3. 架构

      在这里插入图片描述

      • Docker Host:安装Docker的主机
      • Docker Daemon:运行在Docker主机上的Docker后台进程
      • Client:操作Docker主机的客户端(命令行、UI等)
      • Registry:镜像仓库、Docker Hub
      • Images:镜像,带环境打包好的程序,可以直接启动运行
      • Containers:容器,由镜像启动起来正在运行中的程序

      交互逻辑:装好Docker,然后去 软件市场 寻找镜像,下载并运行,查看容器状态日志等排错。

    4. Docker常用命令

      在这里插入图片描述

      1. 容器运行

        在这里插入图片描述

        docker run --name=mynginx -d --restart=always nginx

        • --restart=always:容器随着docker开机自启

        • 👿 如果创建容器的时候,没有指定参数,可以通过:docker update 容器id --restart=always。但是update无法修改端口,如果要做端口映射,则要重启容器。

      2. 进入容器修改内容:docker exec -it 容器id /bin/bash

        • 有的容器没有 bash,可以试试 /bin/sh
      3. 提交改变:docker commit -a "lihuowang" -m "提交内容备注" 容器ID 自己定义的镜像名:tag

      4. 镜像保存:docker save -o xxx.tar 镜像名:tag

        镜像加载:docker load -i xxx.tar

      5. 镜像推送:docker tag 本地镜像:tag 新仓库:tagdocker push 新仓库:tag

        • 这里的 新仓库:远程新建的仓库,比如:lihuowang/本地镜像 把旧镜像的名字,改成仓库要求的新办名字
        • 当然,需要登录:docker login
      6. 挂载数据:docker run --name=xxx -d --restart=always -p 88:80 -v /data/html:/usr/share/nginx/html:ro nginx

        • ro: readonly
        • rw: read and write
        • 修改页面只需要去主机修改即可同步到容器中
      7. 日志查看:docker logs 容器名

      8. 进入容器:docker exec -it 容器名 /bin/bash

      9. 从容器中复制东西到宿主机:docker cp 容器id:/etc/nginx/nginx.conf /data/conf/nginx.conf,反过来一样

  2. 实战和进阶

    1. redis启动: docker run --privileged=true -v E:\11-container\huazhi-redis\redis.conf:/etc/redis/redis.conf -v E:\11-container\huazhi-redis\data\:/data -d --name=huazhi-redis -p 6379:6379 redis:7.4 redis-server /etc/redis/redis.conf

      在这里插入图片描述

    2. 把应用打包成镜像

      1. 以前,以java为例

        • SpringBoot打包成可执行的jar
        • 把jar上传给服务器
        • 服务器运行 java -jar xx.jar
      2. 现在:所有机器都安装docker,任何应用都是镜像,所有机器都可以运行

        • Dockerfile

          FROM openjdk:8-jdk-slim
          LABEL maintainer=huowang
          
          COPY xxx/target/*.jar /app.jar
          ENTRYPOINT ["java", "-jar", "/app.jar"]
          
        • 构建镜像:docker build -t java-demo:v1.0 [-f Dockerfile] .,如果要指定Dockerfile可以加 -f,注意最后要加 . 表示当前路径

    3. 启动容器:docker run -d -p 8080:8080 --name myjava-app java-demo:v1.0

    4. 查看容器运行日志:docker logs 容器ID,跟踪查看:docker logs -f 容器ID

  3. 开发完了怎么迁移到新的环境呢

    1. docker login
    2. docker tag xxx:v1.0 yyy/xxx:v1.0
    3. docker push yyy/xxx:v1.0
    4. docker pull yyy/xxx:v1.0
    5. docker run -d -p 8080:8080 --name zzz xxx:v1.0

3. Kubernetes实战入门

Kubernetes基础概念

  1. 是什么

    我们急需一个大规模容器编排系统

    在这里插入图片描述

    kubernetes具有以下特征:

    • 服务发现和负载均衡:Kubernetes 可以使用 DNS 名称或自己的 IP 地址公开容器,如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。
    • 存储编排:Kubernetes 允许你自动挂载你选择的存储系统,比如本地存储,类似Docker的数据卷。
    • 自动部署和回滚:你可以使用 Kubernetes 描述已部署容器的所需状态,它可以以受控的速率将实际状态更改为期望状态。Kubernetes 会自动帮你根据情况部署创建新容器,并删除现有容器给新容器提供资源。
    • 自动完成装箱计算:Kubernetes 允许你设置每个容器的资源,比如CPU和内存。
    • 自我修复:Kubernetes 重新启动失败的容器、替换容器、杀死不响应用户定义的容器,并运行状况检查的容器。
    • 秘钥与配置管理:Kubernetes 允许你存储和管理敏感信息,例如密码、OAuth令牌和ssh密钥。你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。

    kubernetes 为你提供了一个可弹性运行分布式系统的框架。kubernetes 会满足你的扩展要求、故障转移、部署模式等。例如,Kubernetes 可以轻松管理系统的 Canary 部署。

  2. 架构

    1. 工作方式:kubernetes Cluster = N master node + N worker node(N >= 1)

    2. 组件架构

      在这里插入图片描述

      在这里插入图片描述

      在这里插入图片描述

      • 集群中所有组件的交互都是通过 api-server 的 (秘书处)
      • 集群中所有的网络访问都是通过 kube-proxy 的 (看门大爷)
      • 集群中所有要运行的应用程序都要有一个容器运行时环境
      • 每一个集群节点都要有一个 kubelet (监工,厂长),来监控节点的应用状态,并向 api-server 汇报

      k8s架构

      1. 控制平面组件(Control Plane Components)

        控制平面的组件对集群做出全局决策(比如调度),以及检测和响应集群事件(例如,当不满足部署的 replicas 字段时,启动新的 pod)。控制平面组件可以在集群中的任何节点上运行。然而,为了简单起见,设置脚本通常会在同一个计算机上启动所有控制平面组件, 并且不会在此计算机上运行用户容器。请参阅 使用 kubeadm 构建高可用性集群 中关于多 VM 控制平面设置的示例。

        1.1 kube-apiserver 秘书处 api

        API 服务器是 Kubernetes 控制面的组件,该组件公开了 Kubernetes API。 API 服务器是 Kubernetes 控制面的前端。Kubernetes API 服务器的主要实现是 kube-apiserver。 kube-apiserver 设计上考虑了水平伸缩,也就是说,它可通过部署多个实例进行伸缩。 你可以运行 kube-apiserver 的多个实例,并在这些实例之间平衡流量。

        1.2 etcd 资料库 etcd

        etcd 是兼具一致性和高可用性的键值数据库,可以作为保存 Kubernetes 所有集群数据的后台数据库。您的 Kubernetes 集群的 etcd 数据库通常需要有个备份计划。要了解 etcd 更深层次的信息,请参考 etcd 文档

        **1.3 kube-scheduler ** 调度者 sched

        控制平面组件,负责监视新创建的、未指定运行节点(node)的 Pods,选择节点让 Pod 在上面运行。调度决策考虑的因素包括单个 Pod 和 Pod 集合的资源需求、硬件/软件/策略约束、亲和性和反亲和性规范、数据位置、工作负载间的干扰和最后时限。

        1.4 kube-controller-manager 决策者 c-m

        在主节点上运行 控制器 的组件。

        从逻辑上讲,每个控制器都是一个单独的进程,但是为了降低复杂性,它们都被编译到同一个可执行文件,并在一个进程中运行。

        这些控制器包括:

        • 节点控制器(Node Controller): 负责在节点出现故障时进行通知和响应
        • 任务控制器(Job controller): 监测代表一次性任务的 Job 对象,然后创建 Pods 来运行这些任务直至完成
        • 端点控制器(Endpoints Controller): 填充端点(Endpoints)对象(即加入 Service 与 Pod)
        • 服务帐户和令牌控制器(Service Account & Token Controllers): 为新的命名空间创建默认帐户和 API 访问令牌

        1.5 cloud-controller-manager 外联部 c-c-m

        云控制器管理器是指嵌入特定云的控制逻辑的 控制平面 组件。 云控制器管理器允许您链接集群到云提供商的应用编程接口中, 并把和该云平台交互的组件与只和您的集群交互的组件分离开。cloud-controller-manager 仅运行特定于云平台的控制回路。如果你在自己的环境中运行 Kubernetes,或者在本地计算机中运行学习环境,所部署的环境中不需要云控制器管理器。与 kube-controller-manager 类似,cloud-controller-manager 将若干逻辑上独立的控制回路组合到同一个可执行文件中,供你以同一进程的方式运行。你可以对其执行水平扩容(运行不止一个副本)以提升性能或者增强容错能力。

        下面的控制器都包含对云平台驱动的依赖:

        • 节点控制器(Node Controller): 用于在节点终止响应后检查云提供商以确定节点是否已被删除
        • 路由控制器(Route Controller): 用于在底层云基础架构中设置路由
        • 服务控制器(Service Controller): 用于创建、更新和删除云提供商负载均衡器
      2. Node组件

        节点组件在每个节点上运行,维护运行的 Pod 并提供 Kubernetes 运行环境。

        2.1 kubelet 厂长 kubelet

        一个在集群中每个节点(node)上运行的代理。它保证容器(containers)都运行在 Pod 中。kubelet 接收一组通过各类机制提供给它的 PodSpecs,确保这些 PodSpecs 中描述的容器处于运行状态且健康。kubelet 不会管理不是由 Kubernetes 创建的容器。

        2.2 kube-proxy 门卫大爷 k-proxy

        kube-proxy 是集群中每个节点上运行的网络代理,实现 Kubernetes 服务(Service) 概念的一部分。kube-proxy 维护节点上的网络规则。这些网络规则允许从集群内部或外部的网络会话与 Pod 进行网络通信。如果操作系统提供了数据包过滤层并可用的话,kube-proxy 会通过它来实现网络规则。否则,kube-proxy 仅转发流量本身。

  3. kubeadm创建集群

    在这里插入图片描述

    • 设置主机名:hostnamectl set-hostname xxx
    1. 安装kubeadm

      • 一台兼容的 Linux 主机。Kubernetes 项目为基于 Debian 和 Red Hat 的 Linux 发行版以及一些不提供包管理器的发行版提供通用的指令

      • 每台机器 2 GB 或更多的 RAM (如果少于这个数字将会影响你应用的运行内存)

      • 2 CPU 核或更多

      • 集群中的所有机器的网络彼此均能相互连接(公网和内网都可以)

        • 设置防火墙放行规则
      • 节点之中不可以有重复的主机名、MAC 地址或 product_uuid。请参见这里了解更多详细信息。

        • 设置不同hostname
      • 开启机器上的某些端口。请参见这里 了解更多详细信息。

        • 内网互信
      • 禁用交换分区。为了保证 kubelet 正常工作,你 必须 禁用交换分区。

        • 永久关闭
    2. 所有机器执行以下操作:

      #各个机器设置自己的域名
      hostnamectl set-hostname xxxx
      
      
      # 将 SELinux 设置为 permissive 模式(相当于将其禁用)
      sudo setenforce 0
      sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
      
      #关闭swap
      swapoff -a  
      sed -ri 's/.*swap.*/#&/' /etc/fstab
      
      #允许 iptables 检查桥接流量
      cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
      br_netfilter
      EOF
      
      cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
      net.bridge.bridge-nf-call-ip6tables = 1
      net.bridge.bridge-nf-call-iptables = 1
      EOF
      sudo sysctl --system
      
    3. 安装kubelet、kubeadm、kubectl

      cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
      [kubernetes]
      name=Kubernetes
      baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
      enabled=1
      gpgcheck=0
      repo_gpgcheck=0
      gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
         http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
      exclude=kubelet kubeadm kubectl
      EOF
      
      
      sudo yum install -y kubelet-1.20.9 kubeadm-1.20.9 kubectl-1.20.9 --disableexcludes=kubernetes
      
      # 启动kubelet
      sudo systemctl enable --now kubelet
      

      在这里插入图片描述

      Installing:

      • kubeadm
      • kubectl
      • kubelet

      Installing for dependencies

      • conntrack-tools
      • cri-tools
      • ebtables
      • kubernetes-cni
      • libnetfilter-cthelper
      • libnetfilter-cttimeout
      • libnetfilter-queue
      • socat

      **我的离线安装:[1.20.9] **

      下载正主及其依赖的rpm包:

      • https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/Packages/,在这里选择老师的,1.20.9,没错,我是试错回来了。。。

      • 由于下面的内容已经经历过了,所以我直接开始安装:

        1. kubectlrpm -ivh c968b9ca8bd22f047f56a929184d2b0ec8eae9c0173146f2706cec9e24b5fefb-kubectl-1.20.9-0.x86_64.rpm

        2. 接下来本来是要安装kubelet的,但是报错依赖socat,好家伙原来旧版本依赖啊

          socatrpm -ivh socat-1.7.3.2-8.ky10.x86_64.rpm

        3. kubeletrpm -ivh 02431d76ab73878211a6052a2fded564a3a2ca96438974e4b0baffb0b3cb883a-kubelet-1.20.9-0.x86_64.rpm

        4. kubeadmrpm -ivh 8c6b5ba8f467558ee1418d44e30310b7a8d463fc2d2da510e8aeeaf0edbed044-kubeadm-1.20.9-0.x86_64.rpm

        5. 启动kubelet:sudo systemctl enable --now kubelet

      我的离线安装:[1.31.3]

      下载正主及其依赖的rpm包:

      • https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.31/rpm/x86_64/,这里我选择了最新版的,即1.31。
      • 还有其他的依赖包,基本都可以在aliyun的centos、ubuntu或者其他什么系统的各种镜像里找到,你去os里面找就行。我因为用的是麒麟系统,所以在麒麟的源里找:https://update.cs2c.com.cn/NS/V10

      rpm -ivh xxx.rpm

      • -i: 代表安装(install)。
      • -v: 增强模式,显示更详细的安装信息,比如安装过程中的文件名。
      • -h: 显示进度条(当与 -v 一起使用时)。
      1. cri-toolsrpm -ivh cri-tools-1.31.1-150500.1.1.x86_64.rpm
      2. kubeadmrpm -ivh kubeadm-1.31.3-150500.1.1.x86_64.rpm
      3. kubectlrpm -ivh kubectl-1.31.3-150500.1.1.x86_64.rpm
      4. libnetfilter_queue、libnetfilter_cttimeout、libnetfilter_cthelperrpm -ivh lib*
      5. conntrack-toolsrpm -ivh conntrack-tools-1.4.6-2.ky10.x86_64.rpm
      6. kubernetes-cnirpm -ivh kubernetes-cni-1.5.1-150500.1.1.x86_64.rpm
      7. kubeletrpm -ivh kubelet-1.31.3-150500.1.1.x86_64.rpm
      8. 启动kubelet:sudo systemctl enable --now kubelet
    4. 使用kubeadm引导集群

      1. 下载各个机器需要的镜像

        sudo tee ./images.sh <<-'EOF'
        #!/bin/bash
        images=(
        kube-apiserver:v1.20.9
        kube-proxy:v1.20.9
        kube-controller-manager:v1.20.9
        kube-scheduler:v1.20.9
        coredns:1.7.0
        etcd:3.4.13-0
        pause:3.2
        )
        for imageName in ${images[@]} ; do
        docker pull registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/$imageName
        done
        EOF
           
        chmod +x ./images.sh && ./images.sh
        

        我的离线安装:

        1. 根据老师的视频截图,直接从老师的源下载镜像

          在这里插入图片描述

          docker pull registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/kube-proxy:v1.20.9
          docker pull registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/kube-scheduler:v1.20.9
          docker pull registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/kube-apiserver:v1.20.9
          docker pull registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/kube-controller-manager:v1.20.9
          docker pull registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/etcd:3.4.13-0
          docker pull registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/coredns:1.7.0
          docker pull registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/pause:3.2
          
        2. 导出镜像:docker save -o xxx.tar 镜像ID

        3. 传入服务器并加载镜像: docker load -i xxx.tar,这下镜像都到离线的服务器中啦

        4. 此外也可以用脚本批量导入

          #!/bin/bash
          
          for image in ./images/*.tar; do
              echo "正在导入镜像:$image"
          	docker load -i "$image"
          done
          
          • chmod +x load_images.sh

          • ./load_images.sh

        自建registry

        1. 为了解决镜像不要再传来传去的问题,我决定自建registry: docker run -d -p 5000:5000 --name myregistry --restart=always -v /data/registry:/var/lib/registry registry:latest

        2. 配置需要客户端docker /etc/docker/daemon.json

          {
                     
                     "insecure-registries": ["服务端IP:5000"]}
          
        3. 重启docker:

          • 如果是windows的docker desktop:直接右键重启

          • 如果是linux的docker:

            sudo systemctl daemon-reload
            sudo systemctl restart docker
            
        4. 给镜像打自己的tag:docker tag 镜像ID 服务端IP:5000/kube-proxy:v1.20.9

        5. push到服务端:docker push 服务端IP:5000/kube-proxy:v1.20.9

        6. 从服务端pull:docker pull 服务端IP:5000/kube-proxy:v1.20.9


        问题

        应该是我安装的k8s版本太高了,导致docker里面的镜像版本太低报错:

        this version of kubeadm only supports deploying clusters with the control plane version >= 1.30.0. Current version: v1.20.9
        To see the stack trace of this error execute with --v=5 or higher
        

        我发现最新的版本是 v1.31.3,整吧,整吧

        1. 整完之后报错:没有containerd啥的,就是找不到这个服务,研究了一下发现

          Containerd与Docker有什么区别:https://zhuanlan.zhihu.com/p/718335600

          • 在1.20版本中将内置的dockershim进行分离,这个版本依旧还可以使用dockershim,但是在1.24中被删除。从1.24开始,大家需要使用其他受到支持的运
            行时选项(例如containerd或CRI-O)

            在这里插入图片描述

          现在工作中k8s是使用containerd还是docker来管理容器:https://www.zhihu.com/question/3418508537/answer/31609642599

          为什么这俩工具长得差不多?

          • 咱先说个背景知识,这事儿的根子还在于,Kubernetes 这玩意儿,自己不生产容器,它就是个“调度员”,就是管你要什么容器,跑哪里,怎么跑,这些事儿。容器本身是由更底层的东西来管的。

          • Dockercontainerd,就是两种帮你把容器跑起来的工具。最早 Docker 算是主流,后来 containerd 上位,成了 Kubernetes 里默认的容器管理方式。这两个工具呢,说白了,都能帮你把应用打包成容器,把代码、依赖、配置啥的都塞一块,想在哪儿跑都行。

          • 只是,Docker 做了更多,它不仅仅管容器,还做镜像构建、注册、分发什么的。而 containerd 就精简得多,专注跑容器的核心功能。你可以理解为 Docker 是个大公司里的全能员工,啥都想干;而 containerd 就是个专注一件事的小专家,干活专心不出岔子。

          Docker 落伍的根源在哪?

          说白了,Docker 的锅有点儿多。一开始它啥都干,但 Kubernetes 真正搞起来后,发现有些事不需要它插手。

          比如容器的构建和分发,用不上 Kubernetes 就能搞定;但是 Docker 自带的这些东西不仅多余,还拖慢系统。想想公司里的“全能”同事啥都管,有时候反倒不省心,是不是?

          1. 性能负担:Docker 架构复杂、依赖多,在大规模场景下,额外的服务和功能就成了累赘,常常拖慢系统。就像你把一个公司所有职能都给一个人,这人反倒越干越慢,还常出小毛病。
          2. 兼容性不足:Docker 的架构不符合 Kubernetes CRI(Container Runtime Interface,容器运行时接口)的规范,需要一层转接,叫 dockershim 。多一个环节就多一份不稳定的风险,出点问题谁都搞不清锅在哪儿。换个精简专注的 containerd,直接上 CRI,少了中间商,省心多了。
          3. 复杂架构:Docker 的架构里带了很多没用的东西,举个例子,自己带了个 Docker Engine 和 Docker Daemon,就像一个人带个小助理,干活是方便了,但也有点拖沓。咱不如直接让 containerd 这个大力士上,直接扛活儿干。
          4. Kubernetes 直呼“去掉 dockershim”:2021 年 Kubernetes 就宣布正式抛弃 Docker 支持了,原因很简单,大家都嫌麻烦,尤其是多出来的 dockershim 维护成本高,风险大。既然有更好的选择,谁还拿着“扶不起的阿斗”?

          containerd 有啥独门绝技?

          好嘞,containerd 出场了。这个家伙清晰明了,就是个硬派选手。它干活就干“运行容器”这一件事,不掺和别的,省心省事儿。来看几个它独有的好处:

          1. 体积小,速度快:不多说了,containerd 不像 Docker 那么复杂,你也不用花额外心思去理解各种多余的东西。专注就是力量,咱玩 Kubernetes 就是要这个小、快、专注的工具,别整那些花里胡哨的。
          2. 架构简洁:containerd 和 Kubernetes 打交道的接口天然契合,没啥中间层,直接干活就完事儿。容器调度上,少一环,稳定性就上来。再说,简洁的东西维护起来也省心,不会今天冒泡明天掉线。
          3. 维护方便,社区活跃:虽然 containerd 看着小,但人家是 CNCF(云原生计算基金会)亲自罩的,不会没人管。Kubernetes 里一出啥问题,容器底层的社区老铁马上就给你支援,不怕没解决方案。咱们用它,也更省心。

          现实工作中的利弊权衡

          好了,咱说点实际工作中的情况吧。用 containerd 一开始可能不太习惯,尤其你要是以前 Docker 用得很熟。但公司里啥活不是从学不会到学会,containerd 这玩意儿上手成本其实也没那么高。

          1. 开发、测试的环境:Docker 环境用惯了,你本地开发、打包镜像还是得靠它。但是上了生产环境,部署到集群里,就用 containerd,两者配合着用,各司其职,这样效率最高。
          2. 从 Docker 转 containerd 的迁移成本:对,迁移成本有一些,但这就跟升级设备一样,忍一忍,等习惯了就好。这事儿吧,长痛不如短痛,公司总要向前走。切了 containerd,你会发现架构稳定性提升不止一点半点。
          3. 容器镜像管理:containerd 没有内置的镜像构建和分发功能,但这事儿也不难解决,反正公司内部用一些专门的镜像库(Registry),照样方便得很。大公司还会用 CI/CD 工具链串起来,哪里还用纠结这个。

          总结

          真要总结的话,就是这事儿早就没啥悬念了:Docker 好用在开发阶段,本地折腾项目谁都爱它;可真上生产,containerd 必须安排。干活儿嘛,就要用对的工具,containerd 精简稳定,省去 Docker 的各种麻烦和复杂性。咱就别纠结了,生产上用 Kubernetes 那就直接 containerd,少走弯路。

          Containerd ctr、crictl、nerdctl 客户端命令介绍与实战操作
          https://zhuanlan.zhihu.com/p/562014518

          Containerd 常见命令操作

          更换 Containerd 后,以往我们常用的 docker 命令也不再使用,取而代之的分别是crictlctr两个命令客户端。

          • crictl是遵循 CRI 接口规范的一个命令行工具,通常用它来检查和管理kubelet节点上的容器运行时和镜像。

          • ctrcontainerd的一个客户端工具。

          • ctr -v输出的是containerd的版本,crictl -v输出的是当前 k8s 的版本,从结果显而易见你可以认为crictl是用于k8s的。

          • 一般来说你某个主机安装了 k8s 后,命令行才会有 crictl 命令。而 ctr 是跟 k8s 无关的,你主机安装了 containerd 服务后就可以操作 ctr 命令。

          使用crictl命令之前,需要先配置/etc/crictl.yaml如下:

          runtime-endpoint:unix:///run/containerd/containerd.sock image-endpoint:unix:///run/containerd/containerd.sock timeout:10 debug:false
          

          也可以通过命令进行设置:

          crictl config runtime-endpointunix:///run/containerd/containerd.sock crictlconfigimage-endpointunix:///run/containerd/containerd.sock
          

          更多命令操作,可以直接在命令行输入命令查看帮助。

          docker --help ctr --help crictl --help
          
        2. containerd安装教程:

          参考链接:

          • "validate service connection: validate CRI v1 runtime API for endpoint \" unix:///var/run/containerd/:https://blog.csdn.net/qq_33371766/article/details/140361531

          • 【kubeadm】离线部署k8s(使用containerd):https://blog.csdn.net/Nefertari___/article/details/135932563

          • 轻量级容器管理工具Containerd的两种安装方式:https://www.cnblogs.com/liuzhonghua1/p/18010847

          • 从 github 上下就完了:https://github.com/containerd/containerd/releases,我下的是 containerd-1.7.24-linux-amd64.tar.gz

          • 创建containerd目录并解压

            mkdir /root/containerd
            tar -zxvf containerd-1.7.24-linux-amd64.tar.gz -C /root/containerd
            
          • 追加环境变量并立即生效:

            export PATH=$PATH:/usr/local/bin:/usr/local/sbin && source ~/.bashrc
            
          • 使containerd生效

            cd /root/containerd/bin
            cp * /usr/bin
            cp ctr /usr/local/bin
            
          • 检查containerd的管理命令 ctictl 是否好用:ctictl --version

          • 生成containerd配置文件

            mkdir -p /etc/containerd/
            containerd config default > /etc/containerd/config.toml
            
          • 修改containerd默认配置文件

            • 修改 sandbox_image 为自己registry的 pause 镜像

            • 修改 仓库镜像,我是把所有各种镜像都指向自己的registry了

              [plugins]
              ...
              	[plugins."io.containerd.grpc.v1.cri"]
              	...
              	# sandbox_image = "registry.k8s.io/pause:3.8"
              	sandbox_image = "10.4.32.48:5000/pause:3.10"
              	...
              	[plugins."io.containerd.grpc.v1.cri".registry]
              		[plugins."io.containerd.grpc.v1.cri".registry.mirrors]		
              			[plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]
                      	endpoint = ["http://10.4.32.48:5000"]
                      	[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
                      	endpoint = ["http://10.4.32.48:5000"]
                      	[plugins."io.containerd.grpc.v1.cri".registry.mirrors."10.4.32.48:5000"]
                      	endpoint = ["http://10.4.32.48:5000"]
                  ...
              
          • 启动containerd,且设置自启:systemctl start containerd && systemctl enable containerd

        3. 查看当前版本 kubeadm 安装对镜像的需求:kubeadm config images list

          falling back to the local client version: v1.31.3
          registry.k8s.io/kube-apiserver:v1.31.3
          registry.k8s.io/kube-controller-manager:v1.31.3
          registry.k8s.io/kube-scheduler:v1.31.3
          registry.k8s.io/kube-proxy:v1.31.3
          registry.k8s.io/coredns/coredns:v1.11.3
          registry.k8s.io/pause:3.10
          registry.k8s.io/etcd:3.5.15-0
          

          现在知道下什么了吧,反正通过你的方式搞到这些镜像,然后push到你的registry中,为后续做准备

      2. 初始化主节点,只在主节点运行

        # 所有机器添加master域名映射,以下需要修改为自己的
        # 每一个节点都要添加这句话,让每个节点都知道主节点是谁
        # 执行后的效果:ping cluster-endpoint 可以ping通
        echo "10.4.32.48 cluster-endpoint" >> /etc/hosts
        
        # 主节点初始化
        # --apiserver-advertise-address 管理节点ip
        # --image-repository containerd配置文件中的镜像仓库
        # --control-plane-endpoint 管理节点ip
        # --pod-network-cidr=192.168.0.0/16 这么写是因为后面calico网络安装的yaml文件中默认的是这个
        kubeadm init \
        --apiserver-advertise-address=10.4.32.48 \
        --control-plane-endpoint=cluster-endpoint \
        --image-repository 10.4.32.48:5000 \
        --kubernetes-version v1.20.9 \
        --service-cidr=10.96.0.0/16 \
        --pod-network-cidr=192.168.0.0/16
        
        # 这里k8s的版本,我改回来 v1.20.9
        
        • 因为docker要用 172.xxxx,所以在选集群网络范围的时候要避开
        • 【如果你非要改】所有网络范围不重叠,也不能跟机器ip范围不重叠

        问题 [1.20.9]

        运行很顺利,但是突然报错了个蛇皮错误:error execution phase upload-config/kubelet: Error writing Crisocket information for the control-plane node: timed out waiting for the condition

        在这里插入图片描述

        ⚠️ 这个一搜就搜到了,都是同样的解决方案:

        https://blog.51cto.com/u_16099200/10939353

        https://blog.csdn.net/q_hsolucky/article/details/124273257

        https://blog.csdn.net/weixin_41831919/article/details/118713869

        swapoff -a
        kubeadm reset
        systemctl daemon-reload
        systemctl restart kubelet
        iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X  
        

        其中:

        • swapoff -a:是一个用于禁用所有交换分区和交换文件的命令。在 Linux 系统中,交换空间(swap space)用于将不常用的内存页面从内存移出到磁盘上,以便释放更多的物理内存用于其他进程。使用 swapoff -a 可以将所有当前启用的交换空间禁用。在某些情况下,例如在配置 Kubernetes 集群时,可能需要禁用交换,因为 Kubernetes 对内存管理的要求不鼓励使用交换空间

        • iptables 是一个用于配置 Linux 系统上的网络封包过滤规则的命令:

          1. iptables -F:清空所有默认表(filter 表)中的规则链内的规则。也就是说,这将移除所有的输入(INPUT)、输出(OUTPUT)和转发(FORWARD)链中的规则。

          2. iptables -t nat -F:清空 nat 表中的规则链,这将移除有关网络地址转换(NAT)的所有规则,如源地址伪装(MASQUERADE)和端口映射(DNAT, SNAT)等。

          3. iptables -t mangle -F:清空 mangle 表中的规则链,它主要用于对数据包的服务类型(TOS)、TTL等进行修改。

          4. iptables -X:删除用户自定义链。这个命令不会影响默认的规则链(如 INPUT、OUTPUT、FORWARD),但会删除所有用户自定义的链。

          总结起来,这一系列命令的作用是清空 iptables 中的所有规则和用户自定义的链,恢复到一个相对“干净”的状态。要注意的是,执行这些命令后,可能会导致你当前的防火墙策略失效,导致机器变得不安全,因此要慎重操作

        ⚠️ 其次是一个docker的问题,可能是我的docker版本太高了或者其他的原因:detected “cgroupfs” as the Docker cgroup driver. The recommended driver is “systemd”.

        参考:https://blog.csdn.net/zhyysj01/article/details/130965489

        解决:在 /etc/docker/daemon.json 中加一个配置,然后重启docker服务就行

        {
                  
                  
            "exec-opts": ["native.cgroupdriver=systemd"]
        }
        

        然后查看一下:docker info | grep Cgroup,现在是 systemd 了

        问题 [1.31.3]

        1. 报错了,crictl ps -a 发现etcd和apiserver都没起来

          在这里插入图片描述

          在这里插入图片描述

        2. crictl logs etcd的容器ID 发现,很多路径都没有权限:open /etc/kubernetes/pki/etcd/peer.key: permission denied"

          我直接 chmod 666 整上了:

          • chmod 666 /etc/kubernetes/pki/etcd/peer.key
          • chmod 666 /etc/kubernetes/pki/etcd/server.key
          • 然后把挂了的 etcd 和 apiserver 删掉,一会儿就自动起来了

          注意:不要 kubeadm reset一下,重新来过,还是会没权限,因为每次都是重来。

          在这里插入图片描述

        3. 当我们 crictl ps -a的时候发现警告

          WARN[0000] runtime connect using default endpoints: [unix:///run/containerd/containerd.sock unix:///run/crio/crio.sock unix:///var/run/cri-dockerd.sock]. As the default settings are now deprecated, you should set the endpoint instead.
          WARN[0000] image connect using default endpoints: [unix:///run/containerd/containerd.sock unix:///run/crio/crio.sock unix:///var/run/cri-dockerd.sock]. As the default settings are now deprecated, you should set the endpoint instead.
          

          参考:https://www.cnblogs.com/zmh520/p/18393109

          1. 修改 crictl 的配置文件:vim /etc/crictl.yaml

            runtime-endpoint: "unix:///run/containerd/containerd.sock"
            timeout: 0
            debug: false
            
          2. 重启 containerdsystemctl restart containerd

        我只能说两个字:成功!🎉

        在这里插入图片描述

        Your Kubernetes control-plane has initialized successfully!
        
        To start using your cluster, you need to run the following as a regular user:
        
          mkdir -p $HOME/.kube
          sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
          sudo chown $(id -u):$(id -g) $HOME/.kube/config
        
        Alternatively, if you are the root user, you can run:
        
          export KUBECONFIG=/etc/kubernetes/admin.conf
        
        You should now deploy a pod network to the cluster.
        Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
          https://kubernetes.io/docs/concepts/cluster-administration/addons/
        
        You can now join any number of control-plane nodes by copying certificate authorities
        and service account keys on each node and then running the following as root:
        
          kubeadm join cluster-endpoint:6443 --token syvhe8.j6eux6bvvcjhvpk0 \
            --discovery-token-ca-cert-hash sha256:c0dab366414804cc86b6d4273ab5d6485e017984a10423057bea870d36dcb4b9 \
            --control-plane
        
        Then you can join any number of worker nodes by running the following on each as root:
        
        kubeadm join cluster-endpoint:6443 --token syvhe8.j6eux6bvvcjhvpk0 \
            --discovery-token-ca-cert-hash sha256:c0dab366414804cc86b6d4273ab5d6485e017984a10423057bea870d36dcb4b9
        
      3. 设置 .kube/config

        📍 主节点,使用!创建目录、复制配置文件、赋权~

        mkdir -p $HOME/.kube
        sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
        sudo chown $(id -u):$(id -g) $HOME/.kube/config
        

        成功啦!

        [root@k8s-master ~]# kubectl get nodes
        NAME         STATUS     ROLES                  AGE     VERSION
        k8s-master   NotReady   control-plane,master   3h50m   v1.20.9
        

        ⚠️ 其实中间出了一个小插曲:kubectl get nodes之后报错:

        Unable to connect to the server: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "kubernetes")
        

        略微一搜:https://download.csdn.net/blog/column/11866583/126112342

        好家伙,难不成是之前1.31.4的残留导致的,我直接:rm -rf $HOME/.kube,再重复 📍 中的三行命令即可。真有我的,解决!:happy:

      4. 安装网络组件

        现在主节点是 NotReady 是吧,原因是没有 deploy a pod network to the cluster,即缺少一个网络插件,把k8s的机器用网络插件串起来打通。

        k8s支持很多网络插件,我们选择 calico

        1. 下载 calico 的配置文件:https://docs.projectcalico.org/manifests/calico.yaml,我访问之后直接跳转到了:https://calico-v3-25.netlify.app/archive/v3.25/manifests/calico.yaml

        2. 安装:kubectl apply -f calico.yaml

          问题:报错了:error: unable to recognize "calico.yaml": no matches for kind "PodDisruptionBudget" in version "policy/v1"

          ⚠️ 发现是当前k8s不支持calico的版本

          https://blog.csdn.net/weixin_45379855/article/details/125175823

          那是当然啊,我下的最新的calico,了解了一下,应该选v3.20

          https://docs.projectcalico.org/v3.20/manifests/calico.yaml

          再安装就成功啦 🎉

        3. 一些命令

          1. kubectl get nodes:查看集群所有节点

          2. kubectl apply -f xxx.yaml:根据配置文件,给集群创建资源,比如创建网络资源 calico

          3. 查看集群部署了哪些应用?

            1. docker ps = kubectl get pods -A [-w]:查询所有pod的状态[一直监听]

              watch -n 1 kubectl get pods -A:每一秒执行后面的命令,查看pod状态

            2. 运行中的应用在docker里面叫容器,在k8s里面叫Pod

          4. 查看pod信息: kubectl describe pod 【pod名】 -n 【命名空间】

          5. 删除pod: kubectl delete pod 【pod名】 -n 【命名空间】

        4. 通过 kubectl get nodes 看到主节点 notready,然后用 kubectl get pods -A 看到 calico 的 status 是 Init:ImagePullBackOff,这说明拉镜像失败了,肯定失败啊,我们都没管 calico 的镜像

          • 通过 kubectl describe pod calico-node-m6kp5 -n kube-system,我们可以看到,问题在这儿呢:Failed to pull image "docker.io/calico/cni:v3.20.6"

            在这里插入图片描述

          • 总结还需要如下镜像:

            • docker.io/calico/cni:v3.20.6
            • docker.io/calico/pod2daemon-flexvol:v3.20.6
            • docker.io/calico/node:v3.20.6
            • docker.io/calico/kube-controllers:v3.20.6

            ❓ 问了下GPT4o

            要使用 Calico 作为 Kubernetes 集群的网络插件,你通常需要拉取和部署多个容器镜像。这些镜像各自负责不同的功能和组件。以下是一些常用的 Calico 组件及其所需的镜像:

            1. calico/cni: CNI 插件,负责网络接口的设置和配置。

              • 镜像名称示例:calico/cni
            2. calico/node: 核心组件,负责路由、策略、安全组等。

              • 镜像名称示例:calico/node
            3. calico/kube-controllers: 负责网络策略和 IP 池的管理。

              • 镜像名称示例:calico/kube-controllers
            4. calico/pod2daemon-flexvol: 用于 Flexible Volumes 的插件,支持网络策略的强化。

              • 镜像名称示例:calico/pod2daemon-flexvol
            5. calico/typha: (可选) 用于大规模集群,以减少对 API 服务器的负载。

              • 镜像名称示例:calico/typha
          • 配置 /etc/docker/daemon.json,这样从 docker.io 也会到自建的registry中搞镜像

            "registry-mirrors": ["http://10.4.32.48:5000"]
            

          🎉 在所有镜像push之后,自动就 Ready 啦!pods们都 running 啦!

          在这里插入图片描述

      5. 加入Work节点

        还是之前 kubeadm init 成功显示里面的命令,在Work节点的服务器中运行:

        kubeadm join cluster-endpoint:6443 --token syvhe8.j6eux6bvvcjhvpk0 \
            --discovery-token-ca-cert-hash sha256:c0dab366414804cc86b6d4273ab5d6485e017984a10423057bea870d36dcb4b9
        

        但是这个令牌是24h有效的,如果过期了怎么办?

        在master节点创建新令牌: kubeadm token create --print-join-command

        ⚠️ 当然问题还是会有的,还是老问题

        detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd".
        

        解决:编辑 /etc/docker/daemon.json,记得重启docker哦 systemctl restart docker

        {
                  
                  
          "insecure-registries" : ["10.4.32.48:5000"],
          "registry-mirrors": ["http://10.4.32.48:5000"],
          "exec-opts": ["native.cgroupdriver=systemd"]
        }
        

        🎉 成功啦!

        在这里插入图片描述

        👌 回去主节点上可以看到加入的工作节点们~

        在这里插入图片描述

        ⚠️ 没错没错,问题又来了,从主节点上看到工作节点虽然都ready了,但是!kubectl get pods -A 会发现,有的pod没有启起来

        在这里插入图片描述

        • kubectl describe pod 【pod名】 -n 【命名空间】 看可以发现,是子节点容器启不起来的问题

          在这里插入图片描述

        • 熟悉吗!我太熟悉了!我去work的节点一看 docker ps -a,好家伙一堆卡卡失败的啊,找一个失败的进去看看 docker logs 【容器ID】,报错如下。我百度一查 seccomp,虽然看不懂啊,但我看到了一个关键词 podman,好家伙,这个我熟悉啊,银河麒麟docker的最大绊脚石

          standard_init_linux.go:211: init seccomp caused "permission denied"
          libcontainer: container start initialization failed: standard_init_linux.go:211: init seccomp caused "permission denied"
          

          在这里插入图片描述

        解决yum remove podman,好家伙,我踏马怎么能忘记这个!全部就自己running了,醉醉的。

        在这里插入图片描述

      6. 集群自我修复能力测试

        如果把三个服务器都reboot,重启成功后,可以看到节点都在自动恢复

  4. 部署dashboard

    1. kubernetes官方提供的可视化界面

      • 官方地址:https://github.com/kubernetes/dashboard
      • 下载 v2.3.1 的yaml文件:https://raw.githubusercontent.com/kubernetes/dashboard/v2.3.1/aio/deploy/recommended.yaml
      • 安装:kubectl apply -f recommended-v2.3.1.yaml

      ⚠️ 果然,不出问题是不可能的,必然是镜像的问题

      1. kubernetesui/metrics-scraper:v1.0.6
      2. kubernetesui/dashboard:v2.3.1
    2. 设置访问端口

      1. 修改配置文件中的 type: ClusterIP 改为 type: NodePort

        kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard

      2. 找到端口,在安全组放行:kubectl get svc -A |grep kubernetes-dashboard

        [root@k8s-master others]# kubectl get svc -A |grep kubernetes-dashboard
        kubernetes-dashboard   dashboard-metrics-scraper   ClusterIP   10.96.51.184   <none>        8000/TCP                 33m
        kubernetes-dashboard   kubernetes-dashboard        NodePort    10.96.223.53   <none>        443:31345/TCP            33m
        

        需要在安全组中把 31345,也就是上面的最后一行那个 443:31345 这个端口放开

      3. 访问:https://集群任意IP:端口(即31345),用 k8s-node1 为例:https://10.4.32.50:31345

        在这里插入图片描述

        ⚠️ 输入了打不开,报错内容如下

        10.4.32.50 通常会使用加密技术来保护您的信息。Chrome 此次尝试连接到 10.4.32.50 时,该网站发回了异常的错误凭据。这可能是因为有攻击者在试图冒充 10.4.32.50,或者 Wi-Fi 登录屏幕中断了此次连接。请放心,您的信息仍然是安全的,因为 Chrome 尚未进行任何数据交换便停止了连接。
        
        您目前无法访问10.4.32.50,因为此网站发送了Chrome无法处理的杂乱凭据。网络错误和攻击通常是暂时的,因此,此网页稍后可能会恢复正常。
        

        解决:只能说很神奇,你只需要在当前页面输入 thisisunsafe,就完事儿了,我擦真的很神奇,你看不到你的输入,就是盲打,打完就跳转了。并且后面都是直接跳转了

        参考:https://blog.csdn.net/quanqxj/article/details/103076795

    3. 创建访问账号

      光看这个玩意儿,不知道登录的token是啥啊,需要自己弄,没错:kubectl apply -f dash.yaml

      那么这个文件怎么写呢:

      # 创建访问账号,准备一个yaml文件; vi dash.yaml
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: admin-user
        namespace: kubernetes-dashboard
      ---
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRoleBinding
      metadata:
        name: admin-user
      roleRef:
        apiGroup: rbac.authorization.k8s.io
        kind: ClusterRole
        name: cluster-admin
      subjects:
      - kind: ServiceAccount
        name: admin-user
        namespace: kubernetes-dashboard
      

      这样就创建了一个服务的账号:admin-user

    4. 令牌访问

      1. 获取访问令牌:kubectl -n kubernetes-dashboard get secret $(kubectl -n kubernetes-dashboard get sa/admin-user -o jsonpath="{.secrets[0].name}") -o go-template="{ {.data.token | base64decode}}"

        输出的还挺像jwt token的

        eyJhbGciOiJSUzI1NiIsImtpZCI6IllLRDhuSGpndDhJOFRnUWtCNE5XQXZER1NfMDlwY25BR3VGMEl1dnN0Nm8ifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLWN6ZHo3Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJkY2MyOThhZS1iMzBlLTRiMzUtODMyNy00MDg3ZTkzYzk1NzIiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQ6YWRtaW4tdXNlciJ9.S16hXdYbCu64pmEHw6U7hW28jPzxKB7V-tm-n-m3lupzgPIdaudKvSoUjPTy-O55h2_4CgMI0GuQTSNCopjj0Rnf5CxOzarpfSkHvo6C9HuJp1nQhOJJpzKPTNT3m_rYjwJwSgGnZasvGFfmvCndut6qLLYSsZr_sFdUL1rJOBs5peoCnmR7yptrrrog-e9Vtxkhr-Q04RqwJCYXjxPkmKevGTLYlLfbpC_c_JPlLsafjut3DgFrZWb0hwQzwdYOk1JDBcJbV0Jv5CG98jNT02mFoSq3m0aZ_T_aIWtTzdNi7f4siblzoffViIYcN42_5D_FdR4JctVqddR4Nu_O-Q
        
      2. 然后一粘贴就登录了

        在这里插入图片描述

Kubernetes核心实战

  1. 资源创建方式

    • 命令行
    • YAML
  2. Namespace

    名称空间是用来隔离资源的,对资源进行分组。默认隔离资源,不隔离网络。

    在这里插入图片描述

    • 获取当前名称空间列表:kubectl get ns

    • 查看名称空间中的应用列表:kubectl get pods -n 【名称空间】

    • 删除名称空间:kubectl delete ns 【名称空间】,删除时,会把该空间下的所有应用资源全部删除,请谨慎!

    • 创建名称空间:kubectl create ns 【名称空间】

      # 如果用yaml创建名称空间:kubectl apply -f xxx.yaml
      # 删除:kubectl delete -f xxx.yaml,这样删的比较干净
      
      # 版本号
      apiVersion: v1
      # 资源类型
      kind: Namespace
      metadata:
      	name: hello
      
  3. Pod

    运行中的一组容器,Pod是kubernetes中应用的最小单位

    在这里插入图片描述

    在这里插入图片描述

    1. 创建pod:

      1. 命令行创建:

        kubectl run mynginx --image=nginx,这样创建的pod在默认的命名空间中。

        ⚠️ 如果要用本地的镜像 --image=10.4.32.48:5000/nginx

        ⚠️ 如果本地镜像是http,要设置docker或者containerd的配置文件

        1. 编辑 containerd 的配置文件,通常位于 /etc/containerd/config.toml。在 [plugins.“io.containerd.grpc.v1.cri”.registry] 的 mirrors 部分添加你的注册表:

          [plugins."io.containerd.grpc.v1.cri".registry.mirrors."10.4.32.50:5000"]
            endpoint = ["http://10.4.32.50:5000"]
          
        2. 编辑 Docker 的配置文件 /etc/docker/daemon.json,添加或修改 insecure-registries 字段以包含你的注册表地址。确保配置如下:

          {
            "insecure-registries" : ["10.4.32.50:5000"]
          }
          
      2. 配置文件创建:kubectl apply -f pod.yaml,删除: kubectl delete -f pod.yaml

        apiVersion: v1
        kind: Pod
        metadata:
          labels:
            run: mynginx
          name: mynginx
        #  namespace: default
        spec:
          containers:
          - image: 10.4.32.48:5000/nginx
            name: mynginx
        
      3. 可视化操作,上述配置yaml粘贴到下图中

        在这里插入图片描述

        在这里插入图片描述

    2. 一个pod中有多个容器创建

      apiVersion: v1
      kind: Pod
      metadata:
        labels:
          run: myapp
        name: myapp
      spec:
        containers:
        - image: 10.4.32.48:5000/nginx
          name: nginx
        - image: 10.4.32.48:5000/tomcat:8.5.68
          name: tomcat
      
      • 只有一个IP
      • 默认访问到的是nginx,因为nginx是80端口
      • 如果访问的是8080端口,则会访问到tomcat
      • nginx访问tomcat,仅需 127.0.0.1:8080同一个pod内共享网络空间和存储
      • 如果一个pod中多个容器占用同样的端口,会导致启动失败

      在这里插入图片描述

    3. 查看pod状态:kubectl get pod [-n 命名空间]

    4. 查看pod怎么了:kubectl describe pod pod名称 [-n 名称空间]

    5. 删除pod:kubectl delete pod pod名称 [-n 名称空间]

    6. 查看pod日志:kubectl logs [-f] pod名称

      • -f:一直跟踪
    7. 查看集群指标信息:kubectl top nodes,其中cpu来说1000m就是用了一个核

      [root@k8s-master yamls]# kubectl top nodes
      NAME         CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
      k8s-master   298m         3%     6654Mi          21%
      k8s-node1    177m         2%     2460Mi          16%
      k8s-node2    554m         6%     2323Mi          15%
      

      类似的查看每个pod的指标信息:kubectl top pods -A

    8. 每个pod,k8s都会分配一个ip:kubectl get pod -owide,后面就能使用pod的IP+容器端口,就能访问到其中的应用

      为什么是192.168.xxx.xxx?

      因为在 kubeadm init 的时候,--pod-network-cidr 写的是 192.168.0.0/16

      集群中的任意机器的任意应用都能通过 Pod 分配的IP来访问这个Pod

      注意:只能在集群内访问,集群外不可以

    9. 进入容器:kubectl exec -it mynginx -- /bin/bash

  4. Deployment

    控制Pod,使Pod拥有多副本,自愈,扩缩容等能力

    1. 创建:kubectl create deployment mytomcat --image=10.4.32.48:5000/tomcat:8.5.68
    2. 删除:kubectl delete deploy mytomcat
    3. 查看:kubectl get deploy

    特点

    1. 自愈能力:用 deployment 部署的容器即使delete之后会自动重启一个新的

    2. 多副本kubectl create deploy my-dep --image=10.4.32.48:5000/nginx --replicas=3

      在这里插入图片描述

      通过yaml创建部署

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        labels:
          app: my-dep
        name: my-dep
      spec:
        replicas: 3
        selector:
          matchLabels:
            app: my-dep
        template:
          metadata:
            labels:
              app: my-dep
          spec:
            containers:
            - image: nginx
              name: nginx
      
    3. 扩缩容

      在这里插入图片描述

      1. 命令行:kubectl scale deploy/my-dep --replicas=5,类似的,缩容就是把replicas的数字降低

        在这里插入图片描述

      2. 热编辑yaml:kubectl edit deploy my-dep

        这时候会打开yaml文件,把里面的 replicas 参数改为想要的数值, wq 后即完成扩缩容

      3. 可视化界面扩缩容:

        在这里插入图片描述

    4. 自愈&故障转移

      1. pod炸了会自动重启
      2. node机器炸了就完蛋了,只能在别的机器启

      ⚠️ 没错,我自己测,直接把work节点reboot了,然后发现起不来啦

      Error querying BIkD: unable to connect to Binov4 socket: dial wix /var/run/calico/bird.ctl: connect: connection refused
      calico/node is not ready: BIRD is not ready: BGP not established with
      

      在这里插入图片描述

      解决:https://www.cnblogs.com/exmyth/p/17259198.html

      # [my new add content]
      - name: IP_AUTODETECTION_METHOD
        value: "interface=eth.*"
      
      # Cluster type to identify the deployment type
      - name: CLUSTER_TYPE
        value: "k8s,bgp"
      # Auto-detect the BGP IP address.
      - name: IP
        value: "autodetect"
      # Enable IPIP
      - name: CALICO_IPV4POOL_IPIP
        value: "Always"
      

      官方提供的yaml文件中,ip识别策略(IPDETECTMETHOD)没有配置,即默认为first-found,这会导致一个网络异常的ip作为nodeIP被注册,从而影响node-to-node mesh。我们可以修改成can-reach或者interface的策略,尝试连接某一个Ready的node的IP,以此选择出正确的IP。

      - name: IP_AUTODETECTION_METHOD # 增加内容
        value: "interface=eth.*" 或者 value: "interface=eth0" # 增加内容
      

      备注:记得 systemctl enable kubelet,没自启很难办啊,我排查了半天奶奶滴!😢

    5. 滚动更新

      启一个新的杀一个老的,不断循环。

      在这里插入图片描述

      • 查看deploy的详情:kubectl get deploy my-dep -oyaml

        在这里插入图片描述

      • kubectl set image deploy/my-dep nginx=10.4.32.48:5000/nginx:1.16.1 --record:修改deploy的my-dep中nginx镜像为新的镜像,然后记录这次版本更新

    6. 版本回退

      1. 查看历史记录:kubectl rollout history deployment/my-dep
      2. 查看历史记录详情:kubectl rollout history deployment/my-dep --revision=2
      3. 回滚上次:kubectl rollout undo deployment/my-dep
      4. 回滚指定版本:kubectl rollout undo deployment/my-dep --to-revision=2
    7. 其他工作负载

      除了Deployment,k8s还有 StatefulSetDaemonSetJob 等 类型资源。我们都称为 工作负载。有状态应用使用 StatefulSet 部署,无状态应用使用 Deployment 部署:https://kubernetes.io/zh/docs/concepts/workloads/controllers/

      在这里插入图片描述

      • Deployment:无状态应用,服务在哪儿拉起来都行
      • StatefulSet:有状态应用,服务挂了在别的地方拉起来数据还要有
      • DaemonSet:在每个机器上都有且一份,比如日志收集
      • Job/CronJob:定时任务
  5. Service

    将一组 Pods 公开为网络服务的抽象方法。

    在这里插入图片描述

    1. 暴露Service资源的端口:kubectl expose deploy my-dep --port=8000 --target-port=80 [--type=ClusterIP]默认的类型是集群IP

    2. 查看当前Service的IP:kub

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李英俊小朋友

没事啦!白嫖不要紧啦!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值