当前位置: 首页 > news >正文

沈北新区建设局网站网站友链怎么做

沈北新区建设局网站,网站友链怎么做,wordpress 培训行业主题,中国建设银行网上银行网站集群操作 查看集群信息 kubectl get查看各组件信息 格式#xff1a;kubectl get 资源类型 【资源名】 【选项】 events #查看集群中的所有日志信息 -o wide # 显示资源详细信息#xff0c;包括节点、地址... -o yaml/json #将当前资源对象输出至 yaml/json 格式文…集群操作 查看集群信息 kubectl get查看各组件信息 格式kubectl get 资源类型 【资源名】 【选项】 events #查看集群中的所有日志信息 -o wide # 显示资源详细信息包括节点、地址... -o yaml/json #将当前资源对象输出至 yaml/json 格式文件 --show-labels #查看当前资源对象的标签 -l keyvalue #基于标签进行筛选查找 -A #查看所有名称空间下的POD -n 名字空间 #查看该名字下的资源集合 --show-labels #查看某一资源的标签 -all-namespaces #查看所有名字空间下的资源kubectl get all # 查看所有的资源信息kubectl get ns # 获取名称空间kubectl get cs # 获取集群健康状态组件的状态kubectl get pods --all-namespaces # 查看所有名称空间所有的podkubectl get pods -A # -A是--all-namespaces的简写 查看service的信息 [rootk1 ~]# kubectl get service NAME         TYPE       CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE kubernetes   ClusterIP   10.96.0.1   none        443/TCP   22h ​ 在不同的namespace里面查看service [rootk1 ~]# kubectl get service -n kube-system -n:namespace名称空间 ​ 查看所有名称空间内的资源 [rootk1 ~]# kubectl get pods --all-namespaces ​ 同时查看多种资源信息 [rootk1 ~]# kubectl get pod,svc -n kube-system ​ 查看集群的概览信息: [rootk1 ~]# kubectl cluster-info Kubernetes master is running at https://192.168.246.166:6443 KubeDNS is running at https://192.168.2466.166:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy ​ api查询 [rootk1 ~]# kubectl api-versions 1.查看集群信息 [rootk1 ~]# kubectl get nodes # -n default可不写 NAME             STATUS   ROLES   AGE   VERSION kub-k8s-master   Ready   master   16h   v1.16.1 kub-k8s-node1   Ready   none   15h   v1.16.1 kub-k8s-node2   Ready   none   15h   v1.16.1 2.删除节点无效且显示的也可以删除 [rootk1 ~]# kubectl delete node kub-k8s-node1 3.查看某一个节点(节点名称可以用空格隔开写多个) [rootk1 ~]# kubectl get node kub-k8s-node1 NAME           STATUS   ROLES   AGE   VERSION kub-k8s-node1   Ready   none   15h   v1.16.1 kubectl describe 查看一个 API 对象的细节 注意Events(事件): 在 Kubernetes 执行的过程中对 API 对象的所有重要操作都会被记录在这个对象的 Events 里并且显示在 kubectl describe 指令返回的结果中。 ​ 比如对于这个 Pod我们可以看到它被创建之后被调度器调度Successfully assigned到了 node-1拉取了指定的镜像pulling image然后启动了 Pod 里定义的容器Started container。 ​ 这个部分正是我们将来进行 Debug 的重要依据。如果有异常发生一定要第一时间查看这些 Events往往可以看到非常详细的错误信息。 查看node的详细信息 [rootk1 ~]# kubectl describe node kub-k8s-node1 #也可以查看pod的信息 Name:               kub-k8s-node1 Roles:             none ...--------           --------   ------cpu               100m (2%) 100m (2%)memory             50Mi (1%) 50Mi (1%)ephemeral-storage  0 (0%)     0 (0%) Events:             none #注意:最后被查看的节点名称只能用get nodes里面查到的name! 创建删除更新信息 kubctl create 资源创建 1通过文件名创建资源# kubectl create -f 文件名选项--record #记录命令至滚动信息便于查看每次 revision 的变化 2通过标准输入创建资源# kubectl create 资源类型 [资源名] 选项 --help #获取命令帮助 --tcp集群端口:pod端口 #映射容器内端口至哪个端口 --dry-run #干跑测试 -o yaml/json #将当前资源对象输出至 yaml/json 格式文件中 --imagexxx #指定镜像创建 apply 资源创建/更新 # kubectl apply -f 文件名 选项 --record #记录命令至滚动信息便于查看每次 revision 的变化 删除pod # kubectl delete pod pod名1 pod名2 # kubectl delete pod --all   //批量删除 # kubectl delete pod pod-name --grace-period0 --force --grace-period0 参数表示立即删除 Pod而不是等待一段时间。 --force 参数表示强制删除 Pod即使 Pod 处于未知状态。 ​ 举例 [rootkub-k8s-master prome]# kubectl delete pod website pod website deleted [rootkub-k8s-master prome]# kubectl delete -f pod.yaml #指定创建pod的yml文件名 重新启动 基于yaml文件的应用(这里并不是重新启动服务) # kubectl delete -f XXX.yaml   #删除 # kubectl apply -f XXX.yaml   #创建pod explain 资源字段描述 #查看对象推荐使用的api以及资源对象的描述 # kubectl explain 字段 例如 # kubectl explain pod.spec #查看pod类别一级字段帮助文档 # kubectl explain pod.spec.containers #查看pod类别二级字段帮助文档 创建名称空间 namespace 在k8s中namespace作用 1.将不同的应用隔离开来避免命名冲突和资源的竞争 2.为不同团队和项目提供独立的运行环境使他们可以独立的管理和部署应用程序。 3.控制资源配额和访问权限以确保应用程序之间的安全隔离。 创建和使用namespace  1. 编写yaml文件 [rootkub-k8s-master ~]# mkdir namespace [rootkub-k8s-master ~]# cd namespace/ [rootkub-k8s-master namespace]# vim namespace.yml --- apiVersion: v1   #api版本 kind: Namespace  #类型---固定的 metadata:     #元数据用来描述所创建资源的基本信息name: ns-monitor  #起个名字labels:     #设置标签name: ns-monitor 2. 创建资源 [rootkub-k8s-master namespace]# kubectl apply -f namespace.yml namespace/ns-monitor created 3. 查看资源 [rootkub-k8s-master namespace]# kubectl get namespace NAME             STATUS   AGE default           Active   22h kube-node-lease   Active   22h kube-public       Active   22h kube-system       Active   22h ns-monitor       Active   34s 4.查看某一个namespace [rootkub-k8s-master namespace]# kubectl get namespace ns-monitor 5.查看某个namespace的详细信息 [rootkub-k8s-master namespace]# kubectl describe namespace ns-monitor 6.制作namespace资源限制 [rootk8s-master ~]# kubectl explain resourcequota.spec #查看命令帮助 ​ [rootk8s-master namespace]# vim create_ns_quota.yml apiVersion: v1 kind: ResourceQuota  #定义限制 metadata:name: test-quotanamespace: ns-monitor #指定要做限制的namespace spec:hard: #定义资源限制集,https://kubernetes.io/docs/concepts/policy/resource-quotas/limits.cpu: 2limits.memory: 2Girequests.cpu: 2requests.memory: 2Gilimits定义资源在当前名称空间可以使用的资源是多少。容器可以使用的资源上限 requests定义资源可以请求调度到node节点需要的多少资源才允许资源调度。容器可以 预期获得的最低资源保障 查看 [rootk8s-master namespace]# kubectl get resourcequota -n ns-monitor NAME         AGE   REQUEST                                             LIMIT test-quota   3h5m   requests.cpu: 0/2, requests.memory: 0/2Gi   limits.cpu: 0/2, limits.memory: 0/2Gi 使用 [rootk8s-master namespace]# vim create_pod.yml apiVersion: v1 kind: Pod metadata:name: test-pod-1namespace: ns-monitor #指定名称空间labels:web: nginx-1 spec:containers:- name: nginx-1image: daocloud.io/library/nginximagePullPolicy: IfNotPresentports:- containerPort: 80resources: #指定资源限制limits: #定义容器在当前名称空间可以使用的最大资源cpu: 500mmemory: 1Girequests: #定义该pod调度到的节点需要满足的资源cpu: 100mmemory: 500Mi 查看使用后 [rootk8s-master namespace]# kubectl get resourcequota -n ns-monitor NAME         AGE   REQUEST                                             LIMIT test-quota   3h5m   requests.cpu: 300m/2, requests.memory: 1000Mi/2Gi   limits.cpu: 1/2, limits.memory: 2Gi/2Gi ​ 注意运行pod的node节点的资源和容器运行所使用的资源一旦超过定义的那就无法使用调度 pod到对应节点。 ​ 7.删除名称空间先删除namespace对应的pod [rootkub-k8s-master namespace]# kubectl delete -f create_pod.yml [rootkub-k8s-master namespace]# kubectl delete -f namespace.yml namespace ns-monitor deleted 发布容器化应用 1.有镜像 2.部署应用--考虑做不做副本。不做副本就是pod做副本以deployment方式去创建。做了副本访问还需要做一个service用于访问。 发布第一个容器化应用 扮演一个应用开发者的角色使用这个 Kubernetes 集群发布第一个容器化应用。1. 作为一个应用开发者你首先要做的是制作容器的镜像。 2. 有了容器镜像之后需要按照 Kubernetes 项目的规范和要求将你的镜像组织为它能够认识的方式然后提交上去。 什么才是 Kubernetes 项目能认识的方式就是使用 Kubernetes 的必备技能编写配置文件。 这些配置文件可以是 YAML 或者 JSON 格式的。Kubernetes 跟 Docker 等很多项目最大的不同就在于它不推荐你使用命令行的方式直接运行容器虽然 Kubernetes 项目也支持这种方式比如kubectl run而是希望你用 YAML 文件的方式即把容器的定义、参数、配置统统记录在一个 YAML 文件中然后用这样一句指令把它运行起来 # kubectl apply -f 我的配置文件 好处你会有一个文件能记录下 Kubernetes 到底run了什么 编写yaml文件内容 [rootk1 prome]# vim pod.yml --- apiVersion: v1  #api版本支持pod的版本 kind: Pod     #Pod定义类型注意语法开头大写 metadata:     #元数据name: website   #这是pod的名字labels:app: website   #自定义但是不能是纯数字 spec:    #指定的意思containers:   #定义容器- name: test-website   #容器的名字可以自定义imagePullPolicy:IfNotPresentimage: daocloud.io/library/nginx   #镜像ports:- containerPort: 80   #容器暴露的端口 创建pod [rootk1 prome]# kubectl apply -f pod.yml pod/website created 查看pod [rootk1 prome]# kubectl get pods NAME     READY   STATUS   RESTARTS   AGE website   1/1     Running   0         74s各字段含义 NAME: Pod的名称 READY: Pod的准备状况右边的数字表示Pod包含的容器总数目左边的数字表示准备就绪的容器数目。 STATUS: Pod的状态。 RESTARTS: Pod的重启次数 AGE: Pod的运行时间。 pod的准备状况指的是Pod是否准备就绪以接收请求Pod的准备状况取决于容器即所有容器都准备就绪了Pod才准备就绪。 一个pod刚被创建的时候是不会被调度的因为没有任何节点被选择用来运行这个pod。调度的过程发生在创建完成之后但是这个过程一般很快所以你通常看不到pod是处于unscheduler状态的除非创建的过程遇到了问题。 pod被调度之后分配到指定的节点上运行这时候如果该节点没有所需要的image那么将会自动从默认的Docker Hub上pull指定的image一切就绪之后看到pod是处于running状态了 查看pod运行在哪台机器上 [rootk1 prome]# kubectl get pods -o wide 可以测试访问: [rootkub-k8s-master prome]# curl 10.244.1.3   #访问pod的ip 查看pods定义的详细信息 查看pod的详细信息----指定pod名字(不显示events字段信息) [rootk1 prome]# kubectl get pod website -o yaml -ooutput yamlyaml格式也可以是json格式 查看kubectl describe 支持查询Pod的状态 [rootk1 prome]# kubectl describe pod website kubectl describe返回字段含义 1.各字段含义 Name: Pod的名称 Namespace: Pod的Namespace。 Image(s): Pod使用的镜像 Node: Pod所在的Node。 Start Time: Pod的起始时间 Labels: Pod的Label。 Status: Pod的状态。 Reason: Pod处于当前状态的原因。 Message: Pod处于当前状态的信息。 IP: Pod的PodIP Replication Controllers: Pod对应的Replication Controller。2.Containers:Pod中容器的信息 Container ID: 容器的ID Image: 容器的镜像 Image ID:镜像的ID State: 容器的状态 Ready: 容器的准备状况(true表示准备就绪)。 Restart Count: 容器的重启次数统计 Environment Variables: 容器的环境变量 Conditions: Pod的条件包含Pod准备状况(true表示准备就绪) Volumes: Pod的数据卷 Events: 与Pod相关的事件列表生命周期的介绍 整个pod的生命周期 1.在启动任何容器之前先创建pause基础容器pid1它初始化Pod的环境并为后续加⼊的容器 提供共享的名称空间。 2.按配置文件定义的顺序启动初始化容器只有全部的初始化容器启动完成后才会启动主容器也就是 container字段定义的容器。 3.在主容器启动之后可以通过钩子定义容器启动之后做什么比如执行什么命令 4.定义探针 1startupprobe启动探针用来检测容器是否启动成功当容器启动成功后就绪探针和存活探针开始 对容器进行检测 2就绪探针的作用检测容器是否准备就绪如果就绪就可以接受来自service的请求没有就不 接受service转发过来的请求 3存活探针用来检测容器里面的进程是否健康如果不健康根据容器的重启策略进行容器的重启。 5.通过钩子定义在容器关闭之前要做什么比如在容器关闭之前先正常退出nginx进程。 一个Pod 对象在 Kubernetes 中的生命周期: ​ 生命周期指的是status通过 [rootkub-k8s-master ~]# kubectl get pod #生命周期包括running、Pending、Failed... ​ Pod 生命周期的变化主要体现在 Pod API 对象的Status 部分这是除了 Metadata 和 Spec 之外的第三个重要字段。有如下几种可能的情况 ​pod状态 Pending此状态表示Pod的YAML文件已经提交给了KubernetesAPI 对象已经被创建并保存在Etcd 当中准备状态。但这个 Pod 里有些容器因为某种原因而不能被顺利创建。如调度不成功。 Running此状态表示Pod 已经调度成功跟一个具体的节点绑定。它包含的容器都已经创建成功并且至少有一个正在运行中。 Succeeded此状态表示 Pod 里的所有容器都正常运行完毕并且已经退出了。这种情况在运行一次性任务时最为常见。 Failed此状态表示 Pod 里至少有一个容器以不正常的状态非 0 的返回码退出。比如查看Pod的Events 和日志。 Unknown这是一个异常状态(未知状态)表示 Pod 的状态不能持续地被 kubelet 汇报给kube-apiserver这很有可能是主从节点Master 和 Kubelet间的通信出现了问题 其他状态 completed:         pod里面所有容器正常退出 CrashLoopBackOff 容器退出kubelet正在将它重启 InvalidImageName 无法解析镜像名称 ImageInspectError 无法校验镜像 ErrImageNeverPull 策略禁止拉取镜像 ImagePullBackOff 正在重试拉取 RegistryUnavailable 连接不到镜像中心 ErrImagePull 拉取镜像出错 CreateContainerConfigError 不能创建kubelet使用的容器配置 CreateContainerError 创建容器失败 m.internalLifecycle.PreStartContainer 执行hook报错 RunContainerError 启动容器失败 PostStartHookError 执行hook报错 ContainersNotInitialized 容器没有初始化完毕 ContainersNotReady 容器没有准备完毕 ContainerCreating容器创建中 PodInitializingpod 初始化中 DockerDaemonNotReadydocker还没有完全启动 NetworkPluginNotReady 网络插件还没有完全启动 进入Pod对应的容器内部 通过pod名称 [rootkub-k8s-master prome]# kubectl exec -it website /bin/bash rootwebsite:/# 扩展 create与apply的区别 create创建的应用如果需要修改yml文件必须先指定yml文件删除在创建新的pod。 如果是apply创建的应用可以直接修改yml文件继续apply创建不用先删掉。 Yaml文件语法解析 通常使用配置文件的方式会比直接使用命令行更可取因为这些文件可以进行版本控制而且文件的变化和内容也可以进行审核当使用及其复杂的配置来提供一个稳健、可靠和易维护的系统时这些点就显得非常重要。 在声明定义配置文件的时候所有的配置文件都存储在YAML或者JSON格式的文件中并且遵循k8s的资源配置方式。 kubernetes中用来定义YAML文件创建Pod和创建Deployment等资源。 使用YAML配置文件定义K8s的的好处 便捷性不必添加大量的参数到命令行中执行命令 可维护性YAML文件可以通过源头控制跟踪每次操作 灵活性YAML可以创建比命令行更加复杂的结构 YAML语法规则 大小写敏感 使用缩进表示层级关系 缩进时不允许使用Tal键只允许使用空格 缩进的空格数目不重要只要相同层级的元素左侧对齐即可 ”#” 表示注释从这个字符一直到行尾都会被解析器忽略 注- - - 为可选的分隔符 当需要在一个文件中定义多个结构的时候需要使用 在 k8s 中只需要知道两种结构类型 1.Lists 2.Maps 字典a{key:value, key1:{key2:value2}, key3:{key4:[1,{key5:value5},3,4,5]}} key: value key1:key2: value2 key3:key4:- 1- key5: value5- 3- 4 YAML Maps Map指的是字典即一个Key:Value 的键值对信息。 例如 --- apiVersion: v1 kind: Pod 注--- 为可选的分隔符 当需要在一个文件中定义多个结构的时候需要使用。上述内容表示有 两个键apiVersion和kind分别对应的值为v1和Pod。 ​ 例如 --- apiVersion: v1 kind: Pod metadata:name: kube100-sitelabels:app: web    注上述的YAML文件中metadata这个KEY对应的值为一个Maps而嵌套的labels这个KEY的值 又是一个Map。实际使用中可视情况进行多层嵌套。 ​ YAML处理器根据行缩进来知道内容之间的关联。上述例子中使用两个空格作为缩进但空格的数 据量并不重要只是至少要求一个空格并且所有缩进保持一致的空格数 。例如name和labels是 相同缩进级别因此YAML处理器知道他们属于同一map它知道app是lables的值因为app的缩进更大。 注意在YAML文件中绝对不要使用tab键 YAML   Lists List即列表就是数组 例如 args:- beijing- shanghai- shenzhen- guangzhou ​ Maps的value既能够对应字符串也能够对应一个Maps。 可以指定任何数量的项在列表中每个项的定义以连字符-开头并且与父元素之间存在缩进。 ​ 在JSON格式中表示如下 {args: [beijing, shanghai, shenzhen, guangzhou] } 总结 如果key和value同行:后面要加空格 所有的一级key顶格写 value如有没有嵌套不换行value如果有嵌套需要换行 二级key要缩进同行元素左对齐 列表元素每行一个前面加-后面带空格 不能使用tab键 Pod API属性详解 Pod API 对象 Pod是 k8s 项目中的最小编排单位。容器Container就成了 Pod 属性里一个普通的字段。 问题​ 通过yaml文件创建pod的时候里面有容器这个文件里面到底哪些属性属于 Pod 对象哪些属性属于 Container 把 Pod 看成传统环境里的虚拟机机器、把容器看作是运行在这个机器里的用户程序那么 很多关于 Pod 对象的设计就非常容易理解了。 凡是调度、网络、存储以及安全相关的属性基本上是 Pod 级别的 ​ 共同特征是它们描述的是机器这个整体而不是里面运行的程序。 比如 配置这个机器的网卡即Pod 的网络定义 配置这个机器的磁盘即Pod 的存储定义 配置这个机器的防火墙即Pod 的安全定义 这台机器运行在哪个服务器之上即Pod 的调度 kind指定了这个 API 对象的类型Type是一个 Pod根据实际情况此处资源类型可以是 Deployment、Job、Ingress、Service等。 ​ metadata包含Pod的一些meta信息比如名称、namespace、标签等信息. specspecification of the resource content指定该资源的内容,包括一些containerstorage volume以及其他Kubernetes需要的参数以及诸如是否在容器失败时重新启动容器的属性。可在特定 Kubernetes API找到完整的Kubernetes Pod的属性。 specification-----[spesɪfɪˈkeɪʃn] 容器可选的设置属性包括 name、image、command、args、workingDir、ports、env、resource、 volumeMounts、livenessProbe、readinessProbe、livecycle、 terminationMessagePath、imagePullPolicy、securityContext、stdin、 stdinOnce、tty 跟机器相关的配置 [rootk1 ~]# cd prome/ [rootk1 prome]# kubectl get pods NAME     READY   STATUS   RESTARTS   AGE website   1/1     Running   0         2d23h [rootkub-k8s-master prome]# kubectl get pod -o wide   #查看pod运行在哪台机器上面 人工干预调度器  nodeSelector nodeName 这两个属性的功能是一样的都是用于人工干预调度器 第一种方式nodeName  将node1上面的pod删除掉 [rootk1 prome]# kubectl delete -f pod.yml pod website deletednodeName是一个供用户将 Pod 与 Node 进行绑定的字段用法 现在指定将pod创在node2上面 [rootk1 prome]# vim pod.yml --- apiVersion: v1 kind: Pod metadata:name: websitelabels:app: website spec:containers:- name: test-websiteimage: daocloud.io/library/nginxports:- containerPort: 80nodeName: kub-k8s-node2     #指定node节点的名称 创建 [rootk1 prome]# kubectl apply -f pod.yml pod/website created 第二种方式通过node标签 首先我们需要知道node2上面你的标签有哪些 1.查看node2上面的标签 # kubectl describe node kub-k8s-node2 1.重新创建一个新的pod nodeSelector是一个供用户将 Pod 与 Node 进行绑定的字段通过指定标签来指定 ​ [rootkub-k8s-master prome]# vim tomcat.yml --- apiVersion: v1 kind: Pod metadata:name: tomcatlabels:app: tomcat spec:containers:- name: test-tomcatimage: daocloud.io/library/tomcat:8ports:- containerPort: 8080nodeSelector:      #指定标签kubernetes.io/hostname: kub-k8s-node2 2.创建pod   [rootkub-k8s-master prome]# kubectl apply -f tomcat.yml pod/tomcat created 表示这个 Pod 永远只能运行在携带了kubernetes.io/hostname: kub-k8s-node2标签Label的节点上否则它将调度失败。 第三个方式主机别名 设置pod容器里面的hosts文件内容也是做本地解析 HostAliases定义 Pod 的 hosts 文件比如 /etc/hosts里的内容 ​在 k8s 中如果要设置 hosts 文件里的内容一定要通过这种方法。否则如果直接修改了 hosts 文件在 Pod 被删除重建之后kubelet 会自动覆盖掉被修改的内容。 1.首先先将刚创建的pod删除掉 [rootkub-k8s-master prome]# kubectl delete -f tomcat.yml pod tomcat deleted [rootkub-k8s-master prome]# vim tomcat.yml --- apiVersion: v1 kind: Pod metadata:name: tomcatlabels:app: tomcat spec:hostAliases:- ip: 192.168.246.113   #给哪个ip做解析。实验环境下这个ip自定义的hostnames:- foo.remote    #解析的名字。用引号引起来可以写多个- bar.remotecontainers:- name: test-tomcatimage: daocloud.io/library/tomcat:8ports:- containerPort: 8080 2.创建pod [rootkub-k8s-master prome]# kubectl apply -f tomcat.yml pod/tomcat created 3.连接pod [rootkub-k8s-master prome]# kubectl exec -it tomcat /bin/bash roottomcat:/usr/local/tomcat# cat /etc/hosts   #查看hosts文件 ​ 凡是跟容器的 Linux Namespace 相关的属性也一定是 Pod 级别的 原因Pod 的设计就是要让它里面的容器尽可能多地共享 Linux Namespace仅保留必要的隔离和限制能力。 举例一个 Pod 定义 yaml 文件如下 共享同一个pod里面容器的进程 ​ [rootkub-k8s-master prome]# kubectl delete -f pod.yml pod website deleted [rootkub-k8s-master prome]# vim pod.yml   #修改如下。最好是提前将镜像pull下来。 --- apiVersion: v1 kind: Pod metadata:name: websitelabels:app: website spec:shareProcessNamespace: true  #共享进程名称空间containers:- name: test-webimage: daocloud.io/library/nginxports:- containerPort: 80- name: busybosimage: daocloud.io/library/busyboxstdin: truetty: true2.创建 [rootkub-k8s-master prome]# kubectl apply -f pod.yml pod/website created 1. 定义了 shareProcessNamespacetrue 表示这个 Pod 里的容器要共享进程(PID Namespace)如果是false则为不共享。 2. 定义了两个容器 一个 nginx 容器 一个开启了 tty 和 stdin 的 busybos 容器 ​ 在 Pod 的 YAML 文件里声明开启它们俩等同于设置了 docker run 里的 -it-i 即 stdin-t 即 tty参数。此 Pod 被创建后就可以使用 shell 容器的 tty 跟这个容器进行交互了。 查看运行在那台机器上面 我们登录node1的机器连接busybox的容器 [rootkub-k8s-node1 ~]# docker exec -it f684bd1d05b5 /bin/sh 在容器里不仅可以看到它本身的 ps 指令还可以看到 nginx 容器的进程以及 /pause 进程。也就是说整个 Pod 里的每个容器的进程对于所有容器来说都是可见的它们共享了同一个 PID Namespace。 将shareProcessNamespacetrue修改为false [rootkub-k8s-master prome]# kubectl delete -f pod.yml [rootkub-k8s-master prome]# vim pod.yml 将shareProcessNamespacetrue修改为false [rootkub-k8s-master prome]# kubectl apply -f pod.yml pod/website created 验证 凡是 Pod 中的容器要共享宿主机的 Namespace也一定是 Pod 级别的定义。 刚才的都是pod里面容器的Namespace并没有和本机的Namespace做共享接下来我们可以做与本机的Namespace共享可以在容器里面看到本机的进程。 ​ [rootkub-k8s-master prome]# kubectl delete -f pod.yml pod website deleted [rootkub-k8s-master prome]# vim pod.yml #修改如下 --- apiVersion: v1 kind: Pod metadata:name: websitelabels:app: website spec:hostNetwork: true  #共享宿主机网络hostIPC: true  #共享ipc通信hostPID: true  #共享宿主机的pidcontainers:- name: test-webimage: daocloud.io/library/nginxports:- containerPort: 80- name: busybosimage: daocloud.io/library/busyboxstdin: truetty: true 创建pod [rootkub-k8s-master prome]# kubectl apply -f pod.yml pod/website created 验证 定义了共享宿主机的 Network、IPC 和 PID Namespace。这样此 Pod 里的所有容器会直接使用宿主机的网络、直接与宿主机进行 IPC 通信、看到宿主机里正在运行的所有进程。 容器属性 Pod 里最重要的字段Containers Containers这个字段属于 Pod 对容器的定义。 k8s 对 Container 的定义和 Docker 相比并没有什么太大区别。 Docker中Image镜像、Command启动命令、workingDir容器的工作目录、Ports容器要开发的端口以及 volumeMounts容器要挂载的 Volume都是构成 k8s 中 Container 的主要字段。   其他的容器属性 ImagePullPolicy 字段:定义镜像的拉取策略。之所以是一个 Container 级别的属性是因为容器镜像本来就是 Container 定义中的一部分。 ​ 默认值 Always:表示每次创建 Pod 都重新拉取一次镜像。 Never:表示Pod永远不会主动拉取这个镜像 IfNotPresent:表示只在宿主机上不存在这个镜像时才拉取。 ​ ​ Lifecycle 字段定义 Container Lifecycle Hooks。作用是在容器状态发生变化时触发一系列钩子。 ​ 注 lifecycle /laɪf ˈsaɪkl/ n   生命周期 例子这是 k8s 官方文档的一个 Pod YAML 文件 在这个例子中容器成功启动之后在 /usr/share/message 里写入了一句欢迎信息即 postStart 定义的操作。而在这个容器被删除之前我们则先调用了 nginx 的退出指令即 preStop 定义的操作从而实现了容器的优雅退出。 [rootkub-k8s-master prome]# kubectl delete -f pod.yml pod website deleted [rootkub-k8s-master prome]# cp pod.yml pod.yml.bak [rootkub-k8s-master prome]# vim pod.yml --- apiVersion: v1 kind: Pod metadata:name: lifecycle-demo spec:containers:- name: lifecycle-demo-containerimage: daocloud.io/library/nginxlifecycle:postStart:  #容器启动之后exec: command: [/bin/sh, -c, echo Hello from the postStart handler /usr/share/message]preStop:  #容器关闭之前exec: command: [/usr/sbin/nginx,-s,quit] 验证 [rootkub-k8s-node1 ~]# docker exec -it 3d404e658 /bin/bash rootlifecycle-demo:~# cat /usr/share/message Hello from the postStart handler 1. 定义了一个 nginx 镜像的容器 2. 设置了一个 postStart 和 preStop 参数 ​ postStart:是在容器启动后立刻执行一个指定的操作。 注意postStart 定义的操作虽然是在 Docker 容器 ENTRYPOINT 执行之后但它并不严格保证顺序。也就是说在 postStart 启动时ENTRYPOINT 有可能还没有结束。 如果 postStart执行超时或者错误k8s 会在该 Pod 的 Events 中报出该容器启动失败的错误信息导致 Pod 也处于失败的状态。 ​ preStop:是容器被杀死之前比如收到了 SIGKILL 信号。 注意preStop 操作的执行是同步的。 所以它会阻塞当前的容器杀死流程直到这个 Hook 定义操作完成之后才允许容器被杀死这跟 postStart 不一样。 投射数据卷 Projected Volume 注Projected Volume 是 Kubernetes v1.11 之后的新特性 卷配置卷、加密卷、数据卷 什么是Projected Volume 在 k8s 中有几种特殊的 Volume它们的意义不是为了存放容器里的数据而是为容器提供预先定义好的数据。 将容器使用的数据变量做成一个卷挂载到容器内部供容器使用。 从容器的角度来看这些 Volume 里的信息仿佛是被 k8s 投射Project进入容器当中的。 k8s 支持的 Projected Volume 一共有四种方式 Secret ConfigMap Downward API ServiceAccountToken Secret详解 secret用来保存小片敏感数据的k8s资源例如密码token或者秘钥。这类数据当然也可以存放在 Pod或者镜像中但是放在Secret中是为了更方便的控制如何使用数据并减少暴露的风险。而不需要 把这些敏感数据暴露到镜像或者Pod Spec中。 用户可以创建自己的secret系统也会有自己的secret。Pod需要先引用才能使用某个secret ​Secret类型type 1.kubernetes.io/service-account-token 用于被 serviceaccount 引用。serviceaccout 创建时 Kubernetes 会默认创建对应的 secret。 Pod 如果使用了 serviceaccount对应的 secret 会自动挂载到 Pod 的的/run/secrets/kubernetes.io/serviceaccount 目录中。 2.Opaquebase64编码格式的Secret 用来存储密码、秘钥等。但数据也可以通过base64 –decode解码得到原始数据所有加密性很弱 3.kubernetes.io/dockerconfigjson 用来存储私有docker registry的认证信息 4.kubernetes.io/tls 此类型仅用于存储私钥和证书 Pod使用secret方式 1作为环境变量可以将Secret中的数据作为环境变量暴露给Pod中的容器。这种方式便于应用程序 直接读取而不必担心文件路径的问题。 2作为Volume挂载Secret也可以作为一个Volume被一个或多个容器挂载。这种方式适用于需要将 Secret作为文件形式访问的情况。 3拉取镜像时使用在Pod的Spec中指定imagePullSecrets字段可以使得Kubelet使用指定的 Secret来拉取私有仓库中的镜像。 內建的Secrets: 由ServiceAccount创建的API证书附加的秘钥k8s自动生成的用来访问apiserver的Secret所有Pod会默认使用这个Secret与apiserver通信 创建自己的Secret: 方式1使用kubectl create secret命令 方式2yaml文件创建Secretyaml方式创建Secret 假如某个Pod要访问数据库需要用户名密码现在我们分别设置这个用户名和密码 Secret 对象要求这些数据必须是经过 Base64 转码的以免出现明文密码显示的安全隐患。 创建一个secret.yaml文件内容用base64编码:明文显示容易被别人发现这里先转码。 [rootkub-k8s-master ~]# echo -n admin | base64 YWRtaW4 [rootkub-k8s-master ~]# echo -n 1f2d1e2e67df | base64 MWYyZDFlMmU2N2Rm ​ -w 0 表示不换行 创建一个secret.yaml文件内容用base64编码 [rootkub-k8s-master prome]# vim secret.yml --- apiVersion: v1 kind: Secret metadata:name: mysecret type: Opaque  #模糊 data:username: YWRtaW4password: MWYyZDFlMmU2N2Rm 创建 [rootkub-k8s-master prome]# kubectl apply -f secret.yml secret/mysecret created 解析Secret中内容,还是经过编码的---需要解码库被辞退了 查看secret [rootkub-k8s-master ~]# kubectl get secrets # 缩写se NAME                 TYPE                                 DATA   AGE default-token-7vc82   kubernetes.io/service-account-token   3     30h mysecret             Opaque                                2     6s ​ 查看secret详细信息 [rootkub-k8s-master prome]# kubectl get secret mysecret -o yaml apiVersion: v1 data:password: MWYyZDFlMmU2N2Rmusername: YWRtaW4 kind: Secret metadata:creationTimestamp: 2019-10-21T03:07:56Zname: mysecretnamespace: defaultresourceVersion: 162855selfLink: /api/v1/namespaces/default/secrets/mysecretuid: 36bcd07d-92eb-4755-ac0a-a5843ed986dd type: Opaque 手动base64解码方式:[rootkub-k8s-master ~]# echo MWYyZDFlMmU2N2Rm | base64 --decode 使用Secret secret可以作为数据卷挂载或者作为环境变量暴露给Pod中的容器使用也可以被系统中的其他资源使用。 一个Pod中引用Secret的列子 创建一个Secret多个Pod可以引用同一个Secret ​ 修改Pod的定义在spec.volumes[]加一个volume给这个volume起个名字spec.volumes[].secret.secretName记录的是要引用的Secret名字 [rootkub-k8s-master prome]# vim pod_use_secret.yaml apiVersion: v1 kind: Pod metadata:name: mypodlabels:app:webapp spec:containers:- name: testredisimage: daocloud.io/library/redisimagePullPolicy:IfNotPresentvolumeMounts:    #挂载一个卷- name: foo     #这个名字需要与定义的卷的名字一致mountPath: /etc/foo  #挂载到容器里哪个目录下随便写readOnly: truevolumes:     #数据卷的定义- name: foo   #卷的名字这个名字自定义secret:    #卷是直接使用的secret。secretName: mysecret   #调用刚才定义的secret创建 [rootkub-k8s-master prome]# kubectl apply -f pod_use_secret.yaml pod/mypod created [rootkub-k8s-master prome]# kubectl exec -it mypod /bin/bash rootmypod:/data# cd /etc/foo/ rootmypod:/etc/foo# ls password username rootmypod:/etc/foo# cat password 1f2d1e2e67df 结果中看到保存在 Etcd 里的用户名和密码信息已经以文件的形式出现在了容器的 Volume 目录里。 而这个文件的名字就是 kubectl create secret 指定的 Key或者说是 Secret 对象的 data 字段指定的 Key。 每一个被引用的Secret都要在spec.volumes中定义如果Pod中的多个容器都要引用这个Secret那么每一个容器定义中都要指定自己的volumeMounts但是Pod定义中声明一次spec.volumes就好了。 被挂载的secret内容自动更新 也就是如果修改一个Secret的内容那么挂载了该Secret的容器中也将会取到更新后的值但是这个时间间隔是由kubelet的同步时间决定的。 1.设置base64加密 [rootkub-k8s-master prome]# echo qianfeng | base64 cWlhbmZlbmcK 2.将admin替换成qianfeng [rootkub-k8s-master prome]# vim secret.yml --- apiVersion: v1 kind: Secret metadata:name: mysecret type: Opaque data:username: cWlhbmZlbmcK   #修改为qianfeng的base64加密后的password: MWYyZDFlMmU2N2Rm1.创建 [rootkub-k8s-master prome]# kubectl apply -f secret.yml Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply secret/mysecret configured 2.连接pod容器 [rootkub-k8s-master prome]# kubectl exec -it mypod /bin/bash rootmypod:/data# cd /etc/foo/my-group rootmypod:/etc/foo/my-group# ls my-username rootmypod:/etc/foo/my-group# cat my-username qianfeng 以环境变量的形式使用Secret [rootkub-k8s-master prome]# kubectl delete -f pod_use_secret.yaml pod mypod deleted [rootkub-k8s-master prome]# vim pod_use_secret.yaml --- apiVersion: v1 kind: Pod metadata:name: mypod spec:containers:- name: testredisimage: daocloud.io/library/redisenv:  #定义环境变量- name: SECRET_USERNAME   #创建新的环境变量名称valueFrom:secretKeyRef:     #调用的key是什么name: mysecret       #变量的值来自于mysecretkey: username       #username里面的值 ​ 2.创建使用secret的pod容器 [rootkub-k8s-master prome]# kubectl apply -f pod_use_secret.yaml pod/mypod created 3.连接 [rootkub-k8s-master prome]# kubectl exec -it mypod /bin/bash rootmypod:/data# echo $SECRET_USERNAME   #打印一下定义的变量 qianfeng 实战案例 1.创建数据库用户的密码secret [rootmaster test]# echo -n QianFeng123! | base64 UWlhbkZlbmdAMTIzIQ [rootmaster test]# cat secret.yml apiVersion: v1 kind: Secret metadata:name: mysql-secret type: Opaque data:password: UWlhbkZlbmdAMTIzIQ[rootmaster test]# kubectl apply -f secret.yml ​ 2.创建数据库并使用secret [rootmaster test]# cat myslq.yaml apiVersion: v1 kind: Pod metadata:name: my-mysql spec:containers:- name: mysqlimage: daocloud.io/library/mysql:5.7ports:- containerPort: 3306env:- name: MYSQL_ROOT_PASSWORDvalueFrom:secretKeyRef:name: mysql-secretkey: password [rootmaster test]# kubectl apply -f myslq.yaml [rootmaster test]# kubectl get pod -o wide NAME       READY   STATUS   RESTARTS   AGE     IP           NODE   NOMINATED NODE   READINESS GATES my-mysql   1/1     Running   0         2m47s   10.244.2.13   node2   none           none ​ 测试: [rootmaster test]# mysql -uroot -pQianFeng123! -h 10.244.2.13 -P3306 注意 如果报错上面这条命令会报错如下 # kubectl exec -it test-projected-volume /bin/sh error: unable to upgrade connection: Forbidden (usersystem:anonymous, verbcreate, resourcenodes, subresourceproxy) ​ 解决绑定一个cluster-admin的权限 # kubectl create clusterrolebinding system:anonymous   --clusterrolecluster-admin   --usersystem:anonymous clusterrolebinding.rbac.authorization.k8s.io/system:anonymous created k8s配置harbor仓库 192.168.116.141 harbor  --安装harbor仓库 1.首先在集群中的每个节点上配置登陆harbor仓库的地址 [rootmaster ~]# cat /etc/docker/daemon.json { insecure-registries: [192.168.116.141] } ​ [rootnode1 ~]# cat /etc/docker/daemon.json { insecure-registries: [192.168.116.141] } ​ [rootnode2 ~]# cat /etc/docker/daemon.json { insecure-registries: [192.168.116.141] } ​ # systemctl restart docker ​ 测试上传镜像 2.配置k8s集群连接harbor的认证secret 核心思路拉取私有仓库镜像需要配置私有仓库的登陆信息用Secret存储并且定义Deployment或者Pod时指定imagePullSecret为保存了私有仓库登陆信息的Secret名。 如果使用docker login登陆过私有仓库那么可以直接使用.docker/config.json文件生成的Secret ​ 查看master上面认证的密钥文件 [rootk1 yaml]# cat /root/.docker/config.json {auths: {192.168.116.141: {auth: YWRtaW46SGFyYm9yMTIzNDU}} } ​ 将密钥文件进行base64的加密 [rootk1 yaml]# cat /root/.docker/config.json | base64 -w 0 ewoJImF1dGhzIjogewoJCSIxOTIuMTY4LjExNi4xNDEiOiB7CgkJCSJhdXRoIjogIllXUnRhVzQ2U0dGeVltOXlNVEl6TkRVPSIKCQl9Cgl9Cn0 ​创建k8s连接harbor的secret #注意: Secret的data项目key是.dockerconfigjson; .docker/config.json文件BASE64编码然后粘贴到data[.dockerconfigjson]。不要有换行 Secret type必须是kubernetes.io/dockerconfigjson; ​ [rootk1 ~]# cat harbor-secret.yaml apiVersion: v1 kind: Secret metadata:name: harbor-login type: kubernetes.io/dockerconfigjson data:.dockerconfigjson: ewoJImF1dGhzIjogewoJCSIxOTIuMTY4LjExNi4xNDEiOiB7CgkJCSJhdXRoIjogIllXUnRhVzQ2U0dGeVltOXlNVEl6TkRVPSIKCQl9Cgl9Cn0[rootk1 ~]# kubectl apply -f harbor-secret.yaml secret/harbor-login created ​ 查看 [rootk1 ~]# kubectl get secret NAME                 TYPE                                 DATA   AGE default-token-zdkzq   kubernetes.io/service-account-token   3     10h harbor-login         kubernetes.io/dockerconfigjson        1     18s 测试--创建一个nginx的应用 [rootmaster yaml]# vim nginx-pod.yaml apiVersion: v1 kind: Pod metadata:name: nginx-web spec:containers:- name: nginx-1image: 192.168.116.141/nginx/nginx:v1.1 #指定镜像仓库地址imagePullSecrets:  #指定使用的harbor仓库的secret- name: harbor-login ​ [rootmaster yaml]# kubectl apply -f nginx-pod.yaml pod/nginx-web created ​ 查看 [rootmaster yaml]# kubectl get pod NAME       READY   STATUS   RESTARTS   AGE nginx-web   1/1     Running   0         2m47s 设置节点亲和性 taint 污点Taints和容忍度Tolerations的作用是在节点上设置一些排斥条件使得没有适当容忍度的 Pod 不会被调度到该节点上。但是当 nodeName 字段被设置时调度器会忽略这些条件直接将 Pod 调度到指定节点上。 nodeName 对污点的作用 直接调度当在 Pod 规约中设置了 nodeName 字段后Kubernetes 调度器会忽略这个 Pod而指定节点上的 kubelet 会尝试将 Pod 放到该节点上 4。 强制匹配使用 nodeName 的调度规则是强制性的即 Pod 必须且只能调度到指定的节点上。这种方式可以越过 Taints 污点进行调度 1。 优先级使用 nodeName 来选择节点的优先级高于使用 nodeSelector 或亲和性与反亲和性的规则 19。 apiVersion: v1 kind: Pod metadata:name: webapp2labels:app: webapp2 spec:nodeName: k4containers:- name: webappimage: daocloud.io/library/nginximagePullPolicy: IfNotPresentports:- containerPort: 80 kubectl taint nodes k4 key1value1:NoSchedule taints 是键值数据用在节点上定义污点 tolerations 是键值数据用在pod上定义容忍度能容忍哪些污点。 taints的 effect 字段 必填 用来定义对pod对象的排斥等级 NoSchedule仅影响pod调度过程仅对未调度的pod有影响。例如这个节点的污点改了使得之前调度的pod不能容忍了对现存的pod对象不产生影响NoExecute既影响调度过程又影响现存的pod对象例如如果现存的pod不能容忍节点后来加的污点这个pod就会被驱逐排斥等级最高PreferNoSchedule最好不也可以是NoSchedule的柔性版本。例如pod实在没其他节点调度了也可以到到这个污点等级的节点上排斥等级最低 污点增删查操作 #设置(增加)污点 kubectl taint node 节点名 键值:污点类型 kubectl taint node node01 key1value1:NoSchedule#节点说明中查找 Taints 字段 kubectl describe node 节点名 kubectl describe node node01 kubectl describe node node01 | grep Taints kubectl describe node node01 | grep -A2 -i taint#去除(删除)污点 kubectl taint node 节点名 键名- kubectl taint node node01 key1- kubectl taint node 节点名 键名值:污点类型- kubectl taint node node01 key1:NoSchedule-key2- 这将删除所有键名为key2的污点 -A2 表示显示过滤行及其后两行 -i 表示不区分大小写 容忍度操作符 在Pod上定义容忍度时它支持两种操作符Equal和Exists。 Equal容忍度与污点必须在key、value和effect三者完全匹配。 Exists容忍度与污点必须在key和effect二者完全匹配容忍度中的value字段要使用空值。 apiVersion: v1 kind: Pod metadata:name: example-pod spec:containers:- name: example-containerimage: nginx:latesttolerations:# 使用 Equal 操作符要求 key、value 和 effect 完全匹配- key: example-keyoperator: Equalvalue: example-valueeffect: NoSchedule# 使用 Exists 操作符只要 key 和 effect 匹配即可- key: example-keyoperator: Existseffect: NoSchedule# 特殊情况匹配所有 key、value 和 effect 为 NoSchedule 的污点- key: operator: Existseffect: NoSchedule ConfigMap配置卷 ConfigMap 主要用于存储非敏感数据如应用配置文件、环境变量、命令行参数等。它允许你将配置信 息以键值对的形式存储并可以在 Pod 的环境变量、命令行参数或者配置卷中使用它们。 ConfigMap与 Secret 类似用来存储配置文件的kubernetes资源对象所有的配置内容都存储在etcd中。 ConfigMap与 Secret 的区别 ConfigMap 保存的是不需要加密的、应用所需的配置信息。 ConfigMap 的用法几乎与 Secret 完全相同可以使用 kubectl create configmap 从文件或者目录创建 ConfigMap也可以直接编写 ConfigMap 对象的 YAML 文件。 创建ConfigMap 创建ConfigMap的方式有4种方式1通过直接在命令行中指定configmap参数创建即--from-literal 方式2通过指定文件创建即将一个配置文件创建为一个ConfigMap--from-file文件 方式3通过指定目录创建即将一个目录下的所有配置文件创建为一个ConfigMap--from-file目录 配置文件方式 方式4事先写好标准的configmap的yaml文件然后kubectl create -f 创建 1.1 使用 kubectl create configmap 命令创建 kubectl create configmap my-config --from-literalkey1value1 --from-literalkey2value2 通过命令行参数--from-literal创建。创建命令 kubectl create configmap test-configmap --from-literaluseradmin --from-literalpass1122334 结果如下面的data内容所示 [rootkub-k8s-master prome]# kubectl get configmap test-configmap -o yaml apiVersion: v1 data:pass: 1122334user: admin kind: ConfigMap metadata:creationTimestamp: 2019-10-21T07:48:15Zname: test-configmapnamespace: defaultresourceVersion: 187590selfLink: /api/v1/namespaces/default/configmaps/test-configmapuid: 62a8a0d0-fab9-4159-86f4-a06aa213f4b1 1.2 从文件创建 kubectl create configmap my-config --from-fileexample.conf 编辑文件server.conf内容如下 [rootkub-k8s-master prome]# vim server.conf server { listen 80; server_name localhost; location / { root /var/www/html; index index.html index.htm; } } 创建可以有多个--from-file kubectl create configmap test-config2 --from-fileserver.conf 结果如下面data内容所示 [rootkub-k8s-master prome]# kubectl get configmap test-config2 -o yaml apiVersion: v1 data:server.conf: | #多行字符串开始符号|前是key是文件名|后是值是文件内容server {listen 80;server_name localhost;localtion / {root /var/www/html;index index.html index.htm;}} kind: ConfigMap metadata:creationTimestamp: 2019-10-21T08:01:43Zname: test-config2namespace: defaultresourceVersion: 188765selfLink: /api/v1/namespaces/default/configmaps/test-config2uid: 790fca12-3900-4bf3-a017-5af1070792e5 通过指定文件创建时configmap会创建一个key/value对key是文件名value是文件内容。 1.3 从目录创建 kubectl create configmap my-config --from-filedir/ ​configs 目录下的config-1和config-2内容如下所示 [rootkub-k8s-master prome]# mkdir config [rootkub-k8s-master prome]# cd config/ [rootkub-k8s-master config]# vim config1 aaa bbb cd [rootkub-k8s-master config]# vim config2 eee fff hk 创建 [rootkub-k8s-master config]# cd .. [rootkub-k8s-master prome]# kubectl create configmap test-config3 --from-file./config configmap/test-config3 created 查看data内容 [rootkub-k8s-master prome]# kubectl get configmap test-config3 -o yaml 指定目录创建时configmap内容中的各个文件会创建一个key/value对key是文件名value是文件内容。 1.4 使用 YAML 文件创建 通过事先写好configmap的标准yaml文件创建 yaml文件内容如下 注意其中一个key的value有多行内容时要添加竖线| [rootkub-k8s-master prome]# vim configmap.yaml --- apiVersion: v1 kind: ConfigMap metadata:name: test-config4namespace: default data:cache_host: memcached-gcxtcache_port: 11211cache_prefix: gcxtmy.cnf: |[mysqld]log-bin mysql-binuser mysqlserver-id 1app.conf:server {listen 80;server_name localhost;location / {root /usr/share/nginx/html;index index.html;}}port: 80user: nginx 创建 [rootkub-k8s-master prome]# kubectl apply -f configmap.yaml configmap/test-config4 created 查看结果 [rootkub-k8s-master prome]# kubectl get configmap test-config4 -o yaml 查看configmap的详细信息 # kubectl describe configmap 查看ConfigMap # 查看命名空间中的所有 ConfigMap kubectl get configmap -n namespace# 查看名为 game-config 的 ConfigMap 的详细信息 kubectl describe configmap game-config -n namespace# 查看 ConfigMap 的 YAML 格式定义 kubectl get configmap configmap-name -n namespace -o yaml# 查看 ConfigMap 中特定键的值 kubectl get configmap configmap-name -n namespace -o jsonpath{.data.key-name}# 查看所有命名空间中的 ConfigMap kubectl get configmap -A# 查看带有特定标签的 ConfigMap kubectl get configmap -l label-keylabel-value -n namespace# 使用管道查看 ConfigMap 数据并通过 jq 处理 kubectl get configmap configmap-name -n namespace -o yaml | jq .data 删除ConfigMap # 删除单个 ConfigMap kubectl delete configmap configmap-name -n namespace# 示例删除位于 default 命名空间中的名为 game-config 的 ConfigMap kubectl delete configmap game-config -n default# 如果当前上下文已经设置为某个命名空间可以省略 -n 参数 kubectl delete configmap game-config# 通过标签选择器删除多个 ConfigMap kubectl delete configmap -l label-keylabel-value -n namespace# 示例删除所有带有 envproduction 标签的 ConfigMap kubectl delete configmap -l envproduction -n default# 通过 YAML 文件删除 kubectl delete -f path-to-yaml-file# 示例删除文件 configmaps.yaml 中定义的所有 ConfigMap kubectl delete -f configmaps.yaml 使用ConfigMap 使用ConfigMap的方式一种是通过环境变量的方式直接传递pod另一种是使用volume的方式挂载入到pod内 示例ConfigMap文件 [rootkub-k8s-master prome]# vim config-map.yml --- apiVersion: v1 kind: ConfigMap metadata:name: config-mapnamespace: default data:special.how: veryspecial.type: charm   ​ 创建   [rootkub-k8s-master prome]# kubectl apply -f config-map.yml configmap/config-map created 2.1 通过变量使用 (1) 使用valueFrom、configMapKeyRef、name、key指定要用的key: 设置指定变量的方式 [rootkub-k8s-master prome]# vim testpod.yml --- apiVersion: v1 kind: Pod metadata:name: dapi-test-pod spec:containers:- name: test-containerimage: daocloud.io/library/nginxenv:   #专门在容器里面设置变量的关键字- name: SPECIAL_LEVEL_KEY   #这里的-name,是容器里设置的新变量的名字valueFrom:configMapKeyRef:name: config-map   #这里是来源于哪个configMapkey: special.how      #configMap里的key- name: SPECIAL_TYPE_KEYvalueFrom:configMapKeyRef:name: config-mapkey: special.typerestartPolicy: Never ​ 创建pod [rootkub-k8s-master prome]# kubectl apply -f testpod.yml pod/dapi-test-pod created 测试 [rootkub-k8s-master prome]# kubectl exec -it dapi-test-pod /bin/bash rootdapi-test-pod:/# echo $SPECIAL_TYPE_KEY charm (2) 通过envFrom、configMapRef、name使得configmap中的所有key/value对儿 都自动变成环境变量 [rootkub-k8s-master prome]# kubectl delete -f testpod.yml pod dapi-test-pod deleted [rootkub-k8s-master prome]# cp testpod.yml testpod.yml.bak [rootkub-k8s-master prome]# vim testpod.yml --- apiVersion: v1 kind: Pod metadata:name: dapi-test-pod spec:containers:- name: test-containerimage: daocloud.io/library/nginxenvFrom:- configMapRef:name: config-maprestartPolicy: Never 这样容器里的变量名称直接使用configMap里的key名 [rootkub-k8s-master prome]# kubectl apply -f testpod.yml pod/dapi-test-pod created. [rootkub-k8s-master prome]# kubectl exec -it dapi-test-pod -- /bin/bash rootdapi-test-pod:/# env HOSTNAMEdapi-test-pod NJS_VERSION0.3.3 NGINX_VERSION1.17.1 KUBERNETES_PORT_443_TCP_PROTOtcp KUBERNETES_PORT_443_TCP_ADDR10.96.0.1 PKG_RELEASE1~stretch KUBERNETES_PORTtcp://10.96.0.1:443 PWD/ special.howvery HOME/root KUBERNETES_SERVICE_PORT_HTTPS443 KUBERNETES_PORT_443_TCP_PORT443 KUBERNETES_PORT_443_TCPtcp://10.96.0.1:443 TERMxterm SHLVL1 KUBERNETES_SERVICE_PORT443 PATH/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin special.typecharm KUBERNETES_SERVICE_HOST10.96.0.1 _/usr/bin/env 2.2 作为volume挂载使用 (1) 把1.4中test-config4所有key/value挂载进来 [rootkub-k8s-master prome]# kubectl delete -f testpod.yml pod dapi-test-pod deleted [rootkub-k8s-master prome]# vim volupod.yml --- apiVersion: v1 kind: Pod metadata:name: nginx-configmap spec:containers:- name: nginx-configmapimage: daocloud.io/library/nginxvolumeMounts:- name: config-volume4mountPath: /tmp/config4volumes:- name: config-volume4configMap:name: test-config4创建pod [rootkub-k8s-master prome]# kubectl apply -f volupod.yml pod/nginx-configmap created 进入容器中/tmp/config4查看 [rootkub-k8s-master prome]# kubectl exec -it nginx-configmap -- /bin/bash rootnginx-configmap:/# ls /tmp/config4/ cache_host cache_port cache_prefix my.cnf rootnginx-configmap:/# cat /tmp/config4/cache_host memcached-gcxt rootnginx-configmap:/# 可以看到在config4文件夹下以每一个key为文件名,value为内容,创建了多个文件。 实战一创建Nginx配置并挂载 创建了一个包含 Nginx 配置的 ConfigMap并挂载到容器中的 Nginx 配置目录。 1.定义nginx配置文件使用configmap制作为卷挂载到nginx容器中 [rootk8s-master map]# cat nginx_configmap.yml apiVersion: v1 kind: ConfigMap metadata:name: ng-map data:app.conf: |server {listen 80;server_name localhost;location / {root /data/www/html;index index.html;}}[rootk8s-master map]# kubectl apply -f nginx_configmap.yml [rootk8s-master map]# kubectl get cm NAME               DATA   AGE kube-root-ca.crt   1     32d ng-map             1     18m [rootk8s-master map]# kubectl describe cm ng-map Name:         ng-map Namespace:   default Labels:       none Annotations: none ​ Dataapp.conf: ---- server {listen 80;server_name localhost;location / {root /data/www/html;index index.html;}} ​ ​ BinaryData​ Events: none ​ 2.将configmap定义成卷挂载到容器里面 [rootk8s-master map]# cat use_nginx_map.yml apiVersion: v1 kind: Pod metadata:name: my-nginxlabels:app: nginx spec:containers:- image: daocloud.io/library/nginximagePullPolicy: IfNotPresentname: nginxports:- containerPort: 80lifecycle:postStart:exec:command: [/bin/bash,-c,mkdir -p /data/www/html]preStop:exec:command: [/bin/sh,-c,nginx -s quit]volumeMounts:- name: nginx-confmountPath: /etc/nginx/conf.dvolumes:- name: nginx-confconfigMap:name: ng-map[rootk8s-master map]# kubectl apply -f use_nginx_map.yml [rootk8s-master map]# kubectl get pod NAME               READY   STATUS   RESTARTS     AGE my-nginx           1/1     Running   0             3m17s [rootk8s-master map]# kubectl exec -it my-nginx /bin/bash kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. rootmy-nginx:/# cd /data/www/ rootmy-nginx:/data/www# ls html rootmy-nginx:/data/www# cd html/ rootmy-nginx:/data/www/html# ls rootmy-nginx:/data/www/html# echo 123123 index.html rootmy-nginx:/data/www/html# exit exit [rootk8s-master map]# kubectl get pod -o wide NAME               READY   STATUS   RESTARTS     AGE     IP             NODE     NOMINATED NODE   READINESS GATES my-nginx           1/1     Running   0             32s     10.244.247.45   node-2   none           none ​ [rootk8s-master map]# curl 10.244.247.45 123123 实战二创建并使用 ConfigMap 配置文件。 创建了一个包含静态网页内容的 ConfigMap并挂载到容器中的 Nginx 静态文件目录。 创建configmap [rootk1 configmap]# vim configmap.yaml --- apiVersion: v1 kind: ConfigMap metadata:name: nginx-server-confnamespace: default data:index.html: |Hello, cloud computingHello, Mr. Wang[rootk1 configmap]# kubectl get configmap NAME               DATA   AGE nginx-server-conf   2     7s [rootk1 configmap]# kubectl get configmap nginx-server-conf -o yaml ​ 使用configmap [rootkub-k8s-master configmap]# vim pod.yaml --- apiVersion: v1 kind: Pod metadata:name: test-webapp spec:containers:- name: nginx-appimage: daocloud.io/library/nginxports:- containerPort: 80volumeMounts:- name: nginx-volumemountPath: /usr/share/nginx/htmlvolumes:- name: nginx-volumeconfigMap:name: nginx-server-conf [rootkub-k8s-master configmap]# kubectl apply -f pod.yaml [rootkub-k8s-master configmap]# kubectl get pod NAME         READY   STATUS   RESTARTS   AGE test-webapp   1/1     Running   0         6s [rootkub-k8s-master configmap]# kubectl exec -it test-webapp -- /bin/bash roottest-webapp:/# cd /usr/share/nginx/html/ roottest-webapp:/usr/share/nginx/html# ls index.html roottest-webapp:/usr/share/nginx/html# cat index.html Hello, cloud computing Hello, Mr. Wang ​ [rootkub-k8s-master configmap]# curl 10.244.2.25 Hello, cloud computing Hello, Mr. Wang restartPolicy  spec.restartPolicy字段在 Pod 定义中进行设置。Always 表示一直重启这也是默认的重启策略。Kubelet 会定期查询容器的状态一旦某个容器处于退出状态就对其执行重启操作 OnFailure 表示只有在容器异常退出即退出码不为 0 时才会对其进行重启操作 Never 表示从不重启 Downward API Downward API 用于在容器中获取pod的基本信息kubernetes原生支持 ​ Downward API提供了两种方式用于将 POD 的信息注入到容器内部 1.环境变量用于单个变量可以将 POD 信息直接注入容器内部。 2.Volume挂载将 POD 信息生成为文件直接挂载到容器内部中去。 目前 Downward API 支持的字段 1. 使用 fieldRef 可以声明使用: spec.nodeName - 宿主机名字 status.hostIP - 宿主机 IP metadata.name - Pod 的名字 metadata.namespace - Pod 的 Namespace status.podIP - Pod 的 IP spec.serviceAccountName - Pod 的 Service Account 的名字 metadata.uid - Pod 的 UID metadata.labels[KEY] - 指定 KEY 的 Label 值 metadata.annotations[KEY] - 指定 KEY 的 Annotation 值 metadata.labels - Pod 的所有 Label metadata.annotations - Pod 的所有 Annotation ​上面这个列表的内容随着 Kubernetes 项目的发展肯定还会不断增加。所以这里列出来的信息仅供参考在使用 Downward API 时还是要记得去查阅一下官方文档。​ 所有基本信息可以使用下面的方式去查看describe方式看不出来[rootk1 configmap]# kubectl get pod test-webapp -o yaml apiVersion: v1 kind: Pod metadata:annotations:kubectl.kubernetes.io/last-applied-configuration: |{apiVersion:v1,kind:Pod,metadata:{annotations:{},name:test-webapp,namespace:default},spec:{containers:[{image:daocloud.io/library/nginx,name:nginx-app,volumeMounts:[{mountPath:/usr/share/nginx/html,name:nginx-volume}]}],volumes:[{configMap:{name:nginx-server-conf},name:nginx-volume}]}}creationTimestamp: 2021-02-21T09:44:51Zname: test-webappnamespace: defaultresourceVersion: 270687selfLink: /api/v1/namespaces/default/pods/test-webappuid: ed92d685-f800-464f-95dc-d6aa5f92fc9c ...... 实战 使用fieldRef获取 POD 的基本信息以环境变量的方式实现 [rootk1 prome]# vim test-env-pod.yml --- apiVersion: v1 kind: Pod metadata:name: test-env-podnamespace: kube-system spec:containers:- name: test-env-podimage: daocloud.io/library/nginxenv:- name: POD_NAME   #第一个环境变量的名字valueFrom:      #使用valueFrom方式设置fieldRef:    #关联一个字段metadata.namefieldPath: metadata.name  #这个字段从当前运行的pod详细信息查看- name: POD_NAMESPACEvalueFrom:fieldRef:fieldPath: metadata.namespace- name: POD_IPvalueFrom:fieldRef:fieldPath: status.podIP 注意 POD 的 name 和 namespace 属于元数据是在 POD 创建之前就已经定下来了的所以使用metadata 获取就可以了但是对于 POD 的 IP 则不一样因为POD IP 是不固定的POD 重建了 就变了它属于状态数据所以使用 status 去获取。 创建上面的 POD [rootk1 prome]# kubectl apply -f test-env-pod.yml pod/test-env-pod created POD 创建成功后查看 [rootk1 prome]# kubectl exec -it test-env-pod -n kube-system -- /bin/bash roottest-env-pod:/# env | grep POD POD_NAMEtest-env-pod POD_NAMESPACEkube-system POD_IP10.244.1.35 roottest-env-pod:/# Volume挂载 通过Downward API将 POD 的 Label、等信息通过 Volume 以文件的形式挂载到容器的某个文件中去然后在容器中打印出该文件的值来验证。 [rootk1 prome]# vim test-volume-pod.yaml --- apiVersion: v1 kind: Pod metadata:name: test-volume-podnamespace: kube-systemlabels:k8s-app: test-volumenode-env: test spec:containers:- name: test-volume-pod-containerimage: daocloud.io/library/nginxvolumeMounts:- name: podinfomountPath: /etc/podinfovolumes:- name: podinfodownwardAPI:items:- path: labelsfieldRef:fieldPath: metadata.labels 创建上面的 POD [rootk1 prome]# kubectl apply -f test-volume-pod.yaml [rootk1 prome]# kubectl get pod -n kube-system [rootk1 prome]# kubectl exec -it test-volume-pod -n kube-system -- /bin/bash Secret、ConfigMap以及 Downward API 这三种 Projected Volume 定义的信息大多还可以 通过环境变量的方式出现在容器里。但是通过环境变量获取这些信息的方式不具备自动更新的能力。 一般情况下建议使用 Volume 文件的方式获取这些信息。 ServiceAccount详解 k8s中提供了良好的多租户认证管理机制如RBAC、ServiceAccount还有各种Policy等。官方文档地址Configure Service Accounts for Pods | Kubernetes/ k8s中账户分为UserAccounts用户账户 和 ServiceAccounts服务账户 两种UserAccount是给kubernetes集群外部用户使用的使用kubectl访问k8s的时候要用的用户 而在kubeadm安装的k8s默认的useraccount用户是kubernetes-admin 什么是 Service Account 1定义 ServiceAccount 是 Kubernetes (K8s) 中的一种内置对象它提供了应用和服务的一个身份 使得它们可以与API服务器交互或者与其他服务通信。   ​​​​​​​2使用场景 Service Account它并不是给kubernetes集群的用户使用的而是给pod里面的进程使用的 它为pod提供必要的身份认证。----专门为pod里面的进程和apiserver通信提供认证的。 默认的ServiceAccount 3默认的ServiceAccount 每个命名空间都会自动创建一个名为default的ServiceAccount这个ServiceAccount会在没有显式 指定其他ServiceAccount的情况下被分配给新创建的Pod。 Service account与User account区别 1. User account是为人设计的而service account则是为Pod中的进程调用Kubernetes API或 其他外部服务而设计的 2. User account是跨namespace的而service account则是仅局限它所在的namespace 3. 每个namespace都会自动创建一个default service account     4. Token controller检测service account的创建并为它们创建secret Service Account应用 因为平时系统会使用默认service account我们不需要自己创建感觉不到service account的存在本实验是使用自己手动创建的service account 1、创建serviceaccount [rootk1 ~]# kubectl create serviceaccount mysa serviceaccount/mysa created 2、查看mysa [rootk1 ~]# kubectl describe sa mysa Name:               mysa Namespace:           default Labels:             none Annotations:         none Image pull secrets: none Mountable secrets:   mysa-token-cknwf Tokens:             mysa-token-cknwf Events:             none 3、查看mysa自动创建的secret [rootk1 ~]# kubectl get secret NAME                 TYPE                                 DATA   AGE db-user-pass         Opaque                                2     11h default-token-6svwp   kubernetes.io/service-account-token   3     4d23h mysa-token-cknwf     kubernetes.io/service-account-token   3     76s mysecret             Opaque                                2     11h mysecret-01           Opaque                                2     6h58m pass                 Opaque                                1     7h6m user                 Opaque                                1     7h7m ​ 4、使用mysa的sa资源配置pod [rootkub-k8s-master ~]# cd prome/ [rootkub-k8s-master prome]# vim mysa-pod.yaml --- apiVersion: v1 kind: Pod metadata:name: nginx-podlabels:app: my-pod spec:containers:- name: my-podimage: daocloud.io/library/nginxports:- name: httpcontainerPort: 80serviceAccountName: mysa   #指定serviceaccount的名称5、导入 [rootk1 prome]# kubectl apply -f mysa-pod.yaml pod/nginx-pod created 6、查看 [rootk1 prome]# kubectl describe pod nginx-pod 7、查看使用的token和secret使用的是mysa的token [root1 prome]# kubectl get pod nginx-pod -o jsonpath{.spec.volumes} [map[name:mysa-token-cknwf secret:map[defaultMode:420 secretName:mysa-token-cknwf]]] RBAC (基于角色的访问控制) 在k8s执行kubectl命令需要与apiserver进行通信且k8s通过apiserver对外提供服务需要对访问 apiserver的用户做认证。当认证通过后整个用户只是被apiserver信任的用户只能访问apiserver 没有对各种资源操作权限需要对此用户进行授权。基于角色的访问控制Role-Based Access Control, RBAC是一种用于管理用户权限的方法广泛 应用于企业级系统中。在 Kubernetes 中RBAC 是一种授权机制用于控制集群对象上的访问权限。 Kubernetes 自 1.5 版本开始就支持 RBAC从 1.8 版本开始成为默认启用的授权模式。RBAC 是一种通过给角色赋予相应权限从而使该角色具有访问相关资源权限的机制。 Kubernetes授权模式授权策略 - ABAC (Attribute Based Access Control)基于属性的访问控制。表示使用用户配置的授权 规则对用户请求进行匹配和控制 - RBAC (Role-Based Access Control)基于角色的访问控制。默认使用该规则 - Webhook一种 HTTP 回调模式允许使用远程 REST 端点管理授权 - Node允许节点访问集群。一种特殊用途的授权模式专门授权由 kubelet 发出的 API 请求 - AlwaysDeny始终拒绝访问请求。仅用于测试 - AlwaysAllow始终允许访问请求。如果有集群不需要授权流程则可以采用该策略RBAC API类型 RBAC API 所声明的四种顶级类型【Role、ClusterRole、RoleBinding 和 ClusterRoleBinding】。用户可以像与其他 API 资源交互一样通过 kubectl API 调用等方式与这些资源交互。  Kubernetes 支持两种类型的用户 - User为人设计的用户账户如个人使用的账号。跨Namespace的。手动认证使用 kubeconfig 文件。用于人类操作、外部监控。 - ServiceAccount为Pod设计的账号主要用于Pod内的应用程序与Kubernetes API服务器进 行通信。仅限于其所在命名空间内的操作。自动挂载认证Token至Pod。适用于服务间通信、自动化流程RBAC 授权步骤 1. 定义角色在定义角色时指定此角色对于资源的访问控制规则。 2. 绑定角色将主体与角色进行绑定对用户进行访问授权。RBAC 资源分为两个级别 - 命名空间级别Role 和 RoleBinding这些资源仅在一个特定的命名空间内生效。 - 集群级别ClusterRole 和 ClusterRoleBinding这些资源在整个集群范围内生效。Role 和 ClusterRole - Role普通角色仅用于授予对某一单一命名空间中资源的访问权限。 - ClusterRole集群角色适用于整个 Kubernetes 集群范围内的资源访问权限。 Role 和 ClusterRole 的规则 - 允许的操作如 get, list, update, create, delete 等权限。 - 允许操作的对象如 pod, svc服务等资源。RoleBinding 和 ClusterRoleBinding - RoleBinding将用户绑定到 Role 上。 - ClusterRoleBinding将用户绑定到 ClusterRole 上。如果使用 ClusterRoleBinding 绑定到 ClusterRole 上表示绑定的用户拥有所有命名空间的权限。 kubectl config上下文操作 ​检查现有的上下文 kubectl config get-contexts 删除现有的上下文 kubectl config delete-context context-name 创建新的集群和上下文 # 创建集群配置 kubectl config set-cluster kubernets \--certificate-authority/path/to/ca.pem \--serverhttps://api.kubernets.example.com # 创建用户配置 kubectl config set-credentials kubernets-admin \--client-certificate/path/to/admin.pem \--client-key/path/to/admin-key.pem # 创建上下文 kubectl config set-context kubernets-adminkubernets \--clusterkubernets \--userkubernets-admin # 设置当前上下文 kubectl config use-context kubernets-adminkubernets 修改现有的上下文 # 假设已有上下文名为 existing-context kubectl config rename-context existing-context kubernets-adminkubernets 测试连接 kubectl cluster-info rolebinding和clusterrolebinding操作命令 # 创建 RoleBinding # 通过 YAML 文件创建 RoleBinding kubectl apply -f path/to/rolebinding.yaml -n namespace# 创建 ClusterRoleBinding # 通过 YAML 文件创建 ClusterRoleBinding kubectl apply -f path/to/clusterrolebinding.yaml# 查看 RoleBinding kubectl get rolebindings -n namespace # 查看特定命名空间中的 RoleBinding kubectl get rolebinding rolebinding-name -n namespace # 查看所有命名空间中的 RoleBinding kubectl get rolebindings --all-namespaces# 查看 ClusterRoleBinding kubectl get clusterrolebindings # 查看特定 ClusterRoleBinding kubectl get clusterrolebinding clusterrolebinding-name# 显示 RoleBinding 的详细信息 kubectl describe rolebinding rolebinding-name -n namespace # 显示 ClusterRoleBinding 的详细信息 kubectl describe clusterrolebinding clusterrolebinding-name# 删除 RoleBinding kubectl delete rolebinding rolebinding-name -n namespace# 删除 ClusterRoleBinding kubectl delete clusterrolebinding clusterrolebinding-name# 更新 RoleBinding # 修改 YAML 文件后重新应用 kubectl apply -f path/to/modified-rolebinding.yaml -n namespace# 更新 ClusterRoleBinding # 修改 YAML 文件后重新应用 kubectl apply -f path/to/modified-clusterrolebinding.yaml# 查看 RoleBinding 的 YAML 定义 kubectl get rolebinding rolebinding-name -n namespace -o yaml# 查看 ClusterRoleBinding 的 YAML 定义 kubectl get clusterrolebinding clusterrolebinding-name -o yaml# 使用 JSONPath 输出 RoleBinding 的特定信息 kubectl get rolebinding rolebinding-name -n namespace -o jsonpath{.spec.subjects}# 使用 JSONPath 输出 ClusterRoleBinding 的特定信息 kubectl get clusterrolebinding clusterrolebinding-name -o jsonpath{.spec.roleRef.name}# 检查 RoleBinding 的状态 kubectl get rolebinding rolebinding-name -n namespace -o jsonpath{.status}# 检查 ClusterRoleBinding 的状态 kubectl get clusterrolebinding clusterrolebinding-name -o jsonpath{.status}# 使用 kubectl auth can-i 检查权限 kubectl auth can-i * * -n namespace # 或者对于特定用户和服务账户 kubectl auth can-i * * --asusername -n namespace kubectl auth can-i * * --asserviceaccount:namespace:name -n namespace# 修复 RoleBinding # 如果 RoleBinding 损坏可以删除后重新创建 kubectl delete rolebinding rolebinding-name -n namespace kubectl apply -f path/to/rolebinding.yaml -n namespace# 修复 ClusterRoleBinding # 如果 ClusterRoleBinding 损坏可以删除后重新创建 kubectl delete clusterrolebinding clusterrolebinding-name kubectl apply -f path/to/clusterrolebinding.yaml 创建k8s账号与RBAC授权使用 [rootk1 ~]#kubectl config view 显示如下 apiVersion: v1 clusters: - cluster:certificate-authority-data: DATAOMITTEDserver: https://172.16.229.4:6443     #apiserver的地址name: kubernetes                         #集群的名字 contexts:  #上下文--环境 - context:cluster: kubernetes   #当前环境的名字                   user: kubernetes-admin  #使用的用户  name: kubernetes-adminkubernetes     #环境的名字 current-context: kubernetes-adminkubernetes       #当前上下文的名字 kind: Config preferences: {} users: - name: kubernetes-admin #默认的管理员用户user:client-certificate-data: REDACTEDclient-key-data: REDACTED 创建账号 1、创建私钥 给自己创建一个私钥 [rootk1 ~]# (umask 077; openssl genrsa -out soso.key 2048) 查看私钥 # kubectl get config 用此私钥创建一个csr(证书签名请求)文件 [rootk1 ~]# openssl req -new -key soso.key -out soso.csr -subj /CNsoso 2、拿着私钥和请求文件生成证书 [rootk1 ~]# openssl x509 -req -in soso.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out soso.crt -days 365 生成账号如soso用户 [rootk1 ~]# kubectl config set-credentials soso --client-certificatesoso.crt --client-keysoso.key --embed-certstrue 3、设置上下文环境--指的是创建这个账号的环境在当前名称空间中 [rootk1 ~]# kubectl config set-context sosokubernetes --clusterkubernetes --usersoso 查看当前的工作上下文 [rootk1 ~]# kubectl config view 4、切换用户切换上下文 [rootk1 ~]# kubectl config use-context sosokubernetes 验证是否已经切换到了新的上下文 [rootk1 ~]# kubectl config current-context 5、测试还未赋予权限 [rootk1 ~]# kubectl get pod Error from server (Forbidden): pods is forbidden: User soso cannot list resource pods in API group in the namespace default # 检查现有的上下文。带有 * 标记的上下文表示当前使用的上下文 kubectl config get-contexts 查看当前上下文 kubectl config current-context 创建新的集群和上下文 # 创建集群配置 kubectl config set-cluster kubernets \--certificate-authority/path/to/ca.pem \--serverhttps://api.kubernets.example.com # 创建用户配置 kubectl config set-credentials kubernets-admin \--client-certificate/path/to/admin.pem \--client-key/path/to/admin-key.pem # 创建上下文 kubectl config set-context kubernets-adminkubernets \--clusterkubernets \--userkubernets-admin # 设置当前上下文 kubectl config use-context kubernets-adminkubernets修改现有的上下文 # 假设已有上下文名为 existing-context kubectl config rename-context existing-context kubernets-adminkubernets测试连接 kubectl cluster-info 创建一个角色role---设置权限 1.切回管理帐号 [rootk1 ~]# kubectl config use-context kubernetes-adminkubernetes Switched to context kubernetes-adminkubernetes. 创建角色命令 [rootk1 ~]# kubectl create role role-reader --verbget,list,watch --resourcepod,svc# role-headerrole名称 --verb允许执行的动作 --resource指定资源类型 yaml文件方式: [rootk1 ~]# vim role.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata:name: role-reader rules: #定义规则- apiGroups: []  #表示当前pod使用核心的APIserver组默认用表示就可以resources: [pods,svcs]verbs: [get, list, watch, create, update, delete] #[*]表示所有权限 [rootk1 ~]# kubectl apply -f role.yaml --save-config # --save-config可不写 [rootk1 ~]# kubectl get roles # 查看角色命令中role/roles都可以建议用roles [rootk1 ~]# kubectl describe role role-reader 2.绑定用户soso上面创建的用户绑定用户到role-reader [rootk1 ~]# kubectl create rolebinding myrole-binding --rolerole-reader --usersoso [rootk1 ~]# vim role-binding.yaml # yaml文件方式 apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata:name: myrolebind subjects:  #定义主体进行操作三种Subjects:Service Account、User Account、Groups - kind: Username: sosoapiGroup: rbac.authorization.k8s.io roleRef:  #定义使用哪个角色kind: Rolename: role-readerapiGroup: rbac.authorization.k8s.io [rootk1 ~]# kubectl apply -f role-binding.yaml [rootk8s-master ~]# kubectl get rolebinding 3.切换用户 [rootk1 ~]# kubectl config use-context sosokubernetes​ 4.查看权限只授权了default名称空间pod和svc的getlistwatch权限 [rootk1 ~]# kubectl get pod [rootk1 ~]# kubectl get pod -n kube-system #无权访问kube-system [rootk1 ~]# kubectl delete pod nginx-pod   #无权限删除 5.切换用户 [rootk1 ~]# kubectl config use-context kubernetes-adminkubernetes ​绑定用户到集群角色 6.删除soso账号之前绑定的rolebinding [rootk1 ~]# kubectl delete rolebinding myrolebind rolebinding.rbac.authorization.k8s.io myrolebind deleted 7.创建clusterrole #可以访问全部的namespace [rootk1 ~]# kubectl create clusterrole myclusterrole --verbget,list,watch --resourcepod,svc yaml文件方式 [rootk1 ~]# vim clusterrole.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata:name: myclusterrole rules: - apiGroups:- resources:- podsverbs:- get- list- watch [rootk1 ~]# kubectl apply -f clusterrole.yaml [rootk1 ~]# kubectl get clusterrole ​ 8.绑定集群角色到用户soso [rootk1 ~]# kubectl create clusterrolebinding my-cluster-rolebinding --clusterrolemyclusterrole --usersoso ​ yaml文件方式 [rootk1 ~]# vim clusterrolebinding.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata:name: my-cluster-rolebinding roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: myclusterrole subjects: - apiGroup: rbac.authorization.k8s.iokind: Username: soso [rootk1 ~]# kubectl apply -f clusterrolebinding.yaml [rootk1 ~]# kubectl get clusterrolebinding ​ 9.切换账号 [rootk1 ~]# kubectl config use-context sosokubernetes Switched to context sosokubernetes. ​ 10.查看权限 查看kube-system空间的pod [rootk1 ~]# kubectl get pod -n kube-system NAME                                     READY   STATUS   RESTARTS   AGE coredns-5644d7b6d9-sm8hs                 1/1     Running   0         5d coredns-5644d7b6d9-vddll                 1/1     Running   0         5d etcd-kub-k8s-master                      1/1     Running   0         5d ... ​ 注意11.切换为管理员用户 [rootk1 ~]# kubectl config use-context kubernetes-adminkubernetes 设置上下文和账户切换 设置工作上下文前提得有用户 [rootk1 ~]# kubectl config set-context sosokubernetes --clusterkubernetes --usersoso 查看当前的工作上下文 [rootk1 ~]# kubectl config view 切换上下文切换用户 [rootk1 ~]# kubectl config use-context sosokubernetes 切换为管理员用户 [rootk1 prome]# kubectl config use-context kubernetes-adminkubernetes 查看某个资源类型是由哪个apiserver版本提供 [rootk1 ~]# kubectl explain ClusterRole 容器监控检查及恢复机制 Kubernetes 探针Probes Kubernetes 支持三种类型的探针probes 启动探针startupProbe、就绪探针readinessProbe和存活探针livenessProbe。 1. 启动探针Startup Probe - 指示容器中的应用程序是否已经启动。 - 如果提供了启动探针则在它成功之前禁用所有其他探针。 - 如果启动探针失败kubelet 将杀死容器并根据其重启策略进行重启。 - 如果容器没有提供启动探针则默认状态为成功Success。 作用 - 确保应用程序完全启动并准备好接收流量之前不会启用其他探针。 - 避免在应用程序尚未准备好时进行健康检查。2. 存活探针Liveness Probe - 指示容器是否正在运行。 - 如果存活探针失败kubelet 会杀死容器并根据其重启策略重启容器。 - 如果容器不提供存活探针则默认状态为成功Success。 作用 - 确保应用程序处于非健康状态如内存泄漏能及时重启。 - 提供自愈能力使集群能够自动恢复故障容器。3. 就绪探针Readiness Probe - 指示容器是否准备好接收请求。 - 如果就绪探针失败端点控制器会将该 Pod 从与之匹配的所有 Service 的端点列表中移除。 - 初始延迟之前的就绪状态默认为失败Failure。 - 如果容器不提供就绪探针则默认状态为成功Success。 作用 - 避免新创建的 Pod 在尚未准备好处理请求的情况下被 Service 选中。 - 确保 Pod 在完全准备好之后才能接收流量提高服务的可靠性。举例说明就绪探针Readiness Probe - 问题新创建的 Pod 可能会被 Service 立即选择并将请求转发给 Pod。然而如果 Pod 尚未准备好如需要加载配置或数据或需要执行预热程序此时转发请求可能导致请求失败。 - 解决方案为 Pod 添加业务就绪探针Readiness Probe。只有当检测到 Pod 已准备好时 才允许 Service 将请求转发给 Pod。存活探针Liveness Probe - 问题即使应用程序内部出现问题如内存泄漏只要容器进程仍在运行Kubernetes 也 不会重启容器。 - 解决方案通过定义 Liveness ProbeKubernetes 可以基于探针的返回值判断容器的健康 状态并在必要时重启容器从而确保应用程序始终处于健康状态。 为什么需要容器探针 容器探针可以确保您的容器在任何时候都处于可预测的状态。 如果没有容器探针那么容器对于K8S平台而言就处于一个黑盒状态。下面是没有使用容器探针 可能出现的一些case 容器未启动负载均衡就把流量转发给容器导致请求大量异常 容器内服务不可用/发生异常负载均衡把流量转发给容器导致请求大量异常 容器已经不正常工作如容器死锁导致的应用程序停止响应K8S平台本身无法感知不能即时低重启容器。 探针的定义方式检测方式 1命令探针Exec Probe执行容器中的命令并检查命令退出的状态码如果状态码为0则说明已经就绪。 Exec 命令探针字段exec指定要执行的命令。command指定要执行的命令及其参数。initialDelaySeconds指定容器启动后首次执行探测之前的等待时间。periodSeconds指定执行探测的频率。 2HTTP 探针HTTP GET 往容器的IP:Port发送HTTP GET请求如果Probe收到2xx或3xx说明已经就绪。 HTTP 探针字段httpGet指定发送 HTTP 请求的配置。path指定请求的路径。port指定目标容器的端口号。httpHeaders可选字段指定自定义的 HTTP 请求头。initialDelaySeconds指定容器启动后首次执行探测之前的等待时间。periodSeconds指定执行探测的频率。 3TCP 探针TCP Socket 尝试与容器建立TCP连接如果能建立连接说明已经就绪。 TCP探针字段tcpSocket指定要连接的容器端口。initialDelaySeconds指定容器启动后首次执行探测之前的等待时间。periodSeconds指定执行探测的频率。探针探测结果有以下值 1、Success表示通过检测。 2、Failure表示未通过检测。 3、Unknown表示检测没有正常进行。 实战 Exec模式定义启动探针-startupprobe exec:通过指定命令执行的返回值判断容器是否启动 [rootk1 test]# vim test-start-exec.yml apiVersion: v1 kind: Pod metadata:name: pod-1labels:web: nginx spec:containers:- name: nginx-1image: daocloud.io/library/nginxports:- name: httpcontainerPort: 80startupProbe: #定义启动探针进行健康检查exec: #指定使用的类型为命令类型command:- /bin/bash- -c- cat /usr/share/nginx/html/index.htmlinitialDelaySeconds: 5 #健康检查在容器启动5s后开始执行默认是 0 秒periodSeconds: 5 #执行探测的时间间隔单位是秒默认为 10s最小值是1timeoutSeconds: 2 #表示容器必须在2s内做出相应反馈给probe否则视为探测失败默认值为1successThreshold: 1 #连续探测几次成功才认为探测成功探测1次成功表示成功最小值为1。failureThreshold: 3 #探测失败的重试次数重试一定次数后将认为失败默认为3最小值为1[rootk1 test]# kubectl get pod -w #-w实时查看 NAME   READY   STATUS   RESTARTS       AGE pod-1   0/1     Pending   0               0s pod-1   0/1     Pending   0               0s pod-1   0/1     ContainerCreating   0               0s pod-1   0/1     ContainerCreating   0               0s pod-1   0/1     Running             0               1s pod-1   1/1     Running             0               10s #等待10秒后后检查成功进入ready状态 httpget模式 httpget模式 [rootk8s-master test]# vim test-start-http.yml apiVersion: v1 kind: Pod metadata:name: pod-8labels:web: nginx spec:containers:- name: nginx-tcpimage: daocloud.io/library/nginxports:- name: httpcontainerPort: 80startupProbe:httpGet: #指定使用的类型为http请求scheme: HTTP #指定请求的协议port: 80 #指定请求的端口path: /index.html #指定请求的路径initialDelaySeconds: 5periodSeconds: 5timeoutSeconds: 2successThreshold: 1failureThreshold: 3 ​ [rootk8s-master test]# kubectl get pod -w NAME   READY   STATUS   RESTARTS       AGE pod-8   0/1     Pending   0               0s pod-8   0/1     Pending   0               0s pod-8   0/1     ContainerCreating   0               0s pod-8   0/1     ContainerCreating   0               1s pod-8   0/1     Running             0               2s pod-8   0/1     Running             0               16s pod-8   1/1     Running             0               16s 存活探针(livenessProbe)------命令模式探针 Kubernetes 文档中的例子 [rootkub-k8s-master prome]# vim ~/prome/test-liveness-exec.yaml --- apiVersion: v1 kind: Pod metadata:labels:test: livenessname: test-liveness-exec spec:containers:- name: livenessimage: daocloud.io/library/nginxargs:- /bin/sh- -c  - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 50livenessProbe:exec:command: - cat - /tmp/healthyinitialDelaySeconds: 5periodSeconds: 5 它在启动之后做的第一件事是在/tmp目录下创建了一个healthy文件以此作为自己已经正常运行的标志。而30s过后它会把这个文件删除掉。与此同时定义了一个这样的 livenessProbe健康检查。它的类型是 exec它会在容器启动后在容器里面执行一句我们指定的命令比如cat /tmp/healthy。这时如果这个文件存在这条命令的返回值就是 0Pod就会认为这个容器不仅已经启动而且是健康的。这个健康检查在容器启动5s后开始执行initialDelaySeconds: 5每5s执行一次periodSeconds: 5。 创建Pod [rootkub-k8s-master prome]# kubectl apply -f test-liveness-exec.yaml pod/test-liveness-exec created 查看 Pod 的状态 [rootkub-k8s-master prome]# kubectl get pod NAME                   READY   STATUS   RESTARTS   AGE nginx-configmap         1/1     Running   0         16h nginx-pod               1/1     Running   0         12h test-liveness-exec      1/1     Running   0         75s 由于已经通过了健康检查这个 Pod 就进入了 Running 状态。 然后30 s 之后再查看一下 Pod 的 Events [rootkub-k8s-master prome]# kubectl describe pod test-liveness-exec 发现这个 Pod 在 Events 报告了一个异常 Events:Type     Reason     Age                 From                   Message----     ------     ----                 ----                    ------- Warning Unhealthy 54s (x9 over 3m34s) kubelet, kub-k8s-node1 Liveness probe failed: cat: /tmp/healthy: No such file or directory 这个健康检查探查到 /tmp/healthy 已经不存在了所以它报告容器是不健康的。那么接下来会发生什么呢 再次查看一下这个 Pod 的状态 [rootkub-k8s-master prome]# kubectl get pod test-liveness-exec NAME                 READY   STATUS   RESTARTS   AGE test-liveness-exec   1/1     Running   4         5m19s 这时发现Pod 并没有进入 Failed 状态而是保持了 Running 状态。这是为什么呢 RESTARTS 字段从 0 到 1 的变化就明白原因了这个异常的容器已经被 Kubernetes 重启了。在 这个过程中Pod 保持 Running 状态不变。 #注 k8s 中并没有 Docker 的 Stop 语义。所以如果容器被探针检测到有问题查看状态虽然看到的是 Restart但实际却是重新创建了容器。 这个功能就是 Kubernetes 里的Pod 恢复机制也叫 restartPolicy。它是 Pod 的 Spec 部分的一个标准字段pod.spec.restartPolicy默认值是 Always即任何时候这个容器发生了异常它一定会被重新创建。 Pod 的恢复过程永远都是发生在当前节点上而不会跑到别的节点上去。事实上一旦 一个 Pod 与一个节点Node绑定除非这个绑定发生了变化pod.spec.node 字段被修改 否则它永远都不会离开这个节点。这也就意味着如果这个宿主机宕机了这个 Pod 也不会主动迁 移到其他节点上去。 http get方式定义探针 创建该pod [rootkub-k8s-master prome]# kubectl create -f liveness-httpget.yaml pod/liveness-httpget-pod created 查看当前pod的状态 [rootkub-k8s-master prome]# kubectl describe pod liveness-httpget-pod ... Liveness:       http-get http://:http/index.html delay1s timeout1s period3s #success1 #failure3 ... 登陆容器 测试将容器内的index.html删除掉 [rootkub-k8s-master prome]# kubectl exec -it liveness-httpget-pod /bin/bash rootliveness-httpget-pod:/# mv /usr/share/nginx/html/index.html index.html rootliveness-httpget-pod:/# command terminated with exit code 137 可以看到当把index.html移走后这个容器立马就退出了。 此时查看pod的信息 [rootk1 prome]# kubectl describe pod liveness-httpget-pod ... Normal   Killing   49s   kubelet, kub-k8s-node2 Container liveness-exec-container failed liveness probe, will be restarted Normal   Pulled     49s   kubelet, kub-k8s-node2 Container image daocloud.io/library/nginx already present on machine ... 看输出容器由于健康检查未通过pod会被杀掉并重新创建[rootk1 prome]# kubectl get pods NAME                   READY   STATUS             RESTARTS   AGE lifecycle-demo          1/1     Running            1         34h liveness-httpget-pod    1/1     Running            1         5m42s ​ #restarts 为 1 重新登陆容器发现index.html又出现了证明容器是被重拉了。[rootk1 prome]# kubectl exec -it liveness-httpget-pod /bin/bash rootliveness-httpget-pod:/# cat /usr/share/nginx/html/index.html在生产环境最好是一块使用尤其是就绪和存活探针共用。 容器的重启策略 Pod 的重启策略 可以通过设置 restartPolicy改变 Pod 的恢复策略。一共有3种1. Always 在任何情况下只要容器不在运行状态就自动重启容器2. OnFailure: 只在容器 异常时才自动重启容器3. Never: 从来不重启容器。 实际使用时需要根据应用运行的特性合理设置这三种恢复策略。 Deployment副本控制器资源详解 如果Pod出现故障对应的服务也会挂掉所以Kubernetes提供了一个Deployment的概念 目的 是让Kubernetes去管理一组Pod的副本也就是副本集这样就能够保证一定数量的副本一直可用 不会因为某一个Pod挂掉导致整个服务挂掉。 Deployment是k8s中最常用的资源对象为ReplicaSet和Pod的创建提供了一种声明式的定义方法 官方建议使用Deployment管理ReplicaSets而不是直接使用ReplicaSets是因为Deployment 还负责在 Pod 定义发生变化时对每个副本进行滚动更新Rolling Update。 每创建一个Deployment控制器都会创建一个对应的ReplicaSet在通过ReplicaSet去创建pod删除 Deployment同时删除对应的ReplicaSet和pod。Deployment 作为一种控制器主要用于管理一组 Pod 的副本。它通过创建和管理 ReplicaSet 来 间接管理 Pod而不是直接管理 Pod 本身。这意味着当你创建一个 Deployment 时Kubernetes 会在后台为你创建一个或多个 ReplicaSet这些 ReplicaSet 确保始终有指定数量的 Pod 复本在运行。主要功能 1.声明式更新机制 定义应用的期望状态如 Pod 的副本数量、容器镜像版本等。Deployment控制器负责确保实际状态 与期望状态一致。 当用户更新 Deployment的Pod模板时k8s会逐步替换旧的ReplicaSet并创建新的ReplicaSet。 2.滚动更新 滚动更新策略允许逐步替换旧版本的 Pod 实例实现应用平滑升级。 通过设置spec.strategy定义更新策略例如 RollingUpdate 或 Recreate。 3.自动回滚 更新过程中出现问题可以自动回滚到前一个稳定的版本,也可以手动选择回滚到特定的修订版本。 4.版本历史记录 Deployment 会保留旧的 ReplicaSet以便进行回滚。可以查看Deployment的修订版本历史记录。 5.金丝雀发布 支持更新过程中的控制如“暂停”或“继续”更新操作。 可以选择在更新过程中暂停观察新版本的行为然后再决定是否继续或回滚。 创建Deployment 使用yaml创建Deployment k8s deployment资源创建流程 1. 用户通过 kubectl 创建 Deployment。 2. Deployment 创建 ReplicaSet。 3. ReplicaSet 创建 Pod。 对象的命名方式是子对象的名字 父对象名字 随机字符串或数字 Deployment是一个定义及管理多副本应用即多个副本 Pod的新一代对象与Replication Controller相比它提供了更加完善的功能使用起来更加简单方便。 apiVersion: apps/v1 # 指定使用的 API 版本 kind: Deployment # 指定这是一个 Deployment 类型的资源 metadata:name: nginx-deployment# 设置 Deployment 的名称labels:app: nginx# 设置标签用于后续选择和管理 spec:replicas: 3# 设置副本数量这里设置为 3 个副本selector:matchLabels:app: nginx# 设置选择器用于匹配由 Deployment 管理的 ReplicaSet 和 Podtemplate:metadata:labels:app: nginx# 设置 Pod 的标签这使得 Deployment 能够通过选择器找到这些 Podspec:containers:- name: nginx# 设置容器名称image: nginx:1.14.2# 设置容器使用的镜像ports:- containerPort: 80# 设置容器监听的端口livenessProbe:httpGet:path: /port: 80initialDelaySeconds: 15periodSeconds: 20# 设置存活探针检查容器是否存活readinessProbe:httpGet:path: /port: 80initialDelaySeconds: 5periodSeconds: 10# 设置就绪探针检查容器是否准备好接收流量 Deployment示例 [rootk1 prome]# vim deployment.yaml apiVersion: apps/v1  #注意版本号 kind: Deployment metadata:name: nginx-deployment spec:selector:  #属性选择器matchLabels:app: nginxreplicas: 2  #管理的副本个数template:  #模板属性metadata: #对pod的描述labels:app: nginxspec:volumes:   #定义共享卷- name: nginx-volemptyDir: {}containers:- name: nginximage: daocloud.io/library/nginxports:- containerPort: 80volumeMounts:  #定义挂载卷- mountPath: /usr/share/nginx/htmlname: nginx-vol 创建Deployment 将上述的YAML文件保存为deployment.yaml然后创建Deployment [rootk1 prome]# kubectl apply -f deployment.yaml deployment.apps/nginx-deployment created ​ 检查Deployment的列表启动之后需要创建时间比较长 通过 kubectl get 命令检查这个 YAML 运行起来的状态 [rootk1 prome]# kubectl get deployments NAME               READY   UP-TO-DATE   AVAILABLE   AGE nginx-deployment   2/2     2            2           2m22s ​ [rootk1 prome]# kubectl get pods -l appnginx NAME                               READY   STATUS   RESTARTS   AGE nginx-deployment-59c4b86474-2llrt   1/1     Running   0         2m51s nginx-deployment-59c4b86474-n2r2m   1/1     Running   0         2m51s ​ 在这里加上了一个 -l 参数即获取所有匹配 app: nginx 标签的 Pod。需要注意的是在命令行中 所有 key-value 格式的参数都使用而非:表示。 ​ 删除Deployment: [rootk1 ~]# kubectl delete deployments nginx-deployment deployment nginx-deployment deleted 或者 [rootk1 ~]# kubectl delete -f  deployment.yaml apiVersion:注意这里apiVersion对应的值是extensions/v1beta1或者apps/v1.这个版本号需要 根据安装的Kubernetes版本和资源类型进行变化记住不是写死的。此值必须在kubectl apiversion中 [rootk1 prome]# kubectl api-versionsapps/v1beta1authentication.k8s.io/v1beta1authorization.k8s.io/v1beta1autoscaling/v1batch/v1certificates.k8s.io/v1alpha1extensions/v1beta1policy/v1beta1rbac.authorization.k8s.io/v1alpha1storage.k8s.io/v1beta1v1 ​ kind:资源类型指定为Deployment。 metadata指定一些meta信息包括名字或标签之类的。每一个 API 对象都有一个叫作 Metadata 的字段这个字段是 API 对象的标识即元数据也是我们从 Kubernetes 里找到这个对象的主要依据。 labels:Labels是最主要的字段,是一组 key-value 格式的标签,k8s中的所有资源都支持携带label, 默认情况下pod的label会复制rc的label k8s使用用户自定义的key-value键值对来区分和标识资源集合就像rc、pod等资源这种键值对 称为label。像 Deployment 这样的控制器对象就可以通过这个 Labels 字段从 Kubernetes 中过滤 出它所关心的被控制对象。 selector:过滤规则的定义是在 Deployment 的spec.selector.matchLabels字段。一般 称之为Label Selector。 pod的label会被用来创建一个selector用来匹配过滤携带这些label的pods。 使用labels定位pods [rootk1 ~]# kubectl get pods -l appnginx -o wide # -l 是 --selector NAME                               READY   STATUS   RESTARTS   AGE   IP           NODE       nginx-deployment-59c4b86474-2llrt   1/1     Running   0         16m   10.244.2.15   kub-k8s-node2   nginx-deployment-59c4b86474-n2r2m   1/1     Running   0         16m   10.244.1.39   kub-k8s-node1   检查你的Pod的IPs [rootk1 ~]# kubectl get pods -l appnginx -o json | grep podIP # JSON格式输出podIP: 10.244.2.15,podIPs: [podIP: 10.244.1.39,podIPs: [ ​spec 一个 k8s 的 API 对象的定义大多可以分为 Metadata 和 Spec 两个部分。前者存放 的是这个对象的元数据对所有 API 对象来说这一部分的字段和格式基本上是一样的而后者存 放的则是属于这个对象独有的定义用来描述它所要表达的功能。 这里定义需要两个副本此处可以设置很多属性主要是受此Deployment影响的Pod的选择器 ​ replicas定义的 Pod 副本个数 (spec.replicas) 2template定义了一个 Pod 模版spec.template这个模版描述了想要创建的 Pod 的细节。 例子里这个 Pod 里只有一个容器这个容器的镜像spec.containers.image是 nginx:latest 这个容器监听端口containerPort是 80。volumes是属于 Pod 对象的一部分。需要修改 template.spec 字段例2中在 Deployment 的 Pod 模板部分添加了一个 volumes 字段定义了这个 Pod 声明 的所有 Volume。它的名字叫作 nginx-vol类型是 emptyDir。  关于emptyDir 类型等同于 Docker 的隐式 Volume 参数即不显式声明宿主机目录的 Volume。 所以Kubernetes 也会在宿主机上创建一个临时目录这个目录将来就会被绑定挂载到容器所声明的Volume 目录上。 k8s 的 emptyDir 类型只是把 k8s 创建的临时目录作为 Volume 的宿主机目录交给了 Docker。 当 Pod 因为某些原因被从节点上删除时emptyDir 卷中的数据也会被永久删除。 ​ volumeMounts:Pod 中的容器使用的是 volumeMounts 字段来声明自己要挂载哪个 Volume 并通过 mountPath 字段来定义容器内的 Volume 目录比如/usr/share/nginx/html。 ​ hostPath:k8s 也提供了显式的 Volume 定义它叫做 hostPath。比如下面的这个 YAML 文件...   volumes:- name: nginx-volhostPath: path: /var/data这样容器 Volume 挂载的宿主机目录就变成了 /var/data ​查看rs ReplicaSet简称 RS是一种工作负载资源它保证某个版本的 Pod 的稳定副本数称为副本即使有 Pod 崩溃或需要更新。ReplicaSet 通常由更高级别的控制器如 Deployment 控制。 [rootk1 ~]# kubectl get rs # 列出所有的 ReplicaSet NAME                         DESIRED   CURRENT   READY   AGE nginx-deployment-59c4b86474   2         2         2     2m49skubectl get rs --selectorappnginx -n default 创建Service Kubernetes 中的服务Service是一种抽象概念它定义了 Pod 的逻辑集和访问 Pod 的协议。  Service 使从属 Pod 之间的松耦合成为可能。 和所有 Kubernetes 对象清单一样, Service 用  YAML 或者 JSON 来定义。 Service 下的一组 Pod 通常由一个 标签选择算符 来标记  Service 允许 Pod中唯一的IP地址公开到集群外部以pod中的应用能够接收流量。 设置Service的spec中的type你可以用不同的方式公开 Service 暴露服务的五种方式 1ClusterIP默认 - 在集群的内部 IP 上公开 Service。这种类型使得 Service 只能从集群内访问。此类型会提供一个集群内部的虚拟IP与Pod不在同一网段)以供集群内部的pod之间通信使用。ClusterIP也是Kubernetes service的默认类型。 能够让其所属Pod能够负载均衡且需要有一个虚拟IPVIP提供给IPtables。由于VIP没有挂接到网络设备所以不能直接访问。 2NodePort  外网client---nodeIPnodePort---podIPPodPort - 使用 NAT 在集群中每个选定 Node 的相同端口上公开 Service 为每个节点暴露一个端口通过nodeip nodeport可以访问这个服务同时服务依然会有cluster类型的ipport。内部通过clusterip方式访问外部通过nodeport方式访问。是 ClusterIP 的超集。 缺点1每个端口只能是一种服务2端口范围只能是 30000-32767k8s规定。 使用场景demo应用或临时应用上使用这种方式。生产环境上不推荐使用 3LoadBalancer  - 在当前云中创建一个外部负载均衡器如果支持的话并为 Service 分配一个固定的外部IP。是 NodePort 的超集。LoadBalancer在NodePort基础上K8S可以请求底层云平台创建一个负载均衡器将每个Node作为后端进行服务分发。 缺点每一个用LoadBalancer暴露的服务都需要付费 4ExternalName  - 将 Service 映射到 externalName 字段的内容例如 foo.bar.example.com通过返回带有该名称的 CNAME 记录实现。不设置任何类型的代理。这种类型需要 kube-dns 的 v1.7 或更高版本或者 CoreDNS 的 0.8 或更高版本。 使用场景Kubernetes集群内部调用外部服务。如DB、没迁移到Kubernetes上的应用。使用ExternalName面向的场景大多是临时调用建议使用完后删除或恢复为原配置 5Ingressenvoy Ingress 并不是 Service 的类型但可以充当集群的入口点。可以将路由规则整合到一个资源中并扮演“智能路由”的角色。ngress是一种HTTP方式的路由转发机制为K8S服务配置HTTP负载均衡器通常会将服务暴露给K8S群集外的客户端。支持 SSL、认证等功能。需要使用同一个 IP 暴露多个服务。支持 HTTP/HTTPS 协议和服务发现。可以使用不同的 Ingress 控制器如 Nginx、Traefik、Istio 等。 实验 ​工作原理 service对外提供请求当访问service的时候并将请求转发到集群中的pod中。此过程是通过endpoint 与selector实现的。selector用于选择带有某个标签的pod然后将该pod的ip和端口添加到endpoint 中。当访问service时就会从endpoint中选择对应的pod的ip和端口然后将请求转发到对应的pod中。 具体请求如何转发过去需要kube-proxy实现。 ​三台安装iptables [rootk1 prome]# yum install -y iptables iptables-services 1.创建一个depl [rootk1 prome]# kubectl delete -f deployment.yaml [rootk1 prome]# vim nginx-depl.yml apiVersion: apps/v1 kind: Deployment metadata:name: dep01 spec:selector:matchLabels:app: webreplicas: 2template:metadata:labels:app: webspec:containers:- name: testnginx9image: daocloud.io/library/nginxports:- containerPort: 80 [rootk1 prome]# kubectl apply -f nginx-depl.yml 2. 创建service并且以nodePort的方式暴露端口给外网 [rootk1 prome]# vim nginx_svc.yaml apiVersion: v1 kind: Service metadata:name: mysvc spec:type: NodePort  #类型ports:- port: 8080nodePort: 30001targetPort: 80selector:   #选择器app: web   [rootk1 prome]# kubectl apply -f nginx_svc.yaml ​ 3.查看 [rootk1 prome]# kubectl get svc NAME         TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE kubernetes   ClusterIP   10.96.0.1       none        443/TCP         5d18h mysvc       NodePort    10.100.166.208   none        8080:30001/TCP   21s ​ 4.查看service的详细信息 [rootk1 prome]# kubectl describe svc mysvc Name:             mysvc ...... Port:             unset  80/TCP TargetPort:        80/TCP Endpoints:         10.244.84.130:80,10.244.84.131:80 Session Affinity: None Events:           none 5.当创建好svc之后k8s会默认给创建一个和svc名字一样的endpoints [rootk1 prome]# kubectl get ep mysvc NAME         ENDPOINTS                           AGE mysvc   10.244.84.130:80,10.244.84.131:80       7m15s NodePort端口详解 安装iptables(但是需要关闭iptables)创建service之后k8s会自动添加规则到Iptables里面而且会生效(虽然iptables处于关闭状态)。 服务中的3个端口设置 这几个port的概念很容易混淆比如创建如下service apiVersion: v1 kind: Service metadata:name: mysvc spec:type: NodePortports:- port: 8080nodePort: 30001targetPort: 80selector:app: web port - service暴露在cluster ip上的端口cluster ip:port 是给集群内部客户访问 service的入口。 nodePort - nodePort是kubernetes提供给集群外部客户访问service入口的方式。nodePort端口范围是从30000到32767 targetPort - pod上的端口从port和nodePort上到来的数据最终经过kube-proxy流入到后端pod的targetPort 上进入容器。 ​ port、nodePort总结 总的来说port和nodePort都是service的端口前者暴露给集群内客户访问服务后者暴露给集 群外客户访问服务。从这两个端口到来的数据都需要经过反向代理kube-proxy流入后端pod的 targetPort从而到达pod上的容器内。 kube-proxy反向代理 kube-proxy支持的三种工作模式 1.userspace 模式 实现简单但性能较低适用于早期的测试和开发环境。 可以直接看kube-proxy访问日志/var/log/kube-proxy (1).kube-proxy 监听 Kubernetes API 服务器中 Service 和 Endpoint 的变化。 (2)当有新的 Service 创建时kube-proxy 会在节点上打开一个端口并将这个端口映射到 Service 对应的后端 Pod。 (3).任何对这个端口的访问请求都会被 kube-proxy 捕捉并转发到后端的 Pod。kube-proxy 使 用用户空间程序来进行这些转发操作。 2.iptables 模式 (1).kube-proxy 同样监听 Kubernetes API 服务器中 Service 和 Endpoint 的变化。 不同的是kube-proxy 使用 iptables 来设置网络规则。这些规则会直接在内核空间进行处理而 不是通过用户空间。 (2).当有新的 Service 创建时kube-proxy 会生成相应的 iptables 规则定义从 Service IP 和端口到后端 Pod 的 NAT 转发规则。 (3).数据包在内核空间直接被转发到相应的后端 Pod减少了上下文切换提高了转发性能。 性能较好适用于大多数生产环境但在处理大量规则时可能复杂。 iptables使用数组遍历方式处理规则当服务增加到1000, 效率比用hash表处理规则的ipvs差了。 3.ipvs 模式 流量转发流程和iptables 模式相似 (1).kube-proxy 监听 Kubernetes API 服务器中 Service 和 Endpoint 的变化 (2).kube-proxy 使用 IPVS 来创建和维护负载均衡规则。IPVS 是内核中的一个模块专门用于负载均衡支持多种调度算法。 (3).当有新的 Service 创建时kube-proxy 会使用 IPVS 创建相应的负载均衡规则定义从 Service IP 和端口到后端 Pod 的转发规则。 (4).数据包在内核空间通过 IPVS 直接转发性能更高同时支持更多的负载均衡算法如轮询、 最小连接数、最短延迟等。 基于netfilter钩子函数实现类似iptables功能但使用hash表作为底层数据结构来查找路由规则 性能最佳支持更多的负载均衡算法和规则适用于高性能和大规模集群 需要高版本内核低版本内核没有ipvs模块这个时候如果设置ipvs模式kube-proxy会自动降级到 iptables模式。 iptables与ipvsadm 当service有了port和nodePort之后就可以对内/外提供服务。 因为kube-proxy在本地node上创建的iptables规则。 ​ Kube-Proxy 通过配置 DNAT 规则从容器出来的访问从本地主机出来的访问两方面将到 这个服务地址的访问映射到本地的kube-proxy端口随机端口。然后 Kube-Proxy 会监听在 本地的对应端口将到这个端口的访问给代理到远端真实的 pod 地址上去,同时生成lvs的负载规则 ​不管是通过集群内部服务入口cluster ip:port还是通过集群外部服务入口node ip:nodePort 的请求都将重定向到本地kube-proxy端口随机端口的映射然后将到这个kube-proxy端口的访问 给代理到远端真实的 pod 地址上去。在通过lvs实现负载 ​ 查看负载规则 [rootk1 prome]# ipvsadm -Ln    如果没有规则 [rootk1 ~]# kubectl edit cm kube-proxy -n kube-system 搜索mode: 添加ipvs 然后将所有的kube-proxy的pod删除等待重新创建即可​ 注意:自k8s1.1以后,service默认使用ipvs规则若ipvs没有被激活则降级使用iptables规则. RC资源 Replication Controller(简称rc)用来管理Pod的副本保证集群中存在指定数量的Pod副本。 集群中副本的数量大于指定数量则会停止指定数量之外的多余容器数量反之则会启动少于指定数 量个数的容器保证数量不变。Replication Controller是实现弹性伸缩、动态扩容和滚动升级的核心。 RC 的主要功能点 确保pod数量指定某个服务在Kubernetes中有相应数量的Pod在运行 确保pod健康当pod不健康运行出错或者无法提供服务时会杀死不健康pod并重新创建 保持pod数量一致 弹性伸缩当业务高峰期的时候可以设置扩增pod数量配合监控就可以做自动伸缩了 滚动升级即蓝绿发布当一个pod使用的镜像更新采用滚动升级模式RC会自动一个个pod进行升级 关闭一个pod的同时进行升级且在原镜像基础上创建一个新pod当一个pod更新完成再关闭一个旧镜像pod。 使用yaml创建并启动replicas集合 Replication Controller会确保pod的数量在运行的时候会一直保持在一个特殊的数字 即replicas的设置。 [rootk1 ~]# cd prome/ [rootk1 prome]# vim nginx-rc.yml --- apiVersion: v1 kind: ReplicationController metadata:name: my-nginx spec:replicas: 2template:metadata:labels:app: nginxspec:containers:- name: nginximage: daocloud.io/library/nginxports:- containerPort: 80 如果你在删除rc之前尝试删除podrc将会立即启动新的pod来替换被删除的pod 完整TOMCAT实例 Java Web应用 注Tomcat有可能无法正常启动原因是虚机的内存和CPU设置过小请酌情调大 下载镜像 [rootk1 ~]# docker pull daocloud.io/library/tomcat 构建Tomcat RC定义文件 [rootk1 prome]# vim myweb.rc.yml --- apiVersion: v1 kind: ReplicationController metadata:name: myweb spec:replicas: 2selector:app: mywebtemplate:metadata:labels:app: mywebspec:containers:- name: mywebimage: daocloud.io/library/tomcat:8ports:- containerPort: 8080   #在8080端口上启动容器进程PodIP与容器端口组成Endpoint代表着一个服务进程对外通信的地址 发布到Kubernetes集群 创建RC [rootk1 prome]# kubectl apply -f myweb.rc.yml replicationcontroller/myweb created 查看RC [rootk1 prome]# kubectl get rc NAME       DESIRED   CURRENT   READY   AGE myweb      1         1         1       20s 查看Pod [rootk1 prome]# kubectl get pods NAME                               READY   STATUS             RESTARTS   AGE myweb-shjfn                         1/1     Running            0         52s 构建Tomcat Kubernetes Service定义文件 [rootk1 prome]# vim myweb-svc.yaml apiVersion: v1 kind: Service metadata: name: myweb spec:type: NodePortports:- port: 8081nodePort: 30009targetPort: 8080selector:app: myweb 创建 [rootk1 prome]# kubectl apply -f myweb-svc.yaml service/myweb created 查看SVC [rootk1 prome]# kubectl get svc NAME         TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE kubernetes   ClusterIP   10.96.0.1       none        443/TCP         5d22h mysvc       NodePort    10.110.160.108   none        8080:30001/TCP   3h37m myweb       NodePort    10.96.19.61     none        8081:30009/TCP   33s 运行 浏览器中输入http://虚拟机IP:30009即可呈现如下内容 注意在节点node中访问不是master [rootk1 ~]# curl 192.168.246.166:30009 控制器模式解析 k8s项目通过一个称作控制器模式controller pattern的设计方法来统一地实现对各种不同 的对象或者资源进行的编排操作。k8s核心就是用一个东西去控制另一个东西所有的内容都是被控制的。 容器镜像虽然好用但是容器这样一个沙盒的概念对于描述应用来说太过简单。好比集装箱固然好用 如果它四面都光秃秃的吊车还怎么把这个集装箱吊起来并摆放好呢 ​所以Pod 对象其实就是容器的升级版。它对容器进行了组合添加了更多的属性和字段。这就好比 给集装箱四面安装了吊环使得 Kubernetes 这架吊车可以更轻松地操作它。 ​而 k8s 操作这些集装箱的逻辑都由控制器Controller完成 回顾 Deployment 这个最基本的控制器对象。之前讲过一个 nginx-deployment 的例子 例1 apiVersion: apps/v1 kind: Deployment metadata:name: nginx-deployment spec:selector:matchLabels:app: nginxreplicas: 2template:metadata:labels:app: nginxspec:containers:- name: nginximage: nginx:1.7.9ports:- containerPort: 80 这个 Deployment 定义的编排动作为 确保携带了 appnginx 标签的 Pod 的个数永远等于 spec.replicas 指定的个数即 2 个。 如果在这个集群中携带 appnginx 标签的 Pod 的个数大于 2 的时候就会有旧的 Pod 被删除 反之就会有新的 Pod 被创建。 究竟是 Kubernetes 项目中的哪个组件在执行这些操作呢 kube-controller-manager 组件 这个组件就是一系列控制器的集合 所有控制器 deployment             job                   podautoscaler           cloud                 disruption             namespace               replicaset             serviceaccount         volume cronjob               garbagecollector       nodelifecycle replication           statefulset           daemonset 上面的每一个控制器都以独有的方式负责某种编排功能。而Deployment正是这些控制器中的一种。 而被控制对象的定义则来自于一个模板。比如Deployment 里的 template 字段。所有被这个Deployment 管理的 Pod 实例都是根据这个 template 字段的内容创建出来的。 对 Deployment 以及其他类似的控制器做一个总结 如图类似 Deployment 的一个控制器都是由两部分组成 上半部分的控制器定义包括期望状态 下半部分的被控制对象的模板组成的。 也正是在这个统一的编排框架下不同的控制器可以在具体执行过程中设计不同的业务逻辑从而达到不同的编排效果。这个实现思路正是 k8s 进行容器编排的核心原理。 水平扩展/收缩与滚动更新 水平扩展/收缩 在Kubernetes中水平扩展的方法通常是通过添加或删除节点来实现的。启动新的Pod时Kubernetes会自动将应用程序负载均衡到新Pod上以提高群集的处理能力从而实现水平扩展。 手动缩放 手动缩放 StatefulSet kubectl scale statefulset my-app-statefulset --replicas5 kubectl scale命令扩缩容 kubectl scale deployment deployment-name --replicasnumber yaml配置扩缩容 [rootk1 prome]# kubectl get deploy NAME               READY   UP-TO-DATE   AVAILABLE   AGE dep01              2/2     2            2           4h41m nginx-deployment   2/2     2            2           5h13m ​ 我们将dep01的副本数量变成4个现在2个 [rootk1 prome]# vim deployment.yaml #修改如下内容 将replicas: 2 修改为 replicas: 4 创建上节的nginx-deployment [rootk1 prome]# kubectl apply -f deployment.yaml --record deployment.apps/nginx-deployment configured ​ --record kubectl apply 每次更新应用时 Kubernetes 都会记录下当前的配置保存为一个 revision版次这样就可以回滚到某个特定 revision。 检查nginx-deployment 创建后的状态信息 [rootk1 prome]# kubectl get deploy NAME               READY   UP-TO-DATE   AVAILABLE   AGE dep01              4/4     4            4           4h53m nginx-deployment   2/2     2            2           5h25m ​ 返回结果中四个状态字段含义 DESIRED 如果有就表示用户期望的 Pod 副本个数spec.replicas 的值 CURRENT 当前处于 Running 状态的 Pod 的个数 UP-TO-DATE 当前处于最新版本的 Pod 的个数所谓最新版本指的是 Pod 的 Spec 部分与 Deployment 里 Pod 模板里定义的完全一致 AVAILABLE 当前已经可用的 Pod 的个数即既是 Running 状态又是最新版本并且已经处于 Ready 健康检查正确状态的 Pod 的个数。只有这个字段描述的才是用户所期望的最终状态。 收缩Deployment [rootk1 prome]# kubectl get deploy NAME               READY   UP-TO-DATE   AVAILABLE   AGE dep01              4/4     4            4           4h59m nginx-deployment   2/2     2            2           5h32m ​ 将dep01的副本将4变为3个 [rootk1 prome]# kubectl edit deployment/dep01 ​ # reopened with the relevant failures. # apiVersion: apps/v1 ... spec:progressDeadlineSeconds: 600replicas: 3   #将这里原来的4改为3revisionHistoryLimit: 10selector:matchLabels: ... 保存退出vim的方式 [rootk1 prome]# kubectl edit deployment/dep01 deployment.apps/dep01 edited [rootk1 prome]# kubectl get deploy NAME               READY   UP-TO-DATE   AVAILABLE   AGE dep01              3/3     3            3           5h16m nginx-deployment   2/2     2            2           5h48m 自动缩放 Deployment 定义了一个自动扩展 Deployment 的 HorizontalPodAutoscaler 对象 my-app-hpa。它指定了要管理的 Deployment 对象的名称 my-app-deployment以及自动扩展的最小和最大副本数。 apiVersion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata:name: my-app-hpa spec:scaleTargetRef:apiVersion: apps/v1kind: Deploymentname: my-app-deploymentminReplicas: 3maxReplicas: 10targetCPUUtilizationPercentage: 50 滚动更新 将一个集群中正在运行的多个 Pod 版本交替地逐一升级的过程就是滚动更新。 命令 # 创建或更新Deployment kubectl apply -f deployment-file.yaml # 触发滚动更新例如更新容器镜像 kubectl set image deployment/deployment-name container-namenew-image:tag # 实现在线更新 kubectl edit deployment xxx # 监控滚动更新的状态 kubectl rollout status deployment/deployment-name # 如果需要回滚到旧版本 kubectl rollout undo deployment/deployment-name 2种更新升级策略   1、Recreate 重建更新 这种更新策略会杀掉所有正在运行的pod再重新创建的pod 在 Deployment 的 YAML 文件中设置 spec.strategy.type 为 Recreate apiVersion: apps/v1 kind: Deployment metadata:name: example-deployment spec:strategy:type: Recreate 2、rollingUpdate 滚动更新这种更新策略deployment会以滚动更新的方式来逐个更新pod 配置参数 maxUnavailable 和 maxSurge 来控制更新过程中的最大不可用 Pod 副本数和超过期望副 本数的最大数量。 apiVersion: apps/v1 kind: Deployment metadata:name: example-deployment spec:strategy:type: RollingUpdaterollingUpdate:maxUnavailable: 1 # 或者 25% 表示最大不可用 Pod 的比例maxSurge: 1 # 或者 25% 表示超过期望副本数的最大数量 版本升级 创建一个新的deploy [rootk1 prome]# cp nginx-depl.yml nginx-depl02.yml [rootk1 prome]# vim nginx-depl02.yml apiVersion: apps/v1 kind: Deployment metadata:name: dep02 #注意修改 spec:selector:matchLabels:app: web1replicas: 2template:metadata:name: testnginx9labels:app: web1spec:containers:- name: testnginx9image: daocloud.io/library/nginx:1.14 #注意修改ports:- containerPort: 80strategy:type: RollingUpdaterollingUpdate:maxUnavailable: 1maxSurge: 1 [rootk1 prome]# kubectl apply -f nginx-depl02.yml deployment.apps/dep02 created [rootk1 prome]# kubectl get pods NAME                               READY   STATUS   RESTARTS   AGE dep01-58f6d4d4cb-997jw              1/1     Running   0         16m dep01-58f6d4d4cb-g6vtg              1/1     Running   0         5h32m dep01-58f6d4d4cb-k6z47              1/1     Running   0         5h32m dep02-78dbd944fc-47czr              1/1     Running   0         44s dep02-78dbd944fc-4snsj              1/1     Running   0         25s ​ 将nginx的版本从1.14升级到1.16 [rootk1 prome]# kubectl edit deployment/dep02 # Please edit the object below. Lines beginning with a # will be ignored, # and an empty file will abort the edit. If an error occurs while saving this file will be ... spec:containers:- image: daocloud.io/library/nginx:1.16  #将这里原来的nginx:1.14修改为nginx:1.16imagePullPolicy: Alwaysname: testnginx9ports:- containerPort: 80 ... 保存退出vim的方式 [rootk1 prome]# kubectl edit deployment/dep02 deployment.apps/dep01 edited 这时可以通过查看 Deployment 的 Events看到这个滚动更新的流程 [rootkub-k8s-master prome]# kubectl describe deployment dep02 ... Events:Type   Reason             Age   From                   Message----    ------             ----  ----                   -------Normal ScalingReplicaSet 50s   deployment-controller Scaled up replica set dep02-846bf8775b to 2Normal ScalingReplicaSet 9s   deployment-controller Scaled up replica set dep02-58f8d5678 to 1Normal ScalingReplicaSet 8s   deployment-controller Scaled down replica set dep02-846bf8775b to 1Normal ScalingReplicaSet 8s   deployment-controller Scaled up replica set dep02-58f8d5678 to 2Normal ScalingReplicaSet 5s   deployment-controller Scaled down replica set dep02-846bf8775b to 0 如此交替进行新 ReplicaSet 管理的 Pod 副本数从0个变成1个再变成2个最后变成3个。 而旧的 ReplicaSet 管理的 Pod 副本数则从3个变成2个再变成1个最后变成0个。这样就完成了这一组Pod 的版本升级过程。 验证 [rootk1 prome]# kubectl get pods NAME                               READY   STATUS   RESTARTS   AGE dep02-78dbd944fc-69t8x              1/1     Running   0         11h dep02-78dbd944fc-7cn86              1/1     Running   0         11h [rootk1 prome]# kubectl exec -it dep02-78dbd944fc-69t8x -- /bin/bash rootdep02-78dbd944fc-69t8x:/# nginx -v nginx version: nginx/1.16.1 rootdep02-78dbd944fc-69t8x:/# exit 滚动更新的好处 在升级刚开始的时候集群里只有 1 个新版本的 Pod。如果这时新版本 Pod 有问题启动不起来 那么滚动更新就会停止从而允许开发和运维人员介入。而在这个过程中由于应用本身还有两个 旧版本的 Pod 在线所以服务并不会受到太大的影响。 版本回滚 # 查看发布历史记录 kubectl rollout history deployment deployment-name # 如果需要回滚到上一个版本 kubectl rollout undo deployment deployment-name # 或者回滚到指定版本例如修订版本3 kubectl rollout undo deployment deployment-name --to-revision3 # 验证回滚状态 kubectl rollout status deployment deployment-name # 查看详细的回滚信息 kubectl describe deployment deployment-name# 创建Deployment并记录更改 kubectl create deployment deployment-name --imageimage-name --record # 更新Deployment并记录更改 kubectl set image deployment deployment-name containernew-image:tag --record 查看版本历史 [rootk1 prome]# kubectl rollout history deployment/dep02 deployment.apps/dep02 REVISION CHANGE-CAUSE 1         none 2         none 回滚到以前的旧版本 ​ 把整个 Deployment 回滚到上一个版本[rootk1 prome]# kubectl rollout undo deployment/dep02 deployment.apps/dep02 rolled back 查看回滚状态 [rootk1 prome]# kubectl rollout status deployment/dep02 deployment dep02 successfully rolled out 验证 [rootk1 prome]# kubectl get pods NAME                               READY   STATUS             RESTARTS   AGE dep02-8594cd6447-pqtxk              1/1     Running            0         55s dep02-8594cd6447-tt4h4              1/1     Running            0         51s [rootk1 prome]# kubectl exec -it dep02-8594cd6447-tt4h4 /bin/bash rootdep02-8594cd6447-tt4h4:/# nginx -v nginx version: nginx/1.14.2 回滚到更早之前的版本: 使用 kubectl rollout history 命令查看每次 Deployment 变更对应的版本。 [rootk1 prome]# kubectl rollout history deployment/dep02 deployment.apps/dep02 REVISION CHANGE-CAUSE 2         none 3         none ​ 默认配置下Kubernetes只会保留最近10个revision。 在Deployment配置文件中通过 spec.revisionHistoryLimit属性增加revision数量。如 spec:revisionHistoryLimit: 15由于在创建这个 Deployment 的时候指定了--record 参数会将创建这些版本时执行的 kubectl 时文件中的配置都会记录下来。 ​ 查看每个版本对应的 Deployment 的 API 对象的细节 [rootk1 prome]# kubectl rollout history deployment/dep02 --revision3 deployment.apps/dep02 with revision #3 Pod Template:Labels: appweb1pod-template-hash8594cd6447Containers:testnginx9:Image: daocloud.io/library/nginx:1.14Port: 80/TCPHost Port: 0/TCPEnvironment: noneMounts: noneVolumes: none 2.在 kubectl rollout undo 命令行最后加上要回滚到的指定版本号就可以回滚到指定版本了。 [rootk1 prome]# kubectl rollout undo deployment/dep02 --to-revision2 deployment.apps/dep02 rolled back 验证 [rootk1 prome]# kubectl get pods NAME READY STATUS RESTARTS AGE dep02-78dbd944fc-8nvxl 1/1 Running 0 86s dep02-78dbd944fc-sb9sj 1/1 Running 0 88s [rootkub-k8s-master prome]# kubectl exec -it dep02-78dbd944fc-8nvxl /bin/bash rootdep02-78dbd944fc-8nvxl:/# nginx -v nginx version: nginx/1.16.1 Ingress服务接入控制器 ingress官方:Installation Guide - Ingress-Nginx Controller/ 要理解ingress需要区分两个概念ingress和ingress-controller ​ ingress对象 指的是k8s中的一个api对象一般用yaml配置。作用是定义请求如何转发到service的规则可以理解为配置模板。 ​ ingress-controller 具体实现反向代理及负载均衡的程序对ingress定义的规则进行解析根据配置的规则来实现请求转发。 ​简单来说ingress-controller才是负责具体转发的组件通过各种方式将它暴露在集群入口外部对集群的请求流量会先到ingress-controller而ingress对象是用来告诉ingress-controller该如何转发请求比如哪些域名哪些path要转发到哪些服务等等。 service 的表现形式为IP:PORT即工作在第四层传输层TCP/IP层对于不同的URL地址经常应用不同的后端服务或者虚拟服务器这些应用层的转发机制仅通过kubernetes的service机制是无法实现的这种情况我么可以使用ingress策略定义和一个具体的ingress Controller. ​Ingress提供七层负载均衡能力可以通过 Ingress 配置提供外部可访问的 URL、负载均衡、SSL、基于名称的虚拟主机等。作为集群流量接入层Ingress 的高可靠性显得尤为重要。 ingress工作原理 基于nginx七层反向代理来实现负载均衡ingress工作原理如下图 外部客户端通过访问负载均衡器然后调度到service上然后在调度到IngressControllerIngressController通过Ingress规则域名或虚拟主机访问到后端pod而在Ingress规则当中对应的主机是由service分组来设定的可以看到上面的service1是用来对外提供服务的而下面的service2仅仅是用来分pod组的。pod处理完请求返回服务是原路返回不直接返回。 Kubernetes 并没有自带 Ingress Controller实际上ingress-controller只是一个统称具体实现有多种需要自己单独安装目前由k8s维护的ingress-controller只有google云的GCE与ingress-nginx两个常用的是 Ingress-nginx Controller.Ingress 一般由三个组件组成 1. Nginx 反向代理负载均衡器 2. Ingress Controller 可以理解为控制器它通过不断的跟 Kubernetes API 交互实时获取后端 Service、Pod 等的变化比如新增、删除等然后结合 Ingress 定义的规则生成配置然后动态更新上边的 Nginx 负载均衡器并刷新使配置生效来达到服务自动发现的作用。 3. Ingress 定义规则通过定义某个域名的请求过来之后转发到集群中指定的 Service。通过 Yaml 文件定义给一个或多个 Service 定义一个或多个 Ingress 规则。 如何创建 Ingress 资源 Ingress 中的spec字段是Ingress资源的核心组成部分主要包含以下3个字段 rules用于定义当前Ingress资源的转发规则列表由rules定义规则或没有匹配到规则时所有的流量会转发到由backend定义的默认后端。backend默认的后端是Service 和端口名称的组合。定义Ingress资源时必须要定义backend或rules两者之一该字段用于让负载均衡器指定一个全局默认的后端。tlsTLS配置目前仅支持通过默认端口443提供服务如果要配置指定的列表成员指向不同的主机则需要通过SNI TLS扩展机制来支持该功能。 部署 Ingress 控制器 下载 ingress controller ​wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.3.0/deploy/static/provider/cloud/deploy.yaml 如果下载不下来记得本机解析github地址 [rootk1 ~]# cat /etc/hosts 127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.116.138 master 192.168.116.130 node1 192.168.116.131 node2 199.232.28.133 raw.githubusercontent.com Ingress-Nginx GitHub地址 https://github.com/kubernetes/ingress-nginx[rootk1 mnt]# wget https://github.com/kubernetes/ingress-nginx/archive/refs/tags/controller-v1.3.0.zip   #下载压缩包 [rootk1 mnt]# unzip ingress-nginx-controller-v1.3.0.zip [rootk1 mnt]# cd ingress-nginx-controller-v1.3.0/deploy/static/provider/cloud/ [rootk1 cloud]# vim deploy.yaml 1、下载配置ingress controller [rootk1 ~]# cd /mnt/ [rootk1 mnt]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.3.0/deploy/static/provider/cloud/deploy.yaml [rootk1 mnt]# cp deploy.yaml /root/ [rootk1 mnt]# cd [rootk1 ~]# vim deploy.yaml #修改配置文件并替换成阿里云的镜像 找到以下apiserver的版本 --- apiVersion: apps/v1 kind: DaemonSet #将原来的Deployment修改为DaemonSet metadata:labels:app.kubernetes.io/component: controllerapp.kubernetes.io/instance: ingress-nginxapp.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxapp.kubernetes.io/version: 1.3.0name: ingress-nginx-controllernamespace: ingress-nginx spec:minReadySeconds: 0revisionHistoryLimit: 10selector:matchLabels:app.kubernetes.io/component: controllerapp.kubernetes.io/instance: ingress-nginxapp.kubernetes.io/name: ingress-nginxtemplate:metadata:labels:app.kubernetes.io/component: controllerapp.kubernetes.io/instance: ingress-nginxapp.kubernetes.io/name: ingress-nginxspec:hostNetwork: true #添加共享到主机网络containers:- args:- /nginx-ingress-controller- --publish-service$(POD_NAMESPACE)/ingress-nginx-controller- --election-idingress-controller-leader- --controller-classk8s.io/ingress-nginx- --ingress-classnginx- --configmap$(POD_NAMESPACE)/ingress-nginx-controller- --validating-webhook:8443- --validating-webhook-certificate/usr/local/certificates/cert- --validating-webhook-key/usr/local/certificates/keyenv:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.name- name: POD_NAMESPACEvalueFrom:fieldRef:fieldPath: metadata.namespace- name: LD_PRELOADvalue: /usr/local/lib/libmimalloc.soimage: registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.3.0sha256:d1707ca76d3b044ab8a28277a2466a02100ee9f58a86af1535a3edf9323ea1b5 #将原来的镜像替换成阿里云仓库的镜像imagePullPolicy: IfNotPresentlifecycle:preStop:exec:command:- /wait-shutdownlivenessProbe:failureThreshold: 5httpGet:path: /healthzport: 10254scheme: HTTPinitialDelaySeconds: 10periodSeconds: 10successThreshold: 1timeoutSeconds: 1name: controllerports:- containerPort: 80name: httpprotocol: TCP- containerPort: 443name: httpsprotocol: TCP- containerPort: 8443name: webhookprotocol: TCPreadinessProbe:failureThreshold: 3httpGet:path: /healthzport: 10254scheme: HTTPinitialDelaySeconds: 10periodSeconds: 10successThreshold: 1timeoutSeconds: 1resources:requests:cpu: 100mmemory: 90MisecurityContext:allowPrivilegeEscalation: truecapabilities:add:- NET_BIND_SERVICEdrop:- ALLrunAsUser: 101volumeMounts:- mountPath: /usr/local/certificates/name: webhook-certreadOnly: truednsPolicy: ClusterFirstnodeSelector:custom/ingress-controller-ready: true #指定运行ingress的node标签serviceAccountName: ingress-nginxterminationGracePeriodSeconds: 300volumes:- name: webhook-certsecret:secretName: ingress-nginx-admission --- ​ #注意:一共有两个镜像需要替换成阿里云仓库的镜像: [rootk1 ~]# cat deploy.yaml | grep imageimage: registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.3.0sha256:d1707ca76d3b044ab8a28277a2466a02100ee9f58a86af1535a3edf9323ea1b5imagePullPolicy: IfNotPresentimage: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.1.1sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660imagePullPolicy: IfNotPresentimage: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.1.1sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660imagePullPolicy: IfNotPresent 需要修改的地方 kind: DaemonSet 官方原始文件使用的是deploymentreplicate 为 1这样将会在某一台节点上启动对应的nginx-ingress-controller pod。外部流量访问至该节点由该节点负载分担至内部的service。测试环境考虑防止单点故障改为DaemonSet然后删掉replicate 配合亲和性部署在制定节点上启动nginx-ingress-controller pod确保有多个节点启动nginx-ingress-controller pod后续将这些节点加入到外部硬件负载均衡组实现高可用性。 hostNetwork: true 添加该字段暴露nginx-ingress-controller pod的服务端口80 nodeSelector: 增加亲和性部署有custom/ingress-controller-ready 标签的节点才会部署该DaemonSet 为需要部署nginx-ingress-controller的节点设置lable 给两个node节点设置label [rootk1 ~]# kubectl label nodes k8s-node1 custom/ingress-controller-readytrue [rootk1 ~]# kubectl label nodes k8s-node2 custom/ingress-controller-readytrue 同时在两个node节点下载镜像 [rootk8s-node1 ~]# docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.3.0 [rootk8s-node1 ~]# docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.1.1 创建ingress-controller [rootk8s-master ~]# kubectl apply -f deploy.yaml ​ ​ 查看ingress-controller资源 [rootk8s-master ~]# kubectl get pods -n ingress-nginx NAME                             READY   STATUS   RESTARTS   AGE nginx-ingress-controller-s8vnl   1/1     Running   0         98m nginx-ingress-controller-ztxz4   1/1     Running   0         97m 测试ingress 创建两个应用和service [rootk1 ~]# vim my-apache.yaml apiVersion: apps/v1 kind: Deployment metadata:name: my-apache spec:selector:matchLabels:run: my-apachereplicas: 2template:metadata:labels:run: my-apachespec:containers:- name: my-apacheimage: daocloud.io/library/httpd:2.4ports:- containerPort: 80 --- apiVersion: v1 kind: Service metadata:name: my-apachelabels:run: my-apache spec:#type: NodePortports:- port: 80targetPort: 80#nodePort: 30002selector:run: my-apache[rootk1 ~]# vim my-nginx.yaml apiVersion: apps/v1 kind: Deployment metadata:name: my-nginx spec:selector:matchLabels:run: my-nginxreplicas: 2template:metadata:labels:run: my-nginxspec:containers:- name: my-nginximage: daocloud.io/library/nginx:1.7.9ports:- containerPort: 80 --- apiVersion: v1 kind: Service metadata:name: my-nginxlabels:run: my-nginx spec:#type: NodePortports:- port: 80targetPort: 80#nodePort: 30001selector:run: my-nginx 创建pod和service [rootk1 ~]# kubectl apply -f my-apache.yaml [rootk1 ~]# kubectl apply -f my-nginx.yaml ​ 查看资源 [rootk1 ~]# kubectl get pods NAME                       READY   STATUS   RESTARTS   AGE my-apache-d49c8b95c-8z8l9   1/1     Running   0         125m my-apache-d49c8b95c-d9q5s   1/1     Running   0         125m my-nginx-5fdc96f9b4-bmf6s   1/1     Running   0         124m my-nginx-5fdc96f9b4-qfw8c   1/1     Running   0         124m [rootk1 ~]# kubectl get svc NAME         TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)       AGE kubernetes   ClusterIP   10.96.0.1       none       443/TCP       20d my-apache   NodePort   10.99.178.186   none       80/TCP   125m my-nginx     NodePort   10.97.171.188   none       80/TCP   124m 配置ingress转发文件 [rootk8s-master ~]# cat ingress-test.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata:name: test-ingressnamespace: defaultannotations:nginx.ingress.kubernetes.io/rewrite-target: / spec:ingressClassName: nginx #指定ingress的类型rules: #定义转发规则- host: test.apache.ingress #指定域名方式http:paths:- path: / #指定访问的路径pathType: Prefix #定义路径的类型backend:   #定义转发后端的服务service: #定义转发的servicename: my-apacheport:number: 80- host: test.nginx.ingresshttp:paths:- path: /pathType: Prefixbackend:service:name: my-nginxport:number: 80[rootk8s-master ~]# kubectl apply -f ingress-test.yaml [rootk8s-master ~]# kubectl get ingress NAME           CLASS   HOSTS                                   ADDRESS   PORTS   AGE test-ingress   none   test.apache.ingress,test.nginx.ingress             80     119m nginx-ingress-controller运行在node1,node2两个节点上。 如果网络中有dns服务器在dns中把这两个域名映射到nginx-ingress-controller运行的任意一个节点上如果没有dns服务器只能修改host文件了。 任意一个节点上操作(客户端解析) 我这里有两个节点部署了控制器ip分别为172.16.229.5172.16.229.6 如果有多个可以随便选。 在wind电脑设置本地解析 172.16.229.5 test.nginx.ingress 172.16.229.6 test.apache.ingress
http://www.dnsts.com.cn/news/50622.html

