k8s+containerd(kvm版)

k8s(Kubernetes)是由Gogle开源的容器编排引擎,可以用来管理容器化的应用程序和服务,k

  • 高可用:系统在长时间内持续正常地运行,并不会因为某一个组件或者服务的故障而导致整个系统不可用
  • 可扩展性:系统可以根据负载的变化来动态的扩展或缩减系统的资源,从而来提高系统的性能和资源利用率

k8s提供了自动重启、自动重建、自动修复提高集群的可用性,以下概念稍微了解即可,看一看直接实操,know what->know how->know why

核心概念

Pod组件

Pod是k8s的最小调度单元,一个Pod是一个或者多个应用容器的组合,Pod里的容器共享存储、网络、运行时配置等

Node节点组件

一个节点就是一个物理机或者虚拟机,一个节点上可以运行一个或多个Pod;一个集群至少2个节点,一个Master-Node一个Worker-Node

一个节点上有三个组件:

  • kubelet:管理和维护每个基点上的Pod,监控Worker-Node运行情况
  • kube-proxy:网络代理和负载均衡
  • container runtime:保障Pod运行,相当于Docker Engine

Master-Node:管理整个集群

  • kube-apiserver:提供k8s集群的api接口服务,所有组件通过这个接口通信

  • ControllerManager控制器管理器,负责管理集群中各种资源对象的状态,包括

    • Node Controller:负责在节点出现故障时进行通知和响应
    • Job Controller:检测代表一次性任务的Job对象,然后创建Pods来运行这些任务直至完成
    • EndpointSlice Controller:填充端点分片对象
    • ServiceAccount Controller:为新的命名空间创建默认服务账号
  • Scheduler:调度器,负责监控k8s集群所有节点的资源使用情况,根据调度策略将Pod调度到合适的节点中运行

  • etcd:键值存储系统,负责存储所有资源对象的状态信息

  • Cloud Controller manager:云控制器管理器,负责与云平台的api交互

Worker-Node: 运行应用和服务

  • kubelet:在每个节点上运行,接受收PodSpecs确保PodSpec中描述的容器处于运行状态且健康
  • kube-proxy:在每个节点上运行的网络代理,实现内外部的网络通信
  • Container Runtime:容器运行时,支持多容器运行,如Docker、Containerd等,目前推荐Containerd,因为Docker太重了,对于k8s来说,只需要有一个容器运行时就可以,而Docker自带的还有网络这些用k8s的proxy就行

Cluster 集群组件

Cluster将多个节点组织到一起共同为系统提供服务的过程称为集群

Control Plane 控制平面组件

控制平面为集群做全局决策,比如资源调度、检测和响应集群事件,一般在Master-Node运行

Addons 插件

  • DNS:集群内部的DNS服务
  • dashbord:web界面,便于管理应用和集群
  • Container Resource Monitoring:容器资源监控
  • Cluster-level Logging:集群日志记录
  • Network Plugins:负责为Pod分配ip并使它们能够在集群内部互相通信

Service 服务

可以将一组Pod封装成一个服务,这个服务可以通过统一的入口来访问,可以防止Pod被销毁或创建后ip改变导致失联

内部服务

像mysql、redis等只需要被集群内部访问不需要外部访问的就是内部服务

外部服务

像后端接口等需要被暴露给外部使用的就是外部服务

常用类型
  • ClusterIP:默认方式,分配一个稳定的IP地址,即VIP,只能在集群内部访问
  • NodePort:在每个节点开放一个端口来暴露服务,可以在集群外部访问,通过NodeIP:NodePort访问(端口范围:30000~32767)
  • LoadBalancer:与NodePort类似,在每个节点启用一个端口来暴露服务。除此之外,K8s请求底层云平台的负载均衡器,把每个[Node IP]:[NodePort]作为后端添加进去
  • ExternalName:外部名称类型,将服务映射到一个外部服务域名上
  • Headless:无头类型,主要用于DNS解析和服务发现
  • Ingress:是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP和HTTPS,还可以提供负载均衡、SSL 终结和基于名称的虚拟托管
  • ConfigMap:API 对象,用来将非机密性的数据保存到键值对中
  • Secret:包含少量敏感数据(如密码、令牌或密钥)的对象,Secret 可以独立于使用它们的 Pod 创建,因此在创建、查看和编辑 Pod 的工作流程中,Secret(及其数据)被泄露的风险较小
  • Volumes:数据持久化存储
  • Deployment:部署有状态应用
  • StatefulSet:部署无状态应用

