大家好,我是比特桃。本文为《极速上手k8s,Kubernetes 从入门到摸鱼系列》的实战篇,旨在快速上手k8s。如没有阅读过k8s相关理论的朋友,可以先阅读理论篇。
1. 实践环境
k8s 的意义在于分布式大规模容器编排,所以如果我们想要在实际中发挥它的最大价值,至少也得需要 3 台机器。其中一台是主节点,剩余两台是工作节点。当然,也可以通过虚拟机中创建三个操作系统来实践。但这样操作还是很繁琐,其实在学习中,有更方便的办法进行。
- minikube
能让你在本地运行 Kubernetes。 minikube 在你本地的个人计算机(包括 Windows、macOS 和 Linux PC)运行一个单节点的 Kubernetes 集群,以便你来尝试 Kubernetes 或者开展每天的开发工作。 - Kind
另一个Kubernetes SIGs项目,但与minikube相比有很大不同。顾名思义,它将集群移动到Docker容器中。与生成VM相比,这将显著加快启动速度。 - Docker Desktop
在Windows、Mac中常用的Docker Desktop 中也内置了一个 k8s 功能,只需要在设置中即可打开使用。
生产环境上的集群安装和配置不建议使用 kind 或者 minikube。本文采用 minikube 来开展,使用其他的环境其实并没有太大区别。minikube的安装可以查阅官网,根据自身不同的操作系统进行安装。minikube 是可以选择依赖于容器还是本机VM:
所以我们可以选择使用 Docker 来当做 minikube 运行的地方,命令:
minikube start --driver='docker’
# 如果你在Docker Desktop版本中使用,建议将 Docke Engine 切换为 Linux的版本
docker context ls
docker context use default
2. 配置
在 k8s 中的核心思想就是:声明式无状态。
所以当我们想通过 API 或 CLI 和 k8s 中主节点中的 API Server 进行通讯的时候,必须采取一种格式。而 CLI 是使用 YAML 格式来进行的, YAML 对于后台开发者来说并不陌生,Spring 中的配置文件也是这个格式。k8s 的 YAML 声明文件分为三个部分:1)metadata;2)specification;3)status。
细心地朋友会发现,第三个 status 好像并没有在文件中声明。这是因为它是由 k8s 自动生成编辑的。它的主要作用就是,时刻将容器的现有状态(status)与声明状态(specification)相比较,如果发现有区别,则会向声明状态所靠拢。
比如这里在声明文件中是要两个 Nginx,但实际运行中发现只有一个,k8s 发现后会主动的再创建一个让两者相匹配。status 实际是由 etcd 进行维护的。
3. 实例
这个实例是一个 Node 应用程序,通过访问MongoDB进行数据访问,部署方式如下所示:
所涉及到的技术点为:
- ConfigMap:MongoDB 连接信息
- Secret:MongoDB 用户名及密码
- Deployment & Service :应用组合及服务
3.1 MongoDB
首先创建 ConfigMap,k8s作为一个工具类的产品,其实可以直接仿照官网的例子来去改写。
将官网的例子复制下来,改写成如下形式:
apiVersion: v1
kind: ConfigMap
metadata:
name: mongo-config
data:
mongo-url: mongo-service
然后创建 Secret,这里需要注意的是,Secret 默认采用了Opaque 的加密方式。我们的用户名和密码需要通过 base64 加密后,粘贴上去。
apiVersion: v1
kind: Secret
metadata:
name: mongo-secret
type: Opaque
data:
mongo-user: bW9uZ291c2Vy
mongo-password: bW9uZ29wYXNzd29yZA==
最后,我们来声明 Deployment & Service,这两个可以单独写,但也可以写在一起:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongo-deployment
labels:
app: mongo
spec:
replicas: 1
selector:
matchLabels:
app: mongo
template:
metadata:
labels:
app: mongo
spec:
containers:
- name: mongodb
image: mongo:5.0
ports:
- containerPort: 27017
env:
- name: MONGO_INITDB_ROOT_USERNAME
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-user
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-password
---
apiVersion: v1
kind: Service
metadata:
name: mongo-service
spec:
selector:
app: mongo
ports:
- protocol: TCP
port: 27017
targetPort: 27017
其中的 template
我们第一次见到,它是为了声明 Pod 的,内部也有自己的元数据(metadata)和声明(specification)。这里面最为重要的就是声明中的容器(containers),其实可以理解为 docker-compose 中声明的 image 信息。
labels
是一个标签,k8s 可以为任何组件指定一个标签,可以作为一个标识符。比如 Pod 的名字是变化莫测,就可以使用标签(labels)来快速识别和寻找特定的组件。
YMAL 语法中,使用---
三个破折号来区分多个配置文件,所以我们使用破折号分割后,又声明了 Service。其中targetPort
为 Pod 中声明的端口,port
则可以任意指定未使用的端口。
3.2 Application
如法炮制,我们来声明部署应用部分。webapp.yaml如下所示:
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp-deployment
labels:
app: webapp
spec:
replicas: 1
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: nanajanashia/k8s-demo-app:v1.0
ports:
- containerPort: 3000
env:
- name: USER_NAME
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-user
- name: USER_PWD
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-password
- name: DB_URL
valueFrom:
configMapKeyRef:
name: mongo-config
key: mongo-url
---
apiVersion: v1
kind: Service
metadata:
name: webapp-service
spec:
type: NodePort
selector:
app: webapp
ports:
- protocol: TCP
port: 3000
targetPort: 3000
nodePort: 30100
其中,我们在 APP 的 Service 中声明了 NodePort
,它的作用旨在让外部浏览器访问。nodePort则为该 k8s 节点中 ip 所绑定的端口,只是它会有端口范围的限制。
4. 运行
将 YAML 文件写好后,就可以通过 Kubectl 告诉 k8s 集群,我们要这些服务组件。首先创建ConfigMap、Securit:
kubectl apply -f mongo-config.yaml
kubectl apply -f mongo-secret.yaml
然后创建MongoDB 和 APP应用:
kubectl apply -f mongo.yaml
kubectl apply -f webapp.yaml
执行kubectl get all
查看当前组件状态:
这里只能看到我们的Deployment、Service、Pod,但配置文件需要单独的命令查询:
kubectl get configmap
kubectl get secret
如果想查看该组件的详细信息,则可以使用该命令:
kubectl describe service webapp-service
在Docker中我们经常查看容器的Log,在 k8s 中查看 pod 日志的命令:
kubectl logs pod名称 -f
总之,kubectl 作为 k8s 最强大的交互工具,它所含的命令集非常多,我们也很难全部记住。就像Linux命令一样,善用-- help
~
最后,我们来访问一下这个 k8s 所部署的应用,查询minikube的ip地址:
可以看到minikube的ip是192.168.64.26
,直接访问:
5. 总结
本文我们通过组合理论篇所学习到的组件,通过一个 Node.js 网页应用连接 MongoDB 的例子,实现了在 k8s 中部署使用。虽然在本机环境下用 minikube 会显得比 Docker Compose 要麻烦的多,但只要我们上了集群,就可以凸显出 k8s 的强大之处了。