[TOC]

根据马哥教育k8s教程学习。

k8s学习大纲
    - 基础大纲
    - 集群部署及陈述式命令管理
    - 资源类型及配置清单
    - pod资源
    - pod 控制器
    - service资源
    - 存储卷
    - configmap与secret资源
    - statefulset控制器
    - 认证、授权及准入控制
    - 网络模型及网络策略
    - pod资源调度
    - crd、自定义资源、自定义控制器及自定义API server, cni=Custom/Container Network Interface, crd=CustomResourceDefinition, CRI=Container Runtime Interface
    - 资源指标与HPA控制器
    - Helm管理器
    - 高可用kubernetes

Cloud Native Apps: 云原生应用,程序开发出来就是运行在云平台上,而非单机上的应用。
Serverless: 与云原生应用组合,成为新的发展趋势,FaaS。 Knative。

单体应用程序: 亦称巨石应用,牵一发而动全身。
分成架构服务: 每个团队维护一个层次。(比如用户,商品,支付)
微服务(Microservice): 服务拆分成多个小功能,单独运行。
    - 服务注册和服务发现: 分布式和微服务存在的问题
    - 三五个程序运行支撑的服务转变为 三五十个微型服务,服务之间的调用成为网状结构。
    - 非静态配置,动态服务发现,服务总线
    - 服务编排系统: 解决运维部署难的问题
    - 容器编排系统: 解决系统异构,服务依赖环境各不相同。 服务编排系统 --> 容器编排系统

容器编排系统: (主流: k8s, Borg, Docker Swarm, Apache Mesos Marathon DC/OS )
    what is container orchestration?
    - container orchestration is all about managing the lifecycles of containers, especially in large, dynamic environments.
    - software teams use container orchestration to control and automade many task:
        - provisioning and deployment of containers
        - redundancy and availability of containers
        - scaling up or removing containers to spread application load evently across host infrastructure
        - movement of containers from one host to another if there is a shortage of resources in host, or if a host dies.
        - allocation of resources between containers
        - exteral exposure of services running in a container with the outside world
        - load balancing of service discovery between containers
        - heath monitoring of containers and hosts
        - configuration of an application in relation to the containers runing it

    简单来说,容器编排是指容器应用的自动布局、协同及管理,它主要负责完成以下具体内容:
    service discovery
    load balancing
    secrets/configuration/storage management
    heath checks
    auto-[scaling/restart/healing] of containers and nodes
    zero-downtime deploys

- pod资源

- pod 控制器:
    pod创建方式:
        - 自助式pod: 直接创建pod
        - 由控制器管理pod: 创建deployment,service等

    ReplicationControler: 

    ReplicaSet/rs: 
        - 副本数
        - 标签选择
        - pod资源摸版

        - kubectl explain rs
        - kubectl explain rs.spec
            - replicas
            - selector
            - template

    Deployment: 无状态任务,关注群体行为. 只关注数量,不关注个体.
        - kubectl explain deploy.spec
            - replicas
            - selector
            - template
            - strategy: 更新策略 
                - rollingUpdate
                    - maxSurge: 最多超出目标pod数量 1/20%
                    - maxUnavailable: 最多不可用数量. 1/80%
                - type
                    - Recreate
                    - rollingUpdate

            - minReadySeconds
            - revisionHistoryLimit: 保存历史版本数量限制

    DaemonSet/ds: 每个node节点只运行一个,eg:ELK.
        - kubectl explain ds.spec
            - selector
            - template

            - minReadySeconds
            - revisionHistoryLimit: 保存历史版本数量限制
            - updateStrategy

    Service:
        工作模式: userspace, iptables, ipvs. (kube-proxy)
            userspace: 1.1-
            iptables: 1.10-
            ipvs: 1.11+

        - NodePort/ClusterIP : client --> NodeIP:NodePort --> ClusterIP:ServicePort --> PodIP:containerPort
            - LBAAS(LoadBalancerAsAService): 公有云环境中.
            - LoadBalancer
            - ExternalName
                - FQDN
                    - CNAME -> FQDN
        - No ClusterIP: Headless Service
            - ServiceName -> PodIP

        - kubectl explain svc
            - type: ExternalName, ClusterIP, NodePort, LoadBalancer
            - port:
                - NodePort # type=NodePort 时 可用. client --> NodeIP:NodePort --> ClusterIP:ServicePort --> PodIP:containerPort
                    - LBAAS(LoadBalancerAsAService): 公有云环境中.
                    - LoadBalancer
                    - ExternalName
                        - FQDN
                            - CNAME -> FQDN
                    - 
                - port
                - targetPort

    Ingress:
        Service: ingress-nginx  (NodePort, DaemonSet - HostNetwork)
        IngressController: ingress-nginx
        Ingress: 
            - site1.ikubernetes.io (virtual host)
            - site2.ikubernetes.io (virtual host)
            - example.com/path1
            - example.com/path2

        - Service: site1
            - pod1
            - pod2

        - Service: site2
            - pod3
            - pod4

