1、k8s 概念
1.1、基本概念
Kubernetes 是谷歌开源的基于容器技术的分布式架构方案,用于管理容器化的工作负载和服务,促进声明式配置和自动化。
Kubernetes 的功能有
- 服务发现和负载均衡:使用 ip 地址或 dns 名称来暴露容器,并实现负载均衡分配网络流量
- 部署和回滚:通过配置文件描述容器的期望状态,支持回滚到指定部署版本
- 弹性伸缩:可根据指标配置自动伸缩策略,以应对突发流量
- 容器配额管理:允许为每个容器指定所需的CPU和内存
- 故障发现和自我修复:监控容器的运行状态,并尝试重启替换状态异常的容器
- 密钥和配置管理:secret 和 configMap,两种资源来分别管理密钥信息和配置信息
- 支持多种数据卷类型:例如:本地存储、公有云提供商、分布式存储系统等
1.2、基本术语
Pod
pod:最小可部署单元,调度的最小基本单位,代表集群上正在运行的一个进程。
k8s 为每个 pod 分配唯一的 pod ip,每个 pod 有一个 pause 容器( 根容器)。pod 内的多个容器,共享 pause 容器的 ip 和 volume;同时 pause 容器的状态代表整个 pod 的状态。
Label
label:kv 键值对,通过给指定资源对象绑定 label 来实现对资源对象的分组管理。
通过 label 为资源对象贴上相对应的标签,然后通过 Label Selector(标签选择器)查询和筛选拥有某些 label 的资源对象。
例如:
# 标签选择器 selector: # 1、标签匹配 matchLabels: app: myweb # 选择标签 key-app,value-myweb 资源 # 2、表达式匹配 matchExpressions: # 选择标签 key-tier, value-in (frontend, backend) - {key: tier, operator: In, values: [frontend,backend]} # 或使用以下写法,操作:In, NotIn, Exists and DoesNotExist - key: tier operator: In values: ["frontend","backend"]
RC
Repliacation Controller,RC 副本控制器。保持 pod 的副本数量与预期数量一致。deployment 内部包含该功能,所以不推荐使用。
RS
Replica Set,RS 副本控制器。RC 的升级版本,区别在于:
- RC 的 Label Selector 仅支持基于等式的表达式,RS 的 Label Selector 可以支持基于集合的表达式。
- 在线编辑后,RS 自动更新 pod,RC 不会自动更新现有 pod。
Deployment
deployment:部署,副本控制器,用于更好的解决 pod 的部署、升级、回滚等问题。内部会自动创建 RS 用于pod 的副本控制。
deployment 相较于 RC/RS 具有以下优势:
- deployment 资源对象会自动创建 RS 资源对象来完成部署,对 deployment 的修改并发布会产生新的 RS 资源对象,为新的发布版本服务。
- 支持查看部署进度,以确定部署操作是否完成
- 更新 deployment,会触发部署从而更新 pod
- 支持 pause | resume 操作,暂停后修改不会触发发布,恢复后发布新的 deployment
- 支持回滚操作
- 支持重新启动操作,触发 pod 更新。
- 自动清理不需要的 RS
StatefulSet
StatefulSet:管理有状态应用的 pod,例如 Kafka 集群、Mysql 集群、MongoDB集群等。与无状态的服务不同的是:无论怎么调度,每个 pod 都有一个永久不变的ID。
面向无状态的应用:RC、Deployment、DaemonSet、Job等。
DaemonSet
副本控制器,每个节点只运行一个 pod 副本。区分 deployment 多副本。
应用:每个节点上运行集群守护进程、日志收集守护进程和监控守护进程。
Service
Service:微服务,将运行在一组 pods 上的应用程序公开为网络服务。通过 service 资源对象定义一个 service 的访问入口地址 。前端应用通过访问这个入口,从而访问其背后的一组有 pod 副本组成的集群实例。service 所针对的目标 pods 集合通常通过 label selector来确定。service 一旦被定义,就被分配了一个不可变更的 cluster ip,在整个 service的生命周期内,该 ip 地址都不会发生改变。
Namespace
namespace:命名空间,提供资源隔离。通过命名空间可以将同一个集群中的资源划分为相互隔离的组。同一命名空间下的资源名称必须唯一,但是不同命名空间下的资源名称可以一样。
其他概念
- Resource:k8s 是一个高度自动化的资源控制系统,大部分概念都可以看作资源对象。
- HPA:Horizontal Pod Autoscale,pod 横向自动伸缩。根据目标 pod 的负载变化,针对性调整目标 pod 的副本数量。
- Job:工作任务
- Volume:数据卷
- ConfigMap:管理非机密的配置项的数据
- Secret:管理密钥数据
2、k8s 架构
2.1、k8s 节点
k8s 集群由 master 节点和 node 节点组成
- master 节点:集群控制节点,为集群做出全局决策,不运行任何工作负载。
- node 节点:集群工作 worker 节点
2.2、k8s 组件
master 节点运行 master 组件 + node 组件,node 节点只运行 node 组件。
2.2.1、master 组件
- kube-controller-manager:负责运行控制器进程。包括节点控制器、任务控制器、端点控制器、副本控制器、服务账户和令牌控制器。
- kube-scheduler:负责监视新创建的、未指定运行节点的 pod,并选择节点来运行 pod。
- kube-apiserver:负责公开 k8s API,处理接受请求的工作,支持高可用部署。
- etcd:兼顾一致性与高可用的键值数据库,用来保存 k8s 集群数据。
2.2.2、node 组件
- kubelet:节点代理,监视分配给节点的 pod
- kube-proxy:网络代理,维护节点上的网络规则,允许 pod 网络通信
- docker:运行容器,例:docker engine + cri-dockerd
3、k8s 集群安装配置
3.1、docker
首先安装并运行 docker。参考文章:Docker: 容器与镜像
在 docker 运行时安装 cri-dockerd
cri-dockerd 安装
# 下载 wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.2.6/cri-dockerd-0.2.6.amd64.tgz # 解压到 /tmp 目录 tar -zxvf cri-dockerd-0.2.6.amd64.tgz -C /tmp # 安装 sudo cp /tmp/cri-dockerd/cri-dockerd /usr/bin/
cri-dockerd 配置
# 获取源码 git clone https://github.com/Mirantis/cri-dockerd.git # 将源码中systemd配置文件拷贝到相应目录 sudo cp cri-dockerd/packaging/systemd/* /etc/systemd/system/ # 配置 sudo vim /etc/systemd/system/cri-docker.service # 在 [Service] ExecStart 配置项添加: # --network-plugin 自定义容器网络 # --pod-infra-container-image 根容器镜像 [Service] ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd:// --network-plugin=cni --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.7
启动服务
# 重新加载配置 sudo systemctl daemon-reload # 设置为开机自启动 sudo systemctl enable cri-docker # 启动服务 sudo systemctl start cri-docker # 检查服务状态 sudo systemctl status cri-docker
3.2、主机环境调整
修改节点 docker 的 cgroup driver
由于 k8s 中 kubelet 组件默认使用的 cgroupdriver 为 systemd,所以将 docker 的 cgroup driver 为 systemd。
sudo vim /etc/docker/daemon.json # 增加配置内容 "exec-opts": [ "native.cgroupdriver=systemd" ] # 重新加载配置并重启 docker 服务 sudo systemctl daemon-reload sudo systemctl restart docker
关闭防火墙
sudo systemctl stop firewalld sudo systemctl disable firewalld
禁用 Selinux
# 查看 selinux 状态 sudo apt install selinux-utils getenforce # 禁用 sudo setenforce 0
禁用 swap
# 禁用交换区 sudo swapoff -a # 打开文件注释交换区定义 sudo vim /etc/fstab # /swap.img none swap sw 0 0 # 查看交换区 free # 显示 交换: 0 0 0
修改主机名
# 1、增加主机名与本机ip映射 sudo vim /etc/hosts # 2、修改系统主机名 # 修改主机名 sudo hostnamectl set-hostname k8s-master1 # 查看主机名 hostname
3.3、安装 kube 工具
# 1、更新包管理索引 sudo apt-get update # 支持 https 访问 sudo apt-get install -y apt-transport-https ca-certificates curl # 2、下载 gpg 秘钥 sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg # 3、设置 k8s 镜像源 echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list # 查看设置好的镜像源 ls /etc/apt/sources.list.d/ # 4、更新apt软件索引,并查看相关软件的可用版本 sudo apt-get update apt-cache madison kubelet kubeadm kubectl # 5、安装指定版本 # sudo apt-get install -y kubelet=<VERSION_STRING> kubeadm=<VERSION_STRING> kubectl=<VERSION_STRING> sudo apt-get install -y kubelet=1.24.1-00 kubeadm=1.24.1-00 kubectl=1.24.1-00 # 6、锁定软件版本(防止自动升级) sudo apt-mark hold kubelet kubeadm kubectl # 7、检查kubelet状态 systemctl status kubelet # 卸载 sudo apt-get remove kubelet kubectl kubeadm
3.4、Master 节点初始化
生成默认配置文件
kubeadm config print init-defaults > init.default.yaml
修改配置文件
vim init.default.yaml
# 1、修改节点IP地址 localAPIEndpoint.advertiseAddress: 192.168.88.132 # 2、修改套接字 nodeRegistration.criSocket: unix:///var/run/cri-dockerd.sock # 3、修改节点名称 nodeRegistration.name: k8s-master1 # 4、修改镜像仓库地址为国内开源镜像库 imageRepository: registry.aliyuncs.com/google_containers # 5、修改版本号 kubernetesVersion: 1.24.1 # 6、增加 podSubnet。安装 flannel 网络插件,必须在集群初始化时指定 pod 地址 # 10.244.0.0/16 为 flannel 组件 podSubnet 默认值,集群与组件配置保持一致。 networking.podSubnet: 10.244.0.0/16
拉取相关镜像
sudo kubeadm config images pull --config=init.default.yaml
初始化集群
# 通过配置文件初始化集群,建议选择配置文件初始化 sudo kubeadm init --config=init.default.yaml
初始化成功,返回提示信息:根据当前用户的类型,二选其一,执行相应的操作
普通用户执行
mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
root 用户执行
export KUBECONFIG=/etc/kubernetes/admin.conf source /etc/profile
查看集群状态
# 查看 pod kubectl get pod -A # 查看节点 kubectl get node # 查看所有组件 kubectl get cs
添加 pod 网络组件
下载 flannel 网络组件定义文件 到本地,也可以将文件内容拷贝到本地新建的 flannel.yml 文件
--- kind: Namespace apiVersion: v1 metadata: name: kube-flannel labels: pod-security.kubernetes.io/enforce: privileged --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: flannel rules: - apiGroups: - "" resources: - pods verbs: - get - apiGroups: - "" resources: - nodes verbs: - get - list - watch - apiGroups: - "" resources: - nodes/status verbs: - patch - apiGroups: - "networking.k8s.io" resources: - clustercidrs verbs: - list - watch --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: 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: name: flannel namespace: kube-flannel --- kind: ConfigMap apiVersion: v1 metadata: name: kube-flannel-cfg namespace: kube-flannel labels: tier: node 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.244.0.0/16", "Backend": { "Type": "vxlan" } } --- apiVersion: apps/v1 kind: DaemonSet metadata: name: kube-flannel-ds namespace: kube-flannel labels: tier: node 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: flannelcni/flannel-cni-plugin:v1.1.2 #for ppc64le and mips64le (dockerhub limitations may apply) image: docker.io/rancher/mirrored-flannelcni-flannel-cni-plugin:v1.1.2 command: - cp args: - -f - /flannel - /opt/cni/bin/flannel volumeMounts: - name: cni-plugin mountPath: /opt/cni/bin - name: install-cni #image: flannelcni/flannel:v0.20.2 #for ppc64le and mips64le (dockerhub limitations may apply) image: docker.io/rancher/mirrored-flannelcni-flannel:v0.20.2 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: flannelcni/flannel:v0.20.2 #for ppc64le and mips64le (dockerhub limitations may apply) image: docker.io/rancher/mirrored-flannelcni-flannel:v0.20.2 command: - /opt/bin/flanneld args: - --ip-masq - --kube-subnet-mgr resources: requests: cpu: "100m" memory: "50Mi" limits: 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
开启 kube-proxy 的 ipvs 模式
# 修改 mode: "ipvs" kubectl edit -n kube-system cm kube-proxy # 重启kube-proxy 守护进程 kubectl rollout restart -n kube-system daemonset kube-proxy
3.5、node 节点初始化
下列步骤同上
- 环境安装:docker,cri-dockerd,kubeadm、kubelet、kubectl 等工具
- 节点环境修改:修改 docker 的 cgroup driver,关闭防火墙,禁用 selinux,禁用 swap
将节点添加到集群
# master 节点执行 kubeadm token create --print-join-command # 获得加入集群的命令 # 在命令上附加参数 --cri-socket unix:///var/run/cri-dockerd.sock,指定容器套接字 # 例如: sudo kubeadm join 192.168.88.132:6443 --token 0dl98k.x44gmzyqy4b9h5gt --discovery-token-ca-cert-hash sha256:707002c5b13f2adc0facaf6e7b514b72dc0f8e7085925988daf5e99caf77a9c9 --cri-socket unix:///var/run/cri-dockerd.sock
3.6、重置节点
# 重置节点 sudo kubeadm reset --cri-socket unix:///var/run/cri-dockerd.sock sudo rm -rf /var/lib/kubelet /var/lib/dockershim /var/run/kubernetes /var/lib/cni/etc/cni/net.d $HOME/.kube/config sudo ipvsadm --clear # 删除网络 sudo ifconfig cni0 down sudo ip link delete cni0
4、k8s 集群升级
升级 k8s 集群到 1.25 版本。
4.1、升级 Master 节点
kubeadm 升级
# 更新包管理器 sudo apt-get update # 查看可用版本 apt-cache madison kubeadm # 解除 kubeadm 软件包保留状态 sudo apt-mark unhold kubeadm # 安装 sudo apt-get install -y kubeadm=1.25.5-00 # 设置为保留,即不自动更新 sudo apt-mark hold kubeadm # 验证版本 kubeadm version
验证升级计划
# 验证升级计划 sudo kubeadm upgrade plan
返回的信息包括:检查可升级的版本,并查看需要手动升级的部分。
节点升级
1、升级 master 组件
根据升级计划,执行指定版本的升级命令,例如:v1.25.5
sudo kubeadm upgrade apply v1.25.5
2、升级 node 组件
2.1 & 2.2、调度保护 | 排空节点
开启调度保护,并将节点上除守护进程之外的其他进程调度到其他节点,不影响正常使用。
kubectl drain <nodename> --ignore-daemonsets # 腾空节点 kubectl drain k8s-master1 --ignore-daemonsets # 查看节点 kubectl get pod -A # pod状态:pending kubectl get node # 节点状态:SchedulingDisabled
2.3、node 组件升级
# 组件升级 sudo apt-mark unhold kubelet kubectl sudo apt-get install -y kubelet=1.25.5-00 kubectl=1.25.5-00 sudo apt-mark hold kubelet kubectl # 重启 kubelet sudo systemctl daemon-reload sudo systemctl restart kubelet
2.4、解除保护
kubectl uncordon <nodename> kubectl uncordon k8s-master1
4.2、升级 node 节点
kubeadm 升级
# 更新包管理器 sudo apt-get update # 查看可用版本 apt-cache madison kubeadm # 解除 kubeadm 软件包保留状态 sudo apt-mark unhold kubeadm # 安装 sudo apt-get install -y kubeadm=1.25.5-00 # 设置为保留,即不自动更新 sudo apt-mark hold kubeadm # 验证版本 kubeadm version
节点升级
sudo kubeadm upgrade node # master 节点操作:腾空节点,开启调度保护 kubectl drain <nodename> --ignore-daemonsets # node 组件升级 sudo apt-mark unhold kubelet kubectl sudo apt-get install -y kubelet=1.25.5-00 kubectl=1.25.5-00 sudo apt-mark hold kubelet kubectl # 重启 kubelet sudo systemctl daemon-reload sudo systemctl restart kubelet # master 节点操作:解除调度保护 kubectl uncordon <nodename>
5、kubectl 常用命令
5.1、准备工作
5.1.1、kubectl 命令补全
# 安装命令自动补全插件 sudo apt-get install -y bash-completion echo "source <(kubectl completion bash)" >> ~/.bashrc source ~/.bashrc
5.1.2、安装 metric-server
metric-server 用于获取节点指标。
从 metrics server 获取 components.yaml 文档,并修改两处:
spec.template.containers.args
字段中添加--kubelet-insecure-tls
选项,不验证客户端证书。spec.template.containers.image
字段替换为registry.aliyuncs.com/google_containers/metrics-server:v0.6.2
5.2、kubectl 语法
kubectl [command] [TYPE] [NAME] [flags]
- command:指定对资源的操作。
- TYPE:指定资源类型。资源类型不区分大小写,可以指定单数、复数或缩写形式
- NAME:指定资源名称。资源名称区分大小写,若省略名称,则显示所有资源的详细信息。
- flags:指定可选的参数
具体命令使用可以通过 -h
来查看
5.3、基础操作命令
# 创建资源 kubectl create -f FILENAME # 创建服务,通过现有资源对象的配置信息将新的 service 与原有资源背后的 pod做关联 kubectl expose # 在集群中使用指定镜像启动容器 kubectl run # 为对象设置功能特性:env, img, resources, select kubectl set SUBCOMMAND # 显示资源文档说明 kubectl explain RESOURC # 显示资源信息 kubectl get # 修改服务器线上资源(已部署) kubectl edit (RESOURCE/NAME | -f FILENAME) # 删除资源 kubectl delete # 更新资源的标签 kubectl label # 更新资源所关联的注解 kubectl annotate
5.4、应用部署命令
# 显示目前版本与将要应用的版本之间的差异 kubectl diff -f FILENAME # 将新的配置应用到资源上,旧的配置不改变 kubectl apply -f FILENAME # 将新的配置已替换的方式应用到资源上,旧的配置覆盖 kubectl replace -f FILENAME # 管理资源的上线 kubectl rollout SUBCOMMAND # 查看历史修订版本和配置 kubectl rollout history (TYPE NAME | TYPE/NAME) [flags] # 暂停标记的资源,目前仅支持 deployment 资源对象 kubectl rollout pause RESOURCE # 恢复暂停的资源 kubectl rollout resume RESOURCE # 重启资源对象 kubectl rollout restart RESOURCE # 查看发布状态 kubectl rollout status (TYPE NAME | TYPE/NAME) [flags] # 回滚之前的版本 kubectl rollout undo (TYPE NAME | TYPE/NAME) [flags] # 伸缩容,设置 pod 的副本数 kubectl scale # 创建自动缩放器,自动选择和设置在 k8s 集群集中运行的 pod 数。 kubectl autoscale
5.5、集群管理命令
# 显示节点或 pod 的资源(cpu/memory)使用情况 kubectl top # 标记节点为不可调度 kubectl cordon <nodename> # 标记节点为可调度的 kubectl uncordon <nodename> # 腾空指定节点 kubectl drain <nodename> # 更新节点污点。 # 污点 taint 和容忍度 toleration 相互配合,可以避免 pod 被分配到不合适的节点。 kubectl taint
5.6、故障排除和调试
# 显示某个资源或某组资源的详细信息 kubectl describe # 输出 pod 中某容器的日志 kubectl logs # 连接到一个正在运行的容器 kubectl attach # 在容器中执行相关命令 kubectl exec # 将一个或者多个本地端口转发到 pod kubectl port-forward # 代理网关 kubectl proxy # 将文件和目录拷入/拷出容器 kubectl cp # 创建用于排查工作负载和节点故障的调试会话 kubectl debug