第一个kubernetes应用

使用小细节

从节点上使用kubectl时,如果出现

1
The connection to the server localhost:8080 was refused - did you specify the right host or port?

可以使用以下命令解决:

1
export KUBECONFIG=/etc/kubernetes/admin.conf

原因暂时母鸡,我试过把这句话加到环境变量,但是并没有卵用…..
(问题找到了。。将master节点的/etc/kubernetes/admin.conf拷贝到 worker节点上)执行如下即可:

1
2
3
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

另外,每次集群宕机后,各节点都需要运行一遍swapoff -a ,不然无法启动。

第一个kubernetes应用

在上一篇笔记中,已经使用kubeadm这个工具搭建好了一个完整的kubernetes集群,现在就是时候来体验一下如何使用kubernetes管理容器应用了。

首先,kubernetes是基于容器进行部署的,那么我们需要的第一个东西就是镜像。然后,我们需要根据kubernetes的规范和要求,将镜像组织为kubernetes能够认识的方式: 编写yaml文件。

kubernetes与Docker的不同之处就在于,kubernetes不推荐使用命令行的方式来运行容器,而是使用yaml/json的方式来运行。将容器的信息都记录在文件中,然后使用如下的语句将它运行起来:

1
kubectl  create -f  xxx.yaml

这样,在运行容器的同时,也记录下了run的相关信息。在需要变更时,可以有相关记录。(其实在容器编排上来说docker-compose也是这样的思路,只是kubernetes提供的功能相对来说更加的强大和全面。)比如下面这个yaml文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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.16.0
ports:
- containerPort: 80

在这个文件中,metadata代表的是元数据信息,name:nginx-deployment就是为这个Deployment自定义的名称,而kind: Deployment代表的是定义多个副本的应用。replicas告诉kubernetes需要在所有节点中,保证有且仅有2个节点在同时运行。

除此之外,template定义了pod的模板,声明每个创建出来的容器都带有一个标签app:nginx,使用的基础镜像为nginx:1.16.0,并且开放容器端口80。

使用kubectl apply指令创建/更新这个yaml文件对应的容器:

1
kubectl apply -f nginx-deployment.yaml

kubectl create 和 kubectl replace 分别对应着创建和更新,但一般不推荐,因为apply可以统一完成这两种操作。

接下来,可以通过kubectl get 检查运行结果:

1
2
3
4
5
6
kubectl get pods -l app=nginx

...
NAME READY STATUS RESTARTS AGE
nginx-deployment-75fdccc955-vpdqm 1/1 Running 0 25s
nginx-deployment-75fdccc955-wdfxf 1/1 Running 0 25s

这个命令中,-l表示的是查找pod中label标签为app=nginx的,也就是yaml文件中所配置的那样,可以看到两个副本都已经处于running状态,表示这个Deployment所管理的Pod都处于预期状态。

此外,使用kubectl describe可以查看pod的相关信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
kubectl describe pod nginx-deployment-75fdccc955-vpdqm

...
Name: nginx-deployment-75fdccc955-vpdqm
Namespace: default
Node: node1/192.168.110.130
Labels: app=nginx
pod-template-hash=75fdccc955
Status: Running
IP: 10.244.0.54
Controlled By: ReplicaSet/nginx-deployment-75fdccc955
......
......
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 65s default-scheduler Successfully assigned default/nginx-deployment-75fdccc955-vpdqm to node1
Normal Pulling 64s kubelet, node1 Pulling image "nginx:1.16.0"
Normal Pulled 44s kubelet, node1 Successfully pulled image "nginx:1.16.0"
Normal Created 44s kubelet, node1 Created container nginx
Normal Started 43s kubelet, node1 Started container nginx

在返回结果中,可以看到诸如name、node、labels、IP等等一系列相关信息。除此之外,还有一个特别的部分:Events。在Events中,可以看到这个Pod从分配节点到拉取镜像再到运行容器的整个流程。所以,当运行发生异常时往往可以在这里看到错误信息,帮助Debug。

当需要进行升级时,如从1.16.0升级到latest版本,只需要将yaml文件对应的镜像改为image: nginx即可,然后运行

1
2
3
4
kubectl apply -f nginx-deployment.yaml

...
deployment.apps/nginx-deployment configured

如果速度较快的话,可以查看到如下情况:(停止和删除原先的Pod,并重新创建的过程)