- 存储卷
    - emptyDir
        - 临时目录, 内存使用, 没有持久性
        - gitRepo

    - hostPath

    - 共享存储
        - SAN: iSCSI
        - NAS: nfs, cifs, http
        - 分布式存储: 
            - glusterfs
            - ceph: rbd
            - cephfs:
        - 云存储
            - EBS
            - Azure Disk
    - pvc: persistentVolumeClaim  
        - pv
        - pvc
        - pod - volumes  - 

    - secret
        base64 的 configmap 

    - configmap: 配置中心
        配置容器化应用的方式:
            1. 自定义命令行参数;
                args: []
            2.把配置文件直接copy进镜像
            3.环境变量
                1.Cloud Native的应用程序一般可直接通过环境变量加载配置
                2.通过entrypoint.sh脚本来预处理变量为配置文件中的配置信息
            4.存储卷

        - 变量注入 --> pod 读取变量
        - 挂载存储卷 --> pod 读取配置
        - 自定义命令行参数

- StatefulSet:
    PetSet -> StatefulSet
    应对有以下要求的服务:
        1.稳定且唯一的网络标识符
        2.稳定且持久的存储
        3.有序平滑的部署和扩展
        4.有序平滑的删除和终止
        5.有序的滚动更新

    三个组件:
        - headless service: clusterIP: None
        - StatefulSet
        - volumeClaimTemplate

