Minikube可以实现一种轻量级的Kubernetes集群,通过在本地计算机上创建虚拟机并部署只包含单个节点的简单集群。
在mac下的minikube中,学习了如果安装minikube以及简单的minikube操作。本节中学习如何发布应用/访问应用/滚动更新应用和回滚,扩容/缩容操作。
假设已经安装了minikube和kubectl,也有预备好的测试镜像hello-node
获取集群信息
1 | kubectl cluster-info |
创建Deployment
容器应用运行在pod上,通过kubectl run命令创建Deployment来管理Pod。1
2kubectl run hello-node --image=dillonliang/hello-node --port=8080
--> deployment.apps "hello-node" created
查看Deployment1
2
3
4
5kubectl get deployments
-->
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
hello-node 1 1 1 1 3d
也可以通过dashboard查看整个集群的运行情况,
启动minikube dashboard1
minikube dashboard
点击doshboard里的部署选项,可以看到刚才创建的hello-node
创建Service
默认情况下,我们不能直接访问kubernetes集群里的pods,kubernetes提供了一种访问集群内pods的方式:Service
1 | ## create service |
查看刚刚创建的service1
2
3
4
5
6kubectl get services
-->
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-node LoadBalancer 10.107.249.99 <pending> 8080:30788/TCP 3d
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d
可以看到有2个service,其中kubernetes是集群默认的,hello-node是刚刚创建的
在minikube中,使用如下命令启动service1
2minikube service hello-node
--> 🎉 Opening kubernetes service default/hello-node in default browser...
我本机测试的时候访问的是http://192.168.64.5:30788/,
因为minikube是单机集群,可以通过minikube ip命令获取集群地址,在上面的service里暴露了30788端口
滚动更新
假设我们的hello-node升级了,重新打包成镜像后的版本是0.0.2,如何更新k8s里的应用呢?
查看k8s里的hello-node1
kubectl describe pods
这里只有一个pod,我们关注输出结果里的Containers->hello-node->Image字段,这里是dillonliang/hello-node
然后我们更新k8s里的应用的镜像,这里也是通过kubectl命令:1
kubectl set image deployment/hello-node hello-node=dillonliang/hello-node:0.0.2
这时我们通过get pods获取k8s里的pod情况,毕竟在k8s里,pod是调度的最小单元,应用的更新/回滚都是依靠pod1
2
3
4
5kubectl get pods
-->
NAME READY STATUS RESTARTS AGE
hello-node-58cb7dd798-mwbmj 0/1 ContainerCreating 0 3d
hello-node-6b8c5879f8-f75r4 1/1 Terminating 0 3d
可以看到旧的pod已经中止,新的pod正在创建中,稍等一会再次get pods,新的pod的状态变为了Running。查看pod的描述1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52kubectl describe pods
-->
Name: hello-node-58cb7dd798-mwbmj
Namespace: default
Priority: 0
PriorityClassName: <none>
Node: minikube/192.168.64.5
Start Time: Fri, 26 Jul 2019 07:43:40 +0800
Labels: pod-template-hash=58cb7dd798
run=hello-node
Annotations: <none>
Status: Running
IP: x.x.x.x
Controlled By: ReplicaSet/hello-node-58cb7dd798
Containers:
hello-node:
Container ID: docker://2c915697b9a33dd31b8d668d64761c55362c20faa3a55555b5b479aefeea6fed
Image: dillonliang/hello-node:0.0.2
Image ID: docker-pullable://dillonliang/hello-node@sha256:224545db28d48c54fc2b5375c85be61198ed7186bb79981036b5ba9642d946a5
Port: 8080/TCP
Host Port: 0/TCP
State: Running
Started: Fri, 26 Jul 2019 07:44:00 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-6ll8c (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-6ll8c:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-6ll8c
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 3d default-scheduler Successfully assigned default/hello-node-58cb7dd798-mwbmj to minikube
Normal Pulling 3d kubelet, minikube Pulling image "dillonliang/hello-node:0.0.2"
Normal Pulled 3d kubelet, minikube Successfully pulled image "dillonliang/hello-node:0.0.2"
Normal Created 3d kubelet, minikube Created container hello-node
Normal Started 3d kubelet, minikube Started container hello-node
从上面的输出可以看到,pod里的hello-node镜像已经是dillonliang/node-node:0.0.2,说明pod已经更新了,最下面的Events里也依次描述了pod的更新流程。
再次访问 http://192.168.64.5:30788/ ,可以看到新的输出结果hello-node-58cb7dd798-mwbmj: Hello World!,这里的hello-node-58cb7dd798-mwbmj是pod的hostname
回滚
实际情况中,我们的应用可能出现问题,需要回滚到之前的状态。
假设我们更新了image:0.0.10
1 | kubectl set image deployment/hello-node hello-node=dillonliang/hello-node:0.0.10 |
然后我们通过kubectl get deployments查看到没有deployment是available,通过get pods查看到,新的镜像status是ErrImagePull,然后通过describe pods,发现Events里是找不到这个dillonliang/hello-node:0.0.10镜像1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119kubectl get deployments
-->
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
hello-node 1 1 1 0 3d
$ kubectl get pods
-->
NAME READY STATUS RESTARTS AGE
hello-node-58cb7dd798-mwbmj 1/1 Terminating 0 3d
hello-node-69d57cc549-qpv5j 0/1 ErrImagePull 0 3d
$ kubectl describe pods
-->
Name: hello-node-58cb7dd798-mwbmj
Namespace: default
Priority: 0
PriorityClassName: <none>
Node: minikube/192.168.64.5
Start Time: Fri, 26 Jul 2019 07:43:40 +0800
Labels: pod-template-hash=58cb7dd798
run=hello-node
Annotations: <none>
Status: Terminating (lasts 3d)
Termination Grace Period: 30s
IP: x.x.x.x
Controlled By: ReplicaSet/hello-node-58cb7dd798
Containers:
hello-node:
Container ID: docker://2c915697b9a33dd31b8d668d64761c55362c20faa3a55555b5b479aefeea6fed
Image: dillonliang/hello-node:0.0.2
Image ID: docker-pullable://dillonliang/hello-node@sha256:224545db28d48c54fc2b5375c85be61198ed7186bb79981036b5ba9642d946a5
Port: 8080/TCP
Host Port: 0/TCP
State: Terminated
Reason: Error
Exit Code: 137
Started: Fri, 26 Jul 2019 07:44:00 +0800
Finished: Fri, 26 Jul 2019 10:07:59 +0800
Ready: False
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-6ll8c (ro)
Conditions:
Type Status
Initialized True
Ready False
ContainersReady False
PodScheduled True
Volumes:
default-token-6ll8c:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-6ll8c
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Killing 3d kubelet, minikube Stopping container hello-node
Name: hello-node-69d57cc549-qpv5j
Namespace: default
Priority: 0
PriorityClassName: <none>
Node: minikube/192.168.64.5
Start Time: Fri, 26 Jul 2019 10:07:28 +0800
Labels: pod-template-hash=69d57cc549
run=hello-node
Annotations: <none>
Status: Pending
IP: x.x.x.x
Controlled By: ReplicaSet/hello-node-69d57cc549
Containers:
hello-node:
Container ID:
Image: dillonliang/hello-node:0.0.10
Image ID:
Port: 8080/TCP
Host Port: 0/TCP
State: Waiting
Reason: ErrImagePull
Ready: False
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-6ll8c (ro)
Conditions:
Type Status
Initialized True
Ready False
ContainersReady False
PodScheduled True
Volumes:
default-token-6ll8c:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-6ll8c
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 3d default-scheduler Successfully assigned default/hello-node-69d57cc549-qpv5j to minikube
Normal Pulling 3d kubelet, minikube Pulling image "dillonliang/hello-node:0.0.10"
Warning Failed 3d kubelet, minikube Failed to pull image "dillonliang/hello-node:0.0.10": rpc error: code = Unknown desc = Error response from daemon: manifest for dillonliang/hello-node:0.0.10 not found
Warning Failed 3d kubelet, minikube Error: ErrImagePull
Normal BackOff 3d kubelet, minikube Back-off pulling image "dillonliang/hello-node:0.0.10"
Warning Failed 3d kubelet, minikube Error: ImagePullBackOff
这时候要进行回滚操作了,执行如下命令:1
2## 意思就是:取消deployment下hello-node的更新操作,即回滚。
kubectl rollout undo deployment/hello-node
再次通过get pods和describe pods命令查查hello-node的情况,发现回滚到之前的状态了。
值得注意的是,这次hostname变了,pod是一个新的pod。
动态扩容/缩容
线上有时候流量缓慢增高/减少,已有的pod会面临2中情况,流量增高时,pod压力变大,无法响应更多的请求,需要新增服务节点pod。流量减少的时候,pod会造成资源浪费,需要减少节点上的pod。
k8s提供了根据线上流量动态扩容/缩容的功能
1 | kubectl scale deployments/hello-node --replicas=4 |
可以通过如下命令查看扩容状态:1
2
3kubectl get deployments
kubectl get pods -o wide
kubectl describe deployments/hello-node
此时,我们把pods扩容到4个,k8s为我们做了负载均衡,如何随机访问这4个pod呢?1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17kubectl describe services/hello-node
-->
Name: hello-node
Namespace: default
Labels: run=hello-node
Annotations: <none>
Selector: run=hello-node
Type: LoadBalancer
IP: 10.107.249.99
Port: <unset> 8080/TCP
TargetPort: 8080/TCP
NodePort: <unset> 30788/TCP
Endpoints: 172.17.0.5:8080,172.17.0.6:8080,172.17.0.7:8080 + 1 more...
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
使用如下命令来访问:1
2
3
4
5export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')
echo NODE_PORT=$NODE_PORT
curl $(minikube ip):$NODE_PORT
可以看到,每次随机访问4个pods中的一个。
如何缩容呢,修改–replicas=2就可以了,然后通过get deployments和get pods -o wide查看集群状态。
参考:
http://docs.kubernetes.org.cn/126.html
https://kubernetes.io/docs/tutorials/kubernetes-basics/