容器编排系统的作用
简单来说,容器编排是指容器应用的自动布局,协同及管理,它主要负责完成以下具体任务:
1、服务注册和发现
2、负载均衡
3、配置和存储管理
4、健康状态检测
5、自动扩容、缩容、重启、关闭、
6、0宕机部署 #意思是在server端做的所有操作客户端是没有感知的

快速入门:

1master 2node
K8S 容器编排
控制平面

API Server: 6443端口
    用户认证双向认证
Scheduler
Controller
Node Pod  kube-proxy  #kube-proxy   类似于master节点上API Server的客户端,随时监视着node节点中的资源变动
Pod, Pod Controller,Service
     Pod Controller
deployment-->ngx-deploy-->nginx Pod
Service-->nginx-svc

K8S中有三种网络分别是:

Node Network:与外部网络接口通信
Service Network:充当路由,代理
Pod Network:Pod内部网络

常用的命令:

kubectl get ns      #查询所有命名空间
kubectl get all     #查询当前名称空间中所有资源
kubectl get pods    #默认查询的是default命名空间中的Pod
kubectl get pods --show-labels #显示默认命名空间所有pod信息并加载对应的标签
kubectl label pods foo unhealthy=true #修改资源标签的书写格式,foo是资源名称 unhealthy=true标签的键值对,注意:如果已有unhealthy=true,想修改true的话,会报错,这时可以使用:
kubectl label --overwrit pods foo unhealthy=flaus 在标签键值对前面加上--overwrit即可覆盖原有值
kubectl label pods foo unhealthy- #意思是删除foo资源的unhealthy标签
kubectl get pods --show-labels -l unhealthy=true    #意思为只显示标签键值对包含app=myapp的pod
kubectl get pods --show-labels -l unhealthy!=true   #意思是只显示除标签键值对为unhealthy=true以外的pod,同键不同值的也可以显示出来
kubectl get pods --show-labels -l "app in (myapp,ngx-dep)"    #只显示标签为app键且包含myapp和ngx-dep的pod
kubectl get pods -l "app in (myapp,ngx-dep)" -L app     #与上面相似但打印出的信息只有值的信息
kubectl get pods -w 意为实时监控默认命名空间所有pod的变化
kubectl exec PODNAME -- rm -f /tmp/ready  意为不用进POD就可以删除POD中/tmp/ready文件
kubectl describe pods PODNAME  查看PODNAME的具体详细信息
kubectl get cs 检查集群各组件健康与否
kubectl logs -f POD_NAME    意为实时监控该POD下所有容器日志

滚动更新镜像,以灰度更新的方式进行更新:

kubectl set image deployment [DEPLOYMENT_NAME] [CONTAINER_NAME=CONTAINER_IMAGE_1 ...] 

举例:

kubectl set image deployment myapp myapp=ikubernetes/myapp:v2

把控制器myapp中的镜像更改为ikubernetes/myapp:v2版本

同理在该命令后方也可以加入暂停更新的命令,更新一个Pod后暂停,然后该Pod和之前一些老Pod一起运行一段时间,看看是否有问题,没问题就全部更新,有问题就回滚

kubectl set image deployment myapp-deploy myapp=ikubernetes/myapp:v2 && kubectl rellout deployment myapp-deploy

实时查看监控状态的详细信息:

kubectl rollout status deployment myapp-deploy

该命令只会更新一个Pod,并不会删除任何Pod,如上所说是更新了一个暂停了,等用一段时间感觉没问题就继续更新。
这时的更新命令将会全部更新:

kubectl rollout resume deployment MYAPP-DEPLOY
kubectl rollout status deployment [DEPLOYMENT_NAME] 显示更新过程

回滚操作:

kubectl rellout undo (TYPE_NAME | TYPE/NAME)[flags][options]

进行回滚操作前建议运行kubectl rollout history deployment MYAPP-DEPLOY查看更新过的版本,其中REVISION的序列号等于更新过的版本,且指定回滚版本时也需要指定该序列号

举例:

kubectl rollout undo deployment myapp

不指定回滚版本,默认回滚至上一级

kubectl rollout undo deployment myapp-deploy --to-revision=1

意为回滚操作滚动到版本1

查看滚动更新历史:

kubectl rollout history deployment DEPLOYMENT_NAME

除了滚动更新还有打补丁式更新:

例如:

kubectl patch deployment myapp-deploy -p '{"spec":{"replocas":5}}'

其中要指定控制器类型和名称外加-p选项,以json格式写出修改选项,改参数需要注意,每一级子字段都需要在后面添加{},例如spec中的metadata字段 '{"spec":{"metadata":}}',以此类推,每多加一级增加一个大括号,修改同一级多个参数时,要用,隔开

修改某一个控制器的端口类型:

kubectl edit svc [DEPLOYMENT_NAME]

默认不支持修改地址,但可以修改port类型,例如源类型为ClusterIP,可以修改为NodePort
如果想查询其他命名空间中的Pod可以在命令后方加入-n参数指定命名空间的名字即可

例如:

kubectl get pods -n kube-system

如果想查看详细信息可在命令行后方加-o wide选项 详细信息中包括pod被调度到哪一台node中,具体的pod地址,运行多长时间,运行状态等信息

例如:

kubectl get pods -n kube-system -o wide

-o 后面跟yaml 意思是以yaml格式输出 同理后面跟json 以json格式输出

kubectl create [type] [type-name]  #创建语法

例如创建命名空间:

kubectl create ns test   #指定创建的类型 ns是命名空间的简写即命名空间类型,test是要创建的命名空间名称
kubectl create ns/test  #与上面作用相同,但第二种语法可以一次创建多个命名空间,

kubectl create和kubecreate apply的区别:
kubectl create 可以创建某个类型的Pod,但是不可以更新而kubectl apply 既可以创建Pod,也可以在创建好基础上更改该Pod,同理删除语法雷同。

例如删除test命名空间:

kubectl delete ns test  #指定要删除的类型。ns是命名空间的简写即命名空间类型 test是要删除的命名空间名称
kubectl delete ns/test  #与上面作用相同,但第二种语法可以一次删除多个命名空间,

注意:删除命名空间会连同其名下所有的pod一并删除

列出描述信息:

kubectl describe ns/default

查看手写yaml需要定义的类型解释:

kubectl explain [TypeName] 如果下级目录中有object 可以在名称类型后方加.然后跟下级名称,依此类推

例如:

kubectl explain [TypeName].[类型名称].[类型名称]...

Pod 容器
Pod可以理解为容器的外壳,一个Pod中可以有一个容器也可以有多个容器,多个容器存在时共享该Pod的网络名称空间

例如:
可以共享该Pod的IPC UTS Network,而每一个容器中都会存在PID Mount User 除此之外同一组Pod也可以共享一个存储卷,当一个Pod中有多个容器的同时,只能有一个主容器,其他的容器都只是为了辅助主容器正常工作。

例如:
目前主流的Pod多容器都是采用一个主容器,后续的副本容器设置为一个proxy(代理)主容器 主容器不直接接受Pod以外的请求。

prot:
    hostprot:只在一个node节点打开prot
    Service NodeProt:NodeProt是在所有node节点中打开NodeProt
    hostnetwork :用宿主机的网络并打开prot

Label)标签
标签就是“键值”类型的数据,他们可于资源创建时直接指定,也可随时按需添加于活动对象,而后即可由标签选择器进行匹配度检查从而完成资源挑选。
1、一个对象可以拥有不止一个标签,而同一个标签也可被添加至多个资源之上
2、实践中,可以为资源附件多个不同维度的标签,以实现灵活的资源分组管理功能,例如版本标签,环境标签,分层架构标签等,用于交叉标识同一个资源所属的不同版本、环境及架构层级等
3、标签中的键名称通常由键前缀和键名组成,其中键前缀可选,其格式型如

“KEY_PREFIX/KEY_NAME:KEYVALUE”

键名至多能使用63个字符,可使用字母、数字、连接号(-)、下划线(_)、点号(.)等
键前缀必须为DNS子域名格式,且不能超过253个字符,省略键前缀时,键将被视为用户的私有数据,不过有kubernetes系统组件或第三方组件自动为用户添加的键必须使用键前缀,而 “kubernetes.io”前缀预留给kubernetes核心组件使用。
标签中的键值必须不能多于63个字符,他要么为空,要么以字母或数字开头及结尾,且中间仅使用了字母、数字、连接号(-)、下划线(_)或点号(.)等字符的数据

标签选择器(Label Selectosr)
标签选择器用于表达标签的查询或选择标准,KubernetesAPI目前支持两个选择器:
基于等值关系(equality-based)操作符有=、==和!=三种,其中前两个意义相同,都表示“等值”关系,最后一个表示“不等值关系”基于集合关系(set-based)

KEY in(VALUE1,VALUE2,...)
KEY not in(VALUE1,VALUE2,...)
KEY :所有存在此键名标签的资源
!KEY:所有不存在此键名标签的资源

使用标签选择器时还将遵循以下逻辑:
同时指定的多个选择器之间的逻辑关系为“与”操作
使用空值的标签选择器以为着每个资源对象都将被选中。
空的标签选择器将无法选出任何资源。
定义标签选择器的方式
kubernetes的诸多资源对象必须以标签选择器的方式关联到Pod资源对象,例如Service、Deployment和ReplicaSet类型的资源等,它们在spec字段中嵌套使用嵌套“selector”字段,通过“matchLabels”来指定标签选择器,有的甚至还支持使用“matchExpressions”构造复杂的标签选择机制。

