适合 Kubernetes 初学者的一些实战练习 (一)
![适合 Kubernetes 初学者的一些实战练习(一)](https://static001.geekbang.org/infoq/fe/fe6ffb7c4537832f74a2a4e3b21970be.png)
本系列记录了笔者刚刚接触并学习 Kubernetes 时动手做过的一些练习,这里分享出自己的 Kubernetes 学习历程,希望对广大 Kubernetes 初学者有所帮助。
练习 1 - 如何在 Kubernetes 里创建一个 Nginx 应用
使用命令行 kubectl run --image=nginx nginx-app --port=80 创建一个名为 nginx-app 的应用
![](https://static001.geekbang.org/infoq/47/47d7c3e8c7532acd707cc8bfbbc3e17b.png)
结果: deployment.apps/nginx-app created
使用命令行 kubectl get pods
查看创建结果,状态已经为 running
:
![](https://static001.geekbang.org/infoq/72/724ad974b3e1ede8072e4da04c2806df.png)
使用命令行 kubectl describe pods
查看 pod 明细:
![](https://static001.geekbang.org/infoq/1f/1fa9ecbd37c21010a3c41a9bbac5e5d5.png)
![](https://static001.geekbang.org/infoq/dd/ddc3a5e731f66b8608189bd5c15c2545.png)
![](https://static001.geekbang.org/infoq/c6/c606d85aa8338250979b5e4cc07785e9.png)
把 pod id 记下来: nginx-app-f75d46bd9-q6c76
使用该 pod id 可以执行一些命令:
kubectl exec nginx-app-f75d46bd9-q6c76 ps aux
kubectl describe pod nginx-app-f75d46bd9-q6c76
kubectl logs nginx-app-f75d46bd9-q6c76
练习 2 - 如何在 Kubernetes 里创建一个 Nginx Service
前一个练习,我们已经使用 kubectl
命令行创建了 Pod,但是在 kubernetes 中,Pod 的 IP 地址会随着 Pod 的重启而变化,因此用 Pod 的 IP 地址来访问我们部署的 nginx 应用不太合适。
Kubernetes 里推荐的方式是用 Service 来消费 nginx 服务。
Service 为一组 Pod 提供一个统一的入口,并为它们提供负载均衡和服务发现支持。
使用如下命令行基于 pod 创建一个 service:
kubectl expose deployment nginx-app --type=NodePort --port=80
收到 service/nginx-app exposed 消息。
![](https://static001.geekbang.org/infoq/82/82408f57590231919fdce1115823e5f6.png)
使用命令行拿到创建成功的 service 的明细:
kubectl describe service nginx-app
![](https://static001.geekbang.org/infoq/0f/0ff6fb01ab0601d02d37c81dd6942b8c.png)
使用 http://<node_id>:32624
访问这个 nginx 应用:
![](https://static001.geekbang.org/infoq/50/50807faa8379ae02748f3ffb306b476b.png)
看到上图说明访问 nginx 成功了。
使用命令行查看 nginx 访问日志:
kubectl logs nginx-app-f75d46bd9-q6c76
![](https://static001.geekbang.org/infoq/d6/d67da6d659c64c8d48d4a2661ad0729c.png)
练习 3 - Kubenetes 里 Pod 和 Service 绑定的实现方式
前一个练习,我们介绍了如何创建一个 Kubernetes pod 和 service,使用的方法是命令kubectl run
.
本文介绍另一种方式,通过这种方式来学习 Kubernetes 里 pod 和对应的 service 是如何绑定的。
首先使用下面的命令行创建一个名称为 jerry-nginx-1982 的 deployment:
kubectl create deployment jerry-nginx-1982 --image=nginx
![](https://static001.geekbang.org/infoq/41/4148d39d3aa2b7a54bacea3fc73592d8.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
然后使用命令行 kubectl get deployment
得到创建好的 deployment:然后创建一个同名的 service,类型为 nodeport.
kubectl create service nodeport jerry-nginx-1982 --tcp 80:80 创建完成后,使用命令行 kubectl get svc 得到名称为 jerry-nginx-1982 对外暴露的端口号:31954:
![](https://static001.geekbang.org/infoq/ec/ecc0a90e3c27a30ac308f1cc89883bd3.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
然后就能通过这个端口号访问 nginx server 了:
![](https://static001.geekbang.org/infoq/46/466d864ec61183fa81ef57e5e9dc7d79.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
那么这两个同名的 pod 和 service 是如何关联的呢?首先打开 kubernetes dashboard,找到之前创建的 pod:
![](https://static001.geekbang.org/infoq/a1/a1b76b295fe631ce43b0b4b176a29f93.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
其明细为:jerry-nginx-1982-67cb658cb8-9hl99
![](https://static001.geekbang.org/infoq/f9/f9567faf4e583dde0571000e433765d6.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
再打开同名 service:
![](https://static001.geekbang.org/infoq/68/68654deb757f33dd874272c86ffe32a5.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
再打开这个 service 里的 pod,发现就是我们前面找到的 jerry-nginx-1982-67cb658cb8-9hl99,说明 pod 和 service 是通过名称关联的。
![](https://static001.geekbang.org/infoq/48/48f62316e34688b6ed45ed5064ddf151.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
我们可以做一个 negative 测试,直接创建一个名为 test 的 service,但不给它预先创建名为 test 的 pod:
kubectl create service nodeport test --tcp 80:80
![](https://static001.geekbang.org/infoq/1a/1ad13b6f21650a8a0c85b56f33277fba.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
service 创建成功后,打开这个 service,发现里面没有分配任何 pod:
![](https://static001.geekbang.org/infoq/4e/4e5ed10f0ef977844f339d4b0d0ee968.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
这个结果和我们预测的一致。
练习 4 - 使用 Kubernetes 里的 job 计算圆周率后 2000 位
使用 Kubernetes 里的 job(作业),我们可以很方便地执行一些比较耗时的操作。新建一个 job.ymal 文件:
定义了一个 Kubernetes job,名称为 pi,类型为 job,容器名称为 pi,镜像为 perl,执行的 perl 命令为 print bpi(2000):
![](https://static001.geekbang.org/infoq/dc/dc0fa585e10484b5eb9645137583b3ef.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
这个 ymal 文件的完整内容:
使用命令 kubectl create -f
导入这个 yaml 文件,创建一个新的 job:
![](https://static001.geekbang.org/infoq/9e/9e9e1406570869fb2046043ea3d3cb54.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
之后在 Kubernetes 的 dashboard 里能看到这个新建的 job:
![](https://static001.geekbang.org/infoq/51/5172c0d538475fec704e54288e13c29b.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
job 对应的 pod 状态为 Waiting ContainerCreating:
![](https://static001.geekbang.org/infoq/c5/c53a477926154f7a527462b6dde6b34f.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
稍后,其状态从 Running 变为了 Terminated:Completed,总共花了 14 分钟。
![](https://static001.geekbang.org/infoq/8c/8caaa9f58325b4c67c57b8d9b8effb74.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
在 pod 的事件日志里,能看到大部分时间花在了 perl 镜像的下载上:
![](https://static001.geekbang.org/infoq/b6/b6d1cbd2dc3030570efbea9b88863d0d.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
点击 dashboard 的 logs 按钮,就能看到这个 2000 位圆周率的计算结果:
![](https://static001.geekbang.org/infoq/5c/5c5bfbe9370e43f571816144e38dd3fd.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
练习 5 - Kubernetes 里的 ConfigMap 的用途
顾名思义,ConfigMap 用于保存配置数据的键值对,可以用来保存单个属性,也可以用来保存配置文件。ConfigMap 同 Kubernetes 的另一个概念 secret 类似,区别是 ConfigMap 主要用于保存不包含敏感信息的明文字符串。
创建方式:
kubectl create configmap special-config --from-literal=i042416=jerry
上述命令行创建了一个名为 special-config
的键值对,
![](https://static001.geekbang.org/infoq/aa/aafb377e4bb6f01f145bc9d2d8df2494.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
![](https://static001.geekbang.org/infoq/18/186860c1808b567075192e400f1d6b5f.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
key 为 i042416, 值为 jerry
![](https://static001.geekbang.org/infoq/5e/5eb10aac9c2ec7af6d5afa8b72169300.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
接下来我希望用这个 key 为 i042416 的值"jerry"来定义成 pod 里的一个环境变量。
下面是我的 yaml 文件:
![](https://static001.geekbang.org/infoq/8f/8fb8e22b341a1230d7a31ad94f9c5f53.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
可以看到第 15 行引用了我的 ConfigMap 的 key:i042416
下面使用 create -f
将该 yaml 文件导入,创建一个新的 pod:
![](https://static001.geekbang.org/infoq/17/17c7fe6e191bb0a6a4645715900d0898.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
创建之后,能在 pod 的明细页面看到 configMap 的 key 已经作为环境变量显示出来了:
![](https://static001.geekbang.org/infoq/c1/c12d84de5360133de84d611eaa6ba7ae.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
因为我 yaml 文件里指定 pod 执行的 script 为 /bin/sh -c env, 因此最后会将容器里所有的环境变量都打印出来,我们定义在 ConfigMap 里的 i042416 的值 jerry 也被显示了出来:
![](https://static001.geekbang.org/infoq/3c/3cd748f9433f5dfefc6dc0f956ae51ec.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
这种定义环境变量的做法和 SAP 云平台 CloudFoundry 环境里定义环境变量的方式很类似。CloudFoundry 环境变量一览表:
https://docs.run.pivotal.io/devguide/deploy-apps/environment-variable.html
CF_INSTANCE_ADDR
CF_INSTANCE_GUID
CF_INSTANCE_INDEX
CF_INSTANCE_IP
CF_INSTANCE_INTERNAL_IP
CF_INSTANCE_PORT
CF_INSTANCE_PORTS
DATABASE_URL
HOME
LANG
MEMORY_LIMIT
PORT
PWD
TMPDIR
USER
VCAP_APP_PORT
VCAP_APPLICATION
VCAP_SERVICES
当使用 cf push 命令将本地应用部署到 SAP 云平台的 CloudFoundry 环境下时,某些环境变量会自动被系统写入相应的值,这个行为同 ABAP 的 sy-sysid 自动被设置为当前系统 ID 具有一样的逻辑。
比如 app router 会把用户访问请求重定向到 XSUAA 实例上。
![](https://static001.geekbang.org/infoq/d5/d5e9dd699d7268bdfc077164bf717fef.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
app router 在 manifest.yml 里定义的 XSUAA 实例名称为 xsuaa-jerry-demo,
![](https://static001.geekbang.org/infoq/fe/fe60ff4465f4fe136e481d1e30d4a4d4.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
在运行时这个 XSUAA 的 id 会被 SAP 云平台自动写入环境变量 VCAP_SERVICES 里:
![](https://static001.geekbang.org/infoq/38/382f76ed7ec4974c960c480e2a4f635d.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
总结
本文介绍了每一个 Kubernetes 从业者的实际工作中几乎都会使用的步骤:创建 Deployment 和 Service,同时通过实际例子讲解了 Pod 和 Service 绑定的实现方式,介绍了使用 Kubernetes Job 计算圆周率这种费时的操作,希望对 Kubernetes 初学者能有所帮助。
版权声明: 本文为 InfoQ 作者【Jerry Wang】的原创文章。
原文链接:【http://xie.infoq.cn/article/27f5f6250a3033ea09c337989】。文章转载请联系作者。
评论