Kubernetes 101
體驗 Kubernetes 最簡單的方法是跑一個 nginx 容器,然後使用 kubectl 操作該容器。Kubernetes 提供了一個類似於 docker run
的命令 kubectl run
,可以方便的創建一個容器(實際上創建的是一個由 deployment 來管理的 Pod):
$ kubectl run --image=nginx:alpine nginx-app --port=80
deployment "nginx-app" created
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-app-4028413181-cnt1i 1/1 Running 0 52s
等到容器變成 Running 後,就可以用 kubectl
命令來操作它了,比如
kubectl get
- 類似於docker ps
,查詢資源列表kubectl describe
- 類似於docker inspect
,獲取資源的詳細信息kubectl logs
- 類似於docker logs
,獲取容器的日誌kubectl exec
- 類似於docker exec
,在容器內執行一個命令
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-app-4028413181-cnt1i 1/1 Running 0 6m
$ kubectl exec nginx-app-4028413181-cnt1i -- ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.5 31736 5108 ? Ss 00:19 0:00 nginx: master process nginx -g daemon off;
nginx 5 0.0 0.2 32124 2844 ? S 00:19 0:00 nginx: worker process
root 18 0.0 0.2 17500 2112 ? Rs 00:25 0:00 ps aux
$ kubectl describe pod nginx-app-4028413181-cnt1i
Name: nginx-app-4028413181-cnt1i
Namespace: default
Node: boot2docker/192.168.64.12
Start Time: Tue, 06 Sep 2016 08:18:41 +0800
Labels: pod-template-hash=4028413181
run=nginx-app
Status: Running
IP: 172.17.0.3
Controllers: ReplicaSet/nginx-app-4028413181
Containers:
nginx-app:
Container ID: docker://4ef989b57d0a7638ad9c5bbc22e16d5ea5b459281c77074fc982eba50973107f
Image: nginx
Image ID: docker://sha256:4efb2fcdb1ab05fb03c9435234343c1cc65289eeb016be86193e88d3a5d84f6b
Port: 80/TCP
State: Running
Started: Tue, 06 Sep 2016 08:19:30 +0800
Ready: True
Restart Count: 0
Environment Variables: <none>
Conditions:
Type Status
Initialized True
Ready True
PodScheduled True
Volumes:
default-token-9o8ks:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-9o8ks
QoS Tier: BestEffort
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
8m 8m 1 {default-scheduler} Normal Scheduled Successfully assigned nginx-app-4028413181-cnt1i to boot2docker
8m 8m 1 {kubelet boot2docker} spec.containers{nginx-app} Normal Pulling pulling image "nginx"
7m 7m 1 {kubelet boot2docker} spec.containers{nginx-app} Normal Pulled Successfully pulled image "nginx"
7m 7m 1 {kubelet boot2docker} spec.containers{nginx-app} Normal Created Created container with docker id 4ef989b57d0a
7m 7m 1 {kubelet boot2docker} spec.containers{nginx-app} Normal Started Started container with docker id 4ef989b57d0a
$ curl http://172.17.0.3
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
$ kubectl logs nginx-app-4028413181-cnt1i
127.0.0.1 - - [06/Sep/2016:00:27:13 +0000] "GET / HTTP/1.0" 200 612 "-" "-" "-"
使用 yaml 定義 Pod
上面是通過 kubectl run
來啓動了第一個 Pod,但是 kubectl run
並不支持所有的功能。在 Kubernetes 中,更經常使用 yaml 文件來定義資源,並通過 kubectl create -f file.yaml
來創建資源。比如,一個簡單的 nginx Pod 可以定義爲:
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
前面提到,kubectl run
並不是直接創建一個 Pod,而是先創建一個 Deployment 資源(replicas=1),再由與 Deployment 關聯的 ReplicaSet 來自動創建 Pod,這等價於這樣一個配置:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: nginx-app
name: nginx-app
namespace: default
spec:
replicas: 1
selector:
matchLabels:
run: nginx-app
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
labels:
run: nginx-app
spec:
containers:
- image: nginx
name: nginx-app
ports:
- containerPort: 80
protocol: TCP
dnsPolicy: ClusterFirst
restartPolicy: Always
使用 Volume
Pod 的生命週期通常比較短,只要出現了異常,就會創建一個新的 Pod 來代替它。那容器產生的數據呢?容器內的數據會隨着 Pod 消亡而自動消失。Volume 就是爲了持久化容器數據而生,比如可以爲 redis 容器指定一個 hostPath 來存儲 redis 數據:
apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: redis
volumeMounts:
- name: redis-persistent-storage
mountPath: /data/redis
volumes:
- name: redis-persistent-storage
hostPath:
path: /data/
Kubernetes volume 支持非常多的插件,可以根據實際需要來選擇:
emptyDir
hostPath
gcePersistentDisk
awsElasticBlockStore
nfs
iscsi
flocker
glusterfs
rbd
cephfs
gitRepo
secret
persistentVolumeClaim
downwardAPI
azureFileVolume
vsphereVolume
使用 Service
前面雖然創建了 Pod,但是在 kubernetes 中,Pod 的 IP 地址會隨着 Pod 的重啓而變化,並不建議直接拿 Pod 的 IP 來交互。那如何來訪問這些 Pod 提供的服務呢?使用 Service。Service 爲一組 Pod(通過 labels 來選擇)提供一個統一的入口,併爲它們提供負載均衡和自動服務發現。比如,可以爲前面的 nginx-app
創建一個 service:
$ kubectl expose deployment nginx-app --port=80 --target-port=80 --type=NodePort
service "nginx-app" exposed
$ kubectl describe service nginx-app
Name: nginx-app
Namespace: default
Labels: run=nginx-app
Selector: run=nginx-app
Type: ClusterIP
IP: 10.0.0.66
Port: <unset> 80/TCP
NodePort: <unset> 30772/TCP
Endpoints: 172.17.0.3:80
Session Affinity: None
No events.
這樣,在 cluster 內部就可以通過 http://10.0.0.66
和 http://node-ip:30772
來訪問 nginx-app。而在 cluster 外面,則只能通過 http://node-ip:30772
來訪問。
Last updated