迁移传统应用到 Kubernetes
Opened this issue · 0 comments
lqshow commented
Overview
当前 kubernetes 盛行,相信大家对如何将现有的传统应用迁移到 kubernetes 中比较关心。
改造一般涉及以下几个方面
- 应用程序容器化
- 配置文件与代码解耦,将配置信息作为 ConfigMap 资源注入到 kubernetes 中
- 把日志当做事件流
- 网络访问
Containerize your application
首选需要将应用容器化,使用 Docker 定义一个包含安装步骤的 Dockerfile 文件,最后构建镜像。
Configuration files
使用 ConfigMap 来将配置和代码解耦, 在 Kubernetes 中通过 ConfigMap 资源将应用的配置文件加载到集群中。
kubernetes 提供两种方式将 ConfigMap 注入到应用程序。
- 环境变量
- 存储卷(volume)
Store config in the environment (The Twelve Factors)
12-Factor推荐将应用的配置存储于 环境变量 中( env vars, env )。环境变量可以非常方便地在不同的部署间做修改,却不动一行代码。
缺点:不支持热更新
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: dev
data:
NODE_ENV: production
DEV_MODE: "false"
PORT: "3000"
ENABLE_SWAGGER_UI: "true"
---
apiVersion: v1
kind: Pod
...
spec:
containers:
- name: app-container
# 将 ConfigMap 中的所有键-值对配置为容器环境变量
envFrom:
- configMapRef:
name: app-config
env:
# 为容器定义环境变量
- name: ENV_NAME
value: "ENV_VALUE"
# 通过环境变量向容器公开Pod信息
- name: SPARK_DRIVER_HOST
valueFrom:
fieldRef:
fieldPath: status.hostIP
# 将 ConfigMap 中指定的键配置到环境变量中
- name: NODE_ENV
valueFrom:
configMapKeyRef:
name: app-config
key: NODE_ENV
...
Use config in volume
用作 Pod 启动时挂载的 volume
优点:支持热更新
-
挂载文件
比如项目不同目录下有两个配置文件需要挂载
- /project/service/config.py
- /project/deploy/supervisord.conf
apiVersion: v1 kind: Pod ... spec: containers: - name: app-container volumeMounts: - name: app-config-volume mountPath: /project/service/config.py subPath: config.py - name: app-config-volume mountPath: /project/deploy/supervisord.conf subPath: supervisord.conf volumes: - name: app-config-volume configMap: name: app-config ...
-
挂载目录
-
如果一个目录下的文件都是需要配置的,通过挂载整个目录的方式来实现
-
生成 configmap
kubectl create configmap hadoop-conf --from-file=conf/hadoop-conf
-
需要注意的是,挂载目录会抹掉目录下原有的文件
apiVersion: v1 kind: Pod ... spec: containers: - name: app-container volumeMounts: - name: hadoop-config-volume mountPath: /etc/hadoop/conf volumes: - name: hadoop-config-volume configMap: defaultMode: 0744 name: hadoop-conf ...
-
Logs
日志输出到 stdout 和 stderr
- 日志应该是 事件流 的汇总,将所有运行中进程和后端服务的输出流按照时间顺序收集起来。日志最原始的格式是一个事件一行。
- 应用本身不应该考虑存储自己的输出流。这种方式难以维护管理,运维人员不可能一一去了解每个应用,将日志目录挂载出来。
- 应用容器化后的日志默认会保存在宿主机的 /var/lib/docker/containers/{{. 容器 ID}}/{{. 容器 ID}}-json.log 文件里,这个目录正是类似 Logplex 和 Fluentd 等开源工具搜集的目标。
kubernets 容器集群对日志收集的解决方案详见: Kubernetes Log Analysis with Fluentd, Elasticsearch and Kibana
Networking
- 一个Pod一个IP,Pod内的容器之间通信,直接通过 localhost 访问。
- 集群内访问走Service
-
<自定义的访问方式名称>.<工作负载所在命名空间> (例如:redis-svc.default)
-
<自定义的访问方式名称>.<工作负载所在命名空间>.svc.cluster.local(例如:redis-svc.default.svc.cluster.local)
-
- 集群外访问走Ingress
Other
- 持久化的数据写入到分布式存储卷
- 控制输出到stdout和stderr的日志写入量
- 使用 Secret 来保护API Key这样的隐私数据
- 使用 liveness 和 readiness 探针来实现健康检查