k8s架构

环境搭建

需要Matser Node虚拟机和Worker-Node虚拟机

安装kubectl

kubectl是使用K8s API 与K8s集群的控制面进行通信的命令行工具,kubectl安装到Matser Node节点的虚拟机

复制代码
#安装kubectl
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
#查看安装
kubectl version --client
#卸载
sudo rm /usr/local/bin/kubectl

安装k8s

环境准备

  • 这里使用kvm Linux虚拟机,使用vmware、virtbox、multipss是一样的,只是虚拟机不同罢了,喜欢哪个用哪个
    kvm教程

网上有很多虚拟机安装教程,这里就不赘述了,本人使用debian12,你用啥Linux都可以,操作基本相同

1、配置要求:

  • 你使用的电脑内存配置16G以上
  • 虚拟机内存:2G或更多
  • 虚拟机CPU:2G或更多
  • 虚拟机硬盘:40或更多
  • 虚拟机网络:每个虚拟机都能访问外网
  • ssh连接正常:一般新装的虚拟机远程登陆默认关闭,先开启再克隆方便用远程连接工具操作
  • 关闭防火墙:生产主机别关,我们学习关了方便操作,生产环境开放端口使用
  • 关闭AppArmor(debian):systemctl stop apparmor.service && systemctl disable apparmor.service
  • 关闭SELinux(centos):sed -i s#SELINUX=enforcing#SELINUX=disabled# /etc/selinux/config不关下不了文件
  • 关闭swap分区(必须):swapoff -a && sed -ri 's/.*swap.*/#&/' /etc/fstab
  • 同步时间:安装sudo apt install ntpdate -y校时ntpdate ntp.ntsc.ac.cn

2、克隆新的虚拟机,我们克隆三个

  • master-node(worker1)
  • worker-node(worker2、worker3)

3、可以看到克隆的虚拟机和被克隆的虚拟机ip不同,因为dhcp默认自动分配了,如果配置过静态ip,修改ip即可。把三台主机的ip记住,经常使用!

4、使用你喜欢的工具远程连接上三台虚拟机,用你喜欢的方式给它们区分好

5、修改主机名,克隆的虚拟机主机名都是一样的,不改的话k8s显示一样的名字无法区分,分别在三台主机上设置,还记得吗,主机/虚拟机就是Node节点,在这一步记得每个虚拟机拍个快照,装错了方便修改

复制代码
#worker1 master-node
hostnamectl set-hostname node1
#worker2 worker-node
hostnamectl set-hostname node2
#worker3 worker-node
hostnamectl set-hostname node3
#查看主机名
hostname

以下操作多台服务器命令一样,在windterm按下alt+w->alt+h水平分屏,按下alt+w->alt+v垂直分屏,然后ctrl+shift+m添加到频道就可以同步多窗口输入了

6、安装containerd,喜欢Docker安装docker也可以,但是对于k8s来说,docker有的功能k8s也有,这里直接用官方建议的containerd

下载对应系统最新的containerdgithub

要是觉得三个一起下的慢就在本机下载了上传到三台服务器

复制代码
#三台虚拟机下载containerd
wget https://github.com/containerd/containerd/releases/download/v1.7.18/containerd-1.7.18-linux-amd64.tar.gz
#解压到/usr/local目录
tar Cxzvf /usr/local containerd-1.7.18-linux-amd64.tar.gz
#检查
containerd -v

containerd默认不会自带runc(真正创建容器的程序),以及cni网络插件(容器之间网络通信)

runc

|cni

复制代码
#如法炮制,到上面链接下载runc、cni
wget https://github.com/opencontainers/runc/releases/download/v1.1.13/runc.amd64
wget https://github.com/containernetworking/plugins/releases/download/v1.5.1/cni-plugins-linux-amd64-v1.5.1.tgz
#安装runc.amd64
install -m 755 runc.amd64 /usr/local/sbin/runc
#安装cni,包名换成自己下的
mkdir -p /opt/cni/bin
tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.5.1.tgz
#检查
runc -v

配置systemd

复制代码
#新建文件
vim /usr/local/lib/systemd/system/containerd.service
#把文件内容复制粘贴到新文件
https://raw.githubusercontent.com/containerd/containerd/main/containerd.service