matchLabels:通过直接给定键值对指定标签选择器;
matchExpressions:基于表达式指定的标签选择器列表,每个选择器形如"{key:KEY_NAME,operator:OPERATOR,valus:[VALUE1,VALUE2,...]}",选择器列表间为"逻辑与"关系;

使用In或者NotIn操作符时,其values非必须为非空的字符串列表,而使用Exists或DostNotExist时,其values必须为空。

nodeSelector <map[string]>
    节点标签选择器,
nodeName <string> 指定node机器
annotations:
    与label不同地方在于,它不能用于挑选资源对象,仅用于为对象提供“元数据”

资源,对象

workload:Pod,replicaSet ,Deployment,StatefulSet,DaemonSet,Job,Cronjob,...
服务发现及均衡:Service,Ingress,...
配置与存储:Volume,CSI
    ConfigMap Secret 
    DownwardAPI
集群级资源:
    Namespace,Node,Role,ClusterRole ROleBinding ClusterRoleBinding
元数据型资源:
    HPA PodTemplate(Pod模板),LimitRange

K8S底层文件

apiserver仅支持JSON格式的资源定义;
yaml格式提供配置清单,apiserver可自动将其转为json格式,而后再提交;

自主式Pod资源:

大部分资源配置的清单
apiserver:group/version
  $ kubectl api-versions
  kind:资源类别
  metadata:元数据
    Name
    namespace   (命名空间)
    labels      (标签)
    annotations  (资源注解)
      每个资源的引用PATH
        /api/GROUP/VERSION/namespace/NAMESPACE/TYPE/NAME
        例如:
           /api/v1/namespaces/default/pods/nginx-deploy-7689897d8d-srqhm
  spec:期望的状态,disired state 以下几个是必须要定义的二级字段
    containers <[]object>
    - name <string>
    image <string>
    imagePullPolicy <string>  #镜像获取的策略

镜像获取的策略

Always:总是到仓库下载                  
Never:本地有镜像就用,没有就不下载                           
IfNotPresent:本地存在直接使用,不存在就下载

标签是latest的默认是以Always策略进行创建,不带latest的默认是以IfNotPresent创建
修改镜像中的默认应用:

command,args
https://kubernetes.io/zh/docs/tasks/inject-data-application/define-command-argument-container/ 该官网有详细解释

status:当前状态 current state 本字段由kubernetes本身来维护

资源注解(annotation)
注解也是键值类型的数据,不过它不能用于标签及挑选kubernetes对象,仅用于为资源提供"元数据"信息
注解中的元数据,不受字符数量的限制,它可大可小,可以为结构化或非结构化形式,也支持使用在标签中禁止使用其他字符
在kubernetes的新版本中(Alpha或Beta阶段)为某资源引入新字段时,常以注解方式提供以避免其增删等变动给用户带来困扰,一旦确定支持使用它们,这些新增字段再引入到资源中并淘汰相关的注解

Pod生命周期中的重要阶段:
初始化容器
生命中预期钩子函数
kubernetes的诸多资源对象必须以标签选择器的方式关联到Pod资源对象,例如Service、Deployment和ReplicaSet类型的资源等,它们在spec字段中嵌套使用嵌套“selector”字段,通过“matchLabels”来指定标签选择器,有的甚至还支持使用“matchExpressions”构造复杂的标签选择机制。

postaStart
postaStop

容器探测
探测类型:

存活状态探测:liveness probe。
就绪状态检测:readiness probe。

探测行为:

ExecAction
TCPSocketAction
HTTPGetAction

探针次数:
failureThreshold:意为探测多少次后的状态是失败的,k8s就认为这个Pod中的这个容器为失败的,反之如果是成功的,k8s就认为这个Pod容器为成功的,默认是探测三次,且支持定义最小探测数为一次。
periodSeconds(周期间隔时常):意为每次探测后隔多少秒后再进行下一次探测,默认是十秒探测一次
timeoutSeconds(超时探测时常):意为发出探测后始终没有响应,需要等多久,默认是一秒钟
initialDelaySeconds(初始化探测时间设定):意为第一次探测在创建Pod几秒后进行探测,如果不定义默认是容器启动后就进行探测。因容器启动不代表服务就能直接可以使用,容器也要初始化,也需要时间

例如:

HTTPGetAction探针方式:
    apiVersion: v1
    kind: Pod
    metadata:
    name: liveness-httpget-pod
    namespace: default
    spec:
      containers:
      - name: livesss-httpget-container
        image: ikubernetes/myapp:v1
        imagePullPolicy: IfNotPresent
        ports:
          - name: http
          containerPort: 80
          livenessProbe:
          httpGet:
              port: http
              path: /index.html
              initialDelaySeconds: 1
              periodSeconds: 3

ExecAction探针方式:

apiVersion: v1
kind: Pod
metadata:
name: liveness-exec-pod
namespace: default
spec:
  containers:
  - name: livesss-exec-container
    image: busybox:latest
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh","-c","touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 3600"]
    livenessProbe:
    exec:
      command: ["test","-c","/tmp/healthy"]
    initialDelaySeconds: 1
    periodSeconds: 3

状态检查:就绪状态检查是没有权力重启容器的,而健康状态检查是有权利重启容器的就绪状态检查是一个周期性的应用,只要就绪状态为0就不会被service所引用

readinessProbe就绪状态检查举例:

apiVersion: v1
kind: Pod
metadata: 
  name: readiness-httpget-pod
  namespace: default
spec:
  containers:
  - name: readiness-httpget-container
    image: ikubernetes/myapp:v1
    imagePullPolicy: IfNotPresent
    ports:
      - name: http
        containerPort: 80
    readinessProbe:
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3

Pod对象的相位:

Pod对象总是应该处于其生命进程中以下几个相位(phase)之一
Pending:API Server创建了Pod资源对象并已存入etcd中,但它尚未被调度完成,活仍处于从长裤中下载镜像的过程中。一般来说Pending出现的情况是资源不足故而没有调度成功,
Runing:Pod已经被调度到至某个节点,并且所有容器都已经被kubelet创建完成
Succeeded: Pod中所有容器都已经成功终止并且不会被重启。
Failed:所有容器都已经终止,但至少有一个容器终止失败,即容器返回了非0值的退出状态或已经卑鄙系统终止
Unknown: API Server无法正常获取Pod对象的状态信息,通常是由于其无法与所在工作节点的kubelet通信所致。

容器的重启策略:
restarPolicy:
Pod对象因容器程序崩溃或容器申请超出限制的资源等原因都可能导致其被终止,因此是否应该重建此Pod则取决于其重启策略(restartPolicy)属性的定义

Always:但凡Pod对象终止就将其重启,此为默认设定;
OnFailure:仅在Pod对象出现错误时方才将其重启;
Never:从不重启
default to Always:默认为Always

资源需求及资源限制
容器的计算资源配额

CPU属于可压缩(compressible)型资源,即资源额度可按需收缩,而内存(当前)则是不可压缩型资源,对其执行收缩操作可能会导致某种程度的问题

CPU资源的计算方式:

一个核心相当于100个微核心,即1=1000m 0.5=500m

内存资源的计量方式:

默认单位为字节,也可以使用E、P、T、G、M和K后缀单位,或Ei、Pi、Ti、Gi、Mi、和Ki形式的单位为后缀。

Pod服务质量类别
根据Pod对象的requests和limits属性,kubernetes把Pod对象归类到bestEffort、Burstable和Guaranteed三个服务质量类别(Quality of Service,Qos)类别下
Guaranteed(必须保证):每个容器都为CPU资源设置了具有相同值的requests和limits属性,以及每个容器都为内存资源设置了具有相同值的requests和limits属性,以及每个容器都为内存资源设置了具有相同值的requests和limits属性的pod资源会自动归属此类别,这类pod资源具有最高优先级。

Burstable(应该保证):至少有一个容器设置了CPU或内存资源的requests属性,但不满足Guaranteed类别要求的pod资源自动归属此类别,他们具有中等优先级。
BestEffort(尽量保证):未为任何一个容器设置requests或limits属性的pod资源自动归属此类别,它们的优先级为最低级别。

Pod控制器:
无状态控制器:
ReplicaSet:用户期望的Pod副本数量

标签选择器  用来判定哪些Pod归自己管理
现存副本数量,不够用户定义的数量时新建Pod,并使用Pod模板创建

Deployment:此控制器是工作在ReplicaSet之上,该控制器不是直接控制Pod而是控制ReplicaSet控制器来控制Pod,所以ReplicaSet支持的功能Deployment也支持。该控制器支持滚动更新,声明式配置,支持动态配置,最应该掌握的控制器之一,且支持使用apply来声明式更新Pod

例如:deploy模板

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
      release: canary
  template:
    metadata:
      labels:
        app: myapp
        release: canary
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
        - name: http
          containerPort: 80

