Kubernetes in Action中YAML详解

291 阅读14分钟

构建一个最基本的Pod

apiVersion: v1
kind: Pod
metadata:
   name: kubia-test
   labels:
      app: test 
spec:
   containers:
      - image: luksa/kubia
        name: kubia
        ports:
           - containerPort: 8080

构建一个最基本的命名空间NameSpaces

#打标签这个操作,一个对象可以有多个标签,多个对象多个标签间可以有重叠,namespaces命名空间可以将对象分割成一个独立且不重叠的组。
#独立并不是隔离,2个命名空间能否通信主要取决于采用的网络协议。
#kubectl create -f kubia.yaml -n custom-namespace 指定pod的命名空间,否则pod会被纳入默认defalut命名空间
apiVersion: v1
kind: Namespace
metadata:
   name: custom-namespace

构建一个包含标签选择器的Pod

#标签选择器可以根据以下条件来选择资源
#包含或不包含使用特定键的标签
#包含具有特定键和值的标签
#包含具有特定健的标签,但值与我们指定的不同
apiVersion: v1
kind: Pod
metadata:
   name: kubia-lable-v2
   labels:
      create_method: manual
      env: debug
spec:
   containers:
      - image: luksa/kubia
        name: kubia
        ports:
           - containerPort: 8080
             protocol: TCP

构建一个具有NodeSelect节点选择器的Pod

#现在假设场景如下,Node1节点主机为高性能GPU计算主机,所有需要GPU计算的pod全部往Node1上调度
#kubectl label node Node1 gpu=true 为Node1打上gpu=true标签
apiVersion: v1
kind: Pod
metadata:
   name: nodeselect-v1
sepc:
   nodeSelector:
      gpu: "true"
   containers:
      - image: luska/kubia
        name: kubia

构建一个DaemonSet

#守护副本集,定位类似于运行于Pod中的守护进程,在每个Pod中有且只能有一个。主要处理针对需要在Pod后台运行守护进程的需求
#例如网络插件的Agent,存储插件的Agent,监控系统的数据采集Agent,日志系统的数据采集Agent
apiVersion: apps/v1
kind: DaemonSet
metadata:
   name: ssd-monitor
spec:
   selector:
      matchLabels:
         app: ssh-monitor
   template:
      metadata:
         labels:
            app: ssh-monitor
      spec:
         nodeSelector:
            disk: ssd
         containers:
            - name: main
              image: luksa/ssd-monitor

构建一个存活探针

#存活探针,检测应用是否存活,支持http,TCP,exec
apiVersion: v1
kind: Pod
metadata:
   name: kubia-liveness
spec:
   containers:
      - image: luksa/kubia-unhealthy
        name: kubia
        livenessProbe:
           httpGet:
              path: /
              port: 8080
           initialDelaySeconds: 15 #第一次检测前先等待15秒,给应用启用时间

构建一个最基本的ReplicationController

#RC主要包含3部分 
#lable selector 确定RC的作用域
#replica count 指定副本个数
#pod template 指定创建pod的模板 扩缩副本个数的时候RC以此为标准生成新的pod
#伸缩RC的2种方式
#kubectl scale rc kubia --replicas=10 使用scale/kubectl edit rc kubia 使用edit调用文本编辑器直接修改副本参数
apiVersion: v1
kind: ReplicationController
metadata:
   name: kubia
spec:
   replicas: 3 #指定副本个数
   selector:
      app: kubia #标签选择器定义RC操作的对象
   template: #模板-扩缩副本个数的时候RC以此为标准生成新的pod,包含一个pod的完整定义
      metadata:
         labels:
            app: kubia #给pod打上标签,使标签选择器知道需要操作的Pod
      spec:
         containers:
            - name: kubia
              image: luksa/kubia
              ports:
                 - containerPort: 8080

构建一个最基本的ReplicaSet

#select选择器部分运用RS更强大的选择器特性也可以写作
#selector:
#   matchExpressions:
#      - key: app
#        operator: In In:label的值必须与其中一个指定的values匹配 NotIn: label的值与任何指定的values不匹配
#                  Exists:Pod必须包含一个指定名称的标签(无论值是多少),使用这个选项时不指定values
#                  DoesNotExists:Pod不得包含一个指定名称的标签(无论值是多少),使用这个选项时不指定values
 #       values:
#           - kubia
apiVersion: apps/v1
kind: ReplicaSet
metadata:
   name: kubia
spec:
   replicas: 3
   selector:
      matchLabels:
         app: kubia
   template:
      metadata:
         labels:
            app: kubia
      spec:
         containers:
            - name: kubia
              image: luksa/kubia