重新加载

复制代码
systemctl daemon-reload
systemctl enable --now containerd

7、配置containerd

复制代码
#新建文件夹
mkdir -p /etc/containerd
#生成配置文件
containerd config default > /etc/containerd/config.toml
#查看配置文件
cat /etc/containerd/config.toml

配置cgroup,vim /etc/containerd/config.toml

复制代码
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
  ...
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
    SystemdCgroup = true

:set nu显示行号,在139行改为true,或者输入/runc.options定位(需要装vim,vi太难用了)

设置开机自启并启动

复制代码
systemctl enable containerd && systemctl start containerd && systemctl status containerd

重启

复制代码
sudo systemctl restart containerd

配置沙盒镜像,vim /etc/containerd/config.toml,你也可以改成国内的(2024/6/25无法使用)

复制代码
[plugins."io.containerd.grpc.v1.cri"]
  sandbox_image = "registry.k8s.io/pause:3.2"

复制代码
registry.aliyuncs.com/google_containers/pause:3.9

设置镜像加速器,设置自己的加速地址,阿里

如果使用cri-dockerd

复制代码
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
          endpoint = ["https://ci8e67uo.mirror.aliyuncs.com"]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."k8s.gcr.io"]
          endpoint = ["https://registry.cn-hangzhou.aliyuncs.com/google_containers"]

重新加载

复制代码
systemctl daemon-reload && systemctl restart containerd

8、配置网络

修改hosts,改成自己对应的ip,实际生产环境使用DNS服务器

复制代码
cat >> /etc/hosts<<EOF
192.168.122.162 node1
192.168.122.191 node2
192.168.122.157 node3
EOF

ping node1ping node2ping node3检查一下

修改内核参数

复制代码
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

验证

复制代码
#重启
sudo sysctl --system
#验证
sysctl net.ipv4.ip_forward

加载overlay网络驱动、br_netfilter启用网络过滤规则

复制代码
modprobe overlay
modprobe br_netfilter

重启生效

复制代码
init 6或者reboot

9、添加k8s源

Debian/Ununtu
添加国内下载源(二选一)
复制代码
#更新并安装apt-transport-https
apt-get update && apt-get install -y apt-transport-https
#添加阿里镜像要多少版本就改v1.30
curl -fsSL https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.30/deb/Release.key |
    gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
#添加
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.30/deb/ /" |
    tee /etc/apt/sources.list.d/kubernetes.list
#更新
apt-get update
添加官方下载源(二选一)

导入 gpg key

复制代码
apt-get update && apt-get install -y apt-transport-https

sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg

新建文件

复制代码
vim /etc/apt/sources.list.d/kubernetes.list
#添加一下内容
deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://mirrors.tuna.tsinghua.edu.cn/kubernetes/apt kubernetes-xenial main
RHEL/CentOS

新建文件

复制代码
vim /etc/yum.repos.d/kubernetes.repo
#添加内容
[kubernetes]
name=kubernetes
baseurl=https://mirrors.tuna.tsinghua.edu.cn/kubernetes/yum/repos/kubernetes-el7-$basearch
enabled=1

安装k8s

包管理器安装k8s(推荐)

复制代码
# Debian/Ununtu
apt install -y kubelet kubeadm kubectl
# Centos
yum install -y kubelet kubeadm kubectl

源码包安装k8s(大多数linux适用,需要解决网络问题)

1、安装cni(前面已安装过就跳过)
复制代码
#下载包
wget https://github.com/containernetworking/plugins/releases/download/v1.5.1/cni-plugins-linux-amd64-v1.5.1.tgz
#安装cni,包名换成自己下的
mkdir -p /opt/cni/bin
tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.5.1.tgz
2、安装 crictl(kubeadm/kubelet 容器运行时接口(CRI)所需)

github

复制代码
#新建目录(估计不用,一般有这个目录)
mkdir -p /usr/local/bin
#下载包
wget https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.30.0/crictl-v1.30.0-linux-amd64.tar.gz
#安装
tar zxvf crictl-v1.30.0-linux-amd64.tar.gz -C /usr/local/bin
#验证
crictl -v
#清理包
rm -f crictl-v1.30.0-linux-amd64.tar.gz
  • kubeadm:用来初始化集群的指令
  • kubelet:在集群中的每个节点上用来启动 Pod 和容器等
  • kubectl:用来与集群通信的命令行工具