注意:以上模板中创建完成后会有两个POd,分别是myapp-deploy-f4db5d79c-5zktl和myapp-deploy-f4db5d79c-kjq8z,其中myapp-deploy-f4db5d79c是deployment控制的RS所创建,名字中的f4db5d79c是由模板定义的hash值所得,最后面的五位字符才是Pod随机生成的名字。
其中滚动更新后,会生成两个rs控制器,更新后只有一个更新后的rs正常提供服务,而之前的rs会被保留到rs控制器中,但不提供任何服务,在被需要时可以滚动回到之前版本,

DaemonSet: 用于确保集群中每一个Node节点,只运行一个特定的Pod副本,通常用来实现一些系统级的后台任务。当集群中加入新的node节点时,会自动添加一个此类的Pod副本,此控制器定义不取决于Pod的数量而是取决于集群规模,Pod模板和标签选择器都是要存在的。也可以运行在某一些Node节点上,例如五台node节点,三台有SSD硬盘,两台没有SSD硬盘,这时需求是只监听有SSD硬盘的Node节点,而此控制器可以做到这一点,此类进程必须是守护进程类在后端一直运行。
job: 只要完成就正常退出,没完成重做。
Cronjob: 周期性运行,每一次运行都会正常退出,与Linux中的cron很相像
ingress及ingress controller:拥有七层代理能力和调度能力的资源对象
ingress controller的访问流程。

用户=>集群node=>解析相关信息交给相关SVC=>svc=>到对应的nginx_ClusterIP=>调度后端Pod信息
也可以直接把nginx—ClusterIP相关Pod,使用NodePort和node节点共用网络命名空间用户=>nginx—ClusterIPPod=>调用后端Pod信息

ingress资源

ingress用于实现用域名的方式访问k8s内部应用。
ingress和ingress controller是两回事,
ingress:定义ingress时就是定义ingress container如何建立前端,前端可能是个虚拟机主机,也可能是个Url映射等,同样也可以建立后端upstream Service,upstream Service中有几个主机ingress是通过后端分类的SVC得到的

ingress有个特点,可以直接通过编辑yaml文件将所需配置注入到ingress controller中并保存为配置文件,而且一但ingress发现调用后端需要的SVC选定的Pod信息发生改变时会及时反应到ingress中,然后ingress会把相关变动及时注入到ingress controller中的upstream配置文件中,还能触发相关ingress controller的调度器重载配置文件需要有个SVC对后端Pod进行分类,注意:此SVC只是起分类作用,ingress基于这个分类识别出后端有多少个Pod,每个Pod的IP是多少,并且把IP地址生成的结果生成一个配置文件注入到ingress container中的upstream中

第一、需要部署一个ingress container,类似于K8s的coredns,是一个Pod
第二、根据自己的需要,用虚拟主机的方式还是用Url代理的方式来配置定义一个前端,然后根据后端分类的SVC收集到的后端PodIP生成Upstream,把这些信息反应在ingress中,用ingress动态注入到ingress container中

部署一个完整的ingress:

第一步、部署一个ingress container,类似于K8s的coredns,是一个Pod
部署完成后,应该是:

default-http-backend-6cdd6c64f8-7tgtv       1/1     Running   1          22h
nginx-ingress-controller-78d9bb7697-64bnn   1/1     Running   0          22h

官网提供的文件中提供的Pod为两个,我们用到的只有第二个nginx-ingress-controller-78d9bb7697-64bnn而第一个default-http-backend-6cdd6c64f8-7tgtv是因为第二个依赖于第一个Pod,相当于yum中的依赖关系

虽然ingress container部署好了,但是无法接入外部流量,所以还需要为ingress container创建个nodePort的SVC,以接入外部流量,此步骤只有ingress刚创建时需要

示例:

apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
spec:
  type: NodePort
  ports:
  - name: http
    port: 80        #SVC的端口
    targetPort: 80  #容器的端口    
    protocol: TCP
    nodePort: 30080 #节点端口,如果没指定意为随机分配
  - name: https
    port: 443     #服务端口443,就是上面的default-http-backend-6cdd6c64f8-7tgtv服务端口
    targetPort: 443     #暴露服务端口
    protocol: TCP
    nodePort: 30443     #节点端口,如果没指定意为随机分配
  selector:
    app: ingress-nginx

第二步、定义ingress 创建好后k8s会把定义的ingress注入到ingress-nginxPod中,而ingress-nginx的Pod会把注入的ingress文件转化为nginx的配置文件

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-myapp   #注意下方要和定义后端Pod时的deployment在同一个命名空间
  namespace: default    #注意下方资源注解中的kubernetes.io/ingress.class: "nginx"必须要写,且要指定用的什么
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: myapp.master.com
    http:
      paths:
      - path:
        backend:
        serviceName: myapp
        servicePort: 80

第三步、定义后端Pod,生成SVC,

举例:

                apiVersion: v1
                kind: Service
                metadata:
                  name: myapp
                  namespace: default
                spec:
                  selector:
                    app: myapp
                    release: canary
                  ports:
                  - name: http
                    targetPort: 80  #该端口和下列要与deployment中容器端口相对应 意为暴露容器的端口是什么,要和容器相对应
                    port: 80        #在svc中暴露的端口为多少
                ---
                apiVersion: apps/v1
                kind: Deployment
                metadata:
                  name: myapp-deploy
                  namespace: default
                spec:
                  replicas: 3
                  selector:
                    matchLabels:
                    app: myapp
                    release: canary
                template:
                    metadata:
                      labels:
                        app: myapp
                        release: canary
                    spec:
                      containers:
                      - name: myapp
                        image: ikubernetes/myapp:v2
                        ports:
                        - name: http
                        containerPort: 80

第四步、建立关联关系
ingress也支持ssl协议,俗称https协议:

第一步、部署后端Pod和分类用的SVC,以下部署两组SVC和后端Pod

            apiVersion: v1
            kind: Service
            metadata:
              name: tomcat
              namespace: default
            spec:
              selector:
                app: tomcat
                release: canary
              ports:
              - name: http
                targetPort: 8080
                port: 8080
              - name: ajp
                targetPort: 8009
                port: 8009
            ---
            apiVersion: apps/v1
            kind: Deployment
            metadata:
              name: tomcat-deploy
              namespace: default
            spec:
              replicas: 3
              selector:
                matchLabels:
                app: tomcat
                release: canary
              template:
                metadata:
                labels:
                  app: tomcat
                  release: canary
                spec:
                  containers:
                  - name: tomcat
                    image: tomcat:8.5.32-jre8-alpine
                    ports:
                    - name: http
                    containerPort: 8080
                    - name: ajp
                    containerPort: 8009
            apiVersion: v1
            kind: Service
            metadata:
              name: myapp
              namespace: default
            spec:
              selector:
                app: myapp
                release: canary
              ports:
              - name: http
                targetPort: 80
                port: 80
            ---
            apiVersion: apps/v1
            kind: Deployment
            metadata:
              name: myapp-deploy
              namespace: default
            spec:
              replicas: 3
              selector:
                matchLabels:
                app: myapp
                release: canary
              template:
                metadata:
                labels:
                  app: myapp
                  release: canary
                spec:
                  containers:
                  - name: myapp
                    image: ikubernetes/myapp:v2
                    ports:
                    - name: http
                    containerPort: 80

第二步、部署ingress controller

            apiVersion: extensions/v1beta1
            kind: Ingress
            metadata:
              name: ingress-tomcat-tls
              namespace: default
              annotations: 
                kubernetes.io/ingress.class: "nginx"
            spec:
              tls:              #tls是做https协议的,因此需要在本地生成对应证书openssl genrsa -out tls.key 2048     openssl req -new -x509 -key tls.key -out tls.crt -subj /C=CN/ST=shanghai/0=DevOps/CN=tomcat.com      
              - hosts:
                - tomcat.com        #此处的tomcat要与下方的host名字对应
                  secretName: tomcat-ingress-secret      这里的secretName是设置tls名称的 kubectl get secret查询证书名称命令找到相应的证书名称并填写到该处
            rules:
              - host: tomcat.com
                http: 
                paths:
                - path:
                    backend:
                    serviceName: tomcat
                    servicePort: 8080
            ---
            apiVersion: extensions/v1beta1
            kind: Ingress
            metadata:
              name: ingress-myapp
              namespace: default
              annotations:
                kubernetes.io/ingress.class: "nginx"
            spec:
              rules:
              - host: myapp.master.com
                http:
                paths:
                - path:
                    backend:
                    serviceName: myapp
                    servicePort: 80

注意:因为上方的ingress containerPod定义了https端口为30443,所以访问tomcat.com时要加上30443端口tomcat.com:30443
以上方式可以访问两个主机名,分别是myapp.master.com:30080 和https://tomcat.com:30443前者为http方式五加密,后者为已加密的https方式

下方为创建证书后并以命令的方式创建相关secret:

                    openssl genrsa -out tls.key 2048
                    openssl req -new -x509 -key tls.key -out tls.crt -subj/C=CN/ST=shanghai/0=DevOps/CN=tomcat.com
                    kubectl create tls tomcat-ingress-secret --cert=tls.crt --key=tls.key
                    [root@master ingress]# kubectl get secret
                    NAME                    TYPE                                  DATA   AGE
                    default-token-dxgqh     kubernetes.io/service-account-token   3      12d
                    tomcat-ingress-secret   kubernetes.io/tls                     2      35m