构建一个最基本的Job

#Job主要应对一些仅需要在某一时刻运行一次的需求,Job不会一直运行,任务完成后Pod就会退出
apiVersion: batch/v1
kind: Job
metadata:
   name: batch-job
spec:
   completions: 5 #可选参数 该Job一共会运行5次。5次均成功后退出
   parallelism: 2 #可选参数 允许该Pod以2次为周期并行运行
   template:
      metadata:
         labels:
            app: batch-job
   spec:
      restartPolicy: OnFailure
      containers:
         - name: main
           image: luksa/batch-job

构建一个最基本的Cron-Job

#带有定时任务性质的Job
apiVersion: batch/v1
kind: CronJob
metadata:
   name: batch-crond
spec:
   schedule: "0,15,30,45 * * * *"
   jobTemplate:
      spec:
         template:
            metadata:
               labels:
                  app: crond-job
            spec:
               restartPolicy: OnFailure
               containers:
                  - name: main
                    image: luksa/batch-job

构建一个最基本的Service(使用默认配置-ClusterIP)

#服务建立后,最简单的验证方法为使用kubectl exec 向任意Pod发起一个Curl请求验证是否可以正常返回
#kubectl exec kubia-5rcg6 -- curl -s http://10.109.146.47
apiVersion: v1
kind: Service
metadata:
   name: kubia-service
spec:
   sessionAffinity: ClientIP #启用节点亲和性,这将会使来自同一clientip的请求转发至同一个pod 默认为None
   ports:
      - port: 80
        targetPort: 8080
   selector:
      app: kubia

构建一个最基本的Service(使用endpoint)

apiVersion: v1
kind: Service
metadata:
   name: external-service #service和endpoint名字对应
spec: #不定义选择器,因为使用的外部服务,没pod选择
   ports:
      - port: 80

---

apiVersion: v1
kind: Endpoints
metadata:
   name: external-service
subsets:
   - addresses:
     - ip: 172.17.10.2 #外部服务的地址
     ports:
        - port: 80 #端口

构建一个最基本的Service(使用nodeport)

apiVersion: v1
kind: Service
metadata:
   name: kubia-nodeport
spec:
   type: NodePort
   ports:
      - port: 80
        targetPort: 8080
   selector:
      app: kubia

构建一个最基本的就绪探针

#就绪探针,检测应用是否就绪,支持http,TCP,exec
apiVersion: v1
kind: Pod
metadata:
name: kubia-readiness
spec:
containers:
- image: luksa/kubia-unhealthy
name: kubia
readinessProbe:
 httpGet:
    path: /
    port: 8080
 initialDelaySeconds: 15 #第一次检测前先等待15秒,给应用启用时间

构建一个最基本的Headless

#在实际应用场景中,可能会遇到如下2种情况
#1· 我不想让应用走service的负载均衡,想直接访问后端pod,得到后端的真实地址。client 可以自己来决定使用哪个Real Server,可以通过查询DNS来获取 Real Server 的信息
#2· 客户端需要连接到所有Pod,而后端客户端Pod也需要连接到同属一个命名空间的其他所有Pod。Headless Service 的对应的每一个 Endpoints,即每一个Pod,都会有对应的DNS域名,这样Pod之间就可以互相访问
#基于以上情况,k8s提供了headless的服务类型
#kubectl run dnsutils --image=tutum/dnsutils --generator=run-pod/v1 --command -- sleep infinity 使用dnsutils镜像中提供的nslookup验证
#kubectl exec dnsutils nslookup kubia-headless
#172-17-0-6.kubia-headless.default.svc.cluster.local 后端默认解析到的真实DNS结构,就可以用这个DNS解析到对应的后端
apiVersion: v1
kind: Service
metadata:
   name: kubia-headless
spec:
   clusterIP: None #将clusterIP定义为None使服务成为headless
   ports:
   - port: 80
     targetPort: 8080
   selector:
         app: kubia

同时包含RC及Service

#kubectl rolling-update kubia-v1 kubia-v2 --image=luksa/kubia:v2 旧版本中可以使用rolling-update对RC进行滚动更新,新版本中已废弃
#弃用的原因在于rolling-update升级过程中太拉跨
#升级过程中,RC会先创建一个名为v2的RC,副本数量设置为0
#v1的Pod会被强制加上deployment标签
#v1的RC选择器会被强制加上一个名为deployment的标签,防止与v2冲突
#v2的副本数被设为1,同时v1的副本数-1,直至所有pod升级完成
#拉跨的原因:整个升级过程都是由kubectl客户端执行的,而不是kubernetes master。如果中间kubectl发生故障。pod和rc将处于一种中间状态。导致服务异常。
apiVersion: v1
kind: ReplicationController
metadata:
   name: kubia-v1
