企业网站制作一,网站开发晋升空间 路径,开发网站的基本流程五个阶段,做网站用php还是node文章目录 一、背景1.1 物理机时代、虚拟机时代、容器化时代1.2 容器编排的需要 二、K8S架构2.2 Worker节点 三、核心概念3.1 Pod3.2 Deployment3.3 Service3.4 Volume3.5 Namespace 四、K8S安装五、kubectl常用命令六、K8S实战6.1 水平扩容6.2 自动装箱6.2.1 节点污点6.2.2 Pod… 文章目录 一、背景1.1 物理机时代、虚拟机时代、容器化时代1.2 容器编排的需要 二、K8S架构2.2 Worker节点 三、核心概念3.1 Pod3.2 Deployment3.3 Service3.4 Volume3.5 Namespace 四、K8S安装五、kubectl常用命令六、K8S实战6.1 水平扩容6.2 自动装箱6.2.1 节点污点6.2.2 Pod调度策略 6.3 Secret6.3.1 挂载卷的方式6.3.2 环境变量的方式 6.4 ConfigMap6.5 存储编排6.6 服务发现与负载均衡6.7 自我修复6.7.1 Pod重启机制6.7.2 Pod健康检查 6.8 自动化上线与回滚 参考资料 一、背景
1.1 物理机时代、虚拟机时代、容器化时代
在介绍K8S之前先来看看服务器的演变过程物理机时代、虚拟机时代、容器化时代。
物理机时代的缺点
部署慢 每台服务器都要安装操作系统、相关的应用程序所需要的环境各种配置成本高物理服务器的价格十分昂贵资源浪费硬件资源不能充分利用扩展和迁移成本高扩展和迁移需要重新配置一模一样的环境 虚拟机时代很好的解决了物理机时代的缺点虚拟机时代的特点是
易部署每台物理机可部署多台虚拟机且可以通过模板部署快成本低资源池开出来的虚拟机可作为资源池备用充分压榨服务器性能资源隔离每个虚拟机都有独立分配的内存磁盘等硬件资源虚拟机之间不会互相影响易扩展随时都能在一个物理机上创建或销毁虚拟机
虚拟机的缺点是每台虚拟机都需要安装操作系统 容器化时代解决了虚拟机时代的缺点容器化时代在继承了虚拟机时代优点的基础之上还有以下优势
更高效的利用硬件资源所有容器共享主机操作系统内核不需要安装操作系统。一致的运行环境相同的镜像产生相同的行为更小较虚拟机而言容器镜像更小因为不需要打包操作系统更快容器能达到秒级启动其本质是主机上的一个进程 1.2 容器编排的需要
容器技术的代表就是dockerdocker在单机上使用方便快捷但在集群中表现如何呢假设现在有5个节点每个节点中都装有docker现在要部署一个应用要求要10个副本有如下做法
在5个节点上随机分配平均分配每台节点分配2个根据不同节点的负载状态分配负载低的优先分配
无论选择哪种方法都需要执行相同docker run命令10遍如果是最后一种做法还需要挨个检查每个节点的负载这种问题叫做不利于自动装箱。
如果以后增加了1个副本还需要再重复上面的动作如果增加10个呢增加100个呢人为去操作那就有点难受了这种问题叫做不利于水平扩容与缩容简称水平扩缩。
如果现在要变更版本更新或者回滚需要停止容器然后替换新版本镜像再启动这样的操作每个副本都要来一次如果副本太多简直是噩梦这种问题叫做不利于自动化上线和回滚。
如果现在一个容器停止运行了docker的重启策略会将它拉起来继续运行这没什么问题如果节点宕机了呢上面的所有容器都停止了docker重启策略就没用了这样副本的数量就会减少这个问题叫做不能自我修复。
假设需要负载均衡那么得新增一个节点安装负载均衡器并且配置5个节点的IP和端口前提是容器的端口要映射到主机端口而且容器之前网络是隔离的不能相互访问维护成本高这个问题叫不利于服务发现与负载均衡。
上面的这些操作就是容器编排既然存在如上问题那么就需要一个技术进行自动化编排这个技术就是K8SK8S即kubernetes /kjubɚ’nɛtɪs/ Kubernetes是一个工业级的容器编排平台。Kubernetes 这个单词是希腊语它的中文翻译是“舵手”或者“飞行员”。在一些常见的资料中也会看到“ks”这个词也就是“K8s”它是通过将 8 个字母“ubernete ”替换为“8”而成为的一个缩写。 K8S官网https://kubernetes.io/zh-cn/ 根据官网描述它有如下功能
二、K8S架构
在K8S中由Master控制节点和Worker节点共同构成一个集群总体架构如下图所示 ## 2.1 Master节点 etcd分布式KV数据库使用Raft协议用于保存集群中的相关数据项目地址https://github.com/etcd-io/etcdAPI Server集群统一入口以restful风格进行操作同时交给etcd存储是唯一能访问etcd的组件提供认证、授权、访问控制、API注册和发现等机制可以通过kubectl命令行工具dashboard可视化面板或者sdk等访问。Scheduler节点的调度选择node节点应用部署。Controller Manager处理集群中常规后台任务一个资源对应一个控制器同时监控集群的状态确保实际状态和最终状态一致。
2.2 Worker节点 kubelet相当于Master派到node节点代表管理本机容器上报数据给API ServerContainer Runtime容器运行时K8S支持多个容器运行环境Docker、Containerd、CRI-O、Rktlet以及任何实现- Kubernetes CRI (容器运行环境接口) 的软件kube-proxy实现服务Service抽象组件屏蔽PodIP的变化和负载均衡
三、核心概念
3.1 Pod
Pod是最小调度单元Pod里面会包含一个或多个容器ContainerPod内的容器共享存储及网络可通过localhost通信 Pod本意是豌豆荚的意思此处指的是K8S中资源调度的最小单位豌豆荚里面的小豆子就像是Container豌豆荚本身就像是一个Pod。
3.2 Deployment
Deployment 是在 Pod 这个抽象上更为上层的一个抽象它可以定义一组 Pod 的副本数目、以及这个 Pod 的版本。一般大家用 Deployment 这个抽象来做应用的真正的管理而 Pod 是组成 Deployment 最小的单元。
定义一组Pod的副本数量版本等通过控制器维护Pod的数目自动恢复失败的Pod通过控制器以指定的策略控制版本 3.3 Service
Pod是不稳定的IP是会变化的所以需要一层抽象来屏蔽这种变化这层抽象叫做Service
提供访问一个或者多个Pod实例稳定的访问地址支持多种访问方式ClusterIP对集群内部访问NodePort对集群外部访问LoadBalancer集群外部负载均衡 3.4 Volume
Volume就是存储卷在Pod中可以声明卷来问访问文件系统同时Volume也是一个抽象层其具体的后端存储可以是本地存储、NFS网络存储、云存储阿里云盘、AWS云盘、Google云盘等、分布式存储比如说像 ceph、GlusterFS
声明在Pod中容器可以访问的文件系统可以被挂载在Pod中一个或多个容器的指定路径下支持多种后端储存 3.5 Namespace
Namespace命令空间是用来做资源的逻辑隔离的比如上面的Pod、Deployment、Service都属于资源不同Namespace下资源可以重名。同一Namespace下资源名需唯一
一个集群内部的逻辑隔离机制鉴权、资源等每个资源都属于一个Namespace同一个Namespace中资源命名唯一不同Namespace中资源可重名 四、K8S安装
具体的安装教程可以参考https://kuboard.cn/install/install-k8s.html 里面写的很详细了此处不再赘述简化过程如下
创建虚拟机2个或者2个以上操作系统为 CentOS 7.8 或者 CentOS Stream 8每个节点CPU 内核数量大于等于 2且内存大于等于 4G实测2G也可以修改网络配置文件/etc/sysconfig/network-scripts/ifcfg-ens33 改成固定IP安装containerd/kubelet/kubeadm/kubectl注意教程中使用的容器运行时为containerd如果需要使用docker可以先安装docker然后跳过脚本中安装containerd的部分初始化-master-节点初始化-worker节点验证在Master节点上执行kubectl get nodes -o wide能看到添加的worker节点即安装成功
我的环境情况如下
NAME STATUS ROLES AGE VERSION INTERNAL-IP
my-master Ready control-plane,master 27h v1.21.0 192.168.108.101
my-node Ready none 27h v1.21.0 192.168.108.102192.168.108.101是Master角色名字为my-master192.168.108.102是Worker角色名字为my-node
五、kubectl常用命令
kubectl 则是 Kubernetes 的命令行工具用于管理 Kubernetes 集群。 kubectl controls the Kubernetes cluster manager. 意为K8S集群管理的控制器kubectl --help可以打印帮助命令。 1查看集群信息
kubectl cluster-info # 显示集群信息。2查看资源状态
kubectl get pods # 查看所有Pod的状态
kubectl get deployments # 查看所有部署的状态
kubectl get services # 查看所有服务的状态
kubectl get nodes # 查看所有节点的状态
kubectl get namespaces # 查看所有命名空间的状态kubectl describe pod pod-name # 显示特定Pod的详细信息
kubectl describe node node-IP/name # 显示特定Node的详细信息3创建和管理资源
kubectl create -f filename # 根据YAML文件创建资源
kubectl apply -f filename # 根据YAML文件创建或更新资源
kubectl delete -f filename # 根据YAML文件删除资源kubectl scale deployment deployment-name --replicasreplica-count # 扩展或缩减部署的副本数
kubectl expose deployment deployment-name --portport --typeservice-type # 创建一个服务来公开部署4执行操作
kubectl exec -it pod-name -- command # 在Pod中执行特定命令
kubectl logs pod-name # 查看Pod的日志
kubectl port-forward pod-name local-port:pod-port # 将本地端口与Pod的端口进行转发5删除资源
kubectl delete deployment deployment-name # 删除部署
kubectl delete pod pod-name # 删除Pod
kubectl delete service service-name # 删除服务六、K8S实战
6.1 水平扩容
为什么先实战水平扩容因为这个最简单首先来部署一个喜闻乐见的nginx
kubectl create deployment web --imagenginx:1.14这句话表示创建一个资源啥资源呢是一个deployment可以简写为deploy取名叫web指定了镜像为nginx的1.14版本但是先别执行这句话我们一般不这么部署应用因为不好复用一般通过yaml文件来部署如下
kubectl create deployment web --imagenginx:1.14 --dry-run -o yaml web.yaml–dry-run表示试运行试一下看行不行但是不运行-o yaml表示以yaml格式输出web.yaml表示将输出的内容重定向到web.yaml文件中
执行之后看看web.yaml文件里面有些什么
apiVersion: apps/v1 # 表示资源版本号为apps/v1
kind: Deployment # 表示这是一个Deployment
metadata: # 一些元数据信息creationTimestamp: nulllabels: # 标签可以随便定义app: webname: web # 这个资源的名字
spec: # 资源的描述或者规格replicas: 1 # 副本数量selector: # 选择器matchLabels: # 需要匹配的标签app: web # 标签的具体键值对strategy: {}template: # 模板。表示Pod的生成规则metadata:creationTimestamp: nulllabels:app: webspec: containers:- image: nginx:1.14 #指定镜像文件name: nginxresources: {}
status: {}用下面的命令应用web.yamlweb.yaml声明了一个Deployment和一个Pod
kubectl apply -f web.yaml执行完后以后可以通过以下命令查看Deployment和Pod
kubectl get deploy,po -o wide结果如下
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/web 1/1 1 1 2m40s nginx nginx:1.14 appwebNAME READY STATUS RESTARTS AGE IP NODE ...
pod/web-5bb6fd4c98-lg555 1/1 Running 0 2m40s 10.100.255.120 my-node ...可以看到资源已经建立起来了运行在Worker节点中尝试访问一下Pod的IP
curl 10.100.255.120有如下nginx的标准返回说明应用已经部署完毕
!DOCTYPE html
html
head
titleWelcome to nginx!/title
...
/html有没有感觉这一路下来挺麻烦的yaml文件还那么长还不如无脑docker run呢别急在后面扩缩容的时候就可以看到它的威力了当然也可以用最开始的命令来执行kubectl create deployment web --imagenginx:1.14测试可以在生产环境中强烈不建议这么做。
【扩容实战】假设现在扩容需求来了需要部署同样的nginx副本10个该怎么做在K8S中很简单直接告诉K8S我要10个副本即可其他的细节不用关心。
具体的做法是修改上面的web.yaml文件将replicas: 1声明成replicas: 10最后再应用一下
kubectl apply -f web.yaml此时快速的执行kubectl get po可以看到一些容器已经开始运行了一些在创建中一些还在挂起
NAME READY STATUS RESTARTS AGE
pod/web-5bb6fd4c98-52qmf 0/1 ContainerCreating 0 1s
pod/web-5bb6fd4c98-5sp5l 0/1 Pending 0 1s
pod/web-5bb6fd4c98-9t2hm 0/1 ContainerCreating 0 1s
pod/web-5bb6fd4c98-lg555 1/1 Running 0 11m
...稍等片刻可以看到所有Pod都是Running状态了当然也可以偷懒一键扩容
kubectl scale deploy web --replicas106.2 自动装箱
根据资源需求和其他约束自动放置容器同时避免影响可用性。将关键性工作负载和尽力而为性质的服务工作负载进行混合放置以提高资源利用率并节省更多资源。
K8S支持多种策略包括节点污点、节点标签、Pod调度策略等。目的是提供最大的灵活性最终提高整体资源利用率这就是自动装箱。
6.2.1 节点污点
Taint 污点节点不做普通分配调度是节点属性属性值有三个
NoSchedule一定不被调度PreferNoSchedule尽量不被调度也有被调度的几率NoExecute不会调度并且还会驱逐Node已有Pod
也就是说给节点打上污点那么调度的时候就会根据上面的属性来进行调度一般来说Master节点的污点值是NoSchedule查看Master污点值
kubectl describe node my-master | grep Taints可以看到如下输出
Taints: node-role.kubernetes.io/master:NoSchedule6.2.2 Pod调度策略
Pod调度策略会影响到Pod最终被调度到哪个节点上Pod调度策略有三类
Pod声明的requests和limits前者就是Pod需要多少资源后者表示Pod最多用多少资源资源比如CPU内存等节点标签选择器会选择符合标签的节点进行调度节点亲和性分为硬亲和和软亲和前者必须满足后者尝试满足不强制
6.3 Secret
Secret意为秘密那在K8S中是啥意思呢在K8S中表示一个存储在etcd中的配置这个配置是秘密的是安全的通常用Base64编码此配置可以通过挂载卷或者环境变量的方式供Pod访问首先定义一个Secret
# 首先将明文转换成base64编码
echo -n root | base64 # 结果是cm9vdA
echo -n 123456 | base64 # 结果是MTIzNDU2通过下面的secret.yaml声明创建一个Secret通过kubectl get secret可以查看刚才创建的Secret
apiVersion: v1
kind: Secret
metadata:name: test-secret
data:username: cm9vdApassword: MTIzNDU26.3.1 挂载卷的方式
声明文件如下:
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: webname: web
spec: replicas: 1selector: matchLabels:app: web strategy: {}template: metadata:labels:app: webspec: containers:- image: nginx:1.14name: nginx# 挂载到容器内volumeMounts:- name: secret-volumemountPath: /etc/secret-volume# 卷声明 volumes:- name: secret-volumesecret:secretName: test-secret
status: {}创建之后进入容器下面是进入容器命令和docker一致你创建出来的Pod不一定是这个名web-66d9b4684b-dvwtm根据实际情况进入
kubectl exec -it web-66d9b4684b-dvwtm bash查看一下挂载的内容
cat /etc/secret-volume/username # 显示root
cat /etc/secret-volume/password # 显示1234566.3.2 环境变量的方式
声明文件如下
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: webname: web
spec: replicas: 1selector: matchLabels:app: web strategy: {}template: metadata:labels:app: webspec: containers:- image: nginx:1.14name: nginx# 环境变量声明env:- name: SECRET_USERNAMEvalueFrom:secretKeyRef:name: test-secretkey: username
status: {}执行后再容器内部查看该环境变量是否符合预期值打印出来的值应该是root即我们设置的Secret
kubectl exec -it web-848bb777bc-x5mh4 -- /bin/sh -c echo $SECRET_USERNAME这里有一个疑问既然是Base64的编码方式不是加密方式为什么说Secret是安全的呢此处的安全是K8S提供的主要是以前几点
传输安全K8S中与API Server的交互都是HTTPS的存储安全Secret被挂载到容器时存储在tmpfs中只存在于内存中而不是磁盘中Pod销毁Secret随之消失访问安全Pod间的Secret是隔离的一个Pod不能访问另一个Pod的Secret
6.4 ConfigMap
ConfigMap可以看做是不需要加密不需要安全属性的Secret也是和配置相关的创建ConfigMap的过程如下首先创建一个配置文件比如redis.properties包含如下内容
redis.port127.0.0.1
redis.port6379
redis.password123456以下命令从文件redis.properties创建了一个名为redis-config的ConfigMap
kubectl create configmap redis-config --from-fileredis.properties使用命令kubectl get configmap可以查看刚才创建的ConfigMap当然ConfigMap也有挂载卷和设置环境变量的方式供Pod调用此处不再赘述。
6.5 存储编排
存储编排可实现自动挂载所选存储系统包括本地存储、诸如 GCP 或 AWS 之类公有云提供商所提供的存储或者诸如 NFS、iSCSI、Gluster、Ceph、Cinder 或 Flocker 这类网络存储系统。
提到存储就不得不说K8S中的PV和PVC了解释如下
PVPersistentVolume持久化卷PVCPersistentVolumeClaim持久化卷声明
PV说白了就是一层存储的抽象底层的存储可以是本地磁盘也可以是网络磁盘比如NFS、Ceph之类既然有了PV那为什么又要搞一个PVC呢
PVC其实在Pod和PV之前又增加了一层抽象这样做的目的在于将Pod的存储行为于具体的存储设备解耦试想一下假设哪天NFS网络存储的IP地址变化了如果没有PVC就需要每个Pod都改一下IP的声明那得多累有PVC来屏蔽这些细节之后只用改PV即可
6.6 服务发现与负载均衡
服务发现与负载均衡可实现无需修改你的应用程序即可使用陌生的服务发现机制。Kubernetes 为容器提供了自己的 IP 地址和一个 DNS 名称并且可以在它们之间实现负载均衡。
到目前为止我们的Pod已经可以实现水平扩缩、自动装箱、配置管理、存储编排了但是访问还是个大问题扩容后这么多Pod应该访问哪一个如果能够自动将流量分配到不同的Pod上负载均衡并且当扩容或者缩容的时候能够动态的将Pod添加或者剔除出负载均衡的范围简而言之就是服务发现。
那么在K8S中有没有东西可以做到服务发现和负载均衡呢答案是有这就是Service还记得前面提到过的核心概念吗Service有三种类型
ClusterIp集群内部访问默认NodePort集群外部访问包含了ClusterIpLoadBalancer对外访问应用使用公有云
6.7 自我修复
自我修复可实现重新启动失败的容器在节点死亡时替换并重新调度容器杀死不响应用户定义的健康检查的容器并且在它们准备好服务之前不会将它们公布给客户端。
6.7.1 Pod重启机制
当Pod异常停止时就会触发Pod的重启机制根据重启策略会表现出不同的行为。
重启策略主要分为以下三种
Always当容器终止退出后总是重启容器默认策略OnFailure当容器异常退出退出状态码非0时才重启Never当容器终止退出从不重启容器
6.7.2 Pod健康检查
健康检查顾名思义就是检查Pod是否健康怎么来定义健康呢假设这么一种情况当程序内部发生了错误已经不能对外提供服务了但此时主程序仍在运行这种情况就是不健康的或者当容器主进程已经启动了但是服务还没有准备好这种情况也是不健康的这就需要从应用层面来检查K8S中定义了两种检查机制
livenessProbe存活检查如果检查失败将杀死容器根据Pod的restartPolicy来操作readinessProbe就绪检查如果检查失败Kubernetes会把Pod从Service endpoints中剔除也就是让客户流量不打到readinessProbe检查失败的Pod上
具体的检查方式支持三种
http Get发送HTTP请求返回200 - 400 范围状态码为成功exec执行Shell命令返回状态码是0为成功tcpSocket发起TCP Socket建立成功
6.8 自动化上线与回滚
Kubernetes 会分步骤地将针对应用或其配置的更改上线同时监视应用程序运行状况以确保你不会同时终止所有实例。如果出现问题Kubernetes 会为你回滚所作更改。你应该充分利用不断成长的部署方案生态系统。
参考资料
K8S原理架构与实战基础篇