创建完成后应该是以上方的形式出现

有状态控制器:
StatefulSet: 单体型控制器,管理我们的有状态应用,每一个应用,每一个Pod副本都是被单独管理的,拥有自己独有的标识和独有的数据集
1、稳定且唯一的网络标识符
2、稳定且持久的存储
3、有序、平滑的部署和扩展
4、有序平滑的删除和终止
5、有序的滚动更新,

由三个组件组成:

      headless    service(无头Service)     StatefulSet      volumeClaimTemplate

volumeClaimTemplate:
卷申请模板,StatefulSet中每个节点应该有每个专用的存储卷,因为每个节点数据不同名字可能一样,所以每个节点应该使用独立存储卷,存放自身的独立数据,因此每个Pod都应该有一个专用的PV和专用的PVC
建完成后volumeClaimTemplate会自动创建PVC和自动绑定合适的PV,在本章案例中PV是手动创建的一个完整的StatefulSet控制器应该由Service、StatefulSet和volumeClaimTemplate组成,且Service必须是无头服务

StatefulSet举例:

          apiVersion: v1
          kind: Service
          metadata:
            name: myapp
            labels:
              app: myapp
          spec:
            ports:
            - port: 80
              name: web
            clusterIP: None
            selector:
              app: myapp-pod
          ---
          apiVersion: apps/v1
          kind: StatefulSet
          metadata:
            name: myapp
          spec:
            serviceName: myapp
            replicas: 3
            selector:
              matchLabels:
                app: myapp-pod
            template:
              metadata:
                labels:
                  app: myapp-pod
              spec:
                containers:
                - name: myapp
                  image: ikubernetes/myapp:v1
                  ports:
                  - containerPort: 80
                    name: web
                  volumeMounts:
                  - name: myappdata
                    mountPath: /usr/share/nginx/html
            volumeClaimTemplates:
            - metadata:
                name: myappdata
              spec:
                accessModes: ["ReadWriteOnce"]
                resources:
                  requests:
                    storage: 5Gi

启动时Pod的顺序为0~N 关闭的顺序为N~0
删除Pod后PVC是不变的且重新创建后存储路径还是会和之前定义绑定的PV在同一个PV中
在StatefulSet中每一个Pod名称都是可被解析的而且还是固定名称
在kuberneter中解析StatefulSet必须跟上无头服务名称才能解析出来相应的Pod名字

格式为:

            POD_NAME.SERVICE_NAME.NS_NAME.svc.cluster.local

滚动更新:
滚动更新方式和以上几种控制器类似
更新分区:

partition:N
 >=N   #意为只更新Pod编号大于等于N的Pod

举例:

kubectl patch sts myapp -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":4}}}}'

可以使用set image来更新镜像

kubectl set image sts/myapp myapp=ikubernetes/myapp:v3