spec:
   replicas: 3
   template:
      metadata:
         name: kubia
         labels:
            app: kubia
      spec:
         containers:
            - image: luksa/kubia:v1
              name: nodejs
---
apiVersion: v1
kind: Service
metadata:
   name: kubia
spec:
   type: NodePort
   selector:
      app: kubia
   ports:
      - port: 80
        targetPort: 8080

创建一个emptyDir

apiVersion: v1
kind: Pod
metadata:
  name: fortune
spec:
  containers:
  - image: luksa/fortune
    name: html-generator
    volumeMounts:
    - name: html
      mountPath: /var/htdocs
  - image: nginx:alpine
    name: web-server
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
      readOnly: true
    ports:
    - containerPort: 80
      protocol: TCP
  volumes:
  - name: html
    emptyDir: {}

GCE不适用PVC直接由Pod引用持久化

apiVersion: v1
kind: Pod
metadata:
  name: mongodb 
spec:
  volumes:
  - name: mongodb-data
    gcePersistentDisk: #声明卷类型为Google GCE
      pdName: mongodb #这个名字为使用GCE命令创建的持久磁盘的名字
      fsType: ext4 #文件系统类型为ext4
  containers:
  - image: mongo
    name: mongodb
    volumeMounts:
    - name: mongodb-data #引用上面定义的GCE
      mountPath: /data/db #数据存放路径
    ports:
    - containerPort: 27017
      protocol: TCP

AWS不适用PVC直接由Pod引用持久化

apiVersion: v1
kind: Pod
metadata:
  name: mongodb-aws
spec:
  volumes:
  - name: mongodb-data
    awsElasticBlockStore:
      volumeID: my-volume
      fsType: ext4
  containers:
  - image: mongo
    name: mongodb
    volumeMounts:
    - name: mongodb-data
      mountPath: /data/db
    ports:
    - containerPort: 27017
      protocol: TCP

创建PV(MiniKube)

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mongodb-pv
spec:
  capacity: 
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
    - ReadOnlyMany
  persistentVolumeReclaimPolicy: Retain
  hostPath:
    path: /tmp/mongodb

创建PV(GCE)

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mongodb-pv
spec:
  capacity: 
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
    - ReadOnlyMany
  persistentVolumeReclaimPolicy: Retain
  gcePersistentDisk:
    pdName: mongodb
    fsType: ext4

声明PV创建PVC供Pod使用

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mongodb-pvc 
spec:
  resources:
    requests:
      storage: 1Gi
  accessModes:
  - ReadWriteOnce
  storageClassName: ""

Pod使用PVC

apiVersion: v1
kind: Pod
metadata:
  name: mongodb 
spec:
  containers:
  - image: mongo
    name: mongodb
    volumeMounts:
    - name: mongodb-data
      mountPath: /data/db
    ports:
    - containerPort: 27017
      protocol: TCP
  volumes:
  - name: mongodb-data
    persistentVolumeClaim:
      claimName: mongodb-pvc

一个最基本的Deployment

#触发滚动更新 kubectl set image deployment  kubia nodejs=luksa/kubia:v2
#触发回滚 kuebctl rollout undo deployment kubia
#查询发布历史得到版本号回滚 kubectl rollout history deployment kubia
#回滚到指定版本 kuebctl rollout undo deployment kubia --to-revision=1
#暂停滚动升级 kubectl rollout pause deployment kubia nodejs=luksa/kubia:v4 这一操作可以实现灰度发布,仅替换少数Pod资源
#恢复滚动升级 kubectl rollout resume deployment kubia
apiVersion: apps/v1
kind: Deployment
metadata:
   name: kubia
spec:
   replicas: 2
   selector:
      matchLabels:
         app: kubia
   template:
      metadata:
         name: kubia
         labels:
            app: kubia
      spec:
         containers:
            - image: luksa/kubia:v1
              name: nodejs

带有就绪探针的Deployment

#此时执行升级,因为就绪探针1秒发出一次请求,请求到第5次的因为会返回500,就绪探针返回未就绪,将Pod从service的endpoint中移除。确保用户不会访问到500的Pod,保障了服务稳定
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kubia
spec:
  replicas: 2
  selector:
      matchLabels:
         app: kubia
  minReadySeconds: 10 #设置Pod运行10s后才将其视为成功,并杀死旧Pod。开始更新下一个Pod
  strategy:
    rollingUpdate:
      maxSurge: 1 #设置升级过程中允许存在的比副本数量多出的Pod数量。例如副本数为2,maxSurge为1.则升级过程中一共会存在3个Pod,启动一个新Pod后才会删除一个旧Pod
      maxUnavailable: 0 #设置升级过程中允许有多少个Pod无法提供服务
    type: RollingUpdate
  template:
    metadata:
      name: kubia
      labels:
        app: kubia
    spec:
      containers:
      - image: luksa/kubia:v3
        name: nodejs
        readinessProbe:
          periodSeconds: 1 #就绪探针1秒执行一次
          httpGet:
            path: /
            port: 8080

