邁入Docker、Kubernetes容器世界的大門
本文通過簡單的示例,帶領初學者快速邁入Docker、Kubernetes(K8S)容器世界 的大門。假設,你已擁有一個K8S叢集,否則,可通過minikube或minishift快速搭建一實驗環境。
Docker
Docker與K8S
Docker本質上是一種虛擬化技術,類似於KVM、XEN、VMWARE,但其更輕量化,且將Docker部署在Linux環境時,其依賴於Linux容器技術(LXC)。Docker較傳統KVM等虛擬化技術的一個區別是無核心,即多個Docker虛擬機器共享宿主機核心,簡而言之,可把Docker看作是無核心的虛擬機器,每Docker虛擬機器有自己的軟體環境,相互獨立。
K8S與Docker之間的關係,如同Openstack之於KVM、VSphere之於VMWARE。K8S是容器叢集管理系統,底層容器虛擬化可使用Docker技術,應用人員無需與底層Docker節點直接打交道,通過K8S統籌管理即可。
Docker基礎
如下所示,執行docker run -it --name test-docker busybox /bin/sh
命令,觀察其輸出,可發現docker先在本地查詢名為busybox的映象(Image)1,若本地無映象,則從docker.io官方映象庫(Registry)下載映象後儲存到本地,接著以此映象構建一個名為test-docker的虛擬機器,其Docker官方術語命名為容器(Container)。
# docker run -it --name test-docker busybox /bin/sh
Unable to find image `busybox:latest` locally
Trying to pull repository docker.io/library/busybox ...
latest: Pulling from docker.io/library/busybox
f70adabe43c0: Pull complete
Digest: sha256:186694df7e479d2b8bf075d9e1b1d7a884c6de60470006d572350573bfa6dcd2
/ #
Docker較傳統KVM、VMware虛擬機器更輕量,如下所示,test-docker容器不會執行額外的系統與核心程式,其僅執行docker run命令提供的/bin/sh程式:
/ # ps -ef
PID USER TIME COMMAND
1 root 0:00 /bin/sh
7 root 0:00 ps -ef
如在Openstack中建立虛擬機器,首先需在Glance映象庫中儲存虛擬機器映象,而後才能選擇映象以建立虛擬機器。Docker同理,且官方提供一共享的映象倉庫(Registry),其中儲存了各式各樣的映象(Image)。如本例用busybox映象建立容器,其映象被拉(pull)到了本地,可執行如下命令檢查發現其僅1MB左右,相當輕量。
# docker images|grep busybox
docker.io/busybox latest 8ac48589692a 5 weeks ago 1.146 MB
通過本節,我們瞭解了3個Docker基本要素:映象倉庫(Registry)中儲存了映象(Image),而映象(Image)包含了程式執行所需的軟體環境,當部署容器(Container)時,映象(Image)通過網路被拉取到Doker主機(Node)。
Kubernetes
K8S是Google開源容器叢集管理系統,其源於Google內部管理系統Borg,以下將通過一個個簡單連貫的示例,帶領初學者熟悉K8S叢集。
Pod
K8S以Pod為最小單位來排程並管理Docker容器(Container),其中1個Pod可含多個容器,且相同Pod裡的容器共享本地網路,容器間可通過localhost地址互訪,即容器如同部署在相同的主機上,而以Pod為最小單元來排程則表明:Pod內的容器被排程到相同的Docker節點上。
如下所示,建立一名為myhttp的Pod,其包含一個使用httpd映象部署的容器,容器名為myhttp:
# cat > /tmp/myhttpd.pod <<EOF
apiVersion: v1
kind: Pod
metadata:
name: myhttp
labels:
app: myhttp
spec:
containers:
- name: myhttp
image: httpd
EOF
% kubectl create -f /tmp/myhttpd.pod
執行kubectl get pod
命令觀察Pod執行成功後,接著驗證容器能提供web服務:
# kubectl get pod
NAME READY STATUS RESTARTS AGE
myhttp 1/1 Running 0 1h
# kubectl describe pod myhttp|grep IP
IP: 10.129.0.232
# curl 10.129.0.232
<html><body><h1>It works!</h1></body></html>
Deployment
將應用直接以Pod形式部署很少見,主因是:Pod無法提供彈性伸縮,且節點故障時K8S無法將其排程到倖存節點上,缺少自愈能力。鑑於此,應用常使用“映象(Rc)/部署(Deployment)”部署,且在K8S新版本中,官方推薦用Deployment替代Rc部署無狀態(Stateless)應用。
執行kubectl delete pod myhttp
刪除pod後,換成以Deployment部署:
# cat > myhttp.yaml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
app: myhttp
name: myhttp
spec:
replicas: 1
selector:
matchLabels:
app: myhttp
template:
metadata:
labels:
app: myhttp
spec:
containers:
- image: httpd
name: myhttp
EOF
# kubectl create -f /tmp/myhttp.yaml
Deployment中的.spec.replicas表明部署多少個Pod,如本例當前僅含一Pod:
# kubectl get deploy,pod
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deploy/myhttp 1 1 1 1 2m
NAME READY STATUS RESTARTS AGE
po/myhttp-7bc6d8b87c-gzlkq 1/1 Running 0 2m
執行kubectl delete pod <pod_name>刪除Pod後,可發現deployment將自動重建pod,其將確保擁有.spec.replicas個pod數量,即意味著,當pod異常時,deployment具備自愈特性。
# kubectl delete pod myhttp-7bc6d8b87c-gzlkq # kubectl get pod -w
NAME READY STATUS RESTARTS AGE
myhttp-7bc6d8b87c-dhmtz 0/1 ContainerCreating 0 2s
myhttp-7bc6d8b87c-dhmtz 1/1 Running 0 8s
myhttp-7bc6d8b87c-gzlkq 1/1 Terminating 0 8m
當需伸縮或擴充套件應用時,若以Pod形式部署,則需刪除或建立Pod,而若使用Deployment部署,則我們僅需調整.spec.replicas,而後K8S映象控制器將自動調整Pod數量。如下所示,擴充套件http應用為2服務:
# kubectl scale deploy/myhttp --replicas=2 # kubectl get pod -w
NAME READY STATUS RESTARTS AGE
myhttp-7bc6d8b87c-cj4g8 0/1 ContainerCreating 0 3s
myhttp-7bc6d8b87c-zsbcc 1/1 Running 0 8m
myhttp-7bc6d8b87c-cj4g8 1/1 Running 0 18s
# kubectl get deploy
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
myhttp 2 2 2 2 21m
執行kubectl delete pod <pod_name>刪除Pod後,可發現Pod名(即容器主機名)及IP是隨機分配的,那麼,我們該如何訪問應用?
# kubectl get pod # kubectl describe pod myhttp-7bc6d8b87c-cj4g8|grep IP
IP: 10.129.3.28
Service
Service服務類似於傳統的F5、A10等硬體負載均衡,但其在K8S中通過軟體實現,且當伸縮應用時可實時跟蹤後端Server,無需人為調整。
內部訪問
我們將對上節部署的myhttp應用建立一個Service服務,但在此前,先建立一個Pod作為叢集內部客戶端以用於後續Service驗證。因下面驗證Svc將使用curl工具,而官方centos映象包含此工具,故用此映象建立Pod,且為保證Pod一直執行不退出,使用了command在前臺執行了無限迴圈命令。
# kubectl create -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: myclient
labels:
app: myclient
spec:
containers:
- name: myclient
image: centos
command: [`sh`,`-c`,`while true; do sleep 3600; done;`]
EOF
執行如下命令為myhttp應用建立一個myhttp-int的服務:
# kubectl expose deployment myhttp --port=8080 --target-port=80 --name=myhttp-int
service "myhttp-int" exposed
上面命令等價於使用下面的Yaml檔案手動建立Service:建立名為myhttp-int的服務,其8080埠指向後端服務的80埠,而後端服務是通過selector選擇label(標籤)為app:myhttp的Pod,觀察myhttp Deployment,可發現.spec.template.metadata.labels定義的標籤就是app:myhttp,故而,通過myhttp-int:8080即可訪問myhttp服務。
apiVersion: v1 kind: Service metadata: labels: app: myhttp name: myhttp-int spec: clusterIP: ports: - port: 8080 protocol: TCP targetPort: 80 selector: app: myhttp sessionAffinity: None
在測試容器中通過myhttp-int:8080訪問Service,可發現將負載均衡到後端的兩pod上:
# kubectl get pod
NAME READY STATUS RESTARTS AGE
myclient 1/1 Running 0 1h
myhttp-7bc6d8b87c-cj4g8 1/1 Running 0 1d
myhttp-7bc6d8b87c-zsbcc 1/1 Running 0 1d
# 重置web主頁,輸出每Pod名稱以便後續觀察 # kubectl exec myhttp-7bc6d8b87c-cj4g8 -it -- sh -c "hostname>htdocs/index.html" # kubectl exec myhttp-7bc6d8b87c-zsbcc -it -- sh -c "hostname>htdocs/index.html" # kubectl exec -it myclient -- curl myhttp-int:8080
myhttp-7bc6d8b87c-cj4g8
# kubectl exec -it myclient -- curl myhttp-int:8080
myhttp-7bc6d8b87c-zsbcc
當伸縮Pod時,我們可通過如下命令觀察到Service將動態跟蹤後端(Endpoints)服務:
# kubectl get endpoints myhttp-int
NAME ENDPOINTS AGE
myhttp-int 10.129.0.237:80,10.129.3.28:80 1h
# kubectl scale deploy myhttp --replicas=3 # kubectl get endpoints myhttp-int
NAME ENDPOINTS AGE
myhttp-int 10.129.0.237:80,10.129.3.28:80,10.131.0.194:80 1h
外部訪問
若應用需向K8S叢集外提供服務,則可建立型別為NodePort的Service,此時K8S叢集上所有節點均監聽nodePort指定的埠,故外部應用可通過叢集中任一節點訪問叢集內部提供的服務。
# kubectl create -f - <<EOF
apiVersion: v1
kind: Service
metadata:
labels:
app: myhttp
name: myhttp-pub
spec:
type: NodePort
ports:
- port: 8080
nodePort: 30001
protocol: TCP
targetPort: 80
selector:
app: myhttp
sessionAffinity: None
EOF
執行如下命令檢查服務,發現一個為ClusterIP型別,一個為NodePort型別,但兩者均分配了ClusterIP地址:
# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
myhttp-int ClusterIP 172.30.37.43 <none> 8080/TCP 1h
myhttp-pub NodePort 172.30.6.69 <none> 8080:30001/TCP 3m
myhttp-pub服務通過nodePort開啟了叢集各節點的主機埠,此時可通過叢集任何節點訪問服務:
# curl 192.168.220.21:30001
myhttp-7bc6d8b87c-zsbcc
# curl 192.168.230.21:30001
myhttp-7bc6d8b87c-zsbcc
# curl 192.168.240.21:30001
myhttp-7bc6d8b87c-cj4g8
通過NodePort型別的Service雖可將服務暴露到叢集外部,但問題是:埠數量有限(限制為30000-32767)、節點故障後,通過此節點訪問服務將失敗。鑑於此原因,NodePort型別的Service不常用,而是換成使用Ingress的技術來暴露服務到叢集外部,但為簡單考慮,本文不再講解Ingress。
Configmap
當容器異常時,映象控制器用Image重建Container,此時對容器的修改會丟失,故而,若需自定義httpd映象的httpd.conf檔案,我們不應直接登入各容器修改配置,而應考慮使用K8S提供的Configmap2技術,其作為中央儲存配置庫所建立的檔案將Pod共享。
如下所示,為簡單考慮,我們隨意建立一檔案並掛載到Deployment中,修改Configmap,擴充套件Deployment,用此來講解Configmap作用。
建立一名為my-config的cm3:
# kubectl create -f - <<EOF
apiVersion: v1
metadata:
name: my-config
data:
hosts: |
127.0.0.1 localhost localhost.localdomain
#::1 localhost localhost.localdomain
kind: ConfigMap
EOF
執行kubectl edit deploy myhttp修改Deployment,將cm掛載到/etc/myhosts目錄中。完整Yaml檔案如下(PS:新增volumeMounts與volume):
apiVersion: extensions/v1beta1 kind: Deployment metadata: labels: app: myhttp name: myhttp spec: replicas: 1 selector: matchLabels: app: myhttp template: metadata: labels: app: myhttp spec: containers: - image: httpd name: myhttp volumeMounts: - name: config-hosts mountPath: /etc/myhosts volumes: - name: config-hosts configMap: name: my-config
修改Deploy後,可發現Pod將自動重建,而後檢查每Pod可發現目錄中含有cm的hosts檔案:
# kubectl get pod
NAME READY STATUS RESTARTS AGE
myhttp-774ffbb989-gz6bd 1/1 Running 0 11m
myhttp-774ffbb989-k8m4b 1/1 Running 0 11m
myhttp-774ffbb989-t74nk 1/1 Running 0 11m
# kubectl exec -it myhttp-774ffbb989-gz6bd -- ls /etc/myhosts
hosts
# kubectl exec -it myhttp-774ffbb989-gz6bd -- cat /etc/myhosts/hosts
127.0.0.1 localhost localhost.localdomain
#::1 localhost localhost.localdomain
修改cm,幾分鐘後,可發現pod中的配置被自動更新:
# kubectl edit cm my-config
...
data:
hosts: |
127.0.0.1 localhost localhost.localdomain
::1 localhost localhost.localdomain
...
# kubectl exec -it myhttp-774ffbb989-gz6bd -- cat /etc/myhosts/hosts
127.0.0.1 localhost localhost.localdomain
::1 localhost localhost.localdomain
擴充套件應用,繼而檢查新的Pod,發現其包含cm內容:
# kubectl scale deploy myhttp --replicas=4 # kubectl get pod
myhttp-774ffbb989-gz6bd 1/1 Running 0 15h
myhttp-774ffbb989-k8m4b 1/1 Running 0 15h
myhttp-774ffbb989-t74nk 1/1 Running 0 15h
myhttp-774ffbb989-z5d6h 1/1 Running 0 21s
# kubectl exec -it myhttp-774ffbb989-z5d6h -- cat /etc/myhosts/hosts
127.0.0.1 localhost localhost.localdomain
::1 localhost localhost.localdomain
Secret
相較於Configmap用於儲存明文,那麼Secret則儲存密文,如使用者密碼等銘感資料,可使用Secret加密儲存。如下所示,我們建立一個Secret加密使用者與密碼,而後提供給容器使用。
Opaque的Secret資料是一個map型別,要求value是base64編碼格式。加密使用者與密碼:
# echo -n root | base64
cm9vdA==
# echo -n Changeme | base64
Q2hhbmdlbWU=
建立名為userpwd-secret的Secret,其包含使用者與密碼:
# kubectl create -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: userpwd-secret
type: Opaque
data:
username: cm9vdA==
password: Q2hhbmdlbWU=
EOF
更新deployment,將secret以volume方式掛載到容器中:
# kubectl edit deployment myhttp
...
spec:
...
spec:
containers:
- image: httpd
...
volumeMounts:
- name: userpwd
mountPath: /etc/mysecret
...
volumes:
- name: userpwd
secret:
secretName: userpwd-secret
...
登入容器可發現secret中的key被儲存為檔案,其內容為value,但在容器內已被正確解密:
# kubectl exec -it myhttp-64575c77c-kqdj9 -- ls -l /etc/mysecret
lrwxrwxrwx. 1 root root 15 May 17 07:01 password -> ..data/password
lrwxrwxrwx. 1 root root 15 May 17 07:01 username -> ..data/username
# kubectl exec -it myhttp-64575c77c-kqdj9 -- cat /etc/mysecret/username
root
Storage
我們將web應用儲存到外部儲存中,而後掛載到Pod上,這樣,無論pod是否重建亦或伸縮,我們釋出的應用都不會丟失。
配置NFS儲存
為簡單考慮,本例採用NFS作為共享儲存:
nfs伺服器安裝軟體:
# yum install nfs-utils
配置共享目錄:
# mkdir -p /exports/httpd # chmod 0777 /exports/* # chown nfsnobody:nfsnobody /exports/* # cat > /etc/exports.d/k8s.exports <<EOF
/exports/httpd *(rw,root_squash)
EOF
配置防火牆,放行nfs埠:
# firewall-cmd --add-port=2049/tcp # firewall-cmd --permanent --add-port=2049/tcp
配置Selinux以允許Docker寫資料到nfs:
# getsebool -a|grep virt_use_nfs # setsebool -P virt_use_nfs=true
啟動nfs服務:
# systemctl restart nfs-config # systemctl restart nfs-server # systemctl enable nfs-server
K8S叢集使用儲存
K8S叢集每節點安裝nfs客戶端軟體,並設定Selinux許可權:
# yum install nfs-utils # setsebool -P virt_use_nfs=true
建立一型別為nfs的持久化卷:PersistentVolume(PV),其指向nfs後端儲存:
# kubectl create -f - <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
name: httpd
spec:
accessModes:
- ReadWriteMany
capacity:
storage: 1Gi
nfs:
path: /exports/httpd
server: 192.168.240.11
persistentVolumeReclaimPolicy: Retain
EOF
建立一持久化卷宣告PersistentVolumeClaim(PVC)指向上一步建立的PV:
# kubectl create -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: httpd
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
volumeName: httpd
EOF
檢查可發現pvc/httpd繫結到pv/httpd:
# oc get pv,pvc
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM ...
pv/httpd 1Gi RWX Retain Bound demo/httpd ...
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc/httpd Bound httpd 1Gi RWX 53s
重建deployment,新增volume與mount掛載點:
# kubectl delete deploy myhttp # kubectl create -f - <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
app: myhttp
name: myhttp
spec:
replicas: 3
selector:
matchLabels:
app: myhttp
template:
metadata:
labels:
app: myhttp
spec:
containers:
- image: httpd
name: myhttp
imagePullPolicy: IfNotPresent
volumeMounts:
- name: config-hosts
mountPath: /etc/myhosts
- name: userpwd
mountPath: /etc/mysecret
- name: httpd-htdocs
mountPath: /usr/local/apache2/htdocs
volumes:
- name: config-hosts
configMap:
name: my-config
- name: userpwd
secret:
secretName: userpwd-secret
- name: httpd-htdocs
persistentVolumeClaim:
claimName: httpd
EOF
Pod生成後,檢查發現nfs目錄被掛載到容器內:
# kubectl get pod # kubectl exec -it myhttp-8699b7d498-dlzrm -- df -h
Filesystem Size Used Avail Use% Mounted on
...
192.168.240.11:/exports/httpd 37G 17G 21G 44% /usr/local/apache2/htdocs ...
# kubectl exec -it myhttp-8699b7d498-dlzrm -- ls htdocs # 當前目錄為空
登入任何一個容器,將web應用釋出到htdocs目錄:
# kubectl exec -it myhttp-8699b7d498-dlzrm -- /bin/sh # echo "this is a test of pv" > htdocs/index.html # 容器內
而後,我們刪除容器亦或擴充套件容器,均會發現容器中的htdocs包含所釋出的應用:
# kubectl delete pod -l app=myhttp # 刪除所有myhttp pod # kubectl get pod # 等待pod重建完畢 # kubectl exec -it myhttp-8699b7d498-6q8tv -- cat htdocs/index.html
this is a test of pv
Satefulset
如上面用Deplyment建立的myhttp應用,其是無狀態(stateless)的,主機名是隨機動態分配的,且所有Pod可共享掛載相同的儲存(volume),但如Kafaka、Zookeeper叢集,其是有狀態的,需要主機名確定為一,且各自掛載儲存,鑑於此,K8S提供了Satefulset技術來滿足此類應用需求。
如下所示,我們使用nginx映象建立一個有狀態的叢集,用此來講解Statefulset用法。
不同於Deployment,我們必須先建立一個ClusterIP: None的Service服務:
# kubectl create -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: web
labels:
app: nginx-web
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx-web
EOF
此Service無ClusterIP,也即我們無法直接通過此Servcie訪問後端服務。
# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
web ClusterIP None <none> 80/TCP 3s
建立名為nginx的有狀態服務,映象數為2,且注意ServiceName配置為上步建立的Svc:
# kubectl create -f - <<EOF
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: nginx
spec:
serviceName: web
replicas: 2
template:
metadata:
labels:
app: nginx-web
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: web
EOF
觀察pod啟動,可發現pod名稱為nginx-n格式4,此名稱是固定唯一的,且可發現pod是順序啟動的,即容器nginx-n在nginx-<n-1>後啟動。
# kubectl get pod -w
NAME READY STATUS RESTARTS AGE
nginx-0 0/1 ContainerCreating 0 7s
nginx-0 1/1 Running 0 10s
nginx-1 0/1 Pending 0 0s
nginx-1 0/1 Pending 0 0s
nginx-1 0/1 ContainerCreating 0 1s
nginx-1 1/1 Running 0 13s
建立的service被statefulset用在dns上以跟蹤pod名稱:
# kubectl run -i --tty --image busybox dns-test --restart=Never --rm /bin/sh # 如下操作均在剛建立的dns-test pod中進行: # nslookup web # 查詢web服務,可發現後端有兩pod
...
Name: web
Address 1: 10.129.0.248 nginx-0.web.demo.svc.cluster.local
Address 2: 10.131.0.200 nginx-1.web.demo.svc.cluster.local
# nslookup nginx-0.web # 驗證pod名稱對應的IP地址
...
Name: nginx-0.web.demo.svc.cluster.local
Address 1: 10.129.0.248 nginx-0.web.demo.svc.cluster.local
# nslookup nginx-1.web
...
Name: nginx-1.web.demo.svc.cluster.local
Address 1: 10.131.0.200 nginx-1.web.demo.svc.cluster.local
配置satefulset掛載volume:
# kubectl delete statefulset nginx # 為簡單起見,刪除以上建立的statefulset # kubectl create -f - <<EOF
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: nginx
spec:
serviceName: web
replicas: 2
template:
metadata:
labels:
app: nginx-web
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: glusterfs-raid0
resources:
requests:
storage: 10Mi
EOF
注意:在volumeClaimTemplates.spec中新增的storageClassName,其指定了名為glusterfs-raid0的儲存,這樣,當pod生成時,k8s會使用動態提供5建立PVC、PV並自動從儲存池glusterfs-raid0中動態分配volume。當然,若使用Storage一節中配置的nfs儲存,則此處需刪除storageClassName,而後手動建立儲存、pv、pvc。
檢查:
# 如下卷是k8s使用動態提供自動從glusterfs建立的: # kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
www-nginx-0 Bound pvc-4a76e4a9... 1Gi RWO glusterfs-raid0 22h
www-nginx-1 Bound pvc-536e8980... 1Gi RWO glusterfs-raid0 22h
# kubectl get statefulset,pod
NAME DESIRED CURRENT AGE
statefulsets/nginx 2 2 22h
NAME READY STATUS RESTARTS AGE
po/nginx-0 1/1 Running 0 22h
po/nginx-1 1/1 Running 0 22h
# 兩Pod掛載各自的卷: # kubectl exec -it nginx-0 -- df -h
Filesystem Size Used Avail Use% Mounted on
192.168.220.21:vol_e6858... 1016M 33M 983M 4% /usr/share/nginx/html
# kubectl exec -it nginx-1 -- df -h
Filesystem Size Used Avail Use% Mounted on
192.168.220.21:vol_c659cc... 1016M 33M 983M 4% /usr/share/nginx/html
Namespace
細心的讀者會在Storage一節中看到demo/httpd,此demo就是作者所使用的Namespace/Project6。如同Openstack雲端計算平臺提供了多租戶用途,其每租戶可建立自己的Project(專案),K8S同樣提供多租戶功能,我們可建立不同的Namespace(名稱空間),並將以上所示的Pod、Service、Configmap等限制在Namespace中。
剛搭建的K8S叢集,預設有如下兩Namespace:
# kubectl get namespace
NAME DISPLAY NAME STATUS
default Active # 預設名稱空間
kube-system Active # k8s自身使用的名稱空間
我們可執行如下命令建立名稱空間:
# kubectl create namespace demo
namespace "demo" created
而後,執行kubectl命令時可附帶”-n <namespace>“引數。如下所示,查詢Pod:
# kubectl get pod -n demo
NAME READY STATUS RESTARTS AGE
nginx-0 1/1 Running 0 23h
nginx-1 1/1 Running 0 23h
最後,對於Openshift平臺,我們可執行如下命令登入到Namespace中,這樣,我們就無需每次附帶“-n <namespace>”了。
# oc project demo # oc get pod
NAME READY STATUS RESTARTS AGE
nginx-0 1/1 Running 0 23h
nginx-1 1/1 Running 0 23h
結束語
通過本文,我們學習了Docker、K8S核心知識,我相信讀者應完全可以熟練使用K8S平臺了。
- 映象格式為:<image_name>:<image_tag>,若不寫image_tag,則預設為latest tag ↩
- 參考官方文件:Configure a Pod to Use a ConfigMap。 ↩
- 內容為key:value格式,且一個cm可包含多個 ↩
- statefulset名稱的生成規則是固定的:<statefulset-name>-n ↩
- 儲存必須支援動態提供,如glusterfs儲存,要支援動態提供,必須配置heketi; ↩
- Openshift平臺,其Project即為K8S的Namespace ↩
相關文章
- 容器、Docker與Kubernetes——Kubernetes的配置入門Docker
- Docker 入門:容器Docker
- Docker - 通往新世界的大門Docker
- Kubernetes 普及系列:容器基礎入門
- Docker容器使用 (入門到精通)Docker
- Docker 入門系列二:容器的資料卷Docker
- 容器技術之Docker基礎入門Docker
- 容器編排系統之Kubernetes基礎入門
- Kubernetes vs Docker:瞭解 2021 年的容器Docker
- 最火的容器技術|Docker入門與實踐Docker
- 自動化整合:Docker容器入門簡介Docker
- Docker從入門到精通(六)——容器通訊Docker
- docker進入容器Docker
- 細述Kubernetes和Docker容器的儲存方式Docker
- 容器引擎Docker和容器編排kubernetes如何優雅的收集容器日誌Docker
- Kubernetes+Docker+Istio 容器雲實踐Docker
- Docker容器基礎入門認知-網路篇Docker
- Docker從入門到精通(七)——容器資料共享Docker
- Docker容器從一知半解到入門Docker
- ?史上最全的企業級容器系列之kubernetes入門和搭建(四)
- ?史上最全的企業級容器系列之kubernetes入門和搭建(三)
- ?史上最全的企業級容器系列之kubernetes入門和搭建(二)
- 淺入kubernetes(1):Kubernetes 入門基礎
- Docker入門系列之一:在一個Docker容器裡執行指定的web應用DockerWeb
- Java服務端容器化:Docker與Kubernetes的應用Java服務端Docker
- 容器,Docker,Kubernetes和Kyma,以及Kyma對SAP的意義Docker
- 容器,Docker, Kubernetes和Kyma,以及Kyma對SAP的意義Docker
- 進入docker容器的四種方法Docker
- docker入門Docker
- 對於kubernetes(k8s)入門需要了解的docker基礎K8SDocker
- 從零入門 Serverless | 一文講透 Serverless Kubernetes 容器服務Server
- Kubernetes 入門基礎
- 簡單入門Kubernetes
- Azure Kubernetes Service 入門
- 入門Kubernetes-StatefulSets
- Kubernetes Helm入門指南
- Kubernetes入門簡介
- Docker(一):Docker入門教程Docker