# K8s介绍 [官网](https://kubernetes.io/) 用官网的话术介绍K8s: Kubernetes(K8s),是用于自动部署、扩容、缩容和管理容器化应用程序的开源系统。它将组成应用程序的容器组合成逻辑单元,以便于管理和服务发现。Kubernetes源自google 15年生产环境的运维经验,同时凝聚了社区最佳创意和实践。 简单讲,K8s就是一个生产级别的容器编排平台和集群管理系统,不仅能够创建、调度容器,还能够监控、管理服务器,它凝聚了 Google 等大公司和 开源社区的集体智慧,从而让中小型公司也可以具备轻松运维海量计算节点——也就是“云计算”的能力。 ## K8s核心组件 1.Master节点 API Server Apiserver是整个K8s系统的唯一入口,以RESTful API提供接口服务,并且加上了验证、授权等功能,所有其他组件都只能和它直接通信,可以说是 K8s里的联络员。 Controller-manager 控制中心,负责维护容器和节点等资源的状态,实现故障检测、服务迁移、应用伸缩等功能。 因为节点状态和Pod信息都存储在etcd里,所以要通过apiserver获得信息,才能够实现对资源的各种操作。 Scheduler 调度器,负责容器的编排工作,检查节点的资源状态,把Pod调度到最适合的节点上运行。 Etcd 是一个高可用的分布式Key-Value数据库,用来持久化存储系统里的各种资源对象和状态。 注意它只与apiserver有直接联系,也就是说任何其他组件想要读写etcd里的数据都必须经过apiserver。 2.Node节点 Kubelet 是Master在Node节点上的Agent,通过指挥容器引擎实现管理本机运⾏容器,⽐如创建容器、Pod挂载数据卷、下载secret、获取容器和节点状态等⼯作。 Kube-proxy 在Node节点上实现Pod⽹络代理,维护⽹络规则和四层负载均衡⼯作。 Container-runtime 容器运行时,即容器引擎,例如docker、containerd、podman。是容器和镜像的实际使用者,在 kubelet 的指挥下创建容器,管理Pod的生命周期。 # K8s单机板搭建 基于containerd ## 准备工作 关闭防火墙firewalld ``` systemctl stop firewalld systemctl disable firewalld ``` 关闭selinux ``` sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config setenforce 0 ``` 设置主机名 ``` hostnamectl set-hostname k8s-master hostnamectl set-hostname k8s-node1 hostnamectl set-hostname k8s-node2 ``` 设置/etc/hosts ``` cat /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.159.105 k8s-master 192.168.159.106 k8s-node01 192.168.159.107 k8s-node02 ``` 关闭swap ``` swapoff -a 永久关闭,vi /etc/fstab 注释掉swap那行 ``` 将桥接的ipv4流量传递到iptables链 ``` modprobe br_netfilter ##生成bridge相关内核参数 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 sysctl --system # 生效 ``` 时间同步 ``` yum install -y chrony; systemctl start chronyd; systemctl enable chronyd ``` ## 安装containerd 安装yum-utils工具 ``` yum install -y yum-utils ``` 配置Docker官方的yum仓库,如果做过,可以跳过 ``` yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo ``` 安装containerd ``` yum install containerd.io -y ``` 启动服务 ``` systemctl enable containerd systemctl start containerd ``` 生成默认配置 ``` containerd config default > /etc/containerd/config.toml ``` 修改配置 ``` vi /etc/containerd/config.toml sandbox_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.8" # 修改为阿里云镜像地址 SystemdCgroup = true # 使用systemd cgroup ``` 重启containerd服务 ``` systemctl restart containerd ``` ## 安装kubeadm、kubelet和kubectl ```bash 由于官方k8s源在google,国内无法访问,这里使用阿里云yum源 # 执行配置k8s阿里云源 cat < /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF # 安装kubeadm和kubelet,启动kubelet yum install -y kubelet-1.25.4 kubeadm-1.25.4 kubectl-1.25.4; systemctl start kubelet.service; systemctl enable kubelet.service # 设置crictl连接 containerd crictl config --set runtime-endpoint=unix:///run/containerd/containerd.sock ``` ## 初始化集群 ```bash kubeadm init --image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers --apiserver-advertise-address=192.168.1.132 --kubernetes-version=v1.25.4 --service-cidr=10.15.0.0/16 --pod-network-cidr=10.18.0.0/16 # 创建目录 mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config # 获取节点信息 kubectl get node kubectl get pod --all-namespaces ``` ## 安装calico网络 ```bash curl https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml -O ``` > 注意:下载需要外网。 > 可手动导入文件(复制粘贴) [calico.yaml](https://gitee.com/wynne217/read-the-docs/blob/master/source/%E6%9C%8D%E5%8A%A1/K8S/calico.yaml) 下载完后还需要修改里面定义 Pod 网络(CALICO_IPV4POOL_CIDR),与前面 kubeadm init 的 --podnetwork-cidr 指定的一样 ```bash vim calico.yaml # - name: CALICO_IPV4POOL_CIDR # value: "192.168.0.0/16" #取消注释,修改为如下: - name: CALICO_IPV4POOL_CIDR value: "10.18.0.0/16" # 部署 kubectl apply -f calico.yaml # 查看 kubectl get pods -n kube-system ``` ## 安装dashboard(可视化管理集群) ```bash # 下载yaml文件 curl -O https://raw.githubusercontent.com/kubernetes/dashboard/v2.5.1/aio/deploy/recommended.yaml ``` > 注意:下载需要外网。 > 可手动导入文件(复制粘贴) [recommended.yaml](https://gitee.com/wynne217/read-the-docs/blob/master/source/%E6%9C%8D%E5%8A%A1/K8S/recommended.yaml) ```bash # 修改配置文件 vi recommended.yaml #修改内如 kind: Service apiVersion: v1 metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kubernetes-dashboard ##这是第38行 spec: type: NodePort ###添加这行 ports: - port: 443 targetPort: 8443 nodePort: 30002 ###添加这行 selector: k8s-app: kubernetes-dashboard # 创建pod kubectl apply -f recommended.yaml # 查看 kubectl get pod -n kubernetes-dashboard kubectl get svc -n kubernetes-dashboard ``` > 注意: 如果`kubectl get pod -n kubernetes-dashboard`查看的状态一直是`pendding`,说明有问题: > ```bash > # 查看原因 > kubectl describe pod kubernetes-dashboard -n kubernetes-dashboard > > Warning FailedScheduling 4m31s (x18 over 89m) default-scheduler 0/1 nodes are available: 1 node(s) had untolerated taint {node-role.kubernetes.io/control-plane: }. preemption: 0/1 nodes are available: 1 Preemption is not helpful for scheduling. > > # 这是因为master节点上不允许该pod部署,需要解除限制: > kubectl taint nodes --all node-role.kubernetes.io/control-plane- > ``` 浏览器访问:https://192.168.1.132:30002 > 注意:chrome浏览器访问有时候会出现“该网站发回了异常的错误凭据。这可能是因为有攻击者在试图冒充”。 > 解决:空白地方输入: thisisunsafe > 或者更换浏览器,如:火狐浏览器 创建 service account 并绑定默认 cluster-admin 管理员集群⻆色: ```bash # 创建用户 kubectl create serviceaccount dashboard-admin -n kubernetes-dashboard # 用户授权 kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:dashboard-admin # 获取用户Token kubectl create token dashboard-admin -n kubernetes-dashboard ``` 使用输出的token登陆Dashboard ## (Containerd)crictl命令用法 ### 镜像相关 | 镜像相关功能 | Docker | Containerd | |----|----|----| | 镜像拉取 | docker pull | crictl pull | | 镜像推送 | docker push | 无,例如buildk | | 镜像删除 | docker rmi | crictl rmi | | 镜像列表 | docker images | crictl images | | 镜像搜索 | docker search | crictl search | | 镜像详情 | docker inspect IMAGE-ID | crictl inspect IMAGE-ID | | 镜像加载 | docker load | crictl load | | 镜像导出 | docker save | crictl save | | 镜像导入 | docker load | crictl load | ### 容器相关 | 容器相关功能 | Docker | Containerd | |----|----|----| | 显示容器列表 | docker ps | crictl ps | | 创建容器 | docker create | crictl create | | 启动容器 | docker start | crictl start | | 停止容器 | docker stop | crictl stop | |删除容器 | docker rm | crictl rm | |容器详情 | docker inspect | crictl inspect | |附加容器 | docker attach | crictl attach | |执行命令 | docker exec | crictl exec | |查看日志 | docker logs | crictl logs | |查看容器资源 | docker stats | crictl stats | ### pod相关 | pod相关功能 | Docker | Containerd | |----|----|----| |显示pod列表 | 无 | crictl pods | |查看pod详情 | 无 | crictl inspectp | |运行pod | 无 | crictl runp | |停止pod | 无 | crictl stopp | ## 在K8s里快速部署一个应用 ```bash # 创建deployment #deploymnet名字为testdp 镜像为nginx:1.23.2 kubectl create deployment testdp --image=nginx:1.23.2 # 查看deployment kubectl get deployment # 查看pod kubectl get pods # 查看pod详情 kubectl describe pod testdp-786fdb4647-pbm7b # 创建service,暴漏pod端口到node节点上 kubectl expose deployment testdp --port=80 --type=NodePort --target-port=80 --name=testsvc # 查看service #可以看到暴漏端口为一个大于30000的随机端口,浏览器里访问 192.168.0.14:31693 kubectl get svc ``` ## K8s主要资源罗列 ### pod K8s里最小部署单元,是整个K8s最核心的资源对象,它是一组容器的集合,可以只是单个容器,也可以多个容器。 pod相关操作命令: |命令|说明| |----|----| |kubectl run podname --image=镜像|启动容器| |kubectl get pods|查看pod列表| |kubectl describe pod podname|查看pod详情| |kubectl exec -it podname -- /bin/bash|进入pod容器| |kubectl delete pod podname|删除pod| |kubectl logs podname|查看pod日志| ### Deployment 比pod更高一层及的资源对象,它提供了一种对pod的管理方式,它可以很方便地实现pod的扩容、缩容、升级、回滚。 Deployment相关操作命令: |命令|说明| |----|----| |kubectl create deployment dpname --image=镜像|创建deployment| |kubectl get deployment|查看deployment列表| |kubectl describe deployment dpname|查看deployment详情| |kubectl delete deployment dpname|删除deployment| |kubectl scale deployment dpname --replicas=n|扩容deployment| |kubectl rollout undo deployment dpname|回滚deployment| ### Service 为pod提供负载均衡、对外统一访问入口,用户访问具体pod时,不需要关心pod地址,而只需要通过这个固定的Service地址来访问 Service相关操作命令: |命令|说明| |----|----| |kubectl expose deployment dpname --port=service端口 --type=NodePort --target-port=pod监听端口 --name=svcname|创建service,同时定义暴漏port| |kubectl get svc|查看service列表| |kubectl describe svc svcname|查看service详情| |kubectl delete svc svcname|删除service| service 的类型: - ClusterIP:提供一个集群内部的虚拟IP以供Pod访问(service默认类型) - NodePort:在每个Node上打开一个端口以供外部访问,Kubernetes将会在每个Node上打开一个端口并且每个kocde的端口都是一样的,通过NodeIp:NodePort的方式Kubernetes集群外部的程序可以访问Service。 注:每个端口只能是一种服务,端口范围只能是 30000-32767。 - LoadBalancer:通过外部的负载均衡器来访问,通常在云平台部署LoadBalancer还需要额外的费用。 ### Label Label是一个键值对,其中键和值都由用户自定义,Label可以附加在各种资源对象上,如Node、Pod、Service、Deployment等。 一个资源对象可以定义多个Label,同一个Label也可以被添加到任意数量的资源对象上。Label可以在定义对象时定义,也可以在对象创建完后动态添加或删除。 ### Volume Volume是pod中能够被多个容器访问的共享目录,kubernetes中的volume和docker中的volume不一样,主要有以下几个方面: - kubernetes的volume定义在pod上,然后被一个pod里的多个容器挂载到具体的目录下 - kubernetes的volume与pod生命周期相同,但与容器的生命周期没关系,当容器终止或者重启时,volume中的数据并不会丢失 - kubernetes支持多种类型的volume,如glusterfs,ceph等先进的分布式文件系统 ### PV(persistent volume) PV可以理解成kubernetes集群中某个网络存储中对应的一块存储,它与volume类似,但有如下区别: - PV只能是网络存储,不属于任何Node,但可以在每个Node上访问到 - PV并不是定义在pod上,而是独立于pod之外定义 - PV目前只有几种类型:GCE Persistent Disk、NFS、RBD、iSCSCI、AWS ElasticBlockStore、GlusterFS ### PVC(PersistentVolumeClaim) 如果某个pod想申请某种条件的PV,首先需要定义一个PVC对象 ### NameSpace 当kubernetes集群中存在多租户的情况下,就需要有一种机制实现每个租户的资源隔离。而namespace的目的就是为了实现资源隔离。 Namespace相关操作命令: |命令|说明| |----|----| |kubectl create namespace nsname|创建一个命名空间| |kubectl get namespaces|查看所有命名空间。
default为默认命名空间,
kube-system:k8s系统外部的命名空间,
kube-public:公开的命名空间,谁都可以访问,
kube-node-lease:K8s 内部命名空间| |kubectl -n nsname|查看资源时指定namespace| |kubectl delete namespace nsname|删除一个命名空间|