3、安装kubeadm,kubelet

查看ip

添加解析的ip到hosts,vim /etc/hosts

复制代码
20.205.243.166  raw.githubusercontent.com

#进入目录
cd /usr/local/bin
#下载最新版kubeadm,kubelet
sudo curl -L --remote-name-all "https://dl.k8s.io/release/$(curl -sSL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/{kubeadm,kubelet}"
#授权
sudo chmod +x {kubeadm,kubelet}
#下载kubelet.service
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/v0.16.2/cmd/krel/templates/latest/kubelet/kubelet.service" | sed "s:/usr/bin:/usr/local/bin:g" | sudo tee /usr/lib/systemd/system/kubelet.service
#创建kubelet系统服务目录
sudo mkdir -p /usr/lib/systemd/system/kubelet.service.d
配置kubeadm
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/v0.16.2/cmd/krel/templates/latest/kubeadm/10-kubeadm.conf" | sed "s:/usr/bin:/usr/local/bin:g" | sudo tee /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf
4、安装kubectl
复制代码
#下载
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
#安装
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
#验证
kubectl version --client

集群配置

设置kubelet开机启动并自启

复制代码
systemctl enable --now kubelet && systemctl start kubelet && systemctl status kubelet

master-node初始化

在线拉取

复制代码
kubeadm config images pull

生成默认配置文件

生成默认配置文件

复制代码
kubeadm config print init-defaults > kubeadm.yml
#编辑
vim kubeadm.yml
  • advertiseAddress:master-node的ip
  • imageRepository:改成阿里镜像源
  • nodeRegistration.name:改为节点名,即master
  • networking.serviceSubnet:service网络ip范围

修改以下三处,国内镜像地址目前用不了(2024/6/25)

拉取镜像,拉不了先解决这个问题

复制代码
# 查看所需的镜像
kubeadm config images list --config kubeadm.yml
#拉取镜像
for img in `kubeadm config images list --config kubeadm.yml` ; do ctr i pull $img ; done

离线导入(历经两天的折磨,推荐此方法,要不就出国拉镜像)

复制代码
#查看需要的镜像
kubeadm config images list
#在能访问外网的电脑,拉取镜像到本地
docker pull 镜像
#将本地镜像导出为tar包不指定版本默认最新 
docker save -o front.tar 镜像
#上传服务器加载镜像
sudo ctr -n k8s.io images import front.tar
#查看镜像
sudo ctr -n k8s.io images ls

查看k8s本地镜像

复制代码
sudo ctr -n k8s.io images ls

只在node1也就是worker1初始化就可以了,这个节点当作master-node也就是control-plan

复制代码
kubeadm init \
  --kubernetes-version 指定版本 \
  --apiserver-advertise-address=master-node的ip \
  --service-cidr=service网络ip,用于分配ip \
  --pod-network-cidr=pod网络内部的ip,随便设置 \
  --image-repository 镜像地址 

先重启

复制代码
systemctl restart containerd

比如我的,执行后会下依赖

复制代码
kubeadm init \
  --apiserver-advertise-address=192.168.122.162 \
  --pod-network-cidr=10.200.0.0/16

初始化失败执行kubeadm reset

在master-node,普通用户执行,第二个框是root用户的操作,一般生产环境root不会随便给你,所以就提权执行

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

然后记住最后一个框的token内容,在你需要加入的节点执行,这里在worker1和worker2执行

复制代码
kubeadm join 192.168.122.162:6443 --token 6kcxpv.cdad9rdrtgx9jcya \
        --discovery-token-ca-cert-hash sha256:f0dcc8a0b5a0f6edacd2cc4ccbdc810d147a91efc788b1e86d5c95adf6adc1f5

token24消失失效,后续添加新节点,在master-node执行以下命令新建token

复制代码
kubeadm token create --print-join-command

master-node获取节点,可以看到worker-node(node2、node3)也被加进来了

复制代码
kubectl get nodes

master-node安装dns插件

在master-node创建配置

复制代码
vim kube-flannel.yml

配置中的Network改为自己设置的pod-network-cidr的ip

复制代码
kind: Namespace
apiVersion: v1
metadata:
  name: kube-flannel
  labels:
    k8s-app: flannel
    pod-security.kubernetes.io/enforce: privileged
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  labels:
    k8s-app: flannel
  name: flannel
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
- apiGroups:
  - ""
  resources:
  - nodes
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - nodes/status
  verbs:
  - patch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  labels:
    k8s-app: flannel
  name: flannel
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: flannel
subjects:
- kind: ServiceAccount
  name: flannel
  namespace: kube-flannel