- 认证、授权及准入控制
    - Authentication
        - restful API: token
        - tls: 双向认证
        - user/password

    - Authorization
        - rbac
            - role
            - rolebinding
            - ClusterRole
            - ClusterRoleBinding

        - webhook
        - abac

    - Admission Control

    client --> API Server
        pod --> api server
            - ServiceAccount?
                - secret
                - ServiceAccountName
                kubectl get secret
                kubectl get sa | serviceaccount
                kubectl create serviceaccount my-sa -o yaml --dry-run
                kubectl get pods myapp -o yaml --export

        API request path: http://IP:port/apis/apps/v1/namespaces/default/deployments/myapp-deploy/
        http request ver:
            get, post, put, delete
        http request --> API requests verb:
            get, list, create, update, patch, watch, proxy, redirect, delete, delectcollection
        Resource:
        Subresource:
        Namespace:
        API group:

    - ServiceAccount:
        alex.crt
        (umask 077; openssl genrsa -out alex.key 2048)
        openssl req -new -key alex.key -out alex.csr -subj "/CN=alex"
        openssl x509 -req -in alex.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out alex.crt -days 3650
        openssl x509 -in alex.crt -text -noout

        kubectl config set-cluster alex-cluster --server="https://192.168.137.131:6443" --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --kubeconfig=/tmp/alex.conf
        kubectl config set-credentials admin \
          --client-certificate=datasets/work/admin/admin.pem \
          --client-key=datasets/work/admin/admin-key.pem \
          --embed-certs=true \
          --kubeconfig=/tmp/alex.conf

        kubectl config set-context alex@kubernetes --cluster=kubernetes --user=admin --kubeconfig=/tmp/alex.conf
        kubectl config use-context kubernetes --kubeconfig=/tmp/alex.conf
        kubectl get pods --kubeconfig=/tmp/alex.conf (error from server forbidden)

    - RBAC
        - role, clusterrole
            object:
                resource group
                resource
                non-resource url

            action:
                get, list, watch, patch, delete, deletecollection, ...

        - rolebinding, clusterrolebinding
            subject:
                user
                group
                serviceaccount

            role:

        - role:
            - operations
            - objects

        - rolebinding:
            - user account or service account
            - role

        - clusterrole

        - clusterrolebinding

        # kubectl create role --help
        # kubectl create rolebinding --help
        # kubectl create role pods-reader --verb=get,list,watch --resource=pods --dry-run=client -o yaml
            apiVersion: rbac.authorization.k8s.io/v1
            kind: Role
            metadata:
              creationTimestamp: null
              name: pods-reader
              namespace: default
            rules:
            - apiGroups:
              - ""
              resources:
              - pods
              verbs:
              - get
              - list
              - watch
        # kubectl create rolebinding alex-read-pods --role=pods-reader --user=alex --dry-run=client -o yaml
            apiVersion: rbac.authorization.k8s.io/v1
            kind: RoleBinding
            metadata:
              creationTimestamp: null
              name: alex-read-pods
            roleRef:
              apiGroup: rbac.authorization.k8s.io
              kind: Role
              name: pods-reader
            subjects:
            - apiGroup: rbac.authorization.k8s.io
              kind: User
              name: alex

        # 接着上面 ServiceAccount 的例子
        # kubectl config use-context kubernetes --kubeconfig=/tmp/alex.conf
        # kubectl get pods --kubeconfig=/tmp/alex.conf
        # kubectl get pods -n kube-system --kubeconfig=/tmp/alex.conf  (error from server forbidden)

        # kubectl create clusterrole --help
        # kubectl create clusterrolebinding --help

    - Kubernetes Dashboard
        - helm install kubernetes-dashboard/kubernetes-dashboard --version 2.3.0 --name=k8s-dashboard [--namespaces=dashboard]
            - helm fetch kubernetes-dashboard/kubernetes-dashboard --version 2.3.0
            - tar xf kubernetes-dashboard-2.3.0.tgz
            - vim kubernetes-dashboard/values.yaml
            - helm install kubernetes-dashboard/kubernetes-dashboard --version 2.3.0 --name=k8s-dashboard -f kubernetes-dashboard/values.yaml [--namespaces=dashboard]
        - kubectl create clusterrolebinding k8s-dashboard-admin --clusterrole=cluster-admin --serviceaccount=default:k8s-dashboard  / [--serviceaccount=dashboard:k8s-dashboard]
        - kubectl describe sa k8s-dashboard [-n dashboard]
        - kubectl describe secret k8s-dashboard-token-xxxx [-n dashboard]

- 网络模型及网络策略
    flannel
        kubectl get daemonset -n kube-system
        kubectl get pods -o wide -n kube-system |grep -i kube-flannel
        kubectl get configmap -n kube-system
        kubectl get configmap kube-flannel-cfg -o json -n kube-system

        from 10.244.1.59 ping 10.244.2.76
        tcpdump -i cni0 -nn icmp
        tcpdump -i flannel.1 -nn
        tcpdump -i ens32 -nn host 192.168.137.131
            overlay otv

    calico

- pod资源调度
    调度器:
        预选策略:
        优先函数:

    节点选择器: nodeSelector, nodeName
    节点亲和调度: nodeAffinity
    taint的effect定义对Pod排斥效果:
        NoSchedule:仅影响调度过程,对现存的Pod对象不产生影响;
        NoExecute:既影响调度过程,也影响现在的Pod对象;不容忍的Pod对象将被驱逐;
        PreferNoSchedule:

