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)

image.png

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

image.png

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

image.png

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添加到频道就可以同步多窗口输入了

image.png

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

下载对应系统最新的containerdgithub

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

#三台虚拟机下载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太难用了)
image.png
设置开机自启并启动

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

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

image.png
如果使用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检查一下
image.png

修改内核参数

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)

image.png

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

# 查看所需的镜像
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

image.png

在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

image.png

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,每秒刷新一次数据

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