Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

迁移传统应用到 Kubernetes #50

Open
lqshow opened this issue Dec 9, 2018 · 0 comments
Open

迁移传统应用到 Kubernetes #50

lqshow opened this issue Dec 9, 2018 · 0 comments
Labels

Comments

@lqshow
Copy link
Owner

lqshow commented Dec 9, 2018

Overview

当前 kubernetes 盛行,相信大家对如何将现有的传统应用迁移到 kubernetes 中比较关心。

改造一般涉及以下几个方面

  1. 应用程序容器化
  2. 配置文件与代码解耦,将配置信息作为 ConfigMap 资源注入到 kubernetes 中
  3. 把日志当做事件流
  4. 网络访问

Containerize your application

首选需要将应用容器化,使用 Docker 定义一个包含安装步骤的 Dockerfile 文件,最后构建镜像。

Configuration files

使用 ConfigMap 来将配置和代码解耦, 在 Kubernetes 中通过 ConfigMap 资源将应用的配置文件加载到集群中。

kubernetes 提供两种方式将 ConfigMap 注入到应用程序。

  1. 环境变量
  2. 存储卷(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

优点:支持热更新

  1. 挂载文件

    比如项目不同目录下有两个配置文件需要挂载

    • /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
    ...
  2. 挂载目录

    • 如果一个目录下的文件都是需要配置的,通过挂载整个目录的方式来实现

    • 生成 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

  1. 日志应该是 事件流 的汇总,将所有运行中进程和后端服务的输出流按照时间顺序收集起来。日志最原始的格式是一个事件一行。
  2. 应用本身不应该考虑存储自己的输出流。这种方式难以维护管理,运维人员不可能一一去了解每个应用,将日志目录挂载出来。
  3. 应用容器化后的日志默认会保存在宿主机的 /var/lib/docker/containers/{{. 容器 ID}}/{{. 容器 ID}}-json.log 文件里,这个目录正是类似 LogplexFluentd 等开源工具搜集的目标。

kubernets 容器集群对日志收集的解决方案详见: Kubernetes Log Analysis with Fluentd, Elasticsearch and Kibana

Networking

  1. 一个Pod一个IP,Pod内的容器之间通信,直接通过 localhost 访问。
  2. 集群内访问走Service
    • <自定义的访问方式名称>.<工作负载所在命名空间> (例如:redis-svc.default)

    • <自定义的访问方式名称>.<工作负载所在命名空间>.svc.cluster.local(例如:redis-svc.default.svc.cluster.local)

  3. 集群外访问走Ingress

Other

  1. 持久化的数据写入到分布式存储卷
  2. 控制输出到stdout和stderr的日志写入量
  3. 使用 Secret 来保护API Key这样的隐私数据
  4. 使用 liveness 和 readiness 探针来实现健康检查

Reference

@lqshow lqshow added the k8s label Dec 9, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant