韩城建设公司网站,网站建设运营培训总结,深圳网站建设网络推广公司,产品展示型网站模板K8S 概览
K8S 是什么 K8S 官网文档#xff1a;https://kubernetes.io/zh/docs/home/ K8S 是 Kubernetes 的全称#xff0c;源于希腊语#xff0c;意为“舵手”或“飞行员”。Kubernetes 是用于自动部署、扩缩和管理容器化应用程序的开源系统。 Kubernetes 源自 Google 15 年…K8S 概览
K8S 是什么 K8S 官网文档https://kubernetes.io/zh/docs/home/ K8S 是 Kubernetes 的全称源于希腊语意为“舵手”或“飞行员”。Kubernetes 是用于自动部署、扩缩和管理容器化应用程序的开源系统。 Kubernetes 源自 Google 15 年生产环境的运维经验同时凝聚了社区的最佳创意和实践。
Docker
作为开源的应用容器引擎可以把应用程序和其相关依赖打包生成一个 Image 镜像文件是一个标准的运行环境提供可持续交付的能力
Kubernetes
作为开源的容器编排引擎用来对容器化应用进行自动化部署、扩缩和管理
K8S 核心特性
服务发现与负载均衡
无需修改你的应用程序即可使用陌生的服务发现机制。
存储编排
自动挂载所选存储系统包括本地存储。
Secret 和配置管理
部署更新 Secrets 和应用程序的配置时不必重新构建容器镜像且不必将软件堆栈配置中的秘密信息暴露出来。
批量执行
除了服务之外Kubernetes 还可以管理你的批处理和 CI 工作负载在期望时替换掉失效的容器。
水平扩缩
使用一个简单的命令、一个 UI 或基于 CPU 使用情况自动对应用程序进行扩缩。
自动化上线和回滚
Kubernetes 会分步骤地将针对应用或其配置的更改上线同时监视应用程序运行状况以确保你不会同时终止所有实例。
自动装箱
根据资源需求和其他约束自动放置容器同时避免影响可用性。
自我修复
重新启动失败的容器在节点死亡时替换并重新调度容器杀死不响应用户定义的健康检查的容器。
K8S 核心架构
我们已经知道了 K8S 的核心功能自动化运维管理多个容器化程序。那么 K8S 怎么做到的呢这里我们从宏观架构上来学习 K8S 的设计思想。K8S 是属于 Master-Worker 架构即有 Master 节点负责核心的调度、管理和运维Worker 节点则执行用户的程序。但是在 K8S 中主节点一般被称为 Master Node 而从节点则被称为 Worker Node 或者 Node。注意Master Node 和 Worker Node 是分别安装了 K8S 的 Master 和 Woker 组件的实体服务器每个 Node 都对应了一台实体服务器虽然 Master Node 可以和其中一个 Worker Node 安装在同一台服务器但是建议 Master Node 单独部署所有 Master Node 和 Worker Node 组成了 K8S 集群同一个集群可能存在多个 Master Node 和 Worker Node。首先来看 Master Node 都有哪些组件
kube-apiserver
K8S 的请求入口服务。API Server 负责接收 K8S 所有请求来自 UI 界面或者 CLI 命令行工具然后API Server 根据用户的具体请求去通知其他组件干活。
Scheduler
K8S 所有 Worker Node 的调度器。当用户要部署服务时Scheduler 会选择最合适的 Worker Node服务器来部署。
Controller Manager
K8S 所有 Worker Node 的监控器。Controller Manager 有很多具体的 ControllerNode Controller、Service Controller、Volume Controller 等。Controller 负责监控和调整在 Worker Node 上部署的服务的状态比如用户要求 A 服务部署 2 个副本那么当其中一个服务挂了的时候Controller 会马上调整让 Scheduler 再选择一个 Worker Node 重新部署服务。
etcd
K8S 的存储服务。etcd 存储了 K8S 的关键配置和用户配置K8S 中仅 API Server 才具备读写权限其他组件必须通过 API Server 的接口才能读写数据。
接着来看 Worker Node 的组件
Kubelet
Worker Node 的监视器以及与 Master Node 的通讯器。Kubelet 是 Master Node 安插在 Worker Node 上的“眼线”它会定期向 Master Node 汇报自己 Node 上运行的服务的状态并接受来自 Master Node 的指示采取调整措施。负责控制所有容器的启动停止保证节点工作正常。
Kube-Proxy
K8S 的网络代理。Kube-Proxy 负责 Node 在 K8S 的网络通讯、以及对外部网络流量的负载均衡。
Container Runtime
Worker Node 的运行环境。即安装了容器化所需的软件环境确保容器化程序能够跑起来比如 Docker Engine 运行环境。
K8S 集群安装 官方文档https://kubernetes.io/zh-cn/docs/setup/production-environment/tools/kubeadm/install-kubeadm/ K8S 快速实战
kubectl 命令使用
kubectl 是 apiserver 的客户端工具工作在命令行下能够连接 apiserver 实现各种增删改查等操作 kubectl。 官方使用文档https://kubernetes.io/zh/docs/reference/kubectl/overview/ K8S 的各种命令帮助文档做得非常不错遇到问题可以多查 help 帮助。
Namespace
K8S 中命名空间Namespace提供一种机制将同一集群中的资源划分为相互隔离的组。同一命名空间内的资源名称要唯一命名空间是用来隔离资源的不隔离网络。Kubernetes 启动时会创建四个初始命名空间
default
Kubernetes 包含这个命名空间以便于你无需创建新的命名空间即可开始使用新集群。
kube-node-lease
该命名空间包含用于与各个节点关联的 Lease租约对象。 节点租约允许 kubelet 发送心跳 由此控制面能够检测到节点故障。
kube-public
所有的客户端包括未经身份验证的客户端都可以读取该命名空间。 该命名空间主要预留为集群使用以便某些资源需要在整个集群中可见可读。 该命名空间的公共属性只是一种约定而非要求。
kube-system
该命名空间用于 Kubernetes 系统创建的对象。
# 查看namespace
kubectl get namespace
# 查看kube-system下的pod
kubectl get pods -n kube-system
# 查看所有namespace下的pod
kubectl get pods -A创建 Namesapce
命令行方式
可以使用下面的命令创建 Namespace
kubectl create namespace firechouyaml 方式
新建一个名为 my-namespace.yaml 的 YAML 文件并写入下列内容
apiVersion: v1
kind: Namespace
metadata:
name: mall然后运行
kubectl apply -f my-namespace.yaml删除 namesapce
kubectl delete namespace firechou
kubectl delete -f my-namespace.yamlPod
Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。Pod就像在鲸鱼荚或者豌豆荚中是一组一个或多个容器这些容器共享存储、网络、以及怎样运行这些容器的声明。
创建 Pod 示例运行一个 NGINX 容器
命令行方式
# 创建pod
kubectl run mynginx --imagenginx:1.14.2
# 获取pod的信息-owide 表示更详细的显示信息 -n 命名空间 查询对应namespace下的pod
kubectl get pod
kubectl get pod -owide
kubectl get pod -owide -n namespace-name
# 查看pod的详情
kubectl describe pod pod-name
# 查看Pod的运行日志
kubectl logs pod-name
# 删除pod
kubectl delete pod pod-nameyaml 方式
# vim nginx-pod.yamlapiVersion: v1
kind: Pod
metadata:labels:run: mynginxname: mynginx
spec:containers:- name: nginximage: nginx:1.14.2ports:- containerPort: 80 然后运行
kubectl apply -f nginx-pod.yaml删除 pod
kubectl delete -f nginx-pod.yamlDeployment
Deployment 负责创建和更新应用程序的实例使 Pod 拥有多副本自愈扩缩容等能力。创建 Deployment 后Kubernetes Master 将应用程序实例调度到集群中的各个节点上。如果托管实例的节点关闭或被删除Deployment 控制器会将该实例替换为群集中另一个节点上的实例。这提供了一种自我修复机制来解决机器故障维护问题。
创建一个 Tomcat 应用程序使用 kubectl create deployment 命令可以创建一个应用部署 deployment 与 pod 。
# my-tomcat表示pod的名称 --image表示镜像的地址
kubectl create deployment my-tomcat --imagetomcat:9.0.55# 查看一下deployment的信息
kubectl get deployment# 删除deployment
kubectl delete deployment my-tomcat# 查看Pod打印的日志
kubectl logs my-tomcat-6d6b57c8c8-n5gm4# 使用 exec 可以在Pod的容器中执行命令
kubectl exec my-tomcat-6d6b57c8c8-n5gm4 -- env # 使用 env 命令查看环境变量
kubectl exec my-tomcat-6d6b57c8c8-n5gm4 -- ls / # 查看容器的根目录下面内容
kubectl exec my-tomcat-6d6b57c8c8-n5gm4 -- sh # 进入Pod容器内部并执行bash命令如果想退出容器可以使用exit命令自愈现在我们来删除刚刚添加的 pod看看会发生什么
# 查看pod信息-w意思是一直等待观察pod信息的变动
kubectl get pod -w开另外一个命令窗口执行如下命令同时观察之前命令窗口的变化情况
kubectl delete pod my-tomcat-6d6b57c8c8-n5gm4我们可以看到之前那个 tomcat 的 pod 被销毁但是又重新启动了一个新的 tomcat pod这是 k8s 的服务自愈功能不需要运维人员干预。
多副本
命令行的方式
# 创建3个副本
kubectl create deployment my-tomcat --imagetomcat:9.0.55 --replicas3yaml方式
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: my-tomcatname: my-tomcat
spec:replicas: 3selector:matchLabels:app: my-tomcattemplate:metadata:labels:app: my-tomcatspec:containers:- image: tomcat:9.0.55name: tomcat 扩缩容
# 扩容到5个pod
kubectl scale --replicas5 deployment my-tomcat
# 缩到3个pod
kubectl scale --replicas3 deployment my-tomcat
# 修改 replicas
kubectl edit deployment my-tomcat滚动升级与回滚对 my-tomcat 这个 deployment 进行滚动升级和回滚将 tomcat 版本由 tomcat:9.0.55 升级到 tomcat:10.1.11再回滚到 tomcat:9.0.55。
滚动升级
kubectl set image deployment my-tomcat tomcattomcat:10.1.11 --record可以执行 kubectl get pod -w 观察 pod 的变动情况可以看到有的 pod 在销毁有的 pod 在创建查看 pod 信息。
kubectl get pod查看某个 pod 的详细信息发现 pod 里的镜像版本已经升级了.
kubectl describe pod my-tomcat-85c5c8f685-lnkfm版本回滚查看历史版本
kubectl rollout history deploy my-tomcat回滚到上一个版本
kubectl rollout undo deployment my-tomcat # --to-revision 参数可以指定回退的版本# 回滚(回到指定版本)
kubectl rollout undo deployment/my-dep --to-revision2查看pod详情发现版本已经回退了。
访问 tomcat pod
集群内访问在集群里任一 worker 节点都可以访问
curl 10.244.169.164:8080集群外部访问
当我们在集群之外访问发现无法访问那么集群之外的客户端如何才能访问呢这就需要我们的 service 服务了下面我们就创建一个 service使外部客户端可以访问我们的 pod。
Service
Service 是一个抽象层它定义了一组 Pod 的逻辑集并为这些 Pod 支持外部流量暴露、负载均衡和服务发现。尽管每个 Pod 都有一个唯一的 IP 地址但是如果没有 Service这些 IP 不会暴露在群集外部。Service 允许你的应用程序接收流量。Service 也可以用在 ServiceSpec 标记 type 的方式暴露type 类型如下
ClusterIP默认在集群的内部 IP 上公开 Service。这种类型使得 Service 只能从集群内访问。NodePort使用 NAT 在集群中每个选定 Node 的相同端口上公开 Service。使用 NodeIP:NodePort 从集群外部访问 Service。是 ClusterIP 的超集。LoadBalancer在当前云中创建一个外部负载均衡器如果支持的话并为 Service 分配一个固定的外部 IP。是 NodePort 的超集。ExternalName通过返回带有该名称的 CNAME 记录使用任意名称由 spec 中的 externalName 指定公开Service。不使用代理。
创建 service 示例
命令行的方式
kubectl expose deployment my-tomcat --nametomcat --port8080 --typeNodePort# 查看service信息port信息里冒号后面的端口号就是对集群外暴露的访问接口
# NodePort范围在 30000-32767 之间
kubectl get svc -o wide集群外部访问使用集群节点的 ip 加上暴露的端口就可以访问。tomcat 版本太高返回 404 的解决办法进入 tomcat 容器把 webapps 目录删除再把 webapps.dist 重命名为 webapps 即可。
yaml 的方式
# vim mytomcat-service.yamlapiVersion: v1
kind: Service
metadata:labels:app: my-tomcatname: my-tomcat
spec:ports:- port: 8080 # service的虚拟ip对应的端口在集群内网机器可以访问用service的虚拟ip加该端口号访问服务nodePort: 30001 # service在宿主机上映射的外网访问端口端口范围必须在30000-32767之间protocol: TCPtargetPort: 8080 # pod暴露的端口一般与pod内部容器暴露的端口一致selector:app: my-tomcattype: NodePort执行如下命令创建 service
kubectl apply -f mytomcat-service.yaml存储
Volume
Volume 指的是存储卷包含可被 Pod 中容器访问的数据目录。容器中的文件在磁盘上是临时存放的当容器崩溃时文件会丢失同时无法在多个 Pod 中共享文件通过使用存储卷可以解决这两个问题。Kubernetes 支持很多类型的卷。Pod 可以同时使用任意数目的卷类型。临时卷类型的生命周期与 Pod 相同但持久卷可以比 Pod 的存活期长。 当 Pod 不再存在时Kubernetes 也会销毁临时卷不过 Kubernetes 不会销毁持久卷。对于给定 Pod 中任何类型的卷在容器重启期间数据都不会丢失。卷的核心是一个目录其中可能存有数据Pod 中的容器可以访问该目录中的数据。所采用的不同卷的类型将决定该目录如何形成的、使用何种介质保存数据以及目录中存放的内容。常用的卷类型有 configMap、emptyDir、local、nfs、secret 等。
ConfigMap
可以将配置文件以键值对的形式保存到 ConfigMap 中并且可以在 Pod 中以文件或环境变量的形式使用。ConfigMap 可以用来存储不敏感的配置信息如应用程序的配置文件。
EmptyDir
是一个空目录可以在 Pod 中用来存储临时数据当 Pod 被删除时该目录也会被删除。
Local
将本地文件系统的目录或文件映射到 Pod 中的一个 Volume 中可以用来在 Pod 中共享文件或数据。
NFS
将网络上的一个或多个 NFS 共享目录挂载到 Pod 中的 Volume 中可以用来在多个 Pod 之间共享数据。
Secret
将敏感信息以密文的形式保存到 Secret 中并且可以在 Pod 中以文件或环境变量的形式使用。Secret 可以用来存储敏感信息如用户名密码、证书等。
1使用方式使用卷时, 在 .spec.volumes 字段中设置为 Pod 提供的卷并在 .spec.containers[*].volumeMounts 字段中声明卷在容器中的挂载位置。容器中的进程看到的文件系统视图是由它们的容器镜像的初始内容以及挂载在容器中的卷如果定义了的话所组成的。 其中根文件系统同容器镜像的内容相吻合。任何在该文件系统下的写入操作如果被允许的话都会影响接下来容器中进程访问文件系统时所看到的内容。
apiVersion: v1
kind: Pod
metadata:name: configmap-pod
spec:containers:- name: testimage: busybox:1.28volumeMounts:..........volumes:............2搭建nfs文件系统nfs(network filesystem)网络文件存储系统。
安装 nfs-server
# 在每个机器。
yum install -y nfs-utils# 在master 执行以下命令
echo /nfs/data/ *(insecure,rw,sync,no_root_squash) /etc/exports# 执行以下命令启动 nfs 服务;创建共享目录
mkdir -p /nfs/data# 在master执行
systemctl enable rpcbind
systemctl enable nfs-server
systemctl start rpcbind
systemctl start nfs-server# 使配置生效
exportfs -r# 检查配置是否生效
exportfs配置 nfs-client
# nfs-server节点的ip
showmount -e 192.168.11.101
mkdir -p /nfs/data
mount -t nfs 192.168.11.101:/nfs/data /nfs/datanfs 方式数据挂载相对于 emptyDir 和 hostPathnfs 这种 Volume 类型的最大特点就是不依赖 Kuberees Volume 的底层基础设施由独立的存储系统管理与 Kubernetes 集群是分离的。数据被持久化后即使整个 Kubernetes 崩溃也不会受损。
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginx-pv-demoname: nginx-pv-demo
spec:replicas: 2selector:matchLabels:app: nginx-pv-demotemplate:metadata:labels:app: nginx-pv-demospec:containers:- image: nginxname: nginxvolumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlvolumes:- name: htmlnfs:server: 192.168.11.101path: /nfs/data/nginx-pvPV PVC
Volume 提供了非常好的数据持久化方案不过在可管理性上还有不足。前面 nfs 例子来说要使用 Volume Pod 必须事先知道以下信息
当前的 Volume 类型并明确 Volume 已经创建好。必须知道 Volume 的具体地址信息。
但是 Pod 通常是由应用的开发人员维护而 Volume 则通常是由存储系统的管理员维护。开发人员要获得上面的信息要么询问管理员要么自己就是管理员。这样就带来一个管理上的问题应用开发人员和系统管理员的职责耦合在一起了。如果系统规模较小或者对于开发环境这样的情况还可以接受当集群规模变大特别是对于生产环境考虑到效率和安全性这就成了必须要解决的问题。Kubernetes 给出的解决方案是 Persistent Volume 和 Persistent Volume Claim。PersistentVolumePV是外部存储系统中的一块存储空间由管理员创建和维护将应用需要持久化的数据保存到指定位置。与 Volume 一样PV 具有持久性生命周期独立于 Pod。Persistent Volume ClaimPVC是对 PV 的申请Claim申明需要使用的持久卷规格。PVC 通常由普通用户创建和维护。需要为 Pod 分配存储资源时用户可以创建一个 PVC指明存储资源的容量大小和访问模式 比如只读等信息Kubernetes 会查找并提供满足条件的 PV。有了 PersistentVolumeClaim用户只需要告诉 Kubernetes 需要什么样的存储资源而不必关心真正的空间从哪里分配、如何访问等底层细节信息。这些 Storage Provider 的底层信息交给管理员来处理只有管理员才应该关心创建 PersistentVolume 的细节信息。
1基本使用创建 pv
apiVersion: v1
kind: PersistentVolume
metadata:name: nfs-pv
spec:capacity:storage: 1Gi # 指定容量大小accessModes: # 访问模式- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:path: /{nfs-server目录名称}server: {nfs-server IP 地址}accessModes支持的访问模式有3种
ReadWriteOnce 表示 PV 能以 readwrite 模式 mount 到单个节点
这个 PV 只能被某个节点以读写方式挂载意味着这个 PV 只能被一个 Pod 挂载到某个节点上并且这个 Pod 可以对这个 PV 进行读写操作。如果尝试在其他节点上挂载这个 PV就会失败。
ReadOnlyMany 表示 PV 能以 read-only 模式 mount 到多个节点
这个 PV 能被多个节点以只读方式挂载意味着这个 PV 可以被多个 Pod 挂载到多个节点上。
ReadWriteMany 表示 PV 能以 read-write 模式 mount 到多个节点
这个 PV 能被多个节点以读写方式挂载意味着这个 PV 可以被多个 Pod 挂载到多个节点上。
persistentVolumeReclaimPolicy指定当 PV 的回收策略支持的策略有 3 种
Retain在 PVC 被删除后保留 PV 和其数据手动清理 PV 中的数据。Delete在 PVC 被删除后自动删除 PV 和其数据。Recycle在 PVC 被删除后通过删除 PV 中的数据来准备 PV 以供重新使用。
值得注意的是persistentVolumeReclaimPolicy只适用于一些类型的 PV如 NFS、HostPath、iSCSI 等。对于一些云平台提供的存储如 AWS EBS 和 Azure Disk由于底层提供商会自动处理 PV 的回收问题因此该属性不适用。
storageClassName指定 PV 的 class 为 nfs。相当于为 PV 设置了一个分类PVC 可以指定 class 申请相应class 的 PV。
创建 pvc
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: nfs-pvc
spec:accessModes:- ReadWriteManyresources:requests:storage: 1GistorageClassName: nfs # 通过名字进行选择
# selector: 通过标签形式
# matchLabels:
# pv-name: nfs-pv2动态供应在前面的例子中我们提前创建了 PV然后通过 PVC 申请 PV 并在 Pod 中使用这种方式叫作静态供应 Static Provision与之对应的是动态供应 (Dynamical Provision即如果没有满足 PVC 条件的 PV会动态创建 PV。相比静态供应动态供应有明显的优势不需要提前创建 PV减少了管理员的工作量效率高。动态供应是通过 StorageClass 实现的StorageClass 定义了如何创建 PV但需要注意的是每个 StorageClass 都有一个制备器Provisioner用来决定使用哪个卷插件制备 PV该字段必须指定才能实现动态创建。
配置
ConfigMap
在 Kubernetes 中ConfigMap 是一种用于存储非敏感信息的 Kubernetes 对象。它用于存储配置数据如键值对、整个配置文件或 JSON 数据等。ConfigMap 通常用于容器镜像中的配置文件、命令行参数和环境变量等。
ConfigMap 可以通过三种方式进行配置数据的注入
环境变量注入将配置数据注入到 Pod 中的容器环境变量中。配置文件注入将配置数据注入到 Pod 中的容器文件系统中容器可以读取这些文件。命令行参数注入将配置数据注入到容器的命令行参数中。
优点
避免了硬编码将配置数据与应用代码分离。便于维护和更新可以单独修改 ConfigMap 而不需要重新构建镜像。可以通过多种方式注入配置数据更加灵活。可以通过 Kubernetes 的自动化机制对 ConfigMap 进行版本控制和回滚。ConfigMap 可以被多个 Pod 共享减少了配置数据的重复存储。
定义 ConfigMap
基本操作
# 查看 configmap
$ kubectl get configmap/cm# 查看详细
$ kubectl describe configmap/cm my-config# 删除 cm
$ kubectl delete cm my-config命令行创建
可以使用 kubectl create configmap 命令来创建 configmap具体命令如下
kubectl create configmap my-config --from-literalkey1value1 --fromliteralkey2value2通过配置文件创建推荐
可以通过创建 YAML 文件的方式来定义 configmap 的内容。例如创建一个名为 my-config 的 configmap内容如下
apiVersion: v1
kind: ConfigMap
metadata:name: my-config
data:key1: value1key2: value2---
apiVersion: v1
kind: ConfigMap
metadata:name: app-config
data:application.yml: |name: firechou然后使用 kubectl apply -f 命令来创建 configmap。
通过文件创建
echo-n admin ./username
echo -n 123456 ./password
kubectl create configmap myconfigmap --from-file./username --from-file./password通过文件夹创建
可以将多个配置文件放在同一个文件夹下然后使用 kubectl create configmap 命令来创建configmap例如
kubectl create configmap my-config --from-fileconfig-files/这将创建一个名为 my-config 的 configmap其中包含 config-files 文件夹下所有的文件内容作为键值对。
通过环境变量创建
可以将环境变量的值转换为 configmap。例如使用以下命令将当前环境变量的值转换为 configmap
kubectl create configmap my-config --from-env-fileenvSecret
Secret 对象类型用来保存敏感信息例如密码、OAuth 令牌和 SSH 密钥。 将这些信息放在 secret 中比放在 Pod 的定义或者容器镜像中来说更加安全和灵活。
在 Kubernetes 中Secrets 通常被用于以下场景
作为卷挂载到 Pod 中用于存储证书、密钥等敏感文件在 Pod 中使用环境变量用于存储用户名和密码等敏感信息用于存储 Docker 镜像仓库的登录信息用于存储外部服务的 API 密钥
定义 Secret
使用命令行创建
可以使用 kubectl create secret 命令来创建 secret例如
kubectl create secret generic my-secret --from-literalusernameadmin --from-literalpasswordadmin123使用 YAML 文件定义
可以创建一个 YAML 文件来定义 Secret 对象例如
apiVersion: v1
kind: Secret
metadata:name: my-secret
type: Opaque
data:username: YWRtaW4 # base64 编码后的用户名 adminpassword: MWYyZDFlMmU2N2Rm # base64 编码后的密码 1f2d1e2e67df注意这个 YAML 文件定义了一个名为 my-secret 的 Secret 对象其中包含了两个 base64 编码后的 key-value 对username 和 password。
使用文件创建
echo -n admin ./username
echo -n 123456 ./password
kubectl create secret generic mysecret --from-file./username --from-file./password通过环境变量创建
可以将环境变量的值转换为 secret。例如使用以下命令将当前环境变量的值转换为 secret
kubectl create secret generic my-config --from-env-fileenv使用示例
从私有docker仓库拉取镜像
docker pull registry.cn-hangzhou.aliyuncs.com/firechou/mall-product:0.0.5无法从私有镜像仓库拉取镜像抛出错误。解决方案使用 docker 的用户信息来生成 secret
# 命令格式
kubectl create secret docker-registry myregistrykey \
--docker-server你的镜像仓库服务器 \
--docker-username你的用户名 \
--docker-password你的密码 \
--docker-email你的邮箱地址kubectl create secret docker-registry myregistrykey --docker-serverregistry.cnhangzhou.aliyuncs.com --docker-usernamefirechou --docker-passwordxxx在创建 Pod 的时候通过 imagePullSecrets 来引用刚创建的 myregistrykey
apiVersion: v1
kind: Podmetadata:name: tulingmall-product
spec: containers:- name: tulingmall-productimage: registry.cn-hangzhou.aliyuncs.com/firechou/mall-product:0.0.5imagePullSecrets:- name: myregistrykeyIngress
Ingress 是一种 Kubernetes 资源类型它允许在 Kubernetes 集群中暴露 HTTP 和 HTTPS 服务。通过 Ingress您可以将流量路由到不同的服务和端点而无需使用不同的负载均衡器。Ingress 通常使用 Ingress Controller 实现它是一个运行在 Kubernetes 集群中的负载均衡器它根据 Ingress 规则配置路由规则并将流量转发到相应的服务。下面是一个将所有流量都发送到同一 Service 的简单 Ingress 示例。
Ingress 和 Service 区别
Ingress 和 Service 都是 Kubernetes 中用于将流量路由到应用程序的机制但它们在路由层面上有所不同
Service 是 Kubernetes 中抽象的应用程序服务它公开了一个单一的 IP 地址和端口可以用于在 Kubernetes 集群内部的 Pod 之间进行流量路由。Ingress 是一个 Kubernetes 资源对象它提供了对集群外部流量路由的规则。Ingress 通过一个公共 IP 地址和端口将流量路由到一个或多个 Service。
安装 Ingress
1下载 ingress 配置文件
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.47.0/deploy/static/provider/baremetal/deploy.yaml[rootk8s-master k8s]# grep image: deploy.yaml image: k8s.gcr.io/ingress-nginx/controller:v0.46.0sha256:52f0058bed0a17ab0fb35628ba97e8d52b5d32299fbc03cc0f6c7b9ff036b61aimage: docker.io/jettech/kube-webhook-certgen:v1.5.1image: docker.io/jettech/kube-webhook-certgen:v1.5.1# 修改镜像
vi deploy.yaml
# 1、将image k8s.gcr.io/ingressnginx/controller:v0.46.0sha256:52f0058bed0a17ab0fb35628ba97e8d52b5d32299fbc03cc0f6c7b9ff036b61a的值改为如下值
registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/ingress-nginx-controller:v0.46.02安装 ingress执行如下命令
kubectl apply -f ingress-controller.yaml3查看是否安装成功
kubectl get pod,svc -n ingress-nginx -owide使用 Ingress 官网地址https://kubernetes.github.io/ingress-nginx/ 配置 ingress 访问规则就是类似配置 nginx 的代理转发配置让 ingress 将域名 tomcat.firechou.com 转发给后端的 my-tomcat 服务新建一个文件 ingress-tomcat.yaml内容如下
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: web-ingress
spec:rules:- host: tomcat.firechou.com # 转发域名http:aths:- pathType: Prefixpath: /backend:service:name: my-tomcatport:number: 8080 # service的端口执行如下命令生效规则
kubectl apply -f ingress-tomcat.yaml查看生效的 ingress 规则
kubectl get ing在访问机器配置 hostwin10 客户机在目录C:\Windows\System32\drivers\etc在 host 里增加如下hostingress 部署的机器 ip 对应访问的域名
192.168.65.82 tomcat.firechou.com配置完后直接在客户机浏览器访问[http://tomcat.firechou.com:30940](http://tomcat.firechou.com:30940)能正常访问 tomcat。
ServiceIngress 总结
Service 是 K8S 服务的核心屏蔽了服务细节统一对外暴露服务接口真正做到了“微服务”。举个例子我们的一个服务 A部署了 3 个备份也就是 3 个 Pod对于用户来说只需要关注一个 Service 的入口就可以而不需要操心究竟应该请求哪一个 Pod。优势非常明显一方面外部用户不需要感知因为 Pod 上服务的意外崩溃、K8S 重新拉起 Pod 而造成的 IP 变更外部用户也不需要感知因升级、变更服务带来的 Pod 替换而造成的 IP 变化另一方面Service 还可以做流量负载均衡。但是Service 主要负责 K8S 集群内部的网络拓扑。集群外部需要用 Ingress。Ingress 是整个 K8S 集群的接入层复杂集群内外通讯。
K8S 核心原理
K8S 的网络模型
K8S 的网络中主要存在 4 种类型的通信
同一 Pod 内的容器间通信各个 Pod 彼此间的通信Pod 和 Service 间的通信集群外部流量和 Service 之间的通信
K8S 为 Pod 和 Service 资源对象分别使用了各自的专有网络Pod 网络由 K8S 的网络插件配置实现而 Service 网络则由 K8S 集群进行指定。
K8S 使用的网络插件需要为每个 Pod 配置至少一个特定的地址即 Pod IP。Pod IP 地址实际存在于某个网卡可以是虚拟机设备上。而 Service 的地址却是一个虚拟 IP 地址没有任何网络接口配置在此地址上它由 Kube-proxy 借助 iptables 规则或 ipvs 规则重定向到本地端口再将其调度到后端的 Pod 对象。Service 的 IP 地址是集群提供服务的接口也称为 Cluster IP。Pod 网络和 IP 由 K8S 的网络插件负责配置和管理具体使用的网络地址可以在管理配置网络插件时进行指定如10.244.0.0/16网络。而 Cluster 网络和 IP 是由 K8S 集群负责配置和管理如10.96.0.0/12网络。
一个 K8S 集群包含是三个网络。
节点网络
各主机Master、Node、ETCD 等自身所属的网络地址配置在主机的网络接口用于各主机之间的通信又称为节点网络。
Pod 网络
专用于 Pod 资源对象的网络它是一个虚拟网络用于为各 Pod 对象设定 IP 地址等网络参数其地址配置在 Pod 中容器的网络接口上。Pod 网络需要借助 kubenet 插件或 CNI 插件实现。
Service网络
专用于 Service 资源对象的网络它也是一个虚拟网络用于为 K8S 集群之中的 Service 配置 IP 地址但是该地址不会配置在任何主机或容器的网络接口上而是通过 Node 上的 kube-proxy 配置为 iptables 或 ipvs 规则从而将发往该地址的所有流量调度到后端的各 Pod 对象之上。
K8S 的工作流程
用 K8S 部署 Nginx 的过程中K8S 内部各组件是如何协同工作的我们在 master 节点执行一条命令要 master 部署一个 nginx 应用kubectl create deployment nginx --imagenginx。
这条命令首先发到 master 节点的网关 api server这是 matser 的唯一入口api server 将命令请求交给 controller mannager 进行控制controller mannager 进行应用部署解析controller mannager 会生成一次部署信息并通过 api server 将信息存入 etcd 存储中scheduler 调度器通过 api server 从 etcd 存储中拿到要部署的应用开始调度看哪个节点有资源适合部署scheduler 把计算出来的调度信息通过 api server 再放到 etcd 中每一个 node 节点的监控组件 kubelet随时和 master 保持联系给 api-server 发送请求不断获取最新数据拿到 master 节点存储在 etcd 中的部署信息假设 node2 的 kubelet 拿到部署信息显示他自己节点要部署某某应用kubelet 就自己 run 一个应用在当前机器上并随时给 master 汇报当前应用的状态信息node 和 master 也是通过 master 的 api-server 组件联系的每一个机器上的 kube-proxy 能知道集群的所有网络只要 node 访问别人或者别人访问 nodenode 上的 kubeproxy 网络代理自动计算进行流量转发 K8S 架构原理六连问
K8S 是一个基于容器技术的分布式集群管理系统。既然是个分布式系统那势必有多个 Node 节点物理主机或虚拟机它们共同组成一个分布式集群并且这些节点中会有一个 Master 节点由它来统一管理 Node 节点。
问题一主节点和工作节点是如何通信的呢
首先Master 节点启动时会运行一个 kube-apiserver 进程它提供了集群管理的 API 接口是集群内各个功能模块之间数据交互和通信的中心枢纽并且它也提供了完备的集群安全机制。在 Node 节点上使用 K8S 中的 kubelet 组件在每个 Node 节点上都会运行一个 kubelet 进程它负责向 Master 汇报自身节点的运行情况如 Node 节点的注册、终止、定时上报健康状况等以及接收 Master 发出的命令创建相应 Pod。在 K8S 中Pod 是最基本的操作单元它与 docker 的容器有略微的不同因为 Pod 可能包含一个或多个容器可以是 docker 容器这些内部的容器是共享网络资源的即可以通过 localhost 进行相互访问。关于 Pod 内是如何做到网络共享的每个 Pod 启动内部都会启动一个 pause 容器google的一个镜像它使用默认的网络模式而其他容器的网络都设置给它以此来完成网络的共享问题。
问题二Master 是如何将 Pod 调度到指定的 Node 上的
该工作由 kube-scheduler 来完成整个调度过程通过执行一些列复杂的算法最终为每个 Pod 计算出一个最佳的目标 Node该过程由 kube-scheduler 进程自动完成。常见的有轮询调度RR。当然也有可能我们需要将 Pod 调度到一个指定的 Node 上我们可以通过节点的标签Label和 Pod 的 nodeSelector 属性的相互匹配来达到指定的效果。
问题三各节点、Pod 的信息都是统一维护在哪里的由谁来维护
从上面的 Pod 调度的角度看我们得有一个存储中心用来存储各节点资源使用情况、健康状态、以及各 Pod 的基本信息等这样 Pod 的调度来能正常进行。在 K8S 中采用 etcd 组件作为一个高可用强一致性的存储仓库该组件可以内置在 K8S 中也可以外部搭建供 K8S 使用。集群上的所有配置信息都存储在了 etcd为了考虑各个组件的相对独立以及整体的维护性对于这些存储数据的增、删、改、查统一由 kube-apiserver 来进行调用apiserver 也提供了 REST 的支持不仅对各个内部组件提供服务外还对集群外部用户暴露服务。外部用户可以通过 REST 接口或者 kubectl 命令行工具进行集群管理其内在都是与 apiserver 进行通信。
问题四外部用户如何访问集群内运行的 Pod
前面讲了外部用户如何管理 K8S而我们更关心的是内部运行的 Pod 如何对外访问。使用过 Docker 的同学应该知道如果使用 bridge 模式在容器创建时都会分配一个虚拟 IP该 IP 外部是没法访问到的我们需要做一层端口映射将容器内端口与宿主机端口进行映射绑定这样外部通过访问宿主机的指定端口就可以访问到内部容器端口了。那么K8S 的外部访问是否也是这样实现的答案是否定的K8S 中情况要复杂一些。因为上面讲的 Docker 是单机模式下的而且一个容器对外就暴露一个服务。在分布式集群下一个服务往往由多个 Application 提供用来分担访问压力而且这些 Application 可能会分布在多个节点上这样又涉及到了跨主机的通信。这里K8S 引入了 Service 的概念将多个相同的 Pod 包装成一个完整的 service 对外提供服务至于获取到这些相同的 Pod每个 Pod 启动时都会设置 labels 属性在 Service 中我们通过选择器 Selector选择具有相同 Name 标签属性的 Pod作为整体服务并将服务信息通过 Apiserver 存入 etcd 中该工作由 Service Controller 来完成。同时每个节点上会启动一个 kube-proxy 进程由它来负责服务地址到 Pod 地址的代理以及负载均衡等工作。
问题五Pod 如何动态扩容和缩放
既然知道了服务是由 Pod 组成的那么服务的扩容也就意味着 Pod 的扩容。通俗点讲就是在需要时将 Pod 复制多份在不需要后将 Pod 缩减至指定份数。K8S 中通过 Replication Controller 来进行管理为每个 Pod 设置一个期望的副本数当实际副本数与期望不符时就动态的进行数量调整以达到期望值。期望数值可以由我们手动更新或自动扩容代理来完成。
问题六各个组件之间是如何相互协作的
最后讲一下 kube-controller-manager 这个进程的作用。我们知道了 ectd 是作为集群数据的存储中心 apiserver 是管理数据中心作为其他进程与数据中心通信的桥梁。而 Service Controller、Replication Controller 这些统一交由 kube-controller-manager 来管理kube-controller-manager 作为一个守护进程每个 Controller 都是一个控制循环通过 apiserver 监视集群的共享状态并尝试将实际状态与期望不符的进行改变。关于 Controllermanager 中还包含了 Node 节点控制器Node Controller、资源配额管控制器ResourceQuota Controller、命名空间控制器Namespace Controller等。