YAML是专门用来配置文件的语言,很是简洁和强大。与了解的properties、XML、json等数据格式,习惯以后就会发现愈来愈好用。其实YAML就是结合了大部分的标记语言的特性,整合新开发的。html
YAML文件的特色:node
井井有条、结构清晰; 使用简单、上手容易; 功能强大、语义丰富; 须要特别注意的是: 大小写敏感; 严格要求缩进;
1)YAML文件的组成linux
**Kubernetes中的YAML文件主要由五个一级字段组成,分别是:** * apiVersion:api版本信息; * kind:指定建立资源对象的类型; * metadata:元数据内部的嵌套字段,定义了资源对象的名称、名称空间等; * spec:规范定义资源应该拥有什么样的特性,依靠控制器确保性能能够知足,知足用户指望的状态。 * status:显示资源的当前状态,K8s就是确保当前状态向目标状态无限靠近从而知足用户指望。表明资源当前的状态;
2)获取编写YAML文件的帮助
虽然知道了YAML文件中的一级字段都是什么,可是仍是不知道应该怎么写。能够借助如下命令来获取一些帮助信息。nginx
[root@master ~]# kubectl api-versions //获取当前集群支持的 apiserver版本 [root@master ~]# kubectl api-resources //获取所有的api资源对象 [root@master ~]# kubectl explain deployment //查看k8s某个对象的配置清单格式,应该包含哪些字段及使用方法 [root@master ~]# kubectl explain deployment.spec //这个命令是很是重要的,它能够一级一级来获取帮助
3)YAML文件的基本格式web
[root@master ~]# cat web.yaml kind: Deployment //指定要建立的资源对象 apiVersion: extensions/v1beta1 //指定deployment所对应的API版本信息 metadata: name: web //定义deployment的名称 spec: replicas: 2 //指定副本数量 template: metadata: labels: //指定pod的标签 app: web_server spec: containers: - name: nginx //指定pod运行的容器的名称 image: nginx //指定运行容器所需的镜像
4)生成资源(容器)验证并查看:docker
[root@master yaml]# kubectl apply -f web.yaml [root@master yaml]# kubectl create -f web.yaml //以上两条命令都是用于生成资源的二选一 //apply能够指定屡次,若是发现文件不一样,则更新 //使用“-f”来指定yaml文件,根据yaml文件中定义的内容生成所需的资源 [root@master ~]# kubectl delete -f web.yaml //若是想快速的删除定义的资源能够用此命令 //删除yaml文件中定义的资源 [root@master yaml]# kubectl get deployments. web //查看web控制器所产生的pod NAME READY UP-TO-DATE AVAILABLE AGE web 2/2 2 2 30s //能够看见已经生成了两台容器 [root@master ~]# kubectl describe deployments. web //用于查看web控制器的详细信息的
注:Kubernetes已经根据YAML文件生成了咱们所需的pod资源,这里资源指的就是容器!json
[root@master yaml]# kubectl get pod -o wide //此命令用于查询生成的资源及IP NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES web-d6ff6c799-c7625 1/1 Running 0 4m2s 10.244.2.3 node01 <none> <none> web-d6ff6c799-sgjc9 1/1 Running 0 4m2s 10.244.1.3 node02 <none> <none> [root@master yaml]# curl -I 10.244.2.3 HTTP/1.1 200 OK Server: nginx/1.19.1 Date: Thu, 13 Aug 2020 09:45:14 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Tue, 07 Jul 2020 15:52:25 GMT Connection: keep-alive ETag: "5f049a39-264" Accept-Ranges: bytes //k8s集群内部访问表示是没有问题的 //咱们需解决一个问题pod的服务可以被外部访问到
[root@master ~]# cat web-svc.yaml kind: Service apiVersion: v1 metadata: name: web-svc spec: type: NodePort //指定类型为NodePort,可让外部访问,不然默认状况下是cluster IP,仅限集群内部访问 selector: app: web_server //必须与deployment资源对象的标签进行关联 ports: - protocol: TCP port: 80 //指定要映射到的Cluster IP的端口 targetPort: 80 //指定的是要映射pod中的端口 nodePort: 31000 //指定映射到宿主机的端口,范围是30000~32767 [root@master ~]# kubectl apply -f web-svc.yaml //生成service的控制文件(yaml中已经定义其名称为web-svc) [root@master ~]# kubectl get svc web-svc //查看service控制器 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE web-svc NodePort 10.100.154.1 <none> 80:31000/TCP 35s //TYPE:为NodePort,可使外部访问; //PORT:映射出的端口与咱们定义的同样
访问浏览器测试:vim
# [root@master ~]# kubectl describe svc web-svc //查看service的详细信息
返回的信息以下:后端
[root@master ~]# kubectl get pod -o wide | awk '{print $6}' //提取后端pod的IP地址 IP 10.244.2.3 10.244.1.3 //与上述查询的结果同样!
咱们知道service是有负载均衡的能力,那么是怎么实现的?api
其实,背后的原理并无那么高大上,kube-proxy经过iptables的转发机制来实现负载均衡的效果的,先定义目标IP是service提供的群集IP,而后使用“-j”选项转发到其余iptables规则,接下来验证一下:
[root@master ~]# kubectl get svc web-svc | awk '{print $3}' CLUSTER-IP 10.100.154.1 [root@master ~]# iptables-save | grep 10.100.154.1 -A KUBE-SERVICES ! -s 10.244.0.0/16 -d 10.100.154.1/32 -p tcp -m comment --comment "default/web-svc: cluster IP" -m tcp --dport 80 -j KUBE-MARK-MASQ -A KUBE-SERVICES -d 10.100.154.1/32 -p tcp -m comment --comment "default/web-svc: cluster IP" -m tcp --dport 80 -j KUBE-SVC-3RBUQ3B6P3MTQ3S7 //从上述结果中能够看出,当目标地址是群集IP时,就会转发到KUBE-SVC-3RBUQ3B6P3MTQ3S7规则中
[root@master ~]# iptables-save | grep KUBE-SVC-3RBUQ3B6P3MTQ3S7 :KUBE-SVC-3RBUQ3B6P3MTQ3S7 - [0:0] -A KUBE-NODEPORTS -p tcp -m comment --comment "default/web-svc:" -m tcp --dport 31000 -j KUBE-SVC-3RBUQ3B6P3MTQ3S7 -A KUBE-SERVICES -d 10.100.154.1/32 -p tcp -m comment --comment "default/web-svc: cluster IP" -m tcp --dport 80 -j KUBE-SVC-3RBUQ3B6P3MTQ3S7 -A KUBE-SVC-3RBUQ3B6P3MTQ3S7 -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-YZTKOTIFXSS7FVXI -A KUBE-SVC-3RBUQ3B6P3MTQ3S7 -j KUBE-SEP-MP33GWHNEEMYWCYU //从查询结果中能够看出其负载均衡的效果,由于后端只建立了两个pod,因此其几率为0.5
由此能够看出service实现负载均衡的效果:默认状况下使用iptables规则,固然还可使用其余的方法,这里就不介绍了!
查看负载均衡的详细信息需根据cluster ip为切入口!
实现负载均衡最根本的原理就是i:iptables规则根据random(随机数)实现的负载均衡!
注:此实验须要搭建私有仓库,关于搭建私有仓库registry请参考博客:Docker搭建私有仓库之registry
[root@master ~]# docker pull httpd [root@master ~]# docker tag httpd 192.168.45.129:5000/httpd:v1 [root@master ~]# docker tag httpd 192.168.45.129:5000/httpd:v2 [root@master ~]# docker tag httpd 192.168.45.129:5000/httpd:v3 //将下载的httpd镜像更改一下名称 [root@master ~]# vim /usr/lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd --insecure-registry 192.168.45.129:5000 [root@master ~]# systemctl daemon-reload [root@master ~]# systemctl restart docker.service //重启docker服务 [root@master ~]# docker push 192.168.45.129:5000/httpd:v1 [root@master ~]# docker push 192.168.45.129:5000/httpd:v2 [root@master ~]# docker push 192.168.45.129:5000/httpd:v3 //将定义成不一样版本镜像上传到私有库 [root@master yaml]# cat httpd01.deployment.yaml kind: Deployment apiVersion: extensions/v1beta1 metadata: name: httpd spec: revisionHistoryLimit: 10 //记录历史版本信息为10个 replicas: 3 template: metadata: labels: app: httpd-server spec: containers: - name: httpd image: 192.168.45.129:5000/httpd:v1 //三个版本根据镜像进行区分 ports: //这个只是一个声名没有任何做用 - containerPort: 80 [root@master yaml]# cat httpd02.deployment.yaml kind: Deployment apiVersion: extensions/v1beta1 metadata: name: httpd spec: revisionHistoryLimit: 10 replicas: 3 template: metadata: labels: app: httpd-server spec: containers: - name: httpd image: 192.168.45.129:5000/httpd:v2 //三个版本根据镜像进行区分 ports: - containerPort: 80 [root@master yaml]# cat httpd03.deployment.yaml kind: Deployment apiVersion: extensions/v1beta1 metadata: name: httpd spec: revisionHistoryLimit: 10 replicas: 3 template: metadata: labels: app: httpd-server spec: containers: - name: httpd image: 192.168.45.129:5000/httpd:v3 //三个版本根据镜像进行区分 ports: - containerPort: 80 [root@master yaml]# kubectl apply -f httpd01.deployment.yaml --record //--record的做用就是记录历史版本信息 [root@master yaml]# kubectl rollout history deployment httpd //查看历史的版本信息 deployment.extensions/httpd REVISION CHANGE-CAUSE 1 kubectl apply --filename=httpd01.deployment.yaml --record=true //1,表示版本对应的编号,也能够看出其对应的yaml [root@master yaml]# kubectl apply -f httpd02.deployment.yaml --record [root@master yaml]# kubectl apply -f httpd03.deployment.yaml --record //根据yaml文件进行两次升级 [root@master yaml]# kubectl rollout history deployment httpd deployment.extensions/httpd REVISION CHANGE-CAUSE 1 kubectl apply --filename=httpd01.deployment.yaml --record=true 2 kubectl apply --filename=httpd02.deployment.yaml --record=true 3 kubectl apply --filename=httpd03.deployment.yaml --record=true //确认升级的版本信息已经记录 [root@master yaml]# vim httpd-svc.yaml kind: Service apiVersion: v1 metadata: name: httpd-svc spec: type: NodePort selector: app: httpd-server ports: - protocol: TCP port: 80 targetPort: 80 nodePort: 31000 [root@master yaml]# kubectl apply -f httpd-svc.yaml //建立一个svc便于访问测试 [root@master yaml]# curl 127.0.0.1:31000 <h1>hello bjq:v3</h1> //访问测试页面效果 [root@master yaml]# kubectl rollout undo deployment httpd --to-revision=1 //回滚到版本1,使用--to-revision=1表示,1表示查看历史版本的第一列编号 [root@master yaml]# curl 127.0.0.1:31000 //测试访问 <h1>hello bjq:v1</h1>
[root@master yaml]# kubectl apply -f httpd03.deployment.yaml --record [root@master yaml]# kubectl get deployments. httpd pod -o wide //能够看出当前的httpd服务版本是v3 NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR httpd 3/3 3 3 54m httpd 192.168.45.129:5000/httpd:v3 app=httpd-server Error from server (NotFound): deployments.extensions "pod" not found
若是不指定pod的位置的话,默认状况下,是由K8s中scheduler这个组件来完成的,不能人为的干预。若是是业务须要手动指定的话,那么就须要如下方法:
[root@master yaml]# kubectl label nodes node02 disk=ssd //手动给node02打上一个 disk=ssd的标签 [root@master yaml]# kubectl get nodes --show-labels | grep disk=ssd //查看集群中各个节点的标签(包含disk=ssd) node02 Ready <none> 5d22h v1.15.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disk=ssd,kubernetes.io/arch=amd64,kubernetes.io/hostname=node02,kubernetes.io/os=linux //从结果中能够可看出只有node02包含这个标签 [root@master yaml]# vim httpd.yaml kind: Deployment apiVersion: extensions/v1beta1 metadata: name: httpd spec: revisionHistoryLimit: 10 replicas: 3 template: metadata: labels: app: httpd-server spec: containers: - name: httpd image: 192.168.45.129:5000/httpd:v1 ports: - containerPort: 80 nodeSelector: //指定标签选择器 disk: ssd [root@master yaml]# kubectl apply -f httpd.yaml //根据yaml文件生成所需的pod资源 [root@master yaml]# kubectl get pod NAME READY STATUS RESTARTS AGE httpd-7df55ff7b5-p8ll2 1/1 Running 0 23s httpd-7df55ff7b5-tdh6w 1/1 Running 0 23s httpd-7df55ff7b5-vjbn8 1/1 Running 0 23s //从查询结果中能够看出三个pod资源都运行在node02节点上
注:上述需求已经实现,可是只要有人为干预的地方就会错误的产生,不得不考虑如下这种状况!假若将node02的标签进行删除的话,看一下会发生什么状况!
[root@master yaml]# kubectl label nodes node02 disk- //将node02的disk=ssd的标签进行删除 [root@master yaml]# kubectl get nodes --show-labels | grep disk=ssd //验证,标签已经被删除 [root@master yaml]# kubectl delete -f httpd.yaml //将本来的pod资源进行删除 [root@master yaml]# kubectl apply -f httpd.yaml //从新生成pod资源(yaml文件中依然指定了标签) [root@master yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES httpd-7df55ff7b5-d2s4s 0/1 Pending 0 12s <none> <none> <none> <none> httpd-7df55ff7b5-h66tj 0/1 Pending 0 12s <none> <none> <none> <none> httpd-7df55ff7b5-rz67j 0/1 Pending 0 12s <none> <none> <none> <none> //可是查看pod的状态为Pending,显然这种状态的pod是不正常的
即便标签的不存在的,yaml文件中也指定了标签,建立pod资源时,不会出现错误,可是pod的状态为Pending(等待的状态),解决方法以下:
[root@master yaml]# kubectl describe pod httpd-7df55ff7b5-d2s4s
注:从结果中就已经看出了是由于标签选择器与集群中node的标签不匹配致使的!
若是以上没有发现错误的信息,还需进行如下操做:
[root@master yaml]# kubectl logs -n kube-system kube-scheduler-master //查看Scheduler组件所产生的日志信息 [root@master yaml]# less /var/log/messages | grep kubelet //查看系统日志中包含kubelet组件的信息 //由于kubelet是负责管理pod的