创建statefulSet

#以往都是在PVC中使用persistentVolumeClaim标签引用PV,使用了一个新的volumeClaimTemplates标签
#volumeClaimTemplates标签会自动将persistentVolumeClaim加入到Pod定义中,并将PVC绑定到PV
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: kubia
spec:
  serviceName: kubia
  replicas: 2
  selector:
    matchLabels:
      app: kubia # has to match .spec.template.metadata.labels
  template:
    metadata:
      labels:
        app: kubia
    spec:
      containers:
      - name: kubia
        image: luksa/kubia-pet
        ports:
        - name: http
          containerPort: 8080
        volumeMounts:
        - name: data
          mountPath: /var/data
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      resources:
        requests:
          storage: 1Mi
      accessModes:
      - ReadWriteOnce

创建headless供statefulSet使用

apiVersion: v1
kind: Service
metadata:
  name: kubia
spec:
  clusterIP: None
  selector:
    app: kubia
  ports:
  - name: http
    port: 80

创建多个PV供stateful使用(GCE)

kind: List
apiVersion: v1
items:
- apiVersion: v1
  kind: PersistentVolume
  metadata:
    name: pv-a
  spec:
    capacity:
      storage: 1Mi
    accessModes:
      - ReadWriteOnce
    persistentVolumeReclaimPolicy: Recycle
    gcePersistentDisk:
      pdName: pv-a
      fsType: ext4
- apiVersion: v1
  kind: PersistentVolume
  metadata:
    name: pv-b
  spec:
    capacity:
      storage: 1Mi
    accessModes:
      - ReadWriteOnce
    persistentVolumeReclaimPolicy: Recycle
    gcePersistentDisk:
      pdName: pv-b
      fsType: ext4
- apiVersion: v1
  kind: PersistentVolume
  metadata:
    name: pv-c
  spec:
    capacity:
      storage: 1Mi
    accessModes:
      - ReadWriteOnce
    persistentVolumeReclaimPolicy: Recycle
    gcePersistentDisk:
      pdName: pv-c
      fsType: ext4

创建多个PV供stateful使用(MiniKube)

kind: List
apiVersion: v1
items:
- apiVersion: v1
  kind: PersistentVolume
  metadata:
    name: pv-a
  spec:
    capacity:
      storage: 1Mi
    accessModes:
      - ReadWriteOnce
    persistentVolumeReclaimPolicy: Recycle
    hostPath:
      path: /tmp/pv-a
- apiVersion: v1
  kind: PersistentVolume
  metadata:
    name: pv-b
  spec:
    capacity:
      storage: 1Mi
    accessModes:
      - ReadWriteOnce
    persistentVolumeReclaimPolicy: Recycle
    hostPath:
      path: /tmp/pv-b
- apiVersion: v1
  kind: PersistentVolume
  metadata:
    name: pv-c
  spec:
    capacity:
      storage: 1Mi
    accessModes:
      - ReadWriteOnce
    persistentVolumeReclaimPolicy: Recycle
    hostPath:
      path: /tmp/pv-c

fsgroup和supplementalGroups

#root用户享有对存储卷中的文件的全部权限,但是为了安全要求,假设现在使用了runAsUser选项限定了容器用户
#因此两个容器可能由两个不同的用户管理,k8s允许为pod内所有容器指定supplementtal组,以允许他们无论以哪个用户运行均能共享文件
apiVersion: v1
kind: Pod
metadata:
  name: pod-with-shared-volume-fsgroup
spec:
  securityContext:
    fsGroup: 555 #fsGroup用于在存储卷创建文件时起作用,设置权限文件的用户组
    supplementalGroups: [666, 777] #supplementalGroups用于定义某个用户所关联的额外的用户组
  containers:
  - name: first
    image: alpine
    command: ["/bin/sleep", "999999"]
    securityContext:
      runAsUser: 1111 #第一个容器使用1111用户
    volumeMounts:
    - name: shared-volume
      mountPath: /volume
      readOnly: false
  - name: second
    image: alpine
    command: ["/bin/sleep", "999999"]
    securityContext:
      runAsUser: 2222 #第二个容器使用2222用户
    volumeMounts:
    - name: shared-volume
      mountPath: /volume
      readOnly: false
  volumes:
  - name: shared-volume
    emptyDir:

