字数 | 4844 |
阅读时间 | 25分钟 |
阅读人群 | 后端运维开发(掌握一些容器概念 例如docker) |
k8s 表示是什么意思
k8s ,8 为 8个字母,全名为 kubernates 在希腊语中表示 舵手,领航员的意思
为什么需要k8s
chatgpt理解:在传统部署时代,应用程序运行在物理服务器上,存在资源分配问题和成本高的问题。虚拟化部署技术被引入,可以在单个物理服务器上运行多台虚拟机,每个虚拟机都具有自己的操作系统和硬件资源。容器部署技术相对于虚拟化更轻量级,容器之间可以共享操作系统,提供了敏捷应用程序的创建和部署、持续开发、集成和部署、可观察性、跨云和操作系统发行版本的可移植性、以应用程序为中心的管理、弹性、解放的微服务等优点。
个人理解:随着服务架构以及容器技术的发展,业务应用从单体到分布再到微服务,服务的拆分越来越细粒度,规模越来越大,运维的难度也越来越大,亟需一个可以管理容器资源编排工具来简化运维等
什么是Kubernetes
- 官网定义:
- Kubernetes 是一个可移植、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。 Kubernetes 拥有一个庞大且快速增长的生态,其服务、支持和工具的使用范围相当广泛。
Kubernetes 为你提供:
- 服务发现和负载均衡
Kubernetes 可以使用 DNS 名称或自己的 IP 地址来暴露容器。 如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。 - 存储编排
Kubernetes 允许你自动挂载你选择的存储系统,例如本地存储、公共云提供商等。 - 自动部署和回滚
你可以使用 Kubernetes 描述已部署容器的所需状态, 它可以以受控的速率将实际状态更改为期望状态。 例如,你可以自动化 Kubernetes 来为你的部署创建新容器, 删除现有容器并将它们的所有资源用于新容器。 - 自动完成装箱计算
你为 Kubernetes 提供许多节点组成的集群,在这个集群上运行容器化的任务。 你告诉 Kubernetes 每个容器需要多少 CPU 和内存 (RAM)。 Kubernetes 可以将这些容器按实际情况调度到你的节点上,以最佳方式利用你的资源。 - 自我修复
Kubernetes 将重新启动失败的容器、替换容器、杀死不响应用户定义的运行状况检查的容器, 并且在准备好服务之前不将其通告给客户端。 - 密钥与配置管理
Kubernetes 允许你存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。 你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。
k8s 集群架构
概念解释 Kubernetes基础概念 (yuque.com)
k8s的核心概念和名词解释
概念/名词 | 解释 |
Pod | Pod是一组紧密关联的容器,共享Network Namespace和主要用于支持共享进程间通信 |
Node | Kubernetes节点是一个运行Kubernetes控制plane组件的VM或物理机 |
Deployment | Deployment负责Pod和ReplicaSet的创建和更新 |
Replica Set | 确保任何时候都有所需数目的Pod副本正在运行 |
Service | Service是对一组Pod进行的逻辑分组,并且为它们提供了一个统一的入口 |
Namespace | 命名空间是可以让你在同一个Kubernetes集群内创建多个虚拟集群 |
Label | 标签是一组key:value键值对,附加到对象上,例如Pod,用于标记对象以便于筛选和管理 |
ConfigMap | ConfigMap允许您将配置数据保存和管理在Kubernetes的对象中 |
Ingress | Ingress是一个pod通过服务访问的入口,控制外部访问 |
Volume | Volume是被多个pod授予访问的目录或独立文件系统 |
Secret | Secret是用来保存敏感数据,如密码、令牌和密钥的对象 |
RBAC | RBAC是基于角色的访问控制(Role-Based Access Control),在K8S中用来鉴定和授权 |
Helm | Helm是一个用于管理Kubernetes应用程序的工具,也被称为包管理器 |
概念混淆点
Pod和Deployment的主要区别是:
- Pod是管理容器(一个或多个)的最小单元,代表运行中的进程。Deployment是管理Pod的中间层,用于部署和扩展应用。
- Pod的生命周期短暂,一旦Pod被删除,它所装载的容器也随之被删除。Deployment管理Pod的副本,可以动态创建和删除Pod。
- 一个Pod只能属于一个Node节点,而Deployment可以通过控制Pod的副本数量,实现应用的高可用和扩展。
- 更新Deployment中的Pod模板,将自动更新Deployment控制的所有Pod。这样可以通过更改Pod模板,实现对部署应用的升级。
- Deployment还提供了回滚应用到之前的版本的功能。
所以总结来说:
- Pod是应用程序在Kubernetes集群中的基本执行单元,是可以被调度的最小计算单元。
- Deployment为Pod和Replica Set提供声明式更新和修复。通过控制器(如Deployment)来管理Pod和ReplicaSet。
- Pod的生命周期短暂,而Deployment管理的Pod副本的整体生命周期。
- 一个Pod属于一个Node,而Deployment管理跨Node的Pod副本。
- 更新Deployment可以自动更新所控制的Pod。
- Deployment支持回滚到之前的版本。
Ingress和Service都是kubernetes中实现服务暴露的方式,但有以下主要区别:
- 服务类型:
- Service主要用于暴露ClusterIP、NodePort两种类型的服务。
- Ingress主要用于暴露 HTTP/HTTPS类型服务,工作在7层。
- 路由规则:
- Service没有路由功能,只是简单的将请求转发到后端Pod。
- Ingress可以通过配置复杂的路由规则实现请求转发,例如基于路径和子域名的路由。
- 负载均衡:
- Service的负载均衡默认简单的轮询到后端的多个Pod。
- Ingress配合Ingress Controller可以实现更复杂的负载均衡算法,例如会话保持等。
- TLS:
- Service不支持TLS。
- Ingress支持TLS,可以对外暴露HTTPS服务。
- 监控统计:
- Service没有监控和日志统计功能。
- Ingress配合Ingress Controller可以提供详细的监控和统计数据。
k8s的安装
- 使用 kubeadmin 进行安装,简单,所有的k8s组件都是镜像模式,拉下来就能用,缺点,服务重启,拉起服务较慢,等等
- 使用二进制安装,缺点,安装复杂,优点,服务拉起速度快,等等
Kubernetes kubeadmin 集群安装
k8s 的常用命令
命令 | 描述 |
| 列出集群中的节点 |
| 列出所有 pod |
| 列出所有的部署 |
| 列出所有的服务 |
| 列出所有的持久化卷 |
| 列出所有的 secret |
| 列出所有的配置映射 |
| 创建资源(从文件) |
| 更新资源(从文件) |
| 删除资源(从文件) |
| 打印 pod 的日志 |
| 在pod中执行命令 |
| 显示资源(deployment,service等)的详细信息 |
| 更新资源的标签 |
| 更新资源的注解 |
| 将 Deployment 暴露为 Service |
| 将 Deployment 扩展到 10 个 Pod |
| 滚动更新 deployment |
| 检查 rollout 状态 |
k8s实战
以下是使用YAML文件实现的Kubernetes解决方案示例:
第一阶段:基本概念和操作
通过命令行创建资源(跳过,生产环境不常用)
# 创建 namespace
kubectl create namespace webdemo
# 创建 pod
kubectl run mynginx --image=nginx:latest --port=80 -oyaml --dry-run=client
kubectl expose pod mynginx --type=NodePort --port=6666 --target-port=80 -oyaml --dry-run=client
kubectl apply mynginx -f nginx-pod.yaml -n webdemo
通过 yaml 文件创建资源(生产环境常用,个人理解会有大量的yaml文件,难以管理,这就引出了下文的helm工具)
- 安装Docker和kubectl命令行工具
- 在Docker中运行Nginx容器,并使用kubectl进行管理:
- 创建命名空间
kubectl create namespace mock
kubectl config set-context mock1 --cluster=kubernetes --user=kubernetes-admin --namespace=mock
kubectl config use-context mock1
- 创建和管理Pods、Deployments和Services:
# nginx-pod.yaml
# k8s 的 api 版本号
apiVersion: v1
# 资源类型
kind: Pod
# 元数据
metadata:
# 资源名称
name: nginx-demo1
# 添加自定义标签
#在 Kubernetes 中,标签是一种键值对,可以附加到各种 Kubernetes 资源上,例如 Pod、Service、Deployment 等等。标签允许用户为资源打上自己的标识,方便后续对它们进行管理和操作。
labels:
app: nginx
spec:
containers:
# 容器名称
- name: nginx
# 镜像名称
image: nginx
# 端口开放
ports:
# 容器端口
- containerPort: 80
# 映射端口到宿主机(不推荐)
hostPort: 8080
---
apiVersion: v1
kind: Pod
metadata:
name: nginx-demo2
labels:
app: nginx
env: dev
spec:
containers:
- name: nginx-container1
image: nginx
ports:
- containerPort: 80
- name: nginx-container2
image: nginx
ports:
- containerPort: 80
kubectl create service nodeport nginx --tcp=8000:80
# nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: NodePort
ports:
- protocol: TCP
port: 8000
targetPort: 80
selector:
app: nginx
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
selector:
app: nginx
# nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
- apiVersion: 指定 Kubernetes API 的版本。在这里,它是 apps/v1,表示使用 apps API 版本的 Deployment 资源。
- kind: 指定要创建的 Kubernetes 资源种类。在这里,它是 Deployment。
- metadata: 用于存储 Kubernetes 资源的元数据,如名称、标签等。在这里,它包括了 Deployment 的名称 nginx-deployment。
- spec: 描述了要创建的 Deployment 的规范。在这里,它包括了以下内容:
- replicas: 指定了要创建的 Pod 的数量。在这里,它是 3,表示将会创建 3 个 Pod 副本。
- selector: 指定了要控制的 Pod 标签。在这里,它是 matchLabels,表示使用标签匹配选择要管理的 Pod。
- matchLabels: 指定要匹配的标签。在这里,它是 app: nginx,表示将匹配带有标签 app=nginx 的 Pod。
- template: 描述了要创建的 Pod 的模板。在这里,它包括以下内容:
- metadata: 存储 Pod 的元数据,如标签等。
- labels: 包含要应用于 Pod 的标签。在这里,它是 app: nginx,与上面的选择器匹配。
- spec: 描述了要创建的 Pod 的规范。在这里,它包括以下内容:
- containers: 包含要在 Pod 中运行的容器。在这里,它有一个名为 nginx 的容器,其中包含了 nginx 镜像,并且暴露了 80 端口。
- 实验:创建多个Pods和Deployments,以及使用Nginx服务负载均衡访问它们。
第二阶段:高级概念和操作
- 使用ConfigMaps存储应用程序配置数据:
# nginx-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-configmap
data:
nginx.conf: |
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
# nginx-pod-configmap.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-configmap
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/conf.d
ports:
- containerPort: 80
volumes:
- name: nginx-config
configMap:
name: nginx-configmap
kubectl edit configmaps nginx-configmap
kubectl exec -it pods/nginx-configmap -- bash
find / -name "nginx.conf"
- 使用Secrets存储敏感信息:
# nginx-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: nginx-secret
type: Opaque
data:
#ssl-cert.pem: <base64-encoded-cert>
username: YWRtaW4=
#ssl-key.pem: <base64-encoded-key>
password: MWYyZDFlMmU2N2Rm
# nginx-pod-secrets.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-secrets
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: nginx-secret
mountPath: /etc/nginx/certs
readOnly: true
ports:
- containerPort: 80
volumes:
- name: nginx-secret
secret:
secretName: nginx-secret
kubectl get secret nginx-secret -oyaml
k exec -it pods/nginx-secrets -- bash
cat /etc/nginx/certs/username
- 使用Persistent Volumes和Persistent Volume Claims存储数据:(失败了)
创建一个10G的nfs类型PV:
apiVersion: v1
kind: PersistentVolume
metadata:
name: mypv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
nfs:
path: /tmp
server: 10.0.0.1
2. 创建PVC,请求10G的ReadWriteMany访问模式的存储:
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: mypvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
- 创建 Pod,使用 volumes 将 PVC 挂载为存储:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: "/mnt/data"
name: webdata
volumes:
- name: webdata
persistentVolumeClaim:
claimName: mypvc
- 验证存储是否挂载成功:
kubectl exec -it nginx -- df -h
一些技巧
# 别名 alias
k = "kubectl"
# k8s 预生成 yaml 格式的资源文件
k -n limit run resource --image=httpd:alpine -oyaml --dry-run=client > pod.yaml
k run nginxdemo --image=nginx --port=80 -oyaml --dry-run=client > 1.yaml
# 设置当前 K8S 环境
k config set-context zarek --user='kubernetes-admin' --cluster='kubernetes' --namespace='zarek'
# 切换当前 K8S 环境
k config use-context zarek
k8s 原理
待完善--_
管理 k8s 的包管理器
为什么需要 k8s 的包管理器
- 包管理:Helm像apt和yum一样,管理Kubernetes的软件包,称为Chart。chart帮助你定义,安装和升级软件包的复杂版本控制。
- 模板引擎:Helm模板使用Golang模板语法,可以让你创建自包含,可定制的Kubernetes资源清单。
- 服务发现:使用Helm,您可以创建一个Ingress Controller来在连接到群集的客户端和群集中运行的服务之间自动完成服务发现。
- 部署复杂环境:部署一个复杂的Kubernetes应用程序通常涉及管理许多资源和其各自的依赖关系。 Helm可以让这个过程更容易,原子而可重复。
- Rollback:Helm将保留您的发行版记录,因此您可以回滚到以前的发行版,甚至可以回到初始安装。
- 共享和回收:Helm Charts可以在仓库中共享和发现,这样您可以充分利用其他人构建的工作。或者您也可以将自己的图表共享出来。
- 多环境部署:可以为不同的环境(dev/staging/prod)创建不同的Helm chart和value文件。所以可以轻松的在不同环境中部署。所以,总的来说,Helm为Kubernetes提供了包管理、部署复杂应用、回滚、共享复用和多环境部署等强大功能。它使得在Kubernetes上部署和管理应用程序变得非常容易。Kubernetes和Helm一起,是运行容器化应用程序的理想平台。
文件 | 作用 |
Chart.yaml | chart 的配置文件,包含chart的名称、版本、描述等信息。 |
helmbuild.sh | 构建chart的shell脚本文件。 |
templates/_helpers.tpl | 定义模板函数和模板变量的模板文件。 |
templates/hpa.yaml | 定义一个Kubernetes HorizontalPodAutoscaler,用于pod副本自动伸缩。 |
templates/ingress.yaml | 定义一个Kubernetes Ingress,用于将HTTP和HTTPS路由到deployment的service。 |
templates/NOTES.txt | 在helm install成功后输出在命令行的简要说明。 |
templates/PersistentVolumeClaim.yaml | 定义一个Kubernetes PVC,用于pod的存储卷声明。 |
templates/serviceaccount.yaml | 定义一个Kubernetes ServiceAccount,用于pod运行的服务账户声明。 |
templates/service.yaml | 定义一个Kubernetes Service,用于pod的服务发现。 |
templates/statefulSet.yaml | 定义一个Kubernetes StatefulSet,用于有状态工作负载。 |
values.schema.json | values.yaml的JSON schema文件,用于值验证。 |
values.yaml | chart 的默认配置文件,包含该chart可配置的参数及其默认值。 |
从上表可以看出:
- templates目录下是真正部署到Kubernetes的资源模板文件。
- Chart.yaml和values.yaml是对chart及其值得描述。
- requirements.yaml可以定义依赖关系。
- NOTES.txt可以在安装后给出提示信息。
- 其他文件像构建脚本、PVCs也可根据需要添加。综上,这些文件共同定义了一个完整的helm chart,通过helm install可以将其 rendering 并部署到 Kubernetes 集群。表格格式可以清晰表达各文件作用,利于您理解和记忆,希望能给您有所帮助!请让我知道如果有任何其他问题。
reference
云原生实战 (yuque.com)
k8s官方文档
k8s在线实战工具
k8s实战大全
问题踩坑
当使用kubectl expose
创建服务时,无法手动指定节点端口,原因如下
- kubectl expose的目的是快速创建服务以暴露已有的工作负载(如Deployment)。如果允许用户手动选择任意节点端口,这可能会导致端口冲突并破坏 Kubernetes 的端口分配逻辑。
- 默认的节点端口范围(30000-32767)已被Kubernetes保留用于服务。允许用户选择这些范围之外的端口会使这种预留变得毫无意义。
- 手动设置节点端口需要管理员确认该端口在集群所有节点上均可用。这增加了创建服务的复杂性,特别是在大型集群中。
- 自动分配节点端口可确保不会意外分配正在使用的端口,并且更易于管理,因为端口号遵循某种顺序或逻辑。
- 如果pod在节点之间移动,手动设置的节点端口将不再正确,可能需要更新服务以反映新端口 - 这会使服务的管理变得麻烦。使用自动端口分配,Kubernetes可以在后台管理此类变化。 所以,总的来说:
- kubectl expose旨在尽可能简化创建基于工作负载的服务的过程。要求用户手动选择节点端口会增加复杂性并导致更多错误。
- Kubernetes已保留默认端口范围以用于服务,允许用户选择范围外的端口会 Undermine 这种预留。
- 手动设置端口需要管理员确认端口可用性,这在大型集群中变得不太现实。
- 自动选择节点端口可以更轻松地管理,特别是当pod在节点之间移动时。
相反,如果要完全控制服务的所有方面(包括手动设置节点端口),建议使用
kubectl create service nodeport
或在服务清单中定义所需的端口。这提供了更大的灵活性,但也需要更高的管理负担。