- crd、自定义资源、自定义控制器及自定义API server
    - HeapSter (数据采集)
        - cAdvisor (数据指标检测)
        - InfluxDB (历史数据记录: 时序数据库系统)
        - Grafana (数据展示)
        - RBAC

    资源指标: 
        metrics-server: k8s资源聚合器

    自定义指标: 
        - prometheus
        - k8s-prometheus-adapter 

        - MertricServer
        - PrometheusOperator
        - NodeExporter
        - kubeStateMetrics
        - Prometheus
        - Grafana

    新一代架构:
        核心指标流水线:
            由kubelet、metrics-server以及由API server提供的api组成;CPU累积使用率、内存实时使用率、Pod的资源占用率及容器的磁盘占用率;
        监控流水线:
            用于从系统收集各种指标数据并提供终端用户、存储系统以及HPA,它们包含核心指标及许多非核心指标。非核心指标本身不能被k8s所解析,

    metrics-server:
        API server

- Helm管理器: chart repository
    Tiller:
    chart: 
        - 配置清单
        - 模板文件
        - 
helm install mem1 stable/memcached

# kubectl explain ingress.spec
FIELDS:
    backend  <Object>
        resource <Object>
        serviceName  <string>
        servicePort  <string>

    ingressClassName <string>

    rules    <[]Object>
        host    <string>
        http    <Object>
            paths   <[]Object> -required-
                backend  <Object> -required-
                path <string>
                pathType <string>

    tls  <[]Object>

    Ingress Controller:
        - Nginx
        - Traefik
        - Envoy

    namespace: ingress-nginx

    Job: 一次性任务
    Cronjob: 周期性任务

    StatefulSet: 关注个体. 对
    EDR: Custom Defined Resources, 1.8+
    Operator: etcd 

    example:
        - # ReplicaSet
            - vim rs-demo.yaml
                apiVersion: apps/v1
                kind: ReplicaSet
                metadata:
                    name: myapp
                    namespace: default
                spec:
                    replicas: 2
                    selector:
                        matchLabels:
                            app: myapp
                            release: canary
                    template:
                        metadata:
                            name: myapp-pod
                            labels:
                                app: myapp
                                release: canary
                                environments: qa
                        sepe:
                            containers:
                            - name: myapp-container
                              image: ikubernetes/myapp:v1
                              ports:
                              - name: http
                                containerPort: 80
            - kubectl create -f rs-demo.yaml
            - kubectl edit rs myapp  --> replicas: 5
            - kubectl get pods
            - kubectl edit rs myapp  --> image: ikubernetes/myapp:v2
            - kubectl get rs -o wide 
            - curl xx.xx.xxx.xx # 只有重建的pod会使用新的image

        - # Deployment
            - vim deploy-demo.yaml
                apiVersion: apps/v1
                kind: Deployment
                metadata:
                    name: myapp-deploy
                    namespace: default
                spec:
                    replicas: 2
                    selector:
                        matchLabels:
                            app: myapp
                            release: canary
                    template:
                        metadata:
                            name: myapp-pod
                            labels:
                                app: myapp
                                release: canary
                                environments: qa
                        sepe:
                            containers:
                            - name: myapp-container
                              image: ikubernetes/myapp:v1
                              ports:
                              - name: http
                                containerPort: 80
            - kubectl apply -f deploy-demo.yaml
            - kubectl get deploy
            - kubectl get rs -o wide 
                myapp-deploy-69b47bc96d --> 模板的hash值
            - kubectl get pods
            - kubectl get pods -l app=myapp -w # 新开窗口
            - vim deploy-demo.yaml  --> image: ikubernetes/myapp:v2
            - kubectl apply -f deploy-demo.yaml
            - kubectl get rs -o wide 
            - kubectl rollout history deployment myapp-deploy
            # 打补丁方式增加pod
            - kubectl patch deployment myapp-deploy -p '{"spec":{"replicas":5}}'
            - kubectl get pods

            - kubectl patch deployment myapp-deploy -p '{"spec":{"strategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":0}}}}'
            - kubectl describe deployment myapp-deploy
            - kubectl get pods -l app=myapp -w  # 新开窗口-1
            - kubectl set image deployment myapp-deploy myapp=ikubernetes/myapp:v3 && kubectl rollout pause deployment myapp-deploy # 暂停rollout, 金丝雀发布
            - kubectl rollout status deployment myapp-deploy  # 新开窗口-2
            - kubectl rollout resume deployment myapp-deploy --> # 查看新开窗口 1, 2
            - kubectl rollout history deployment myapp-deploy # 查看历史版本
            - kubectl get rs -o wide

            # 回滚版本
            - kubectl rollout undo --help
            - kubectl rollout undo deployment myapp-deploy --to-revision=1
            - kubectl rollout history deployment myapp-deploy # 查看历史版本

        - # DaemonSet
            - vim ds-demo.yaml
                apiVersion: apps/v1
                kind: Deployment
                metadata:
                  name: redis
                  namespaces: default
                spec:
                  replicas: 1
                  selector:
                    matchLabels:
                      app: redis
                      role: logstor
                  template:
                    metadata:
                      labels:
                        app: redis
                        role: logstor
                    spec:
                      containers:
                      - name: redis
                        image: redis:4.0-alpine
                        ports:
                        - name: redis
                          containerPort: 6379
                ---
                apiVersion: apps/v1
                kind: DaemonSet
                metadata:
                    name: filebeat-ds
                    namespace: default
                spec:
                    replicas: 2
                    selector:
                        matchLabels:
                            app: filebeat
                            release: stable
                    template:
                        metadata:
                            name: filebeat-pod
                            labels:
                                app: filebeat
                                release: stable
                        sepe:
                            containers:
                            - name: filebeat
                              image: ikubernetes/filebeat:5.6.5-alphine
                              env:
                              - name: REDIS_HOST
                                value: redis.default.svc.cluster.local
                              - name: REDIS_LOG_LEVEL
                                value: info
            - kubectl apply -f ds-demo.yaml
            - kubectl get pods
            - kubectl expose deployment redis --port=6379
            - kubect get svc
            - kubectl exec -it redist-5bxxxx-xxx -- /bin/sh
                # netstat -tnl
                # nslookup redis.default.svc.cluster.local
                # redis-cli -h redis.default.svc.cluster.local
                # kyes * 

            # DaemonSet 滚动更新
            - kubectl set image demonsets filebeat-ds filebeat=ikubernets/filebeat-5.6.6-alphine
            - kubectl get pods -w  # 一个一个的更新.

        - # Service 
            - vim redis-svc.yaml
                apiVersion: v1
                kind: Service
                medatada:
                  name: redis
                  namespace: default
                spec:
                  selector: 
                    app: redis
                    role: logstor
                  # clusterIP: 10.96.96.96
                  type: ClusterIP
                  port: 
                  - port: 6349
                    targetPort: 6379
            - kubectl apply -f redis-svc.yaml
            - kubectl get svc
            - kubectl describe svc redis
            - 

        - curl xx.xx.xxx.xx # 只有重建的pod会使用新的image

