Master/node
Master核心組件: API server,Scheduler,Controller-Manager etcd(存儲組件)
Node核心組件: kubelet(核心組件), docke(容器引擎(支持的引擎不止docker一個)), kube-proxy
Pod Label, label selector
Label: key=value
Label Selector:
Pod:
自主式Pod
控制器管理的Pod
ReplictionController(老版本控制器)
ReplicaSet(新版本控制器)
Deployment #通過控制replicaset來控制pod,最應該掌握的控制器之一
StatefuSet
Job,Ctonjob
AddOns: 附加組件
環境准備:、
Master, etcd: 172.18.0.70
Node1: 172.18.0.67
Node2: 172.18.0.68
前提:
- 基於主機名通信: /etc/hosts
- 時間同步 要不然會出一大推亂七八糟的報錯
- 關閉firewall和iptables.service
OS: Centos 7.3.1611 Rxtras倉庫中
安裝配置步驟:
- Etcd cluster, 近master節點
- Flannel,集群的所有節點
- 配置k8s的master: 僅master節點
Kubernetes-master
啟動的服務:
Kube-apiserver, kube-scheduler, kube-controller-manager
- 配置k8s的各node節點:
Kubernetes-node
先設定啟動docker服務
啟動的k8s的服務
Kube-proxy, kubelet
補充知識:harbor 鏡像倉庫
參考 https://www.cnblogs.com/pangguoping/p/7650014.html
k8s
先准備兩台機器:
172.18.0.70 master #
172.18.0.67 node1
172.18.0.68 node2
注意: 一定要做好時間同步 要不然會有一大推莫名其妙的報錯
然后兩台機器都要配置docker和k8s的yum源
#docker18.09版本和k8s1.15.3版本
wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
直接都使用阿里的鏡像源
[root@master ~]# yum list docker-ce --showduplicates | sort -r
#如果對版本有要求可以使用這個查看 18.09,安裝對應的包
所有機器都安裝
[root@master ~]# yum install docker-ce-18.09.3-3.el7
yum -y install kubelet kubeadm kubectl(api命令行工具)
然后准備啟動docker,在啟動docker之前建議先定義一個環境變量 隨便另起一行寫
[root@master ~]# vim /usr/lib/systemd/system/docker.service
Environment="HTTPS_PROXY=http://www.ik8s.io:10080""
#意思是我們訪問docker服務的時候通過代理下載相關的鏡像文件
Environment="NO_PROXY=127.0.0.8,172.18.0.0/16" #不用代理 本機
:wq
docker國內加速
mkdir -p /etc/docker
vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://lvb4p7mn.mirror.aliyuncs.com"]
}
上面這個貌似不太好用,
#!/bin/bash
# download k8s 1.15.3 images
# get image-list by 'kubeadm config images list --kubernetes-version=v1.15.3'
# gcr.azk8s.cn/google-containers == k8s.gcr.io
images=(
kube-apiserver:v1.15.3
kube-controller-manager:v1.15.3
kube-scheduler:v1.15.3
kube-proxy:v1.15.3
pause:3.1
etcd:3.3.10
coredns:1.3.1
)
for imageName in ${images[@]};do
docker pull gcr.azk8s.cn/google-containers/$imageName
docker tag gcr.azk8s.cn/google-containers/$imageName k8s.gcr.io/$imageName
docker rmi gcr.azk8s.cn/google-containers/$imageName
Done
#使用此腳本可以避免因為鏡像源的問題!!!非常重要!!!
加載環境變量
[root@master ~]# systemctl daemon-reload
啟動docker並使用docker info 查看
[root@master ~]# systemctl start docker && docker info
[root@master ~]#
#默認是1就不用改
[root@master ~]# rpm -ql kubelet
/etc/kubernetes/manifests #清單目錄
/etc/sysconfig/kubelet #配置文件
/usr/bin/kubelet
/usr/lib/systemd/system/kubelet.service
[root@master ~]# systemctl enable kubelet.service #設置成開機自啟動就可以了
[root@master ~]# systemctl enable docker
[root@master ~]# kubelet init --help
#准備初始化
要把swap交換分區關了!!!!!!!!
初始化:
[root@master ~]# kubeadm init --kubernetes-version=v1.15.3 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12
##ps: 如果因為鏡像問題可以使用上面的腳本執行,直接拉取鏡像
成功之后會有以下幾條命令,執行一下 注意一定不要忘記執行!!
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
初始化完成之后會有一段token哈希值,加入集群用的非常重要,可以把他先保存下來,如下:
kubeadm join 172.18.0.70:6443 --token nsezuu.f8xhql0lmz262tqv \
--discovery-token-ca-cert-hash sha256:c98f345addbb9a585d1e9edf3f584c9dcee4dbb847a63392dc2ba444e77ec0a7
[root@master ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
k8s.gcr.io/kube-proxy v1.15.3 232b5c793146 8 days ago 82.4MB
k8s.gcr.io/kube-apiserver v1.15.3 5eb2d3fc7a44 8 days ago 207MB
k8s.gcr.io/kube-controller-manager v1.15.3 e77c31de5547 8 days ago 159MB
k8s.gcr.io/kube-scheduler v1.15.3 703f9c69a5d5 8 days ago 81.1MB
k8s.gcr.io/coredns 1.3.1 eb516548c180 7 months ago 40.3MB
k8s.gcr.io/etcd 3.3.10 2c4adeb21b4f 9 months ago 258MB
k8s.gcr.io/pause 3.1 da86e6ba6ca1 20 months ago
成功之后在node1和node2上面都安裝—
[root@node1 ~]# yum install docker-ce-18.09.7-3.el7 kubectl.x86_64 kubelet.x86_64 kubeadm.x86_64
[root@node2 ~]# yum install docker-ce-18.09.7-3.el7 kubectl.x86_64 kubelet.x86_64 kubeadm.x86_64
swap沒關的話就忽略swap參數
vim /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS="--fail-swap-on=false"
KUBE_PROXY_MODE=ipvs
[root@master ~]# kubectl get cs #查看組件信息
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy {"health":"true"}
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master NotReady master 32m v1.15.3
#這里的狀態信息顯示還未准備好是因為缺少一個重要組件flannel
在git上查找flannel獲取以下命令:
[root@master ~]# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
#這是一個在線的部署清單,基於此清單下載鏡像flannel
[root@master ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
master Ready master 41m v1.15.3
#現在就已經准備好了
[root@master ~]# kubectl get ns #查看名稱空間
NAME STATUS AGE
default Active 43m
kube-node-lease Active 43m
kube-public Active 43m
kube-system Active 43m
把master的配置文件分別拷給node1和node2
[root@master ~] scp /usr/lib/systemd/system/docker.service node1:/usr/lib/systemd/system/docker.service
[root@master ~]# scp /usr/lib/systemd/system/docker.service node2:/usr/lib/systemd/system/docker.service
[root@master ~]# scp /etc/sysconfig/kubelet node1:/etc/sysconfig/kubelet
[root@master ~]# scp /etc/sysconfig/kubelet node2:/etc/sysconfig/kubelet
分別在node1和node2上面啟動docker並設置成開啟自啟
[root@node1 ~]# systemctl start docker #啟動docker
[root@node1 ~]# systemctl enable docker.service kubelet.service #設置成開啟自啟
[root@node2 ~]# systemctl start docker #啟動docker
[root@node2 ~]# systemctl enable docker.service kubelet.service #設置成開啟自啟
[root@node1 ~]# kubeadm join 172.18.0.70:6443 --token k0q4vt.2ok77anvdhzip6s8 --discovery-token-ca-cert-hash sha256:77b7364b7fc2c886aa889488d3c06d6c1f3a8a1cfc48a8857354afa749c37630 --ignore-preflight-errors=Swap
[root@node2 ~]# kubeadm join 172.18.0.70:6443 --token k0q4vt.2ok77anvdhzip6s8 --discovery-token-ca-cert-hash sha256:77b7364b7fc2c886aa889488d3c06d6c1f3a8a1cfc48a8857354afa749c37630 --ignore-preflight-errors=Swap
#加入集群
----------------------------------------------------------------------------------------------------------
[root@master ~]# kubectl describe node master #查看節點的詳細信息,比較常用
[root@master ~]# kubectl cluster-info #查看集群信息
使用k8s進行增刪改查
測試:
[root@master ~]# kubectl run nginx-ceshi --image=nginx --port=80 --replicas=1
#啟動一個nginx pod
[root@master ~]# kubectl get pod #查看pod
NAME READY STATUS RESTARTS AGE
nginx-ceshi-748587595b-975t7 0/1 ContainerCreating 0 8s
[root@master ~]# kubectl get svc #查看服務
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 93m
myapp ClusterIP 10.97.57.166 <none> 80/TCP 22s
nginx ClusterIP 10.108.78.248 <none> 80/TCP 72m
[root@master ~]# kubectl scale --replicas=5 deployment myapp
#擴容副本,后面數值多少就是幾個副本
[root@master ~]# kubectl run client1 --image=busybox --replicas=1 -it --restart=Never
#加一個-it表示創建完直接以交互式方式進去,創建一個客戶端進行測試
/ # wget -O - -q 10.244.1.5/hostname.html #查看是從哪個節點上運行的
myapp-84cd4b7f95-mj6k6
[root@master ~]# kubectl describe deployment nginx-ceshi
#查看選擇器詳細信息
[root@master ~]# kubectl get deployment -w
#-w實時查看
[root@master ~]# kubectl set image deployment myapp myapp=ikubernetes/myapp:v2
deployment.extensions/myapp image updated
#使用set image進行版本升級
[root@master ~]# kubectl rollout undo deployment myapp
#使用rollout out進行回滾版本
[root@master ~]# kubectl edit svc myapp
##修改svc內容
27: type: NodePort
#大約27行,吧他修改為NodePort,就可以使用外網訪問了,大小寫不能錯!
[root@master ~]# kubectl get svc #修改完之后使用get svc查看就會發現多一個端口
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 155m
myapp NodePort 10.97.57.166 <none> 80:30257/TCP 62m
刪除node節點:
一共分兩步:
1.排干此節點
kubectl drain 節點名稱 --delete-local-data --force --ignore-daemonsets
2.刪除此節點
kubectl delete node 節點名稱
Yaml:
具體可以參考:https://www.cnblogs.com/LiuQizhong/p/11536127.html
創建資源的方法:
apiserver僅接受JSON格式的資源定義;
yaml格式提供配置清單,apiserver可自動 將其轉化為JSON格式,而后再提交。
大部分資源的配置清單:
[root@master ~]# kubectl explain pod #查看字段,相當於一個幫助
[root@master ~]# kubectl explain pods.status
##查看字段的詳細幫助
apiversion: group/version
kind: 資源類別
metadata: 元數據
name
namespace
Latels
Annotations
每個資源的引用PATH
/api/GROUP/VERSION/namespeaces/NAMESPEACE/TYPE/NAME
Sepc: 期望的狀態
Status: 當前狀態,current state, 這五個一級字段由kubernetes集群維護;
下面是創建了一個pod里面有兩個容器:格式注意下 yaml文件
apiVersion: v1
kind: Pod
metadata:
name: pod-demo
namespace: default
labels:
app: myapp
tier: frontend
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
- name: busybox
image: busybox:latest
command:
- "/bin/sh"
- "-c"
- "echo $(date) >> /usr/share/nginx/html/index.html; sleep 5"
[root@master yamls]# kubectl create -f pod-damo.yaml
#根據清單創建pod
[root@master yamls]# kubectl delete -f pod-damo.yaml
[root@master yamls]# kubectl delete pods pod-demo
#刪除pod
標簽:
Key=value 鍵名和鍵值都必須小於63個字符
Key只能使用: 字母 數字 下划線 點號 , 只能使用字母或數字開頭
Value 可以為空,鍵值不能為空,只能以字母或數字開頭及結尾,之間可使用
[root@master yamls]# kubectl get pod -l app #-l標簽過濾
[root@master yamls]# kubectl label pods pod-demo release=ccc ##打標簽
[root@master yamls]# kubectl get pods -l app --show-labels #查看
節點選擇器:
nodeSelector: yaml參數指定在哪個標簽的node上運行,和containers平行
KEY=VALUE
NodeName :
標識:
annotations: #與label不同的地方在於,它不能用於挑選資源對象,僅用於為對象提供“元數據”,,寫在metadata里面,如下
使用kubectl describe pods pod名字 查看
----------------------------------------------------------------------------------------------------------
Pod的生命周期:
狀態: Pending(掛起), Running,Failed,Succeeded,Unknown
探針:
探針是由kubelet對容器執行的定期診斷,要執行診斷,kubelet調用由容器實現的Handler,有三種類型的探針:
探測方式:
LivenessProbe(存活探測): 指示器是否正在運行。如果存活探測失效,則kubelet會殺死容器,並且容器將受到其重啟策略的影響,如果容器不提供存活探針,則默認狀態為Success
readinessProbe(就緒與否): 指示容器是否准備好服務請求,如果就緒探測失效,斷點控制器將從與Pod匹配的所有service的端點中刪除該Pod的ip地址。初始延遲之前的就緒狀態Failure。如果容器不提供就緒探針,則默認狀態為success
探針類型有三種:
ExecAction TCPSocketAction HTTPGetAction
ExecAction 在容器內執行指定的命令,如果命令退出時返回碼為0則認為診斷成功。
TCPSocketAction 對指定端口上的容器的IP地址進行TCP檢查。如果端口打開,則診斷被認為是成功的
HTTPGetAction 對指定的端口和路徑上的容器的IP地址執行HTTP GET 請求。如果響應的狀態碼大於等於200 且小於 400, 則診斷被認為是成功的
Pod生命周期中的重要行為:
初始化容器
容器探測
Liveness(存活性探測)
Readinessi(就緒與否)
--必須做的
示例:
Init代表延時
Per代表多少秒檢測一次
Livenessprobe-HTTPGetAction:
livenessProbe-tcp
----------------------------------------------------------------------------------------------------------
啟動或退出動作:
[root@master ym]# kubectl explain pods.spec.container.lifecycle #查看pod生命周期幫助
回顧: Pod
apiVersion, kind, metadata, status(只讀)
spec:
containers:
nodeSelector
nodeName
restartPolicy: #重啟策略
Always, Never, OnFailure
containers:
name
image
imagePullPolicy: Always Never IfNotPresent
ports:
name
contarnerPort #暴露端口
livenessProbe #存活性探測
readlinessProbe #就緒狀態探測
Liftcycle #啟動或退出動作
ExecAction: exec
TCPocketAction: tcpSocket
HTTPGetAction: httpGet
Pod 控制器
ReplictionController(老版本控制器)
ReplicaSet(新版本控制器) #支持擴容,直接編輯yaml實時文件replicas
[root@master ~]# kubectl edit rs myapp 保存即生效
Deployment #通過控制replicaset來控制pod,最應該掌握的控制器之一
DaemoSet #控制每個node上都有一個pod副本
Job #一次性
Cronjob
StatefulSet #有狀態
聲明式編程(deployment) apply(優) create
命令式編程(rs) create(優) apply
[root@master ~]# kubectl explain rs #查看新版本控制器的手冊
使用ReplicaSet控制器創建的yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: myapp
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: myapp
release: canary
template:
metadata:
name: myapp-pod
labels:
app: myapp
release: canary
spec:
containers:
- name: myapp-container
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
使用Deployment控制器創建pod
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: myapp
release: canary
template:
metadata:
labels:
app: myapp
release: canary
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
[root@master ~]# kubectl apply -f deplo.yaml
[root@master ~]# kubectl get deploy
[root@master ~]# kubectl get rs
如果想要擴容副本數,直接用vim編輯yaml文件 然后再執行apply -f 創建,apply可以重復創建
[root@master ~]# kubectl describe deploy myapp-deploy #查看詳細信息
改文件也可以使用打補丁的方式:
[root@master ~]# kubectl patch deploy myapp-deploy -p '{"spec":{"replicas":6}}'
[root@master ~]# kubectl explain deploy.spec.strategy.rollingUpdate #查看幫滾動更新策略幫助
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
滾動更新:
1 直接修改yaml文件然后apply執行就可以
2 如果只更新鏡像版本 可以使用 kubectl set image
[root@master ~]# kubectl set image deploy myapp-deploy myapp=ikubernetes/myapp:v3
[root@master ~]# kubectl set image deploy myapp-deploy myapp=ikubernetes/myapp:v3 && kubectl rollout pause deploy myapp-deploy #金絲雀發布
[root@master ~]# kubectl get rs -o wide #查看歷史版本
回滾:
[root@master ~]# kubectl rollout undo -h
[root@master ~]# kubectl rollout history deploy myapp-deploy #查看版本
[root@master ~]# kubectl rollout undo deploy/myapp-deploy --to-revision=1
使用DamoSet控制器 實例:
[root@master ~]# kubectl explain ds ds縮寫 每個node運行一個pod
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: redis
role: logstor
template:
metadata:
labels:
app: redis
role: logstor
spec:
containers:
- name: redis
image: redis:4.0-alpine
ports:
- name: redis
containerPort: 6379
--- #用三橫杠隔開就可以寫在同一個yaml文件里
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: myapp-ds
namespace: default
spec:
selector:
matchLabels:
release: stable
app: filebeat
template:
metadata:
labels:
app: filebeat
release: stable
spec:
containers:
- name: filebeat
image: ikubernetes/filebeat:5.6.5-alpine
env:
- name: REDIS_HOST
value: redis.default.svc.cluster.local
- name: redis_log
value: info+
兩個pod之前聯動靠svc
Job控制器
Conjob控制器案例:
Service:
工作模式: userspace, iptables, ipvs
Userspace: 1.1
iptables: 1.10
Ipvs: 1.11+
類型:
ExternalName,ClusterIP(集群內部), NodePort, and LoadBalancer
NodePort:
過程:Client-->NodeIP:NodePort-->ClusterIP:ServicePort-->PodIP:contarinersPort
資源記錄:
SVC_NAME. NS_NAME DAMAIN.LTD
Svc.Cluster.Local
Redis.default.svc.cluster.local
Svc通過標簽關聯pod
案列:
·
Headless service(無頭服務)
有時不需要或不想要負載均衡,以及單獨的service ip 。遇到這種情況,可以通過指定cluster ip(spec.cluster IP)的值為“None”來創建headless service。這類service並不會分配cluster IP,kube-proxy不會處理它們,而且平台也不會為它們進行負載均衡和路由
實例:
NodePort:
Ingress-nginx
Ingress-nginx: https://kubernetes.github.io/ingress-nginx/deploy/
-------------------------------------------------------------------------------------------
存儲卷:
介紹:
容器磁盤上的文件的生命周期是短暫的,這就使得在容器中運行重要應用時會出現一些問題,首先,當容器奔潰時,kubelet會重啟它,但是容器中的文件將丟失--容器以干凈的狀態(鏡像最初的狀態)重新啟動,其次在pod中同時運行多個容器時,這些容器之前通常需要共享文件。Kubernetes中的volume抽象就很好的解決了這些問題
Kubernetes支持以下類型的卷:
SAN(本地存儲): ISCSI
NAS(網絡存儲): nfs, cifs
分布式存儲: glusterfs, rbd, cephfs
雲存儲:EBS(亞馬遜的),Azure Disk(微軟的)
# Kubectl explain pods.spec.volumes 這里顯示它支持哪些存儲
[root@master ~]# kubectl explain pods.spec.volumes.emptyDir
[root@master ~]# kubectl explain pods.spec.containers.volumeMounts
apiVersion: v1
kind: Pod
metadata:
name: pod-demo
namespace: default
labels:
app: myapp
tier: frontend
annotations:
magedu.com/created-by: "cluster admin"
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
- name: https
containerPort: 443
volumeMounts:
- name: html
mountPath: /data/web/html
- name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
command:
- "/bin/sh"
- "-c"
- "sleep 7200"
volumeMounts:
- name: html
mountPath: /data/
volumes:
- name: html
emptyDir: {}
hostPath: 節點級存儲 缺點節點壞了,數據也就沒了
Hostpath卷將主機節點的文件系統中的文件或目錄掛載到集群中
Hostpath的用途如下:
示例:
apiVersion: v1
kind: Pod
metadata:
name: pod-vol
namespace: default
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html/
volumes:
- name: html
hostPath:
path: /data/pod/volume1
type: DirectoryOrCreate
NFS: 網絡持久化存儲
PVC:
概念:
PersistentVolume(pv)
是由管理員設置的存儲,它是集群的一部分。就像節點是集群中的資源一樣,pv也是集群中的資源。Pv是volume之類的卷插件,但具有獨立於使用pv的pod的生命周期。此api對象包含存儲實現的細節,即NFS iscsi或特定於雲供應商的存儲系統
PersistentVolumeClaim(pvc)
是用戶存儲的請求,它與pod相似。Pod消耗節點資源,pvc消耗pv資源。Pod可以請求特定級別的資源(cpu或內存)。它聲明可以請求特定的大小和訪問模式(例如,可以以讀/寫或一次貨只讀多次模式掛載)
綁定:
Master中的控制環路監視新的pvc,尋找匹配的pv(如果可能),能將它們綁定在一起,如果為新的pvc動態調配pv,則該環路將始終將該pv綁定到pvc。否則,用戶總戶得到他們請求的存儲。但是容量可能超出要求的數量,一旦pv和pvc綁定后,pvc綁定是排他性的,不管他們是如何綁定的。Pvc跟pv綁定是一對一的映射關系。
狀態:
l Available(可用) ---- 一款空閑資源還沒有被任何聲明綁定
l Bound(已綁定) --- 卷已經被聲明綁定
l Released(已釋放) --- 聲明被刪除,但是資源還未被集群重新聲明
l Failed(失敗) --- 該卷的自動回收失敗
Pvc也是kubernetes里標准的資源
[root@master ~]# kubectl explain pvc.spec
accessModes #訪問模式:
ReadWriteOnce: 單路讀寫
ReadOnlyMany: 多路只讀
ReadWriteMany: 多路讀寫
resources #資源限制
Selector #標簽選擇器
storageClassName #存儲類
volumeMode #存儲卷的模式
volumeName #存儲卷的名字
環境准備:
在所有機器上都安裝nfs-utils
以node2作為nfs服務器
在node2上創建五個掛載目錄 : [root@node2 ~]# mkdir v{1..5}
[root@node2 ~]# vim /etc/exports
/root/v1 172.18.0.0/16(rw)
/root/v2 172.18.0.0/16(rw)
/root/v3 172.18.0.0/16(rw)
/root/v4 172.18.0.0/16(rw)
/root/v5 172.18.0.0/16(rw)
創建pv: 如下
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv001
labels:
name: pv001
spec:
nfs:
path: /root/v1
server: node2
accessModes: ["ReadWriteMany","ReadWriteOnce"] #設置訪問類型。必須要寫
capacity:
storage: 1Gi #大小
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv002
labels:
name: pv002
spec:
nfs:
path: /root/v2
server: node2
accessModes: ["ReadWriteMany","ReadWriteOnce"]
capacity:
storage: 2Gi
[root@master vl]# kubectl apply -f pv.yaml
persistentvolume/pv001 created
persistentvolume/pv002 created
。。。
[root@master vl]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY(回收策略) STATUS CLAIM STORAGECLASS REASON AGE
pv001 1Gi RWO,RWX Retain Available 5s
pv002 2Gi RWO,RWX Retain Available 5s
。。。。
創建pvc
[root@master vl]# vim pvc.yaml 如下
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc
namespace: default #pvc有命名空間,pv沒有
spec:
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
name: pod-pvc
namespace: default
labels:
app: myapp
spec:
containers:
- name: mypvc
image: ikubernetes/myapp:v1
volumeMounts:
- name: mydisk
mountPath: /data/wengwengweng
volumes:
- name: mydisk
persistentVolumeClaim:
claimName: mypvc
[root@master vl]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mypvc Bound綁定 pv001 1Gi RWO,RWX 2m58s
Pvc是存儲在etcd中,就算pod死機,數據也不會丟失
當綁定pv的pvc刪掉之后 想要回收此pv 可以使用edit pv 刪掉ChaimRef這一行 就可以了
------------------------------------------------------------------------------------------------------
configmap
配置容器化應用的方式:
1 自定義命令行參數
Args:
2 把配置文件直接焙進鏡像
3 環境變量
4 存儲卷
[root@master volume]# kubectl create configmap --help #查看configmap幫助信息
[root@master ~]# kubectl create configmap nginx.cconf --from-file=./nginx.cconf
#創建文件式的cm
[root@master ~]# kubectl create configmap nginxport --from-literal=nginx_pory=80
#簡單的cm
configmap是名稱空間級別的資源 直接搜索:
[root@master ~]# kubectl explain cm
以環境變量的方式注入到容器里:
以掛載的方式:
支持edit動態修改
[root@master ~]# kubectl edit cm cm名
secret
Secret存在的意義:
Secret解決了密碼,token,密鑰等敏感數據的配置問題,而不需要把這額敏感數據暴露到鏡像或pod spec中。Secret可以以volume或者環境變量的方式使用
Secret有三種類型:
Service account: 用來訪問k8s API,由k8s自動創建,並且會自動掛載到Pod的/usr/secrets/kubernetes.io/serviceaccount目錄中
Opaque: base64編碼格式的secret,用來存儲密碼,密鑰等 安全性不怎么高,一條命令就可以解開(base64 -d)
Kubernetes.io/dockerconfigjson: 用來存儲私有docker regisry的認證信息
[root@master ~]# kubectl create secret --help
docker-registry #保存認證信息
generic #通用的
tls #私鑰類型
和configmap很相似
以環境變量方式注入:
注意以這種方式注入的密碼都是解碼之后的,安全性不高
如果支持dry-run的方式 可以使用-o yaml 來生成一個yaml框架!
使用secret做私有鏡像認證:
命令里的大寫代表變量
----------------------------------------------------------------------------------------------------------
Statefulset控制器
- 穩定且唯一的網絡標識符
- 穩定且持久的存儲
- 有序,平滑地部署和擴展
- 有序的滾動更新
一個典型的statefulset應該由三個組件組成: headless(必須是一個無頭服務)
Statefulset
volumeclaimTemplate
Sts為每個pod副本創建了一個DNS域名,這個域名的格式為: $(podname).(headless service name),也就意味着服務間是通過pod域名來通信而非pod IP ,因為opd所在的node發生故障時,pod會飄逸到其它node上,pod IP會發生變化,但是pod域名不會有變化
因為懶:
Statefulset的啟停順序:
l 有序部署:部署statefulset時,如果有多個Pod副本,它們會被順序地創建(從0到N-1)並且在下一個pod運行之前所有之前的pod必須都是running和ready狀態
l 有序刪除: 當pod被刪除時,它們被終止的順序是從N-1到0
l 有序擴展: 當對pod執行擴展操作時,與部署一樣,它前面的pod必須都處於running和ready狀態
[root@master ~]# kubectl explain sts #查看控制器的幫助,簡稱
apiVersion: v1
kind: Service
metadata:
name: myapp
labels:
app: myapp
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: myapp-pod
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: myapp
spec:
serviceName: myapp
replicas: 3
selector:
matchLabels:
app: myapp-pod
template:
metadata:
labels:
app: myapp-pod
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- containerPort: 80
name: web
volumeMounts:
- name: myappdata
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: myappdata
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
sts也支持動態更新,動態擴容
----------------------------------------------------------------------------------------------------------
認證
認證 ----> 授權-----> 准入控制
授權用戶:
ServiceaccessountName 授權名 寫在spec下面
創建sa: kubectl create serviceaccount admin
Dashboard:
[root@master ~]# kubectl proxy --port=8080
[root@master ~]# curl http://localhost:8080/ #查看各種資源
- 部署:
(1) [root@master ~]# Kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml
(2) 將service改為Nodeport
[root@master ~]# kubectl patch svc kubernetes-dashboard -p '{"spec": {"type": Nodeport}}' -n kube-system
要使用https的方式訪問
(3) 認證:
認證時的賬號必須為serviceaccount,被dashboard pod拿來由kubernetes進行認證
token:
(1)創建ServiceAccount,根據其管理目標,使用rolebinding或clusterrolebinding綁定至合理role或
clusterrole;
(2)獲取到此ServiceAccount的secret,查看secret的詳細信息,其中就有token;
kubeconfig: 把ServiceAccount的token封裝為kubeconfig文件
(1)創建ServiceAccount,根據其管理目標,使用rolebinding或clusterrolebinding綁定至合理role或
clusterrole;
(2)kubectl get secret | awk '/^ServiceAccount/{print $1}'
KUBE_TOKEN=$(kubectl get secret SERVCIEACCOUNT_SERRET_NAME -o jsonpath={.data.token} |
base64 -d)
(3)生成kubeconfig文件
kubectl config set-cluster --kubeconfig=/PATH/TO/SOMEFILE
kubectl config set-credentials NAME --token=$KUBE_TOKEN --kubeconfig=/PATH/TO/SOMEFILE
kubectl config set-context
kubectl config use-context
令牌認證:
[root@master ~]# kubectl create serviceaccount dashboard-admin -n kube-system
#先創建一個用戶
[root@master ~]# kubectl create clusterrolebinding dashboard-cluster-admin --clusterrole=clu
ster-admin --serviceaccount=kube-system:dashboard-admin #與集群角色進行綁定,左側名稱空間,右側賬號
[root@master ~]# kubectl get secret #找到剛創建角色的token
[root@master ~]# kubectl describe secret dashboard-admin-token-ctjgn -n kube-system
把查到的token信息復制到網頁上完成登入
Config認證:
[root@master ~]# kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server="https://172.18.0.70:6443" --embed-certs=true --kubeconfig=/root/def-ns-admin.conf
[root@master ~]# kubectl config view --kubeconfig=/root/def-ns-admin.conf
[root@master ~]# DEF_NS_ADMIN_TOKEN=$(kubectl get secret def-ns-admin-token-v4wxn -o jsonpath={.data.token} | base64 -d) #知道它的token並解碼賦值給變量
[root@master ~]# kubectl config set-credentials def-ns-admin --token=$DEF_NS_ADMIN_TOKEN --kubeconfig=/root/def-ns-admin.conf #把token傳進去
[root@master ~]# kubectl config set-context def-ns-admin@kubernetes --cluster=kubernetes --user=def-ns-admin --kubeconfig=/root/def-ns-admin.conf
[root@master ~]# kubectl config use-context def-ns-admin@kubernetes --kubeconfig=/root/def-ns-admin.conf
完成! 現在的配置文件可以下載下去,傳到網頁上就可以用了
----------------------------------------------------------------------------------------------------------
授權插件:
Node, ABAC , RBAC, Webhook
Kubernetes集群的管理方式:
- 命令式: create, run, expose, delete。。。
- 命令式配置文件: create -f create -f /PATH/TO/RESOURCE_CONFIGURATION_FILE, delete -f, replace -f
3、聲明式配置文件: apply -f, patch,
----------------------------------------------------------------------------------------------------------
網絡插件calico(網絡策略)
Calico作為網絡插件使用工作於192.168.0.0/16網段
官網文檔:
https://docs.projectcalico.org/v3.9/getting-started/kubernetes/installation/flannel
選擇使用calico用於網絡策略,flannel用於網絡
部署:
[root@master ~]# kubectl apply -f https://docs.projectcalico.org/v3.9/manifests/canal.yaml
[root@master ~]# kubectl get pods -n kube-system #查看是否安裝
使用:
[root@master ~]# kubectl explain networkpolicy.spec
egress 出站
ingress 入站
potSelector 選擇哪個pod
policyTypes 策略
基於名稱空間的網絡策略
拒絕所有入站:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: dey-all-ingress
spec:
podSelector: {}
policyTypes:
- Ingress #拒絕所有入站
[root@master ~]# kubectl apply -f ingress.yaml -n dev -n 代表指定名稱空間
[root@master ~]# kubectl get netpol -n dev #查看策略
放行所有進站:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: dey-all-ingress
spec:
podSelector: {}
ingress:
- {} #寫上之后默認放行所有
policyTypes:
- Ingress
放行特定的網絡:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-ingress
spec:
podSelector:
matchLabels:
app: myapp #放行有這個標簽的pod
ingress:
- from:
- ipBlock:
cidr: 10.244.0.0/16
except: #指定拒絕特定的網絡
- 10.244.1.2/32
ports: #指定放行的端口
- protocol: TCP
port: 80
----------------------------------------------------------------------------------------------------------
Node親和性:
[root@master ~]# kubectl explain pod.spec.affinity.nodeAffinity
preferredDuringSchedulingIgnoredDuringExecution #軟策略
requiredDuringSchedulingIgnoredDuringExecution #硬策略
節點選擇器:nodeSelector, nodeName
節點親和調度:nodeAffinity
Pod親和性
[root@master ~]# kubectl explain pod.spec.affinity.podAffinity
----------------------------------------------------------------------------------------------------------
Taint和toleration:
節點親和性,是pod的一種屬性(偏好或硬性要求),它使pod被吸引到這一類特定的節點,taint則相反,它是節點能夠排斥一類特定的pod
taint的effect定義對Pod排斥效果:
NoSchedule:僅影響調度過程,對現存的Pod對象不產生影響;
NoExecute:既影響調度過程,也影響現在的Pod對象;不容忍的Pod對象將被驅逐;
PreferNoSchedule:
資源需求與限制:
容器的資源需求,資源限制
requests: 需求,最低保障;
limits: 限制,硬限制
CPU:
1顆邏輯cpu
1=1000,millicores
500=0.5CPU
內存:
E, P, T, G, M, K
Ei,Pi
limits 代表上限
Qos: #服務質量
Guranteed: 當資源不夠的時候,優先運行#同時設置CPU和內存的requests和limit
cpu.limits = cpu.requests
memory.limits = memory.request #當條件滿足時,自動歸類為 guranteed
Burstable: #至少有一個容器設置CPU或內存資源的requests屬性
BestEffort: #沒有任何一個容器設置了requests或limit屬性;最低優先級
#當pod資源不夠時,自動殺死BestEffort屬性的容器
----------------------------------------------------------------------------------------------------------
Kubectl top:
Heapster 收集各種指標數據,存到InfluxDB里在由Grafana圖形化展示出來
部署:
在git上搜索heapster
https://github.com/kubernetes-retired/heapster/tree/master/deploy/kube-config #部署方法
這里先部署了infuexDB
[root@master ~]# wget https://raw.githubusercontent.com/kubernetes-retired/heapster/master/deploy/kube-config/influxdb/influxdb.yaml #把yaml文件wget下來
spec: 修改版本為apps/v1
replicas: 1
selector: #添加標簽這4行
matchLabels:
task: monitoring
k8s-app: influxdb
因谷歌網絡限制問題,國內的K8ser大多數在學習Kubernetes過程中因為鏡像下載失敗問題間接地產生些許失落感,筆者也因此腦殼疼,故翻閱資料得到以下解決方式:
在應用yaml文件創建資源時,將文件中鏡像地址進行內容替換即可:
將k8s.gcr.io替換為
registry.cn-hangzhou.aliyuncs.com/google_containers
或者
registry.aliyuncs.com/google_containers
或者
mirrorgooglecontainers
然后部署heapster:
https://github.com/kubernetes-retired/heapster/tree/master/deploy/kube-config/influxdb
[root@master ~]# vim heapster.yaml #群組改成apps/v1 貌似不改也沒關系,加一個標簽
spec:
replicas: 1
selector:
matchlabels:
task: monitoring
k8s-app: heapster
部署grafana:
[root@master ~]# wget https://raw.githubusercontent.com/kubernetes-retired/heapster/master/deploy/kube-config/influxdb/grafana.yaml
[root@master ~]# vim grafana.yaml #跟上面一樣修改版本,添加標簽,如果有需要還可以添加一個nodePort 暴露在公網上
然后查看grafana的svc 瀏覽
如何導入導出面板可以參考:https://blog.csdn.net/gx_1_11_real/article/details/85161491
----------------------------------------------------------------------------------------------------------
Helm:
核心術語:
Chart:一個helm程序包;
Repository:Charts倉庫,https/http服務器;
Release:特定的Chart部署於目標集群上的一個實例;
Chart -> Config -> Release
程序架構:
helm:客戶端,管理本地的Chart倉庫,管理Chart, 與Tiller服務器交互,發送Chart,實例安裝、查詢、卸載等 操作
Tiller:服務端,接收helm發來的Charts與Config,合並生成relase;
安裝步驟:
現在git上找到相應的helm包,下載下來
地址:https://github.com/helm/helm/releases
解壓下載的文件:
[root@master linux-386]# tar -xf tar -xf helm-v2.9.1-linux-amd64.tar.gz
#建議使用舊版本的,要不然會有很多莫名其妙的錯誤
把helm文件直接mv到/usr/bin 就可以直接使用
因為helm運行要使用管理員權限所以還要綁定cluster-admin集群角色上:
RBAC示例:
https://github.com/helm/helm/blob/master/docs/rbac.md
把示例里的yaml文件復制下來,使用apply部署
helm init --service-account tiller --upgrade -i registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.9.1 --stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
#因為網絡問題,這里使用阿里雲的helm鏡像
[root@master helm]# kubectl get pods -n kube-system #查看pod是否啟動
[root@master helm]# helm version #查看helm和tiller版本
[root@master helm]# helm repo update
[root@master helm]# helm repo list #查看可用的正在使用的倉庫
官方可用的chart列表:
Stable代表穩定版 incubator代表測試版,最好還是使用穩定版
示例:
部署一個memcache:
[root@master ~]# helm search stable/memcachecd
[root@master ~]# helm inspect table/memcached
[root@master ~]# helm install --name mem1 stable/memcached
#部署完會有一個反饋信息在下面
[root@master ~]# helm delete mem1 #卸載
helm常用命令:
release管理:
install #安裝
delete #刪除
upgrade/rollback #更新/回滾
list #列出
history:release的歷史信息;
status:獲取release狀態信息;
chart管理:
create
fetch
get
inspect
package
Verify
[root@master ~]# helm fetch stable/redis 下載包
[root@master redis]# tree ./
./
├── Chart.yaml #記錄chart的元數據。。
├── README.md #說明
├── templates #各種模板文件
│ ├── deployment.yaml
│ ├── _helpers.tpl
│ ├── networkpolicy.yaml
│ ├── NOTES.txt
│ ├── pvc.yaml
│ ├── secrets.yaml
│ └── svc.yaml
└── values.yaml #自定義屬性設置默認值
創建chart:
[root@master ~]# helm create myapp 它會自動生成配置文件
[root@master ~]# tree myapp/
myapp/
├── charts
├── Chart.yaml
├── templates
│ ├── deployment.yaml
│ ├── _helpers.tpl
│ ├── ingress.yaml
│ ├── NOTES.txt
│ └── service.yaml
└── values.yaml
修改完yaml文件后使用
[root@master redis]# helm lint ../redis #語法檢測
ElK: #類似於ELK
E: elasticsearch 和kibana版本一定要一致,錯一個小版本號都不行
L: logstash
K:
Fluentd 日志收集代理工具
部署ELK:
[root@master ~]# helm repo add incubator https://kubernetes-charts-incubator.storage.googleapis.com/ #添加測試版倉庫
[root@master ~]# helm fetch incubator/elasticsearch #下載el chart包
[root@master ~]# tar -xf elasticsearch-1.10.2.tgz
[root@master ~]# cd elasticsearch/
[root@master elasticsearch]# helm install --name els2 --namespace=efk -f values.yaml incubator/elasticsearch
[root@master elasticsearch]# kubectl run -it --rm cirror-$RANDOM --image=cirros -- /bin/sh
#運行一個測試的容器
[root@master ~]# helm status el2 #查看入口
在測試的機器里:
/ # nslookup el2-elasticsearch-client.efk.svc
/ # curl el2-elasticsearch-client.efk.svc:9200 #訪問它的端口
/ # curl el2-elasticsearch-client.efk.svc.cluster.local:9200/_cat #查看es庫
部署fluentd:
[root@master mnt]# helm fetch incubator/fluentd-elasticsearch 下載對應chart
elasticsearch:
host: 'el2-elasticsearch-client.efk.svc.cluster.local' #把這里改成解析的主機名的地址
tolerations:
- key: node-role.kubernetes.io/master #把這三個注釋打開,可以容忍主節點的污點
operator: Exists
effect: NoSchedule
service: #如果期望通過服務的方式來訪問它就把這注釋打開
type: ClusterIP
ports:
- name: "monitor-agent"
port: 24231
[root@master fluentd-elasticsearch]# helm install --name flu1 --namespace=efk -f values.yaml incubator/fluentd-elasticsearch #進行安裝
部署k:
]# helm fetch stable/kibana
]# tar -xf kibana-0.2.2.tgz
如果是新版本配置如下:
]# helm install --name kib1 --namespace=efk -f values.yaml stable/kibana
]# kubectl edit svc -n efk kib1-kibana 修改svc為NodePort
完成后的頁面:
證書
證書默認路徑: [root@master pki]# ls /etc/kubernetes/pki/
查看證書使用年限: [root@master pki]# openssl x509 -in apiserver.crt -text -noout
使用go語言修改kubeadm源碼,修改年限
准備go語言環境: 首先在百度上搜索go中文社區(因為官方在谷歌,國內不方便)
百度--> go中文社區--> 下載 --> 選擇linux版本
[root@master data]# wget https://studygolang.com/dl/golang/go1.13.linux-amd64.tar.gz
[root@master data]# tar -xf go1.13.linux-amd64.tar.g -C /usr/local/
export PATH=$PATH:/usr/local/go/bin #變量
[root@master ~]# vim /etc/profile #在這里設置環境變量
export PATH=$PATH:/usr/local/go/bin #把這個貼在文件里,官網上有
[root@master ~]# source /etc/profile
[root@master ~]# go version #查看版本
go version go1.13 linux/amd64
[root@master data]# git clone https://github.com/kubernetes/kubernetes 克隆
[root@master data]# cd kubernetes
[root@master kubernetes]# git checkout -b remotes/origin/release-1.15.3 v1.15.3 #切換分支
cmd/kubeadm/app/util/pkiutil/pki_helpers.go #修改年限的文件(1.14版本到1.15)
[root@master kubernetes]# vim cmd/kubeadm/app/util/pkiutil/pki_helpers.go
const duration3650d = time.Hour * 24(小時) * 365(天) *10(年) #添加,設置常量
certTmpl := x509.Certificate{ #大約566行
Subject: pkix.Name{
CommonName: cfg.CommonName,
Organization: cfg.Organization,
},
DNSNames: cfg.AltNames.DNSNames,
IPAddresses: cfg.AltNames.IPs,
SerialNumber: serial,
NotBefore: caCert.NotBefore,
NotAfter: time.Now().Add(duration3650d).UTC() #改成剛剛的常量
:wq
[root@master kubernetes]# make WHAT=cmd/kubeadm GOFLAGS=-v 編譯
不知道為什么沒有成功。。。
高可用k8s集群構建
睿雲
補充:
Init(容器啟動之前的操作):
參考https://www.cnblogs.com/tylerzhou/p/11007430.html
registry.cn-shanghai.aliyuncs.com/mydlq/