1
2
3
4
5
6
7
8
kubectl get pods -l app=nginx

...
NAME READY STATUS RESTARTS AGE
nginx-deployment-75fdccc955-vpdqm 1/1 Terminating 0 31m
nginx-deployment-75fdccc955-wdfxf 1/1 Running 0 31m
nginx-deployment-7bffbd4747-kz8qt 0/1 ContainerCreating 0 1s
nginx-deployment-7bffbd4747-qb9x2 1/1 Running 0 2s

接下来,尝试为容器添加Volume数据卷映射,修改yaml内容为如下所示:

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
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
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: nginx-vol
volumes:
- name: nginx-vol
hostPath:
path: /var/data

可以看到,在这个yaml中增加了一个volumeMounts的属性,它所代表的含义是将容器mountPath所指定的目录挂载到名称为nginx-vol的Volume中,同时volumes属性声明了一个名为nginx-vol的卷供容器使用,并且类型为hostPath。这样一来,宿主机的/var/data目录就和容器的mountPath目录建立了映射关系。

运行kubectl describe指令可以查看到映射的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
......
......
Containers:
nginx:
Container ID: docker://db553728961f2b62bb3fc48c46e2053674743d04eab21abd19528ae28ad9abde
Image: nginx:1.16.0
Image ID: docker-pullable://nginx@sha256:71f04b5caf2f921f4f0752b036be5a2d005f22c10e946fde6b2aa22676579d66
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Sat, 20 Jul 2019 13:46:26 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/usr/share/nginx/html from nginx-vol (rw)
/var/run/secrets/kubernetes.io/serviceaccount from default-token-6nvp9 (ro)
......
Volumes:
nginx-vol:
Type: HostPath (bare host directory volume)
Path: /var/data
HostPathType:
......

到这里,还可以使用kubectl exec指令进入到Pod中

1
2
3
4
kubectl exec -it nginx-deployment-7bffbd4747-kz8qt  sh

...
# ls /usr/nginx/share/html

最后,如果需要从集群中删除这个nginx-deployment的话,执行kubectl delete指令即可

1
2
3
4
kubectl delete -f nginx-deployment.yaml

...
deployment.apps "nginx-deployment" deleted

制作image-sign的Deployment

在有了上述知识后,我决定将之前在alpine镜像安装字体库使用到的image-sign制作为一个deployment。(可以使用docker pull hoppou/image-sign 从dockerhub拉取这个镜像呢,另外记得改镜像名称~)
编写如下yaml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: apps/v1
kind: Deployment
metadata:
name: image-sign-deployment
spec:
selector:
matchLabels:
app: image-sign
replicas: 2
template:
metadata:
labels:
app: image-sign
spec:
containers:
- name: image-sign
image: image-sign
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9466

由于镜像功能极为简单,yaml的内容也很清晰,只需要将端口打开即可,运行:

1
2
3
kubectl apply -f image-sign-deployment.yaml 
...
deployment.apps/image-sign-deployment created
1
2
3
4
kubectl get pod -l app=image-sign
NAME READY STATUS RESTARTS AGE
image-sign-deployment-59948dd446-8n8l7 1/1 Running 0 16s
image-sign-deployment-59948dd446-fsbdj 1/1 Running 0 16s

查看其中一个pod的相关属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
kubectl describe pod image-sign-deployment-59948dd446-8n8l7

...
Node: node2/192.168.110.131

Status: Running
IP: 10.244.1.40

Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 108s default-scheduler Successfully assigned default/image-sign-deployment-59948dd446-8n8l7 to node2
Normal Pulled 107s kubelet, node2 Container image "image-sign" already present on machine
Normal Created 107s kubelet, node2 Created container image-sign
Normal Started 106s kubelet, node2 Started container image-sign

可以看到IP信息为10.244.1.40,接下来使用postman进行测试:
image

大功告成!!!ヽ(・∀・)ノ

Tips补充

在kubernetes中拉取镜像有如下三种策略,可以通过imagePullPolicy进行设置

1
2
3
Never                          ---- 从不拉取,只使用已有镜像
Always ---- 总是拉取
IfNotPresent ---- 当本地不存在时拉取

目前版本的kubernetes默认使用的是IfNotPresent,但在没有标明镜像的tag时,如 image: nginx 这种写法会采用Always的方式进行拉取。

0%