执行完以上命令后可以检查下是否生效

            [root@master StatefulSet]# kubectl describe sts myapp
            Name:               myapp
            Namespace:          default
            CreationTimestamp:  Wed, 12 Jan 2022 17:01:02 +0800
            Selector:           app=myapp-pod
            Labels:             <none>
            Annotations:        kubectl.kubernetes.io/last-applied-configuration:
                                  {"apiVersion":"apps/v1","kind":"StatefulSet","metadata":{"annotations":{},"name":"myapp","namespace":"default"},"spec":{"replicas":3,"sele...
            Replicas:           3 desired | 3 total
            Update Strategy:    RollingUpdate
              Partition:        4                   #此处是上面命令设置的滚动更新设置,意为只更新大于等于4的Pod
            Pods Status:        3 Running / 0 Waiting / 0 Succeeded / 0 Failed
            Pod Template:
              Labels:  app=myapp-pod
              Containers:
              myapp:
                Image:        ikubernetes/myapp:v1
                Port:         80/TCP
                Host Port:    0/TCP
                Environment:  <none>
                Mounts:
                  /usr/share/nginx/html from myappdata (rw)
              Volumes:  <none>
            Volume Claims:
              Name:          myappdata
              StorageClass:  
              Labels:        <none>
              Annotations:   <none>
              Capacity:      5Gi
              Access Modes:  [ReadWriteOnce]
            Events:          <none>

在此基础上更新镜像或者文件时只会更新名字大于等于4的Pod

          kubectl set image sts/myapp myapp=ikubernetes/myapp:v3

此更新命令只会更新名字大于等于4的Pod,其余不更新,等该Pod使用一段时间后没问题再更改为0意为大于等于0的全部更新也就是全部更新,俗称金丝雀发布

有状态应用建议不要放到K8S中

Service:
工作模式:userspace,iptables ipvs

    userspace:1.1-
    iptables:1.10-
    ipvs:1.11+

类型:

    ExternalName,ClusterIP,NodePort和LoadBalancer
    NodePort的工作逻辑;client->NodeIP.NodePort->ClusterIP.ServicePort->PodIP,containerPort
    No ClusterIP;Headless Service

无头类型的工作逻辑ServiceName->PodIP,由上看出NodePort的工作逻辑是解析出ClusterIP,而无头类型是把ServiceName名称直接解析为后端PodIP

资源记录:

    SVC_NAME.NS_NAME.DOMAIN.LTD
    svc.Cluster.local

举例:

        redis.default.svc.Cluster.local

Service清单举例:

ClusterIP类型:

        apiVersion: v1
        kind: Service
        metadata:
          name: redis
          namespace: default
        spec:
          selector:
            app: redis
            role: logstor
          clusterIP: 10.1.97.97
          type: ClusterIP
          ports:
          - port: 6379
            targetPort: 6379
    NodePort类型:
        apiVersion: v1
        kind: Service
        metadata:
        name: myapp
        namespace: default
        spec:
          sessionAffinity: ClientIP
          clusterIP: 10.1.97.97
          selector:
            app: myapp
            release: canary
          type: NodePort
          ports:
          - port: 80
            targetPort: 80
            nodePort: 30080

注意:其中sessionAffinity可以会话保持,而spec中的ClusterIP和ports中的nodePort可以选择不定义,不定义的结果是Cluster IP和nodeProtIP系统自动分配一个对应的地址和端口

无头类型:

        apiVersion: v1
        kind: Service
        metadata:
          name: myapp-headless
          namespace: default
        spec:
          sessionAffinity: ClientIP
          clusterIP: None
          selector:
            app: myapp
            release: canary
          ports:
          - port: 80
            targetPort: 80

在一个集群中有这个几个组件:pod-a,svc-b,pod-b1,pod-b2。当 pod-a 想访问 pod-b 中的应用程序时,先会把请求打到 svc-b,再由 svc-b 将请求随机转发到 pod-b1或 pod-b2。
如果有个需求:pod-a 需要同时连接到 pod-b1和 pod-b2 ,这时再采用 svc-b 转发显然已经不能满足需求了。那 pod-a 该如何获取到 pod-b1和 pod-b2 的 IP 地址呢?采用 handless service 就可以实现。

无头SVC解析到的主机名:

            [root@master ~]# dig -t A myapp-headless.default.svc.Cluster.local @10.1.0.10
            ; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7 <<>> -t A myapp-headless.default.svc.Cluster.local @10.1.0.10
            ;; global options: +cmd
            ;; Got answer:
            ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36998
            ;; flags: qr aa rd; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 1
            ;; WARNING: recursion requested but not available

            ;; OPT PSEUDOSECTION:
            ; EDNS: version: 0, flags:; udp: 4096
            ;; QUESTION SECTION:
            ;myapp-headless.default.svc.Cluster.local. IN A

            ;; ANSWER SECTION:
            myapp-headless.default.svc.Cluster.local. 30 IN    A 10.244.2.11
            myapp-headless.default.svc.Cluster.local. 30 IN    A 10.244.1.10
            myapp-headless.default.svc.Cluster.local. 30 IN    A 10.244.1.11
            myapp-headless.default.svc.Cluster.local. 30 IN    A 10.244.2.10
            myapp-headless.default.svc.Cluster.local. 30 IN    A 10.244.2.12

            ;; Query time: 55 msec
            ;; SERVER: 10.1.0.10#53(10.1.0.10)
            ;; WHEN: Fri Dec 24 22:57:31 CST 2021
            ;; MSG SIZE  rcvd: 349

此时可以看到解析到的主机名有五个,而有头的SVC却只能解析到一个。

下列举例说明:

            [root@master ~]# dig -t A myapp.default.svc.Cluster.local @10.1.0.10
            ; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7 <<>> -t A myapp.default.svc.Cluster.local @10.1.0.10
            ;; global options: +cmd
            ;; Got answer:
            ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14319
            ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
            ;; WARNING: recursion requested but not available

            ;; OPT PSEUDOSECTION:
            ; EDNS: version: 0, flags:; udp: 4096
            ;; QUESTION SECTION:
            ;myapp.default.svc.Cluster.local. IN    A

            ;; ANSWER SECTION:
            myapp.default.svc.Cluster.local. 30 IN    A    10.1.155.68

            ;; Query time: 1 msec
            ;; SERVER: 10.1.0.10#53(10.1.0.10)
            ;; WHEN: Fri Dec 24 22:59:38 CST 2021
            ;; MSG SIZE  rcvd: 107

存储卷:
如果想要使用存储卷需要定义:
第一、在Pod上要定义volume,而这个volume要指明关联到什么设备上的
第二、在容器中要使用存储卷挂载然后才能使用存储卷
emptyDir:临时目录
特性为相关Pod被删除,该存储卷也一并被删除,就算被控制器重新创建后,数据也无法恢复

示例:以下为一个Pod中存在两个容器,第一个容器为nginx容器,第二个为nginx的index.html主页文件生成数据,一主一辅,其中第一个容器的主页文件路径是/usr/share/nginx/html 而第二个辅助容器生成的数据存放在/data/index.html中,但是访问的时候是显示容器二提供的数据,因此可以得出结论,

          apiVersion: v1
          kind: Pod
          metadata:
            name: pod-demo
            namespace: default
            labels:
              app: myapp
              tier: frontend
            annotations:
              tomcat.com/created-by: "cluster admin"
          spec:
            containers: 
            - name: myapp
              image: ikubernetes/myapp:v1
              imagePullPolicy: IfNotPresent
              ports:
              - name: http
                containerPort: 80
              volumeMounts:
              - name: html
                mountPath: /usr/share/nginx/html/
            - name: busybox
              image: busybox:latest
              imagePullPolicy: IfNotPresent
              volumeMounts:
              - name: html
                mountPath: /data/
              command:
              - "/bin/sh"
              - "-c"
              - "while true; do echo $(date) >> /data/index.html; sleep 2; done"
            volumes:
            - name: html
              emptyDir: {}

gitRepo:
类似于emptyDir,于其不同的地方是,他会去git仓库之上把指定的内容克隆到Pod之中,此操作依赖于宿主机拥有git命令才能完成相关操作,且克隆之后在Pod之中修改源文件不会同步到git仓库中,在git仓库中修改数据也不会同步到Pod中
hostPath:分为三类

SAN:iSCSI
NAS:nfs cifs

分布式存储:

glusterfs,rbd,cephfs

云端存储:

EBS,Azure Disk...在云端存储的都算是云端存储。

具体kubernetes支持多少存储通过以下命令获得:

          kubectl explain pods.spec.volumes

在Pod中挂载宿主机的文件系统,其中挂载类型为:
DirectoryOrCreate:如果给定路径中不存在任何内容,则会根据需要在那里创建一个空目录,其权限设置为 0755,与 Kubelet 具有相同的组和所有权。
Directory:给定路径中必须存在的目录
FileOrCreate:如果给定路径中不存在任何内容,则会根据需要在那里创建一个空文件,其权限设置为 0644,与 Kubelet 具有相同的组和所有权。
File:文件必须存在于给定的路径之中
Socket:给定路径中必须存在 UNIX 套接字
CharDevice:字符设备必须存在于给定的路径中
BlockDevice:块设备必须存在于给定的路径

举例:

            apiVersion: v1
            kind: Pod
            metadata:
              name: pod-vol-hostpath
              namespace: default
            spec:
              containers:
              - name: myapp
                image: ikubernetes/myapp:v1
                imagePullPolicy: IfNotPresent
                volumeMounts: 
                - name: html                            #名称
                  mountPath: /usr/share/nginx/html      #这个是容器中要挂载路径的路径信息
      !!!  volumes:
              - name: html
                hostPath:
                  path: /data/pod/volume1    #这个位置要写NFS中共享出来的存储路径
                  type: DirectoryOrCreate    #这个是类型,详细信息上方有

NFS:
在K8S中需要K8S管理员创建PV和PVS,多个pvs可以和PV建立关系。一个PV自能绑定一个存储系统之上的路径
注意:
一个卷一次只能使用一种访问模式挂载,即使它支持多种访问模式。例如:
GCEPersistentDisk 可以由单个节点挂载为 ReadWriteOnce 或由多个节点挂载为 ReadOnlyMany,但不能同时挂载。

PV访问模型:

https://kubernetes.io/zh/docs/concepts/storage/persistent-volumes/    官网提供信息
ReadWriteOnce:该卷可以由单个节点以读写方式挂载。ReadWriteOnce 访问模式仍然可以允许多个 Pod 在同一节点上运行时访问该卷。
ReadOnlyMany:  该卷可以被许多节点以只读方式挂载。
ReadWriteMany:该卷可以被许多节点以读写方式挂载。
ReadWriteOncePod:该卷可以由单个 Pod 以读写方式挂载。如果您想确保整个集群中只有一个 Pod 可以读取该 PVC 或写入该 PVC,请使用 ReadWriteOncePod 访问模式。这仅支持 CSI 卷和 Kubernetes 1.22+ 版。

在CLI中,访问模式缩写为:

RWO - ReadWriteOnce
ROX - ReadOnlyMany
RWX - ReadWriteMany
RWOP - ReadWriteOncePod

PV在k8S中属于集群类资源,和命名空间一样,所以不可以在部署PV中设置namespace

举例:

        apiVersion: v1
        kind: PersistentVolume
        metadata:
          name: pv001
          labels:
            name: pv001
        spec:
          nfs:                              #文件系统类型
            path: /data/volumes/v1          #nfs的共享路径
            server: data_har                #NFS的地址,此名为解析地址,可写为IP地址
          accessModes: ["ReadWriteMany","ReadWriteOnce"]        #访问模型 支持多节点读写,支持单节点读写 
          capacity:                                             #指定空间大小
            storage: 2Gi                                        #大小为2G
        ---
        apiVersion: v1
        kind: PersistentVolume
        metadata:
          name: pv002
          labels:
            name: pv002
        spec:
          nfs:
            path: /data/volumes/v2
            server: data_har
          accessModes: ["ReadWriteOnce"]
          capacity:
            storage: 5Gi
        ---
        apiVersion: v1
        kind: PersistentVolume
        metadata:
          name: pv003
          labels:
            name: pv003
        spec:
          nfs:
            path: /data/volumes/v3
            server: data_har
          accessModes: ["ReadWriteMany","ReadWriteOnce"]
          capacity:
            storage: 20Gi
        ---
        apiVersion: v1
        kind: PersistentVolume
        metadata:
          name: pv004
          labels:
            name: pv004
        spec:
          nfs:
            path: /data/volumes/v4
            server: data_har
          accessModes: ["ReadWriteMany","ReadWriteOnce"]
          capacity:
            storage: 10Gi
        ---
        apiVersion: v1
        kind: PersistentVolume
        metadata:
          name: pv005
          labels:
            name: pv005
        spec:
          nfs:
            path: /data/volumes/v5
            server: data_har
          accessModes: ["ReadWriteMany","ReadWriteOnce"]
          capacity:
            storage: 10Gi
        ---
        apiVersion: v1
        kind: PersistentVolume
        metadata:
          name: pv006
          labels:
            name: pv006
        spec:
          nfs:
            path: /data/volumes/v6
            server: data_har
          accessModes: ["ReadWriteMany","ReadWriteOnce"]
          capacity:
            storage: 1Gi

以上PV有6个,每个路径都不一样,每个路径都和nfs路径相对应

      showmount -e
      Export list for data_har:
      /data/volumes/v6 10.5.0.0/8
      /data/volumes/v5 10.5.0.0/8
      /data/volumes/v4 10.5.0.0/8
      /data/volumes/v3 10.5.0.0/8
      /data/volumes/v2 10.5.0.0/8
      /data/volumes/v1 10.5.0.0/8

创建完成后可以kubectl get pv查看具体创建信息

举例:以上创建的结果是:

          NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
          pv001   2Gi        RWO,RWX        Retain           Available                                   3h12m
          pv002   5Gi        RWO            Retain           Available                                   3h12m
          pv003   20Gi       RWO,RWX        Retain           Available                                   3h12m
          pv004   10Gi       RWO,RWX        Retain           Available                                   3h12m
          pv005   10Gi       RWO,RWX        Retain           Available                                   3h12m
          pv006   1Gi        RWO,RWX        Retain           Available                                   3h12m

其中RECLAIM POLICY这一项是回收策略,本文没有制定回收策略所以默认显示Retain意为保留策略。建议使用保留策略,而STATUS一栏显示Available,意为可用状态,可以被PVC所绑定
PVC:在k8s中PVC是保存在ETCD中的,一般情况下只删除POD,不会去动PVC,PV在绑定PVC的情况下是无法删除,需解绑后才能删除,在1.9版本以下是可以直接删除PV的

示例:

          apiVersion: v1
          kind: PersistentVolumeClaim         #创建PVC类型
          metadata:
            name: mypvc                       #PVC名字
            namespace: default                #PVC隶属于那个名称空间,要和绑定的Pod在同一种名称空间种,因为下方Pod属于default所以这里也要写default
          spec:
            accessModes: ["ReadWriteMany"]    #PVC支持的格式,此处支持多节点读写,注意此处要和绑定的PV属于同一种类型,或者多类型中的其中一种
            resources:          
              requests:
                storage: 5Gi                  #指定需要的大小空间
          ---
          apiVersion: v1
          kind: Pod
          metadata:
            name: pod-vol-pvc
            namespace: default
          spec:
            containers:
            - name: myapp
              image: ikubernetes/myapp:v1
              imagePullPolicy: IfNotPresent
              volumeMounts: 
              - name: html
                mountPath: /usr/share/nginx/html
            volumes:
            - name: html
              persistentVolumeClaim:
                claimName: mypvc                #此处要和上方的name相对应,以name的方式来**绑定PVC**
  StorageClass(动态卷):暂时不了解动态卷的配置信息

配置容器化应用的方式
1、自定义命令行参数

    command
      args

2、把配置文件直接焙进镜像
3、环境变量

(1)Cloud Natuve的应用程序一般可直接通过环境变量加载配置
(2)通过entrypoint脚本来预处理变量为配置文件中的配置信息

4、存储卷

configMap:

configMap在K8S中充当配置中心的角色,用于修改Pod中的配置文件信息且支持动态修改,只不过修改完配置文件后需要手动使Pod重载配置文件
在K8S中与configMap功能相同的资源是secret,不同的是configMap是以明文形式保存到ETCD中的,而secret是以密文形式保存到ETCD
configMap的重要作用:

    让配置信息与镜像文件解耦,从而增强了应用的可移植性,以及应用的可复用性,简单来说一个configMap就是一切应用数据的集合,而这些数据将来可以注入到Pod对象中的容器中所使用。

而注入的方式有两种:

      第一、直接把configMap当存储卷
      第二、使用ENV  volumeFrom的方式引用configMap当中所保存进去的数据

在每个configMap中所有的配置信息都保存为键值格式比如键名为name键值为张三 name=张三 值是没有限制的所以可以保存相当长的一些配置文件
值可以保存为一些参数,也可以保存为一些完整的配置文件都是没有问题的,例如nginx为键,nginx的配置文件nginx.conf为值的信息,
同样我们可以在Pod启动时从configMap键上获取相关的数据项

创建configMap:
建议configMap用CLI的方式来创建,这样会简单很多

例如:

      kubectl create configmap NAME --from-file=PATH/File

此方式直接指定文件内容为值文件名为键的方式。例如,当前文件有个名为txt而内容是123的文件执行完以上命令,键名就为txt值就是123 txt=123
举例现在有一个在当前目录名为www.conf的配置文件具体配置信息如下:

      server {
              server_name myapp.com
              listen 80;
              root    /data/web/html/;
      }

然后以文件内容方式创建configMap

      kubectl create configmap nginx-www --from-file=./www.conf #此处不写出键名是什么,系统会自动把文件名作为键名,文件内容作为键值来创建configMap

查询configMap是否创建完成:

      [root@master configMap]# kubectl get cm
      NAME           DATA   AGE
      nginx-config   2      13m
      nginx-www      1      6s

查询configMap内容:

[root@master configMap]# kubectl describe cm nginx-www
Name:         nginx-www
Namespace:    default
Labels:       <none>
Annotations:  <none>

  Data
  ====
  www.conf:
  ----
  server {
    server_name myapp.com
    listen 80;
    root  /data/web/html/;
    }

    Events:  <none>

以上内容以www.conf来作为名字且内容为键值,www.conf和文件名相对应
当然也可以直接指明键名是什么值是什么:

kubectl create configmap NAME --from-literal=KEY1=CONFIG1

举例:

kubectl create cm nginx-config --from-literal=nginx_port=8080 --from-literal=server_name=myapp.com

以上创建了一个名为nginx-config的configMap文件,其中存在两个键值分别是nginx_port=8080和server_name=myapp.com

      [root@master configMap]# kubectl describe cm nginx-config
      Name:         nginx-config
      Namespace:    default
      Labels:       <none>
      Annotations:  <none>

      Data
      ====
      server_name:
      ----
      myapp.com
      nginx_port:
      ----
      8080
      Events:  <none>

通过环境变量来传递configMap中的配置信息:

    [root@master configMap]# vim pod-configMap.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-cm-1
      namespace: default
      labels:
        app: myapp
        tier: frontend
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80
        env:
        - name: NGINX_SERVER_PORT   #此处为传递到容器中的环境变量名字
          valueFrom:                
            configMapKeyRef:        
              name: nginx-config    #此处为configMap的名字
              key: nginx_port       #此处为configMap中的键值名
        - name: NGINX_SERVER_NAME   #此处为传递到容器中的环境变量名字
          valueFrom:
            configMapKeyRef:
              name: nginx-config    #此处为configMap的名字
              key: server_name      #此处为传递到容器中的环境变量名字

configMap上面是已经创建的有的因此在上方示例直接引用,通常也是要先创建configMap后引用
以上Pod创建完成后进入Pod中查看环境变量信息是否有
NGINX_SERVER_PORT=8080
NGINX_SERVER_NAME=myapp.com

以下是详细信息:

          MYAPP_SVC_PORT_80_TCP_ADDR=10.98.57.156
          KUBERNETES_SERVICE_PORT=443
          MYAPP_SERVICE_PORT_HTTP=80
          KUBERNETES_PORT=tcp://10.1.0.1:443
          TOMCAT_PORT_8080_TCP=tcp://10.1.155.239:8080
          TOMCAT_PORT_8009_TCP=tcp://10.1.155.239:8009
          MYAPP_SVC_PORT_80_TCP_PORT=80
          HOSTNAME=pod-cm-1
          SHLVL=1
          MYAPP_SVC_PORT_80_TCP_PROTO=tcp
          HOME=/root
          MYAPP_SERVICE_HOST=10.1.80.253
          NGINX_SERVER_PORT=8080
          NGINX_SERVER_NAME=myapp.com
          MYAPP_SVC_PORT_80_TCP=tcp://10.98.57.156:80
          MYAPP_PORT=tcp://10.1.80.253:80
          MYAPP_SERVICE_PORT=80
          TERM=xterm
          NGINX_VERSION=1.12.2
          KUBERNETES_PORT_443_TCP_ADDR=10.1.0.1
          MYAPP_PORT_80_TCP_ADDR=10.1.80.253
          PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
          KUBERNETES_PORT_443_TCP_PORT=443
          TOMCAT_SERVICE_PORT_HTTP=8080
          KUBERNETES_PORT_443_TCP_PROTO=tcp
          MYAPP_PORT_80_TCP_PORT=80
          MYAPP_PORT_80_TCP_PROTO=tcp
          MYAPP_SVC_SERVICE_HOST=10.98.57.156
          TOMCAT_PORT_8080_TCP_ADDR=10.1.155.239
          TOMCAT_SERVICE_HOST=10.1.155.239
          TOMCAT_PORT_8009_TCP_ADDR=10.1.155.239
          KUBERNETES_SERVICE_PORT_HTTPS=443
          KUBERNETES_PORT_443_TCP=tcp://10.1.0.1:443
          TOMCAT_PORT_8080_TCP_PORT=8080
          PWD=/
          TOMCAT_PORT_8080_TCP_PROTO=tcp
          MYAPP_PORT_80_TCP=tcp://10.1.80.253:80
          TOMCAT_PORT_8009_TCP_PORT=8009
          KUBERNETES_SERVICE_HOST=10.1.0.1
          MYAPP_SVC_SERVICE_PORT=80
          MYAPP_SVC_PORT=tcp://10.98.57.156:80
          TOMCAT_PORT_8009_TCP_PROTO=tcp
          TOMCAT_PORT=tcp://10.1.155.239:8080
          TOMCAT_SERVICE_PORT=8080
          TOMCAT_SERVICE_PORT_AJP=8009

以上看出是存在NGINX_SERVER_PORT=8080和NGINX_SERVER_NAME=myapp.com的证明环境变量传入成功!
注意:当我们使用环境变量注入时只在Pod启动时生效,更改configmaps时Pod中不生效,缺乏灵活性,通过存储卷的方式获取是可以实时更新的
修改configMap时可以用edit来修改相关信息
使用存储卷来传递configMap中的信息:

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-cm-2
      namespace: default
      labels:
        app: myapp
        tier: frontend
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80
        volumeMounts:                       
        - name: nginxconf                     #挂载到容器中的名字一般要和volumes中的名字一样
          mountPath: /etc/nginx/config.d/     #挂载到容器中的位置信息
          readOnly: true
      volumes:
      - name: nginxconf                       #存储卷名字
        configMap:                            #存储卷类型
          name: nginx-config                  #事先创建的configMap的名字,因为上方已经创建本yaml文件中使用的以创建好的configmap

此存储卷可以动态更改配置文件,意思是说可以直接更改configMap文件更改完成后Pod也会生效,只不过需要一点时间来做同步。注意注入到Pod中文件显示为浅蓝色,但是其实他就是一个链接文件,可以直接使用cat查看,或者使用都是可以的

举例注入Nginx配置文件:

        apiVersion: v1
        kind: Pod
        metadata:
          name: pod-cm-3
          namespace: default
          labels:
            app: myapp
            tier: frontend
        spec:
          containers: 
          - name: myapp
            image: ikubernetes/myapp:v1
            imagePullPolicy: IfNotPresent
            ports:
            - name: http
              containerPort: 80
            volumeMounts:
            - name: nginxconf
              mountPath: /etc/nginx/conf.d/
              readOnly: true
          volumes:
          - name: nginxconf
            configMap:
              name: nginx-www

此处引用的也是上方事先创建好的configMap文件,其挂在路径换到nginx的默认配置路径下然后创建出配置文件下的网页目录和index.html
注意:此方式可以随时更改Nginx的配置文件,但是要想使配置文件生效需要手动重载下nginx的配置信息,不然不生效

用户的认证授权于准入控制:
在K8S中认证机制一般包括三个部分,认证、授权、准入控制,因K8S是高度模块化的系统,所以这三个部分也是由各个模块组成

客户端-->API Server
    user: username  UID
    group:  用户组
    Extra:  提供额外信息
    API: 资源

在master中使用kubectl时不许要认证可以直接使用该命令进行创建,部署,删除等一系列操作,是因为安装kubernetes时已经在根目录下保存了admin文件,里面有需要的认证信息

      /root/.kube/config    需要认证的信息在该文件中保存

在K8S中kubectl是可以远程使用的,只需要在目标主机安装好kubectl并把认证相应的包拷贝到对应主机上就可以正常使用,一般来说目标主机上会有个kubectl-proxy守护进程

举例:

          kubectl-proxy一般监听在127.0.01:8080上

原理是由kubectl-proxy反向代理至apiserver中,目标主机和kubectl-proxy之间不需要认证,认证交给kubectl-proxy和apiserver之间进行
在K8S中所有的访问信息以及创建部署等方式都是采用Request path方式来进行的,也就是利用访问各种API接口的方式来控制K8S,格式是http格式的

    API
      Request path
            http://127.0.0.1:6443/apis/apps/v1/namespace/default/deployments/myapp-deploy

举例用kubectl监听一个端口后通过该端口进行访问查询kubernetes中的资源:

            kubectl proxy --port=8080       #监听目标主机的8080端口

验证是否成功:

[root@master ~]# netstat -ntpl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
            tcp        0      0 127.0.0.1:8080          0.0.0.0:*               LISTEN      20997/kubectl 

如果监听成功,查询端口时会出现以上信息
然后使用Request path查询k8s中多少个namespace以及相关信息

curl http://localhost:8080/api/v1/namespaces

对于所有的K8S来讲都起源于一个根也就是apis,api的复数,上面之所以可以使用api/v1是因为他是一个特殊链接,只有核心群组才有这样的访问逻辑,其他群组只要不是核心群组的,只要不是第一群组的都必须要起始于apis

举例:

格式:apis/组名/版本/namespaces/kube-system/deployments   #namespaces是固定关键词不可更改

下方是查询kube-system下deployment控制器列表等同于kubectl get deploy -n kube-system,相比kubectl的显示的信息更全面

curl http://localhost:8080/apis/apps/v1/namespaces/kube-system/deployments

如果不想看对象列表,只想看该控制器下的pod,例如:

curl http://localhost:8080/apis/apps/v1/namespaces/kube-system/deployments/coredns

一般来说http的请求包括:

http request verb:
     get、post、put、delete

一般对于K8S支持的请求:

API requets verb:
    get、list、create、update、patch、watch、proxy、redirect、delete、deletecollectio......

请求访问某个资源一般来说是指某个资源的ID:

Resoure:     资源的ID,资源的名称
Subresoure:  子资源
Namespace:   
API GROUP

K8S认证API的账号分为两类,

      第一类、现实中的客户端认证      userAccount
      第二类、就是Pod客户端认证       serviceAccount

每一个Pod运行时都需要与APIServer打交道,在每个名称空间创建完成后或者默认的名称空间都会存在一个名为default-token-*的一个认证token,表示该命名空间的所有Pod资源试图访问APIService时隐藏的预置的一个认证信息,因此在此命名空间的所有Pod都能直接联系APIServer,但是此secret仅仅只是获取当前Pod自身的相关属性,不能随意观看别人的,默认的secret权限比较小,因此可以自己手动定义secret,也就是手动创建个serviceAccent

serviceAccent:token认证
我这里是使用的CTL的形式创建的,因为CTL创建比较简单,

kubectl create serviceaccount admin

创建完成后会自动生成一个token信息

  [root@master ~]# kubectl describe sa admin
  Name:                admin
  Namespace:           default
  Labels:              <none>
  Annotations:         <none>
  Image pull secrets:  <none>
  Mountable secrets:   admin-token-wr8kl
  Tokens:              admin-token-wr8kl
  Events:              <none>

且该命名空间也会多一个名为admin的token信息

  [root@master ~]# kubectl get sa 
  NAME      SECRETS   AGE
  admin     1         4m50s
  default   1         33d

下面创建的是以上面的sa为基础

举例:

apiVersion: v1
kind: Pod
metadata:
  name: pod-sa-demo
  namespace: default
  labels:
    app: myapp
    tier: frontend
  annotations:
    master/created-by: "cluster admin"
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    ports:
    - name: http
      containerPort: 80
  serviceAccountName: admin       #与上方sa相对应

生产环境中,我们把配置清单提交给APIServer时,API告诉集群中的kubelet,node节点需要创建并运行一个Pod,而Pod中的容器启动要依赖于一个私有仓库中的镜像时,此时这个镜像如果需要下载
那么这个私有仓库机器可能需要在K8S集群中认证之后才可以下载
以上认证方式可以使用imagePullSecrets来告诉这个Pod怎么去下载镜像文件,但是这种认证方式存在一些缺陷,推荐使用serviceAccountName,因为使用serviceAccountName相当于是指定了SA账号,
而这个SA可以附带认证到私有仓库Secret信息

  [root@master ~]# kubectl describe sa admin
  Name:                admin
  Namespace:           default
  Labels:              <none>
  Annotations:         <none>
  Image pull secrets:  <none>           #这个位置可以设置去哪里下载镜像文件
  Mountable secrets:   admin-token-wr8kl
  Tokens:              admin-token-wr8kl
  Events:              <none>

推荐以后Image pull secrets配置在sa上,不要配置在Pod中,然后把sa定义到Pod中,这样我们的Pod通过sa来调度Image pull secrets也能完成相关下载认证信息而且还不会泄露secret相关认证信息
kubectl config 用来管理kubectl的配置文件,所有连往APIService的客户端在认证时基于配置文件,如果要基于配置文件来保存客户端的认证信息而不是使用上方的token来提供认证信息,那么我们就应该给他配置为一个配置文件。

kubeconfig:
其实在k8S中的所有组件,除API外,像Scheduler、Controller都是API的客户端
kubeconfig:APIServer能提供正确的账号,证书,私钥或者token等信息,我们需要把这些信息保存到一个配置文件中,而这个配置文件就是kubeconfig,是APIserver的客户端,连入APIserver时使用的认证格式的客户端配置文件!而kubectl也是APIServer的客户端也有配置文件

kubectl config view #查看当前配置文件信息

    apiVersion: v1
    clusters:         #集群列表
    - cluster:
        certificate-authority-data: DATA+OMITTED      #集群证书但被隐藏了
        server: https://10.5.0.100:6443       #API的网址和端口
      name: kubernetes
    contexts:         #上下文列表
    - context:
        cluster: kubernetes
        user: kubernetes-admin
      name: kubernetes-admin@kubernetes     #改名字通常写成   用户名@集群名
    current-context: kubernetes-admin@kubernetes      #当前上下文
    kind: Config
    preferences: {}
    users:          #用户列表
    - name: kubernetes-admin
      user:
        client-certificate-data: REDACTED
        client-key-data: REDACTED

上下文:一个配置文件不单单只是让kubectl访问一个集群的,如果有多个K8S集群,而管理员只有一个KeY一个客户端主机,而这时你想控制多个集群,在传统认知里面要管理多个集群需要更换
多个账号来管理,而在K8S里面只需要先定义好kubectl的配置文件,例如我们有三个集群,一台客户端,三个用户,其中三个用户中的第一个用户账号访问第一个集群,第二个用户也是访问第一个集群
而第三个用户账号访问第二个集群和第三个集群,而要指定哪个账号访问哪个集群这时就要用到context(上下文),一个context(上下文)就是一个列表,一个context(上下文)包含用户名和一个
集群,因为一个context(上下文)就是一个列表,而确定当前使用的是哪个context(上下文),这时看配置文件中的current-context就好了
自建链接api的证书和私钥:

(umask 0777; openssl genrsa -out qwx.key 2048)

执行完这个命令后会在当前目录产生一个名为qwx.key的私钥,然后基于这个私钥来生成一个证书并且由K8S中的/etc/kubernetes/pki/ca.crt来签署
生成证书签署请求:

openssl req -new -key qwx.key -out qwx.csr -subj "/CN=qwx"    #/CN=后面是用户账号名字

签证:

openssl x509 -req -in qwx.csr -CA ./ca.crt -CAkey ./ca.key -CAcreateserial -out qwx.crt -days 3650
            -CA:指定谁来签署 -CA ./ca.crt意为由当前目录的ca.crt来签署
            -CAkey:指定签署的私钥
            -CAcreateserial:意为用ca自己的认证服务信息
            -out:保存为证书文件
            -days:签署多少天

验证签署信息:

openssl x509 -in qwx.crt -text -noout    #因为qwx.crt在当前目录所以就直接使用相对路径如果不在当前目录可以指定绝对路径
    Certificate:
    Data:
          Version: 1 (0x0)
          Serial Number:
               d8:68:be:64:ac:4c:76:19
          Signature Algorithm: sha256WithRSAEncryption
          Issuer: CN=kubernetes                         #Issuer意为谁签署的,在本次测试中是由kubernetes自己签署的,所以显示kubernetes
          Validity
            Not Before: Feb  9 06:29:19 2022 GMT      #签署的起始时间
            Not After : Feb  7 06:29:19 2032 GMT      #证书的过期时间
            Subject: CN=qwx                               #qwx作为用户账号,被k8s识别的用户身份,所以授权的时候都要授权到这个账号之上
            Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                   Public-Key: (2048 bit)
                   Modulus:
                            00:cb:45:eb:85:d3:4c:8e:46:27:d9:90:27:1a:7e:
                            4f:09:90:76:e2:8a:d8:f0:53:be:00:02:e0:54:ec:
                            81:5d:79:43:95:31:54:09:32:2e:81:7e:2d:5c:af:
                            a4:42:5a:4b:a0:8d:57:c6:e7:21:c0:0e:f9:2b:d1:
                            73:f9:bc:9a:12:21:c4:6e:64:34:3f:2b:a6:f5:36:
                            d9:e7:8d:6e:a5:cb:27:72:55:21:c5:e0:b8:95:c4:
                            27:83:5b:4b:13:c3:fe:87:1d:e8:b7:2a:14:bf:e7:
                            f0:61:f9:b7:74:ae:10:1c:fa:7c:8f:4e:64:5a:69:
                            d2:e0:d3:06:f0:73:1c:db:32:2d:15:9e:34:99:1e:
                            ab:2e:8d:5b:45:8e:79:a7:5f:d2:f7:e2:69:c9:bb:
                            79:06:dc:00:ff:9f:e7:7c:7e:a5:50:09:78:9d:e4:
                            d6:f8:57:74:be:69:be:f8:6b:b5:69:77:12:7a:1b:
                            7d:2f:17:15:3f:42:d2:d2:b0:84:8d:c7:04:72:04:
                            3d:30:2c:c5:2e:a3:16:f4:37:c0:26:9f:4a:48:45:
                            2a:8d:c4:1a:31:c8:83:86:b5:cc:61:c9:4f:43:95:
                            fc:80:9a:f5:5b:d0:7d:05:0c:10:1a:4f:62:4c:d9:
                            4e:b5:6e:de:6a:bd:01:56:6a:52:f5:fc:af:cb:ba:
                            d9:8b
                        Exponent: 65537 (0x10001)
            Signature Algorithm: sha256WithRSAEncryption
                92:8b:fc:e3:dc:65:5e:1a:15:cd:61:8c:ea:6b:06:63:f4:c5:
                a4:ea:ab:3f:77:55:4a:27:1c:7b:dd:3c:9b:0a:51:38:63:56:
                a6:04:71:ab:86:97:60:d8:66:32:95:99:7a:39:21:90:1a:07:
                5d:55:f3:8c:bd:ab:29:7c:4e:1e:4a:bc:c8:ff:73:d0:c8:10:
                34:8e:83:3b:52:63:c7:c7:fa:b3:b7:5f:9c:3f:4b:60:e4:71:
                45:88:eb:56:01:da:c8:94:63:cc:aa:4a:6d:e3:23:c3:59:d4:
                6b:4c:37:1f:fa:51:ee:c8:93:70:07:11:ff:23:18:45:ca:c4:
                d4:20:97:d2:b5:8f:34:5f:4d:4b:df:89:b5:28:b7:46:e1:6a:
                ac:41:c4:85:e4:51:37:33:41:61:b5:8a:da:ee:b2:c7:6c:41:
                d0:23:cd:d5:5c:65:4f:f5:f8:8e:68:d2:0b:68:2c:c3:fa:23:
                bc:94:84:2c:0b:e4:45:3c:4f:fa:b3:5e:64:ec:fb:d2:58:8d:
                74:89:68:39:c7:33:0d:60:11:6c:68:3f:c9:9c:2a:92:7b:a6:
                ea:f6:ef:09:c1:b2:fc:4f:d0:6c:a6:56:72:d1:e4:ad:ca:1d:
                a4:b2:e8:e3:10:ef:c1:7a:67:e4:2c:5b:8a:52:c9:de:70:43:
                63:0b:21:83

将qwx用户添加到kubectl配置文件中:

查询当前kubectl配置信息

       [root@master ~]# kubectl config view
        apiVersion: v1
        clusters:
        - cluster:
            certificate-authority-data: DATA+OMITTED
            server: https://10.5.0.100:6443
          name: kubernetes
        contexts:
        - context:
            cluster: kubernetes
            user: kubernetes-admin
          name: kubernetes-admin@kubernetes
        current-context: kubernetes-admin@kubernetes
        kind: Config
        preferences: {}
        users:
        - name: kubernetes-admin
          user:
            client-certificate-data: REDACTED
            client-key-data: REDACTED 

因为测试阶段没有多余集群,所以还是使用当前集群,此处只需要添加contexts(上下文)和user(用户)
以CLI的形式来添加用户:

命令格式:

        kubectl config set-credentials NAME [--client-certificate=path/to/certfile] [--client-key=path/to/keyfile]
        [--token=bearer_token] [--username=basic_user] [--password=basic_password] [--auth-provider=provider_name]
        [--auth-provider-arg=key=value] [--exec-command=exec_command] [--exec-api-version=exec_api_version] [--exec-arg=arg]
        [--exec-env=key=value] [options]

证书形式认证:

        --client-certificate=path/to/certfile: 客户端证书
        --client-key=path/to/keyfile :客户端密钥

token(令牌)形式认证:

        --token=bearer_token:令牌

账号密码认证:

        --username=basic_user:指定用户名
        --password=basic_password:指定密码

其中[options]选项中有个--embed-certs=true意为隐藏证书和密钥,把true改为false或者不添加该参数意为不隐藏

当前测试是用证书形式:

        kubectl config set-credentials qwx --client-certificate=./qwx.crt --client-key=./qwx.key --embed-certs=true

命令反馈:

User "qwx" set.  #意为操作成功

以CLI的形式来添加上下文:

参数:

Options:
  --current=false: Modify the current context   #修改当前上下文,把false改为true

命令格式:

kubectl config set-context [NAME | --current] [--cluster=cluster_nickname] [--user=user_nickname][--namespace=namespace] [options]
指定集群名字
    --cluster=cluster_nickname
指定用户名字:
    --user=user_nickname
 绑定名称空间:
     --namespace=namespace
 添加上下文:
     kubectl config set-context qwx@kubernetes --cluster=kubernetes --user=qwx

如果想添加上下文的同时,执行修改当前上下文:

kubectl config set-context qwx@kubernetes --cluster=kubernetes --user=qwx --current=true qwx@kubernetes

把当前context(上下文)更改为刚才创建的qwx@kubernetes也可以被称为切换用户:

kubectl config use-context qwx@kubernetes     #qwx@kubernetes就是上方创建的context
运行kubectl config view查看结果:
        apiVersion: v1
        clusters:
        - cluster:                            #集群不变
            certificate-authority-data: DATA+OMITTED
            server: https://10.5.0.100:6443
          name: kubernetes
        contexts:
        - context:
            cluster: kubernetes
            user: kubernetes-admin
          name: kubernetes-admin@kubernetes
        - context:                            #新添加的context
            cluster: kubernetes
            user: qwx
          name: qwx@kubernetes
        current-context: qwx@kubernetes
        kind: Config
        preferences: {}
        users:
        - name: kubernetes-admin
          user:
            client-certificate-data: REDACTED
            client-key-data: REDACTED
        - name: qwx                           #新添加的用户
          user:
            client-certificate-data: REDACTED
            client-key-data: REDACTED

虽然已经创建用户,但是仅仅是一个普通用户账号,没有管理员权限

添加新的集群:

        Options:
          --embed-certs=false: 和上方添加用户中的--embed-certs=false一致

          # 设置新集群中的API地址
          kubectl config set-cluster NAME --server=https://1.2.3.4

          # 嵌入新集群的ca证书,也就是集群中master的/etc/kubernetes/pki/ca.crt
          kubectl config set-cluster NAME --certificate-authority=~/.kube/e2e/kubernetes.ca.crt --embed-certs=true

以上两条命令结合为一个例如:

              kubectl config set-cluster NAME --server="https://IP:Port" --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true

以上都是把所有操作保存在kubectl默认配置文件中了,如果不想保存到默认文件中,查看以下操作:
执行命令时使用--kubeconfig参数指定要使用的文件名路径即可。

例如:

          kubectl config set-cluster mycluster --kubeconfig=/tmp/test.conf --server="https://10.5.0.100:6443" --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true

这条命令意为创建一个cluster,并将配置文件保存到/tmp/test.conf文件中,且隐藏该证书信息
测试命令是否执行完成:

          kubectl config view --kubeconfig=/tmp/test.conf
          apiVersion: v1
          clusters:
          - cluster:
              certificate-authority-data: DATA+OMITTED
              server: https://10.5.0.100:6443
            name: mycluster
          contexts: []
          current-context: ""
          kind: Config
          preferences: {}
          users: []

查询得知刚才创建的集群和不保存到默认配置文件中成功
以上是如何自定义证书使用kubectl认证接入到APIServer中的

K8S中有多个授权插件:

  Node、ABAC、RBAC、Webhook、RBAC
  RBAC:Role-based AC   
最后修改:2023 年 06 月 09 日
如果觉得我的文章对你有用,请随意赞赏