kubernetes整理知識點


基本介紹:

編排歷史:

服務編排系統 =》容器編排系統
docker compose\swarm\docker machine
mesos,marathon
kubernets

集群節點:

聚合了所有node的cpu和內存,能自動尋找適合的node

運行單元:

pods

master組成:

APIserver接收請求放到etcd,其他如kubectl、scheduler、controller與apiserver打交道
scheduler調度,給一個pod找一個node
controller負責監控執行,有個循環loop 
etcd(保存整個集群的配置,key-value),服務端口(其他證書)和集群內通信端口(點到點證書)

node組成:

kubelet負責和master連接,注冊node, listen-watch 本node的任務等
kube-proxy用於k8s service對象,監控service的變動,變為當前node的iptables
container runtime除了docker k8s還支持 rkt等容器實現

Addons附件:

DNS(kube-dns ==> coredns)主要用來解析service域名
CNI網絡容器接口(如fannel calico),pod,網絡是節點網絡類型,提供網絡策略通過名稱空間來隔離租戶
    flannel網絡配置,疊加網絡,不支持網絡策略
    calico網絡配置、網絡策略,三層隧道網絡
    canel:結合兩者
    weave網絡策略
web ui
container resource monitoring
cluster-level logging

證書:

5套證書,分內部和外部服務通信

常用對象:

Workload:

分為Pod ReplicaSet Deployment statefulSet DaemonSet Job CronJob
pods,k8s管理的最小對象,是一組共享uts, network, ipc namespace的容器(也支持共享pid,默認不開啟)
rc和rs等controller(管理pods)
deployment
    簡單地說deployment是rc的上一層,用來管理rc的
    主要功能是管理pod運行的版本

服務發現與均衡:

service
    pod是非持久的,會不斷的重啟,導致pod的ip是隨時變化的,同時pod的數量會是動態變化的,客戶端很難和pod直接通訊,service是用來解決這一問題的
    service 為提供同一服務的pods 提供了統一的入口
    service 的生命周期內其綁定ip是不會變化的
    通過環境變量或者DNS 可以查詢service 的ip和端口
    之前創建的service只有一個集群內的固定ip,如果需要在集群外訪問有三種方法
        默認的service 的類型是 'ClusterIP',修改為NodePort即可
        創建一個loadbalance
        創建Ingress resource
Ingress

配置與存儲:

Volume

集群級資源:

namespace,node,role,clusterRole,RoleBinding

部署與安裝:

部署要點:

測試環境:

可以使用單master節點,單etcd實例
node數量按需
nfs或glusterfs等存儲

生產環境:

高可用etcd集群,建立3/5/7
高可用master
    -kube-apiserver無狀態,可多實例,借助nginx\happorxy負載
    kube-scheduler及kube-controller-manager各自只能有一個活動實例,可以選舉備用
多node
IScsi、fcsan

網絡(本地多vm):

節點網絡:172.20.0.0/16
pod網絡:10.244.0.0/16 fannel默認使用
service網絡:10.96.0.0/12

常用部署工具:

kubeadm
kops
kubespray
kontena pharos

集群架構組成:

初始化:

所有節點啟動docker
初始化master(運行三個controller、etcd)和node(kube-proxy)

基礎組件:

master和node啟動kubelet和CNI

kubeadm部署流程:

1.更新下載源

配置yum或apt阿里雲源,yum下載gpg,定義.repo文件
    https://developer.aliyun.com/mirror/kubernetes
    ubuntu下:
        sudo apt-get update && sudo apt-get install -y apt-transport-https
        curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add - 
        cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
        deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
        EOF
        k8s_version="1.18.0-00"
        apt-get update
        apt-get install -y kubelet=${k8s_version} kubeadm=${k8s_version} kubectl=${k8s_version}

2.安裝軟件

install docker-ce kubelet kubeadm=v1.11.0 kubectl,並且enable docker-ce kubelet

3.docker拉取所需鏡像

通過代理拉取:
路徑是/etc/systemd/system/docker.service.d/http-proxy.conf或/usr/lib/systemd/system/docker.service
Environment="HTTPS_PROXY=http://www.ik8s.io:10080"
Environment="NO_PROXY=127.0.0.0/8,172.20.0.0/16"
systemctl daemon-reload
systemctl start docker
通過tag重命名的方式:
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver:v1.18.1
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager:v1.18.1
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler:v1.18.1
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy:v1.18.1
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.4.3-0
docker pull coredns/coredns:1.6.7
docker images |grep registry.cn-hangzhou.aliyuncs.com/google_containers |awk '{print "docker tag ",$1":"$2,$1":"$2}' |sed -e 's#registry.cn-hangzhou.aliyuncs.com/google_containers#k8s.gcr.io#2' |sh -x
docker tag docker.io/coredns/coredns:1.6.7 k8s.gcr.io/coredns:1.6.7
docker images |grep mirrorgooglecontainers |awk '{print "docker rmi "$1":"$2}' |sh -x

4.初始化部署

swapoff -a
kubeadm reset -f && rm -rf /etc/kubernetes/
kubeadm init --kubernetes-version=v1.11.0 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12 初始化
    --ignore-preflight-errors=SystemVerification --ignore-preflight-errors=KubeletVersion
    --control-plane-endpoint=apulis-china-infra01.sigsus.cn
    --image-repository=harbor.sigsus.cn:8443/library/k8s.gcr.io
執行后續提示步驟
出錯原因查看:journalctl -xeu kubelet
    如果還不是很明確,可以繼續通過docker ps -a和docker logs xxx查看容器具體的報錯的信息

    標准的初始化流程可以參考官方文檔https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/

配置kubectl的文件
    mkdir -p $HOME/.kube
    sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    sudo chown $(id -u):$(id -g) $HOME/.kube/config

5.部署其他組件:

CNI:
部署flannel:
kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=v1.18.1"
sudo scp dlwsadmin@apulis-sz-sanbox-master:/etc/kubernetes/admin.conf ./deploy/sshkey/admin.conf
部署weave:
kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')&env.IPALLOC_RANGE=10.32.0.0/16"
DNS(coredns):
https://github.com/kubernetes/kubernetes/blob/e176e477195f92919724bd02f81e2b18d4477af7/cluster/addons/dns/coredns/coredns.yaml.sed
修改clusterIP為10.3.0.53,刪除配置中的loop
效果:
    部署完后,集群內pod之間、service與pod之間就可以訪問域名通信。
    service的更新實時通過kube-proxy獲取api-server來更新dns的service地址到本地
    刪除dns后又重新添加,dns的service網絡地址不變
問題:
    1.部署機可以訪問pod網絡,但因為resolv.conf不變,不能訪問service域名
    2.無法解析集群外域名
        解決:修改resolv.conf,但unable to resolve host,因為本地host依賴本地的dns,編輯/etc/hosts,把主機名加到127.0.0.1即可。
        或者啟動coredns時,指定forward . 8.8.8.8

6.worker節點部署:

安裝docker
使用kubeadm join的方式初始化子節點:
    token可以通過kubeadm token create和openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
    組合成kubeadm join --token %s %s:6443 --discovery-token-ca-cert-hash sha256:%s
        kubeadm token create --ttl 0 --print-join-command
多次部署:
    systemctl stop kube-proxy
    systemctl stop kubelet
    systemctl stop docker
    iptables --flush                # 修復no route to host
    iptables -tnat --flush
    iptables -P INPUT ACCEPT        # 設置filter表INPUT默認規則是 ACCEPT
    iptables -P FORWARD ACCEPT
    iptables -P OUTPUT ACCEPT
    iptables -F                 # 清空所有規則 
    systemctl start kubelet                 
    systemctl start docker

運維操作:

刪除節點:

