k8s集群yum安裝
k8s集群架構
核心組件:
Add-ons:
組件名稱 | 說明 |
---|---|
kube-dns | 負責為整個集群提供DNS服務 |
Ingress Controller | 為服務提供外網入口 |
Heapster | 提供資源監控 |
Dashboard | 提供GUI |
Federation | 提供跨可用區的集群 |
Fluentd-elasticsearch | 提供集群日志采集、存儲與查詢 |
環境准備
主機名 | IP | 配置 |
---|---|---|
k8s-master | 10.0.0.11 | 1核1G |
k8s-node-1 | 10.0.0.12 | 1核1G |
k8s-node-2 | 10.0.0.13 | 1核1G |
-
關閉:
selinux
,firewalld
和NetworkManager
,postfix
(非必須) -
修改IP地址、主機名
hostnamectl set-hostname 主機名
sed -i 's/200/IP/g' /etc/sysconfig/network-scripts/ifcfg-eth0
- 添加hosts解析
cat >> /etc/hosts <<EOF
10.0.0.11 k8s-master
10.0.0.12 k8s-node-1
10.0.0.13 k8s-node-2
10.0.0.14 k8s-node-3
EOF
master部署
etcd
- 安裝
yum install etcd -y
- 配置
sed -i "6c ETCD_LISTEN_CLIENT_URLS=\"http://0.0.0.0:2379\"" /etc/etcd/etcd.conf
sed -i "21c ETCD_ADVERTISE_CLIENT_URLS=\"http://10.0.0.11:2379\"" /etc/etcd/etcd.conf
#[Member] #ETCD_CORS="" ETCD_DATA_DIR="/var/lib/etcd/default.etcd" # 數據文件存放路徑 #ETCD_WAL_DIR="" #ETCD_LISTEN_PEER_URLS="http://localhost:2380" # 同類監聽地址,用於集群時同步 ETCD_LISTEN_CLIENT_URLS="http://localhost:2379" # 客戶端監聽地址 #ETCD_MAX_SNAPSHOTS="5" # 快照最大數量 #ETCD_MAX_WALS="5" ETCD_NAME="default" # 服務名,集群時不能一樣 ... ... # #[Clustering] #ETCD_INITIAL_ADVERTISE_PEER_URLS="http://localhost:2380" ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379" ... ...
- 啟動並加入開機啟動
systemctl start etcd.service
systemctl enable etcd.service
- 檢查集群健康狀態
etcdctl -C http://10.0.0.11:2379 cluster-health
要加入已有集群,先在集群再添加成員,再在成員節點修改配置文件
status="existing"
,啟動服務。etcdctl member list etcdctl member remove 成員 etcdctl member add nodeN URL
- etcdctl命令介紹
etcdctl [global options] command [command options] [arguments...]
etcdctl mk [command options] <key> <value>
etcdctl ls [command options] [key]
etcdctl set [command options] <key> <value>
etcdctl get [command options] <key>
backup # 備份etcd目錄
cluster-health # 檢查etcd群集的運行狀況
mk # 生成一個具有給定值的新鍵
mkdir # 創建新目錄
rm # 刪除鍵或目錄
rmdir # 刪除鍵。如果是空目錄或鍵值對
get # 檢索鍵的值
ls # 檢索目錄
set # 設置鍵的值
setdir # 創建新目錄或更新現有目錄TTL
update # 使用給定值更新現有密鑰
updatedir # 更新現有目錄
watch # 觀察鍵的變化
exec-watch # 觀察一個鍵的變化並執行一個可執行文件
member # 成員add、remove和list子命令
user # 用戶add、grant和revoke子命令
role # 角色add、grant和revoke子命令
auth # 總體身份驗證控制
kubernetes-master
- 安裝
yum install kubernetes-master -y
- 配置apiserver
sed -i "8c KUBE_API_ADDRESS=\"--insecure-bind-address=0.0.0.0\"" /etc/kubernetes/apiserver
sed -i "11c KUBE_API_PORT=\"--port=8080\"" /etc/kubernetes/apiserver
sed -i "14c KUBELET_PORT=\"--kubelet-port=10250\"" /etc/kubernetes/apiserver
sed -i "17c KUBE_ETCD_SERVERS=\"--etcd-servers=http://10.0.0.11:2379\"" /etc/kubernetes/apiserver
sed -i "s/ServiceAccount,//" /etc/kubernetes/apiserver
默認配置文件:
### # kubernetes system config # # The following values are used to configure the kube-apiserver # # The address on the local server to listen to. KUBE_API_ADDRESS="--insecure-bind-address=127.0.0.1" # The port on the local server to listen on. # KUBE_API_PORT="--port=8080" # Port minions listen on # KUBELET_PORT="--kubelet-port=10250" # Comma separated list of nodes in the etcd cluster KUBE_ETCD_SERVERS="--etcd-servers=http://127.0.0.1:2379" # Address range to use for services KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.254.0.0/16" # default admission control policies KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota" # Add your own! KUBE_API_ARGS=""
- 配置config
sed -i "22c KUBE_MASTER=\"--master=http://10.0.0.11:8080\"" /etc/kubernetes/config
默認配置文件:
### # kubernetes system config # # The following values are used to configure various aspects of all # kubernetes services, including # # kube-apiserver.service # kube-controller-manager.service # kube-scheduler.service # kubelet.service # kube-proxy.service # logging to stderr means we get it in the systemd journal KUBE_LOGTOSTDERR="--logtostderr=true" # journal message level, 0 is debug KUBE_LOG_LEVEL="--v=0" # Should this cluster be allowed to run privileged docker containers KUBE_ALLOW_PRIV="--allow-privileged=false" # How the controller-manager, scheduler, and proxy find the apiserver KUBE_MASTER="--master=http://127.0.0.1:8080"
- 啟動並加入開機啟動
systemctl enable kube-apiserver.service
systemctl enable kube-controller-manager.service
systemctl enable kube-scheduler.service
systemctl start kube-apiserver.service
systemctl start kube-controller-manager.service
systemctl start kube-scheduler.service
- 檢查服務是否安裝正常
[root@k8s-master ~]# kubectl get componentstatus
NAME STATUS MESSAGE ERROR
etcd-0 Healthy {"health":"true"}
scheduler Healthy ok
controller-manager Healthy ok
node部署
kubernetes-node(集成cadvisor)
- 安裝
yum install kubernetes-node -y
- 配置config
sed -i "22c KUBE_MASTER=\"--master=http://10.0.0.11:8080\"" /etc/kubernetes/config
- 配置kubelet
sed -i "5c KUBELET_ADDRESS=\"--address=0.0.0.0\"" /etc/kubernetes/kubelet
sed -i "8c KUBELET_PORT=\"--port=10250\"" /etc/kubernetes/kubelet
sed -i "14c KUBELET_API_SERVER=\"--api-servers=http://10.0.0.11:8080\"" /etc/kubernetes/kubelet
k8s-node-1:10.0.0.12
sed -i "11c KUBELET_HOSTNAME=\"--hostname-override=10.0.0.12\"" /etc/kubernetes/kubelet
k8s-node-2:10.0.0.13
sed -i "11c KUBELET_HOSTNAME=\"--hostname-override=10.0.0.13\"" /etc/kubernetes/kubelet
默認配置文件:
### # kubernetes kubelet (minion) config # The address for the info server to serve on (set to 0.0.0.0 or "" for all interfaces) KUBELET_ADDRESS="--address=127.0.0.1" # The port for the info server to serve on # KUBELET_PORT="--port=10250" # You may leave this blank to use the actual hostname KUBELET_HOSTNAME="--hostname-override=127.0.0.1" # location of the api-server KUBELET_API_SERVER="--api-servers=http://127.0.0.1:8080" # pod infrastructure container KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrast ructure:latest" # Add your own! KUBELET_ARGS=""
- 啟動並加入開機啟動
systemctl enable docker
systemctl enable kubelet.service
systemctl enable kube-proxy.service
systemctl start kubelet.service
systemctl start kube-proxy.service
- 在master節點檢查
kubectl get nodes
- 訪問cadvisor的web界面:
所有節點配置flannel網絡
- 安裝
yum install flannel -y
- 配置
sed -i 's#127.0.0.1#10.0.0.11#g' /etc/sysconfig/flanneld
- master節點創建key,安裝docker啟動並加入開機啟動
etcdctl mk /atomic.io/network/config '{ "Network": "172.18.0.0/16","Backend": {"Type": "vxlan"} }'
flannel三種模式:
- udp:性能最差
- vxlan:性能較好
- host-gw:性能最好,但雲主機不能用
yum install docker -y
systemctl enable docker
systemctl start docker
- 啟動並加入開機啟動
systemctl enable flanneld.service
systemctl start flanneld.service
docker指定bip設置docker0網卡的IP
- 配置docker服務啟動文件:啟動時設置iptables規則允許轉發
sed -i "/ExecStart=/i ExecStartPost=/usr/sbin/iptables -P FORWARD ACCEPT" /usr/lib/systemd/system/docker.service
systemctl daemon-reload
systemctl restart docker
- 查看flannel網卡
ifconfig flannel0
- 驗證各節點互通
docker run -it alpine
ifconfig
- 配置倉庫信任和加速
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["https://registry.docker-cn.com"],
"insecure-registries": ["10.0.0.11:5000"]
}
EOF
systemctl restart docker
master部署鏡像倉庫
docker run -d -p 5000:5000 --restart=always --name registry -v /opt/myregistry:/var/lib/registry registry
node提交鏡像測試
docker tag alpine:3.9 10.0.0.11:5000/alpine:3.9
docker push 10.0.0.11:5000/alpine:3.9
查看倉庫鏡像文件
ls /opt/myregistry/docker/registry/v2/repositories
k8s介紹
k8s是一個docker集群的管理工具,是容器的編排工具。
Kubernetes 是用於自動部署,擴展和管理容器化應用程序的開源系統。
Kubernetes 源自Google 15 年生產環境的運維經驗(使用golang重構borg(容器管理平台) -->kubernetes),同時凝聚了社區的最佳創意和實踐。
k8s歷史:
-
2014年 docker容器編排工具,立項
-
2015年7月 發布kubernetes 1.0,加入cncf基金會,孵化
-
2016年 kubernetes 1.2干掉兩個對手,docker swarm,mesos marathon
-
2017年 1.5-1.9
-
2018年 k8s 從cncf基金會畢業,1.10 1.11 1.12
-
2019年:1.13,1.14,1.15,1.16,1.17
-
2020年:1.18,1.19,1.20
cncf:Cloud Native Compute Foundation 孵化器
kubernetes (k8s):希臘語 舵手,領航者 容器編排領域,
k8s核心功能
自我修復: 重新啟動失敗的容器,在節點不可用時,替換和重新調度節點上的容器,對用戶定義的健康檢查不響應的容器會被中止,並且在容器准備好服務之前不會把其向客戶端廣播。
彈性伸縮: 通過監控容器的cpu的負載值,如果這個平均高於80%,增加容器的數量;如果這個平均低於10%,減少容器的數量。
服務的自動發現和負載均衡:不需要修改您的應用程序來使用不熟悉的服務發現機制,Kubernetes 為容器提供了自己的 IP 地址和一組容器的單個 DNS 名稱,並可以在它們之間進行負載均衡。
滾動升級和一鍵回滾: Kubernetes 逐漸部署對應用程序或其配置的更改,同時監視應用程序運行狀況,以確保它不會同時終止所有實例。 如果出現問題,Kubernetes會為您恢復更改,利用日益增長的部署解決方案的生態系統。
私密配置文件管理:web容器里,數據庫的賬戶密碼(測試庫密碼)
k8s安裝方式
-
yum安裝:1.5.2;最容易安裝成功,最適合學習的
-
源碼編譯安裝:難度最大,可以安裝最新版
-
二進制安裝:步驟繁瑣,可以安裝最新版,自動化腳本(shell,ansible,saltstack),適合生產
-
kubeadm:安裝最容易,可以安裝最新版,國外網絡,適合生產
-
minikube:適合開發人員體驗k8s, 國外網絡
k8s應用場景
k8s最適合跑微服務項目!
k8s開機檢查
kubectl get componentstatus
kubectl get nodes
kubectl get pod -o wide
[root@k8s-master ~]# kubectl get componentstatus # 檢查組件狀態
NAME STATUS MESSAGE ERROR
etcd-0 Healthy {"health":"true"}
scheduler Healthy ok
controller-manager Healthy ok
[root@k8s-master ~]# kubectl get nodes # 檢查nodes節點狀態
NAME STATUS AGE
10.0.0.12 Ready 21m
10.0.0.13 Ready 3d
[root@k8s-master ~]# kubectl get pod -o wide # 檢查pod節點狀態
NAME READY STATUS RESTARTS AGE IP NODE
nginx-8phch 1/1 Running 1 13h 172.18.100.2 10.0.0.13
nginx-dc8wc 1/1 Running 1 13h 172.18.100.3 10.0.0.13
nginx-kcmpv 1/1 Running 1 13h 172.18.100.4 10.0.0.13
nginx-mknrb 1/1 Running 1 13h 172.18.100.6 10.0.0.13
nginx-zk9kg 1/1 Running 0 8s 172.18.68.2 10.0.0.12
[root@k8s-master ~]# ping 172.18.100.2
PING 172.18.100.2 (172.18.100.2) 56(84) bytes of data.
64 bytes from 172.18.100.2: icmp_seq=1 ttl=63 time=3.82 ms
64 bytes from 172.18.100.2: icmp_seq=2 ttl=63 time=0.380 ms
^C
--- 172.18.100.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.380/2.104/3.829/1.725 ms
[root@k8s-master ~]# ping 172.18.68.2
PING 172.18.68.2 (172.18.68.2) 56(84) bytes of data.
64 bytes from 172.18.68.2: icmp_seq=1 ttl=63 time=2.48 ms
64 bytes from 172.18.68.2: icmp_seq=2 ttl=63 time=0.354 ms
^C
--- 172.18.68.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.354/1.421/2.488/1.067 ms
k8s資源
准備:
node下載鏡像,上傳至私有倉庫
docker pull nginx:1.13
docker tag docker.io/nginx:1.13 10.0.0.11:5000/nginx:1.13
docker push 10.0.0.11:5000/nginx:1.13
docker pull nginx:1.15
docker tag docker.io/nginx:1.15 10.0.0.11:5000/nginx:1.15
docker push 10.0.0.11:5000/nginx:1.15
docker pull alpine
docker tag docker.io/alpine:latest 10.0.0.11:5000/alpine:latest
docker push 10.0.0.11:5000/alpine:latest
Pod
Pod(容器組)是 Kubernetes 中最小的調度單元,可以通過 yaml 定義文件直接創建一個 Pod。
Pod 本身並不具備自我恢復(self-healing),彈性伸縮等高級特性。如果一個 Pod 所在的節點出現故障,或者調度程序自身出現問題,以及節點資源不夠或節點進入維護而驅逐 Pod 時,Pod 將被刪除,且不能自我恢復。
啟動一個pod,至少會有兩個容器,基礎容器pause和業務容器
,多個業務容器共享一個基礎容器。一個Pod中的容器默認共享網絡命名空間,
Pod容器分類
- Infrastructure Container:基礎容器pause,維護整個Pod網絡空間。
- InitContainers:初始化容器,先於業務容器開始執行。
- Containers:業務容器,並行啟動。
Pod存在的意義:為親密性應用而存在
- 兩個應用之間發生文件交互
- 兩個應用需要通過127.0.0.1或socker通信
- 兩個應用需要發生頻繁的調用
任何一個k8s資源都可以由yml清單文件來定義。
apiVersion: 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
k8s yaml的主要組成:
apiVersion:v1
:api版本kind:pod
:資源類型metadata
:屬性spec
:詳細
- master節點編寫pod資源yaml
mkdir -p /root/k8s_yaml/pod && cd /root/k8s_yaml/pod
cat > /root/k8s_yaml/pod/k8s_pod.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: web
spec:
containers:
- name: nginx
image: 10.0.0.11:5000/nginx:1.13
ports:
- containerPort: 80
EOF
- master節點創建資源
kubectl create -f k8s_pod.yaml
- master節點查看所有pod資源狀態(集裝箱化)
[root@k8s-master pod]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 0/1 ContainerCreating 0 27m
- master節點查看指定pod資源描述(調度至10.0.0.13)
[root@k8s-master pod]# kubectl describe pod nginx
Name: nginx
Namespace: default
Node: 10.0.0.13/10.0.0.13
Start Time: Mon, 07 Dec 2020 16:19:46 +0800
Labels: app=web
Status: Pending
IP:
Controllers: <none>
Containers:
nginx:
Container ID:
Image: 10.0.0.11:5000/nginx:1.13
Image ID:
Port: 80/TCP
State: Waiting
Reason: ContainerCreating
Ready: False
Restart Count: 0
Volume Mounts: <none>
Environment Variables: <none>
Conditions:
Type Status
Initialized True
Ready False
PodScheduled True
No volumes.
QoS Class: BestEffort
Tolerations: <none>
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
27m 27m 1 {default-scheduler } Normal Scheduled Successfully assigned nginx to 10.0.0.13
27m 1m 10 {kubelet 10.0.0.13} Warning FailedSync Error syncing pod, skipping: failed to "StartContainer" for "POD" with ErrImagePull: "image pull failed for registry.access.redhat.com/rhel7/pod-infrastructure:latest, this may be because there are no credentials on this request. details: (open /etc/docker/certs.d/registry.access.redhat.com/redhat-ca.crt: no such file or directory)"
27m 39s 116 {kubelet 10.0.0.13} Warning FailedSync Error syncing pod, skipping: failed to "StartContainer" for "POD" with ImagePullBackOff: "Back-off pulling image \"registry.access.redhat.com/rhel7/pod-infrastructure:latest\""
0s 0s 1 {kubelet 10.0.0.13} Warning MissingClusterDNS kubelet does not have ClusterDNS IP configured and cannot create Pod using "ClusterFirst" policy. Falling back to DNSDefault policy.
- node節點(10.0.0.13)搜索缺失鏡像並下載,上傳至私有倉庫
docker search pod-infrastructure
docker pull docker.io/tianyebj/pod-infrastructure
docker tag docker.io/tianyebj/pod-infrastructure:latest 10.0.0.11:5000/pod-infrastructure:latest
docker push 10.0.0.11:5000/pod-infrastructure:latest
- 所有node節點修改配置文件,指定POD下載鏡像地址為私有倉庫,重啟服務
sed -i "17c KUBELET_POD_INFRA_CONTAINER=\"--pod-infra-container-image=10.0.0.11:5000/pod-infrastructure:latest\"" /etc/kubernetes/kubelet
systemctl restart kubelet.service
- master節點再次查看所有pod資源狀態(運行中)
[root@k8s-master pod]# kubectl get pod -o wide # -o 顯示更寬
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 59m 172.18.100.2 10.0.0.13
- node節點(10.0.0.13)查看運行的容器
[root@k8s-node-2 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f4a6497de298 10.0.0.11:5000/nginx:1.13 "nginx -g 'daemon ..." 34 minutes ago Up 34 minutes k8s_nginx.91390390_nginx_default_f70dd446-3864-11eb-b602-000c295a6f81_362db3ed
8cf407292934 10.0.0.11:5000/pod-infrastructure:latest "/pod" 34 minutes ago Up 34 minutes k8s_POD.177f01b0_nginx_default_f70dd446-3864-11eb-b602-000c295a6f81_9d56b0b4
[root@k8s-node-2 ~]# docker inspect f4a6497de298 | grep NetworkMode
"NetworkMode": "container:8cf407292934095b3ddabecb197adb33acda43bc38a7ee73a12a681ca30a9a43",
[root@k8s-node-2 ~]# docker inspect 8cf407292934 | grep -A 1 Networks
"Networks": {
"bridge": {
pod資源至少由兩個容器組成:基礎容器pause和(多個)業務容器nginx組成,共用網絡空間。
基礎容器pod用於實現k8s高級功能。
- master節點編寫pod資源yaml(兩個業務容器)
cat > /root/k8s_yaml/pod/k8s_pod2.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
name: test
labels:
app: web
spec:
containers:
- name: nginx
image: 10.0.0.11:5000/nginx:1.13
ports:
- containerPort: 80
- name: alpine
image: 10.0.0.11:5000/alpine:latest
command: ["sleep","1000"]
EOF
- master節點創建資源
kubectl create -f k8s_pod2.yaml
- master節點查看所有pod資源狀態
[root@k8s-master pod]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 2h
test 2/2 Running 1 28m
- node節點(10.0.0.12)查看運行的容器(輪詢負載均衡)
[root@k8s-node-1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7bf33f049a9c 10.0.0.11:5000/alpine:latest "sleep 1000" 11 minutes ago Up 11 minutes k8s_alpine.314fe414_test_default_6ef312be-3876-11eb-bf96-000c295a6f81_48c71571
363f874e9d5a 10.0.0.11:5000/nginx:1.13 "nginx -g 'daemon ..." 28 minutes ago Up 28 minutes k8s_nginx.91390390_test_default_6ef312be-3876-11eb-bf96-000c295a6f81_f036679b
d75cc74ef792 10.0.0.11:5000/pod-infrastructure:latest "/pod" 28 minutes ago Up 28 minutes k8s_POD.177f01b0_test_default_6ef312be-3876-11eb-bf96-000c295a6f81_96282638
[root@k8s-node-1 ~]# docker inspect 7bf33f049a9c | grep NetworkMode
"NetworkMode": "container:d75cc74ef79284342d2c31698867a660c404f90a72170729b1f6728514efb84e",
[root@k8s-node-1 ~]# docker inspect 363f874e9d5a | grep NetworkMode
"NetworkMode": "container:d75cc74ef79284342d2c31698867a660c404f90a72170729b1f6728514efb84e",
[root@k8s-node-1 ~]# docker inspect d75cc74ef792 | grep -A 1 Networks
"Networks": {
"bridge": {
ReplicationController
Replication Controller 副本控制器,應用托管在Kubernetes后,Kubernetes需要保證應用能夠持續運行,這是RC的工作內容,它會確保任何時間Kubernetes中都有指定數量的Pod正在運行。在此基礎上,RC還提供了一些高級的特性,比如滾動升級、升級回滾等。
新版 Kubernetes 建議使用 ReplicaSet(簡稱為RS )來取代 ReplicationController。
- master節點編寫ReplicationController資源yaml
mkdir -p /root/k8s_yaml/rc && cd /root/k8s_yaml/rc
cat > /root/k8s_yaml/rc/k8s_rc.yaml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx
spec:
replicas: 5 # 副本5個
selector:
app: myweb
template: # Pod模板
metadata:
labels:
app: myweb
spec:
containers:
- name: myweb
image: 10.0.0.11:5000/nginx:1.13
ports:
- containerPort: 80
EOF
- master節點創建資源(5個pod)
kubectl create -f k8s_rc.yaml
- master節點查看資源狀態
[root@k8s-master rc]# kubectl get rc
NAME DESIRED CURRENT READY AGE
nginx 5 5 5 6s
[root@k8s-master rc]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 2h
nginx-2w6fb 1/1 Running 0 1m
nginx-35m8t 1/1 Running 0 1m
nginx-7xhms 1/1 Running 0 1m
nginx-kxljm 1/1 Running 0 1m
nginx-sv4d5 1/1 Running 0 1m
test 2/2 Running 2 38m
rc保證指定數量的pod始終存活
- master節點刪除一個pod,再查看資源狀態:仍然有5個pod
[root@k8s-master rc]# kubectl delete pod nginx-2w6fb
pod "nginx-2w6fb" deleted
[root@k8s-master rc]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 2h
nginx-35m8t 1/1 Running 0 2m
nginx-5mbbq 1/1 Running 0 4s
nginx-7xhms 1/1 Running 0 2m
nginx-kxljm 1/1 Running 0 2m
nginx-sv4d5 1/1 Running 0 2m
test 2/2 Running 2 38m
[root@k8s-master rc]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 2h 172.18.100.2 10.0.0.13
nginx-35m8t 1/1 Running 0 6m 172.18.100.3 10.0.0.13
nginx-5mbbq 1/1 Running 0 4m 172.18.68.5 10.0.0.12
nginx-7xhms 1/1 Running 0 6m 172.18.100.4 10.0.0.13
nginx-kxljm 1/1 Running 0 6m 172.18.68.3 10.0.0.12
nginx-sv4d5 1/1 Running 0 6m 172.18.100.5 10.0.0.13
test 2/2 Running 2 43m 172.18.68.2 10.0.0.12
- 關閉一個node節點(10.0.0.12)(等2分鍾)
systemctl stop kubelet.service
- master節點查看到一個node節點離線,移除該節點
[root@k8s-master rc]# kubectl get node
NAME STATUS AGE
10.0.0.12 NotReady 3d
10.0.0.13 Ready 3d
[root@k8s-master rc]# kubectl delete node 10.0.0.12
node "10.0.0.12" deleted
- master節點查看資源狀態(rc資源自動遷移)
[root@k8s-master rc]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 2h 172.18.100.2 10.0.0.13
nginx-35m8t 1/1 Running 0 10m 172.18.100.3 10.0.0.13
nginx-7xhms 1/1 Running 0 10m 172.18.100.4 10.0.0.13
nginx-dhcxr 1/1 Running 0 7s 172.18.100.7 10.0.0.13
nginx-jqhr9 1/1 Running 0 7s 172.18.100.6 10.0.0.13
nginx-sv4d5 1/1 Running 0 10m 172.18.100.5 10.0.0.13
rc通過標簽選擇器來關聯pod
- master節點刪除一個pod
kubectl delete pod nginx-35m8t
使用
--all
參數刪除所有指定種類資源kubectl delete pod --all
- master節點查看標簽
[root@k8s-master rc]# kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx 1/1 Running 0 2h app=web
nginx-7xhms 1/1 Running 0 14m app=myweb
nginx-ccxz2 1/1 Running 0 11s app=myweb
nginx-dhcxr 1/1 Running 0 4m app=myweb
nginx-jqhr9 1/1 Running 0 4m app=myweb
nginx-sv4d5 1/1 Running 0 14m app=myweb
[root@k8s-master rc]# kubectl get rc -o wide
NAME DESIRED CURRENT READY AGE CONTAINER(S) IMAGE(S) SELECTOR
nginx 5 5 5 13m myweb 10.0.0.11:5000/nginx:1.13 app=myweb
- 修改nginx的標簽為
app: myweb
,自動刪除最年輕的pod資源,保持5個
[root@k8s-master rc]# kubectl edit pod nginx
[root@k8s-master rc]# kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx 1/1 Running 0 2h app=myweb
nginx-7xhms 1/1 Running 0 16m app=myweb
nginx-dhcxr 1/1 Running 0 5m app=myweb
nginx-jqhr9 1/1 Running 0 5m app=myweb
nginx-sv4d5 1/1 Running 0 16m app=myweb
rc滾動升級
- 根據k8s_rc2.yaml創建升級k8s_rc2.yaml,修改:
name
app
image
cat > /root/k8s_yaml/rc/k8s_rc2.yaml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx2
spec:
replicas: 5
selector:
app: myweb2
template:
metadata:
labels:
app: myweb2
spec:
containers:
- name: myweb2
image: 10.0.0.11:5000/nginx:1.15
ports:
- containerPort: 80
EOF
- 升級(5s一個)
kubectl rolling-update nginx -f k8s_rc2.yaml --update-period=5s
[root@k8s-master rc]# kubectl rolling-update nginx -f k8s_rc2.yaml --update-period=5s
Created nginx2
Scaling up nginx2 from 0 to 5, scaling down nginx from 5 to 0 (keep 5 pods available, don't exceed 6 pods)
Scaling nginx2 up to 1
Scaling nginx down to 4
Scaling nginx2 up to 2
Scaling nginx down to 3
Scaling nginx2 up to 3
Scaling nginx down to 2
Scaling nginx2 up to 4
Scaling nginx down to 1
Scaling nginx2 up to 5
Scaling nginx down to 0
Update succeeded. Deleting nginx
replicationcontroller "nginx" rolling updated to "nginx2"
[root@k8s-master rc]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx2-725jx 1/1 Running 0 35s 172.18.100.6 10.0.0.13
nginx2-fhw68 1/1 Running 0 30s 172.18.100.3 10.0.0.13
nginx2-l4b5f 1/1 Running 0 50s 172.18.100.7 10.0.0.13
nginx2-r027f 1/1 Running 0 40s 172.18.100.8 10.0.0.13
nginx2-rkc14 1/1 Running 0 25s 172.18.100.2 10.0.0.13
[root@k8s-master rc]# curl -I 172.18.100.6
HTTP/1.1 200 OK
Server: nginx/1.15.5
Date: Mon, 07 Dec 2020 11:26:46 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 02 Oct 2018 14:49:27 GMT
Connection: keep-alive
ETag: "5bb38577-264"
Accept-Ranges: bytes
- 回滾(1s一個)
kubectl rolling-update nginx2 -f k8s_rc.yaml --update-period=1s
[root@k8s-master rc]# kubectl rolling-update nginx2 -f k8s_rc.yaml --update-period=1s
Created nginx
Scaling up nginx from 0 to 5, scaling down nginx2 from 5 to 0 (keep 5 pods available, don't exceed 6 pods)
Scaling nginx up to 1
Scaling nginx2 down to 4
Scaling nginx up to 2
Scaling nginx2 down to 3
Scaling nginx up to 3
Scaling nginx2 down to 2
Scaling nginx up to 4
Scaling nginx2 down to 1
Scaling nginx up to 5
Scaling nginx2 down to 0
Update succeeded. Deleting nginx2
replicationcontroller "nginx2" rolling updated to "nginx"
[root@k8s-master rc]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-4r223 1/1 Running 0 16s 172.18.100.4 10.0.0.13
nginx-8phch 1/1 Running 0 13s 172.18.100.3 10.0.0.13
nginx-dc8wc 1/1 Running 0 15s 172.18.100.2 10.0.0.13
nginx-kcmpv 1/1 Running 0 11s 172.18.100.5 10.0.0.13
nginx-mknrb 1/1 Running 0 9s 172.18.100.6 10.0.0.13
[root@k8s-master rc]# curl -I 172.18.100.6
HTTP/1.1 200 OK
Server: nginx/1.13.12
Date: Mon, 07 Dec 2020 11:33:03 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Mon, 09 Apr 2018 16:01:09 GMT
Connection: keep-alive
ETag: "5acb8e45-264"
Accept-Ranges: bytes
Service
service:提供服務的自動發現和負載均衡
Pod隨時會被銷毀和重新創建、並且每個Pod會通過調度器將其部署到不同的N個Node節點,這樣會導致Pod ip地址會發生變化。所以需要通過Service去發現Pod並獲取其IP地址。
K8s中三種Ip地址類型:Node ip、cluster ip、pod ip。
Pod使用RC(Replication Controller)實現高可用,會出現一些問題:
-
只能在k8s的內部訪問,客戶端無法訪問,因為Pod IP是私有IP地址,外界無法訪問。
-
K8s中Node端口映射不可以直接映射到的Pod IP。如果一些Pod死掉了,RC就會創建一些新的Pod,新的Pod的ip地址會變化,此時做端口映射,修改規則很麻煩。
K8s使用Service資源,kube-proxy服務自動隨機分配固定不變的VIP(cluster ip),VIP地址段的范圍是10.254.0.0/16。Service資源幫助pod暴露端口。
Pod與Service的關系
- 防止Pod失聯,獲取Pod信息(通過label-selector關聯)
- 定義一組Pod的訪問策略(負載均衡 TCP/UDP 4層)
- 支持ClusterIP,NodePort以及LoadBalancer 三種類型
- Server的底層實現主要有iptables和IPVS二種網絡模式
每個Service關聯一個應用,每個Service資源自動關連一個同名endpoints資源。
Service類型
- ClusterIP:默認,主要實現不同Pod之間互相訪問,是分配在一個集群內部,可以訪問的虛擬IP(vip)。
- NodePort:在每個Node上分配一個端口作為外部訪問入口
- LoadBalancer:工作在特定的Cloud Provider上,例如Google Cloud, AWS,OpenStack
- master節點編寫service資源yaml
mkdir -p /root/k8s_yaml/svc && cd /root/k8s_yaml/svc
cat > /root/k8s_yaml/svc/k8s_svc.yaml <<EOF
apiVersion: v1
kind: Service # 簡稱svc
metadata:
name: myweb
spec:
type: NodePort # 端口映射類型,默認ClusterIP類型
#clusterIP:10.254.1.1
ports:
- port: 80 # clusterIP port
nodePort: 30000 # node port 默認30000-32767
targetPort: 80 # pod port
selector: # 選擇器。當有多個Pod的時候,需要使用選擇器選擇為那些Pod做負載均衡。和RC一樣,使用標簽選擇器。
app: myweb
EOF
- master節點創建資源
kubectl create -f k8s_svc.yaml
- master節點查看所有svc資源狀態
[root@k8s-master svc]# kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.254.0.1 <none> 443/TCP 3d
myweb 10.254.238.3 <nodes> 80:30000/TCP 4s
[root@k8s-master svc]# kubectl describe svc
Name: kubernetes
Namespace: default
Labels: component=apiserver
provider=kubernetes
Selector: <none>
Type: ClusterIP
IP: 10.254.0.1
Port: https 443/TCP
Endpoints: 10.0.0.11:6443
Session Affinity: ClientIP
No events.
Name: myweb
Namespace: default
Labels: <none>
Selector: app=myweb
Type: NodePort
IP: 10.254.73.4
Port: <unset> 80/TCP
NodePort: <unset> 30000/TCP
Endpoints: 172.18.100.2:80,172.18.100.3:80,172.18.100.4:80 + 2 more...
Session Affinity: None
No events.
- master節點訪問node節點端口
[root@k8s-master svc]# curl -I http://10.0.0.12:30000
HTTP/1.1 200 OK
Server: nginx/1.13.12
Date: Tue, 08 Dec 2020 01:19:56 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Mon, 09 Apr 2018 16:01:09 GMT
Connection: keep-alive
ETag: "5acb8e45-264"
Accept-Ranges: bytes
[root@k8s-master svc]# curl -I http://10.0.0.13:30000
HTTP/1.1 200 OK
Server: nginx/1.13.12
Date: Tue, 08 Dec 2020 01:19:56 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Mon, 09 Apr 2018 16:01:09 GMT
Connection: keep-alive
ETag: "5acb8e45-264"
Accept-Ranges: bytes
service提供負載均衡
- master節點調整rc副本數量
kubectl scale rc nginx --replicas=3
- master節點進入3個pod容器,修改容器的首頁為不同頁面
kubectl get pod
kubectl exec -it pod_name1 /bin/bash
echo 'web01' > /usr/share/nginx/html/index.html
exit
kubectl exec -it pod_name2 /bin/bash
echo 'web02' > /usr/share/nginx/html/index.html
exit
kubectl exec -it pod_name3 /bin/bash
echo 'web03' > /usr/share/nginx/html/index.html
exit
pod中有多個業務容器,使用參數
--container
進入指定業務容器kubectl exec --container=alpine -it test /bin/sh
- master節點驗證負載均衡
[root@k8s-master svc]# i=1;while ((i<=3));do curl http://10.0.0.12:30000;sleep 2;((i++));done
web02
web03
web01
service默認使用iptables實現四層負載均衡。
k8s 1.8版本推薦使用lvs(四層負載均衡 傳輸層tcp,udp)
service提供服務的自動發現
- master節點調整rc副本數量為2,查看pod
kubectl scale rc nginx --replicas=2
kubectl get pod
- master節點調整rc副本數量為3,查看pod
kubectl scale rc nginx --replicas=3
kubectl get pod
自定義nodePort范圍
sed -i "26c KUBE_API_ARGS=\"--service-node-port-range=3000-50000\"" /etc/kubernetes/apiserver
systemctl restart kube-apiserver.service
命令行創建service資源(node端口只能隨機)
kubectl expose rc nginx --type=NodePort --port=80 --target-port=80
service類型
第一種:NodePort類型
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30008
第二種:ClusterIP類型,默認
type: ClusterIP
ports:
- port: 80
targetPort: 80
Deployment
rc在滾動升級之后,標簽改變,但service卻無法跟着改變,會造成服務訪問中斷,於是k8s引入了deployment資源。
Deployment 為Pod
和ReplicaSet
之上,提供了一個聲明式定義(declarative)方法,替代以前的ReplicationController
來方便的管理應用。
只需要在Deployment
中描述您想要的目標狀態
是什么,Deployment controller
就會幫您將Pod
和ReplicaSet
的實際狀態改變到您的目標狀態
。可以定義一個新的Deployment
來創建ReplicaSet
或者刪除已有的 Deployment
並創建一個新的來替換。也就是說Deployment
是可以管理多個ReplicaSet
的,如下圖:
雖然也 ReplicaSet 可以獨立使用,但建議使用 Deployment 來自動管理 ReplicaSet,這樣就無需擔心跟其他機制的不兼容問題。
- master節點編寫deployment資源yaml
mkdir -p /root/k8s_yaml/deploy && cd /root/k8s_yaml/deploy
cat > /root/k8s_yaml/deploy/k8s_deploy.yaml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 3
strategy: # 策略
rollingUpdate: # 滾動升級
maxSurge: 1 # 多啟動幾個容器
maxUnavailable: 1 # 最大不可用的pod數量
type: RollingUpdate
minReadySeconds: 30 # 升級間隔最小秒
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: 10.0.0.11:5000/nginx:1.13
ports:
- containerPort: 80
resources: # 資源
limits: # 限制
cpu: 100m
memory: 50Mi
requests:
cpu: 100m
memory: 50Mi
EOF
- master節點創建資源
kubectl create -f k8s_deploy.yaml
- master節點查看資源狀態
[root@k8s-master deploy]# kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx 3 3 3 0 3s
[root@k8s-master deploy]# kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-2807576163-3550z 1/1 Running 0 4s app=nginx,pod-template-hash=2807576163
nginx-2807576163-bmxmz 1/1 Running 0 4s app=nginx,pod-template-hash=2807576163
nginx-2807576163-pt83k 1/1 Running 0 4s app=nginx,pod-template-hash=2807576163
nginx-8phch 1/1 Running 1 15h app=myweb
nginx-dc8wc 1/1 Running 1 15h app=myweb
nginx-twk24 1/1 Running 0 1h app=myweb
[root@k8s-master deploy]# kubectl get all
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deploy/nginx 3 3 3 3 41m
NAME DESIRED CURRENT READY AGE
rc/nginx 3 3 3 16h
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc/kubernetes 10.254.0.1 <none> 443/TCP 3d
svc/myweb 10.254.73.4 <nodes> 80:30000/TCP 2h
svc/nginx 10.254.185.133 <nodes> 80:31504/TCP 38m
NAME DESIRED CURRENT READY AGE
rs/nginx-2807576163 0 0 0 41m
rs/nginx-3014407781 3 3 3 34m
NAME READY STATUS RESTARTS AGE
po/nginx-3014407781-4j9ld 1/1 Running 0 34m
po/nginx-3014407781-dbw3c 1/1 Running 0 30m
po/nginx-3014407781-prlzh 1/1 Running 0 34m
po/nginx-8phch 1/1 Running 1 16h
po/nginx-dc8wc 1/1 Running 1 16h
po/nginx-twk24 1/1 Running 0 2h
deployment滾動升級
deployment滾動升級不依賴配置文件,服務訪問不中斷;修改配置文件立即生效。
deployment升級時:更新了Pod,通過創建一個新的Replica Set(rc的升級版)並擴容3個replica,同時將原來的Replica Set縮容到0個replica。
下次更新這些pod的時候,只需要更新Deployment中的pod的template即可。
Deployment可以保證在升級時只有一定數量的Pod是down的。默認maxUnavailable: 1(最多一個不可用)。
Deployment同時也可以確保只創建出超過期望數量的一定數量的Pod。默認maxSurge: 1(最多1個surge)。
- 命令行創建service資源
kubectl expose deploy nginx --type=NodePort --port=80 --target-port=80
- 查看service資源映射node端口
[root@k8s-master deploy]# kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.254.0.1 <none> 443/TCP 3d
myweb 10.254.73.4 <nodes> 80:30000/TCP 1h
nginx 10.254.185.133 <nodes> 80:31504/TCP 19s
- 升級:修改deployment配置文件。僅需要修改鏡像版本
kubectl edit deployment nginx
- 訪問驗證:升級過程中新老版本可以同時訪問
i=1;while ((i<=3));do curl -I 10.0.0.12:31504;sleep 1;((i++));done
deployment升級和回滾
命令行創建deployment(--record 記錄版本變更原因)
kubectl run nginx --image=10.0.0.11:5000/nginx:1.13 --replicas=3 --record
命令行滾動升級版本
kubectl set image deployment nginx nginx=10.0.0.11:5000/nginx:1.15
pod中有多個業務容器,指定業務容器名稱
alpine=10.0.0.11:5000/alpine:1.15
查看deployment所有歷史版本
kubectl rollout history deployment nginx
deployment回滾到上一個版本
kubectl rollout undo deployment nginx
deployment回滾到指定版本
kubectl rollout undo deployment nginx --to-revision=2
間章:練習
k8s中容器之間通過VIP相互訪問
tomcat+mysql:2個deployment資源和2個service資源。tomcat訪問mysql的svc提供的VIP
- node節點下載鏡像,上傳至私有倉庫
docker pull tomcat-app:v2
docker tag docker.io/kubeguide/tomcat-app:v2 10.0.0.11:5000/tomcat-app:v2
docker push 10.0.0.11:5000/tomcat-app:v2
docker pull mysql:5.7
docker tag docker.io/mysql:5.7 10.0.0.11:5000/mysql:5.7
docker push 10.0.0.11:5000/mysql:5.7
- master節點創建配置文件
mkdir -p /root/k8s_yaml/tomcat_demo && cd /root/k8s_yaml/tomcat_demo
cat > /root/k8s_yaml/tomcat_demo/mysql-rc.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
name: mysql
spec:
replicas: 1
selector:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: 10.0.0.11:5000/mysql:5.7
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: '123456'
EOF
cat > /root/k8s_yaml/tomcat_demo/mysql-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
targetPort: 3306
selector:
app: mysql
EOF
cat > /root/k8s_yaml/tomcat_demo/tomcat-rc.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
name: myweb
spec:
replicas: 1
selector:
app: myweb
template:
metadata:
labels:
app: myweb
spec:
containers:
- name: myweb
image: 10.0.0.11:5000/tomcat-app:v2
ports:
- containerPort: 8080
env:
- name: MYSQL_SERVICE_HOST
value: 'mysql'
- name: MYSQL_SERVICE_PORT
value: '3306'
EOF
cat > /root/k8s_yaml/tomcat_demo/tomcat-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
name: myweb
spec:
type: NodePort
ports:
- port: 8080
nodePort: 30008
selector:
app: myweb
EOF
- master節點創建mysql的rc和svc資源
kubectl create -f mysql-rc.yml
kubectl create -f mysql-svc.yml
- master節點查看所有svc資源
[root@k8s-master tomcat_demo]# kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.254.0.1 <none> 443/TCP 3d
mysql 10.254.37.112 <none> 3306/TCP 18s
myweb 10.254.73.4 <nodes> 80:30000/TCP 5h
nginx 10.254.185.133 <nodes> 80:31504/TCP 3h
- master節點刪除已有同名svc資源myweb
kubectl delete svc myweb
- master節點修改tomcat的rc資源配置文件,修改變量MYSQL_SERVICE_HOST的值為mysql的VIP
vim tomcat-rc.yml
- master節點創建tomcat的rc和svc資源
kubectl create -f tomcat-rc.yml
kubectl create -f tomcat-svc.yml
資源創建流程
創建pod資源流程:
- 用戶和
api-server
交互,使用創建命令kubectl create -f .
api-server
檢查yaml文件語法- 錯誤,報錯
- 正確寫入etcd數據庫
api-server
調用scheduler
- 沒有可用node,Pending
- 調度成功,返回name給
api-server
api-server
調用kubelet
,發送pod配置文件
刪除pod資源流程:
- 用戶和
api-server
交互,使用創建命令kubectl delete pod nginx
api-server
修改etcd數據庫中pod的狀態api-server
調用kubelet
停止並刪除容器- 調用失敗,Unkown
- 調用成功,
api-server
刪除etcd數據庫中pod的記錄
創建deployment資源流程:
- 用戶和
api-server
交互,使用創建命令kubectl create -f .
api-server
檢查yaml文件語法- 錯誤,報錯
- 正確寫入etcd數據庫
controller-manager
創建rscontroller-manager
申請創建podapi-server
調用scheduler
- 沒有可用node,Pending
- 調度成功,返回name給
api-server
api-server
調用kubelet
,發送pod配置文件
DaemonSet
不需要指定副本數,有幾個node節點創建幾個。
在一個區域(zone)
或者所有Node
上運行同一個守護進程(pod)
:
- 每個Node上運行一個分布式存儲的守護進程,例如glusterd,ceph等。
- 日志采集器運行在每個Node上,例如fluentd,logstash等。
- 監控的采集端運行在每個Node,例如prometheus node exporter,collectd等。
DaemonSet的Pod調度策略與RC類似,除了使用系統內置的調度算法在每個Node上進行調度,也可以在Pod定義中使用NodeSelector或NodeAffinity來指定滿足條件的Node范圍進行調度。
注意:各資源labels不能一致!否則會導致pod一直刪除再創建死循環。
mkdir -p /root/k8s_yaml/daemonset && cd /root/k8s_yaml/daemonset
cat > /root/k8s_yaml/daemonset/k8s_daemonset.yaml <<EOF
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: nginx
spec:
template:
metadata:
labels:
app: oldboy
spec:
containers:
- name: nginx
image: 10.0.0.11:5000/nginx:1.13
ports:
- containerPort: 80
EOF
kubectl create -f k8s_daemonset.yaml
kubectl get pod -o wide
其他資源
- StatefulSet (PetSets)
- StatefulSet (PetSets):寵物應用,有狀態的應用,pod名稱固定(有序 01 02 03),適用於每個Pod中有自己的編號,需要互相訪問,以及持久存儲區分。例如數據庫應用,redis,ES集群,mysql集群
- 其他資源:畜生應用,無狀態的應用,pod名稱隨機
- Jobs
- Jobs:一次性任務,完成狀態complate
- Pod:一直運行
- Cronjobs:定時任務
- Ingress
- Ingress:七層負載均衡
- Service:四層負載均衡
- Secret:密碼,密鑰
- ConfigMaps:配置文件
資源總結
k8s資源 | 作用 |
---|---|
daemonSet | 用來描述每個宿主機上必須且只能運行一個副本的守護進程服務 |
Job | 用來描述一次性運行的 Pod(比如,大數據任務) |
CronJob | 用於描述定時任務 |
k8s附加組件
DNS服務
DNS服務:將svc的名稱解析成對應VIP地址
- node2節點(10.0.0.13)下載鏡像,並導入(4個鏡像,來自google倉庫)
[root@k8s-node-2 ~]# docker load -i docker_k8s_dns.tar.gz
8ac8bfaff55a: Loading layer 1.293 MB/1.293 MB
5f70bf18a086: Loading layer 1.024 kB/1.024 kB
b79219965469: Loading layer 45.91 MB/45.91 MB
Loaded image: gcr.io/google_containers/kubedns-amd64:1.9
3fc666989c1d: Loading layer 5.046 MB/5.046 MB
5f70bf18a086: Loading layer 1.024 kB/1.024 kB
9eed5e14d7fb: Loading layer 348.7 kB/348.7 kB
00dc4ffe8624: Loading layer 2.56 kB/2.56 kB
Loaded image: gcr.io/google_containers/kube-dnsmasq-amd64:1.4
9007f5987db3: Loading layer 5.05 MB/5.05 MB
5f70bf18a086: Loading layer 1.024 kB/1.024 kB
d41159f2130e: Loading layer 9.201 MB/9.201 MB
Loaded image: gcr.io/google_containers/dnsmasq-metrics-amd64:1.0
dc978cfc3e09: Loading layer 7.279 MB/7.279 MB
99740866972b: Loading layer 7.168 kB/7.168 kB
5f70bf18a086: Loading layer 1.024 kB/1.024 kB
Loaded image: gcr.io/google_containers/exechealthz-amd64:1.2
- master節點創建配置文件(指定調度到node2)
mkdir -p /root/k8s_yaml/dns && cd /root/k8s_yaml/dns
cat > /root/k8s_yaml/dns/skydns-svc.yaml <<EOF
# Copyright 2016 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# TODO - At some point, we need to rename all skydns-*.yaml.* files to kubedns-*.yaml.*
# Warning: This is a file generated from the base underscore template file: skydns-svc.yaml.base
apiVersion: v1
kind: Service
metadata:
name: kube-dns
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
kubernetes.io/name: "KubeDNS"
spec:
selector:
k8s-app: kube-dns
clusterIP: 10.254.230.254
ports:
- name: dns
port: 53
protocol: UDP
- name: dns-tcp
port: 53
protocol: TCP
EOF
cat > /root/k8s_yaml/dns/skydns.yaml <<EOF
# Copyright 2016 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# TODO - At some point, we need to rename all skydns-*.yaml.* files to kubedns-*.yaml.*
# Should keep target in cluster/addons/dns-horizontal-autoscaler/dns-horizontal-autoscaler.yaml
# in sync with this file.
# __MACHINE_GENERATED_WARNING__
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: kube-dns
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
spec:
replicas: 1
# replicas: not specified here:
# 1. In order to make Addon Manager do not reconcile this replicas parameter.
# 2. Default is 1.
# 3. Will be tuned in real time if DNS horizontal auto-scaling is turned on.
strategy:
rollingUpdate:
maxSurge: 10%
maxUnavailable: 0
selector:
matchLabels:
k8s-app: kube-dns
template:
metadata:
labels:
k8s-app: kube-dns
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ''
scheduler.alpha.kubernetes.io/tolerations: '[{"key":"CriticalAddonsOnly", "operator":"Exists"}]'
spec:
nodeName: 10.0.0.13 # 指定調度到的node
containers:
- name: kubedns
image: gcr.io/google_containers/kubedns-amd64:1.9
resources:
# TODO: Set memory limits when we've profiled the container for large
# clusters, then set request = limit to keep this container in
# guaranteed class. Currently, this container falls into the
# "burstable" category so the kubelet doesn't backoff from restarting it.
limits:
memory: 170Mi
requests:
cpu: 100m
memory: 70Mi
livenessProbe:
httpGet:
path: /healthz-kubedns
port: 8080
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
readinessProbe:
httpGet:
path: /readiness
port: 8081
scheme: HTTP
# we poll on pod startup for the Kubernetes master service and
# only setup the /readiness HTTP server once that's available.
initialDelaySeconds: 3
timeoutSeconds: 5
args:
- --domain=cluster.local.
- --dns-port=10053
- --config-map=kube-dns
- --kube-master-url=http://10.0.0.11:8080
# This should be set to v=2 only after the new image (cut from 1.5) has
# been released, otherwise we will flood the logs.
- --v=0
#__PILLAR__FEDERATIONS__DOMAIN__MAP__
env:
- name: PROMETHEUS_PORT
value: "10055"
ports:
- containerPort: 10053
name: dns-local
protocol: UDP
- containerPort: 10053
name: dns-tcp-local
protocol: TCP
- containerPort: 10055
name: metrics
protocol: TCP
- name: dnsmasq
image: gcr.io/google_containers/kube-dnsmasq-amd64:1.4
livenessProbe:
httpGet:
path: /healthz-dnsmasq
port: 8080
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
args:
- --cache-size=1000
- --no-resolv
- --server=127.0.0.1 # 10053
#- --log-facility=-
ports:
- containerPort: 53
name: dns
protocol: UDP
- containerPort: 53
name: dns-tcp
protocol: TCP
# see: https://github.com/kubernetes/kubernetes/issues/29055 for details
resources:
requests:
cpu: 150m
memory: 10Mi
- name: dnsmasq-metrics
image: gcr.io/google_containers/dnsmasq-metrics-amd64:1.0
livenessProbe:
httpGet:
path: /metrics
port: 10054
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
args:
- --v=2
- --logtostderr
ports:
- containerPort: 10054
name: metrics
protocol: TCP
resources:
requests:
memory: 10Mi
- name: healthz
image: gcr.io/google_containers/exechealthz-amd64:1.2
resources:
limits:
memory: 50Mi
requests:
cpu: 10m
# Note that this container shouldn't really need 50Mi of memory. The
# limits are set higher than expected pending investigation on #29688.
# The extra memory was stolen from the kubedns container to keep the
# net memory requested by the pod constant.
memory: 50Mi
args:
- --cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1 >/dev/null
- --url=/healthz-dnsmasq
- --cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1:10053 >/dev/null
- --url=/healthz-kubedns
- --port=8080
- --quiet
ports:
- containerPort: 8080
protocol: TCP
dnsPolicy: Default # Don't use cluster DNS.
EOF
- master節點創建DNS的資源
kubectl create -f .
- master節點檢查命名空間kube-system
kubectl get namespace
kubectl get all -n kube-system -o wide
[root@k8s-master dns]# kubectl get all -n kube-system
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deploy/kube-dns 1 1 1 1 10m
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc/kube-dns 10.254.230.254 <none> 53/UDP,53/TCP 10m
NAME DESIRED CURRENT READY AGE
rs/kube-dns-249145955 1 1 1 10m
NAME READY STATUS RESTARTS AGE
po/kube-dns-249145955-wdmq8 4/4 Running 0 10m
- 所有node節點修改kubelet配置文件,重啟服務
sed -i '20c KUBELET_ARGS=\"--cluster_dns=10.254.230.254 --cluster_domain=cluster.local\"' /etc/kubernetes/kubelet
systemctl restart kubelet
- master節點修改tomcat的rc資源配置文件,修改變量MYSQL_SERVICE_HOST的值為mysql,重新創建資源
cd /root/k8s_yaml/tomcat_demo
vim tomcat-rc.yml
kubectl delete -f .
kubectl create -f .
- master節點驗證
[root@k8s-master tomcat_demo]# kubectl get pod # 查找myweb容器名
NAME READY STATUS RESTARTS AGE
mysql-sj480 1/1 Running 0 3m
myweb-th9rx 1/1 Running 0 1m
[root@k8s-master tomcat_demo]# kubectl exec -it myweb-th9rx /bin/bash #進入容器
root@myweb-th9rx:/usr/local/tomcat# cat /etc/resolv.conf # 查看DNS解析
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.254.230.254
nameserver 223.5.5.5
options ndots:5
root@myweb-th9rx:/usr/local/tomcat# ping mysql # 能解析,不能ping通,VIP
PING mysql.default.svc.cluster.local (10.254.106.204): 56 data bytes
^C--- mysql.default.svc.cluster.local ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss
root@myweb-th9rx:/usr/local/tomcat# exit
exit
namespace命名空間
namespace:實現資源隔離
- 查看命名空間
kubectl get namespace
- 創建命名空間
kubectl create namespace tomcat
- 修改配置文件指定命名空間
cd /root/k8s_yaml/tomcat_demo/
sed -i "3a \ \ namespace: tomcat" *
yum install dos2unix -y
dos2unix *
- 刪除所有svc和rc資源
kubectl delete svc --all
kubectl delete rc --all
- 創建rc和svc資源
kubectl create -f .
- 查看命名空間tomcat的所有資源
kubectl get all -n tomcat
間章:作業
k8s中容器之間通過VIP相互訪問,應用DNS,namespace
wordpress+mysql:2個deployment資源和2個service資源。wordpress訪問mysql的svc提供的VIP
- node下載鏡像,上傳至私有倉庫
docker pull wordpress
docker tag docker.io/wordpress:latest 10.0.0.11:5000/wordpress:latest
docker push 10.0.0.11:5000/wordpress:latest
docker pull mysql:5.7
docker tag docker.io/mysql:5.7 10.0.0.11:5000/mysql:5.7
docker push 10.0.0.11:5000/mysql:5.7
- 創建rc和svc配置文件
mkdir -p /root/k8s_yaml/wordpress_rc && cd /root/k8s_yaml/wordpress_rc
cat > /root/k8s_yaml/wordpress_rc/mysql-rc.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
namespace: wordpress
name: mysql
spec:
replicas: 1
selector:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
nodeName: 10.0.0.12
containers:
- name: mysql
image: 10.0.0.11:5000/mysql:5.7
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: 'root_pwd'
- name: MYSQL_DATABASE
value: 'blog'
- name: MYSQL_USER
value: 'blog'
- name: MYSQL_PASSWORD
value: 'blog'
args:
- --character-set-server=utf8
- --collation-server=utf8_bin
EOF
cat > /root/k8s_yaml/wordpress_rc/mysql-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
namespace: wordpress
name: mysql
spec:
ports:
- port: 3306
targetPort: 3306
selector:
app: mysql
EOF
cat > /root/k8s_yaml/wordpress_rc/wordpress-rc.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
namespace: wordpress
name: wordpress
spec:
replicas: 1
selector:
app: wordpress
template:
metadata:
labels:
app: wordpress
spec:
nodeName: 10.0.0.12
containers:
- name: wordpress
image: 10.0.0.11:5000/wordpress:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
env:
- name: WORDPRESS_DB_HOST
value: 'mysql'
- name: WORDPRESS_DB_PASSWORD
value: 'blog'
- name: WORDPRESS_DB_USER
value: 'blog'
- name: WORDPRESS_DB_NAME
value: 'blog'
EOF
cat > /root/k8s_yaml/wordpress_rc/wordpress-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
namespace: wordpress
name: wordpress
spec:
type: NodePort
ports:
- port: 80
nodePort: 30080
selector:
app: wordpress
EOF
查看系統補全的配置文件
kubectl get pod NAME -n NAMESPACE -o yaml
鏡像拉取策略
[root@k8s-master ~]# kubectl explain pod.spec.containers.imagePullPolicy FIELD: imagePullPolicy <string> DESCRIPTION: Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/images#updating-images Always 每次創建Pod都會重新拉取一次鏡像 Never Pod永遠不會主動拉取這個鏡像 IfNotPresent 默認值,鏡像在宿主機上不存在時才拉取
- 刪除所有資源
kubectl delete svc --all
kubectl delete rc --all
kubectl delete deployment --all
- 創建命名空間
kubectl create namespace wordpress
- 創建資源
kubectl create -f .
- 查看svc資源,訪問:http://10.0.0.12:30080/
kubectl get all -n wordpress -o wide
- 創建deploy和svc配置文件
mkdir -p /root/k8s_yaml/wordpress_demo && cd /root/k8s_yaml/wordpress_demo
cat > /root/k8s_yaml/wordpress_demo/mysql-demo.yml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
namespace: wordpress
name: mysql
spec:
replicas: 1
template:
metadata:
labels:
app: mysql
spec:
nodeName: 10.0.0.12
containers:
- name: mysql
image: 10.0.0.11:5000/mysql:5.7
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: 'root_pwd'
- name: MYSQL_DATABASE
value: 'blog'
- name: MYSQL_USER
value: 'blog'
- name: MYSQL_PASSWORD
value: 'blog'
args:
- --character-set-server=utf8
- --collation-server=utf8_bin
EOF
cat > /root/k8s_yaml/wordpress_demo/mysql-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
namespace: wordpress
name: mysql
spec:
ports:
- port: 3306
targetPort: 3306
selector:
app: mysql
EOF
cat > /root/k8s_yaml/wordpress_demo/wordpress-demo.yml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
namespace: wordpress
name: wordpress
spec:
replicas: 1
template:
metadata:
labels:
app: wordpress
spec:
nodeName: 10.0.0.12
containers:
- name: wordpress
image: 10.0.0.11:5000/wordpress:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
env:
- name: WORDPRESS_DB_HOST
value: 'mysql'
- name: WORDPRESS_DB_PASSWORD
value: 'blog'
- name: WORDPRESS_DB_USER
value: 'blog'
- name: WORDPRESS_DB_NAME
value: 'blog'
EOF
cat > /root/k8s_yaml/wordpress_demo/wordpress-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
namespace: wordpress
name: wordpress
spec:
type: NodePort
ports:
- port: 80
nodePort: 30080
selector:
app: wordpress
EOF
健康檢查和可用性檢查
探針種類:
livenessProbe
:健康狀態檢查,周期性檢查服務是否存活,檢查結果失敗,自動重啟容器。
readinessProbe
:可用性檢查,周期性檢查服務是否可用,不可用將從service的endpoints中移除。
探針檢測方法:
- exec:執行一段命令,返回值為0正常,非0錯誤。
- httpGet:檢測某個 http 請求的返回狀態碼 2xx,3xx正常;4xx,5xx錯誤。
- tcpSocket:測試某個端口是否能夠連接。
liveness探針的exec使用
mkdir -p /root/check/ && cd /root/check/
cat > /root/check/nginx_pod_exec.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
name: exec
spec:
containers:
- name: nginx
image: 10.0.0.11:5000/nginx:1.13
ports:
- containerPort: 80
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessProbe: # 模擬健康檢查,啟動后30s內健康,之后不健康
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5 # 初始化5秒后開始檢查
periodSeconds: 5 # 檢查周期5s一次
timeoutSeconds: 3 # 檢查命令執行超時時間,默認1s
successThreshold: 1 # 檢查成功1次就算成功,默認1次
failureThreshold: 1 # 檢查失敗1次就算失敗,默認3次
EOF
kubectl create -f nginx_pod_exec.yaml
kubectl describe pod exec
mysqladmin ping # 檢測mysql存活
liveness探針的httpGet使用
cat > /root/check/nginx_pod_httpGet.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
name: httpget
spec:
containers:
- name: nginx
image: 10.0.0.11:5000/nginx:1.13
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /index.html
port: 80
initialDelaySeconds: 3
periodSeconds: 3
EOF
kubectl create -f nginx_pod_httpGet.yaml
kubectl describe pod httpget
kubectl exec -it httpget /bin/bash
rm -f /usr/share/nginx/html/index/html
exit
kubectl describe pod httpget
liveness探針的tcpSocket使用
cat > /root/check/nginx_pod_tcpSocket.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
name: tcpsocket
spec:
containers:
- name: nginx
image: 10.0.0.11:5000/nginx:1.13
ports:
- containerPort: 80
args:
- /bin/sh
- -c
- tail -f /etc/hosts
livenessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 10
periodSeconds: 3
EOF
kubectl create -f nginx_pod_tcpSocket.yaml
kubectl describe pod tcpsocket
kubectl exec -it tcpsocket /bin/bash
nginx -s stop
exit
kubectl describe pod tcpsocket
readiness探針的httpGet使用
cat > /root/check/nginx_rc_httpGet.yaml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
name: readiness
spec:
replicas: 2
selector:
app: readiness
template:
metadata:
labels:
app: readiness
spec:
containers:
- name: readiness
image: 10.0.0.11:5000/nginx:1.13
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /qiangge.html
port: 80
initialDelaySeconds: 3
periodSeconds: 3
EOF
kubectl create -f nginx_rc_httpGet.yaml
kubectl expose rc readiness --type=NodePort --port=80 --target-port=80
kubectl describe svc readiness
kubectl get pod
kubectl exec -it readiness-NAME /bin/bash
echo 'web' > /usr/share/nginx/html/qiangge.html
exit
kubectl get pod
kubectl describe svc readiness
Dashboard服務
- node2節點(10.0.0.13)下載鏡像,並導入,打標(來自tenxcloud倉庫)
[root@k8s-node-2 opt]# docker load -i kubernetes-dashboard-amd64_v1.4.1.tar.gz
5f70bf18a086: Loading layer 1.024 kB/1.024 kB
2e350fa8cbdf: Loading layer 86.96 MB/86.96 MB
Loaded image: index.tenxcloud.com/google_containers/kubernetes-dashboard-amd64:v1.4.1
[root@k8s-node-2 opt]# docker tag index.tenxcloud.com/google_containers/kubernetes-dashboard-amd64:v1.4.1 10.0.0.11:5000/kubernetes-dashboard-amd64:v1.4.1
- master節點創建配置文件(指定調度到node2)
mkdir -p /root/k8s_yaml/dashboard/ && cd /root/k8s_yaml/dashboard/
cat > /root/k8s_yaml/dashboard/dashboard.yaml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
# Keep the name in sync with image version and
# gce/coreos/kube-manifests/addons/dashboard counterparts
name: kubernetes-dashboard-latest
namespace: kube-system
spec:
replicas: 1
template:
metadata:
labels:
k8s-app: kubernetes-dashboard
version: latest
kubernetes.io/cluster-service: "true"
spec:
nodeName: 10.0.0.13 # 指定調度到的node
containers:
- name: kubernetes-dashboard
image: 10.0.0.11:5000/kubernetes-dashboard-amd64:v1.4.1
resources:
# keep request = limit to keep this container in guaranteed class
limits:
cpu: 100m
memory: 50Mi
requests:
cpu: 100m
memory: 50Mi
ports:
- containerPort: 9090
args:
- --apiserver-host=http://10.0.0.11:8080
livenessProbe:
httpGet:
path: /
port: 9090
initialDelaySeconds: 30
timeoutSeconds: 30
EOF
cat > /root/k8s_yaml/dashboard/dashboard-svc.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
name: kubernetes-dashboard
namespace: kube-system
labels:
k8s-app: kubernetes-dashboard
kubernetes.io/cluster-service: "true"
spec:
selector:
k8s-app: kubernetes-dashboard
ports:
- port: 80
targetPort: 9090
EOF
- master節點創建dashboard的資源
kubectl create -f .
- master節點檢查命名空間kube-system
kubectl get all -n kube-system
全局資源
- Namespaces
- Nodes
- Persistemt Volume Claims
局部資源(各Namespaces分別使用的資源)
通過apiservice反向代理訪問service資源
-
分析dashboard服務web頁面
主頁+錨點(#)
http://10.0.0.11:8080/api/v1/proxy/namespaces/kube-system/services/kubernetes-dashboard/#/workload?namespace=default
- 查看所有命名空間的svc
kubectl get svc --all-namespaces
- 通過apiservice反向代理訪問service資源
http://10.0.0.11:8080/api/v1/proxy/namespaces/命名空間名稱/services/service名稱/
彈性伸縮
Kubernetes HPA(Horizontal Pod Autoscaler)Pod 水平自動擴縮:可以基於 CPU 利用率自動擴縮 ReplicationController、Deployment、ReplicaSet 和 StatefulSet 中的 Pod 數量。 除了 CPU 利用率,也可以基於其他應程序提供的自定義度量指標來執行自動擴縮。 但不適用於無法擴縮的對象,比如 DaemonSet。
Pod 水平自動擴縮特性由 Kubernetes API 資源和控制器實現。資源決定了控制器的行為。 控制器會周期性的調整副本控制器或 Deployment 中的副本數量,以使得 Pod 的平均 CPU 利用率與用戶所設定的目標值匹配。
Pod水平自動伸縮:
- 1.11版本之前,依賴heapster監控各node節點信息。
- 1.11版本之后,使用metric-server采集指標信息。
HPA工作機制
安裝heapster監控
k8s原生集群監控方案(Heapster+InfluxDB+Grafana+Dashboard) :
Heapster處理數據儲存到InfluxDB,Grafana從InfluxDB讀取數據出圖,Dashboard調用Grafana的圖。
- node2節點(10.0.0.13)下載鏡像,並導入,打標(3個鏡像,來自官方倉庫)
for n in `ls *.tar.gz`;do docker load -i $n ;done
docker tag docker.io/kubernetes/heapster_grafana:v2.6.0 10.0.0.11:5000/heapster_grafana:v2.6.0
docker tag docker.io/kubernetes/heapster_influxdb:v0.5 10.0.0.11:5000/heapster_influxdb:v0.5
docker tag docker.io/kubernetes/heapster:canary 10.0.0.11:5000/heapster:canary
- master節點創建配置文件(指定調度到node2)
mkdir -p /root/k8s_yaml/heapster-influxdb && cd /root/k8s_yaml/heapster-influxdb
cat > /root/k8s_yaml/heapster-influxdb/heapster-controller.yaml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
labels:
k8s-app: heapster
name: heapster
version: v6
name: heapster
namespace: kube-system
spec:
replicas: 1
selector:
k8s-app: heapster
version: v6
template:
metadata:
labels:
k8s-app: heapster
version: v6
spec:
nodeName: 10.0.0.13 # 指定調度到的node
containers:
- name: heapster
image: 10.0.0.11:5000/heapster:canary
#imagePullPolicy: Always
command:
- /heapster
- --source=kubernetes:http://10.0.0.11:8080?inClusterConfig=false
- --sink=influxdb:http://monitoring-influxdb:8086
EOF
cat > /root/k8s_yaml/heapster-influxdb/influxdb-grafana-controller.yaml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
labels:
name: influxGrafana
name: influxdb-grafana
namespace: kube-system
spec:
replicas: 1
selector:
name: influxGrafana
template:
metadata:
labels:
name: influxGrafana
spec:
nodeName: 10.0.0.13 # 指定調度到的node
containers:
- name: influxdb
image: 10.0.0.11:5000/heapster_influxdb:v0.5
volumeMounts:
- mountPath: /data
name: influxdb-storage
- name: grafana
image: 10.0.0.11:5000/heapster_grafana:v2.6.0
env:
- name: INFLUXDB_SERVICE_URL
value: http://monitoring-influxdb:8086
# The following env variables are required to make Grafana accessible via
# the kubernetes api-server proxy. On production clusters, we recommend
# removing these env variables, setup auth for grafana, and expose the grafana
# service using a LoadBalancer or a public IP.
- name: GF_AUTH_BASIC_ENABLED
value: "false"
- name: GF_AUTH_ANONYMOUS_ENABLED
value: "true"
- name: GF_AUTH_ANONYMOUS_ORG_ROLE
value: Admin
- name: GF_SERVER_ROOT_URL
value: /api/v1/proxy/namespaces/kube-system/services/monitoring-grafana/
volumeMounts:
- mountPath: /var
name: grafana-storage
volumes:
- name: influxdb-storage
emptyDir: {}
- name: grafana-storage
emptyDir: {}
EOF
cat > /root/k8s_yaml/heapster-influxdb/grafana-service.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
labels:
kubernetes.io/cluster-service: 'true'
kubernetes.io/name: monitoring-grafana
name: monitoring-grafana
namespace: kube-system
spec:
# In a production setup, we recommend accessing Grafana through an external Loadbalancer
# or through a public IP.
# type: LoadBalancer
ports:
- port: 80
targetPort: 3000
selector:
name: influxGrafana
EOF
cat > /root/k8s_yaml/heapster-influxdb/influxdb-service.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
labels: null
name: monitoring-influxdb
namespace: kube-system
spec:
ports:
- name: http
port: 8083
targetPort: 8083
- name: api
port: 8086
targetPort: 8086
selector:
name: influxGrafana
EOF
cat > /root/k8s_yaml/heapster-influxdb/heapster-service.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
labels:
kubernetes.io/cluster-service: 'true'
kubernetes.io/name: Heapster
name: heapster
namespace: kube-system
spec:
ports:
- port: 80
targetPort: 8082
selector:
k8s-app: heapster
EOF
- master節點創建dashboard的資源
kubectl create -f .
- master節點檢查命名空間kube-system,查看集群信息
kubectl get all -n kube-system
kubectl cluster-info
- 瀏覽器訪問dashboard驗證:http://10.0.0.11:8080/ui/
- 可以使用top命令
kubectl top node
彈性伸縮
- master節點創建測試Deployment和svc資源
cd /root/k8s_yaml/deploy
cat > /root/k8s_yaml/deploy/k8s_deploy2.yaml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: 10.0.0.11:5000/nginx:1.13
ports:
- containerPort: 80
resources:
limits:
cpu: 100m
memory: 50Mi
requests:
cpu: 100m
memory: 50Mi
EOF
kubectl create -f k8s_deploy2.yaml
kubectl expose deploy nginx --type=NodePort --port=80 --target-port=80
- 創建彈性伸縮規則
kubectl autoscale deploy nginx --max=8 --min=1 --cpu-percent=5
- 查看hpa資源,nginx訪問地址IP:PORT
kubectl get all -o wide
- 查看hpa資源配置文件
kubectl get hpa nginx -o yaml
- 壓測
yum install httpd-tools -y
ab -n 1000000 -c 40 http://10.0.0.12:32114/index.html
壓測前:
壓測10s后,自動擴容:
停止壓測5分鍾后,自動縮容:
持久化存儲
查看解釋
kubectl explain pod.spec.containers.volumeMounts
kubectl explain pod.spec.volumes
持久化存儲類型:
- emptyDir:共享pod生存期的臨時目錄。
- hostPath:主機上預先存在的文件或目錄直接公開給容器。這通常用於允許查看主機的系統代理或其他特權對象。
- nfs:共享pod生存期的NFS裝載。
emptyDir
臨時的空目錄:伴隨pod的生命周期,隨着pod刪除而刪除,數據持久化但不共享。
適用於存放日志(pod之間不同,但需要保存的數據)。
emptyDir是一種臨時存儲,pod創建的時候會在node節點上為容器申請一個臨時的目錄,跟隨容器的生命周期,若容器刪除,emptyDir定義的臨時存儲空間也會隨之刪除,容器發生意外crash則不受影響,同時如果容器發生了遷移,其上的數據也會丟失,emptyDir一般用於測試,或者緩存場景。注意:容器崩潰不會導致數據的丟失,因為容器的崩潰並不移除pod.
emptyDir
的一些用途:
- 緩存空間,例如基於磁盤的歸並排序。
- 為耗時較長的計算任務提供檢查點,以便任務能方便地從崩潰前狀態恢復執行。
- 在 Web 服務器容器服務數據時,保存內容管理器容器獲取的文件。
- 創建tomcat+mysql的資源
cd /root/k8s_yaml/tomcat_demo && kubectl create -f .
- 訪問:http://10.0.0.12:30008/demo/,添加數據
- node節點清空容器,雖然會重啟一批容器,但之前添加的數據沒了,因此需要持久化存儲
docker rm -f `docker ps -aq`
- master節點創建emptyDir持久化配置文件
cat > /root/k8s_yaml/tomcat_demo/mysql-emptyDir.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
name: mysql
spec:
replicas: 1
selector:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
nodeName: 10.0.0.12
volumes:
- name: mysql
emptyDir: {}
containers:
- name: wp-mysql
image: 10.0.0.11:5000/mysql:5.7
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3306
volumeMounts:
- mountPath: /var/lib/mysql
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: '123456'
EOF
- master節點刪除原rc資源,創建emptyDir持久化的rc資源
kubectl delete -f mysql-rc.yml
kubectl create -f mysql-emptyDir.yml
- node節點查看臨時目錄
ll /var/lib/kubelet/pods/
ll /var/lib/kubelet/pods/sha256號/volumes/kubernetes.io~empty-dir/mysql
刪除pod,這個文件也會自動刪除。
HostPath
HostPath:可以多個容器共享持久化數據,但不能跨宿主機。
hostPath
卷能將node宿主機節點文件系統上的文件或目錄掛載到您的 Pod 中。
- 運行一個需要訪問 Docker 引擎內部機制的容器;請使用
hostPath
掛載/var/lib/docker
路徑。 - 在容器中運行 cAdvisor 時,以
hostPath
方式掛載/sys
。 - 允許 Pod 指定給定的
hostPath
在運行 Pod 之前是否應該存在,是否應該創建以及應該以什么方式存在。
使用這種類型的卷時要小心,因為:
- 具有相同配置(例如從 podTemplate 創建)的多個 Pod 會由於節點上文件的不同而在不同節點上有不同的行為。
- 當 Kubernetes 按照計划添加資源感知的調度時,這類調度機制將無法考慮由
hostPath
使用的資源。 - 基礎主機上創建的文件或目錄只能由 root 用戶寫入。您需要在特權容器中以 root 身份運行進程,或者修改主機上的文件權限以便容器能夠寫入
hostPath
卷。
- master節點創建wordpress+mysql資源
cd /root/k8s_yaml/wordpress_demo
kubectl create namespace wordpress
kubectl create -f .
- master節點持久化mysql
cat > /root/k8s_yaml/wordpress_demo/mysql-demo.yml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
namespace: wordpress
name: mysql
spec:
replicas: 1
template:
metadata:
labels:
app: mysql
spec:
nodeName: 10.0.0.12
volumes:
- name: mysql
emptyDir: {}
containers:
- name: mysql
image: 10.0.0.11:5000/mysql:5.7
volumeMounts:
- mountPath: /var/lib/mysql
name: mysql
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: 'root_pwd'
- name: MYSQL_DATABASE
value: 'blog'
- name: MYSQL_USER
value: 'blog'
- name: MYSQL_PASSWORD
value: 'blog'
args:
- --character-set-server=utf8
- --collation-server=utf8_bin
EOF
- master節點應用配置文件:新建一個資源,此次不適用
kubectl apply -f mysql-demo.yml
kubectl get pod -o wide -n wordpress
kubectl delete deploy -n wordpress --all
kubectl create -f mysql-demo.yml
kubectl create -f wordpress-demo.yml
- master節點持久化wordpress
cat > /root/k8s_yaml/wordpress_demo/wordpress-demo.yml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
namespace: wordpress
name: wordpress
spec:
replicas: 1
template:
metadata:
labels:
app: wordpress
spec:
nodeName: 10.0.0.12
volumes:
- name: wp-code
hostPath:
path: /data/wp-code
containers:
- name: wordpress
image: 10.0.0.11:5000/wordpress:latest
imagePullPolicy: IfNotPresent
volumeMounts:
- name: wp-code
mountPath: /var/www/html
ports:
- containerPort: 80
env:
- name: WORDPRESS_DB_HOST
value: 'mysql'
- name: WORDPRESS_DB_PASSWORD
value: 'blog'
- name: WORDPRESS_DB_USER
value: 'blog'
- name: WORDPRESS_DB_NAME
value: 'blog'
EOF
- master節點替換配置文件,刪除所有pod生效
mkdir -p /data/wp-code
kubectl replace -f wordpress-demo.yml
kubectl delete pod -n wordpress --all
kubectl get pod -o wide -n wordpress
-
安裝wordpress:http://10.0.0.12:30080/
-
node1(10.0.0.12)節點查看持久化目錄
ll /data/wp-code
-
wordpress上傳圖片
-
node1查看上傳圖片
ll /data/wp-code/wp-content/uploads/
刪除pod時,文件不會刪除掉,還要保存到node上。
- master節點修改副本數
kubectl scale -n wordpress deployment wordpress --replicas=2
- master節點查看pod資源
kubectl get pod -o wide -n wordpress
- node1創建phpinfo頁面
echo "<?php phpinfo() ?>" > /data/wp-code/info.php
- 訪問phpinfo頁面,驗證調度到多個pod,但共享數據
curl 10.0.0.12:30080/info.php | grep -i 172.18.98
NFS
NFS:可以多個容器跨宿主機共享持久化數據。
- 所有節點安裝nfs-utils
yum -y install nfs-utils
- master節點部署nfs服務
mkdir -p /data/tomcat-db
cat > /etc/exports <<EOF
/data 10.0.0.0/24(rw,sync,no_root_squash,no_all_squash)
EOF
systemctl start nfs
- 所有node節點檢查掛載
showmount -e 10.0.0.11
- master節點創建nfs持久化配置文件
cd /root/k8s_yaml/tomcat_demo
cat > /root/k8s_yaml/tomcat_demo/mysql-emptyDir.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
name: mysql
spec:
replicas: 1
selector:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
volumes:
- name: mysql
nfs:
path: /data/tomcat-db
server: 10.0.0.11
containers:
- name: wp-mysql
image: 10.0.0.11:5000/mysql:5.7
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3306
volumeMounts:
- mountPath: /var/lib/mysql
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: '123456'
EOF
- master節點替換配置文件,刪除所有pod生效
kubectl replace -f mysql-emptyDir.yml
kubectl delete pod --all
kubectl get pod -o wide
- node1查看nfs掛載
df -Th|grep nfs
-
master節點修改配置文件:調度到13上
cat > /root/k8s_yaml/tomcat_demo/mysql-emptyDir.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
name: mysql
spec:
replicas: 1
selector:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
nodeName: 10.0.0.13
volumes:
- name: mysql
nfs:
path: /data/tomcat-db
server: 10.0.0.11
containers:
- name: wp-mysql
image: 10.0.0.11:5000/mysql:5.7
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3306
volumeMounts:
- mountPath: /var/lib/mysql
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: '123456'
EOF
- master節點替換配置文件,刪除所有pod生效
kubectl replace -f mysql-emptyDir.yml
kubectl delete pod --all
kubectl get pod -o wide
- node2查看nfs掛載
df -Th|grep nfs
PV和PVC
PersistentVolume(持久化卷):全局資源,是對底層的共享存儲的一種抽象。PV 由管理員進行創建和配置,它和具體的底層的共享存儲技術的實現方式有關,比如 Ceph、GlusterFS、NFS 等,都是通過插件機制完成與共享存儲的對接。
PersistentVolumeClaim(持久化卷聲明):局部資源,屬於某一個namespace。PVC 是用戶存儲的一種聲明,PVC 和 Pod 比較類似,Pod 消耗的是節點,PVC 消耗的是 PV 資源,Pod 可以請求 CPU 和內存,而 PVC 可以請求特定的存儲空間和訪問模式。對於真正使用存儲的用戶不需要關心底層的存儲實現細節,只需要直接使用 PVC 即可。
- Volumes:最基礎的存儲抽象,其支持多種類型,包括本地存儲、NFS、FC以及眾多的雲存儲,我們也可以編寫自己的存儲插件來支持特定的存儲系統。Volume可以被Pod直接使用,也可以被PV使用。普通的Volume和Pod之間是一種靜態的綁定關系,在定義Pod的同時,通過volume屬性來定義存儲的類型,通過volumeMount來定義容器內的掛載點。
- PersistentVolume:是Kubernetes中的一個資源對象,創建一個PV相當於創建了一個存儲資源對象,這個資源的使用要通過PVC來請求。
- PersistentVolumeClaim:是用戶對存儲資源PV的請求,根據PVC中指定的條件Kubernetes動態的尋找系統中的PV資源並進行綁定。目前PVC與PV匹配可以通過StorageClassName、matchLabels或者matchExpressions三種方式。
- StorageClass:存儲類,目前kubernetes支持很多存儲,例如ceph,nfs。glusterfs等。
生命周期
PV是集群中的資源。PVC是對這些資源的請求,也是對資源的索賠檢查。 PV和PVC之間的相互作用遵循這個生命周期:Provisioning ——-> Binding ——–>Using——>Releasing——>Recycling
PVC 處理流程
Provisioning
PV的提供方式:靜態或者動態。
- Static:集群管理員創建多個PV。 它們攜帶可供集群用戶使用的真實存儲的詳細信息。 它們存在於Kubernetes API中,可用於消費。
- Dynamic:當管理員創建的靜態PV都不匹配用戶的PersistentVolumeClaim時,集群可能會嘗試為PVC動態配置卷。 此配置基於StorageClasses:PVC必須請求一個類,並且管理員必須已創建並配置該類才能進行動態配置。 要求該類的聲明有效地為自己禁用動態配置。
PV訪問模式
- RWO - ReadWriteOnce——該卷可以被單個節點以讀/寫模式掛載
- ROX - ReadOnlyMany——該卷可以被多個節點以只讀模式掛載
- RWX - ReadWriteMany——該卷可以被多個節點以讀/寫模式掛載
- master節點創建svc配置文件
mkdir -p /root/k8s_yaml/volume && cd /root/k8s_yaml/volume
cat > /root/k8s_yaml/volume/mysql-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
namespace: tomcat
name: mysql
spec:
ports:
- port: 3306
targetPort: 3306
selector:
app: mysql
EOF
cat > /root/k8s_yaml/volume/tomcat-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
namespace: tomcat
name: myweb
spec:
type: NodePort
ports:
- port: 8080
nodePort: 30008
selector:
app: myweb
EOF
- master節點創建pv配置文件
mkdir -p mkdir -p /data/pv{1,2,3}
cat > /root/k8s_yaml/volume/pv1.yaml <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv1
labels:
type: nfs001
spec:
capacity:
storage: 10Gi # 不會去驗證是否真的有這么多空間
accessModes:
- ReadWriteMany # 允許多個pod讀寫,實現共享
persistentVolumeReclaimPolicy: Recycle # 回收策略:回收
nfs:
path: "/data/pv1"
server: 10.0.0.11
readOnly: false
EOF
cat > /root/k8s_yaml/volume/pv2.yaml <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv2
labels:
type: nfs001
spec:
capacity:
storage: 20Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Recycle
nfs:
path: "/data/pv2"
server: 10.0.0.11
readOnly: false
EOF
cat > /root/k8s_yaml/volume/pv3.yaml <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv3
labels:
type: ssd
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Recycle
nfs:
path: "/data/pv3"
server: 10.0.0.11
readOnly: false
EOF
回收策略:
kubectl explain persistentvolumes.spec.persistentVolumeReclaimPolicy
Retain(保留):手動回收pv。默認
Recycle(回收):基本擦除pv( rm -rf /thevolume/* )
Delete(刪除):關聯的存儲資產(例如 AWS EBS、GCE PD、Azure Disk 和 OpenStack Cinder 卷) 將被刪除
當前,只有 NFS 和 HostPath 支持回收策略。AWS EBS、GCE PD、Azure Disk 和 Cinder 卷支持刪除策略
- master節點創建pv資源
kubectl create namespace tomcat
kubectl create -f .
- master節點查看pv資源
kubectl get pv
pv卷狀態:
- Available(可用):一塊空閑資源還沒有被任何聲明綁定
- Bound(已綁定):卷已經被聲明綁定
- Released(已釋放):聲明被刪除,但是資源還未被集群重新聲明
- Failed(失敗):該卷的自動回收失敗 命令行會顯示綁定到 PV 的 PVC 的名稱
- master節點創建pvc配置文件
cat > /root/k8s_yaml/volume/mysql_pvc.yaml <<EOF
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
namespace: tomcat
name: tomcat-mysql
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 30Gi
EOF
- master節點創建pvc資源
kubectl create -f mysql_pvc.yaml
- master節點查看pv和pvc資源
kubectl get pv
kubectl get pvc -n tomcat
- master節點創建Deployment資源:pod模板里使用volume
cat > /root/k8s_yaml/volume/mysql-rc.yml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
namespace: tomcat
name: mysql
spec:
replicas: 1
selector:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
nodeName: 10.0.0.12
volumes:
- name: mysql
persistentVolumeClaim:
claimName: tomcat-mysql
containers:
- name: wp-mysql
image: 10.0.0.11:5000/mysql:5.7
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3306
volumeMounts:
- mountPath: /var/lib/mysql
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: '123456'
EOF
- master節點創建pvc資源
kubectl create -f mysql-rc.yml
- master節點驗證pv和pvc資源的使用
kubectl get pv
kubectl get pod -n tomcat
kubectl describe pod -n tomcat mysql-k90jm | grep -i persistentVolumeClaim
kubectl describe pod -n tomcat mysql-k90jm | grep -i tomcat-mysql
回收pv資源
- master節點刪除tomcat命名空間
kubectl delete namespace tomcat
- master節點查看pv處於回收狀態,會創建一個pod用來回收(鏡像在Google倉庫)
kubectl get pv
kubectl get pod
- master節點修改鏡像地址為阿里雲源
kubectl edit pod recycler-for-pv3
image: registry.aliyuncs.com/google_containers/busybox:latest
- master節點查看pod正常運行
kubectl get pod
- master節點查看pv回收完畢,處於正常狀態
kubectl get pv
標簽選擇器(優先)
- master節點創建pv配置文件
cat > /root/k8s_yaml/volume/pv4.yaml <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv4
labels:
type: sata
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Recycle
nfs:
path: "/data/pv4"
server: 10.0.0.11
readOnly: false
EOF
- master節點創建pv資源
kubectl create -f pv4.yaml
- master節點查看pv資源的標簽
kubectl get pv --show-labels
- master節點創建pvc配置文件:使用標簽選擇器
cat > /root/k8s_yaml/volume/mysql_pvc2.yaml <<EOF
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: tomcat-mysql
spec:
selector:
matchLabels:
type: ssd
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
EOF
- master節點創建pvc資源
kubectl create -f mysql_pvc2.yaml
- master節點驗證pv資源優先使用標簽選擇器的指定
kubectl get pv --show-labels
Ceph
Storage:
-
存儲硬件:nas,san
-
存儲軟件:nfs,lvm
Storage方式
- 塊存儲:提供硬盤,lvm,cinder
- 文件存儲:提供目錄,nfs(單機存儲),glusterfs(分布式存儲)
- 對象存儲:提供接口,fastdfs,Swift,ceph(分布式存儲)
存儲方式 | 技術實現 | 優勢 | 劣勢 | 代表作 |
---|---|---|---|---|
塊存儲 | 裸盤上划分邏輯卷,邏輯卷格式化成任意文件系統 | 支持多種文件系統,傳輸速度快,提供硬件容錯機制 | 無法實現網絡共享 | FC-SAN,iSCSI |
文件存儲 | 在格式化的磁盤上存儲文件 | 提供網絡共享 | 網絡傳輸速度制約讀寫速度,分層目錄結構限制可擴展性 | NFS,FAT,EXT3 |
對象存儲 | 以靈活可定制的對象為存儲單元,元數據服務器提供快速並發尋址 | 讀寫速度較快的同時支持網絡共享,對象靈活定義 | 管理軟件的購買、使用和運維成本高 | Swift |
塊存儲
典型設備: 磁盤陣列,硬盤
塊存儲主要是將裸磁盤空間整個映射給主機使用的。
通過划邏輯盤、做Raid、或者LVM(邏輯卷)等種種方式邏輯划分出N個邏輯的硬盤。
接着塊存儲會采用映射的方式將這幾個邏輯盤映射給主機,操作系統還需要對掛載的裸硬盤進行分區、格式化后,才能使用,與平常主機內置硬盤的方式完全無異。
優點:
-
通過了Raid與LVM等手段,對數據提供了保護。
-
將多塊廉價的硬盤組合起來,成為一個大容量的邏輯盤對外提供服務,提高了容量。
-
可以並行寫入,提升讀寫效率。
-
很多時候塊存儲采用SAN架構組網,傳輸速率以及封裝協議的原因,使得傳輸速度與讀寫速率得到提升。
缺點:
-
采用SAN架構組網時,需要額外為主機購買光纖通道卡,還要買光纖交換機,成本高。
-
主機之間的數據無法共享。不利於不同操作系統主機間的數據共享。
文件存儲
典型設備:FTP、NFS服務器
為了克服塊存儲中文件服務共享的問題,所以有了文件存儲。
主機A可以直接對文件存儲進行文件的上傳下載,與塊存儲不同,主機A是不需要再對文件存儲進行格式化的,因為文件管理功能已經由文件存儲自己搞定了。
優點:
-
造價低:隨便一台機器,普通以太網就可以,不需要SAN網絡。
-
方便文件共享:針對塊存儲中文件無法共享問題,使用文件存儲,第三方進行中轉。
缺點:
- 讀寫速率低,傳輸速率慢:以太網,上傳下載速度較慢;另外所有讀寫都要1台服務器里面的硬盤來承擔,相比起磁盤陣列動不動就幾十上百塊硬盤同時讀寫,速率慢了許多。
對象存儲
典型設備:內置大容量硬盤的分布式服務器
對象存儲最常用的方案,就是多台服務器內置大容量硬盤,再裝上對象存儲軟件,然后搞幾台服務器作為管理節點,安裝上對象存儲管理軟件。管理節點可以管理其他服務器對外提供讀寫訪問功能。
塊存儲讀寫快,不利於共享,文件存儲讀寫慢,利於共享。能否搞一個讀寫快,利於共享的出來呢?於是有了對象存儲。對象存儲結合了塊存儲與文件存儲的優點。
對象存儲中,OSD(Object-based Storage Device)是對象存儲設備,MDS(Metadata Server)是元數據服務器。
對象存儲的原理
首先,一個文件包含了屬性(術語叫metadata,元數據,例如該文件的大小、修改時間、存儲路徑等)以及內容(以下簡稱數據)。
以往像FAT32這種文件系統,是直接將一份文件的數據與metadata一起存儲的,存儲過程先將文件按照文件系統的最小塊大小來打散(如4M的文件,假設文件系統要求一個塊4K,那么就將文件打散成1000個小塊),再寫進硬盤里面,過程中沒有區分數據/metadata的。而每個塊最后會告知你下一個要讀取的塊的地址,然后一直這樣順序地按圖索驥,最后完成整份文件的所有塊的讀取。
對象存儲將元數據獨立出來,控制節點叫元數據服務器(服務器+對象存儲管理軟件),里面主要負責存儲對象的屬性(主要是對象的數據被打散存放到了那幾台分布式服務器中的信息),而其他負責存儲數據的分布式服務器叫做OSD,主要負責存儲文件的數據部分。當用戶訪問對象,會先訪問元數據服務器,元數據服務器只負責反饋對象存儲在那些OSD,假設反饋文件A存儲在B、C、D三台OSD,那么用戶就會再次直接訪問3台OSD服務器去讀取數據。
這時候由於是3台OSD同時對外傳輸數據,所以傳輸的速度就加快了。當OSD服務器數量越多,這種讀寫速度的提升就越大,通過這種方式,實現了讀寫快的目的。
另一方面,對象存儲軟件是有專門的文件系統的,所以OSD對象又相當於文件服務器,那么就不存在文件共享方面的困難了,也就解決了文件共享方面的問題。
總結
-
塊存儲可以認為是裸盤,最多包一層邏輯卷(LVM);常見的DAS、FC-SAN、IP-SAN都是塊存儲,塊存儲最明顯的特征就是不能被操作系統直接讀寫,需要格式化為指定的文件系統(Ext3、Ext4、NTFS)后才可以訪問。優點:讀寫快(帶寬&IOPS);缺點:因為太底層了,不利於擴展。
-
文件存儲:指的是在文件系統上的存儲,也就是主機操作系統中的文件系統。
-
對象存儲,對象存儲肯定是分布式存儲,但分布式存儲可能是分布式文件系統,不一定是對象存儲;常見的對象存儲開源實現有 Ceph 的RADOS、openstack的swift、AWS s3等,常見分布式文件系統,lustre、glusterfs、HDFS等;對象存儲和分布式文件系統的表面區別:對象存儲支持的訪問接口基本都是restful接口、而分布式文件系統提供的POSIX兼容的文件操作接口;
分布式文件系統和對象存儲最本質的區別:
分布式文件系統文件組織方式為目錄樹、對象存儲采用的則是扁平的組織方式;對象存儲不支持隨機讀取和寫入,put和get操作都是針對的整個文件。
Ceph 簡介
Ceph 獨一無二地在一個統一的系統中同時提供了對象、塊、和文件存儲功能。
它可靠性高、管理簡單,並且是開源軟件。 Ceph 的強大可以改變您公司的 IT 基礎架構和海量數據管理能力。
Ceph 可提供極大的伸縮性——供成千用戶訪問 PB 乃至 EB 級的數據。 Ceph 節點以普通硬件和智能守護進程作為支撐點, Ceph 存儲集群組織起了大量節點,它們之間靠相互通訊來復制數據、並動態地重分布數據。
CEPH 對象存儲
- REST 風格的接口
- 與 S3 和 Swift 兼容的 API
- S3 風格的子域
- 統一的 S3/Swift 命名空間
- 用戶管理
- 利用率跟蹤
- 條帶化對象
- 雲解決方案集成
- 多站點部署
- 災難恢復
CEPH 塊設備
- 瘦接口支持
- 映像尺寸最大 16EB
- 條帶化可定制
- 內存緩存
- 快照
- 寫時復制克隆
- 支持內核級驅動
- 支持 KVM 和 libvirt
- 可作為雲解決方案的后端
- 增量備份
CEPH 文件系統
- 與 POSIX 兼容的語義
- 元數據獨立於數據
- 動態重均衡
- 子目錄快照
- 可配置的條帶化
- 有內核驅動支持
- 有用戶空間驅動支持
- 可作為 NFS/CIFS 部署
- 可用於 Hadoop (取代 HDFS)
Ceph 特點
高性能
- 摒棄了傳統的集中式存儲元數據尋址的方案,采用CRUSH算法,數據分布均衡,並行度高。
- 考慮了容災域的隔離,能夠實現各類負載的副本放置規則,例如跨機房、機架感知等。
- 能夠支持上千個存儲節點的規模,支持TB到PB級的數據。
高可用性
- 副本數可以靈活控制。
- 支持故障域分隔,數據強一致性。
- 多種故障場景自動進行修復自愈。
- 沒有單點故障,自動管理。
高可擴展性
- 去中心化。
- 擴展靈活。
- 隨着節點增加而線性增長。
特性豐富
- 支持三種存儲接口:塊存儲、文件存儲、對象存儲。
- 支持自定義接口,支持多種語言驅動。
Ceph 體系結構
Ceph 基礎組件
構成 ceph 集群的基礎組件:OSD、Manager、MDS、Monitor。
-
OSD(ceph-osd)
:object storage daemon,對象存儲進程。ceph 管理物理硬盤時,引入了OSD概念,每一塊盤都會針對的運行一個OSD進程。換句話說,ceph 集群通過管理 OSD 來管理物理硬盤。OSD 一般功能為:存儲數據、維護數據副本、數據恢復、數據再平衡以及對ceph monitor組件提供相關監控信息。 -
Manager(ceph-mgr)
:用於收集ceph集群狀態、運行指標,比如存儲利用率、當前性能指標和系統負載。對外提供 ceph dashboard(ceph ui)和 resetful api。Manager組件開啟高可用時,至少2個。 -
Monitor(ceph-mon)
:維護集群的狀態,包含monitor組件信息,manger 組件信息,osd組件信息,mds組件信息,crush 算法信息。還負責ceph集群的身份驗證功能,client在連接ceph集群時通過此組件進行驗證。Monitor組件開啟高可用時,至少3個。 -
MDS(ceph-mds)
:Metadata server,元數據服務。為ceph 文件系統提供元數據服務(ceph 對象存儲和塊存儲不需要MDS)。為 posix 文件系統用戶提供性能良好的基礎命令(ls,find等)。
創建Ceph 存儲,至少需要以下服務:
- 一個Ceph Monitor
- 兩個OSD守護進程
Ceph IO算法流程
File
是用戶需要讀寫的文件。File->Object映射:
- ino (File的元數據,File的唯一id)。
- ono(File切分產生的某個object的序號,默認以4M切分一個塊大小)。
- oid(object id: ino + ono)。
Object
是RADOS需要的對象。Ceph指定一個靜態hash函數計算oid的值,將oid映射成一個近似均勻分布的偽隨機值,然后和mask按位相與,得到pgid。Object->PG映射:
- hash(oid) & mask-> pgid 。
- mask = PG總數m(m為2的整數冪)-1 。
PG(Placement Group)
用於對object的存儲進行組織和位置映射, (類似於redis cluster里面的slot的概念) 一個PG里面會有很多object。采用CRUSH算法,將pgid代入其中,然后得到一組OSD。PG->OSD映射:
- CRUSH(pgid)->(osd1,osd2,osd3) 。
OSD(Object Storage Device)
對象存儲設備:物理或邏輯存儲單元(如LUN)。有時,Ceph用戶使用術語“OSD”來指代Ceph OSD守護進程,盡管正確的術語是“Ceph OSD”。
Ceph IO偽代碼流程
locator = object_name
obj_hash = hash(locator)
pg = obj_hash % num_pg
osds_for_pg = crush(pg) # returns a list of osds
primary = osds_for_pg[0]
replicas = osds_for_pg[1:]
參考文檔:
部署Ceph集群
Ceph 集群架構
使用ceph-deploy部署nautilus版Ceph
- 3個Ceph Monitor
- 3個Ceph OSD
環境准備
主機名 | IP | 配置 |
---|---|---|
ceph01 | 10.0.0.14 | 1核1G,額外硬盤sdb單個文件50G |
ceph02 | 10.0.0.15 | 1核1G,額外硬盤sdb單個文件50G |
ceph03 | 10.0.0.16 | 1核1G,額外硬盤sdb單個文件50G |
-
關閉:
selinux
,firewalld
和NetworkManager
,postfix
(非必須) -
修改IP地址、主機名
hostnamectl set-hostname 主機名
sed -i 's/200/IP/g' /etc/sysconfig/network-scripts/ifcfg-eth0
- 添加hosts解析
cat >> /etc/hosts <<EOF
10.0.0.14 ceph01
10.0.0.15 ceph02
10.0.0.16 ceph03
EOF
- 如果熱添加硬盤,需要掃描發現硬盤
echo '- - -' >/sys/class/scsi_host/host0/scan
echo '- - -' >/sys/class/scsi_host/host1/scan
echo '- - -' >/sys/class/scsi_host/host2/scan
fdisk -l
- 准備yum源:Base epel ceph
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
cat > /etc/yum.repos.d/ceph.repo <<EOF
[ceph_x86]
name=ceph_x86
baseurl=https://mirrors.tuna.tsinghua.edu.cn/ceph/rpm-nautilus/el7/x86_64/
gpgcheck=0
[ceph_noarch]
name=ceph_noarch
baseurl=https://mirrors.tuna.tsinghua.edu.cn/ceph/rpm-nautilus/el7/noarch/
gpgcheck=0
EOF
如果你想保留rpm的話,可以開啟緩存。
vim /etc/yum.conf ... ... keepcache=1 # 開啟緩存 ... ...
打包緩存
mkdir ceph_rpm find /var/cache/yum -type f -name "*.rpm" | xargs mv -t ceph_rpm tar zcf ceph_rpm.tar.gz ceph_rpm
ceph-deploy節點
- 配置ssh密鑰免密登錄所有節點
ssh-keygen
ssh-copy-id root@ceph01
ssh-copy-id root@ceph02
ssh-copy-id root@ceph03
注意: 如果SSH不使用默認22端口時
cat > ~/.ssh/config <<EOF Port 12345 EOF
- 安裝ceph-deploy
yum install ceph-deploy -y
所有節點安裝
yum install ceph ceph-mon ceph-mgr ceph-radosgw.x86_64 ceph-mds.x86_64 ceph-osd.x86_64 -y
ceph-deploy使用其內置官網源安裝,非常慢!!!因此要提前裝好所需包。
ceph-deploy部署ceph集群
- ceph-deploy初始化集群配置文件
cd /root
mkdir ceph-deploy && cd ceph-deploy
ceph-deploy new --public-network 10.0.0.0/24 ceph01 ceph02 ceph03
默認
[--cluster-network CLUSTER_NETWORK]=[--public-network PUBLIC_NETWORK]
生產中建議
--cluster-network
使用萬兆帶寬網絡。
- 初始化集群:部署ceph-monitor並啟動
ceph-deploy mon create-initial
在各節點生成配置文件
/etc/ceph
- 創建管理員用戶:生成並推送管理員密鑰
ceph-deploy admin ceph01 ceph02 ceph03
- 查看集群狀態:mon存在
ceph -s
- 部署ceph-manager並啟動
ceph-deploy mgr create ceph01 ceph02 ceph03
- 查看集群狀態:mon和mgr存在
ceph -s
- 創建osd
ceph-deploy osd create ceph01 --data /dev/sdb
ceph-deploy osd create ceph02 --data /dev/sdb
ceph-deploy osd create ceph03 --data /dev/sdb
data:數據盤路徑
journal:日志盤路徑,日志盤(ssd)越快,ceph越快。尤其是小塊數據I/O,提速明顯。
- 查看集群狀態:mon和mgr和osd存在
ceph -s
如果狀態有健康警告如下:
[root@ceph01 ceph-deploy]# ceph -s cluster: id: a4f16e95-ba09-49f5-b0bf-ada31833a457 health: HEALTH_WARN clock skew detected on mon.ceph03 services: mon: 3 daemons, quorum ceph01,ceph02,ceph03 (age 23m) mgr: ceph01(active, since 53m), standbys: ceph02, ceph03 osd: 3 osds: 3 up (since 29m), 3 in (since 29m) data: pools: 0 pools, 0 pgs objects: 0 objects, 0 B usage: 3.0 GiB used, 147 GiB / 150 GiB avail pgs:
生產環境請使用ntp服務!
測試環境可以調整ceph配置中的[global]下時間偏差閾值:
cat >> /root/ceph-deploy/ceph.conf <<EOF mon clock drift allowed = 2 mon clock drift warn backoff = 30 EOF
向所有同步的mon節點推送配置文件,重啟mon服務:
ceph-deploy --overwrite-conf config push ceph0{1,2,3} systemctl restart ceph-mon.target
最后查看集群狀態:HEALTH_OK
- 查看monitors信息
ceph mon dump
ceph 資源配置
- 創建pool資源池
ceph osd pool create k8s 128 128
- 查看pool資源池
ceph osd pool ls
ceph osd pool stats k8s
- 調整pool資源池的ps數量
ceph osd pool set k8s pg_num 128
- 創建RBD塊設備
rbd create --size 1024 k8s/tomcat_mysql.img
- 查看RBD塊設備
rbd info k8s/tomcat_mysql.img
rbd info --pool k8s tomcat_mysql.img
rbd info --pool k8s --image tomcat_mysql.img
- 查看OSD節點數量
ceph osd pool get k8s size
增加OSD節點會自動進行數據整合,請在業務低谷期間增加,一台一台慢慢加。
- 查看RBD塊設備所有對象
rados -p k8s ls
rados -p k8s ls | grep rbd_data.ac74b202ed1a
rados -p k8s ls | grep rbd_data.ac74b202ed1a | wc -l
用多少,分多少。
- 樹狀顯示所有OSD
ceph osd tree
使用RBD塊設備
- 禁用高級特性
rbd feature disable k8s/tomcat_mysql.img object-map fast-diff deep-flatten
- 映射到實際設備
rbd map k8s/tomcat_mysql.img
關機映射失效,需要重新映射,數據不會丟失。
- 格式化
mkfs.xfs /dev/rbd0
- 掛載
mount /dev/rbd0 /mnt
- 卸載
umount /mnt
- 擴容
rbd resize --size 2048 k8s/tomcat_mysql.img
- 掛載
mount /dev/rbd0 /mnt
- 調整容量
xfs_growfs /dev/rbd0
- 掛載,查看
df -Th
Ceph 對接 k8s
Ceph RBD 對接 k8s :參考官方文檔
准備
所有k8s node節點安裝ceph-common
cat > /etc/yum.repos.d/ceph.repo <<EOF
[ceph_x86]
name=ceph_x86
baseurl=https://mirrors.tuna.tsinghua.edu.cn/ceph/rpm-nautilus/el7/x86_64/
gpgcheck=0
[ceph_noarch]
name=ceph_noarch
baseurl=https://mirrors.tuna.tsinghua.edu.cn/ceph/rpm-nautilus/el7/noarch/
gpgcheck=0
EOF
yum -y install ceph-common
ceph01
- 推送ceph用戶密鑰文件和配置文件給所有k8s node節點
scp -rp /etc/ceph/ceph.client.admin.keyring root@10.0.0.12:/etc/ceph/
scp -rp /etc/ceph/ceph.client.admin.keyring root@10.0.0.13:/etc/ceph/
scp -rp /etc/ceph/ceph.conf root@10.0.0.12:/etc/ceph/
scp -rp /etc/ceph/ceph.conf root@10.0.0.13:/etc/ceph/
- 獲取base64加密的ceph用戶key
grep key /etc/ceph/ceph.client.admin.keyring |awk '{printf "%s", $NF}'|base64
- 創建最小特性鏡像
rbd create --size 2048 --image-feature layering k8s/test.img
rbd ls -p k8s
k8s-master
- master節點編寫Secret資源yaml
mkdir -p /root/k8s_yaml/ceph && cd /root/k8s_yaml/ceph
cat > /root/k8s_yaml/ceph/ceph-secret.yaml <<EOF
apiVersion: v1
kind: Secret
metadata:
namespace: tomcat
name: ceph-secret
type: "kubernetes.io/rbd"
data:
key: QVFDYTV0RmY3ZVBlQWhBQU45aU1ONHFYdUhNNkRGZ2pCOTJMUFE9PQ==
EOF
- master節點創建Secret資源
kubectl create namespace tomcat
kubectl create -f ceph-secret.yaml
- master節點查看Secret資源
kubectl get secret -n tomcat
- master節點查看Secret資源配置文件
kubectl get secret -n tomcat ceph-secret -o yaml
能看到ceph用戶key,可以解密。
pod 對接ceph rbs存儲
查看解釋
kubectl explain pod.spec.volumes.rbd
- master節點編寫Pod資源yaml
cat > /root/k8s_yaml/ceph/test_ceph_pod.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
namespace: tomcat
name: rbd
spec:
containers:
- image: 10.0.0.11:5000/nginx:1.13
name: rbd-rw
volumeMounts:
- name: rbdpd
mountPath: /data
volumes:
- name: rbdpd
rbd:
monitors:
- '10.0.0.14:6789'
- '10.0.0.15:6789'
- '10.0.0.16:6789'
pool: k8s
image: test.img
fsType: ext4
user: admin
keyring: /etc/ceph/keyring
secretRef:
name: ceph-secret
EOF
- master節點創建Pod資源
kubectl create -f test_ceph_pod.yaml
- master節點查看Pod資源
kubectl get pod -o wide -n tomcat
- master節點進入容器,查看有/dev/rbd0設備,驗證對接成功
kubectl exec -n tomcat -it rbd /bin/bash
df -h
- node節點查看所有映射的rbd
rbd device ls
pv 對接ceph rbs存儲
- master節點編寫PV資源yaml
cat > /root/k8s_yaml/ceph/ceph_pv1.yaml <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
name: ceph01
labels:
type: rbd
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Recycle
rbd:
monitors:
- '10.0.0.14:6789'
- '10.0.0.15:6789'
- '10.0.0.16:6789'
pool: k8s
image: test2.img
fsType: xfs
user: admin
secretRef:
name: ceph-secret
EOF
注意:請使用xfs格式。
ext4格式默認創建一個lost+found目錄,導致mysql無法啟動。
需要手動刪除
df -Th|grep rbd rm -fr /var/lib/kubelet/plugins/kubernetes.io/rbd/rbd/k8s-image-test2.img/*
或者使用initContainer配置項,參考文檔
- ceph創建最小特性鏡像
rbd create --size 2048 --image-feature layering k8s/test2.img
rbd ls -p k8s
- master節點創建pv資源
kubectl create -f ceph_pv1.yaml
- master節點查看pv資源
kubectl get pv -o wide
- master節點編寫PVC資源yaml
cat > /root/k8s_yaml/ceph/ceph_pvc.yaml <<EOF
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: tomcat-rbd1
namespace: tomcat
spec:
selector:
matchLabels:
type: rbd
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
EOF
- master節點創建pvc資源
kubectl create -f ceph_pvc.yaml
- master節點查看pvc資源
kubectl get pvc -n tomcat -o wide
- master節點編寫Deployment資源yaml
cat > /root/k8s_yaml/ceph/mysql-deploy.yaml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
namespace: tomcat
name: mysql
spec:
replicas: 1
template:
metadata:
labels:
app: mysql
spec:
volumes:
- name: mysql
persistentVolumeClaim:
claimName: tomcat-rbd1
containers:
- name: wp-mysql
image: 10.0.0.11:5000/mysql:5.7
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3306
volumeMounts:
- mountPath: /var/lib/mysql
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: '123456'
EOF
- master節點創建Deployment資源
kubectl create -f mysql-deploy.yaml
- master節點查看Deployment資源
kubectl get pod -n tomcat -o wide
Jenkins實現k8s持續更新
環境准備
主機名 | IP | 服務 | 內存 |
---|---|---|---|
k8s-master | 10.0.0.11 | kube-apiserver 8080 | 1G |
k8s-node-1 | 10.0.0.12 | kube-apiserver 8080 | 1G |
k8s-node-2 | 10.0.0.13 | Jenkins(tomcat + jdk) 8080 | 2G |
- 代碼倉庫使用gitee托管
gitee倉庫准備
- 創建遠程倉庫
- Git 全局設置:
git config --global user.name "卜算子"
git config --global user.email "wuqi83417883@163.com"
- 新倉庫:
mkdir oldboy
cd oldboy
git init
touch README.md
git add README.md
git commit -m "first commit"
git remote add origin https://gitee.com/busuanzi/oldboy.git
git push -u origin master
- 已有倉庫:
cd /opt
git clone https://gitee.com/kangjie1209/monitor.git
git remote remove origin
git remote add origin https://gitee.com/busuanzi/oldboy.git
git push -u origin master
jenkins部署(k8s-node-2)
- 准備Jenkins + tomcat + jdk
cd /opt
for n in apache-tomcat-8.0.27.tar.gz jdk-8u102-linux-x64.rpm jenkin-data.tar.gz jenkins.war;do wget http://192.168.15.253/k8s_jenkins/$n ;done
- 二進制安裝jenkins
rpm -ivh jdk-8u102-linux-x64.rpm
mkdir /app -p
tar xf apache-tomcat-8.0.27.tar.gz -C /app
rm -fr /app/apache-tomcat-8.0.27/webapps/*
mv jenkins.war /app/apache-tomcat-8.0.27/webapps/ROOT.war
tar xf jenkin-data.tar.gz -C /root
/app/apache-tomcat-8.0.27/bin/startup.sh
netstat -lntup
jenkins構建測試
- 訪問jenkins:http://10.0.0.12:8080/,默認賬號密碼 admin:123456
- 創建一個新任務
- 配置jenkins拉取gitlab代碼憑據
- 構建Shell測試
- 立即構建
- 查看控制台輸出
構建docker鏡像
-
docker鏡像基礎包:nginx:1.13
-
編寫
dockerfile
和.dockerignore
並運行測試
cat > dockerfile <<EOF
FROM 10.0.0.11:5000/nginx:1.13
RUN rm -rf /usr/share/nginx/html/*
ADD . /usr/share/nginx/html
EOF
echo dockerfile > .dockerignore
docker build -t test:v1 .
docker run -d -p 80:80 test:v1
-
瀏覽器訪問:http://10.0.0.12/
-
上傳
dockerfile
和.dockerignore
到私有倉庫
git add .dockerignore dockerfile
git commit -m "add dockerfile"
git push -u origin master
- gitee添加標簽v1,修改首頁,添加標簽v2
- master節點手動發布
kubectl create namespace oldboy
kubectl run -n oldboy oldboy --image=10.0.0.11:5000/oldboy:v1 --replicas=2
kubectl expose -n oldboy deploy oldboy --type=NodePort --port=80 --target-port=80
kubectl get all -n oldboy
jenkins滾動更新
- 使用參數構建
- 修改Shell
docker build -t 10.0.0.11:5000/oldboy:$version .
docker push 10.0.0.11:5000/oldboy:$version
kubectl -s 10.0.0.11:8080 set image -n oldboy deploy oldboy oldboy=10.0.0.11:5000/oldboy:$version
- 執行測試
Build with Parameters --> 輸入版本 --> 開始構建
jenkins從gitee下載代碼,構建docker鏡像並上傳到私有倉庫,調用k8s滾動發布。
- 查看控制台輸出
- shell腳本
if [ -f /tmp/oldboy.lock ];then
docker build -t 10.0.0.11:5000/oldboy:v$version .
docker push 10.0.0.11:5000/oldboy:v$version
kubectl -s 10.0.0.11:8080 set image -n oldboy deploy oldboy oldboy=10.0.0.11:5000/oldboy:v$version
port=`kubectl -s 10.0.0.11:8080 get svc -n oldboy|grep -oP '(?<=80:)\d+'`
echo "你的項目地址訪問是http://10.0.0.13:$port"
echo "更新成功"
else
docker build -t 10.0.0.11:5000/oldboy:v$version .
docker push 10.0.0.11:5000/oldboy:v$version
kubectl -s 10.0.0.11:8080 create namespace oldboy
kubectl -s 10.0.0.11:8080 run oldboy -n oldboy --image=10.0.0.11:5000/oldboy:v$version --replicas=3 --record
kubectl -s 10.0.0.11:8080 expose -n oldboy deployment oldboy --port=80 --type=NodePort
port=`kubectl -s 10.0.0.11:8080 get svc -n oldboy|grep -oP '(?<=80:)\d+'`
echo "你的項目地址訪問是http://10.0.0.13:$port"
echo "發布成功"
touch /tmp/oldboy.lock
chattr +i /tmp/oldboy.lock
fi
jenkins一鍵回滾
另建一個工程,不需要拉代碼,僅僅需要指定版本參數和shell,參數化回滾:
kubectl -s 10.0.0.11:8080 set image -n oldboy deploy oldboy oldboy=10.0.0.11:5000/oldboy:$version
k8s高可用
架構
主機名 | IP | 服務 |
---|---|---|
k8s-master01 | 10.0.0.11 | api-server,controller-manager,scheduler,etcd,keepalived,flannel |
k8s-master02 | 10.0.0.12 | api-server,controller-manager,scheduler,etcd,keepalived,flannel |
k8s-node-1 | 10.0.0.13 | kubernetes-node,flannel |
etcd高可用集群
不能單機擴集群,首次使用請使用集群,集群是奇數個,競選。(虛擬機請還原快照)
- 所有節點安裝
yum install etcd -y
- 所有節點配置
#[Member] #ETCD_CORS="" ETCD_DATA_DIR="/var/lib/etcd/" #ETCD_WAL_DIR="" ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380" ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379" #ETCD_MAX_SNAPSHOTS="5" #ETCD_MAX_WALS="5" ETCD_NAME="node1" # 節點的名字 #ETCD_SNAPSHOT_COUNT="100000" #ETCD_HEARTBEAT_INTERVAL="100" #ETCD_ELECTION_TIMEOUT="1000" #ETCD_QUOTA_BACKEND_BYTES="0" #ETCD_MAX_REQUEST_BYTES="1572864" #ETCD_GRPC_KEEPALIVE_MIN_TIME="5s" #ETCD_GRPC_KEEPALIVE_INTERVAL="2h0m0s" #ETCD_GRPC_KEEPALIVE_TIMEOUT="20s" # #[Clustering] ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.0.0.11:2380" # 節點同步數據的地址 ETCD_ADVERTISE_CLIENT_URLS="http://10.0.0.11:2379" # 節點提供服務的地址 #ETCD_DISCOVERY="" #ETCD_DISCOVERY_FALLBACK="proxy" #ETCD_DISCOVERY_PROXY="" #ETCD_DISCOVERY_SRV="" ETCD_INITIAL_CLUSTER="node1=http://10.0.0.11:2380,node2=http://10.0.0.12:2380,node3=http://10.0.0.13:2380" # 初始化集群 ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" # 初始化集群令牌 ETCD_INITIAL_CLUSTER_STATE="new" # 初始化集群狀態
cat > /etc/etcd/etcd.conf <<EOF
#[Member]
#ETCD_CORS=""
ETCD_DATA_DIR="/var/lib/etcd/"
#ETCD_WAL_DIR=""
ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
#ETCD_MAX_SNAPSHOTS="5"
#ETCD_MAX_WALS="5"
ETCD_NAME="node1"
#ETCD_SNAPSHOT_COUNT="100000"
#ETCD_HEARTBEAT_INTERVAL="100"
#ETCD_ELECTION_TIMEOUT="1000"
#ETCD_QUOTA_BACKEND_BYTES="0"
#ETCD_MAX_REQUEST_BYTES="1572864"
#ETCD_GRPC_KEEPALIVE_MIN_TIME="5s"
#ETCD_GRPC_KEEPALIVE_INTERVAL="2h0m0s"
#ETCD_GRPC_KEEPALIVE_TIMEOUT="20s"
#
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.0.0.11:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://10.0.0.11:2379"
#ETCD_DISCOVERY=""
#ETCD_DISCOVERY_FALLBACK="proxy"
#ETCD_DISCOVERY_PROXY=""
#ETCD_DISCOVERY_SRV=""
ETCD_INITIAL_CLUSTER="node1=http://10.0.0.11:2380,node2=http://10.0.0.12:2380,node3=http://10.0.0.13:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
#ETCD_STRICT_RECONFIG_CHECK="true"
#ETCD_ENABLE_V2="true"
#
#[Proxy]
#ETCD_PROXY="off"
#ETCD_PROXY_FAILURE_WAIT="5000"
#ETCD_PROXY_REFRESH_INTERVAL="30000"
#ETCD_PROXY_DIAL_TIMEOUT="1000"
#ETCD_PROXY_WRITE_TIMEOUT="5000"
#ETCD_PROXY_READ_TIMEOUT="0"
#
#[Security]
#ETCD_CERT_FILE=""
#ETCD_KEY_FILE=""
#ETCD_CLIENT_CERT_AUTH="false"
#ETCD_TRUSTED_CA_FILE=""
#ETCD_AUTO_TLS="false"
#ETCD_PEER_CERT_FILE=""
#ETCD_PEER_KEY_FILE=""
#ETCD_PEER_CLIENT_CERT_AUTH="false"
#ETCD_PEER_TRUSTED_CA_FILE=""
#ETCD_PEER_AUTO_TLS="false"
#
#[Logging]
#ETCD_DEBUG="false"
#ETCD_LOG_PACKAGE_LEVELS=""
#ETCD_LOG_OUTPUT="default"
#
#[Unsafe]
#ETCD_FORCE_NEW_CLUSTER="false"
#
#[Version]
#ETCD_VERSION="false"
#ETCD_AUTO_COMPACTION_RETENTION="0"
#
#[Profiling]
#ETCD_ENABLE_PPROF="false"
#ETCD_METRICS="basic"
#
#[Auth]
#ETCD_AUTH_TOKEN="simple"
EOF
# node2
sed -i "9c ETCD_NAME=\"node2\"" /etc/etcd/etcd.conf
sed -i "20c ETCD_INITIAL_ADVERTISE_PEER_URLS=\"http://10.0.0.12:2380\"" /etc/etcd/etcd.conf
sed -i "21c ETCD_ADVERTISE_CLIENT_URLS=\"http://10.0.0.12:2379\"" /etc/etcd/etcd.conf
# node3
sed -i "9c ETCD_NAME=\"node3\"" /etc/etcd/etcd.conf
sed -i "20c ETCD_INITIAL_ADVERTISE_PEER_URLS=\"http://10.0.0.13:2380\"" /etc/etcd/etcd.conf
sed -i "21c ETCD_ADVERTISE_CLIENT_URLS=\"http://10.0.0.13:2379\"" /etc/etcd/etcd.conf
- 所有節點同時啟動,並加入開機自啟
systemctl enable etcd
systemctl start etcd
- 檢查集群健康狀態和成員列表
etcdctl cluster-health
etcdctl member list
flannel配置
- 修改配置文件
sed -i "4c FLANNEL_ETCD_ENDPOINTS="http://10.0.0.11:2379,http://10.0.0.12:2379,http://10.0.0.13:2379"" /etc/sysconfig/flanneld
- 創建key
etcdctl mk /atomic.io/network/config '{ "Network": "172.18.0.0/16","Backend": {"Type": "vxlan"} }'
- 啟動並加入開機自啟
systemctl start flanneld
systemctl enable flanneld
systemctl restart docker
- 檢查網卡
ip a
master節點
master01和master02部署api-server,controller-manager,scheduler
- 安裝
yum install kubernetes-master -y
- 配置apiserver
sed -i "8c KUBE_API_ADDRESS=\"--insecure-bind-address=0.0.0.0\"" /etc/kubernetes/apiserver
sed -i "11c KUBE_API_PORT=\"--port=8080\"" /etc/kubernetes/apiserver
sed -i "14c KUBELET_PORT=\"--kubelet-port=10250\"" /etc/kubernetes/apiserver
sed -i "17c KUBE_ETCD_SERVERS=\"--etcd-servers=http://10.0.0.11:2379,http://10.0.0.12:2379,http://10.0.0.13:2379\"" /etc/kubernetes/apiserver
sed -i "s/ServiceAccount,//" /etc/kubernetes/apiserver
- 配置config
sed -i "22c KUBE_MASTER=\"--master=http://127.0.0.1:8080\"" /etc/kubernetes/config
- 啟動並加入開機啟動
systemctl enable kube-apiserver.service
systemctl enable kube-controller-manager.service
systemctl enable kube-scheduler.service
systemctl start kube-apiserver.service
systemctl start kube-controller-manager.service
systemctl start kube-scheduler.service
- 檢查服務是否安裝正常
kubectl get componentstatus
Keepalived配置
在master01和master02安裝keepalived。
- 安裝
yum install keepalived -y
- master01配置
cat > /etc/keepalived/keepalived.conf <<EOF
! Configuration File for keepalived
global_defs {
router_id LVS_DEVEL_11
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.0.0.10
}
}
EOF
- master02配置
cat > /etc/keepalived/keepalived.conf <<EOF
! Configuration File for keepalived
global_defs {
router_id LVS_DEVEL_12
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 80
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.0.0.10
}
}
EOF
- 啟動並加入開機自啟
systemctl enable keepalived
systemctl start keepalived
node節點
所有node節點的kubelet,kube-proxy指向api-server的vip。
- 安裝:見k8s集群yum安裝
- 配置
sed -i "22c KUBE_MASTER=\"--master=http://10.0.0.10:8080\"" /etc/kubernetes/config
sed -i "14c KUBELET_API_SERVER=\"--api-servers=http://10.0.0.10:8080\"" /etc/kubernetes/kubelet
- 重啟生效
systemctl restart kubelet.service kube-proxy.service