更新了集群環境的搭建,與單機實驗環境的搭建
搭建k8s單點實驗環境
由於在國內網絡問題,我們無法很好的使用minikube進行部署k8s實驗環境,所以可以使用阿里提供的minikube進行搭建。除了minikube,也可以使用kubeasz進行部署。
下面我基於kubeaze給出部署方法,部署方法都參照https://github.com/easzlab/kubeasz,其中附上我的踩坑經驗。
1.基礎系統配置
- 准備一台虛機配置內存2G/硬盤30G以上
- 最小化安裝
Ubuntu 16.04 server
或者CentOS 7 Minimal
- 配置基礎網絡、更新源、SSH登錄等
注意: 確保在干凈的系統上開始安裝,不能使用曾經裝過kubeadm或其他k8s發行版的環境
2.下載文件
- 下載工具腳本easzup,舉例使用kubeasz版本2.2.1
export release=2.2.1
curl -C- -fLO --retry 3 https://github.com/easzlab/kubeasz/releases/download/${release}/easzup
chmod +x ./easzup
- 使用工具腳本下載
默認下載最新推薦k8s/docker等版本,使用命令./easzup
查看工具腳本的幫助信息
設置docker源:
{
"registry-mirrors": [
"https://eig40bb2.mirror.aliyuncs.com",
"https://docker.mirrors.ustc.edu.cn",
"http://hub-mirror.c.163.com",
"https://reg-mirror.qiniu.com"
],
"max-concurrent-downloads": 10,
"log-driver": "json-file",
"log-level": "warn",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"data-root": "/var/lib/docker"
}
添加完之后刷新一下配置:
systemctl daemon-reload
systemctl restart docker
# 舉例使用 k8s 版本 v1.18.2,docker 19.03.5
./easzup -D -d 19.03.5 -k v1.18.2
- 可選下載離線系統包 (適用於無法使用yum/apt倉庫情形)
./easzup -P
上述腳本運行成功后,所有文件(kubeasz代碼、二進制、離線鏡像)均已整理好放入目錄/etc/ansible
/etc/ansible
包含 kubeasz 版本為 ${release} 的發布代碼/etc/ansible/bin
包含 k8s/etcd/docker/cni 等二進制文件/etc/ansible/down
包含集群安裝時需要的離線容器鏡像/etc/ansible/down/packages
包含集群安裝時需要的系統基礎軟件
3.安裝集群
- 容器化運行 kubeasz,詳見文檔
./easzup -S
- 使用默認配置安裝 aio 集群
docker exec -it kubeasz easzctl start-aio
4.驗證安裝
如果提示kubectl: command not found,退出重新ssh登錄一下,環境變量生效即可
$ kubectl version # 驗證集群版本
$ kubectl get node # 驗證節點就緒 (Ready) 狀態
$ kubectl get pod -A # 驗證集群pod狀態,默認已安裝網絡插件、coredns、metrics-server等
$ kubectl get svc -A # 驗證集群服務狀態
搭建k8s集群環境
我們打算搭建一個這樣的三節點的集群:
1. 准備服務器
首先3台虛機,搭建一個多主高可用集群。
- 推薦內存2G/硬盤30G以上
- 最小化安裝
Ubuntu 16.04 server
或者CentOS 7 Minimal
- 配置基礎網絡、更新源、SSH登錄等
2. 在每個節點安裝ansible依賴工具
CentOS 7 請執行以下腳本:
# 文檔中腳本默認均以root用戶執行
yum update
# 安裝python
yum install python -y
安裝pip的時候先安裝
yum -y install epel-release
安裝pip
yum install git python-pip -y
pip 安裝 ansible
# CentOS 7
yum install git python-pip -y
# pip安裝ansible(國內如果安裝太慢可以直接用pip阿里雲加速)
pip install pip --upgrade -i https://mirrors.aliyun.com/pypi/simple/
pip install ansible==2.6.18 netaddr==0.7.19 -i https://mirrors.aliyun.com/pypi/simple/
在ansible控制端配置免密碼登錄
# 更安全 Ed25519 算法
ssh-keygen -t ed25519 -N '' -f ~/.ssh/id_ed25519
# 或者傳統 RSA 算法
ssh-keygen -t rsa -b 2048 -N '' -f ~/.ssh/id_rsa
ssh-copy-id 192.168.13.131
ssh-copy-id 192.168.13.132
ssh-copy-id 192.168.13.133
如果這一步不設置,那么在部署的時候無法訪問到相應的節點會報如下錯:
192.168.13.130 | UNREACHABLE! => {
"changed": false,
"msg": "SSH Error: data could not be sent to remote host \"192.168.13.130\". Make sure this host can be reached over ssh",
"unreachable": true
}
3.在ansible控制端編排k8s安裝
- 4.0 下載項目源碼
- 4.1 下載二進制文件
- 4.2 下載離線docker鏡像
推薦使用 easzup 腳本下載 4.0/4.1/4.2 所需文件;運行成功后,所有文件(kubeasz代碼、二進制、離線鏡像)均已整理好放入目錄/etc/ansible
# 下載工具腳本easzup,舉例使用kubeasz版本2.0.2
export release=2.0.2
curl -C- -fLO --retry 3 https://github.com/easzlab/kubeasz/releases/download/${release}/easzup
chmod +x ./easzup
# 使用工具腳本下載
./easzup -D
4.配置集群參數
-
必要配置:
cd /etc/ansible && cp example/hosts.multi-node hosts
, 然后實際情況修改此hosts文件根據我們上圖的介紹,我們將hosts改成如下:
# 'etcd' cluster should have odd member(s) (1,3,5,...) # variable 'NODE_NAME' is the distinct name of a member in 'etcd' cluster [etcd] 192.168.13.131 NODE_NAME=etcd1 192.168.13.132 NODE_NAME=etcd2 192.168.13.133 NODE_NAME=etcd3 # master node(s) [kube-master] 192.168.13.131 # work node(s) [kube-node] 192.168.13.131 192.168.13.132 192.168.13.133 ...
只改如上配置,其他的可不動。
-
驗證ansible 安裝:
ansible all -m ping
正常能看到節點返回 SUCCESS -
開始安裝 如果你對集群安裝流程不熟悉,請閱讀項目首頁 安裝步驟 講解后分步安裝,並對 每步都進行驗證
# 分步安裝 ansible-playbook 01.prepare.yml ansible-playbook 02.etcd.yml ansible-playbook 03.docker.yml ansible-playbook 04.kube-master.yml ansible-playbook 05.kube-node.yml ansible-playbook 06.network.yml ansible-playbook 07.cluster-addon.yml
-
如果不想分步安裝,那么可以一步安裝:
# 一步安裝 #ansible-playbook 90.setup.yml
在k8s中運行一個程序
編寫YAML文件
Kubernetes 跟 Docker 等很多項目最大的不同,就在於它不推薦你使用命令行的方式直接運行容器,而是希望你用 YAML 文件的方式,然后用這樣一句指令把它運行起來:
$ kubectl create -f 我的配置文件
yaml如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
Kind 字段,指定了這個 API 對象的類型(Type),是一個 Deployment。Deployment,是一個定義多副本應用的對象,Deployment 還負責在 Pod 定義發生變化時,對每個副本進行滾動更新。
像這樣使用一種 API 對象(Deployment)管理另一種 API 對象(Pod)的方法,在Kubernetes 中,叫作“控制器”模式(controller pattern)。
一個 Kubernetes 的 API 對象的定義,大多可以分為 Metadata 和 Spec 兩個部分。前者存放的是這個對象的元數據,對所有 API 對象來說,這一部分的字段和格式基本上是一樣的;而后者存放的,則是屬於這個對象獨有的定義,用來描述它所要表達的功能。
spec.replicas是2,表示定義的 Pod 副本個數。
spec.template作用是描述了我想要創建的 Pod 的細節。spec.containers.image表示容器鏡像是nginx:1.7.9,containerPort表示監聽的端口是80。
Labels 字段可以用來過濾控制對象,在上面這個 YAML 文件中,Deployment 會把所有正在運行的、攜帶“app: nginx”標簽的 Pod 識別為被管理的對象,並確保這些 Pod 的總數嚴格等於兩個。
spec.selector.matchLabels是用來定義過濾規則的,一般稱之為:Label Selector。
創建一個pod
在理解完上面的知識后,我們可以運行起來:
$ kubectl create -f nginx-deployment.yaml
然后,通過 kubectl get 命令檢查這個 YAML 運行起來的狀態是不是與我們預期的一致:
$ kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
nginx-deployment-67594d6bf6-9gdvr 1/1 Running 0 10m
nginx-deployment-67594d6bf6-v6j7w 1/1 Running 0 10m
-l表示獲取所有匹配 app: nginx 標簽的 Pod。
注意:在命令行中,所有 key-value 格式的參數,都使用“=”而非“:”表示。
此外,我們還可以使用kubectl describe 命令,查看一個 API 對象的細節:
$ kubectl describe pod nginx-deployment-67594d6bf6-9gdvr
Name: nginx-deployment-67594d6bf6-9gdvr
Namespace: default
Priority: 0
PriorityClassName: <none>
Node: node-1/10.168.0.3
Start Time: Thu, 16 Aug 2018 08:48:42 +0000
Labels: app=nginx
pod-template-hash=2315082692
Annotations: <none>
Status: Running
IP: 10.32.0.23
Controlled By: ReplicaSet/nginx-deployment-67594d6bf6
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 1m default-scheduler Successfully assigned default/nginx-deployment-67594d6bf6-9gdvr to node-1
Normal Pulling 25s kubelet, node-1 pulling image "nginx:1.7.9"
Normal Pulled 17s kubelet, node-1 Successfully pulled image "nginx:1.7.9"
Normal Created 17s kubelet, node-1 Created container
Normal Started 17s kubelet, node-1 Started container
上面詳細信息中,在 Kubernetes 執行的過程中,對 API 對象的所有重要操作都會記錄到Events里面。
為pod進行版本升級
如果我們要對這個 Nginx 服務進行升級,把它的鏡像版本從 1.7.9 升級為 1.8,那么我們可以修改一下YAML文件:
...
spec:
containers:
- name: nginx
image: nginx:1.8 #這里被從1.7.9修改為1.8
ports:
- containerPort: 80
然后使用kubectl replace 指令來完成k8s集群中更新:
$ kubectl replace -f nginx-deployment.yaml
我們也可以使用kubectl apply 命令,來統一進行 Kubernetes 對象的創建和更新操作,具體做法如下所示:
$ kubectl apply -f nginx-deployment.yaml
# 修改nginx-deployment.yaml的內容
$ kubectl apply -f nginx-deployment.yaml
使用kubectl apply 命令是 Kubernetes“聲明式 API”所推薦的使用方法。也就是說,作為用戶,你不必關心當前的操作是創建,還是更新,你執行的命令始終是 kubectl apply,而 Kubernetes 則會根據 YAML 文件的內容變化,自動進行具體的處理。
聲明一個 Volume
在 Kubernetes 中,Volume 是屬於 Pod 對象的一部分。所以,我們就需要修改這個 YAML 文件里的 template.spec 字段,如下所示:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.8
ports:
- containerPort: 80
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: nginx-vol
volumes:
- name: nginx-vol
emptyDir: {}
我們在上面定義了volumes字段,名字叫做nginx-vol,類型是 emptyDir。Pod 中的容器,使用的是 volumeMounts 字段來聲明自己要掛載哪個 Volume,並通過 mountPath 字段來定義容器內的 Volume 目錄,比如:/usr/share/nginx/html。
emptyDir表示,Kubernetes 也會在宿主機上創建一個臨時目錄,這個目錄將來就會被綁定掛載到容器所聲明的 Volume 目錄上。
然后使用kubectl apply 指令,更新這個Deployment,然后使用 kubectl describe 查看一下最新的 Pod:
...
Containers:
nginx:
Container ID: docker://07b4f89248791c2aa47787e3da3cc94b48576cd173018356a6ec8db2b6041343
Image: nginx:1.8
...
Environment: <none>
Mounts:
/usr/share/nginx/html from nginx-vol (rw)
...
Volumes:
nginx-vol:
Type: EmptyDir (a temporary directory that shares a pod's lifetime)
最后,你還可以使用 kubectl exec 指令,進入到這個 Pod 當中(即容器的 Namespace 中)查看這個 Volume 目錄:
$ kubectl exec -it nginx-deployment-5c678cfb6d-lg9lw -- /bin/bash
# ls /usr/share/nginx/html
如果要刪除這個Nginx Deployment 的話,直接執行:
$ kubectl delete -f nginx-deployment.yaml
總結
- 與k8s進行交互盡量選擇yaml文件交互;
- 我們可以使用kubectl create 命令創建一個pod;
- 想要獲取目前pod的狀態可以使用kubectl get pods命令;
- 使用kubectl describe pod 可以查看某個pod的詳細信息;
- 如果想要對pod更新最好使用kubectl apply -f ,這樣可以做到更加無感的創建pod或更新;
- 我們可以使用Volumes來掛載卷;
- 使用kubectl delete -f可以刪除一個pod;