kubectl drain k8snode02 --delete-local-data --force --ignore-daemonsets node/k8snode02
kubectl delete node k8snode02
kubeadm reset(systemctl stop kubelet && rm -rf /etc/kubernetes/*)

master的ip變更:

kubeadm部署的:
1.重新生成證書,可以通過kubeadm alpha phase certs
2.把config文件、kubebconfig文件、/etc/kubernetes/文件夾里的*.conf文件的舊ip都改為新的IP
3.重啟服務
二進制部署:
只要簽發的證書沒有指定master的ip,那么是不用重新生成證書的
只要把conf文件都改掉舊的ip即可
注意事項:
admin.confkubelet.conf以及crt文件里面都需要改動ip
方法:
systemctl stop kubelet docker
cd /etc/
mv kubernetes kubernetes-backup
mv /var/lib/kubelet /var/lib/kubelet-backup
mkdir -p kubernetes
cp -r kubernetes-backup/pki kubernetes

rm kubernetes/pki/{apiserver.*,etcd/peer.*}
systemctl start docker

# reinit master with data in etcd
# add --kubernetes-version, --pod-network-cidr and --token options if needed
# 原文使用如下命令:
# kubeadm init --ignore-preflight-errors=DirAvailable--var-lib-etcd
# 但是由於我使用的是Flannel網絡,所以一定要加上參數,否則后續安裝 flannel addon無法啟動pod
# kubeadm init --ignore-preflight-errors=DirAvailable--var-lib-etcd --pod-network-cidr=10.244.0.0/16
kubeadm init --ignore-preflight-errors=all --kubernetes-version=v1.18.2

# update kubectl config
cp kubernetes/admin.conf ~/.kube/config

常見問題點:

初始化:

1.10250這個端口一直被/snap/kubelet/1388/kubelet的掛載目錄給占用了。
    umount -fl即可
    如果強制卸載后,還是ps -ef|grep kube還是存在,可以rm /dev/loop0試試
2.子節點join失敗。
    查看具體原因log -v 256
3.日志提示Error response from daemon: readlink /var/lib/docker/overlay2/l: invalid argument
    刪除該目錄會報錯,link來的,然后重新拉取鏡像就沒問題了
4.worker節點reset后提示沒有/etc/kubernetes/bootstrap-kubelet.conf
    systemctl status kubelet查看配置文件
    復制其他worker節點的文件過來,kubelet即可運行
5.提示error while creating mount source path '/var/lib/kubelet/pods/etc-hosts': mkdir /var/lib/kubelet: read-only file system
    重啟docker
6.kubeadm init初始化失敗,報node "ubuntu" not found
    原因: 
        通過docker logs查看pod啟動失敗原因,發現是k8s集群鏡像的架構不同導致的,樹莓派上的鏡像之前已經自帶的,導致apiserver啟動失敗。
7.Failed to create pod sandbox: open /run/systemd/resolve/resolv.conf: no such file or directory
    解決: 
        ln -s /run/resolvconf/ /run/systemd/resolve
8.kubelet提示panic: runtime error: invalid memory address or nil pointer dereference,不斷重啟
    原因:calico鏡像有問題,delete掉deployment后,還殘留了容器,docker ps -a查看,一直拉取舊的鏡像。前一行提示了error image not found while inspecting docker container
9.init失敗:
    # /etc/kubernetes/work-kubernetes.yaml需要配置,讀取/etc/kubernetes/ssl/里面的相關證書  
    # 這是join用到的kubelet配置,會影響主節點的部署/etc/systemd/system/kubelet.service.d/10-kubeadm.conf
    # 后來發現是之前部署的10-kubeadm.conf遺留造成的影響,換為一個能用的就行
    # 沒有10-kubeadm.conf會一直空跑

網絡CNI:

1.weave端口被占用也會導致容器網絡失敗,通過lsof -i:xxx 查看,然后kill -9 pid即可重啟weave,但有可能open /weavedb/weave-netdata.db失敗,delete pod然后再啟動一次即可。
2.新節點加入weave報錯Could not get peers: Get https://10.96.0.1:443/api/v1/nodes: dial tcp 10.96.0.1:443connectno route to host
    kube-proxy還沒啟動,導致無法路由
3.提示[192.168.3.2:6783|be:87:40:f0:e9:c2(atlas01-worker01)]: connection shutting down due to error: IP allocation was seeded by different peers (received: [ca:1c:e7:11:2c:9f],ours: [02:61:5f:88:9a:d9(atlas01)])
    關聯問題:On a network with multiple interfaces weave uses different ones on different hosts
    解決方案:
        some Weave Net peers were initialized into one cluster and some into another cluster; Weave Net cannot operate in this state.
        https://www.weave.works/docs/net/latest/tasks/ipam/troubleshooting-ipam/#seeded-different-peers
        https://github.com/weaveworks/weave/issues/3588
        rm -rf /var/lib/weave
        重啟weave
4.FATA: 2020/09/17 14:57:45.957005 [kube-peers] Could not get peers: Get "https://10.96.0.1:443/api/v1/nodes": dial tcp 10.96.0.1:443: i/o timeout
    Failed to get peers
    查看kube-proxy的log: 
        10.96.0.1 in clusterIP has incorrect IP version (service default/kubernetes)
    解決: 
        看kubelet status可以看到NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized,weave引起的
        主要解決weave即可
        curl -vk https://10.96.0.1

        懷疑和機器本身的網卡驅動有關

        x86也遇到過,禁用ipv6后成功啟動weave
            sysctl net.ipv6.conf.all.disable_ipv6=1

            vim /etc/sysctl.d/10-disable-ipv6.conf
            write_files:
              - path: /etc/sysctl.d/10-disable-ipv6conf
                permissions: 0644
                owner: root
                content: |
                  net.ipv6.conf.eth0.disable_ipv6 = 1

        后來發現是機器本身的內核問題,換一台機器就好了,但不是根治之法

        默認要有一個default router

        查閱了一下,手動添加route: 
            ip route add 10.96.0.0/12 dev eno1 src 10.31.3.63 無效

        可能與iptables-save規則有關
            iptables -A KUBE-SERVICES -d 10.96.0.1/32 -p tcp -m comment --comment "default/kubernetes:https cluster IP" -m tcp --dport 443
            或者直接reset整個iptables                     

            驗證:
                iptables -A KUBE-SERVICES -d 10.96.0.1/32 -p tcp -m comment --comment "default/kubernetes:https cluster IP" -m tcp --dport 443 -j REJECT
                刪掉weave pod后果然起不來

        還是無效的話,重啟reboot看看

    發現與coredns解析連不了8.8.8.8有關,因為看到了域名解析錯誤,將機器連上網后正常。
    一般不用管iptables
5.kubernetes ha vip起來,但其他組件無法訪問vip,查看VIP的log發現ipv6達不到
    手動添加對應的inet6無效
    swapoff -a
    sed -i 's/.*swap.*/#&/' /etc/fstab
    setenforce 0
    echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables
    echo 1 > /proc/sys/net/bridge/bridge-nf-call-ip6tables
    echo 1 > /proc/sys/net/ipv4/ip_forward
    echo 1 > /proc/sys/net/ipv6/conf/default/forwarding
    sysctl -w net.bridge.bridge-nf-call-iptables=1
    vim /etc/sysctl.conf
        net.ipv4.ip_forward=1
        net.bridge.bridge-nf-call-iptables=1
        net.bridge.bridge-nf-call-ip6tables=1
    sysctl -p
    重啟電腦后才生效

6.weave組件Inconsistent bridge state detected. Please do 'weave reset' and try again
    下載weave腳本,執行weave reset,會短暫斷網
    https://github.com/weaveworks/weave/blob/master/weave
    wget https://raw.githubusercontent.com/weaveworks/weave/master/weave
7.weave組件啟動異常,提示Network 10.32.0.0/12 overlaps with existing route 0.0.0.0/1 on host
    確認是否啟動了全局代理vpn,先移除再啟動
8.weave組件啟動后,interface的ip和在controller中cluster ip設置的范圍不一樣,造成了pod內無法通信
    yaml文件里面定義:
        containers:
        - name: weave
          env:
            - name: IPALLOC_RANGE
              value10.0.0.0/16
    先停止,刪掉interface,再reset,然后啟動即可。
9.weave報錯的情況下,pod還能分配到node上,擁有host???
    問題:
        發現master無法部署,即使去掉taints,后來發現dns無法nodenotready,原來是weave啟動失敗,
        更換flannel后,同時edit master的pod_cidr為相同的network,就可以啟動。

運維:

1.遇到pod rpc deallock等error,一直pengind、terminating中
重新加入worker節點
2.pod一直處於Terminating,docker ps查看進程存在,stop kill rm -f都不成功
原因:/var/lib/docker/containers/文件存在,可能是container清理時網絡問題導致文件未清理掉,造成進程已退,但文件存在的假container
    npu的腳本報錯會導致kill不掉,原因是sudo -E bash -c cd /data/code/mindspore/example/resnet50_cifar10/ && ./run_8p.sh &&sleep infinity的./run_8p.sh報錯了
    如果正常執行,則不會出現該情況
解決: 
    刪除/var/lib/docker/containers/下的對應文件夾
    systemctl restart docker
    或kubectl delete pod --force  xxx  但docker沒清掉
    或docker top xxx查看容器停留進程,然后kill 進程號試試
重現:
    再次跑job后,仍然出現該情況
3.pod的port通過service轉發,pod內進程是啟動的,內網ip+targetport可以訪問,但通過service的cluster_ip+port或外網ip+nodeport不能訪問
iptables-save |grep 10.104.74.188
-A KUBE-SERVICES -d 10.104.74.188/32 -p tcp -m comment --comment "default/e-461e6f51-66fc-4969-8eec-65ec74960c91-ipython:ipython has no endpoints" -m tcp 
    --dport 44460 -j REJECT --reject-with icmp-port-unreachable
意思是44460端口不可訪問
    網上搜索說selector錯誤,但pod是啟動的
4.pod內Unable to connect to the server: dial tcp 10.96.0.1:443: i/o timeout,kubectl或python接口都超時
原因: ufw啟動,本地訪問6443端口是可以的,但容器內不能訪問。容器內網絡是正常的。
解決: ufw allow 6443
5.樹莓派出現[ERROR SystemVerification]: missing cgroups: memory
解決:
/boot/firmware/cmdline.txt和/boot/firmware/nobtcmd.txt添加cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1
6.pod一直處於containcreating狀態。kubernetes Get https://[10.96.0.1]:443/apis/crd.projectcalico.org/v1/clusterinformations/default: x509: certificate signed by unknown authority
/etc/cni/net.d/目錄下面有其他的網絡插件,比如calio,刪除掉
ip route flush proto bird
ip link list | grep cali
iptables-save|grep cali 
modprobe -r ipip
service kubelet restart 
7.pod狀態出現diskpresure
vi /var/lib/kubelet/config.yaml
evictionHard:
  nodefs.available: "5%"
8.pod內resolf.conf文件沒有nameserver
過程:
該節點卸載過avahi,該軟件導致了默認route的改變,增加了網卡,卸載導致systemd-resolved.service起不來。
解決:
重啟,然后服務正常,但nslookup查找失敗
ls -l /etc/resolv.conf可以看到指向不正常
rm /etc/resolv.conf
ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf正常的軟鏈才是正常的,pod內使用的/etc/resolv.conf文件也是這個,systemd-resolved 實時更新 /run/systemd/resolve/stub-resolv.conf
9.容器內其他用戶執行kubectl提示error: You must be logged in to the server (Unauthorized)
原因:
每個pod都掛載了default token,對應serviceaccount的default,該token由TokenController 作為 kube-controller-manager 的一部分運行。
使用了該default token導致kubectl返回401錯誤(kubenretes的python api也會401
    from kubernetes import client as k8s_client
    from kubernetes import config as k8s_config
    k8s_config.load_incluster_config()
    k8s_core_api = k8s_client.CoreV1Api()
    k8s_core_api.list_namespaced_config_map(namespace="default")
該token可以通過jwt解,但只是一些基本信息。看kubelet的報錯,原因可能是掛載的token是舊的,對應的已經被刪除了。
解決:
刪掉token,等待自動生成。
9.pod一直處於pulling,同時有多個pod
原因:kubelet默認串行拉取鏡像,改為並行
查找:kubelet -v可以設置更高的級別,輸出更多的log

DNS:

1.coredns問題
查看本地dns服務是否啟動,排除weave是否正常,ping內網ip是否通,
查看coredns的pod,依賴配置configmap:coredns,kgk cm coredns -o yaml查看配置
查看coredns的log,發現dial udp [fdcd:55c4:4289::1]:53connect: cannot assign requested address
    通過netcat工具,nc -z -v -u [hostname/IP address] [port number]
    原因:fdcd:55c4:4289::1是根據configmap中的forward . /etc/resolv.conf來導向的,看看/etc/resolv.conf是否有問題
一直CrashLoopBackOff
    [FATAL] plugin/loop: Loop (127.0.0.1:37845 -> :53) detected for zone ".", see https://coredns.io/plugins/loop#troubleshooting. Query: "HINFO 5239076309015988897.2370766897435033976."
    原因: loop 
        修改本地127.0.0.538.8.8.8

常用指令:

kubectl get nodes
            pods -n kube-system -o wide\yaml\json
            ns
            svc
        run nginx-dep --image=nginx:1.14-alpine --port=80 --replicas=1  # 啟動的是deployment,如果想運行pod的話,kubectl run nginx --image=nginx --port=80 --restart=Never
        expose deployment nginx-dep --name=xxx --port=80 --target-port=80 --protocol=TCP --type=ClusterIP
            創建service來動態綁定端口,nodePort類型才能被外網訪問
        edit svc xx
        scale deployment xx --replicas=5
        set image deployment myapp myapp=ikuberbetes/myapp:v2
        rollout status deployment myapp灰度更新
                history\undo\pause\resume
        patch deployment myapp -p '{"spec":{"replicas":5}}'
        create ns(namespace) xxx
                deploy ngx --image=nginx:1.14-alpine # 自動重啟,ip會變(集群內才能訪問該ip),加service層
                    會啟動pod
                service clusterip my-cs --tcp=5378:8000 # 與deploy同名會自動關聯過來
                service nodeport my-ns --tcp=       # 區別是外網可以訪問,但不是指定端口
        delete ns/xxx ns/yyy 可以一次輸入多個
        api-resources
        describe
        exec -it xxx /bin/bash
            pod-demo -c 某個container -n prod -it -- /bin/bash
        scale --replicas=3 deployment mydeploy擴容后svc自動添加負載
        log pod xxx -n prod -c container
        cluster-info

概念介紹:

Controller種類:

概述:

Kubernetes 通常不會直接創建 Pod,而是通過 Controller 來管理 Pod 的。

分類:

ReplicationController(舊)
ReplicaSet:指定數量的副本,不建議直接使用,而是使用deployment ;擴縮容可以scale或edit;
        升級edit不會更新已存在的pod,只能藍綠更新
Deployment:通過控制ReplicaSet來控制pod,功能大於replicas,支持灰度滾動更新(管理多個rs來實現)
        配置更新可以編輯文件然后apply\set image\patch
DaemonSet:每個節點運行,node守護進程,適合node節點收集路徑日志的服務,由k8s維護重啟
StatefulSet:狀態,如redis,持久存儲
Job:執行一次
Ctonjob:周期執行
HPA

網絡:

節點網絡:

與外部網絡接口,運維提供,而其他兩種網絡由插件通過

service網絡:

概述:
內部網絡,無法外部訪問,通過coreDns注冊;被刪前穩定ip
實現原理:
不是實體組件,而是一套iptable規則,其service名稱通過自身的dns來解析
請求通過service訪問pod,而iptable將負載交給ipvs提供負載平衡功能,即相當於生成了ipvs規則
當pod狀態變更時,service通過守護進程kube-proxy改變節點的相關ipvs規則

pod網絡:

概述:
由cni提供,一般加一層service網絡代理,service通過label與pod綁定
實現原理:
pod之間可以通過overlay network疊加網絡相互訪問,而service只是規則
(如果直接物理橋橋接,pod數量多了不夠分,通過疊加網絡二層轉發或隧道轉發三層)
訪問過程:
docker之間先轉發出節點,再相互通信
pod要訪問service,先請求網關,到達臨橋地址通過iptabel規則表找到service

service資源:

工作原理:

pod之間請求通過service,pod的更新到apiserver后,apiserver通過kube-proxy通知service進行更新

工作模式:

userspace、iptable、ipvs

type類型:

ExternalName, ClusterIP, NodePort,LoadBalancer,Headless.
NodePort
    會將對本地集群任何一個機器ip的某一個port的請求轉發到相應的cluster ip+port上
    Port的范圍是所有機器共享的
Headless
    無頭service,clusterIP: None #None表示是無頭service
    會直接解析為具體多個pod的ip
    該服務不會分配Cluster IP,也不通過kube-proxy做反向代理和負載均衡。而是通過DNS提供穩定網絡ID來訪問,DNS會將headless service的后端直接解析為podIP列表。主要供StatefulSet使用。
LoadBalancer:
    和nodePort類似,不過除了使用一個Cluster IP和nodePort之外,還會向所使用的公有雲申請一個負載均衡器(負載均衡器后端映射到各節點的nodePort),實現從集群外通過LB訪問服務。
    雲平台底層將請求負載轉發給各個nodePort的service,service再分發給pod
ExternalName:
    集群內的pod訪問外部服務,私網ip回不來
    建一個service,由service請求外部服務,請求先回到service,再轉發給pod
    是 Service 的特例。此模式主要面向運行在集群外部的服務,通過它可以將外部服務映射進k8s集群,且具備k8s內服務的一些特征(如具備namespace等屬性),來為集群內部提供服務。

訪問url格式:

svc_name.ns_name.domain.ltd
例如redis.default.svc.cluster.local.

配置示例:

apiVersion:v1
kind: Service
metadata:
    name:
    namespace
spec:
    selector:
        app:nginx
    clusterIP:          # 分配
    type: ClusterIP     # nodePort 會在宿主機上映射一個端口,供外部應用訪問模式。
    ports:
    - port:6379             # service映射端口
      targetPort: 6379      # 容器內端口
      nodePort: 33080       # 指定node的端口,默認30000-32767

Ingress:

作用:

外部https請求到達nginx,nginx通過url前綴轉發給不同的services,再由service轉發給對應一組pod

部署方案:

方法一:將nginx部署為daemonset,部分節點,nginx內配置多個location,location代理給services。
        再為多個nginx部署一個nodeport的service,指定nodePort,就可以接入外部請求
方法二:Ingress controller資源,先部署一個nginx的deployment,再部署一個ingress,路由多個path

安裝:

1.創建namespace\configmap\rbac\tcp-services-configmap\with-rbac yaml文件
2.kubectl apply -f ./部署nginx
3.定義ingress
apiVersion:extensions/v1beta1
kind:Ingress
metadata:
    name:ingress
    namespace
    annotations:
        kubernetes.io//ingress.class:"nginx"
spec:
    tls:
    - hosts:
      - tomcat.com
      secretName:tomcat-ingress-secret
    rules:
    -host:myapp.com
     http:
        paths:
        - path:     #空為根路徑
          backend:
            serviceName:myapp
            servicePort:80      # service端口,而ingress的nginx端口默認為80和443,現在不能更改
4.定義后nginx自動更新配置
#pod更新后,nginx的upstream也會自動更新
5.https,先openssl生成證書和密鑰,然后創建secret對象
openssl genrsa -out tls.key 2048
openssl req -new -x509 -key tls.key -out tls.crt -subj /C=CN/ST=Beijing/L=Beijing/0=DevOps/CN=tomcat.com
kubectl create secret tls tomcat-secret --cert=tls.crt --key=tls.key

kube-ApiServer:

restful api server,上面的指令實際都是http請求的不同action,get\put\post
資源對應着url

資源對象的配置格式:

kind:用於標識對象所屬的資源類型、api群組
apiVersion
metadata:名稱、namespace、標簽
spec:包括一些container,storage,volume以及其他Kubernetes需要的參數,以及諸如是否在容器失敗時重新啟動容器的屬性。
status:

資源對象管理方式:

創建:

陳述式命令     run
陳述式對象配置    create -f
聲明式對象配置    apply,用於添加,刪除使用陳述式對象配置的delete,配置文件修改了可以再次apply。可以目錄

區別:

run創建deploymnet,pod由控制器管理,而后兩種只是創建pod

Pod:

pod對象創建過程:

1.提交create pod
2.apiserver寫入etcd,etcd成功后響應
3.apiserver調度scheduler,watch new pod
4.scheduler bind pod給apiserver
5.apiserver寫入etcd
6.apiserver請求kubelet,watch bound pod
7.kubelet請求docker run
8.kubelet update pod status給apiserver
9.apiserver寫入etcd

pod的終止過程:

1.提交delete請求,apiserver標記為terminating
2.apiserver寫入etcd,設置grace period
3.apiserver請求kubelet,watch pod marked as terminating
4.kubelet send term signal給docker
5.kubelet run preStop hook
6.apiserver請求endpoint controller,remove pod from endpoint of all service
7.apiserver watch expiry of grace period,請求kubelet,kubelet send SIGKILL給docker
8.docker 立刻刪除pod
9.apiserver 請求刪除etcd對應的object

pod生命周期:

狀態:
Pending         API Server已經創建該Pod,但在Pod內還有一個或多個容器的鏡像沒有創建,包括正在下載鏡像的過程。
Runnung         Pod內所有容器均已創建,且至少有一個容器處於運行狀態、正在啟動狀態或正在重啟狀態。
Succeeded       Pod內所有容器均成功執行后退出,且不會再重啟。
Failed          Pod內所有容器均已退出,但至少有一個容器退出為失敗狀態。
Unknown         由於某種原因無法獲取該Pod的狀態,可能由於網絡通信不暢導致
相關鈎子:
postStart:
httpGet\exec\tcpSocket
容器啟動后立刻執行,如果執行失敗會根據policy重啟與否
preStop:
存活探測:
livenessProbe健康監測:  位於containers層面
    exec:(0表示成功)
        command
    httpGet(返回200狀態碼)
        host
        port:必須,name或數字
        path:
    tcpSocket
        host
        port
    failureThreshold
    initialDelaySeconds
    periodSeconds
    timeoutSeconds
就緒探測:
readinessProbe:
無論就緒ready與否,不能重啟,只是不能作為服務被引用
ready后才被server引用會更合理,比如多個replicas的一個,還沒就緒會導致502

重啟策略:

always:但凡對象終止就重啟
onfailure
never

pod security:

級別:
pod.spec.securityContext
pod.spec.container.securityContext
    capabilities add/drop

資源設置:

cpu一個核心=1000m
pods.spec.containers.resources
    limits最高限制
    requests申請資源

pod服務質量:

Guaranteed:為cpu和內存設置了相同request和limit的pod會自動歸屬此類,最高優先級
Burstable:至少一個容器設置了cpu和內存資源的request
BestEffort:未設置requests或limit屬性,最低優先級

其他知識點:

priorityClass
limitRange

關於Command和args:

如果定義了args,會使用docker鏡像的entrypoint,忽略cmd

關於yaml格式的書寫:

[]string這種,可以使用["/usr/sbin/nginx","-s","quit"]來表示,也可以- -

多個容器:

邊車,side car
一個主容器,其他容器輔助,如日志收集、后台服務的proxy代理
共享IPC、UTS、network、volumes

yaml文件示例:

apiVersion: v1       #必選,版本號,例如v1
kind: Pod       #必選,Pod
metadata:       #必選,元數據
  name: string       #必選,Pod名稱
  namespace: string    #必選,Pod所屬的命名空間
  labels:      #自定義標簽
    - name: string     #自定義標簽名字
  annotations:       #自定義注釋列表
    - name: string
spec:         #必選,Pod中容器的詳細定義
  containers:      #必選,Pod中容器列表
  - name: string     #必選,容器名稱
    image: string    #必選,容器的鏡像名稱
    imagePullPolicy: [Always | Never | IfNotPresent] #獲取鏡像的策略 Alawys表示下載鏡像 IfnotPresent表示優先使用本地鏡像,否則下載鏡像,Nerver表示僅使用本地鏡像
    command: [string]    #容器的啟動命令列表,如不指定,使用打包時使用的啟動命令
    args: [string]     #容器的啟動命令參數列表
    workingDir: string     #容器的工作目錄
    volumeMounts:    #掛載到容器內部的存儲卷配置
    - name: string     #引用pod定義的共享存儲卷的名稱,需用volumes[]部分定義的的卷名
      mountPath: string    #存儲卷在容器內mount的絕對路徑,應少於512字符
      readOnly: boolean    #是否為只讀模式
    ports:       #需要暴露的端口庫號列表
    - name: string     #端口號名稱
      containerPort: int   #容器需要監聽的端口號
      hostPort: int    #容器所在主機需要監聽的端口號,默認與Container相同,
      protocol: string     #端口協議,支持TCP和UDP,默認TCP
    env:       #容器運行前需設置的環境變量列表
    - name: string     #環境變量名稱
      value: string    #環境變量的值
    resources:       #資源限制和請求的設置
      limits:      #資源限制的設置
        cpu: string    #Cpu的限制,單位為core數,將用於docker run --cpu-shares參數
        memory: string     #內存限制,單位可以為Mib/Gib,將用於docker run --memory參數
      requests:      #資源請求的設置
        cpu: string    #Cpu請求,容器啟動的初始可用數量
        memory: string     #內存清楚,容器啟動的初始可用數量
    livenessProbe:     #對Pod內個容器健康檢查的設置,當探測無響應幾次后將自動重啟該容器,檢查方法有exec、httpGet和tcpSocket,對一個容器只需設置其中一種方法即可
      exec:      #對Pod容器內檢查方式設置為exec方式
        command: [string]  #exec方式需要制定的命令或腳本
      httpGet:       #對Pod內個容器健康檢查方法設置為HttpGet,需要制定Path、port
        path: string
        port: number
        host: string
        scheme: string
        HttpHeaders:
        - name: string
          value: string
      tcpSocket:     #對Pod內個容器健康檢查方式設置為tcpSocket方式
         port: number
       initialDelaySeconds: 0  #容器啟動完成后首次探測的時間,單位為秒
       timeoutSeconds: 0   #對容器健康檢查探測等待響應的超時時間,單位秒,默認1秒
       periodSeconds: 0    #對容器監控檢查的定期探測時間設置,單位秒,默認10秒一次
       successThreshold: 0
       failureThreshold: 0
       securityContext:
         privileged:false
    restartPolicy: [Always | Never | OnFailure]#Pod的重啟策略,Always表示一旦不管以何種方式終止運行,kubelet都將重啟,OnFailure表示只有Pod以非0退出碼退出才重啟,Nerver表示不再重啟該Pod
    nodeSelector: obeject  #設置NodeSelector表示將該Pod調度到包含這個label的node上,以key:value的格式指定
    imagePullSecrets:    #Pull鏡像時使用的secret名稱,以key:secretkey格式指定
    - name: string
    hostNetwork:false      #是否使用主機網絡模式,默認為false,如果設置為true,表示使用宿主機網絡
    volumes:       #在該pod上定義共享存儲卷列表
    - name: string     #共享存儲卷名稱 (volumes類型有很多種)
      emptyDir: {}     #類型為emtyDir的存儲卷,與Pod同生命周期的一個臨時目錄。為空值
      hostPath: string     #類型為hostPath的存儲卷,表示掛載Pod所在宿主機的目錄
        path: string     #Pod所在宿主機的目錄,將被用於同期中mount的目錄
      secret:      #類型為secret的存儲卷,掛載集群與定義的secre對象到容器內部
        scretname: string  
        items:     
        - key: string
          path: string
      configMap:     #類型為configMap的存儲卷,掛載預定義的configMap對象到容器內部
        name: string
        items:
        - key: string
          path: string

label:

標簽就是鍵值
key:字母、數字、_、-、.
value:可以為空,只能字母或數字開頭及結尾
一個對象可多個標簽,一個標簽可添加到多個資源上
key通常由鍵前綴和鍵名組成,前綴可選
使用:
    metadata定義后apply應用
    kubectl label --overwrite pod key=val key-刪除
快速清空label:
    kubectl edit編輯刪除

label selector:

基於等值關系
    = == !=
基於集合關系
    key in\not in ()
    key 所有存在此key的資源
    key
    !key
邏輯:
    多個選擇權為“與”
    空值意味着每個資源對象都被選中
    空的選擇器將無法選出任何資源
使用:
    kubectl get pods --show-labels -l app
=myapp
                    -l "app in (myapp,dep)" -L app 顯示該標簽 -l是選擇
                    -l '!app'
控制器配置文件使用:
    matchLabels:直接給定鍵值
    matchExpressions:給定表達式,{key:"KEY",operator:"OPERATOR",values:[value1,value2..]}
        operator操作符:
            In,notIn:非空列表
            Exists,NotExists:必須空列表

資源注解annotation:

僅用於為資源提供元數據信息,不能用於挑選資源對象。沒有長度限制
apply就用到這個來對比更新

更新策略:

重建:

概述:
會終止所有正在運行的實例,然后用較新的版本來重新創建它們。
示例:
spec:
  replicas: 3
strategy:
    type: Recreate

藍綠發布:

概述:
同時運行兩個版本的應用,如上圖所示,藍綠部署的時候,並不停止掉老版本,而是直接部署一套新版本,等新版本運行起來后,再將流量切換到新版本上。
缺點:
對硬件的要求就是日常所需的二倍
示例:
創建新舊兩個deployment(兩個label,app和version)和service(selector不同),在測試新版本滿足要求后,替換 label selector 中的版本標簽

滾動更新:

概述:
滾動更新通過逐個替換實例來逐步部署新版本的應用,直到所有實例都被替換完成為止。
示例:
spec:
  replicas: 3
strategy:
    type: RollingUpdate
rollingUpdate:
      maxSurge: 2        # 一次可以添加多少個Pod
      maxUnavailable: 1  # 滾動更新期間最大多少個Pod不可用

灰度發布:

概述:
也叫金絲雀發布,起源是,礦井工人發現,金絲雀對瓦斯氣體很敏感,礦工會在下井之前,先放一只金絲雀到井中,如果金絲雀不叫了,就代表瓦斯濃度高。
流程:
先啟動一個新版本應用,但是並不直接將流量切過來,而是測試人員對新版本進行線上測試,啟動的這個新版本應用,就是我們的金絲雀。
如果沒有問題,那么可以將少量的用戶流量導入到新版本上,然后再對新版本做運行狀態觀察,收集各種運行時數據,如果此時對新舊版本做各種數據對比,就是所謂的A/B測試(A/B測試是效果測試)。
當確認新版本運行良好后,再逐步將更多的流量導入到新版本上,在此期間,還可以不斷地調整新舊兩個版本的運行的服務器副本數量,以使得新版本能夠承受越來越大的流量壓力。
直到將100%的流量都切換到新版本上,最后關閉剩下的老版本服務,完成灰度發布。
示例:
方式一:
具有相同 Pod 標簽的 Deployment,通過數量來控制流量的比例。
方式二:
需要更精確的控制策略,建議使用服務網格(如 Istio),它們可以通過權重或 HTTP 頭等更好地控制流量。

statefulset:

概述:

Pod發生re-schedule后仍然要保持之前的網絡標識和持久化存儲

特點:

1.部署、擴展、更新、刪除都要有順序。
2.每個pod都有自己存儲,所以都用volumeClaimTemplates,為每個pod都生成一個自己的存儲,保存自己的狀態
3.pod名字始終是固定的
4.service沒有ClusterIP,是headlessservice,所以無法負載均衡,返回的都是pod名,所以pod名字都必須固定,StatefulSet在Headless Service的基礎上又為StatefulSet控制的每個Pod副本創建了一個DNS域名:$(podname).(headless server name).namespace.svc.cluster.local

組件:

headless service、statefulset、volumeClaimTemplate

適合場景:

有狀態的應用

擴縮容:

scale\set image

創建示例:

spec:
serviceName:
template:

spec:
containers:

- name:myapp
  volumeMounts:
volumeClaimTemplate:        # 類似pvc
- metadata:
name:myappdata
spec:
    accessModes:["readwriteOnce"]
    resources:
      request:
        storage:2Gi
updateStrategy:

type:
rollingUpdate:

partition:默認0,指定大於數字才進行更新。一般先指定較大,更新沒問題后修改為0全部更新

ReplicaSet:

概述:

運行維護一組副本pod
建議使用 Deployment 而不是直接使用 ReplicaSet

創建示例:

apiVersion
kind
metadata
spec
    replicas:2
    selector:
        matchLabels:以標簽來選擇pod是否符和,如果其他label碰撞了,隨機kill一個
            app:myapp
    template
        metadata:
            name
            labels:至少符合selector規則
        spec:
            containers:

Deployment:

概述:

ReplicaSet的更高級
pod之間沒有順序
所有pod共享存儲
pod名字包含隨機數字
service都有ClusterIP,可以負載均衡    

創建示例:

apiVersion
kind:Deployment
metadata
    name
    namespace
spec:
    replicas:
    selector:
        matchLabels:
            app:myapp
    template:
        metadata:
            labels:
        spec:
            containers:
            -
    strategy:
        type:   recreate刪一個建一個 or rollingUpdate
        rollingUpdate:
            maxSurge:
            maxUnavailable:
    reversionHistoryLimit:10

DaemonSet:

概述:

DaemonSet 確保全部(或者某些)節點上運行一個 Pod 的副本。 當有節點加入集群時, 也會為他們新增一個 Pod 。
當有節點從集群移除時,這些 Pod 也會被回收。刪除 DaemonSet 將會刪除它創建的所有 Pod。

適合場景:

在每個節點上運行集群守護進程
在每個節點上運行日志收集守護進程
在每個節點上運行監控守護進程
創建示例
apiVersion
kind:DaemonSet
metadata
    name
    namespace
spec:
    selector:
        matchLabels:
            app:myapp
    template:
        metadata:
            labels:
        spec:
            containers:
            -
    updateStrategy:
        type:onDelete類似recreate or rollingUpdate
        rollingUpdate:
            maxUnavailable:只能少不能多
    reversionHistoryLimit

存儲卷:

種類:

emptyDir臨時路徑、hostPath

底層存儲:

傳統存儲:
SAN:iSCSI...
NAS:nfs,cifs
分布式存儲:
glusterfs,rbd,cephfs
雲存儲:
EBS\Azure

emptyDir:

volumes:
- name:xxx
emptyDir:
    medium:""或Memory
sizeLimit:
然后在containers中volumeMounts
    mountPath:
    name:
    readOnly:
    subPath:子路徑

gitRepo:

clone一份到emptydir中使用,更新不會同步

hostPath:

volumes:
- name:xxx
hostPath:
path:
type:默認空字符串,不執行檢查掛載文件類型,DirectoryOrCreate\FileOrCreate\Socket\CharDevice\BlockDevice

共享存儲:

使用服務器部署nfs:
安裝nfs-utils        sudo apt-get install nfs-kernel-server
vim /etc/exports      /dev/share *(rw,fsid=1,sync,no_subtree_check,no_root_squash)        *表示不限制ip,fsid注意需不同
                                    rw,sync,no_root_squash,insecure
    sync    將數據同步寫入內存緩沖區與磁盤中,效率低,但可以保證數據的一致性
    async   將數據先保存在內存緩沖區中,必要時才寫入磁盤
systemctl start nfs        # ubuntu下是sudo service nfs-kernel-server restart\sudo systemctl start nfs-kernel-server
    # 如果nfs而不是nfs4,原因可能是配置有問題
        apt-get purge nfs-kernel-server
        重新安裝apt-get install nfs-kernel-server
sudo showmount -e localhost
sudo exportfs -rv        #將配置文件中的目錄全部重新export一次!無需重啟服務。
sudo nfsstat            #查看NFS的運行狀態
客戶端測試連接:
    #查看網絡端口,NFS默認是使用111端口。要確保端口已開,不建議通過外網訪問,而是集群內相互通信,這樣就不需要內網與外網之間的端口映射(即開放外網端口)
    sudo apt install nfs-common
    sudo showmount -e apulis-china-infra01.sigsus.cn
    sudo mount -t nfs4 apulis-china-infra01:/mnt/share /dlwsdata  # 會暫時覆蓋原來的目錄
    sudo mount -t nfs4 -o vers=4 -o mountvers=4 sandbox2-storage:/data/share /mntdlw
其他服務器進行掛載:
mount  -t nfs 192.168.255.1:/data/volumes /mnt
umount /mnt
volumes:
- name:xxx
nfs:
path:/data/volumes
server:store01.com

能夠多個pod共享讀寫,不能填寫相對路徑
問題:
mount.nfs: access denied by server while mounting  # ip和掩碼的問題,改為*就可以
同一個集群內
    一個機器訪問另一個機器,訪問域名時注意的是使用內網ip,如果填的是公網段才能訪問,那么將會access denied,只能192.168.0.0/24
        表示32-24=828次方表示256個可用ip,即最后一位是主機部分,前面三位是網絡部分
        27位的網掩碼是: 255.255.255.224,表示
    這個時候公網ip的111端口可以不開
華為集群
    沒有內網ip,直接通過外網ip通信,那么116.66.187.0/24,其他同一網段的機器可以訪問,但本機的域名解析為127.0.0.1,不符合公網限制,所以access denied
    或者將/etc/hosts里面的映射去掉也可以
mount.nfs: requested NFS version or transport protocol is not supported
    確認已經開啟了nfs server 
掛載卡住:
    配置nfs 
        RPCMOUNTDOPTS="--manage-gids -p 13025"
    重啟
        systemctl restart nfs-kernel-server
    確認防火牆已經開放了端口1112049,和配置的port

persistentVolumeClaim:

創建pv:
定義了多個nfs后,即可創建,定義和volumes差不多
apiversion
kind: PersistentVolume
metadata:
    name:pv001
    # 沒有namespace,屬於集群資源,這點比較關鍵!!!
    labels:
        name:
spec:
    nfs:                                                            # 除了nfs外,還支持hostpath、cephfs等,k8s內置支持。
        path:
        server:
    accessModes:["ReadWriteOnce","ReadOnlyMany","ReadWritemany"]
    capacity:
        storage:2Gi                                                 # 這個大小貌似不影響,用的是整個目錄,目前只有 capacity 這個label可作為 resource request 的依據,用於pvc的申請
    persistentVolumeReclaimPolicy: Retain (default) and Recycle.
    storageClassName: xxx                                           # 每個 PV 可以屬於某個類(Class),通過將其 storageClassName 屬性設置為某個 StorageClass 的名稱來指定。 
                                        # 特定類的 PV 卷只能綁定到請求該類存儲卷的 PVC 申領。 未設置 storageClassName 的 PV 卷沒有類設定,只能綁定到那些沒有指定特定 存儲類的 PVC 申領。                                
    hostPath:
        path: 
創建pvc:
kind:PersistentVolumeClaim
metadata:
    name:pvc
    namespace:default #和pod同一個命名空間
spec:
    accessModes:[]
    resources:
        requests:
            storage:6Gi
    selector:
        matchLabels                         # 不加selector時,任意匹配滿足容量的
    volumeMode: Filesystem                  # 掛載為pod內的目錄,此外還有Block,掛載為原始塊設備。
    volumeName: aiplatform-model-data-pv    # 指定pv,當前版本18.2不能綁定已經綁定過的pv(一對一),會一直pending。
    storageClassName: nfs                   # 對應pv的類型,可以是手動創建的pv,或者由storageClass動態創建的。

不同名稱空間的pvc可以同名字,pv是集群級別的資源,同名字肯定只能一個
pv和pvc是one to one的關系
使用:
volumeMounts:                        #掛載容器中的目錄到pvc nfs中的目錄
- name: www
  mountPath: /usr/share/nginx/html
  subPath: nginxpvc-test
volumes:
- name: www
  persistentVolumeClaim:              #指定pvc
    claimName: pvc-nfs
    readOnly

storageClass:

動態創建nfs目錄,創建pv來滿足pvc的需求

configMap:

放置配置,明文,pod掛載路徑即可,key-value字典來設置data的方式
創建configMap:
    kubectl create configmap myconfig --from-file=key1=/path/txt --from-literal=key1=config1        # key都放到data下
    apiversion
    kind
    metadata
    data:
    binaryData:
env使用:
    env:
    - name:Nginx_Port
      valueFrom:
        configMapKeyRef:
            name: nginx-cofig   # configmap名字為nginx-cofig
            key: nginx_port     # data下的key為Nginx_Port的數據
            optional:           # 是否configmap要事先定義
    更新后pod中不會自動更新
volume使用:
    volumeMounts:
      - name: config
        mountPath: "/config"        # key為文件名/config/key,value為內容
        readOnly: true
    volumes:
    - name: config
      configMap:
        name: nginx-config
        items:
         - key:    # 指定要掛載的key,如果不指定,則生成多個文件。
           path:   # 指定key生成的file名字,可以替代默認的名字key
    更新后短暫時間后同步到pod

secret:

加密的方式來存儲
創建secret:
    類型: 
        三種,kubectl create secret docker-registry\generic\tls
        docker-registry
            docker-registry用於spec.imagePullSecrets,生成后指定name即可
        generic
            typeOpaque
        tls
    示例:
        kubectl create secret generic mysql-root-password --from-literal=password=MyP@ss.8*9
        kubectl create secret generic ssh-key-secret --from-file=ssh-privatekey=/path/to/.ssh/id_rsa --from-file=ssh-publickey=/path/to/.ssh/id_rsa.pub
        kubectl create secret docker-registry harborsecret --docker-server=harbor.demo.com.cn --docker-username='docker-admin' --docker-password='==pwd==' --docker-email='admin@demo.com'
使用:
    generic的使用類似configmap,可以在env或volume中使用。
    volumes:
      - name: foo
        secret:
          secretName: mysecret
          items:
          - key: username
            path: my-group/my-username
            mode077
    env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: username

認證:

認證=》授權=》准入控制
認證支持token令牌和證書tls
授權支持node、abac、RBAC、webhook等
訪問apiserver可以curl訪問kubelet proxy,然后再轉發
kubectl如何認證:
    kubeconfig
pod如何認證:
    默認的使用default-token-xxx,僅有權限訪問自身的屬性,要想訪問其他pod,需手動創建
    serviceAccountName
restful api\verb\http action
subject針對user\group\serviceaccount
object針對resource\group
action:get,list,watch,patch,delete,deleteconllection
objectUrl:
    /apis/<GROUP>/<VERSION>/namespace/<NAMESPACE>/<KIND>/<object_id>/
    不同的action
    兩者分別對應起來,組合不同的permission
    permission給不同的role

用戶賬號serviceAccount:

主要是pod的賬號,用來指定pod的管理其他pod權限,如一些系統級的pod,flannel
pod生成時默認有一個default-token存儲卷,通過get secret查看
生成serviceAccount:
    kubectl create serviceaccount mysa -o yaml  還沒任何權限,可以包含image pull secrets(也可pod直接指定)
    創建后,生成mysa-token-xxx的secret
如何使用:
    spec:
        serviceAccount:     # 需先使用rolebinding或clusterrolebinding綁定到role或clusterrole上
                            # 只能使用對應名稱空間下的

賬號:

kubectl config view查看配置信息
生成證書密鑰,用k8s的證書openssl簽發,然后config創建用戶
相關操作:kubectl config use-context/set-cluster/set-context
    (umask 077;openssl genrsa -out czl.key 2048) 生成私鑰
    openssl req -new -key dashboard.key -out dashboard.csr -subj "/O=czl/CN=czl"  證書簽屬請求
    用系統ca簽:openssl x509 -req -in dashboard.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out dashboard.crt -days 365
    創建賬號kubectl config set-credentials czl --client-certificate=./mage.crt --client-key=./czl.key --embed-certs=true
    創建context:kubectl config set-context czl@kubernetes --cluster=kubernets --user=czl
    創建集群: kubectl config set-cluster --kubeconfig=/tmp/admin.conf --server="https://172.20.0.73:6443" --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true
    創建secret:create secret generic xxx -n kube-system --from-file=xx.crt=./xxx.crt --from-file=./xxx.key
刪除: 
    kubectl --kubeconfig=config-demo config unset users.<name>
    kubectl --kubeconfig=config-demo config unset clusters.<name>
    kubectl --kubeconfig=config-demo config unset contexts.<name>
問題: 
    1.提示需要輸入密碼:
        正常的config view輸入應該如下:
            apiVersion: v1
            clusters:
            - cluster:
                certificate-authority-dataDATA+OMITTED
                server: https://192.168.1.184:6443
              name: DLWS
            contexts:
            - context:
                cluster: DLWS
                useradmin
              namecontext-DLWS-admin
            current-contextcontext-DLWS-admin
            kind: Config
            preferences: {}
            users:
            - nameadmin
              user:
                client-certificate-data: REDACTED
                client-key-data: REDACTED
        看看set-credentials的參數是否對齊
    2.kubeconfig文件生成后,如果需要更改user等,需要刪掉文件后重新生成,set-context等命令不會覆蓋

RBAC:(用於pod的屬性serviceAccount)
kubeadm init搭建的集群默認是啟用了rbac --authorization-mode=Node,RBAC

role:
    operations:
    objects
rolebinding
    位於一個名稱空間下
    user account或service account
    role
    # 也可以綁定clusterRole,作為當前binding所在ns下的管理員!!!
    # 可以建立一個clusterrole,然后rolebing為各個namespace下的管理員
clusterRole\clusterrolebinding
    集群級別

創建role
    create role reader --verb=get,list --resources=pods
    kind:Role
    rules:
    - apiGroups:
      - ""              # 一般不需指定
      resources:
      - pods
      verbs:
      - get
      - list
創建rolebinding
    create rolebinding name --clusterrole=name|--role=name
    kind:RoleBinding
    metadata:
        name
        namespace
    roleRef:
      apiGroup:rbac.authorization.k8s.io
      kind:Role
      name:pods-reader
    subjects:
    - apiGroup:rbac.authorization.k8s.io
      kind:User     # 可以是group,例如kubernetes-admin就屬於system:masters組
                    # openssl x509 -in ./apiserver-kubelet-client.crt -text -noout
                    # serviceAccount
      name:czl
創建clusterrole
    create clusterrole NAME --verb=get,list,watch --resource=pods -o yaml
    其他類似
創建clusterrolebinding
    create clusterrolebinding NAME --cluster-role=xxx --user=xxx
    kubectl create clusterrolebinding default-cluster-admin --clusterrole=cluster-admin --serviceaccount=default:default --dry-run -o yaml

為node添加role
    kubectl label node master02 kubernetes.io/role=master

dashboard:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta8/aio/deploy/recommended.yaml
更改為nodePort后即可訪問
選擇serviceaccount的令牌或kubeconfig讓dashboard認證到k8s集群
生成專門證書:
    (umask 077;openssl genrsa -out dashboard.key 2048)
    openssl req -new -key dashboard.key -out dashboard.csr -subj "/O=czl/CN=domain"  證書簽屬請求
    用系統ca簽:openssl x509 -req -in dashboard.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out dashboard.crt -days 365
    創建secret:create secret generic xxx -n kube-system --from-file=xx.crt=./xxx.crt --from-file=./xxx.key
創建serviceaccount
    create serviceaccount xxx -n kue-system
進行rolebinding
    create clusterrolebinding xxx --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
找到綁定后生成的secret,describe打開復制令牌token即可
要想使用證書
    權限控制
        創建一個serviceaccount
        create rolebinding xxx --clusterrole=admin --serviceaccount=default:xxx
        config set-cluster kubernetes --certificate-authority=./ca.crt --server="https://172.20.0.0:6443" -embed-certs=true --kubeconfig=/tmp/admin.conf
    設置用戶賬號
        # 解密token: kubectl get secret xxx -o json這個其實就是describe獲取到的base64加密后的,每個sa賬號自動創建
        config set-credentials admin --token=xxxxxx --kubeconfig=/tmp/admin.conf
        kubectl config set-context xxx@kuberbetes --cluster=kubernetes --user=admin --kubeconfig=/tmp/admin.conf
        config use-context xxx@kuberbetes --kubeconfig=/tmp/admin.conf
    自定義證書如何生成配置:
        config set-credentials xxx --client-certificate=./xxx.crt --client-key=./xxx.key導入證書
        使用set-context設置所綁定的用戶:set-context xxx --cluster=kuberbetes --user=xxx

CNI:

概述:

容器間通信
包含兩個,一個是cni工具bin(coredns和kubelet都依賴),一個是cni插件,如weave

flannel:

背景:
container1要想與外界通信並且回來,本身生成的虛擬網卡eth0,關聯到docker臨橋veth上;
離開宿主機時在eth0做源地址轉換
container2要想服務被訪問,也要在物理機上做目標地址轉換,暴露出來
通信種類:
1.容器間通信:同一個pod內,通過lo
2.pod之間通信
3.pod與service通信 # 不在同一網段,通過itable或ipvs通信,切換mode在configmap中切換集群使用哪個
4.service與集群外通信
解決方案:
虛擬網橋,一半在pod,一半在宿主機上接入網橋中,還可以接入真實接口相關的網橋上使用物理橋接的方式
多路復用:MacVLAN
硬件交換:SR-IOV單根虛擬化
配置路徑:
/etc/cni/net.d/   k8s會自動加載該路徑下的網絡插件
flannel優缺點:
簡單,但不提供網絡策略,進行網絡隔離,集群內不同ns可以訪問
方法:
使用VxLAN,經過隧道接口封裝報文進行通信,支持vxlan\directrouting
host-gw主機網關,使用主機網關,要求同一網段
VxLAN+host-gw:directrouting同一網段使用host-gw,隔路由使用VxLAN
UDP:性能差,舊版本使用
部署:
任何kubelet的node都需要flannel來與pod通信,系統進程\kaemonset方式,每個node一個
配置參數:
Network:flannel使用的CIDR格式的網絡地址,用於為pod配置網絡功能
         10.244.0.0/16 =》 master:10.244.0.0/24 node01:10.244.1.0/24 ... 10.244.255.0/24
SubnetLen:把network切分子網供各節點使用時,使用多長的掩碼進行切分,默認24位
SubnetMin:10.244.10.0/24
SubnetMax:10.244.100.0/24
Backend:vxlan,host-gw,udp
配置示例:
    {"Network":"","Backend":{"Type":"vxlan","Directrouting":true}}
    下載配置文件,修改backend即可
    kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/k8s-manifests/kube-flannel-legacy.yml
    配置修改后需要重啟pod才生效

calico:

作為網絡插件時,網段是192.168.0.0/16
僅用來部署policy
部署:
    使用k8s自帶的etcd來存儲數據
    1.如果啟用了rbac,需要配置role和綁定
        kubectl apply -f https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/canal/rbac.yaml
    2.kubectl apply -f https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/canal/canal.yaml
應用:
    部署calico后,就可以使用policy控制不同命名空間之間的通信
    Egress出棧控制to,ports
    Ingress入棧控制from,要去的ports
    # 注意policy控制的是對應命名空間下的pod的出入棧
定義networkpolicy:
    apiVersion:networking.k8s.io/v1
    spec:
        egress:
        - ports:
          - port:
            protocal
          to:
          - podSelector:        # 控制pod之間通信
            namespaceSelector:  # 控制名稱空間
            ipBlock             # ip塊
        ingress:                # - {} 表示允許所有
        - from:
          - ipBlock:
               cidr: 10.244.0.0/16
               except:
               - 10.244.1.2/32
          ports:
          - port:80
            protocol:TCP
        podSelector:            # {}全部pod
            matchLabels:
                app: myapp
        policyTypes:["Egress"]  # 默認定義了都生效,如果沒定義的話,默認應用拒絕

調度器scheduler:

默認scheduler調度資源,返回給apiserver,存入etcd
資源限制:
    下限和上限
調度策略:
    1.Predicate預選過程:排除不符合的node
    2.Priority優選:計算各個node的優先級
    3.Select取最高優先級的
Pod選擇:
    nodeName
    nodeSelector    影響調度策略的范圍
調度方式:
    1.nodeAffinity節點傾向性\親和性,通過nodeSelector、nodename完成調度
    2.podAffinity\podAntiAffinity pod傾向性,運行在同一個node
    3.Taints污點\污點容忍Tolerations:打上污點后不運行pod,pod要想運行必須容忍所有的污點
預選策略:
    CheckNodeCondition檢測node是否正常
    GeneralPredicates包含了幾種
        hostname:檢測pod對象是否定義了pod.spec.hostname,調度到匹配的主機
        PodFitsHostPorts:pods.spec.containers.ports.hostPort檢測端口是否占用
        MatchNodeSelector:pod.spec.nodeSelector
        PodFitsResources:檢測node資源是否足夠
    NoDiskConflict:沒有磁盤沖突,存儲卷類型需求(不是默認)
    PodToleratesNodeTaints:檢查pod的spec.toleration是否包含node的污點
    PodToleratesNodeNoExecuteTaints:檢查
    CheckNodeLabelPresence:默認禁用
    CheckServiceAffinity:傾向於service已有pod的node
    MaxEBSVolumeCount
    MaxGCEPDVolumeCount
    MaxAzureDiskVolumeCount
    CheckVolumeBinding:查看所需pvc的node
    NoVolumeZoneConflict:
    CheckNodeMemoryPressure:
    CheckNodePIDPressure:
    CheckNodeDiskPressure:
    MatchInterPodAffinity:檢查pod的親和性
優選函數:
    least_requested:占用node資源比例最低的
    balanced_resource_allocation:資源占用比率相近
    node_prefer_avoid_pods:根據node注解信息scheduler.alpha.kubernetes.io/preferAvoidPods
    taint_toleration:將pod對象的tolerations與node的taints對比
    selector_spreading:散開pod對象
    InterPodAffinity:pod親和性
    NodeAffinity:
    (未啟動)
    MostRequested:傾向於集中node運行任務,空閑其他node
    NodeLabel:看標簽即可,不看值
    ImageLocality:node是否有所需的鏡像
    # 看綜合得分
使用nodeSelector:
    spec:
        containers:
        nodeSelector:
            app:myapp
使用affinity:
    spec:
      affinity:
        nodeAffinity:
            requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions
                  -  key:zone
                     operator:In
                     value:
                     - foo
                     - bar
            preferredDuringSchedulingIgnoredDuringExecution:
            - preference:
                matchExpressions:
              weight:1-100

    podaffinity可以通過nodeaffinity來實現,但需要編排兩次
        podAffinity49472:
            requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                - {key:app,operator:In,value:["myapp"]}
              topologyKey:kubernetes.io/hostname        # 使用這個來區分node位置
            preferredDuringSchedulingIgnoredDuringExecution#類似
                podAffinityTerm
                    labelSelector
                    topologyKey: kubernetes.io/hostname     # 根據節點hostname來判斷親和
    podAntiAffinity類似,效果相反
使用taints:node選擇pod
    effect:定義對pod的排斥效果
        NoSchedule僅影響調度、NoExecute不能運行、PreferNoSchedule:柔性影響調度
    管理node污點:
        kubectl taint node name key1=value1:effect1 ...
                taint           key1-
    設置pod的toleration:
        spec:
            tolerations:
            - key:"node-type"
              operator:"Equal"      # Exists
              value:"production"
              effect:"NoSchedule"   # 要准確對應污點的effect,空時匹配所有效果
              # tolerationSeconds:3600
    每次更改pod的toleration后會重新調度

容器的資源需求:

cpu可壓縮,內存不可壓縮,會OOM
requests和limits,調度pod時看node上運行的pod的requests之和,作為已分配出去的資源
CPU:
    兩核四線程為4個邏輯CPU
    1=1000微核心millicores
內存:
    E\P\T\G\M\K
    Ei\Pi\Ti\Gi\Mi\Ki   1024
定義:
    containers:
    - name:
      resources:
        requests:
            cpu:"500m"
            memory:"256Mi"
        limits:
            cpu:
            memory:
Qos:
    Guranteed:每個同時設置了cpu和內存的requests和limits,且相同
    Burstable:至少有一個容器設置了cpu或內存的requests屬性,優先終止占用request資源比例大的pod
    BestEffort:沒有任何一個容器設置了request或limits屬性,最低優先級
HeadpSter:
    kubelet中采集node資源情況的是內置的cAdvisor
    HeadpSter收集各個node的cAdvisor,緩存一段時間
    持久歷史放在InfluxDB,通過grafana進行可視化
部署influxdb:
    https://raw.githubusercontent.com/kubernetes-retired/heapster/master/deploy/kube-config/influxdb/influxdb.yaml
    wget下載,修改version為apps/v1,修改nodeselector,修改存儲卷,services
部署heapster:
    https://raw.githubusercontent.com/kubernetes-retired/heapster/master/deploy/kube-config/rbac/heapster-rbac.yaml
    https://raw.githubusercontent.com/kubernetes-retired/heapster/master/deploy/kube-config/influxdb/heapster.yaml
    先進行role綁定,再部署serviceaccount\deployment
    修改version為apps/v1,修改nodeselector
    command連接到influxdb,指定source=kubernetes:https://kubernetes.default定義了如何連接apiserver
    --sink=influxdb:http://monitoring-influxdb.kube-system.svc:8086指向influxdb的service
部署grafana:
    https://raw.githubusercontent.com/kubernetes-retired/heapster/master/deploy/kube-config/influxdb/grafana.yaml
    wget,修改apiversion為apps/v1,添加對應的selector,修改service的type為nodePort
    https證書自動掛載本地的/etc/ssl/certs
    添加dashborad即可可視化
    如果經過nginx代理,grafana可能會找不到靜態文件,需要修改homepage之類的。
    hostNetwork為true,直接訪問其他端口3000,而不是更改url則沒問題
命令行查看:
    kubectl top node\pod

資源指標與自定義指標:

一些HPA、top命令早期依賴heapster,僅支持內存和cpu指標
heapster為了適配各種存儲后端,整合了多個適配器,更新緩慢,導致代碼大
新一代依靠metrics-server這個API server服務與資源指標,部署為pod
自定義指標:premetheus,組件k8s-prometheus-adapter
新一代架構:
    核心指標流水線:由kubelet、metrics-server以及API server提供的api組成,CPu累積使用率、內存實時使用率,pod資源占用以及容器磁盤使用率
    監控流水線:用於從系統收集各種指標數據並提供終端用戶、存儲系統以及HPA,包含許多核心指標和非核心指標。
metrics-server提供資源指標,由kube-aggregator聚合metrics-server和apiserver的原生指標,通過/apis/metrics.k8s.io/v1beta1
部署metrics-server:
    https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/metrics-server
    for file in auth-delegator.yaml auth-reader.yaml metrics-apiserver.yaml  metrics-server-deployment.yaml 
    metrics-server-service.yaml resource-reader.yaml;do wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/metrics-server/$file;done
    apply后kubectl api-versions即可查看新url
    查看metrics資源:
        master下用kubectl proxy --port=8080
        然后curl http://localhost:8080/apis/metrics.k8s.io/v1beta1
    問題:獲取不了數據
        1.修改command:改默認10255為10250
        默認通過http的kubernetes.summary_api的默認鏈接來訪問,但被默認禁用了
        /metris-server --source=kubernetes.summary_api:https://kubernetes.default?kubeletHttps=true&kubeletPort=10250&insecure=true
        # 新版的不用修改了
        2.修改clusterRole的resources添加一個nodes/stats
部署prometheus獲取其他指標:
    Prometheus為server,client為node_exporter采集系統數據,其他數據需要如mysql_exporter
    通過PromQL提供restful接口數據,經過Prometheus adapter轉為metrics api的數據
    git clone https://github.com/iKubernetes/k8s-prom.git
    1.部署node-exporter,daemonset的形式,采集node的數據
        kubectl apply -f ./k8s-prom/node_exporter/
    2.部署prometheus以及相應的serviceaccount、rolebinding、service,即可訪問webui
        默認監聽9090
        將service端口30090加到nginx中,但還是有非根目錄導致404靜態文件的問題
        kubectl apply -f ./k8s-prom/prometheus/
        在啟動的時候設置web.external-url使用下面的命令:
            ./prometheus --web.external-url=prometheus --config.file=prometheus.yml
        nginx配置為 location /prometheus       proxy_pass http://prometheus.prom.svc.cluster.local:9090/prometheus
        登錄網頁即可查看指標
        curl http://localhost:9091/prometheus/api/v1/label/__name__/values # grafana通過這個接口來查詢metrics
    3.部署kube-state-metrics轉為metrics api指標
        ./k8s-prom/kube-state-metrics/
    4.部署kube-prometheus-adapter,自制k8s簽署的證書cm-adapter-serving-certs,生成generic secret供https使用
        cd /etc/kubernetes/pki/
        (umask 077;openssl genrsa -out serving.key 2048)
        openssl req -new -key serving.key -out serving.csr -subj "/CN=serving"
        openssl x509 -req -in serving.csr -CA ./ca.crt -CAkey ./ca.key -CAcreateserial -out serving.crt -days 3650
        kubectl create secret generic cm-adapter-serving-certs --from-file=./serving.crt --from-file=serving.key -n prom
        apply -f ./k8s-prom/k8s-prometheus-adapter/ # deploy取自https://github.com/DirectXMan12/k8s-prometheus-adapter/tree/master/deploy/manifests 
    即可看到自定義的custom.metrics.k8s.io/v1beta1
        curl http://localhost:8080/apis/custom.metrics.k8s.io/v1beta1
    配合HPA或grafana定義數據源導入模板即可
        應用grafana,注釋掉env中的influxdb,修改namespace
        # 進入所在pod,修改配置/etc/grafana/grafana.ini,修改root_url = http://apulis-china-infra01.sigsus.cn/grafana
        修改yaml中的env的GF_SERVER_ROOT_URL為/grafana/     # 進入pod查看root_url沒變
        nginx代理數據源為proxy_pass http://prometheus.prom.svc.cluster.local:9090/;
        在grafana dashborad搜索kubernetes模板,下載json,在home導入即可
        # 數據源也可以配置
        如何調試:
            頁面登錄賬號后,就可以編輯pannel,添加數據源等,在pannel中調試數據源的指標,點擊Query Inspector即可顯示url
            這個url可以前端請求來獲取資源數據
HPA:
    自動伸縮容
    kubectl autoscale deployment myapp --min=1 --max=8 --cpu-percent=60 # 默認使用v1控制器
    進行請求壓測install httpd-utils
        ab -c 1000 -n 500000 http://xxx
    v2控制器可以使用其他評估指標
        kind:HorizontalPodAutoscaler
        metadata:
        spec:
            scaleTargetRef:
                apiversion:apps/v1
                kind:Deployment
                name:myapp
            minReplicas:1
            maxReplicas:8
            metrics:
            - type:Resource
              resource:
                name:cpu
                targetAverageUtilization:55
            - type:resource
              resource:
                name:memory
                targetAverageValue:50Mi         # v1不支持內存
        自定義指標輸出:如pod的最大請求數,hpa收集
            - type:Pods
              pods:
                metricName:http_requests
                targetAverageValue:800m     # 個

Helm入門:

命令行工具,不直接交互apiserver,而是Tiller,運行為pod
下載需要的chart到本地,不同的配置文件成為不同的release
helm支持chart版本更新,查詢和卸載等操作,將配置清單可復用
核心術語:
    Chart:一個helm程序包
    Repository:倉庫
    Release:特定的Chart部署於目標集群上的一個實例
架構:
    chart->config->release
    tiller接收helm發送的charts和config,合並為release
安裝:
    wget https://get.helm.sh/helm-v2.9.1-linux-amd64.tar.gz --no-check-certificate
    helm使用kubectl的配置文件來訪問apiserver
    配置role
        apiVersion: v1
        kind: ServiceAccount
        metadata:
          name: tiller
          namespace: kube-system
        ---
        apiVersion: rbac.authorization.k8s.io/v1
        kind: ClusterRoleBinding
        metadata:
          name: tiller
        roleRef:
          apiGroup: rbac.authorization.k8s.io
          kind: ClusterRole
          name: cluster-admin
        subjects:
        - kind: ServiceAccount
          name: tiller
          namespace: kube-system
    安裝tiller:
        helm init --service-account tiller
        鏡像下載不了,kubectl edit deploy tiller-deploy -n kube-system改為jinxiaoyuan/tiller
        # 或者先pull鏡像,tag
        # docker pull jinxiaoyuan/tiller:v2.9.1
        sudo apt install socat
倉庫:
    https://hub.helm.sh/
    helm repo update
    helm search redis
    heml inspect stable/redis
    helm install --name myredis -f value.yaml stable/redis
    helm delete/status/history xx

    create/fetch/get(不解包)/package/verify
目錄結構:
    xxx:
        Chart.yaml  # helm本身維護的chart元信息
        README.md
        charts:     # 放置依賴
        requirements.yaml  
        templates
            _helpers.tpl
            xxx.yaml    # 大量利用go模板語法生成字段
        values-production.yaml 
        values.yaml     # 配置變量,install -f可以指定自定義變量文件
自定義chart:
    go模板語法:{{.Values.imageRegistry}}  表示引用values.yaml文件的第一層次字段imageRegistry
        {{default "" .Values.imageRegistry}}
    helm create myapp編輯好values
    helm lint myapp
    helm serve 
    helm package myapp
    helm search myapp
    helm install --name myapp local/myapp
    helm status myapp 
    helm delete --purge myapp

日志系統:

部署方案:

1.sidecar,不建議一個pod超過兩個容器
2.部署為daemonset

ELK:

使用每個node的fluentd+logstash server+elastic master接收請求+data處理后端

部署:

helm fetch stable/elasticsearch
修改values文件
helm install --name els --namespace=prom -f values.yaml stable/elasticsearch
運行測試程序:
    kubectl run cirror --rm -it -image=cirros -- /bin/bash
    curl elasticd的域名:9200/_cat/nodes
部署fluentd每個node收集日志:
    helm fetch stable/fluentd-elasticsearch
    填寫es域名和9200,如果master要收集要填寫tolerations,要監控填寫prometheus
    helm install --name flu --namespace=prom -f values.yaml stable/fluentdel-asticsearch
部署kibana:
    helm etch stable/kibana
    填寫es地址
    helm install --name kib --namespace=prom -f values.yaml stable/kibana

Paas概述:

CI(Continuous Integration)\CD\CD
發布過程:
    developer->git->Jenkins/CI->application->docker build->docker hub->k8s 
    developer->git->docker file->docker build->docker hub->k8s 
    developer用python寫一段代碼,實現自動發布到k8s
Paas:
    openshit:包含一整套k8s以及日志監控、自動發布上線的os

命名空間:

示例:

kubectl get ns default -o yaml --export
---
apiVersion:v1
kind:Namespace
metadata:
    name:develop    # 其他的createTime\selfLink會自動生成
spec:
    finalizers:
        - kunernetes    # 負責回收,可以不定義

搭建DLWS:

用到的服務:

PXE預啟動執行環境,提供一種網絡接口啟動計算機的機制
重定向服務(DHCP代理)
TFTP協議下載到內存

資源:

一台服務器時可以起docker在里面部署本機為master,部署機本身始終沒有啟動任何服務,都是通過腳本ssh到遠程執行命令
(按道理可以本機部署本機?)
域名注冊和dns解析(阿里雲購買域名后免費提供解析)
更新hostname為子域名

流程:

前置:

如果部署過kubeadm,記得apt remove\autoremove清空,然后重新./deploy.py -y build

1.在部署機ubuntu上安裝基本所需工具

如果是docker內部署本機,sudo docker run -v /var/run/docker.sock:/var/run/docker.sock -v ~/:/home/dlwsadmin -it ubuntu:16.04
sh ../../install_prerequisites.sh
兩個node一個master:
    apt install net-tools,vim,sudo,openssh-server
    sudo systemctl start ssh
    passwd
    vim /etc/ssh/sshd_config    #PermitRootLogin prohibit-password為PermitRootLogin yes,再運行密碼登錄,重啟ssh
    etc/init.d/ssh start
    apt-get  install openssh-server
    最后因為docker沒有bus,進行不下去

2.配置集群config.yaml,配置id,domain,machine

3.如果系統未安裝,部署機可以安裝PXE

4.執行./deploy.py -y build

wget http://ccsdatarepo.westus.cloudapp.azure.com/data/containernetworking/cni-amd64-v0.5.2.tgz
mkdir ./deploy/bin && mv cni-amd64-v0.5.2.tgz ./deploy/bin/

5.將賬號密碼輸入echo dlwsadmin > ./deploy/sshkey/rootpasswd ./deploy/sshkey/rootuser以便部署機使用賬號密碼訪問

6.安裝key ./deploy.py sshkey install

7.查看key是否安裝成功./deploy.py execonall sudo ls -al

8.遠程為node安裝基本工具./deploy.py runscriptonall ./scripts/prepare_ubuntu.sh

./deploy.py execonall sudo usermod -aG docker dlwsadmin

9.下載鏡像

./deploy.py execonall docker pull dlws/pause-amd64:3.0
./deploy.py execonall docker tag  dlws/pause-amd64:3.0 gcr.io/google_containers/pause-amd64:3.0

10.開始部署kubernets

./deploy.py -y deploy            # 如果部署失敗,systemctl status kubelet查看原因,如/etc/hosts沒有加入短域名,端口1443未外網開放
./deploy.py -y updateworker        # 不同集群的機器作為worker的話,執行這個沒有成功加入。如果集群內兩台機器,則稍等后可以看到node
./deploy.py labelworker
./deploy.py -y kubernetes labelservice        # 根據域名來label node,如果域名不一致,會失敗
在master上啟動workload 
    ./deploy.py -y kubernetes uncordon
創建軟鏈
    sudo ln -s /home/ubuntu/QianJiangYuan/src/ClusterBootstrap/deploy/bin/kubectl /usr/bin/kubectl

11.掛載分享文件盤

./deploy.py mount
./deploy.py mount stop

12.deploy nvidia-device

准備:安裝顯卡驅動
./deploy.py kubectl label node apulis-sz-dev-worker01 gpuType=nvidia
./deploy.py kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v1.9/nvidia-device-plugin.yml
# v1.9版本與kubelet相關,要看版本,k8s版本1.15以上用v1.11
    sudo apt-get install nvidia-container-runtime
    distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
       && curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - \
       && curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
    curl -s -L https://nvidia.github.io/nvidia-container-runtime/experimental/$distribution/nvidia-container-runtime.list | sudo tee /etc/apt/sources.list.d/nvidia-container-runtime.list
    apt-get update
    apt-get install -y nvidia-docker2
    cat /proc/driver/nvidia/version
    設置/etc/docker/daemon.json
        {
            "default-runtime""nvidia",
            "runtimes": {
                "nvidia": {
                    "path""/usr/bin/nvidia-container-runtime",
                    "runtimeArgs": []
                }
            },
            "registry-mirrors": ["https://expuzg6d.mirror.aliyuncs.com"]
        }
# 遇到too old to support healtchecking with error: %!s(MISSING). Marking it unhealthy
    給plugin添加env DP_DISABLE_HEALTHCHECKS=xids

13.部署各個service

./deploy.py webui
./deploy.py docker push restfulapi
./deploy.py docker push webui3
./deploy.py docker push init-container
./deploy.py docker push prometheus        # 監控組件
./deploy.py docker push grafana
./deploy.py docker push collectd
./deploy.py docker push influxdb
./deploy.py docker push nginx
./deploy.py nginx fqdn
./deploy.py nginx webui3
./deploy.py nginx config    # 復制文件到/etc/nginx/conf.other
./deploy.py setconfigmap
./deploy.py kubernetes start mysql jobmanager2 restfulapi2 webui3 monitor nginx custommetrics repairmanager2 openresty
    # 會以集群name為前綴拉起image,修改config.yaml可以生效
    # nginx的certbot需要解析域名,如果是local域名,需要配置/etc/resolv.conf為本地,如果是公網域名,/etc/resolv.conf為公開dns地址即可

14.清理集群

./deploy.py cleanworker
./deploy.py cleanmasteretcd
./deploy.py clean

./deploy.py kubeadm reset

kubeadm部署方式

10. ./deploy.py --verbose kubeadm init

11. ./deploy.py --verbose kubeadm join

其余相同

修改apiserver的nodeport的范圍
vim /etc/kubernetes/manifests/kube-apiserver.yaml
增加參數- --service-node-port-range=1-65535
# 好像不用重啟
systemctl daemon-reload
systemctl restart kubelet

備份配置文件:

./deploy.py backup [backup_file_prefix] [password]        # 前綴
./deploy.py restore [backup_file] [password]    
./deploy.py restorebin        # 第二個command為restore的地方會被第一個攔截,修改為restorebin
    需要用到鏡像
        docker pull rancher/hyperkube:v1.16.9-rancher1
        docker tag rancher/hyperkube:v1.16.9-rancher1 gcr.azk8s.cn/google-containers/hyperkube:v1.15.2
即可正常執行kubernetes命令

HA:

官方文檔:

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/high-availability/

1.利用vip鏡像生成/etc/kubernetes/manifests/vip.yaml

2.通過命令生成ha初始集群

kubeadm init --v=8 --control-plane-endpoint=10.31.3.207 --kubernetes-version=v1.18.2 --upload-certs

3.加入剩余的master和worker

kubeadm init --v=8 phase upload-certs --upload-certs
kubeadm token create
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
kubeadm join --v=8 --token %s %s:%s --discovery-token-ca-cert-hash sha256:%s --control-plane --certificate-key %s

sudo kubeadm join --v=8 --token %s %s:%s --discovery-token-ca-cert-hash sha256:%s

vip原理:

docker容器先檢測本地的物理接口eno1,增加inet6,然后容器能夠ping通后,生成vip到具體的master上,局域網內可以訪問這個vip

二進制搭建kubernetes集群:

微軟方式:

生成ca證書
    mkdir -p ca
    openssl genrsa -out ca/ca-key.pem 2048
    openssl req -x509 -new -nodes -key ca/ca-key.pem -days 10000 -out ca/ca.pem -subj "/CN=kube-ca"
生成kubelet證書:
    編輯文件openssl-kubelet.cnf:
        [req]
        req_extensions = v3_req
        distinguished_name = req_distinguished_name
        [req_distinguished_name]
        [ v3_req ]
        basicConstraints = CA:FALSE
        keyUsage = nonRepudiation, digitalSignature, keyEncipherment
        subjectAltName = @alt_names
        [alt_names]
        DNS.1 = kubernetes
        DNS.2 = kubernetes.default
        DNS.3 = kubernetes.default.svc
        DNS.4 = kubernetes.default.svc.cluster.local
        DNS.5 = *.sigsus.cn
        DNS.6 = *.redmond.corp.microsoft.com
        DNS.7 = *.corp.microsoft.com
    mkdir -p kubelet
    openssl genrsa -out kubelet/apiserver-key.pem 2048
    openssl req -new -key kubelet/apiserver-key.pem -out kubelet/apiserver.csr -subj "/CN=kube-apiserver" -config openssl-kubelet.cnf
    openssl x509 -req -in kubelet/apiserver.csr -CA ca/ca.pem -CAkey ca/ca-key.pem -CAcreateserial -out kubelet/apiserver.pem -days 3650 -extensions v3_req -extfile openssl-kubelet.cnf
    cp ca/ca.pem kubelet
    rm ca/ca.srl
    rm kubelet/apiserver.csr
生成etcd證書
    mkdir -p etcd
    openssl genrsa -out etcd/etcd-key.pem 2048
    openssl req -new -key etcd/etcd-key.pem -out etcd/etcd.csr -subj "/CN=kube-apiserver" -config openssl-etcd.cnf
    openssl x509 -req -in etcd/etcd.csr -CA ca/ca.pem -CAkey ca/ca-key.pem -CAcreateserial -out etcd/etcd.pem -days 3650 -extensions v3_req -extfile openssl-etcd.cnf
    cp ca/ca.pem etcd
    rm etcd/etcd.csr
復制到指定目錄下:
    mkdir -p /etc/etcd/ssl
    cp etcd/ca.pem /etc/etcd/ssl
    cp etcd/etcd.pem /etc/etcd/ssl
    cp etcd/etcd-key.pem /etc/etcd/ssl
配置etcd3 service:
    編輯文件/etc/systemd/system/etcd3.service
        [Service]
        ExecStart=/usr/bin/docker run -v /usr/share/ca-certificates/mozilla:/etc/ssl/certs -v /etc/etcd/ssl:/etc/etcd/ssl -v /var/etcd:/var/etcd -p 2379:2379 -p 2380:2380 \
          --net=host \
          --name etcd3 dlws/etcd:3.1.10 /usr/local/bin/etcd \
          -name dlworkspace-etcd1 \
          -initial-cluster dlworkspace-etcd1=https://worker.sigsus.cn:2380 \
          -initial-cluster-state new \
          -initial-cluster-token 536eea5f-280e-453e-81a3-6198e66fb56d \
          -advertise-client-urls https://worker.sigsus.cn:2379 \
          -listen-client-urls https://0.0.0.0:2379 \
          -initial-advertise-peer-urls https://worker.sigsus.cn:2380 \
          -listen-peer-urls https://0.0.0.0:2380 \
          -data-dir /var/etcd/data \
          -client-cert-auth \
          -trusted-ca-file=/etc/etcd/ssl/ca.pem \
          -cert-file=/etc/etcd/ssl/etcd.pem \
          -key-file=/etc/etcd/ssl/etcd-key.pem \
          -peer-client-cert-auth \
          -peer-trusted-ca-file=/etc/etcd/ssl/ca.pem \
          -peer-cert-file=/etc/etcd/ssl/etcd.pem \
          -peer-key-file=/etc/etcd/ssl/etcd-key.pem
        Restart=always
        RestartSec=5
        [Install]
        WantedBy=multi-user.target
    編輯文件/opt/etcd_ssl.sh
        #ETCD_VER=v3.3.2 && DOWNLOAD_URL=https://github.com/coreos/etcd/releases/download && \
        #curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz && \
        #mkdir -p /tmp/test-etcd && \
        #tar xzvf /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -C /tmp/test-etcd --strip-components=1 && \
        #mkdir -p /opt/bin && \
        #mv /tmp/test-etcd/etcd /opt/bin && \
        #mv /tmp/test-etcd/etcdctl /opt/bin
        #rm -r /tmp/test-etcd
        docker rm -f etcd3
        systemctl daemon-reload
        systemctl start etcd3
        systemctl enable etcd3
啟動etcd3服務
    chmod +x /opt/etcd_ssl.sh
    systemctl start etcd3
    這一步嘗試去拉取鏡像,然后啟動容器,監聽端口2379
    等待服務起來:
        curl  --cacert /etc/etcd/ssl/ca.pem --cert /etc/etcd/ssl/etcd.pem --key /etc/etcd/ssl/etcd-key.pem "https://127.0.0.1:2379/v2/keys"
設置network范圍:
    curl  --cacert /etc/etcd/ssl/ca.pem --cert /etc/etcd/ssl/etcd.pem --key /etc/etcd/ssl/etcd-key.pem -X PUT -d "value={\"Network\":\"10.2.0.0/16\",\"Backend\":{\"Type\":\"vxlan\"}}" "https://127.0.0.1:2379/v2/keys/coreos.com/network/config"

生成apiserver證書
    編輯文件openssl-apiserver.cnf:
        [req]
        req_extensions = v3_req
        distinguished_name = req_distinguished_name
        [req_distinguished_name]
        [ v3_req ]
        basicConstraints = CA:FALSE
        keyUsage = nonRepudiation, digitalSignature, keyEncipherment
        subjectAltName = @alt_names
        [alt_names]
        DNS.1 = kubernetes
        DNS.2 = kubernetes.default
        DNS.3 = kubernetes.default.svc
        DNS.4 = kubernetes.default.svc.cluster.local
        DNS.5 = worker.sigsus.cn
        IP.0 = 10.3.0.1
        IP.1 = 127.0.0.1
        IP.2 = 127.0.1.1
    mkdir -p apiserver
    openssl genrsa -out apiserver/apiserver-key.pem 2048
    openssl req -new -key apiserver/apiserver-key.pem -out apiserver/apiserver.csr -subj "/CN=kube-apiserver" -config openssl-apiserver.cnf
    openssl x509 -req -in apiserver/apiserver.csr -CA ca/ca.pem -CAkey ca/ca-key.pem -CAcreateserial -out apiserver/apiserver.pem -days 3650 -extensions v3_req -extfile openssl-apiserver.cnf
    cp ca/ca.pem apiserver
    cp ca/ca-key.pem apiserver
    rm apiserver/apiserver.csr
生成kubernetes證書:
    執行腳本./gencerts_aggregator.sh,利用easyrsa生成pki/private/ca.key和pki/ca.crt,cfssl和cfssljson基於ca證書生成pki/issued/proxy-client.crt和pki/private/proxy-client.key,用於apiserver組件--proxy-client-cert-file
    官方kubeadm的yaml除了--proxy-client-cert-file還有--kubelet-client-certificate等,需要的crt和key更多。

下載kubectl二進制文件
    可以從鏡像獲取
    docker create -it --name test dumb008/hyperkube:1.15.0
    docker cp --follow-link=true test:/kubelet /opt/bin/kubelet
    docker cp --follow-link=true test:/kubectl /usr/bin/kubectl
生成kubelet.service服務文件:
    [Service]
    Environment=KUBELET_VERSION=v1.5.2_coreos.0
    Environment="RKT_OPTS=--uuid-file-save=/var/run/kubelet-pod.uuid \
      --volume var-log,kind=host,source=/var/log \
      --mount volume=var-log,target=/var/log \
      --volume dns,kind=host,source=/etc/resolv.conf \
      --mount volume=dns,target=/etc/resolv.conf"

    ExecStartPre=/bin/bash -c 'mkdir -p /etc/kubernetes/manifests'
    ExecStartPre=/bin/bash -c 'mkdir -p /var/log/containers'
    #ExecStartPre=-/usr/bin/rkt rm --uuid-file=/var/run/kubelet-pod.uuid
    ExecStartPre=/bin/bash -c 'if lspci | grep -qE "[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F].[0-9] (3D|VGA compatible) controller: NVIDIA Corporation.*"; then if [ -e /etc/systemd/system/nvidia-docker.service ] ; then until wget -q -O - http://localhost:3476/gpu/info ; do /bin/echo "waiting for nvidia-docker..." ; /bin/sleep 2 ; done fi fi'
    #
    # https://github.com/kubernetes/kubernetes/issues/48937
    # Glusterfs currently need docker-disable-shared-pid option, will evaluate in future kubernete release
    #
    # https://kubernetes.io/docs/tasks/manage-gpus/scheduling-gpus/
    ExecStart=/opt/bin/kubelet \
      --volume-plugin-dir=/etc/kubernetes/volumeplugins \
      --kubeconfig=/etc/kubernetes/worker-kubeconfig.yaml \
      --register-with-taints=node-role.kubernetes.io/master=:NoSchedule \
      --pod-infra-container-image=dlws/pause-amd64:3.0 \
      --container-runtime=docker \
      --feature-gates="DevicePlugins=true,PodShareProcessNamespace=true" \
      --pod-manifest-path=/etc/kubernetes/manifests \
      --network-plugin=cni \
      --cluster_dns=10.3.0.53 \
      --cluster_domain=cluster.local
    #ExecStop=-/usr/bin/rkt stop --uuid-file=/var/run/kubelet-pod.uuid
    Restart=always
    RestartSec=10
    [Install]
    WantedBy=multi-user.target
復制證書文件、bin文件、kube系統的yaml文件以及其他文件到master
    /etc/kubernetes/ssl/ca-key.pem
    /etc/kubernetes/ssl/ca.pem
    /etc/kubernetes/ssl/apiserver.pem
    /etc/kubernetes/ssl/apiserver-key.pem
    ...
    kube-apiserver.yaml                     # 里面的image為hyperkube,但可以參考官方的yaml文件
    kube-controller-manager.yaml 
    kube-scheduler.yaml
3.啟動kubelet
    sudo cp /etc/kubernetes/ssl/ca.pem /etc/ssl/etcd/ca.pem
    sudo cp /etc/kubernetes/ssl/ca-key.pem /etc/ssl/etcd//ca-key.pem
    sudo cp /etc/kubernetes/ssl/apiserver.pem /etc/ssl/etcd/apiserver.pem
    sudo cp /etc/kubernetes/ssl/apiserver-key.pem /etc/ssl/etcd/apiserver-key.pem
    sudo chmod +x /opt/bin/* 
    sudo systemctl daemon-reload
    sudo systemctl stop kubelet
    sudo systemctl start kubelet
    sudo systemctl start rpc-statd
    sudo systemctl enable kubelet
kubelet啟動后,查看status是否正常,docker ps查看manifests的幾個組件是否啟動
    systemctl status kubelet 
    journalctl -xeu kubelet查看具體報錯原因,比如image拉取問題
    docker ps 
    注:kubelet維護kube-apiserver kube-controller-manager kube-scheduler的正常運行,另外一種做法就是將kube-apiserver kube-controller-manager kube-scheduler單獨維護service,無需kubelet來維護,也可以用kubectl
        kubelet此外還負責pod管理、節點管理等
等待8080端口(scheduler監聽)啟動后,kubectl即可用
    kubectl get node 
    kubectl apply 
通過kubectl和yaml啟動weave、dns-addon、kube-proxy
    kubectl apply -f /opt/addons/kube-addons/weave.yaml --validate=false
    kubectl apply -f /opt/addons/kube-addons/dns-addon.yml --validate=false
    kubectl apply -f /opt/addons/kube-addons/kube-proxy.json --validate=false

問題: 
    1.weave啟動失敗,獲取kubernetes service失敗Get https://10.3.0.1:443/api/v1/nodes: dial tcp 10.3.0.1:443: i/o timeout
        原因1:
            發現apiserver組件log異常,Resetting endpoints for master service "kubernetes" to [127.0.0.1]
            原來是yaml里面的--advertise-address指定了127.0.0.1
        原因2:
            kube-proxy是否正常啟動,它負責了iptables的建立,實現service與pod間的iptables調度或ipvs調度、即pod與集群間通信
    2.kube-dns服務不好用 
        dns-addon組件log是否異常,然后定位本地的systemd-resolved是否啟動。

如何clean集群:
    sudo systemctl stop kubelet
    sudo systemctl stop etcd3
    sudo timeout 10 docker rm -f $(docker ps -a | grep 'k8s_kube\|k8s_POD\|k8s_' | awk '{print $1}')
    sudo rm -r /etc/kubernetes
    sudo rm -r /etc/ssl/etcd
    rm -r /var/etcd/data
    rm -r /etc/etcd/ssl
    sudo rm -r /etc/flannel
    sudo rm -r /opt/addons
    sudo systemctl daemon-reload

二進制做法:

1.安裝chrony時間服務

apt remove -y ntp
apt install chrony
配置一下主master上的/etc/chrony/chrony.conf,修改一下server地址、allow
然后配置其他節點的pool為第一個master

2.生成CA根證書和私鑰

安裝cfssl:
apt install golang-cfssl
配置文件ca-config.json、ca-csr.json,里面不包含具體信息
執行cfssl gencert -initca ca-csr.json|cfssljson -bare ca生成ca.csr、ca-key.pem、ca.pem

3.生成對應的數字證書和私鑰用於kubectl、proxy、manager、scheduler

設置kubectl
    配置admin-csr.json簽名請求,里面不包含具體ip信息,只有admin這個用戶名
    簽發數字證書和私鑰,生成admin.csr、admin-key.pem、admin.pem
        cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin
    設置集群參數kubectl config set-cluster DLWS --certificate-authority=/root/kubernetes/ssl/ca.pem --embed-certs=true --server=https://192.168.1.184:6443    # 沒有指定路徑的話,生成文件/root/.kube/config
    設置客戶端認證參數kubectl config set-credentials admin --client-certificate=/root/kubernetes/ssl/admin.pem --embed-certs=true --client-key=/root/kubernetes/ssl/admin-key.pem # --embed-certs為true,將證書寫入文件
    設置上下文參數kubectl config set-context context-DLWS-admin --cluster=DLWS --user=admin
    選擇默認上下文kubectl config use-context context-DLWS-admin
    確認:kubectl config view
設置proxy,作為該組件的kubeconfig以獲取集群資源:
    准備文件kube-proxy-csr.json,里面不包含具體信息
    簽發: 
        cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
    設置集群參數kubectl config set-cluster DLWS --certificate-authority=ca.pem --embed-certs=true --server=https://192.168.1.184:6443 --kubeconfig=./kube-proxy.kubeconfig
    設置客戶端認證參數kubectl config set-credentials kube-proxy --client-certificate=kube-proxy.pem --embed-certs=true --client-key=kube-proxy-key.pem --kubeconfig=./kube-proxy.kubeconfig
    設置上下文參數kubectl config set-context default --cluster=DLWS --user=kube-proxy --kubeconfig=./kube-proxy.kubeconfig
    選擇默認上下文kubectl config use-context default --kubeconfig=./kube-proxy.kubeconfig
設置kube-controller-manager,作為該組件的kubeconfig以獲取集群資源
    准備文件kube-controller-manager-csr.json,里面不包含具體信息
    簽發: 
        cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager
    設置集群參數kubectl config set-cluster DLWS --certificate-authority=ca.pem --embed-certs=true --server=https://192.168.1.184:6443 --kubeconfig=./kube-controller-manager.kubeconfig
    設置客戶端認證參數kubectl config set-credentials system:kube-controller-manager --client-certificate=kube-controller-manager.pem --embed-certs=true --client-key=kube-controller-manager-key.pem --kubeconfig=./kube-controller-manager.kubeconfig
    設置上下文參數kubectl config set-context default --cluster=DLWS --user=system:kube-controller-manager --kubeconfig=./kube-controller-manager.kubeconfig
    選擇默認上下文kubectl config use-context default --kubeconfig=./kube-controller-manager.kubeconfig
設置kube-scheduler,作為該組件的kubeconfig以獲取集群資源:
    准備文件kube-scheduler-csr.json,里面不包含具體信息
    簽發: 
        cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-scheduler-csr.json | cfssljson -bare kube-scheduler
    生成config文件kubectl config set-cluster DLWS --certificate-authority=ca.pem --embed-certs=true --server=https://192.168.1.184:6443 --kubeconfig=./kube-scheduler.kubeconfig
    設置客戶端認證參數kubectl config set-credentials system:kube-scheduler --client-certificate=kube-scheduler.pem --embed-certs=true --client-key=kube-scheduler-key.pem --kubeconfig=./kube-scheduler.kubeconfig
    設置上下文參數kubectl config set-context default --cluster=DLWS --user=system:kube-scheduler --kubeconfig=./kube-scheduler.kubeconfig
    選擇默認上下文kubectl config use-context default --kubeconfig=./kube-scheduler.kubeconfig
復制到節點的對應目錄:
    cp kube-proxy.kubeconfig kube-controller-manager.kubeconfig kube-scheduler.kubeconfig /etc/kubernetes/   # 如果復制到其他master,需要替換掉其中的server ip

4.下載bin文件,生成etcd證書和私鑰,systemctl維護etcd服務(可以宿主機上后台進程)

ETCD_VER=v3.4.13
wget --tries=10 https://github.com/etcd-io/etcd/releases/download/$ETCD_VER/etcd-$ETCD_VER-linux-amd64.tar.gz
tar zxf etcd-$ETCD_VER-linux-amd64.tar.gz && cd etcd-$ETCD_VER-linux-amd64 && cp etcd etcdctl /opt/kube/bin
准備文件etcd-csr.json,里面包含具體ip信息hosts
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes etcd-csr.json | cfssljson -bare etcd
cp etcd-key.pem etcd.pem /etc/etcd/ssl/
mkdir /etc/kubernetes/ssl/
cp ca.pem ca-key.pem ca-config.json /etc/kubernetes/ssl/
准備etcd的service文件,復制到/etc/systemd/system/etcd.service
mkdir /var/lib/etcd
systemctl enable etcd
systemctl daemon-reload && systemctl restart etcd
服務起來后,監聽端口2379,用於與client端交互,監聽peer端口2380用於etcd內部交互

5.下載二進制文件,生成k8s證書,創建aggregator proxy相關證書,然后systemctl維護kube-apiserver kube-controller-manager kube-scheduler(可以宿主機上后台進程),kubectl即可用

K8S_VER=v1.18.0
wget --tries=10 https://dl.k8s.io/$K8S_VER/kubernetes-server-linux-amd64.tar.gz
tar zxf kubernetes-server-linux-amd64.tar.gz && cd kubernetes/server/bin && cp kube-apiserver kube-controller-manager kube-scheduler kubelet kube-proxy kubectl /opt/kube/bin
mkdir /opt/cni/bin
准備cni插件,必須,kubeadm安裝的話自帶,二進制的話必須手動復制(cni插件是給coredns用的,默認讀取/opt/cni/bin/路徑)
    CNI_VER=v0.8.7
    wget --tries=10 https://github.com/containernetworking/plugins/releases/download/$CNI_VER/cni-plugins-linux-amd64-$CNI_VER.tgz
    tar zxf cni-plugins-linux-amd64-$CNI_VER.tgz && cp bridge flannel host-local loopback portmap tuning /opt/cni/bin
准備文件kubernetes-csr.json,填上允許的ip,用於apiserver來決定從哪些ip(即kubeconfig中的server)可以訪問它(如果用了vip,則建議除了各master的ip,加上vip)
    cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes
准備aggregator-proxy-csr.json,不包含ip信息
    cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes aggregator-proxy-csr.json |
 cfssljson -bare aggregator-proxy
准備三個系統組件的service文件
    cp kube-apiserver.service kube-controller-manager.service kube-scheduler.service /etc/systemd/system/   
    復制相應的證書
    cp kubernetes-key.pem kubernetes.pem /etc/kubernetes/ssl/
    cp aggregator-proxy-key.pem aggregator-proxy.pem /etc/kubernetes/ssl/
    cp admin-key.pem admin.pem /etc/kubernetes/ssl/
systemctl enable kube-apiserver kube-controller-manager kube-scheduler
systemctl daemon-reload
systemctl start kube-apiserver kube-controller-manager kube-scheduler
各個狀態均為running即可。
6.master部署kubelet和kube-proxy,然后kubectl get node信息才獲取到。

7.部署網絡組件、dns(順序可選最后),node變為ready

kubectl apply -f weave-role.yaml
kubectl apply -f weave.yaml
刪除原有cni配置/etc/cni/net.d/10-default.conf 
ip link set mynet0 down
ip link del mynet0
重啟docker、kubelet、kube-proxy
准備coredns文件
kubectl apply -f coredns.yaml

8.kubelet證書和kubeconfig,kube-proxy證書和kubeconfig,worker節點復制證書、部署kubelet和kube-proxy

准備文件kubelet-csr.json,包含節點具體ip信息
    證書除了用於生成kubeconfig,還用於kubelet的tlsCertFile。tlsCertFile包含的ip信息也會用於kubelet來與apiserver(ca證書)通信驗證hosts,所以新的節點ip也要更新。
    否則,Error from server: Get https://192.168.1.153:10250/containerLogs/kube-system/kube-vip-3/kube-vip?follow=true: x509: certificate is valid for 127.0.0.1, 192.168.1.83, not 192.168.1.153
    至於kubeconfig中的ca證書hosts是否包含ip,目前好像沒影響,只要求對應的user是相應的system:node:192.168.1.153即可。
    cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kubelet-csr.json | cfssljson -bare kubelet
    cp kubelet-key.pem kubelet.pem /etc/kubernetes/ssl/     # 其他節點的話,就用scp即可
生成config文件kubectl config set-cluster kubernetes --certificate-authority=ca.pem --embed-certs=true --server=https://192.168.1.184:6443 --kubeconfig=./kubelet.kubeconfig
設置客戶端認證參數kubectl config set-credentials system:node:192.168.1.184 --client-certificate=kubelet.pem --embed-certs=true --client-key=kubelet-key.pem --kubeconfig=./kubelet.kubeconfig
設置上下文參數kubectl config set-context default --cluster=kubernetes --user=system:node:192.168.1.184 --kubeconfig=./kubelet.kubeconfig
選擇默認上下文kubectl config use-context default --kubeconfig=./kubelet.kubeconfig,使得kubelet可以訪問集群資源,role為system:node
cp ./kubelet.kubeconfig /etc/kubernetes/
准備cni配置/etc/cni/net.d/10-default.conf        # 用於初始化master的時候kubelet變為ready用的,不然一直不ready,因為這個時候network插件還沒部署。Unable to update cni config: no networks found in /etc/cni/net.d
准備kubelet yaml文件/var/lib/kubelet/config.yaml
准備kubelet.service文件/etc/systemd/system/kubelet.service
systemctl enable kubelet
systemctl daemon-reload && systemctl restart kubelet
准備kube-proxy文件/etc/systemd/system/kube-proxy.service
mkdir /var/lib/kube-proxy
systemctl enable kube-proxy
systemctl daemon-reload && systemctl restart kube-proxy
為節點打上相應的role名字kubectl label node 192.168.1.184 kubernetes.io/role=master --overwrite

擴容worker:

cp ca.pem ca-key.pem ca-config.json /etc/kubernetes/ssl/
准備/opt/cni/bin和/opt/kube/bin/
swapoff -a && sed -i '/swap/d' /etc/fstab && sysctl -w vm.swappiness=0
為該節點生成對應ip的kubelet-key.pem kubelet.pem(kubeconfig要重新生成,否則提示system:node:192.168.1.83cannot get resource,can only access node lease with the same name)
scp ca.pem ca-key.pem ca-config.json /etc/kubernetes/ssl/
准備文件/var/lib/kubelet/config.yaml和/etc/systemd/system/kube-proxy.service、/etc/systemd/system/kube-proxy.service
啟動kubelet和kube-proxy

擴容master:

在worker的基礎上
scp kube-proxy.kubeconfig kube-controller-manager.kubeconfig kube-scheduler.kubeconfig /etc/kubernetes/  # 每個master的可以不同。
關於etcd:
    原有的etcd高可用集群,一開始初始化的時候都配置好了集群的成員member,而且/var/lib/etcd/為空,master一個個順序起來是可以的。
    擴容相當於在/var/lib/etcd/數據已存在,member已確定的情況下,再添加一個node,這是不允許的。
    對於擴容,由於member信息已經寫好,需要通過命令行增加member才行
        ./etcdctl member list
        ./etcdctl member add etcd2 --peer-urls=https://192.168.1.162:2380       # 否則error validating peerURLs,member count is unequal
    然后etcd的service文件中需要配置--initial-cluster-state=existing               # 否則提示cluster ID mismatc,is starting a new election at term 173
        service文件中的name要修改對應
    不重新簽發證書會提示rejected connection from "192.168.1.162:60004" (error "remote error: tls: bad certificate", ServerName "")
重新簽發etcd證書,增加新的ip,        # 每個master的該證書可以不同,只保留自己ip。
准備/etc/systemd/system/etcd.service
啟動etcd
重新簽發apiserver證書-kubernetes,增加新的hosts ip來允許從哪個節點上可以訪問它,復制到每個master上。該證書每個節點也可以不同。
cp kube-apiserver.service kube-controller-manager.service kube-scheduler.service /etc/systemd/system/        # kube-apiserver.service中的etcd server看情況需要增加
cp kubernetes-key.pem kubernetes.pem aggregator-proxy-key.pem aggregator-proxy.pem admin-key.pem admin.pem /etc/kubernetes/ssl/
cp kube-proxy.kubeconfig kube-controller-manager.kubeconfig kube-scheduler.kubeconfig /etc/kubernetes/
systemctl enable kube-apiserver kube-controller-manager kube-scheduler
systemctl start kube-apiserver kube-controller-manager kube-scheduler

問題:etcd不斷在選擇,is starting a new election at term 1109,原因有兩個
    1.高可用的集群中,etcd的數量不夠2個。
    2.etcd初始化由於各種原因加入失敗,一直嘗試加入。

關於kube-vip,可以在kuernetes的主要組件起來后,啟用network后,再啟用vip.yaml文件,pod起來后,即可搭建一個vip供訪問。        
部署方式一:先啟動kube-vip組件就提供一個虛擬ip,
    kubeadm部署的話,沒有指定配置文件,但是傳了kubeconfig,也可以獲取到localPeer、remotePeers的信息。
    kubeadm init初始化的時候指定--control-plane-endpoint為vip,為所有控制平面節點設置共享端點。
    部署: 
        vip=192.168.1.35
        docker run --network host --rm plndr/kube-vip:0.2.1 manifest pod --interface ens3 --vip $vip --arp --leaderElection | sudo tee /etc/kubernetes/manifests/vip.yaml
        kubeadm init --kubernetes-version=v1.18.2 --control-plane-endpoint $vip --upload-certs
            初始化完成后,會給出其余master和worker join的命令
            這個時候節點還沒ready,因為Unable to update cni config: no networks found in /etc/cni/net.d,部署weave后coredns和集群網絡正常,node變為ready
        kubeadm join 192.168.1.35:6443 --token ixbsy4.ku7tjmmzgjp307io --discovery-token-ca-cert-hash sha256:4572e960edd6ea8 --control-plane --certificate-key 1ac26cc40c9f6d8a23eb414e361ed8d8a3d9fe1d6df2fc076f61dbc7425d7ab5
            其中的certificate-key可以通過kubeadm init phase upload-certs --upload-certs得出,token可以通過kubeadm token create或kubeadm token create --print-join-command,
            discovery-token-ca-cert-hash可以通過openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
            問題: 
                如果一開始join失敗,后面再join會出現etcd等待第二個節點選舉的問題,導致vip等待etcd一直起不來,導致apiserver(6443)用vip無法訪問,同時也導致kubelet無法訪問apiserver無法提供管理服務,
                將主節點重新部署后,一次性加入即可成功。如果嘗試清空/var/lib/etcd會導致集群信息丟失。
                兩個master節點的集群當一個master停機時也會這樣。
        docker run --network host --rm plndr/kube-vip:0.2.1 manifest pod --interface ens3 --vip $vip --arp --leaderElection | sudo tee /etc/kubernetes/manifests/vip.yaml
            注意不同節點的網卡可能不同。
    高可用:
        一個非leader的node停機時,其他節點的etcd會嘗試連接該節點,vip繼續正常工作。
        兩個非leader的node停機時,當前leader的vip由於etcd忙於選舉,起不來,整個服務停止。開機后恢復正常。
        leader所在node停機時,vip組件切換leader,提示This node is starting with leadership of the cluster,Broadcasting ARP update
        delete一個node時,該node上還存在vip,vip不會漂移,因為kubelet服務沒停,manifest還存在,直到kubeadm reset停掉container
        delete的節點需要處理etcd才能重新作為master加入。如果是worker則不用。如果是vip節點,還要ip ad del。
            ETCDCTL_API=3 ./etcdctl --endpoints=127.0.0.1:2379 member list --cacert /etc/kubernetes/pki/etcd/server.crt --cert /etc/kubernetes/pki/etcd/peer.crt --key /etc/kubernetes/pki/etcd/peer.key
            ETCDCTL_API=3 ./etcdctl --endpoints=127.0.0.1:2379 member remove xxx --cacert /etc/kubernetes/pki/etcd/server.crt --cert /etc/kubernetes/pki/etcd/peer.crt --key /etc/kubernetes/pki/etcd/peer.key

    目前來看主要體現為
        1.生成的kubeconfig文件里的server ip為vip。各個master的kubelet、apiserver等的ip還是自己的。
        2.apiserver使用的證書多加上了vip。

部署方式二:集群各個node起來后,通過kube-vip組件提供一個高可用的vip
    流程:
        1.准備配置文件config.yaml,里面配置了localPeer、remotePeers、loadBalancers等,用於選舉leader和負載均衡
        2.cp config.yaml /etc/kube-vip/config.yaml
        3.准備yaml文件kube-vip.yaml,每個kube-vip需要指定運行的nodeName,不然會重復分配到一個節點上
        4.kubectl apply -f kube-vip.yaml
        5.同時,之前簽發的kubeconfig要確保server地址為vip,才能高可用(否則當最初節點停機后,其他master不能調度)。
    注意: 
        kubeconfig要確保server地址為vip
    HA高可用原理:
        vip在多個master之間漂移,多個master的ip中之一。訪問的是當前leader所在節點的業務服務,要求master之間都有有完整的業務系統。

        多個master啟動kube-apiserver kube-controller-manager kube-scheduler的address填的都是自己的ip,但etcd的--etcd-servers填的是同一個,這樣存儲是相同的。
            也就是說,多master能實現同一個集群而不是單獨的集群,是通過同一個etcd來實現的。

        worker的kubelet通過--kubeconfig里指定的server ip(vip)(set-cluster步驟生成)來向master通信請求,如表示worker自己處於ready狀態,master可以向worker分配job。
            master和worker的kubelet.kubeconfig權限不一樣(通過clusterrolebinding指定User或者Group,非ServiceAccount)。
            只要worker上的kubelet和kube-proxy起來后,kubectl get node就可以看到node了。這時候role還沒分配而已。這時候可以分配job了。
            role沒有實際的用途,taint還有一點。

        那么,如果vip組件在k8s之上的一層組件的話,可以在集群master都起來后再啟動。

        master和worker節點的區別:
            worker節點上只運行了kubelet和kube-proxy。
            master除了運行了三個系統組件外,和worker的區別就是role的不同,導致了taint的不同。(可以將worker標記為master,但沒有三個組件,會異常)

vip工作原理: 
    arp廣播,配置localPeer、remotePeers、loadBalancers等,用於選舉leader,至少兩個節點(超過配置的半數)才能選舉成功。單個節點也可以。
    需要startAsLeader: false      # 是否一開始就作為leader,多個實例時后面的實例需要為false。不然都廣播,arp會收到多個包。

    實現方式:
        1.網卡雙ip的方式
            ifconfig ens3:1 192.168.1.42/24或ip ad add 192.168.1.42/24 dev ens3
            手動增加可以體驗arping收到多個來源
        2.網卡雙ip+arp廣播實時更新其他機器(除沒有重啟的舊leader)的arp表
            gratuitousARP: true(在2.2版本上為enableARP)
        3.BGP方式
        4.Packet方式

    擴容:
        一個kube-vip節點起來后,開始當leader
        新加入master后,需要先修改之前master的配置,增加ip,重啟(否則新節點的投票會被拒絕), 然后新的master才能正常啟動。

    測試:
        通過stop docker可以看到選舉過程。
        1.至少需要兩票,所以節點數量得為單數。
        2.leader負責與其他候選人通信,當失聯時一直嘗試,直到恢復。
        3.當leader失聯時,兩個節點進行選舉,選出新的leader

    問題: 
        選舉新的leader后,如果機器沒有停電,只是關閉docker:
            1.除了剩余master所在的機器(永遠實時更新),其他機器ip指向還是舊的(可以收到新的和舊的arp包,ssh登錄使用舊的)。
                新增:可以通過ip route get 192.168.1.42查看可能的路由,如果是舊leader,雙網卡,返回的是dev lo
            2.提供的6443還能訪問舊的節點服務。
            3.使用arping/arp指令獲取到的mac地址是新的,但ping、ssh等命令還是用舊的。
            4.tcpdump、nc等命令試了沒效果,可以嘗試arp -an和ip neigh查看arp緩存還是舊的mac地址,使用ip neigh flush清空后再ping可以獲取新的mac地址。
                但一段時間后,機器的arp表又變回舊的mac地址,估計舊的一直在廣播。
                新的機器如果從來沒有獲取過vip,可能優先選擇舊的。
            5.原leader可以ip add show查看到vip綁定到網卡的inet上。執行刪除ip ad del 192.168.1.42/24 dev ens3和清空arp后其他機器不再收到舊的arp包(leader切換會自動在舊機器執行這個)。
                原leader的雙ip不會自動刪除,需要重新上線后由pod自己刪除。

特點:

1.采用Chrony進行時間同步
NTP 客戶端的替代品,更快的同步只需要數分鍾而非數小時時間,從而最大程度減少了時間和頻率誤差,對於並非全天 24 小時運行的虛擬計算機而言非常有用
2.Cfsslopenssl區別在於cfssl可以使用json格式,較方便。    

證書對比kubeadm:

admin-key.pem                    用於apiserver的--kubelet-client-key(kubelet TLS 客戶端密鑰文件)pki/apiserver-kubelet-client.key       
admin.pem                        用於apiserver的--kubelet-client-certificate                        pki/apiserver-kubelet-client.crt        
aggregator-proxy-key.pem        用於apiserver的--proxy-client-key-file(調用外部程序以處理請求)pki/front-proxy-client.key              
aggregator-proxy.pem            用於apiserver的--proxy-client-cert-file                            pki/front-proxy-client.crt              
ca-key.pem                        用於controller-manager的--cluster-signing-key-file             pki/ca.key
                                用於controller-manager的--service-account-private-key-file     pki/sa.key                                          
ca.pem                            用於controller-manager的--cluster-signing-cert-file                pki/ca.crt
                                用於controller-manager的--root-ca-file                         pki/ca.crt
                                /var/lib/kubelet/config.yaml                                    pki/ca.crt
                                用於etcd的--trusted-ca-file                                        pki/etcd/ca.crt
                                用於etcd的--peer-trusted-ca-file                               pki/etcd/ca.crt
                                用於apiserver的--client-ca-file                                    pki/ca.crt
                                用於apiserver的--etcd-cafile(用於保護 etcd 通信的 SSL 證書頒發機構文件)pki/etcd/ca.crt
                                用於apiserver的--kubelet-certificate-authority                 kubeadm中沒有,證書頒發機構的證書文件的路徑。
                                用於apiserver的--service-account-key-file                      pki/sa.pub
                                用於apiserver的--requestheader-client-ca-file(驗證接入請求中客戶端證書的根證書包)pki/front-proxy-ca.crt
etcd-key.pem                    用於etcd的--key-file                                           pki/etcd/server.key
                                用於etcd的--peer-key-file                                      pki/etcd/peer.key
etcd.pem                        用於etcd的--cert-file                                          pki/etcd/server.crt 
                                用於etcd的--peer-cert-file                                     pki/etcd/peer.crt   
kube-controller-manager-key.pem
kube-controller-manager.pem
kube-controller-manager.kubeconfig 用於controller-manager的--kubeconfig                            controller-manager.conf
kubelet-key.pem                    用於/var/lib/kubelet/config.yaml的tlsPrivateKeyFile                kubeadm中的kubelet沒用上
kubelet.pem                        用於/var/lib/kubelet/config.yaml的tlsCertFile                  kubeadm中的kubelet沒用上
kube-proxy-key.pem                
kube-proxy.pem
kube-proxy.kubeconfig            用於kube-proxy service的--kubeconfig                           kubeadm中的daemon資源的kube-proxy這個configmap
kubernetes-key.pem                用於apiserver的--etcd-keyfile(用於保護 etcd 通信的 SSL 密鑰文件)pki/apiserver-etcd-client.key
                                用於apiserver的--tls-private-key-file(候選service-account-key-file)pki/apiserver.key
kubernetes.pem                    用於kube-apiserver的--tls-cert-file                                pki/apiserver.crt
                                用於apiserver的--etcd-certfile                                 pki/apiserver-etcd-client.crt
kube-scheduler-key.pem            
kube-scheduler.pem
kube-scheduler.kubeconfig        用於kube-scheduler的--kubeconfig                               scheduler.conf

卸載weave流程:

1.刪除weave的k8s資源
2.rm -rf /etc/cni/net.d/10-weave.conflist

卸載集群:

1.清理etcd
systemctl stop etcd 
systemctl disable etcd 
rm -rf /var/lib/etcd /etc/etcd/ /etc/systemd/system/etcd.service
2.清理三個系統組件
systemctl stop kube-apiserver kube-controller-manager kube-scheduler
systemctl disable kube-apiserver kube-controller-manager kube-scheduler
rm -rf /var/run/kubernetes /etc/systemd/system/kube-apiserver.service /etc/systemd/system/kube-controller-manager.service /etc/systemd/system/kube-scheduler.service
3.清理kubelet和kube-proxy
systemctl stop kubelet kube-proxy
systemctl disable kubelet kube-proxy
mount | grep '/var/lib/kubelet'| awk '{print $3}'|xargs umount || exit 0
rm -rf /var/lib/kubelet/ /var/lib/kube-proxy/ /etc/systemd/system/kubelet.service /etc/systemd/system/kube-proxy.service /opt/kube/kube-system/ /etc/kubernetes/
umount目錄:
    /var/run/docker/netns/default
    echo /var/lib/docker/overlay2/*/merged|xargs umount
    /var/lib/docker/overlay
    echo /var/lib/docker/containers/*/
mounts/shm|xargs umount
    echo /var/run/docker/netns/*|xargs umount


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM