Kubectl命令行管理对象 类型 命令 描述 基础命令 create 通过文件名或标准输入创建资源。 expose 将一个资源公开为一个新的Kubernetes服务。 run 创建并运行一个特定的镜像,可能是副本。 创建一个deployment或job管理创建的容器。 set 配置应用资源。 修改现有应用程序资源。 get 显示一个或多个资源。 explain 文档参考资料。 edit 使用默认的编辑器编辑一个资源。 delete 通过文件名、标准输入、资源名称或标签选择器来删除资源。 部署命令 rollout 管理资源的发布。 rolling-update 执行指定复制控制的滚动更新。 scale 扩容或缩容Pod数量,Deployment、ReplicaSet、RC或Job。 autoscale 创建一个自动选择扩容或缩容并设置Pod数量。 集群管理命令 certificate 修改证书资源。 cluster-info 显示集群信息。 top 显示资源(CPU/Memory/Storage)使用。需要Heapster运行。 cordon 标记节点不可调度。 uncordon 标记节点可调度。 drain 维护期间排除节点。 taint -------------------------------------- Kubectl命令行管理对象 类型 命令 描述 故障诊断和调试命令 describe 显示特定资源或资源组的详细信息。 logs 在pod或指定的资源中容器打印日志。如果pod只有一个容器,容器名称是可选的。 attach 附加到一个进程到一个已经运行的容器。 exec 执行命令到容器。 port-forward 转发一个或多个本地端口到一个pod。 proxy 为kubernetes API Server启动服务代理。 cp 拷贝文件或目录到容器中。 auth 检查授权。 高级命令 apply 通过文件名或标准输入对资源应用配置。 patch 使用补丁修改、更新资源的字段。 replace 通过文件名或标准输入替换一个资源。 convert 不同的API版本之间转换配置文件。YAML和JSON格式都接受。 设置命令 label 更新资源上的标签。 annotate 在一个或多个资源上更新注释。 completion 用于实现kubectl工具自动补全。 其他命令 api-versions 打印受支持的API版本。 config 修改kubeconfig文件(用于访问API,比如配置认证信息)。 help 所有命令帮助。 plugin 运行一个命令行插件。 version 打印客户端和服务版本信息 ------------------------------------ Kubectl命令行管理对象 示例: # 运行应用程序 kubectl run hello-world --replicas=3 --labels="app=example" --image=nginx:1.10 --port=80 # 显示有关Deployments信息 kubectl get deployments hello-world kubectl describe deployments hello-world # 显示有关ReplicaSet信息 kubectl get replicasets kubectl describe replicasets # 创建一个Service对象暴露Deployment(在88端口负载TCP流量) kubectl expose deployment hello-world --port=88 --type=NodePort --target-port=80 --name=example-service # 创建一个Service对象暴露Deployment(在4100端口负载UDP流量) kubectl expose deployment hello-world --port=4100 --type=NodePort --protocol=udp --target-port=80 -- name=example-service # 显示有关Service信息 kubectl describe services example-service # 使用节点IP和节点端口访问应用程序 curl http://<public-node-ip>:<node-port> #根据端口查询服务 netstat -anpt | grep : 端口号 #ingress查看 kubectl get svc -n ingress-ngnix #获取configmap kubuvtl get cm #configmap详细信息 kubectl describe cm configmap名称 #修改configmap kubectl edit configmap configmap名称 #阿里云时间同步服务器 ntpdate ntp1.aliyun.com #获取pv kubectl get pv #获取pvc kubectl get pvc #获取指定pv的内容输出格式为yaml kubectl get pv pv名称 -o yaml #修改内容 kubectl edit pv pv名称 #通过 kubectl replace 命令完成对Node 状态的修改 [root@master node]# kubectl replace -f unschedule_node.yaml node/192.168.0.222 replaced [root@master node]# kubectl get nodes NAME STATUS ROLES AGE VERSION 192.168.0.144 Ready <none> 25d v1.11.6 192.168.0.148 Ready <none> 25d v1.11.6 192.168.0.222 Ready,SchedulingDisabled <none> 5d v1.11.6 #查看Node的状态,可以观察到在Node的状态中增加了一项SchedulingDisabled,对于后续创建的Pod,系统将不会再向该Node进行调度。也可以不使用配置文件,直接使用 kubectl patch 命令完成: kubectl patch node k8s-node-1 -p '{"spec": {"unschedulaable": true}}' #需要注意的是,将某个Node脱离调度范围时,在其上运行的pod并不会自动停止,管理员需要手动停止在改Node是上运行的pod. #同样,如果需要将某个node重新纳入集群调度范围,则将unschedulable 设置为false,再次执行 kubectl replace 或者kubectl patch 命令就能恢复系统对改node的调度。 #第三种方法: #使用kubectl cordon <node_name> 对某个Node 进行隔离调度操作 [root@master node]# kubectl cordon 192.168.0.148 node/192.168.0.148 cordoned [root@master node]# kubectl get nodes NAME STATUS ROLES AGE VERSION 192.168.0.144 Ready <none> 25d v1.11.6 192.168.0.148 Ready,SchedulingDisabled <none> 25d v1.11.6 192.168.0.222 Ready,SchedulingDisabled <none> 5d v1.11.6 #恢复调度操作: [root@master node]# kubectl uncordon 192.168.0.222 node/192.168.0.222 uncordoned [root@master node]# kubectl get nodes NAME STATUS ROLES AGE VERSION 192.168.0.144 Ready <none> 25d v1.11.6 192.168.0.148 Ready <none> 25d v1.11.6 192.168.0.222 Ready <none> 5d v1.11.6 #创建命名空间 kubectl create namespace 名称 #获取命名空间 kubectl get namespace #删除命名空间 kubectl delete namespace 名称 #获取目前API接口信息 kubectl api-resources #对运行时容器进行修改 kubectl patch pod rc-容器app名称-kpiqt -p #对副本扩缩容 kubectl scale rc rc-容器app名称 —replicas=扩缩容数量 #pod对副本自动进行扩缩容 kubectl autoscale rc rc-容器app名称 --min=1 --max=4 kubectl常用命令: kubectl cluster-info #查看集群信息 kubectl describe pod -n kube-system kube-flannel-ds-amd64-trpqq #查看pod的描述信息 kubectl get pods -n kube-system #查看指定命名空间的pod kubectl create deployment NAME --image=image [--dry-run] [options] #创建deployment, dry-run为true就是测试不执行 kubectl create serviceaccount admin -o yaml --dry-run #针对所有可以用kubectl create 创建的资源,都可以加 -o yaml --dry-run ,用来导出yaml标准格式的文件。 kubectl expose deployment nginx-deploy --name=nginx --port=80 --target-port=80 --protocol=TCP #为deployment创建service, --name为service的名字, --port为暴露端口, --target-port为目标pod端口 dig -t A nginx.default.svc.cluster.local @10.96.0.10 #验证是否能正确解析service, @后边的ip为k8s的dns地址 kubectl describe svc nginx #查看名为nginx的这个service的详细信息 kubectl get pods --show-labels #查看pod的标签 kubectl scale deployment nginx-deploy --replicas=3 #扩容或缩容, --replicas为数量 wget -O - -q nginx-deploy kubectl rollout undo deployment myapp-deploy --to-revision=1 #回滚到指定版本, 默认回滚到上一版本 kubectl explain pod #查看pod用法的详细信息(参数选项等)
kubectl工具的使用 #创建 kubectl run nginx --replicas=3 --labels="app=nginx-example" --image=nginx:1.17.4 --port=80 #查看 kubectl get deploy kubectl get pods --show-labels kubectl get pods -l app=example kubectl get pods -o wide #发布 kubectl expose deployment nginx --port=88 --type=NodePort --tartget-port=80 --name=nginx-service kubectl describe service nginx-service #故障排查 kubectl describe TYPE NAME_PREFIX kubectl logs nginx-xxx kubectl exec -it nginx-xxx bash #更新 kubectl set image deployment/nginx nginx=nginx:1.17.4 或 kubectl edit deployment/nginx #资源发布管理 kubectl rollout status deployment/nginx kubectl rollout history deployment/nginx kubectl rollout history deployment/nginx --revision=3 kubectl scale deployment nginx --replicas=10 #回滚 kubectl rollout undo deployment/nginx-deployment kubectl rollout undo deployment/nginx-deployment --to-revision=3 #删除 kubectl delete deploy/nginx kubectl delete svc/nginx-service #写yaml文件用到的api #定义配置时,指定最新稳定版API(当前为v1) kubectl api-versions
YAML配置文件管理对象 对象管理: # 创建deployment资源 kubectl create -f nginx-deployment.yaml # 查看deployment kubectl get deploy # 查看ReplicaSet kubectl get rs # 查看pods所有标签 kubectl get pods --show-labels # 根据标签查看pods kubectl get pods -l app=nginx # 滚动更新镜像 kubectl set image deployment/nginx-deployment nginx=nginx:1.11 或者 kubectl edit deployment/nginx-deployment 或者 kubectl apply -f nginx-deployment.yaml # 实时观察发布状态: kubectl rollout status deployment/nginx-deployment # 查看deployment历史修订版本 kubectl rollout history deployment/nginx-deployment kubectl rollout history deployment/nginx-deployment --revision=3 # 回滚到以前版本 kubectl rollout undo deployment/nginx-deployment kubectl rollout undo deployment/nginx-deployment --to-revision=3 # 扩容deployment的Pod副本数量 kubectl scale deployment nginx-deployment --replicas=10 # 设置启动扩容/缩容 kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
apiVersion: v1 kind: Pod metadata: name: pod-test labels: os: centos spec: containers: - name: hello image: centos:7 env: - name: Test value: "123456" command: ["bash","-c","while true;do date;sleep 1;done"] restartPolicy: OnFailure 支持三种策略: Always:当容器终止退出后,总是重启容器,默认策略。 OnFailure:当容器异常退出(退出状态码非0)时,才重启容器。 Never:当容器终止退出,从不重启容器。
apiVersion: v1 kind: Pod metadata: name: pod-test1 labels: test: centos spec: containers: # 第一个容器 - name: hello-write image: centos:7 command: ["bash","-c","for i in {1..1000};do echo $i >> /data/hello;sleep 1;done"] # 第二个容器 - name: hello-read image: centos:7 command: ["bash","-c","for i in {1..1000};do cat $i >> /data/hello;sleep 1;done"] volumeMounts: - name: data mountPath: /data # 数据卷 volumes: - name: data hostPath: path: /data
apiVersion: v1 kind: Pod metadata: name: nginx-pod labels: app: nginx spec: containers: - name: nginx image: nginx:1.10 ports: - name: http containerPort: 80 hostIP: 0.0.0.0 hostPort: 80 protocol: TCP - name: https containerPort: 443 hostIP: 0.0.0.0 hostPort: 443 protocol: TCP
apiVersion: v1 kind: Pod metadata: name: nginx-pod labels: app: nginx spec: containers: - name: nginx image: nginx:1.10 ports: - containerPort: 80 livenessProbe: httpGet: path: /index.html port: 80
apiVersion: v1 #指定api版本,此值必须在kubectl apiversion中 kind: Pod #指定创建资源的角色/类型 metadata: #资源的元数据/属性 name: web04-pod #资源的名字,在同一个namespace中必须唯一 labels: #设定资源的标签,详情请见http://blog.csdn.net/liyingke112/article/details/77482384 k8s-app: apache version: v1 kubernetes.io/cluster-service: "true" annotations: #自定义注解列表 - name: String #自定义注解名字 spec:#specification of the resource content 指定该资源的内容 restartPolicy: Always #表明该容器一直运行,默认k8s的策略,在此容器退出后,会立即创建一个相同的容器 nodeSelector: #节点选择,先给主机打标签kubectl label nodes kube-node1 zone=node1 zone: node1 containers: - name: web04-pod #容器的名字 image: web:apache #容器使用的镜像地址 imagePullPolicy: Never #三个选择Always、Never、IfNotPresent,每次启动时检查和更新(从registery)images的策略, # Always,每次都检查 # Never,每次都不检查(不管本地是否有) # IfNotPresent,如果本地有就不检查,如果没有就拉取 command: ['sh'] #启动容器的运行命令,将覆盖容器中的Entrypoint,对应Dockefile中的ENTRYPOINT args: ["$(str)"] #启动容器的命令参数,对应Dockerfile中CMD参数 env: #指定容器中的环境变量 - name: str #变量的名字 value: "/etc/run.sh" #变量的值 resources: #资源管理,请求请见http://blog.csdn.net/liyingke112/article/details/77452630 requests: #容器运行时,最低资源需求,也就是说最少需要多少资源容器才能正常运行 cpu: 0.1 #CPU资源(核数),两种方式,浮点数或者是整数+m,0.1=100m,最少值为0.001核(1m) memory: 32Mi #内存使用量 limits: #资源限制 cpu: 0.5 memory: 32Mi ports: - containerPort: 80 #容器开发对外的端口 name: httpd #名称 protocol: TCP livenessProbe: #pod内容器健康检查的设置,详情请见http://blog.csdn.net/liyingke112/article/details/77531584 httpGet: #通过httpget检查健康,返回200-399之间,则认为容器正常 path: / #URI地址 port: 80 #host: 127.0.0.1 #主机地址 scheme: HTTP initialDelaySeconds: 180 #表明第一次检测在容器启动后多长时间后开始 timeoutSeconds: 5 #检测的超时时间 periodSeconds: 15 #检查间隔时间 #也可以用这种方法 #exec: 执行命令的方法进行监测,如果其退出码不为0,则认为容器正常 # command: # - cat # - /tmp/health #也可以用这种方法 #tcpSocket: //通过tcpSocket检查健康 # port: number lifecycle: #生命周期管理 postStart: #容器运行之前运行的任务 exec: command: - 'sh' - 'yum upgrade -y' preStop: #容器关闭之前运行的任务 exec: command: ['service httpd stop'] volumeMounts: #详情请见http://blog.csdn.net/liyingke112/article/details/76577520 - name: volume #挂载设备的名字,与volumes[*].name 需要对应 mountPath: /data #挂载到容器的某个路径下 readOnly: True volumes: #定义一组挂载设备 - name: volume #定义一个挂载设备的名字 #meptyDir: {} hostPath: path: /opt #挂载设备类型为hostPath,路径为宿主机下的/opt,这里设备类型支持很多种
基本管理: # 创建pod资源 kubectl create -f pod.yaml # 查看pods kubectl get pods pod-test # 查看pod描述 kubectl describe pod pod-test # 替换资源 kubectl replace -f pod.yaml -force # 删除资源 kubectl delete pod pod-test 健康管理 提供Probe机制,有以下两种类型: livenessProbe 如果检查失败,将杀死容器,然后根据Pod的重启策略来决定是否 重启。 readinessProbe 如果检查失败,Kubernetes会把Pod从服务代理的分发后端剔除。 Probe支持以下三种检查方法: httpGet 发送HTTP请求,返回200-400范围状态码为成功。 exec 执行Shell命令返回状态码是0为成功。 tcpSocket 发起TCP Socket建立成功。
apiVersion: apps/v1beta2 kind: Deployment metadata: name: nginx-deployment spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.10 ports: - containerPort: 80
apiVersion: extensions/v1beta1 kind: Deployment metadata: <Object> spec: <Object> minReadySeconds: <integer> #设置pod准备就绪的最小秒数 paused: <boolean> #表示部署已暂停并且deploy控制器不会处理该部署 progressDeadlineSeconds: <integer> strategy: <Object> #将现有pod替换为新pod的部署策略 rollingUpdate: <Object> #滚动更新配置参数,仅当类型为RollingUpdate maxSurge: <string> #滚动更新过程产生的最大pod数量,可以是个数,也可以是百分比 maxUnavailable: <string> # type: <string> #部署类型,Recreate,RollingUpdate replicas: <integer> #pods的副本数量 selector: <Object> #pod标签选择器,匹配pod标签,默认使用pods的标签 matchLabels: <map[string]string> key1: value1 key2: value2 matchExpressions: <[]Object> operator: <string> -required- #设定标签键与一组值的关系,In, NotIn, Exists and DoesNotExist key: <string> -required- values: <[]string> revisionHistoryLimit: <integer> #设置保留的历史版本个数,默认是10 rollbackTo: <Object> revision: <integer> #设置回滚的版本,设置为0则回滚到上一个版本 template: <Object> -required- metadata: spec: containers: <[]Object> #容器配置 - name: <string> -required- #容器名、DNS_LABEL image: <string> #镜像 imagePullPolicy: <string> #镜像拉取策略,Always、Never、IfNotPresent ports: <[]Object> - name: #定义端口名 containerPort: #容器暴露的端口 protocol: TCP #或UDP volumeMounts: <[]Object> - name: <string> -required- #设置卷名称 mountPath: <string> -required- #设置需要挂载容器内的路径 readOnly: <boolean> #设置是否只读 livenessProbe: <Object> #就绪探测 exec: command: <[]string> httpGet: port: <string> -required- path: <string> host: <string> httpHeaders: <[]Object> name: <string> -required- value: <string> -required- scheme: <string> initialDelaySeconds: <integer> #设置多少秒后开始探测 failureThreshold: <integer> #设置连续探测多少次失败后,标记为失败,默认三次 successThreshold: <integer> #设置失败后探测的最小连续成功次数,默认为1 timeoutSeconds: <integer> #设置探测超时的秒数,默认1s periodSeconds: <integer> #设置执行探测的频率(以秒为单位),默认1s tcpSocket: <Object> #TCPSocket指定涉及TCP端口的操作 port: <string> -required- #容器暴露的端口 host: <string> #默认pod的IP readinessProbe: <Object> #同livenessProbe resources: <Object> #资源配置 requests: <map[string]string> #最小资源配置 memory: "1024Mi" cpu: "500m" #500m代表0.5CPU limits: <map[string]string> #最大资源配置 memory: cpu: volumes: <[]Object> #数据卷配置 - name: <string> -required- #设置卷名称,与volumeMounts名称对应 hostPath: <Object> #设置挂载宿主机路径 path: <string> -required- type: <string> #类型:DirectoryOrCreate、Directory、FileOrCreate、File、Socket、CharDevice、BlockDevice - name: nfs nfs: <Object> #设置NFS服务器 server: <string> -required- #设置NFS服务器地址 path: <string> -required- #设置NFS服务器路径 readOnly: <boolean> #设置是否只读 - name: configmap configMap: name: <string> #configmap名称 defaultMode: <integer> #权限设置0~0777,默认0664 optional: <boolean> #指定是否必须定义configmap或其keys items: <[]Object> - key: <string> -required- path: <string> -required- mode: <integer> restartPolicy: <string> #重启策略,Always、OnFailure、Never nodeName: <string> nodeSelector: <map[string]string> imagePullSecrets: <[]Object> hostname: <string> hostPID: <boolean> status: <Object>
服务类型: ClusterIP 分配一个内部集群IP地址,只能在集群内部访问(同Namespace内的Pod),默认ServiceType。 NodePort 分配一个内部集群IP地址,并在每个节点上启用一个端口来暴露服务,可以在集群外部访问。 访问地址:<NodeIP>:<NodePort> LoadBalancer 分配一个内部集群IP地址,并在每个节点上启用一个端口来暴露服务。 除此之外,Kubernetes会请求底层云平台上的负载均衡器,将每个Node([NodeIP]:[NodePort])作为后端添加进去。 ExternalName 通过CNAME将Service与externalName的值映射。要求kube-dns的版本为v1.7+。
apiVersion: v1 kind: Service metadata: labels: run: nginx name: nginx namespace: default spec: ports: - port: 88 targetPort: 80 selector: app: nginx
apiVersion: v1 kind: Service metadata: name: my-service spec: selector: app: nginx ports: - name: http protocol: TCP port: 888 targetPort: 80 # 可以指定ip clusterIP: "10.10.10.123" # - name: https # protocol: TCP # port: 443 # targetPort: 9377
apiVersion: v1 kind: Service metadata: name: nginx-service labels: app: nginx spec: selector: app: nginx ports: - name: http port: 8080 targetPort: 80 nodePort: 30001 type: NodePort
Kubernetes是容器集群管理系统,是一个开源的平台,可以实现容器集群的自动化部署、自动扩缩容、维护等功能。
通过Kubernetes你可以:
我们的目标是促进完善组件和工具的生态系统,以减轻应用程序在公有云或私有云中运行的负担。
Kubernetes是Google 2014年创建管理的,是Google 10多年大规模容器管理技术Borg的开源版本。
Kubernetes是Google 2014年创建管理的,是Google 10多年大规模容器管理技术Borg的开源版本。
为什么要使用容器?通过以下两个图对比:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bkWcJzyz-1626275743487)(https://d33wubrfki0l68.cloudfront.net/e7b766e0175f30ae37f7e0e349b87cfe2034a1ae/3e391/images/docs/why_containers.svg#height=150&id=UvIIQ&originHeight=150&originWidth=196&originalType=binary&status=done&style=none&width=196)]
传统的应用部署方式是通过插件或脚本来安装应用。这样做的缺点是应用的运行、配置、管理、所有生存周期将与当前操作系统绑定,这样做并不利于应用的升级更新/回滚等操作,当然也可以通过创建虚机的方式来实现某些功能,但是虚拟机非常重,并不利于可移植性。
新的方式是通过部署容器方式实现,每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。相对于虚拟机,容器能快速部署,由于容器与底层设施、机器文件系统解耦的,所以它能在不同云、不同版本操作系统间进行迁移。
容器占用资源少、部署快,每个应用可以被打包成一个容器镜像,每个应用与容器间成一对一关系也使容器有更大优势,使用容器可以在build或release 的阶段,为应用创建容器镜像,因为每个应用不需要与其余的应用堆栈组合,也不依赖于生产环境基础结构,这使得从研发到测试、生产能提供一致环境。类似地,容器比虚机轻量、更“透明”,这更便于监控和管理。最后,
容器优势总结:
可以在物理或虚拟机的Kubernetes集群上运行容器化应用,Kubernetes能提供一个以“容器为中心的基础架构”,满足在生产环境中运行应用的一些常见需求,如:
Kubernetes的名字来自希腊语,意思是“舵手” 或 “领航员”。_K8s_是将8个字母“ubernete”替换为“8”的缩写。
Master组件提供集群的管理控制中心。
Master组件可以在集群中任何节点上运行。但是为了简单起见,通常在一台VM/机器上启动所有Master组件,并且不会在此VM/机器上运行用户容器。请参考 构建高可用群集以来构建multi-master-VM。
kube-apiserver
kube-apiserver用于暴露Kubernetes API。任何的资源请求/调用操作都是通过kube-apiserver提供的接口进行。请参阅构建高可用群集。
ETCD
etcd是Kubernetes提供默认的存储系统,保存所有集群数据,使用时需要为etcd数据提供备份计划。
kube-controller-manager
kube-controller-manager运行管理控制器,它们是集群中处理常规任务的后台线程。逻辑上,每个控制器是一个单独的进程,但为了降低复杂性,它们都被编译成单个二进制文件,并在单个进程中运行。
这些控制器包括:
cloud-controller-manager
云控制器管理器负责与底层云提供商的平台交互。云控制器管理器是Kubernetes版本1.6中引入的,目前还是Alpha的功能。
云控制器管理器仅运行云提供商特定的(controller loops)控制器循环。可以通过将--cloud-provider
flag设置为external启动kube-controller-manager ,来禁用控制器循环。
cloud-controller-manager 具体功能:
kube-scheduler
kube-scheduler 监视新创建没有分配到Node的Pod,为Pod选择一个Node。
插件 addons
插件(addon)是实现集群pod和Services功能的 。Pod由Deployments,ReplicationController等进行管理。Namespace 插件对象是在kube-system Namespace中创建。
DNS
虽然不严格要求使用插件,但Kubernetes集群都应该具有集群 DNS。
群集 DNS是一个DNS服务器,能够为 Kubernetes services提供 DNS记录。
由Kubernetes启动的容器自动将这个DNS服务器包含在他们的DNS searches中。
了解更多详情
用户界面
kube-ui提供集群状态基础信息查看。更多详细信息,请参阅使用HTTP代理访问Kubernetes API
容器资源监测
容器资源监控提供一个UI浏览监控数据。
Cluster-level Logging
Cluster-level logging,负责保存容器日志,搜索/查看日志。
节点组件运行在Node,提供Kubernetes运行时环境,以及维护Pod。
kubelet
kubelet是主要的节点代理,它会监视已分配给节点的pod,具体功能:
kube-proxy
kube-proxy通过在主机上维护网络规则并执行连接转发来实现Kubernetes服务抽象。
docker
docker用于运行容器。
RKT
rkt运行容器,作为docker工具的替代方案。
supervisord
supervisord是一个轻量级的监控系统,用于保障kubelet和docker运行。
fluentd
fluentd是一个守护进程,可提供cluster-level logging.。
#创建pod kubectl create -f pod配置文件 #运行pod kubectl apply -f pod.yaml #获取pod信息 describe pod 镜像id kubectl get pod kubectl log 镜像的ID -c 容器名称 #删除pod kubectl delete pod podID #pod详细信息 kubectl get pod -o wide
apiVersion: group/apiversion # 如果没有给定group 名称,那么默认为 core,可以使用 kubectl api- versions # 获取当前 k8s 版本上所有的 apiVersion 版本信息( 每个版本可能不同 ) kind: #资源类别 metadata: #资源元数据 name namespace lables annotations # 主要目的是方便用户阅读查找 spec: # 期望的状态(disired state) status: # 当前状态,本字段有 Kubernetes 自身维护,用户不能去定义
[root@k8s-master01 ~]# kubectl api-versions [root@k8s-master01 ~]# kubectl explain pod [root@k8s-master01 ~]# kubectl explain Ingress [root@k8s-master01 ~]# kubectl explain pod
apiVersion: v1 kind: Pod metadata: name: myapp labels: app: myapp version: v1 spec: containers: - name: app images: 镜像名:v1 - name: test images: 镜像名:v1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iBEUZibC-1626275743489)(images%5Cpod%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.png#id=J7m1o&originalType=binary&status=done&style=none)]
当cri在初始化之后,会加载一个pause基础容器,这个是对pod中的所有其他容器服务的,包括数据卷,网络等等,之后会初始化容器Init C,这个容器初始化动作为串行执行,正常退出码为0,不为零会根据重启策略其判断执行,之后执行成功会消亡。加载成功之后进入Main C主容器的运行,在运行起始的时候可以执行一些命令或者脚本,结束的时候也可以运行一些命令和脚本,在运行开始多少秒之后进行readness探测,在readness没探测成功之前pod的状态不能变为running状态;在运行期间,还有liveness参与,liveness主要是探测主容器状态,如果主容器不可用或者异常,执行重启或者删除等操作,根据重启策略来操作。
apiVersion: v1 kind: Pod metadata: name: myapp-pod labels: app: myapp spec: containers: - name: myapp-container image: busybox command: ['sh', '-c', 'echo The app is running! && sleep 3600'] initContainers: - name: init-myservice image: busybox command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;'] - name: init-mydb image: busybox command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
kind: Service apiVersion: v1 metadata: name: myservice spec: ports: - protocol: TCP port: 80 targetPort: 9376 --- kind: Service apiVersion: v1 metadata: name: mydb spec: ports: - protocol: TCP port: 80 targetPort: 9377
apiVersion: v1 kind: Pod metadata: name: readiness-httpget-pod namespace: default spec: containers: - name: readiness-httpget-container image: wangyanglinux/myapp:v1 imagePullPolicy: IfNotPresent readinessProbe: httpGet: port: 80 path: /index1.html initialDelaySeconds: 1 periodSeconds: 3
apiVersion: v1 kind: Pod metadata: name: liveness-exec-pod namespace: default spec: containers: - name: liveness-exec-container image: hub.atguigu.com/library/busybox imagePullPolicy: IfNotPresent command: ["/bin/sh","-c","touch /tmp/live ; sleep 60; rm -rf /tmp/live; sleep 3600"] livenessProbe: exec: command: ["test","-e","/tmp/live"] initialDelaySeconds: 1 periodSeconds: 3
apiVersion: v1 kind: Pod metadata: name: liveness-httpget-pod namespace: default spec: containers: - name: liveness-httpget-container image: hub.atguigu.com/library/myapp:v1 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80 livenessProbe: httpGet: port: http path: /index.html initialDelaySeconds: 1 periodSeconds: 3 timeoutSeconds: 10
apiVersion: v1 kind: Pod metadata: name: probe-tcp spec: containers: - name: nginx image: hub.atguigu.com/library/myapp:v1 livenessProbe: initialDelaySeconds: 5 timeoutSeconds: 1 tcpSocket: port: 80
apiVersion: v1 kind: Pod metadata: name: lifecycle-demo spec: containers: - name: lifecycle-demo-container image: nginx lifecycle: postStart: exec: command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"] preStop: exec: command: ["/bin/sh", "-c", "echo Hello from the poststop handler > /usr/share/message"]
Kubernetes 中内建了很多 controller(控制器),这些相当于一个状态机,用来控制 Pod 的具体状态和行为
Kubernetes 中内建了很多 controller(控制器),这些相当于一个状态机,用来控制 Pod 的具体状态和行为
① ReplicationController 和 ReplicaSet
② Deployment
③ DaemonSet
④ StateFulSet
⑤ Job/CronJob
⑥ Horizontal Pod Autoscaling
ReplicationController(RC)用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的 Pod 来替代;而如果异常多出来的容器也会自动回收;在新版本的 Kubernetes 中建议使用 ReplicaSet 来取代 ReplicationController 。ReplicaSet 跟ReplicationController 没有本质的不同,只是名字不一样,并且 ReplicaSet 支持集合式的 selector(标签 );
Deployment 为 Pod 和 ReplicaSet 提供了一个声明式定义 (declarative) 方法,用来替代以前的ReplicationController 来方便的管理应用。典型的应用场景包括;
① 定义 Deployment 来创建 Pod 和 ReplicaSet
② 滚动升级和回滚应用
③ 扩容和缩容
④ 暂停和继续 Deployment
滚动更新:会创建一个新副本的rs1,旧的rs的pod减少一个时,rs1会新加一个,直到全部增减完成
回滚:同理,需要恢复旧的rs时,会启动rs,再进行增减操作
DaemonSet确保全部(或者一些)Node 上运行一个 Pod 的副本。当有 Node 加入集群时,也会为他们新增一个Pod 。当有 Node 从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod
使用 DaemonSet 的一些典型用法:
① 运行集群存储 daemon,例如在每个 Node 上运行glusterd、ceph
② 在每个 Node 上运行日志收集 daemon,例如fluentd、logstash
③ 在每个 Node 上运行监控 daemon,例如Prometheus Node Exporter、collectd、Datadog 代理、New Relic 代理,或 Ganglia gmond
Job 负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个 Pod 成功结束
管理基于时间的 Job,即:
使用前提条件:当前使用的 Kubernetes 集群,版本 >= 1.8(对 CronJob)。对于先前版本的集群,版本 <1.8,启动 API Server时,通过传递选项–runtime-config=batch/v2alpha1=true可以开启 batch/v2alpha1API
典型的用法如下所示:
在给定的时间点调度 Job 运行
创建周期性运行的 Job,例如:数据库备份、发送邮件
StatefulSet 作为 Controller 为 Pod 提供唯一的标识。它可以保证部署和 scale 的顺序
StatefulSet是为了解决有状态服务的问题(对应Deployments和ReplicaSets是为无状态服务而设计),其应用场景包括:
① 稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现
② 稳定的网络标志,即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有Cluster IP的Service)来实现
③ 有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现
④ 有序收缩,有序删除(即从N-1到0)
应用的资源使用率通常都有高峰和低谷的时候,如何削峰填谷,提高集群的整体资源利用率,让service中的Pod个数自动调整呢?这就有赖于Horizontal Pod Autoscaling了,顾名思义,使Pod水平自动缩放
主要的作用就是用来确保容器应用的副本数始终保持在用户定义的副本数。即如果有容器异常退出,会自动创建新的Pod来替代;而如果异常多出来的容器也会自动回收
Kubernetes 官方建议使用 RS(ReplicaSet )替代 RC (ReplicationController )进行部署,RS 跟 RC 没有本质的不同,只是名字不一样,并且 RS 支持集合式的 selector
查看RS完整模板信息:kubectl explain rs
RS创建模板
apiVersion: extensions/v1beta1 kind: ReplicaSet metadata: name: frontend spec: replicas: 3 selector: matchLabels: tier: frontend template: metadata: labels: tier: frontend spec: containers: - name: myapp image: hub.lqz.com/library/nginx:V1 env: - name: GET_HOSTS_FROM value: dns ports: - containerPort: 80
资源控制器所创建的pod,删除后会被新建
kubectl get pod --show-labels 查看标签
Deployment 为 Pod 和 ReplicaSet 提供了一个声明式定义(declarative)方法,用来替代以前的ReplicationController 来方便的管理应用。典型的应用场景包括:
① 定义Deployment来创建Pod和ReplicaSet
② 滚动升级和回滚
③ 应用扩容和缩容
④ 暂停和继续Deployment
1、创建
kubectl apply -f deployment.yaml --record
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 3 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80
kubectl create -f https://kubernetes.io/docs/user-guide/nginx-deployment.yaml --record## --record参数可以记录命令,我们可以很方便的查看每次 revision 的变化
2、扩容
kubectl scale deployment nginx-deployment --replicas 10
3、如果集群支持 horizontal pod autoscaling 的话,还可以为Deployment设置自动扩展
kubectl autoscale deployment nginx-deployment --min=10–max=15–cpu-percent=80
4、更新镜像也比较简单
kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
5、回滚
kubectl rollout undo deployment/nginx-deployment
6、更新 Deployment
6.1假如我们现在想要让 nginx pod 使用nginx:1.9.1的镜像来代替原来的nginx:1.7.9的镜像
kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1deployment “nginx-deployment” image updated
6.2可以使用edit命令来编辑 Deployment
kubectl edit deployment/nginx-deploymentdeployment “nginx-deployment” edited
6.3查看 rollout 的状态
kubectl rollout status deployment/nginx-deployment
6.4查看历史 RS
6.5 Deployment 更新策略
6.6Rollover(多个rollout并行)
假如您创建了一个有5个niginx:1.7.9 replica的 Deployment,但是当还只有3个nginx:1.7.9的 replica 创建出来的时候您就开始更新含有5个nginx:1.9.1 replica 的 Deployment。在这种情况下,Deployment 会立即杀掉已创建的3个nginx:1.7.9的 Pod,并开始创建nginx:1.9.1的 Pod。它不会等到所有的5个nginx:1.7.9的Pod 都创建完成后才开始改变航道
6.7回退 Deployment
kubectl set image deployment/nginx-deployment nginx=nginx:1.91 kubectl rollout status deployments nginx-deployment kubectl get pods kubectl rollout history deployment/nginx-deployment kubectl rollout undo deployment/nginx-deployment ## 可以使用 --revision参数指定某个历史版本 kubectl rollout undo deployment/nginx-deployment --to-revision=2 ## 暂停 deployment 的更新 kubectl rollout pause deployment/nginx-deployment
您可以用kubectl rollout status命令查看 Deployment 是否完成。如果 rollout 成功完成,kubectl rolloutstatus将返回一个0值的 Exit Code
6.8清理 Policy
您可以通过设置.spec.revisonHistoryLimit项来指定 deployment 最多保留多少 revision 历史记录。默认的会保留所有的 revision;如果将该项设置为0,Deployment 就不允许回退了
apiVersion: apps/v1 kind: DaemonSet metadata: name: daemon-example labels: app: daemonSet spec: selector: metchLables: name: daemon-example template: metadatas: lables: name: daemon-example spec: containers: - name: daemon-example images: 容器镜像:版本
Job 负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个 Pod 成功结束
特殊说明
spec.template格式同Pod
RestartPolicy仅支持Never或OnFailure
单个Pod时,默认Pod成功运行后Job即结束
spec.completions 标志Job结束需要成功运行的Pod个数,默认为1
spec.parallelism 标志并行运行的Pod的个数,默认为1
spec.activeDeadlineSeconds 标志失败Pod的重试最大时间,超过这个时间不会继续重试
apiVersion: batch/v1 kind: Job metadata: name: pi spec: template: metadata: name: pi spec: containers: - name: pi images: per1 command: ["per1", "-Mbignum=bpi", "-wle", "print bpi(2000)"] restartPolicy: Nerver
CronJob Spec
spec.template格式同Pod
RestartPolicy仅支持Never或OnFailure
单个Pod时,默认Pod成功运行后Job即结束
spec.completions 标志Job结束需要成功运行的Pod个数,默认为1
spec.parallelism 标志并行运行的Pod的个数,默认为1
spec.activeDeadlineSeconds 标志失败Pod的重试最大时间,超过这个时间不会继续重试
CronJob
Cron Job 管理基于时间的 Job,即:
在给定时间点只运行一次
周期性地在给定时间点运行
使用条件:当前使用的 Kubernetes 集群,版本 >= 1.8(对 CronJob)
典型的用法如下所示:
在给定的时间点调度 Job 运行
创建周期性运行的 Job,例如:数据库备份、发送邮件
CronJob Spec
.spec.schedule :调度,必需字段,指定任务运行周期,格式同 Cron
.spec.jobTemplate :Job 模板,必需字段,指定需要运行的任务,格式同 Job
.spec.startingDeadlineSeconds :启动 Job 的期限(秒级别),该字段是可选的。如果因为任何原因而错
过了被调度的时间,那么错过执行时间的 Job 将被认为是失败的。如果没有指定,则没有期限
.spec.concurrencyPolicy :并发策略,该字段也是可选的。它指定了如何处理被 Cron Job 创建的 Job 的
并发执行。只允许指定下面策略中的一种:
Allow (默认):允许并发运行 Job
Forbid :禁止并发运行,如果前一个还没有完成,则直接跳过下一个
Replace :取消当前正在运行的 Job,用一个新的来替换
注意,当前策略只能应用于同一个 Cron Job 创建的 Job。如果存在多个 Cron Job,它们创建的 Job 之间总
是允许并发运行。
spec.suspend :挂起,该字段也是可选的。如果设置为 true ,后续所有执行都会被挂起。它对已经开始
执行的 Job 不起作用。默认值为 false 。
spec.successfulJobsHistoryLimit 和
spec.failedJobsHistoryLimit :历史限制,是可选的字段。它
们指定了可以保留多少完成和失败的 Job。默认情况下,它们分别设置为 3 和 1 。设置限制的值为 0 ,相
关类型的 Job 完成后将不会被保留。
apiVersion: batch/v1beta1 kind: CronJob metadata: name: hello spec: #每一分钟执行一次 schedule: "*/1 * * * *" jobTemplate: spec: template: spec: containers: - name: hello images: busybox atgs: - /bin/sh - -C - data; echo Hello from the Kubernetes cluster restartPolicy: OnFailure
$ kubectl get cronjob NAME SCHEDULE SUSPEND ACTIVE LAST-SCHEDULE hello */1 * * * * False 0 <none> $ kubectl get jobs NAME DESIRED SUCCESSFUL AGE hello-1202039034 1 1 49s $ pods=$(kubectl get pods --selector=job-name=hello-1202039034 --output=jsonpath= {.items..metadata.name}) $ kubectl logs $pods Mon Aug 29 21:34:09 UTC 2016 Hello from the Kubernetes cluster # 注意,删除 cronjob 的时候不会自动删除 job,这些 job 可以用 kubectl delete job 来删除 $ kubectl delete cronjob hello cronjob "hello" deleted
Kubernetes Service定义了这样一种抽象:一个Pod的逻辑分组,一种可以访问它们的策略 —— 通常称为微服务。这一组Pod能够被Service访问到,通常是通过Label Selector
Service能够提供负载均衡的能力,但是在使用上有以下限制:只提供 4 层负载均衡能力,而没有 7 层功能,但有时我们可能需要更多的匹配规则来转发请求,这点上 4 层负载均衡是不支持的
Service 在 K8s 中有以下四种类型ClusterIp:
① 默认类型,自动分配一个仅 Cluster 内部可以访问的虚拟 IP
② NodePort:在 ClusterIP 基础上为 Service 在每台机器上绑定一个端口,这样就可以通过:NodePort 来访问该服务
③ LoadBalancer:在 NodePort 的基础上,借助 cloud provider 创建一个外部负载均衡器,并将请求转发到: NodePort
④ ExternalName:把集群外部的服务引入到集群内部来,在集群内部直接使用。没有任何类型代理被创建,这只有 kubernetes 1.7 或更高版本的 kube-dns 才支持
svc基础导论
总结
客户端访问节点时通过iptables实现的,
iptables规则是通过kube-proxy写入的,
apiserver通过监控kube-proxy去进行对服务和端点的监控,
kube-proxy通过pod的标签(lables)去判断这个断点信息是否写入到Endpoints里去。
在 Kubernetes 集群中,每个 Node 运行一个kube-proxy进程。kube-proxy负责为Service实现了一种VIP(虚拟 IP)的形式,而不是ExternalName的形式。在 Kubernetes v1.0 版本,代理完全在 userspace。在Kubernetes v1.1 版本,新增了 iptables 代理,但并不是默认的运行模式。从 Kubernetes v1.2 起,默认就是iptables 代理。在 Kubernetes v1.8.0-beta.0 中,添加了 ipvs 代理
在 Kubernetes 1.14 版本开始默认使用ipvs 代理
在 Kubernetes v1.0 版本,Service是 “4层”(TCP/UDP over IP)概念。在 Kubernetes v1.1 版本,新增了Ingress API(beta 版),用来表示 “7层”(HTTP)服务
DNS会在很多的客户端里进行缓存,很多服务在访问DNS进行域名解析完成、得到地址后不会对DNS的解析进行清除缓存的操作,所以一旦有他的地址信息后,不管访问几次还是原来的地址信息,导致负载均衡无效。
这种模式,kube-proxy 会监视 Kubernetes Service对象和Endpoints,调用netlink接口以相应地创建ipvs 规则并定期与 Kubernetes Service对象和Endpoints对象同步 ipvs 规则,以确保 ipvs 状态与期望一致。访问服务时,流量将被重定向到其中一个后端 Pod
与 iptables 类似,ipvs 于 netfilter 的 hook 功能,但使用哈希表作为底层数据结构并在内核空间中工作。这意味着 ipvs 可以更快地重定向流量,并且在同步代理规则时具有更好的性能。此外,ipvs 为负载均衡算法提供了更多选项,例如:
① rr:轮询调度
② lc:最小连接数
③ dh:目标哈希
④ sh:源哈希
⑤ sed:最短期望延迟
⑥ nq:不排队调度
clusterIP 主要在每个 node 节点使用 iptables,将发向 clusterIP 对应端口的数据,转发到 kube-proxy 中。然后 kube-proxy 自己内部实现有负载均衡的方法,并可以查询到这个 service 下对应 pod 的地址和端口,进而把数据转发给对应的 pod 的地址和端口
为了实现图上的功能,主要需要以下几个组件的协同工作:
创建 myapp-deploy.yaml 文件
apiVersion: apps/v1 kind: Deployment metadata: name: myapp-deploy namespace: default spec: replicas: 3 selector: matchLabels: app: myapp release: stabel template: metadata: labels: app: myapp release: stabel env: test spec: containers: - name: myapp image: wangyanglinux/myapp:v2 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80
创建service
apiVersion: v1 kind: Service metadata: name: myapp namespace: default spec: type: ClusterIP selector: app: myapp release: stabel ports: - name: http port: 80 targetPort: 80
有时不需要或不想要负载均衡,以及单独的 Service IP 。遇到这种情况,可以通过指定 ClusterIP(spec.clusterIP) 的值为 “None” 来创建 Headless Service 。这类 Service 并不会分配 Cluster IP, kube-proxy 不会处理它们,而且平台也不会为它们进行负载均衡和路由
[root@k8s-master mainfests]# vim myapp-svc-headless.yaml apiVersion: v1 kind: Service metadata: name: myapp-headless namespace: default spec: selector: app: myapp clusterIP: "None" ports: - port: 80 targetPort: 80 [root@k8s-master mainfests]# dig -t A myapp-headless.default.svc.cluster.local. @10.96.0.10
的原理在于在 node 上开了一个端口,将向该端口的流量导入到 kube-proxy,然后由 kube-proxy 进一步到给对应的 pod
类型 命令 描述 基础命令 create 通过文件名或标准输入创建资源 expose 将一个资源公开为一个新的Service run 在集群中运行一个特定的镜像 set 在对象上设置特定的功能 get 显示一个或多个资源 explain 文档参考资料。 edit 使用默认的编辑器编辑一个资源。 delete 通过文件名、标准输入、资源名称或标签选择器来删除资源。 部署命令 rollout 管理资源的发布 rolling-update 对给定的复制控制器滚动更新 scale 扩容或缩容Pod数量,Deployment、ReplicaSet、RC或Job autoscale 创建一个自动选择扩容或缩容并设置Pod数量 集群管理命令 certificate 修改证书资源 cluster-info 显示集群信息 top 显示资源(CPU/Memory/Storage)使用。需要Heapster运行 cordon 标记节点不可调度 uncordon 标记节点可调度 drain 维护期间排除节点 taint
[root@master manifests]# vim myapp-service.yaml apiVersion: v1 kind: Service metadata: name: myapp namespace: default spec: type: NodePort selector: app: myapp release: stabel ports: - name: http port: 80 targetPort: 80 查看流程 iptables -t nat -nv
loadBalancer 和 nodePort 其实是同一种方式。区别在于 loadBalancer 比 nodePort 多了一步,就是可以调用cloud provider 去创建 LB 来向节点导流(LB收费)
这种类型的 Service 通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容( 例如:hub.atguigu.com )。ExternalName Service 是 Service 的特例,它没有 selector,也没有定义任何的端口和Endpoint。相反的,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务
kind: Service apiVersion: v1 metadata: name: my-service-1 namespace: default spec: type: ExternalName externalName: hub.atguigu.com
当查询主机 my-service.defalut.svc.cluster.local ( SVC_NAME.NAMESPACE.svc.cluster.local )时,集群的DNS 服务将返回一个值 my.database.example.com 的 CNAME 记录。访问这个服务的工作方式和其他的相同,唯一不同的是重定向发生在 DNS 层,而且不会进行代理或转发
Ingress-Nginx github 地址:https://github.com/kubernetes/ingress-nginx
Ingress-Nginx 官方网站:https://kubernetes.github.io/ingress-nginx/
进入官方下载
**wget **https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
kubectl apply -f mandatory.yaml kubectl apply -f service-nodeport.yaml
Ingress HTTP 代理访问
deployment、Service、Ingress Yaml 文件
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nginx-dm spec: replicas: 2 template: metadata: labels: name: nginx spec: containers: - name: nginx image: wangyanglinux/myapp:v1 imagePullPolicy: IfNotPresent ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx-svc spec: ports: - port: 80 targetPort: 80 protocol: TCP selector: name: nginx --- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: nginx-test spec: rules: - host: www1.atguigu.com http: paths: - path: / backend: serviceName: nginx-svc servicePort: 80
创建证书,以及 cert 存储方式
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj"/CN=nginxsvc/O=nginxsvc" kubectl create secret tls tls-secret --key tls.key --cert tls.crt
deployment、Service、Ingress Yaml 文件
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: nginx-test spec: tls: - hosts: - foo.bar.com secretName: tls-secret rules: - host: foo.bar.com http: paths: - path: / backend: serviceName: nginx-svc servicePort: 80
yum -y install httpd htpasswd -c auth foo kubectl create secret generic basic-auth --from-file=auth
yaml
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-with-auth annotations: nginx.ingress.kubernetes.io/auth-type: basic nginx.ingress.kubernetes.io/auth-secret: basic-auth nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - foo' spec: rules: - host: foo2.bar.com http: paths: - path: / backend: serviceName: nginx-svc servicePort: 80
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: nginx-test annotations: nginx.ingress.kubernetes.io/rewrite-target: http://foo.bar.com:31795/hostname.html spec: rules: - host: foo10.bar.com http: paths: - path: / backend: serviceName: nginx-svc servicePort: 80
ConfigMap 功能在 Kubernetes1.2 版本中引入,许多应用程序会从配置文件、命令行参数或环境变量中读取配置信息。ConfigMap API 给我们提供了向容器中注入配置信息的机制,ConfigMap 可以被用来保存单个属性,也可以用来保存整个配置文件或者 JSON 二进制大对象
ConfigMap 的创建存储之ConfigMap
$ ls docs/user-guide/configmap/kubectl/ game.properties ui.properties $ cat docs/user-guide/configmap/kubectl/game.properties enemies=aliens lives=3 enemies.cheat=true enemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=true secret.code.lives=30 $ cat docs/user-guide/configmap/kubectl/ui.properties color.good=purple color.bad=yellow allow.textmode=true how.nice.to.look=fairlyNice $ kubectl create configmap game-config --from-file=docs/user-guide/configmap/kubectl game-config :configmap的名称 --from-file:指定一个目录,目录下的所有内容都会被创建出来。以键值对的形式 —from-file指定在目录下的所有文件都会被用在 ConfigMap 里面创建一个键值对,键的名字就是文件名,值就是文件的内容
kubectl get cm 查看configmap文件 kubectl get cm game-config -o yaml 查看详细信息 kubectl describe cm
只要指定为一个文件就可以从单个文件中创建 ConfigMap
$ kubectl create configmap game-config-2 --from-file=docs/user-guide/configmap/kubectl/game.properties $ kubectlget configmaps game-config-2 -o yaml
–from-file这个参数可以使用多次,你可以使用两次分别指定上个实例中的那两个配置文件,效果就跟指定整个目录是一样的
使用文字值创建,利用—from-literal参数传递配置信息,该参数可以使用多次,格式如下
$ kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm $ kubectlget configmaps special-config -o yaml #查看 --from-literal=special.how=very 指定键名为special.how 键值为very
apiVersion: v1 kind: ConfigMap metadata: name: special-config namespace: default data: special.how: very special.type: charm
apiVersion: v1 kind: ConfigMap metadata: name: env-config namespace: default data: log_level: INFO
#将两个ConfigMap文件注入到pod环境中 apiVersion: v1 kind: Pod metadata: name: dapi-test-pod spec: containers: - name: test-container image: hub.atguigu.com/library/myapp:v1 command: ["/bin/sh","-c","env"] env: #第一种导入方案 - name: SPECIAL_LEVEL_KEY valueFrom: configMapKeyRef: name: special-config #从那个configMap文件导入 key: special.how #导入的是那个键的键名,就是将special.how键的键值赋予 - name: SPECIAL_TYPE_KEY valueFrom: configMapKeyRef: name: special-config key: special.type envFrom: #第二种导入方案 - configMapRef: name: env-config restartPolicy: Never
apiVersion: v1 kind: ConfigMap metadata: name: special-config namespace: default data: special.how: very special.type: charm
apiVersion: v1 kind: Pod metadata: name: dapi-test-pod spec: containers: - name: test-container image: hub.atguigu.com/library/myapp:v1 command: ["/bin/sh","-c","echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)"] env: - name: SPECIAL_LEVEL_KEY valueFrom: configMapKeyRef: name: special-config key: special.how - name: SPECIAL_TYPE_KEY valueFrom: configMapKeyRef: name: special-config key: special.type restartPolicy: Never
apiVersion: v1 kind: ConfigMap metadata: name: special-config namespace: default data: special.how: very special.type: charm
在数据卷里面使用这个 ConfigMap,有不同的选项。最基本的就是将文件填入数据卷,在这个文件中,键就是文件名,键值就是文件内容
apiVersion: v1 kind: Pod metadata: name: dapi-test-pod spec: containers: - name: test-container image: hub.atguigu.com/library/myapp:v1 command: ["/bin/sh","-c","cat /etc/config/special.how"] volumeMounts: #容器下进行volum挂载 - name: config-volume #挂载的名称为config-volume,与下边相呼应 mountPath: /etc/config volumes: - name: config-volume #名称为config-volume configMap: #从configMap导入 name: special-config #导入的configMap名称 restartPolicy: Never
#创建一个configMap apiVersion: v1 kind: ConfigMap metadata: name: log-config namespace: default data: log_level: INFO --- #创建Deployment对configMap进行调用,调用的方式是以volum方式进行挂载 apiVersion: extensions/v1beta1 kind: Deployment metadata: name: my-nginx spec: replicas: 1 template: metadata: labels: run: my-nginx spec: containers: - name: my-nginx image: hub.atguigu.com/library/myapp:v1 ports: - containerPort: 80 volumeMounts: - name: config-volume mountPath: /etc/config volumes: - name: config-volume configMap: name: log-config
#获取信息 $ kubectl exec `kubectl get pods -l run=my-nginx -o=name|cut -d "/" -f2`cat/etc/config/log_level INFO
修改 ConfigMap
$ kubectl edit configmap log-config
修改log_level的值为DEBUG等待大概 10 秒钟时间,再次查看环境变量的值
$ kubectl exec `kubectl get pods -l run=my-nginx -o=name|cut -d "/" -f2`cat /tmp/log_levelDEBUG
ConfigMap 更新后滚动更新 Pod
更新 ConfigMap 目前并不会触发相关 Pod 的滚动更新,可以通过修改 pod annotations 的方式强制触发滚动更新
$ kubectl patch deployment my-nginx --patch'{"spec": {"template": {"metadata": {"annotations":{"version/config": "20190411" }}}}}'
这个例子里我们在.spec.template.metadata.annotations中添加version/config,每次通过修改version/config来触发滚动更新
!!!更新 ConfigMap 后:使用该 ConfigMap 挂载的 Env 不会同步更新使用该 ConfigMap 挂载的 Volume 中的数据需要一段时间(实测大概10秒)才能同步更新
Secret 解决了密码、token、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者 Pod Spec中。Secret 可以以 Volume 或者环境变量的方式使用
① Service Account:用来访问 Kubernetes API,由 Kubernetes 自动创建,并且会自动挂载到 Pod 的/run/secrets/kubernetes.io/serviceaccount目录中
② Opaque:base64编码格式的Secret,用来存储密码、密钥等
③ kubernetes.io/dockerconfigjson:用来存储私有 docker registry 的认证信息
Service Account 用来访问 Kubernetes API,由 Kubernetes 自动创建,并且会自动挂载到 Pod的/run/secrets/kubernetes.io/serviceaccount目录中
Opaque 类型的数据是一个 map 类型,要求 value 是 base64 编码格式:
$ echo-n"admin" | base64 YWRtaW4= $ echo-n"1f2d1e2e67df" | base64 MWYyZDFlMmU2N2Rm
secrets.yml
apiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque data: password: MWYyZDFlMmU2N2Rm username: YWRtaW4=
1)、将 Secret 挂载到 Volume 中
apiVersion: v1 kind: Pod metadata: labels: name: seret-test name: seret-test spec: volumes: - name: secrets secret: secretName: mysecret containers: - image: hub.atguigu.com/library/myapp:v1 name: db volumeMounts: - name: secrets mountPath: "" #挂载目录 readOnly: true
2)、将 Secret 导出到环境变量中
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: pod-deployment spec: replicas: 2 template: metadata: labels: app: pod-deployment spec: containers: - name: pod-1 image: hub.atguigu.com/library/myapp:v1 ports: - containerPort: 80 env: - name: TEST_USER valueFrom: secretKeyRef: name: mysecret key: username - name: TEST_PASSWORD valueFrom: secretKeyRef: name: mysecret key: password
使用 Kuberctl 创建 docker registry 认证的 secret
$ kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAILsecret "myregistrykey" created.
在创建 Pod 的时候,通过imagePullSecrets来引用刚创建的 `myregistrykey
apiVersion: v1 kind: Pod metadata: name: foo spec: containers: - name: foo image: roc/awangyang:v1 imagePullSecrets: - name: myregistrykey
容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题。首先,当容器崩溃时,kubelet 会重启它,但是容器中的文件将丢失——容器以干净的状态(镜像最初的状态)重新启动。其次,在Pod中同时运行多个容器时,这些容器之间通常需要共享文件。Kubernetes 中的Volume抽象就很好的解决了这些问题
Kubernetes 中的卷有明确的寿命 —— 与封装它的 Pod 相同。所f以,卷的生命比 Pod 中的所有容器都长,当这个容器重启时数据仍然得以保存。当然,当 Pod 不再存在时,卷也将不复存在。也许更重要的是,Kubernetes支持多种类型的卷,Pod 可以同时使用任意数量的卷
当 Pod 被分配给节点时,首先创建emptyDir卷,并且只要该 Pod 在该节点上运行,该卷就会存在。正如卷的名字所述,它最初是空的。Pod 中的容器可以读取和写入emptyDir卷中的相同文件,尽管该卷可以挂载到每个容器中的相同或不同路径上。当出于任何原因从节点中删除 Pod 时,emptyDir中的数据将被永久删除
emptyDir的用法有:
① 暂存空间,例如用于基于磁盘的合并排序
② 用作长时间计算崩溃恢复时的检查点
③ Web服务器容器提供数据时,保存内容管理器容器提取的文件
apiVersion: v1 kind: Pod metadata: name: test-pd spec: containers: - image: k8s.gcr.io/test-webserver name: test-container volumeMounts: - mountPath: /cache name: cache-volume volumes: - name: cache-volume emptyDir: {}
卷将主机节点的文件系统中的文件或目录挂载到集群中
hostPath的用途如下:
① 运行需要访问 Docker 内部的容器;使用/var/lib/docker的hostPath
② 在容器中运行 cAdvisor;使用/dev/cgroups的hostPath
③ 允许 pod 指定给定的 hostPath 是否应该在 pod 运行之前存在,是否应该创建,以及它应该以什么形式存在
除了所需的path属性之外,用户还可以为hostPath卷指定type
空字符串(默认)用于向后兼容,这意味着在挂载 hostPath 卷之前不会执行任何检查
值 | 行为 |
---|---|
空字符串(默认)用于向后兼容,这意味着在挂载 hostPath 卷之前不会执行任何检查 | |
DirectoryOrCreate | 如果在给定的路径上没有任何东西存在,那么将根据需要在那里创建一个空目录,权限设置为0755,与Kubelet具有相同的组和所有权。 |
Directory | 给定的路径下必须存在目录 |
FileOrCreate | 如果在给定的路径上没有任何东西存在,那么会根据需要创建一个空文件,权限设置为0644,与Kubelet具有相同的组和所有权。 |
File | 给定的路径下必须存在文件 |
Socket | 给定的路径下必须存在UNIX套接字 |
CharDevice | 给定的路径下必须存在字符设备 |
BlockDevice | 给定的路径下必须存在块设备 |
使用这种卷类型是请注意,因为:
① 由于每个节点上的文件都不同,具有相同配置(例如从 podTemplate 创建的)的 pod 在不同节点上的行为可能会有所不同
② 当 Kubernetes 按照计划添加资源感知调度时,将无法考虑hostPath使用的资源
③ 在底层主机上创建的文件或目录只能由 root 写入。您需要在特权容器中以 root 身份运行进程,或修改主机上的文件权限以便写入hostPath卷
apiVersion: v1 kind: Pod metadata: name: test-pd spec: containers: - image: k8s.gcr.io/test-webserver name: test-container volumeMounts: - mountPath: /test-pd name: test-volume volumes: - name: test-volume hostPath: # directory location on host path: /data # this field is optional type: Directory type: Directory
是由管理员设置的存储,它是群集的一部分。就像节点是集群中的资源一样,PV 也是集群中的资源。 PV 是 Volume 之类的卷插件,但具有独立于使用 PV 的 Pod 的生命周期。此 API 对象包含存储实现的细节,即 NFS、
iSCSI 或特定于云供应商的存储系统
是用户存储的请求。它与 Pod 相似。Pod 消耗节点资源,PVC 消耗 PV 资源。Pod 可以请求特定级别的资源
(CPU 和内存)。声明可以请求特定的大小和访问模式(例如,可以以读/写一次或 只读多次模式挂载)
集群管理员创建一些 PV。它们带有可供群集用户使用的实际存储的细节。它们存在于 Kubernetes API 中,可用
于消费
当管理员创建的静态 PV 都不匹配用户的 PersistentVolumeClaim 时,集群可能会尝试动态地为 PVC 创建卷。此
配置基于 StorageClasses :PVC 必须请求 [存储类],并且管理员必须创建并配置该类才能进行动态创建。声明该
类为 “” 可以有效地禁用其动态配置
要启用基于存储级别的动态存储配置,集群管理员需要启用 API server 上的 DefaultStorageClass [准入控制器]
。例如,通过确保 DefaultStorageClass 位于 API server 组件的 --admission-control 标志,使用逗号分隔的
有序值列表中,可以完成此操作
master 中的控制环路监视新的 PVC,寻找匹配的 PV(如果可能),并将它们绑定在一起。如果为新的 PVC 动态
调配 PV,则该环路将始终将该 PV 绑定到 PVC。否则,用户总会得到他们所请求的存储,但是容量可能超出要求
的数量。一旦 PV 和 PVC 绑定后, PersistentVolumeClaim 绑定是排他性的,不管它们是如何绑定的。 PVC 跟
PV 绑定是一对一的映射
PVC 保护的目的是确保由 pod 正在使用的 PVC 不会从系统中移除,因为如果被移除的话可能会导致数据丢失
当启用PVC 保护 alpha 功能时,如果用户删除了一个 pod 正在使用的 PVC,则该 PVC 不会被立即删除。PVC 的
删除将被推迟,直到 PVC 不再被任何 pod 使用
PersistentVolume 类型以插件形式实现。Kubernetes 目前支持以下插件类型:
GCEPersistentDisk AWSElasticBlockStore AzureFile AzureDisk FC (Fibre Channel)
FlexVolume Flocker NFS iSCSI RBD (Ceph Block Device) CephFS
Cinder (OpenStack block storage) Glusterfs VsphereVolume Quobyte Volumes
HostPath VMware Photon Portworx Volumes ScaleIO Volumes StorageOS
持久卷演示代码
apiVersion: v1 kind: PersistentVolume metadata: name: pv0003 spec: capacity: storage: 5Gi volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle storageClassName: slow mountOptions: - hard - nfsvers=4.1 nfs: path: /tmp server: 172.17.0.2
PersistentVolume 可以以资源提供者支持的任何方式挂载到主机上。如下表所示,供应商具有不同的功能,每个
PV 的访问模式都将被设置为该卷支持的特定模式。例如,NFS 可以支持多个读/写客户端,但特定的 NFS PV 可能
以只读方式导出到服务器上。每个 PV 都有一套自己的用来描述特定功能的访问模式
**ReadWriteOnce——**该卷可以被单个节点以读/写模式挂载 **ReadOnlyMany——**该卷可以被多个节点以只读模式挂载 **ReadWriteMany——**该卷可以被多个节点以读/写模式挂载
在命令行中,访问模式缩写为:
**RWO - ReadWriteOnce** **ROX - ReadOnlyMany** **RWX - ReadWriteMany**
Retain(保留)——手动回收
Recycle(回收)——基本擦除( rm **-**rf /thevolume/)
Delete(删除)——关联的存储资产(例如 AWS EBS、GCE PD、Azure Disk 和 OpenStack Cinder 卷)
将被删除
当前,只有 NFS 和 HostPath **支持回收策略。AWS EBS、GCE PD、**Azure Disk 和 Cinder 卷支持删除策略
卷可以处于以下的某种状态:
Available(可用)——一块空闲资源还没有被任何声明绑定
Bound(已绑定)——卷已经被声明绑定
Released(已释放)**——**声明被删除,但是资源还未被集群重新声明Failed(失败)——该卷的自动回收失败
命令行会显示绑定到 PV 的 PVC 的名称
yum install -y nfs-common nfs-utils rpcbind mkdir /nfsdata chmod 666 /nfsdata chown nfsnobody /nfsdata cat /etc/exports /nfsdata *(rw,no_root_squash,no_all_squash,sync) systemctl start rpcbind systemctl start nfs
apiVersion: v1 kind: PersistentVolume metadata: name: nfspv1 spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle storageClassName: nfs nfs: path: /data/nfs server: 10.66.66.10
apiVersion: v1 kind: Service metadata: name: nginx labels: app: nginx spec: ports: - port: 80 name: web clusterIP: None selector: app: nginx --- apiVersion: apps/v1 kind: StatefulSet metadata: name: web spec: selector: matchLabels: app: nginx serviceName: "nginx" replicas: 3 template: metadata: labels: app: nginx spec: containers: - name: nginx image: k8s.gcr.io/nginx-slim:0.8 ports: - containerPort: 80 name: web volumeMounts: - name: www mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: www spec: accessModes: [ "ReadWriteOnce" ] storageClassName: "nfs" resources: requests: storage: 1Gi
匹配 Pod name ( 网络标识 ) 的模式为:$(statefulset名称)-$(序号),比如上面的示例:web-0,web-1, web-2 StatefulSet 为每个 Pod 副本创建了一个 DNS 域名,这个域名的格式为: $(podname).(headless server name),也就意味着服务间是通过Pod域名来通信而非 Pod IP,因为当Pod所在Node发生故障时, Pod 会 被飘移到其它 Node 上,Pod IP 会发生变化,但是 Pod 域名不会有变化 StatefulSet 使用 Headless 服务来控制 Pod 的域名,这个域名的 FQDN 为:$(service name).$(namespace).svc.cluster.local,其中,“cluster.local” 指的是集群的域名 根据 volumeClaimTemplates,为每个 Pod 创建一个 pvc,pvc 的命名规则匹配模式: (volumeClaimTemplates.name)-(pod_name),比如上面的 volumeMounts.name=www, Pod name=web-[0-2],因此创建出来的 PVC 是 www-web-0、www-web-1、www-web-2 删除 Pod 不会删除其 pvc,手动删除 pvc 将自动释放 pv,
**有序部署:**部署StatefulSet时,如果有多个Pod副本,它们会被顺序地创建(从0到N-1)并且,在下一个
Pod运行之前所有之前的Pod必须都是Running和Ready状态。
**有序删除:**当Pod被删除时,它们被终止的顺序是从N-1到0。
**有序扩展:**当对Pod执行扩展操作时,与部署一样,它前面的Pod必须都处于Running和Ready状态。
1、稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于 PVC 来实现。
2、稳定的网络标识符,即 Pod 重新调度后其 PodName 和 HostName 不变。
3、有序部署,有序扩展,基于 init containers 来实现。
4、有序收缩。
Kubernetes调度器作为集群的大脑,在如何提高集群的资源利用率、保证集群中服务的稳定运行中也会变得越来越重要Kubernetes的资源分为两种属性。
预选策略 | 作用 |
---|---|
CheckNodeCondition | 检查是否可以在节点报告磁盘、网络不可用或未准备好时将Pod调度其上 |
HostName | 如果Pod对象拥有spec.hostname属性,则检查节点名称字符串是否和该属性值匹配。 |
PodFitsHostPorts | Pod的spec.hostPort属性时,检查端口是否被占用 |
MatchNodeSelector | Pod的spec.nodeSelector属性时,检查节点标签 |
NoDiskConflict | Pod依赖的存储卷在此节点是否可用,默认没有启用 |
PodFitsResources | 检查节点上的资源(CPU、内存)可用性是否满足Pod对象的运行需求。 |
PodToleratesNodeTaints | Pod的spec.tolerations属性,仅关注NoSchedule和NoExecute两个效用标识的污点 |
PodToleratesNodeNoExecuteTaints | Pod的spec.tolerations属性,是否能接纳节点的NoExecute类型污点,默认没有启用 |
CheckNodeLabelPresence | 仅检查节点上指定的所有标签的存在性,默认没有启用 |
CheckServiceAffinity | 将相同Service的Pod对象放置在同一个或同一类节点上以提高效率,默认没有启用 |
MaxEBSVolumeCount | 检查节点已挂载的EBS(亚马逊弹性块存储)存储卷数量是否超过设置的最大值,默认为39 |
MaxGCEPDVolumeCount | 检查节点上已挂载的GCE PD(谷歌云存储) 存储卷数量是否超过最大值,默认为16 |
MaxAzureDiskVolumeCount | 检查节点上已挂载的Azure Disk存储卷数量是否超过最大值,默认为16 |
CheckVolumeBinding | 检查节点上已绑定和未绑定的PVC是否满足需求 |
NoVolumeZoneConflict | 在给定区域zone限制下,检查此节点部署的Pod对象是否存在存储卷冲突 |
CheckNodeMemoryPressure | 检查节点内存压力,如果压力过大,那就不会讲pod调度至此 |
CheckPodePIDPressure | 检查节点PID资源压力 |
CheckNodeDiskPressure | 检查节点磁盘资源压力 |
MatchInterPodAffinity | 检查节点是否满足Pod对象亲和性或反亲和性条件 |
函数名称 | 详细说明 |
---|---|
LeastRequestedPriority | 节点的优先级就由节点空闲资源与节点总容量的比值,即由(总容量-节点上Pod的容量总和-新Pod的容量)/总容量)来决定。 CPU和内存具有相同权重,资源空闲比越高的节点得分越高。 |
cpu((capacity – sum(requested)) * 10 / capacity) + memory((capacity – sum(requested)) * 10 / capacity) / 2 | |
BalancedResourceAllocation | CPU和内存使用率越接近的节点权重越高,该策略不能单独使用,必须和LeastRequestedPriority组合使用,尽量选择在部署Pod后各项资源更均衡的机器。 如果请求的资源(CPU或者内存)需求大于节点的capacity,那么该节点永远不会被调度到。 |
InterPodAffinityPriority | 通过迭代 weightedPodAffinityTerm 的元素计算和,并且如果对该节点满足相应的PodAffinityTerm,则将 “weight” 加到和中,具有最高和的节点是最优选的。 |
SelectorSpreadPriority | 为了更好的容灾,对同属于一个service、replication controller或者replica的多个Pod副本,尽量调度到多个不同的节点上。 如果指定了区域,调度器则会尽量把Pod分散在不同区域的不同节点上。当一个Pod的被调度时,会先查找Pod对于的service或者replication controller, 然后查找service或replication controller中已存在的Pod,运行Pod越少的节点的得分越高。本质就是往运行同类pod少的节点上分配。 |
NodeAffinityPriority | 亲和性机制。Node Selectors(调度时将pod限定在指定节点上), 支持多种操作符(In, NotIn, Exists, DoesNotExist, Gt, Lt),而不限于对节点labels的精确匹配。 另外支持两种类型的选择器,一种是“hard(requiredDuringSchedulingIgnoredDuringExecution)”选择器, 它保证所选的主机必须满足所有Pod对主机的规则要求。 这种选择器更像是之前的nodeselector,在nodeselector的基础上增加了更合适的表现语法。 另一种是“soft(preferresDuringSchedulingIgnoredDuringExecution)”选择器, 它作为对调度器的提示,调度器会尽量但不保证满足NodeSelector的所有要求。 |
NodePreferAvoidPodsPriority(权重1W) | 如果 节点的 Anotation (注解信息)没有设置 key-value:scheduler. alpha.kubernetes.io/ preferAvoidPods = “…”,则节点对该 policy 的得分就是10分, 加上权重10000,那么该node对该policy的得分至少10W分。如果Node的Anotation设置了, scheduler.alpha.kubernetes.io/preferAvoidPods = “…” ,如果该 pod 对应的 Controller 是 ReplicationController 或 ReplicaSet, 则该 node 对该 policy 的得分就是0分。 |
TaintTolerationPriority | 使用 Pod 中 tolerationList 与 节点 Taint 列表项进行匹配,配对成功的项越多,则得分越低。污点越匹配,得分越低 |
ImageLocalityPriority | 根据Node上是否存在一个pod的容器运行所需镜像大小对优先级打分,分值为0-10。遍历全部Node, 如果某个Node上pod容器所需的镜像一个都不存在,分值为0; 如果Node上存在Pod容器部分所需镜像,则根据满足当前需求的镜像的大小来决定分值,镜像越大,分值就越高;如果Node上存在pod所需全部镜像,分值为10。默认没有启用 |
EqualPriority | 是一个优先级函数,它给予所有节点相等权重。 |
MostRequestedPriority | 在 ClusterAutoscalerProvider 中,替换 LeastRequestedPriority,给使用多资源的节点,更高的优先级。 计算公式为: |
(cpu(10 sum(requested) / capacity) + memory(10 sum(requested) / capacity)) / 2
默认没有启用 |
硬亲和性 required 、软亲和性 preferred。
requiredDuringSchedulingIgnoredDuringExecution
# 调度至 zone = foo 的节点 kubectl label nodes kube-node1 zone=foo apiVersion: v1 kind: Pod metadata: name: with-required-nodeaffinity spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: # 定义硬亲和性 nodeSelectorTerms: - matchExpressions: #集合选择器 - {key: zone,operator: In,values: ["foo"]} containers: - name: myapp image: ikubernetes/myapp:v1
preferredDuringSchedulingIgnoredDuringExecution
apiVersion: apps/v1 kind: Deployment metadata: name: myapp-deploy-with-node-affinity spec: replicas: 2 selector: matchLabels: app: myapp template: metadata: name: myapp-pod labels: app: myapp spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: #节点软亲和性 - weight: 60 preference: matchExpressions: - {key: zone, operator: In, values: ["foo"]} - weight: 30 preference: matchExpressions: - {key: ssd, operator: Exists, values: []} containers: - name: myapp image: ikubernetes/myapp:v1
亲和性
,将一些Pod对象组织在相近的位置(同一节点、机架、区域、地区)反亲和性
,将一些Pod在运行位置上隔开调度器将第一个Pod放置于任何位置,然后与其有亲和或反亲和关系的Pod据此动态完成位置编排
MatchInterPodAffinity
预选策略完成节点预选,基于InterPodAffinityPriority
优选函数进行各节点的优选级评估位置拓扑,定义"同一位置"
requiredDuringSchedulingIgnoredDuringExecution
Pod亲和性描述一个Pod与具有某特征的现存Pod运行位置的依赖关系;即需要事先存在被依赖的Pod对象
# 被依赖Pod kubectl run tomcat -l app=tomcat --image tomcat:alpine kubectl explain pod.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution.topologyKey
apiVersion: v1 kind: Pod metadata: name: with-pod-affinity spec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: # 硬亲和调度 - labelSelector: matchExpressions: #集合选择器 - {key: app, operator: In, values: ["tomcat"]} # 选择被依赖Pod # 上面意思是,当前pod要跟标签为app值为tomcat的pod在一起 topologyKey: kubernetes.io/hostname # 根据挑选出的Pod所有节点的hostname作为同一位置的判定 containers: - name: myapp image: ikubernetes/myapp:v1
apiVersion: apps/v1 kind: Deployment metadata: name: myapp-with-preferred-pod-affinity spec: replicas: 3 selector: matchLabels: app: myapp template: metadata: name: myapp labels: app: myapp spec: affinity: podAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 80 podAffinityTerm: labelSelector: matchExpressions: - {key: app, operator: In, values: ["cache"]} topologyKey: zone - weight: 20 podAffinityTerm: labelSelector: matchExpressions: - {key: app, operator: In, values: ["db"]} topologyKey: zone containers: - name: myapp image: ikubernetes/myapp:v1
Pod反亲和调度用于分散同一类应用,调度至不同的区域、机架或节点等
将 spec.affinity.podAffinity
替换为 spec.affinity.podAntiAffinity
反亲和调度也分为柔性约束和强制约束
apiVersion: v1 kind: Pod metadata: name: pod-first labels: app: myapp tier: fronted spec: containers: - name: myapp image: ikubernetes/myapp:v1 --- apiVersion: v1 kind: Pod metadata: name: pod-second labels: app: backend tier: db spec: containers: - name: busybox image: busybox:latest imagePullPolicy: IfNotPresent command: ["/bin/sh", "-c", "sleep 3600"] affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - {key: app, operator: In, values: ["myapp"]} topologyKey: zone
污点 taints 是定义在节点
上的键值型属性数据,用于让节点拒绝将Pod调度运行于其上,除非Pod有接纳节点污点的容忍度容忍度 tolerations 是定义在Pod
上的键值属性数据,用于配置可容忍的污点,且调度器将Pod调度至其能容忍该节点污点的节点上或没有污点的节点上
使用PodToleratesNodeTaints预选策略和TaintTolerationPriority优选函数完成该机制
污点定义于nodes.spec.taints
容忍度定义于pods.spec.tolerations
语法: key=value:effect
NoSchedule
,不能容忍,但仅影响调度过程,已调度上去的pod不受影响,仅对新增加的pod生效。PreferNoSchedule
,柔性约束,节点现存Pod不受影响,如果实在是没有符合的节点,也可以调度上来NoExecute
,不能容忍,当污点变动时,Pod对象会被驱逐一个节点可配置多个污点,一个Pod也可有多个容忍度
同一个键值数据,effect不同,也属于不同的污点
kubectl taint node <node-name> <key>=<value>:<effect> kubectl taint node node2 node-type=production:NoShedule #举例
kubectl get nodes <nodename> -o go-template={{.spec.taints}}
kubectl taint node <node-name> <key>[:<effect>]- kubectl patch nodes <node-name> -p '{"spec":{"taints":[]}}' kubectl taint node kube-node1 node-type=production:NoSchedule kubectl get nodes kube-node1 -o go-template={{.spec.taints}} # 删除key为node-type,effect为NoSchedule的污点 kubectl taint node kube-node1 node-type:NoSchedule- # 删除key为node-type的所有污点 kubectl taint node kube-node1 node-type- # 删除所有污点 kubectl patch nodes kube-node1 -p '{"spec":{"taints":[]}}'
spec.tolerations
字段添加
tolerationSeconds
用于定义延迟驱逐Pod的时长
# 等值判断 tolerations: - key: "key1" operator: "Equal" #判断条件为Equal value: "value1" effect: "NoExecute" tolerationSeconds: 3600 # 存在性判断 tolerations: - key: "key1" operator: "Exists" #存在性判断,只要污点键存在,就可以匹配 effect: "NoExecute" tolerationSeconds: 3600
apiVersion: v1 kind: Deployment metadata: name: myapp-deploy namespace: default spec: replicas: 3 selector: matchLabels: app: myapp release: canary template: metadata: labels: app: myapp release: canary spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: http containerPort: 80 tolerations: - key: "node-type" operator: "Equal" value: "production": effect: "NoExecute" tolerationSeconds: 3600
自动为节点添加污点信息,使用NoExecute效用标识,会驱逐现有Pod
K8s核心组件通常都容忍此类污点
node.kubernetes.io/not-ready 节点进入NotReady状态时自动添加
node.alpha.kubernetes.io/unreachable 节点进入NotReachable状态时自动添加
node.kubernetes.io/out-of-disk 节点进入OutOfDisk状态时自动添加
node.kubernetes.io/memory-pressure 节点内存资源面临压力
node.kubernetes.io/disk-pressure 节点磁盘面临压力
node.kubernetes.io/network-unavailable 节点网络不可用
node.cloudprovider.kubernetes.io/uninitialized kubelet由外部云环境程序启动时,自动添加,待到去控制器初始化此节点时再将其删除
优选级,Pod对象的重要程度
优选级会影响节点上Pod的调度顺序和驱逐次序
一个Pod对象无法被调度时,调度器会尝试抢占(驱逐)较低优先级的Pod对象,以便可以调度当前Pod
Pod优选级和抢占机制默认处于禁用状态
启用:同时为kube-apiserver、kube-scheduler、kubelet程序的 --feature-gates 添加 PodPriority=true
使用:
事先创建优先级类别,并在创建Pod资源时通过 priorityClassName属性指定所属的优选级类别
学习目标:集群的认证 鉴权 访问控制 原理及流程
A、HTTP Token认证:通过一个Token来识别合法用户。
B、 HTTP Base认证:通过用户名+密码的方式认证
C、最严格的HTTPS证书认证:基于CA根证书签名的客户端身份认证方式
A、两种类型
kubernetes组件对API Server的访问:kubectl、Controller Manager、Scheduler、kubelet、kube-proxy
kubernetes管理的pod对容器的访问:pod(dashboard是以pod形式运行)
B、安全性说明
Controller Manager、Scheduler与API Server在同一台机器,所以直接使用API Server的非安全端口访问, --insecure-bind-address=127.0.0.1
kubectl、kubelet、kube-proxy访问API Server就需要证书进行HTTPS双向认证
证书颁发
a. 手动签发:通过k8s集群的根ca进行签发HTTPS证书
b. 自动签发:kubelet首次访问API Server时,使用token做认证,通过后,Controller Manager会为kubelet生成一个证书,以后的访问都是用证书做认证了。
C、kubeconfig
D、ServiceAccount
E、Secret和SA之间的关系
a. token是使用api server私钥签名的JWT。用于访问API Server,Server端认证。
b. ca.crt,根证书用于Clien端验证API Server发送的证书。
c. namespace,标识这个server-account-token的作用域空间
e. kubectl get secrets --all-namespace
kubectl describe secret default-token-59mfg --namespace-kube-system
f. 默认情况下每个namespace都会有一个ServiceAccount,如果Pod在创建时没有指定ServiceAccount,就会使用Pod所属的namespace的ServiceAccount
默认挂载目录:/run/secrets/kubernetes.io/serviceaccount/
F、总结
A、上面认证过程,只是确认了通信的双方是可信的,可以互相通信。而鉴权是确定请求方有哪些资源的权限。API Server目前支持以下几种授权策略(通过API Server的启动参数“–authorization-mode”设置)
AlwaysDeny:表示拒绝所有请求,一般用于测试
AlwaysAllow:允许接收所有请求,如果集群不需要授权流程,则可以采用该策略。
ABAC(Attribute-Based Access Control):基于属性的访问控制,表示使用用户配置的授权规则对用户进行匹配和控制
webbook:通过调用外部的REST服务对用户进行授权
RBAC(Role-Based Access Control):基于角色的访问控制,现行默认
B、RBAC授权模式
RBAC引入了4个新的顶级资源对象:Role、ClusterRole、RoleBinding、ClusterRoleBinding,4中对象类型均可以通过kubectl和API操作
{ "CN": "admin", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "name": { "C": "CN", "ST": "hangzhou", "L": "XS", "O": "system:masters", "OU": "System" } }
API Server会把客户端的CN字段作为User,把names.O字段作为组Group
C、Role和ClusterRole
kind: Role apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: pod-reader namespace: default rules: - apiGroups: [""] # ""代表API核心组 resources: ["pods"] verbs: ["get", "watch","list"]
a. 集群级别的资源控制(例如node访问权限)
b. 非资源型endpoints(例如/healz访问)
c. 所有名称空间资源控制(如pods)
kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: # 这里不要定义namespace,因为ClusterRole是集群概念下的,不是名称空间概念下的 name: secret-reader rules: - apiGroup: [""] resources: ["secrets"] verbs: ["get","watch","list"]
D、RoleBind 和 ClusterRoleBinding
a. 例子
kind: RoleBinding apiServer: rbac.authorization.k8s.io/v1beta1 metadata: name: read-pods namespace: default subjects: - kind: User name: jane apiGroup: rbac.autorization.k8s.io roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io
2. RoleBing同样可以引用ClusterRole来对当前namespace内用户、用户组或ServiceAccount进行授权,这种操作允许集群管理员在整个集群内定义一些通用的ClusterRole,然后在不同的namespace中使用RoleBinding来引用。
kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1beta metadata: name: read-secrets namespace: development #这只会给development名称空间下的授予权限 subjects: - kind: User name: dave apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: secrets-reader apiGroup: rbac.authorization.k8s.io
3.使用ClusterRoleBinding可以对整个集群中的所有命名空间资源进行授权
a. 例子
kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: read-secret-global subjects: - kind: Group name: manager apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: secret-reader apiGroup: rbac.authorization.k8s.io
F、Resources
GET /api/v1/namespaces/{namespace}/pods/{pod}/log
kind: Role apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: pod-and-pod-logs-reader namespace: default rules: - apiGroup: [""] resources: ["pods","pods/log"] verbs: ["get","list"]
H、实验:创建一个用户只能管理dev空间
user add devuser
passwd devuser
cd /usr/local/install-k8s/ && mkdir cert && cd cert && vim devuser-csr.json
{ "CN": "devuser", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] }
\4. 下载证书工具到/usr/local/bin下:
a. wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
mv cfssl_linux-amd64 cfssl
b. wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
mv cfssljson_linux-amd64 cfssljson
c. wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
mv cfssl-certinfo_linux-amd64 cfssl-certinfo
d. cd /etc/kubernetes/pki/
f. cfssl gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes /usr/local/install-k8s/cert/devuser/devuser-csr.json | cfssljson -bare devuser
a. export KUBE_APISERVER=“https://192.168.66.10:6443”
b. kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --server=${KUBE_APISERVER} --kubeconfig=devuser.kubeconfig
a. kubectl config set-credentials devuser --client-certificate=/etc/kubernetes/pki/devuser.pem --client-key=/etc/kubernetes/pki/devuser-key.pem --embed-certs=true --kubeconfig=devuser.kubeconfig
a. kubectl config set-context kubernetes --cluster=kubernetes --user=devuser --namespace=dev --kubeconfig=devuser.kubeconfig
c. 创建一个rolebinding将admin角色绑定至dev名称空间下的devuser:kubectl create rolebinding devuser-admin-binding --clusterrole=admin --user=devuser --namespace=dev
e. 将devuser.kubeconfig拷贝至devuser下.kube目录下: cp devuser.kubeconfig /home/devuser/.kube/
f. 改变devuser.kubeconfig的所有者为devuser组下的devuser: chown devuser:devuser /home/devuser/.kube/devuser.kubeconfig
g. 将devuser.kubeconfig文件名修改为config: mv devuser.kubeconfig config
h. 切换上下文:kubectl config use-context kubernetes --kubeconfig=/home/devuser/.kube/config
A、准入控制是Api Server的插件集合,通过添加不同的插件,实现额外的准入控制规则。甚至API Server的一些主要功能都需要通过Admission Controllers实现,比如ServiceAccount,官方文档上有一份针对不同版本的准入控制器推荐列表。
B、列举几个插件的功能
NamespaceLifeCycle:防止在不存在的namespace上创建对象,防止删除系统预置的namespace,删除namespace时,连带删除它的所有资源对象。
LimitRanger:确保请求的资源不会超过资源所在的Namespace的LimitRange
ServiceAccount:实现了自动化添加ServiceAccount
ResourceQuota:确保请求资源不会超过资源的ResourceQuota限制
查看系统运行日志:journalctl -f