绑定宿主机节点上的端口而不使用宿主机节点的网络命名空间

#绑定宿主机节点上的端口而不使用宿主机节点的网络命名空间
# port所暴露的是service本身的端口
# targetport暴露的是Pod端口
# containerPort暴露的是容器端口
# nodeport是向外暴露的端口,可以使应用被外部所访问
# hostport是一个特殊的port,它将容器的端口与所调度的节点上的端口路由,这样用户就可以通过宿主机的IP加上来访问Pod了
apiVersion: v1
kind: Pod
metadata:
  name: kubia-hostport
spec:
  containers:
  - image: luksa/kubia
    name: kubia
    ports:
    - containerPort: 8080 #该容器可以通过Pod IP的8080端口访问
      hostPort: 9000 #也可以通过所在节点的9000端口访问
      protocol: TCP

设置根文件系统只读,但可读写存储卷

#设置根文件系统只读,但可读写存储卷
apiVersion: v1
kind: Pod
metadata:
  name: pod-with-readonly-filesystem
spec:
  containers:
  - name: main
    image: alpine
    command: ["/bin/sleep", "999999"]
    securityContext:
      readOnlyRootFilesystem: true
    volumeMounts:
    - name: my-volume
      mountPath: /volume
      readOnly: false
  volumes:
  - name: my-volume
    emptyDir:

使用宿主机节点的PID和IPC命名空间

#使用宿主机节点的PID和IPC命名空间
apiVersion: v1
kind: Pod
metadata:
  name: pod-with-host-pid-and-ipc
spec:
  hostPID: true # 使用宿主机节点PID
  hostIPC: true # 使用宿主机节点IPC
  containers:
  - name: main
    image: alpine
    command: ["/bin/sleep", "999999"]

使用特定用户运行容器

#使用特定用户运行容器
apiVersion: v1
kind: Pod
metadata:
  name: pod-as-user-guest
spec:
  containers:
  - name: main
    image: alpine
    command: ["/bin/sleep", "999999"]
    securityContext:
      runAsUser: 405 #使用guest用户 guest用户的id是405

使用特权模式运行,获取宿主机的完整权限

#使用特权模式运行,获取宿主机的完整权限
apiVersion: v1
kind: Pod
metadata:
  name: pod-privileged
spec:
  containers:
  - name: main
    image: alpine
    command: ["/bin/sleep", "999999"]
    securityContext:
      privileged: true

以更细的粒度细分Pod可以操作的内核功能-给予内核权限

#以更细的粒度细分Pod可以操作的内核功能,特权模式权限太大
#一般情况下容器是不被允许修改系统时间的,可以通过增加SYS_TIME内核权限给予修改权限
#一般Linux内核功能一般为CAP_开头,但在yaml里省略前缀
apiVersion: v1
kind: Pod
metadata:
  name: pod-add-settime-capability
spec:
  containers:
  - name: main
    image: alpine
    command: ["/bin/sleep", "999999"]
    securityContext:
      capabilities:
        add:
        - SYS_TIME

以更细的粒度细分Pod可以操作的内核功能-拒绝内核权限

#以更细的粒度细分Pod可以操作的内核功能,特权模式权限太大
#一般情况下容器是可以修改系统所有者的的,可以通过删除CHOWN内核权限拒绝修改权限
apiVersion: v1
kind: Pod
metadata:
  name: pod-drop-chown-capability
spec:
  containers:
  - name: main
    image: alpine
    command: ["/bin/sleep", "999999"]
    securityContext:
      capabilities:
        drop:
        - CHOWN

在pod中使用宿主机节点的网络命名空间

#在pod中使用宿主机节点的网络命名空间
apiVersion: v1
kind: Pod
metadata:
  name: pod-with-host-network
spec:
  hostNetwork: true #hostNetwork: true
  containers:
  - name: main
    image: alpine
    command: ["/bin/sleep", "999999"]

只允许容器以非root用户运行

#只允许容器以非root用户运行
apiVersion: v1
kind: Pod
metadata:
  name: pod-run-as-non-root
spec:
  containers:
  - name: main
    image: alpine
    command: ["/bin/sleep", "999999"]
    securityContext:
      runAsNonRoot: true #pod会被调度,但不会被执行

创建本地storageclass自动分配持久卷

#创建本地storageclass自动分配持久卷
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: k8s.io/minikube-hostpath
parameters:
  type: pd-ssd

创建GCE自动分配持久卷

#创建GCE自动分配持久卷
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-ssd