---
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: flannel
  name: flannel
  namespace: kube-flannel
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: kube-flannel-cfg
  namespace: kube-flannel
  labels:
    tier: node
    k8s-app: flannel
    app: flannel
data:
  cni-conf.json: |
    {
      "name": "cbr0",
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "flannel",
          "delegate": {
            "hairpinMode": true,
            "isDefaultGateway": true
          }
        },
        {
          "type": "portmap",
          "capabilities": {
            "portMappings": true
          }
        }
      ]
    }
  net-conf.json: |
    {
      "Network": "10.200.0.0/16",
      "EnableNFTables": false,
      "Backend": {
        "Type": "vxlan"
      }
    }
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-flannel-ds
  namespace: kube-flannel
  labels:
    tier: node
    app: flannel
    k8s-app: flannel
spec:
  selector:
    matchLabels:
      app: flannel
  template:
    metadata:
      labels:
        tier: node
        app: flannel
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: kubernetes.io/os
                operator: In
                values:
                - linux
      hostNetwork: true
      priorityClassName: system-node-critical
      tolerations:
      - operator: Exists
        effect: NoSchedule
      serviceAccountName: flannel
      initContainers:
      - name: install-cni-plugin
        image: docker.io/flannel/flannel-cni-plugin:v1.4.1-flannel1
        command:
        - cp
        args:
        - -f
        - /flannel
        - /opt/cni/bin/flannel
        volumeMounts:
        - name: cni-plugin
          mountPath: /opt/cni/bin
      - name: install-cni
        image: docker.io/flannel/flannel:v0.25.4
        command:
        - cp
        args:
        - -f
        - /etc/kube-flannel/cni-conf.json
        - /etc/cni/net.d/10-flannel.conflist
        volumeMounts:
        - name: cni
          mountPath: /etc/cni/net.d
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      containers:
      - name: kube-flannel
        image: docker.io/flannel/flannel:v0.25.4
        command:
        - /opt/bin/flanneld
        args:
        - --ip-masq
        - --kube-subnet-mgr
        resources:
          requests:
            cpu: "100m"
            memory: "50Mi"
        securityContext:
          privileged: false
          capabilities:
            add: ["NET_ADMIN", "NET_RAW"]
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: EVENT_QUEUE_DEPTH
          value: "5000"
        volumeMounts:
        - name: run
          mountPath: /run/flannel
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
        - name: xtables-lock
          mountPath: /run/xtables.lock
      volumes:
      - name: run
        hostPath:
          path: /run/flannel
      - name: cni-plugin
        hostPath:
          path: /opt/cni/bin
      - name: cni
        hostPath:
          path: /etc/cni/net.d
      - name: flannel-cfg
        configMap:
          name: kube-flannel-cfg
      - name: xtables-lock
        hostPath:
          path: /run/xtables.lock
          type: FileOrCreate

应用配置

复制代码
kubectl apply -f kube-flannel.yml

新建一个窗口监控,执行watch -n 1 -d kubectl get pods -A,每秒刷新一次数据

相关推荐
chuanauc7 小时前
Kubernets K8s 学习
java·学习·kubernetes
小张是铁粉7 小时前
docker学习二天之镜像操作与容器操作
学习·docker·容器
烟雨书信8 小时前
Docker文件操作、数据卷、挂载
运维·docker·容器
IT成长日记8 小时前
【Docker基础】Docker数据卷管理:docker volume prune及其参数详解
运维·docker·容器·volume·prune
这儿有一堆花8 小时前
Docker编译环境搭建与开发实战指南
运维·docker·容器
LuckyLay8 小时前
Compose 高级用法详解——AI教你学Docker
运维·docker·容器
Uluoyu8 小时前
redisSearch docker安装
运维·redis·docker·容器
IT成长日记12 小时前
【Docker基础】Docker数据持久化与卷(Volume)介绍
运维·docker·容器·数据持久化·volume·
疯子的模样16 小时前
Docker 安装 Neo4j 保姆级教程
docker·容器·neo4j
虚伪的空想家17 小时前
rook-ceph配置dashboard代理无法访问
ceph·云原生·k8s·存储·rook