相关文章:

  • 精品网站建设价格建设网站有哪些目的
  • 网站 视觉上wordpress和wamp
  • 深圳网站seo关键词常州快速建站模板
  • 自己做本地网站wordpress 蓝色主题
  • 如何把网站做成appwordpress 标题 拼音
  • 住房建设部投诉网站专业的外贸建站公司
  • 小企业网站建设价格房产中介网站模板
  • 海门市建设局网站国外好的网页设计
  • 江苏建安建设有限公司网站做网站要ftp信息吗
  • 你买域名我送网站国外网站做盗版
  • 安徽圣力建设集团有限公司网站建筑工程有限公司起名大全
  • 怎么创建一个网站卖东西如何对现有的网站改版
  • 公司免费网站制作怎么申请网站
  • 网上打字兼职正规网站电子商务网站建设工资
  • 科普互联网站建设长沙开发网站的公司
  • 高端网站建设页面小程序开发源码
  • 在哪个网站找学做包子安徽建设官网
  • 安化建设局网站网站建设的作用是什么
  • 官方网站找oem做洗发水厂家如何用ftp做网站
  • 个人网站制作模板图片软件设计师考试大纲
  • 沧州网站建设 熊掌号浙江软装设计公司
  • 温州网站建设服务器现在开什么网站
  • 好看网站手机版深圳做网站乐云seo费用优惠
  • 投资融资理财网站模板网站建设一秒互联
  • 珠海正规网站制作哪家好wordpress语音
  • 网站建设期末题答案濮阳网站优化公司哪家好
  • 企业对做营销型网站有什么优势网站搭建是什么专业学的
  • 郑州快速建站公司js检测网站是否能打开
  • 网站开发定制合同范本wordpress 优化插件
  • .org做商业网站做热处理工艺的网站有哪些