- service资源

Helm: like Linux yum/apt/apk ... 

k8s Server
    Master
        API Server
            - port: 6443
            - auth: 双向认证, /etc/kubernetes/pki 
            - config: ~/.kube/config
            - kubectl config view
            - restful api
                - kubectl api-versions
                - json
                - kubectl get pod == curl https://master:6443/v1/...

            - communicate with all the service
                - kubectl
                - kube-controller-manager
                - kube-scheduler
                - etcd
                - kubelet
                - kube-proxy

            - api 接口中的资源分成多个逻辑组合 apiVersion
            - 和解循环(Reconciliation Loop): status --> spec

        Scheduler

        Controller
            - 和解循环(Reconciliation Loop): status --> spec

    Node:
        - pod
        - service -> iptables/ipvs -> kube-proxy
        - kube-proxy

    Resource
        资源有两个级别: 
            - 集群级别
                - Node
                - Namespace
                - Role
                - ClusterRole
                - RoleBinding
                - ClusterRoleBinding
                - PersistentVolume

            - 名称空间级别
                - pod
                - service
                - deploy

            - 元数据型资源
                - HPA
                - PodTemplate
                - LimitRange

        资源组成部分:
            - apiVersion: group/version (kubectl api-versions)
            - kind: 资源类别
            - metadata
            - spec: 资源期望状态
                - labels/tag: kubectl label
                - annotations: kubectl annotate 
                - initContainers: kubectl explain pods.spec.initContainers: 容器初始化, 运行前, 运行后, 运行时 (存活检测, 就绪检测)
                    - lifecycle
                    - livenessProbe
                    - readinessProbe
                    - startupProbe
                    - 
                - Containers: kubectl explain pods.spec.Containers: 容器初始化, 运行前, 运行后, 运行时 (存活检测, 就绪检测)
                    - lifecycle: preStart hook, preStop hook
                    - livenessProbe
                    - readinessProbe
                    - startupProbe

                    - name:
                    - command: ["/bin/bash" "-c" "sleep 3600"]
                    - args: 
                    - image:
                    - imagePullPolicy: 
                        - Never
                        - Always
                        - IfNotPresent
                    - port:
                        - name:
                        - hostIP:
                        - hostPort:
                        - protocol
                        - containerPort

            - status: 资源当前状态

        资源引用Object URL:
            /apis/<GROUP>/<VERSION>/namespaces/<NAMESPACE_NAME>/<KIND>[/OBJECT_ID]/
            - /api/GROUP/VERSION/namespaces/NAMESPACE/TYPE/NAME
            - kubectl get pod/nginx-ds-s4hpn
                - selfLink: /api/v1/namespaces/default/pods/nginx-ds-s4hpn

        资源记录:
            SVC_NAME.NS_NAME.DOMAIN.LTD.

            redis.default.svc.cluster.local

        - Pod
        - Pod Controller
            - Deployment: 类型 --> ngx-deploy --> nginx pod
        - Service
            - nginx-svc --> 关联到 nginx pod

    kubeadm

    kubectl
    - kubectl explain pods.spec.initContainers
    - kubectl -h
        - basic commands beginner
            - create
            - expose
            - run
            - set

        - basic commands intermediate
            - explan
            - get 
            - edit
            - delete
        
        - deploy commands
            - rollout
            - scale 
            - autoscale

        - cluster management commands
            - certificate
            - cluster-info
            - top
            - cordon
            - uncordon
            - drain
            - taint

        - troubleshooting and debugging commands
            - describe
            - logs
            - attach
            - exec: kubectl exec -it PodName -c ContainerName -- /bin/sh 
            - port-forward

    - kubectl config view [-o wide/json/yaml]
        # kubectl config view
        apiVersion: v1
        clusters:
        - cluster:
            certificate-authority-data: DATA+OMITTED
            server: https://192.168.137.131: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

    - kubectl api-resources: 支持的资源类型 以及缩写
    - kubectl get  [-o wide/json/yaml] [-n default/kube-system/...] [-L label-name] [-l label-name ==/!= label-value]
        - all
        - nodes
        - pods
        - ns/namespace
            - default
            - kube-public
            - kube-system
        - deploy
        - svc/service

    - kubectl create [ -f file]
        - job
        - namespace
            - kubectl create namespace testing
            - kubectl create namespace prod
            - kubectl create namespace develop
            - kubectl get ns
            - kubectl delete namespace testing
            - kubectl delete ns/prod ns/develop

        - deployment
            - kubectl create deployment nginx-deploy --image=nginx:1.14-alpine
            - kubectl get all -o wide
                - pod/nginx-deploy-xxxx (ip: 10.244.1.2)
                - deployment.apps/nginx-deploy
                - replicaset.apps/nginx-deploy-xxxx
            - curl 10.244.1.2  ( welcome nginx!)
            - kubectl delete pod/nginx-deploy-xxxx
            - kubectl get all -o wide
                - pod/nginx-deploy-xxxx (ip: 10.244.3.2)
                ...
            - curl 10.244.3.2  ( welcome nginx!)

        - service
            - kubectl create service -h
                - ClusterIP
                - NodePort

            - kubectl create service clusterip nginx-deploy --tcp=80:80 (名字和上面deploy保持一致,就会自动分配IP)
            - kubectl get svc/nginx-deploy -o yaml 
                - clusterip: 10.110.129.64
                - endpoints: 10.244.3.2

            - kubectl describe svc/nginx-deploy

            # 删除 pod 测试
            - curl 10.110.129.64  ( welcome nginx!)
            - kubectl delete pod/nginx-deploy-xxxx
            - kubectl get all -o wide
                - pod/nginx-deploy-xxxx (ip: 10.244.1.3)
                ...

            - kubectl get svc/nginx-deploy -o yaml 
                - clusterip: 10.110.129.64
                - endpoints: 10.244.1.3 (自动关联到最新的pod)

            # 删除 service 测试
            - curl nginx-deploy.default.svc.cluster.local.  ( welcome nginx!)
            - kubectl delete svc/nginx-deploy
            - kubectl create service clusterip nginx-deploy --tcp=80:80 (名字和上面deploy保持一致,就会自动分配IP)
            - kubectl describe svc/nginx-deploy -o yaml 
                - clusterip: 10.111.215.249
                - endpoints: 10.244.3.2
            - curl nginx-deploy.default.svc.cluster.local. ( welcome nginx!)

            # 按需伸缩 pod 测试
            - kubectl create deploy myapp --image=ikubernetes/myapp:v1
            - kubectl get deploy
            - kubectl get pods -o wide 
                - ip : 10.244.3.3
            - curl 10.244.3.3
            - curl 10.244.3.3/hostname.html  (show the pod name: myapp-xxxx-yyyy)

            - kubectl create service clusterip myapp --tcp=80:80
            - kubectl describe svc/myapp
                - IP 10.100.182.218
                - Endpoints: 10.244.3.3

            - curl nginx-deploy.default.svc.cluster.local.  ( welcome myapp!)
            - curl nginx-deploy.default.svc.cluster.local/hostname.html  (show the pod name: myapp-xxxx-yyyy)
            - kubectl scale --replicas=3 myapp (deploy name)

            - kubectl describe svc/myapp
                - IP 10.100.182.218
                - Endpoints: 10.244.3.3, 10.244.1.4, 10.244.2.2

            - curl nginx-deploy.default.svc.cluster.local/hostname.html  (随机显示不同IP的pod name,多次重复执行查看效果)
            - kubectl scale --replicas=2 myapp

            - kubectl describe svc/myapp
                - IP 10.100.182.218
                - Endpoints: 10.244.3.3, 10.244.1.4

            # nodeport 外网访问
            - kubectl delete svc/myapp
            - kubectl create service nodeport -h
            - kubectl create service nodeport myapp --tcp=80:80
            - kubectl get svc
                - ports: 80:31996/TCP 
            - 集群外部访问所有nodes的 http://nodesip:31996/hostname.html
            - 自动创建规则在每一个节点的iptables --> kube-proxy
            - ssh nodes "iptables -t nat -vnL"

        eg: 

    - kubectl expose 

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

    - kubectl label [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version]
        kubectl label pods -n dev-namespaces apptag=my-app release=stable deltag-

    - kubectl api-versions

    - kubectl describe

    Network
        - node network
        - service network: service 注册/发现
        - pod network

    外网访问:
        - Service: NodePort
        - hostport:
        - hostNetwork:

        ipvs/iptables 4 层调度器   ingress 7 层调度器