更多技术干货请戳:听云博客

听云线上使用k8s已经有一段时间了,下面对一些听云使用过程中的问题进行一些梳理,包括架构设计,安装部署和后期维护。 目录结构如下:

下面进入正题:

我们以听云系统的一个报表系统为例来详细进行说明:

1.系统架构

该应用属于Java Web报表类应用,部署在Ucloud云上。系统架构如下:

这是典型web应用的系统架构,在听云内部大部分应用都是此形式,对于并发量不高的业务均可参考此文档。

基本规范:

1.configmap用来管理配置文件

2.deployment用来编排应用,进行升级回滚等

3.pv用于共享存储,后端为glustefsr和nfs

4.daemonset 用于变更不频繁,一台机器一个docker的应用

5.nginx+ingress来做前端负载均衡和自动发现

6.对并发要求很高的应用可以尝试用host模式,不用service做负载均衡

2.部署说明

参考架构图,我们需要nginx-ingress-controller 和 应用的Docker。下面分别进行详细说明。

2.1 准备基础Docker镜像

听云先进行应用的部署,规范是每个项目一个Docker镜像,版本号为jenkins构建的版本号。

为了规范日后上线。我们需要按层次构建镜像,方便日后使用。

构建基础镜像

由于听云的项目中绝大大部分为Java项目,为了精简Docke镜像大小,基础镜像我们没有采用Centos或者Ubuntu,而是采用了alpine,该镜像只有4MB。

Dockerfile内容如下:

  1. FROM registry.tingyun.com/docker.io/alpine
  2. MAINTAINER netop "netop@tingyun.com"
  3. ENV REFRESHED_AT 2016-03-18
  4. RUN apk add --no-cache --update-cache bash
  5. ENV GLIBC_PKG_VERSION=2.23-r1
  6. RUN apk add --no-cache --update-cache curl ca-certificates bash && \
  7.   curl -Lo /etc/apk/keys/andyshinn.rsa.pub "https://github.com/andyshinn/alpine-pkg-glibc/releases/download/${GLIBC_PKG_VERSION}/andyshinn.rsa.pub" && \
  8.   curl -Lo glibc-${GLIBC_PKG_VERSION}.apk "https://github.com/andyshinn/alpine-pkg-glibc/releases/download/${GLIBC_PKG_VERSION}/glibc-${GLIBC_PKG_VERSION}.apk" && \
  9.   curl -Lo glibc-bin-${GLIBC_PKG_VERSION}.apk "https://github.com/andyshinn/alpine-pkg-glibc/releases/download/${GLIBC_PKG_VERSION}/glibc-bin-${GLIBC_PKG_VERSION}.apk" && \
  10.   curl -Lo glibc-i18n-${GLIBC_PKG_VERSION}.apk "https://github.com/andyshinn/alpine-pkg-glibc/releases/download/${GLIBC_PKG_VERSION}/glibc-i18n-${GLIBC_PKG_VERSION}.apk" && \
  11.   apk add glibc-${GLIBC_PKG_VERSION}.apk glibc-bin-${GLIBC_PKG_VERSION}.apk glibc-i18n-${GLIBC_PKG_VERSION}.apk
  12. add Shanghai /etc/localtime
  13. ENV LANG en_US.UTF-8

构建镜像

docker build -t registry.tingyun.com/common/alpine .

push 到仓库中

docker push registry.tingyun.com/common/alpine

构建JDK镜像

Dockerfile内容如下:

  1. FROM registry.tingyun.com/common/alpine
  2. MAINTAINER netop "netop@tingyun.com"
  3. ENV REFRESHED_AT 2016-03-14
  4. ADD  jdk1.7.0_45.tar.gz /opt
  5. ENV LANG en_US.UTF-8
  6. ENV JAVA_VERSION  1.7.0_45
  7. ENV JAVA_HOME  /opt/jdk1.7.0_45
  8. ENV PATH $JAVA_HOME/bin:$PATH

该镜像只添加了一个jdk包,我们build它

  1. docker build -t registry.tingyun.com/common/jdk7 .
  2. push 到仓库中
  3. docker push registry.tingyun.com/common/jdk7
  4. 构建tomcat镜像
  5. Docker内容如下:
  6. FROM registry.tingyun.com/common/jdk7
  7. MAINTAINER netop "netop@tingyun.com"
  8. ENV REFRESHED_AT 2016-03-14
  9. ADD  apache-tomcat-6.0.45.tar.gz /opt
  10. RUN ln -/opt/apache-tomcat-6.0.45 /opt/apache-tomcat
  11. ADD server.xml /opt/apache-tomcat/conf/server.xml
  12. ENV CATALINA_HOME /opt/apache-tomcat
  13. ENV PATH $CATALINA_HOME/bin:$PATH
  14. ENV TOMCAT_MAJOR 6
  15. ENV TOMCAT_VERSION 6.0.45
  16. ENV JAVA_OPTS   -server -Djava.library.path=/opt/apache-tomcat/lib -XX:+UseConcMarkSweepGC  -XX:+PrintGCDetails  -XX:+PrintGCDateStamps -Xloggc:/opt/apache-tomcat/logs/gc.log
  17. WORKDIR $CATALINA_HOME
  18. ENV TINGYUN_APP_NAME="Java Application" \
  19. TINGYUN_LICENSE_KEY=f451bae910b4c3f4473e0c83d2113742
  20. RUN curl -/tingyun-agent-java-latest.zip  http://download.tingyun.com/agent/java/latest/tingyun-agent-java-latest.zip
  21. RUN mkdir /opt/tingyun_agent;unzip /tingyun-agent-java-latest.zip -/opt/tingyun_agent
  22. RUN rm /tingyun-agent-java-latest.zip -rf
  23. ENV CONNECTOR='<Connector port="8080" maxHttpHeaderSize="8192"    maxThreads="300" minSpareThreads="25" maxSpareThreads="300"      enableLookups="false" redirectPort="8443" acceptCount="100"     connectionTimeout="20000" disableUploadTimeout="true" />'
  24. ENV CONTEXT=""
  25. ENV ACCESS_LOG="<Valve className=\"org.apache.catalina.valves.AccessLogValve\" directory=\"logs\"               prefix=\"access_log.\" suffix=\".log\"               pattern='%{X-Request-Start}i %{X-Queue-Start}i  %{X-Forwarded-For}i %h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-Agent}i\" %T' resolveHosts=\"false\"/>"
  26. ADD run.sh /run.sh
  27. EXPOSE 8080
  28. CMD ["/run.sh"]

run.sh内容如下:

  1. #!/bin/bash
  2. TINGYUN_AGENT_PATH="/opt/tingyun_agent/tingyun/tingyun.properties"
  3. TOMCAT_CONF_PATH="/opt/apache-tomcat/conf/server.xml"
  4. sed -"s/Java Application/$TINGYUN_APP_NAME/"  $TINGYUN_AGENT_PATH
  5. sed -"s/<%=license_key%>/$TINGYUN_LICENSE_KEY/"  $TINGYUN_AGENT_PATH
  6. sed -"s#CONNECTOR#$CONNECTOR#"  $TOMCAT_CONF_PATH
  7. sed -"s#CONTEXT#$CONTEXT#"  $TOMCAT_CONF_PATH
  8. sed -"s#ACCESS_LOG#$ACCESS_LOG#"  $TOMCAT_CONF_PATH
  9. catalina.sh run

server.xml内容如下:

此处不贴文本了,内容为标准的server.xml 做了字符串替换。

此处将Connector注释掉,改为CONNECTOR

此处将access_log和 context部分 删掉 ,替换为图片中字符串。

我们进行build

  1. docker build -t registry.tingyun.com/common/jdk7-tomcat6 .
  2. docker push registry.tingyun.com/common/jdk7-tomcat6

查看该Dockerfile会注意到我们将听云Server探针进行了嵌入。是否启用探针我们会在后续的k8s配置文件进行控制,因为应用在k8s上跑具体跑在哪台机器上是不固定的,原有的zabbix jmx监控无法满足需求,我们利用听云Server来进行监控。

2.2 利用jenkins构建应用镜像

按照上文方式,准备好相关的基础镜像,如jdk7-tomcat6  jdk8-tomcat8等。

下边利用jenkins来构建应用镜像。

由于听云的jenkins本身操作系统版本太低,无法使用docker, 所以要选一台部署了docker的机器作为build机,通过ssh的方式来进行build。(此处视build的数量考虑是否需要利用jenkins slave的方式来进行build。简单测试过mesos 作为slave的方式,流程跑通,没有深测)

听云工程师们是通过写个通用的build脚本,用来build应用的镜像。

vi build_tomcat_docker.sh

  1. #!/bin/bash
  2. FUN_DIR=$1
  3. APP_DIR=$2
  4. PACK_NAME=$3
  5. PACK_MD5=$4
  6. APP_NAME=$5
  7. BASE_IMG=$6
  8. FINISH_IMG=$7
  9. BUILD_NUM=$8
  10. if [ -"/data/tmp" ];then
  11.     rm /data/tmp/* -rf 
  12. else
  13.     mkdir /data/tmp -p
  14. fi
  15. if [ ! -n "$1" ] || [ ! -n "$2" ] || [ ! -n "$3" ] || [ ! -n "$4" ] || [ ! -n "$5" ] || [ ! -n "$6" ] || [ ! -n "$7" ] || [ ! -n "$8" ] ;then
  16.     echo "build error,please input  vars"
  17. else
  18.     PACK_URL=http://192.168.1.16/tingyun/${PACK_NAME}
  19.     MD5_URL=http://192.168.1.16/tingyun/${PACK_MD5}
  20.     /usr/bin/curl -o /data/tmp/${PACK_NAME} $PACK_URL
  21.     /usr/bin/curl -o /data/tmp/${PACK_MD5} $MD5_URL
  22.     MD5_ORIGN=`/usr/bin/curl $MD5_URL | awk '{print $1}'`
  23.     MD5_WGET=`cat /data/tmp/${PACK_MD5} | awk '{print $1}'`
  24.     if [ "$MD5_ORIGN" = "$MD5_WGET" ]; then
  25.         echo "md5sum sucess"
  26.         /usr/bin/unzip /data/tmp/${PACK_NAME} -d  /data/tmp/${APP_NAME}
  27.         ADD_FILE="ADD ${APP_NAME} /opt/${FUN_DIR}/${APP_DIR}/${APP_NAME}"
  28.         cp /data/build/Dockerfile_template /data/tmp/Dockerfile 
  29.         sed -i "s#BASE_IMG#$BASE_IMG#" /data/tmp/Dockerfile
  30.         sed -i "s#ADD_FILE#$ADD_FILE#" /data/tmp/Dockerfile
  31.         docker build --no-cache=true -t  ${FINISH_IMG}:${BUILD_NUM} /data/tmp/
  32.         docker push ${FINISH_IMG}:${BUILD_NUM}
  33.         echo  "build img is ${FINISH_IMG}:${BUILD_NUM}"
  34.     else
  35.         echo "md5sum failed"
  36.     fi  
  37. fi

vim Dockerfile_template

  1. FROM BASE_IMG
  2. MAINTAINER netop "netop@tingyun.com"
  3. ENV REFRESHED_AT 2016-02-18
  4. ADD_FILE

如果Java探针有更新,需要重新build下前边的基础镜像,在build机器上重新pull镜像后再构建应用镜像。

打开jenkins该项目,标红处添加该行,用于记录要升级的镜像和build号

注意命名规范:中间列是产品线。

添加下列用于构建镜像的机器

用jenkins build

build 成功。

2.3 k8s配置应用

镜像已经准备好了,接下来配置应用

2.3.1 配置configmap

应用的配置文件统一通过conigmap来管理

  1. mkdir configmap
  2. cd configmap
  3. ls -al

配置文件放到该目录下

  1. vim create_configmap.sh
  2. kubectl create configmap report-app-beta-config --from-file=configmap
  3. vim reload_configmap.sh 
  4. kubectl delete configmap report-app-beta-config
  5. kubectl create configmap report-app-beta-config --from-file=configmap

2.3.2 配置deployment

下面配置deployment

vim deployment.yaml

  1. apiVersion: extensions/v1beta1
  2. kind: Deployment
  3. metadata:
  4.   name: report-app-beta     #应用名称
  5. spec:
  6.   replicas: 10               #启动副本个数
  7.   minReadySeconds: 60     #滚动升级时60s后认为该pod就绪
  8.   strategy:
  9.     rollingUpdate:
  10.       maxSurge: 50%      #滚动升级时会先启动20%的pod
  11.   template:
  12.     metadata:
  13.       labels:
  14.         name: report-app-beta
  15.     spec:
  16.       volumes:
  17.       - name: config-volume               #configmap的挂载点
  18.         configMap:                      
  19.           name: report-app-beta-config
  20.       - name: pv-mapping-files             #pvc的挂载点
  21.         persistentVolumeClaim:
  22.           claimName: mapping-files
  23.       nodeSelector:                     #选择调度的node节点
  24.         zone: low
  25. #      hostNetwork: true
  26.       containers:
  27.       - name: report-app-beta
  28. #        livenessProbe:                  #监控
  29. #          httpGet:
  30. #            path: /healthCheck
  31. #            port: 8080
  32. #          initialDelaySeconds: 30
  33. #          timeoutSeconds: 10
  34.         image: registry.tingyun.com/app/report-app:1
  35.         command:             #小hack,为了不重打镜像,不执行默认的命令
  36.           - sh
  37.           - "-c"
  38.           - ln -/opt/mapping_files/puuid /bin/puuid && /run.sh
  39.            env:                               #环境变量
  40.         - name: TINGYUN_APP_NAME
  41.           value: report-app
  42.         - name: TINGYUN_LICENSE_KEY
  43.           value: f451bae910b4c3f4473e0c83d2113742
  44.         - name: JAVA_OPTS
  45.           value: "-server -Djava.library.path=/opt/apache-tomcat/lib -Xms512m -Xmx2048m -XX:NewRatio=4 -Xss1024k  -XX:PermSize=64M -XX:MaxPermSize=256M   -XX:+UseConcMarkSweepGC  -XX:+PrintGCDetails  -XX:+PrintGCDateStamps -Xloggc:/opt/apache-tomcat/logs/gc.log -javaagent:/opt/tingyun_agent/tingyun/tingyun-agent-java.jar -Duser.language=zh -Duser.region=CN -Duser.timezone=GMT+08 -DappName=report-app"
  46.         - name: CONNECTOR
  47.           value: '<Connector port="8080" maxHttpHeaderSize="8192"    maxThreads="300" minSpareThreads="25" maxSpareThreads="300"      enableLookups="false" redirectPort="8443" acceptCount="100"     connectionTimeout="20000" disableUploadTimeout="true" /> '
  48.         - name: CONTEXT
  49.           value: '<Context path="/mobile" reloadable="false" allowLinking="true"  docBase="/opt/tingyun/report-app/webapp/" workDir="/opt/tingyun/report-app/work/"/>   '
  50.         ports:
  51.          - containerPort: 8080
  52.         volumeMounts:                     #上边的挂载点挂载到容器中的路径
  53.         - name: config-volume                           
  54.           mountPath: /opt/tingyun/report-app/conf      
  55.         - name: pv-mapping-files
  56.           mountPath: /opt/mapping_files

kubectl create -f deployment.yaml

kuectl get pods

看pod已经起来了

2.3.3 配置Service

下面配置service

vim service.yaml

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4.   name: report-app-beta
  5.   labels:
  6.     name: report-app-beta
  7. spec:
  8.  # sessionAffinity: ClientIP   #在基于新的nginx-ingress-controller已经不需要配置该项,session绑定在nginx处配置
  9.   ports:
  10.     - port: 8080
  11.   selector:
  12.     name: report-app-beta

kubectl create -f service.yaml

kubectl get service

2.3.4 配置ingress

下面配置ingress

  1. vim ingress.yaml
  2. apiVersion: extensions/v1beta1
  3. kind: Ingress
  4. metadata:
  5.   name: report-app-beta
  6. spec:
  7.   rules:
  8.   - host: report-beta.tingyun.com     #域名
  9.     http:
  10.       paths:
  11.       - path: /mobile               #访问路径
  12.         backend: 
  13.           serviceName: report-app-beta    #service名称
  14.           servicePort: 8080              #service端口

kubectl create -f ingress.yaml

kubect get ingress

2.4 创建nginx-ingress-controller

nginx-ingress-controller  需要监听宿主机的80端口,固定在某几台机器上,为此需要给相关node 定义标签。

kubectl label nodes ucd-ty-k8s-node-001.ucd.tingyun.com role=nginx-lb

kubectl get nodes --show-labels

创建configmap

vim nginx.tmpl

该文件可以去github上下载

https://github.com/kubernetes/contrib/blob/master/ingress/controllers/nginx/nginx.tmpl

kubectl create configmap nginx-template --from-file=nginx.tmpl=nginx.tmpl

为了将为所有在nginx后的项目开启session保持,同时听云的开发工程师要打开后端监控页面,需要修改两个地方。

这里暂时先改为无论如何都启用session保持

这里直接启用traffic_status

vim rc.yaml

该文件可以去github下载

https://github.com/kubernetes/contrib/blob/master/ingress/controllers/nginx/examples/full/rc-full.yaml

kubectl create rc.yaml

查看nginx_status界面

http://10.10.228.175:8080/nginx_status

接下来即可访问该项目

原文链接:http://blog.tingyun.com/web/article/detail/825

kubernetes听云实战发布版的更多相关文章

  1. 利用听云Server和听云Network实测Kubernetes和Mesos在高并发下的网络性能

    文章出自:听云博客 随着公司业务的不断增长,我们的应用数量也有了爆发式增长.伴随着应用爆发式的增长,管理的难度也随之加大.如何在业务爆发增长的同时快速完成扩容成了很大的挑战.Docker的横空出世恰巧 ...

  2. 阿里云重磅发布RDS for SQL Server AlwaysOn集群版

    2018年双十一刚过,阿里云数据库发布RDS for SQL Server AlwaysOn集群版,这是业界除微软云SQL Database外,首家云计算公司基于SQL Server最新AlwaysO ...

  3. Kubernetes 应用部署实战

    Kubernetes 应用部署实战 2018-08-08 19:44:56 wuxiangping2017 阅读数 3084  收藏 更多 分类专栏: linux运维与架构师   简介 伙计们,请搬好 ...

  4. 【活动】写#听云#原创博文 赢取iPhone 6超级大奖

    移动应用的使用量和重要性与日俱增,用户体验的要求也越来越高.与桌面程序相比,移动应用耗电小,速度慢,但手机用户却希望享受到与桌面程序同样的加载速度.那么如何发现移动应用的性能黑洞,优化移动应用性能,这 ...

  5. 第八篇 :微信公众平台开发实战Java版之如何网页授权获取用户基本信息

    第一部分:微信授权获取基本信息的介绍 我们首先来看看官方的文档怎么说: 如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑. 关于网页授权回调域 ...

  6. 第七篇 :微信公众平台开发实战Java版之如何获取微信用户基本信息

    在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的.对于不同公众号,同一用户的openid不同). 公众号可通过本接口来根据O ...

  7. 第六篇 :微信公众平台开发实战Java版之如何自定义微信公众号菜单

    我们来了解一下 自定义菜单创建接口: http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_to ...

  8. 第五篇 :微信公众平台开发实战Java版之如何获取公众号的access_token以及缓存access_token

    一.access_token简介 为了使第三方开发者能够为用户提供更多更有价值的个性化服务,微信公众平台 开放了许多接口,包括自定义菜单接口.客服接口.获取用户信息接口.用户分组接口.群发接口等, 开 ...

  9. 第四篇 :微信公众平台开发实战Java版之完成消息接受与相应以及消息的处理

    温馨提示: 这篇文章是依赖前几篇的文章的. 第一篇:微信公众平台开发实战之了解微信公众平台基础知识以及资料准备 第二篇 :微信公众平台开发实战之开启开发者模式,接入微信公众平台开发 第三篇 :微信公众 ...

随机推荐

  1. Javascript动画效果(四)

    Javascript动画效果(四) 前面我们自己写了一个小小的关于js动画的插件,下面我们来使用之前的框架来完成我们想要的动画效果.我们经常在淘宝网中看到,鼠标经过某一图片时,该图片有从上滚出而又从下 ...

  2. 用SQL语句查找包含有某个关键字的存储过程、触发器、函数等(仅适用MS SQL SERVER)

    第一种方法:利用系统表进行查询   --将text替换成你要查找的内容  select name  from sysobjects o, syscomments s  where o.id = s.i ...

  3. 【转载】谷歌酝酿将苹果Swift作为安卓APP主要开发语言

    TNW中文站 4月8日报道 安卓操作系统的软件开发语言是Java,而在过去几年中,有关Java的版权,谷歌(微博)和甲骨文之间发生了长期的诉讼.最新外媒消息称,谷歌正在考虑将苹果开发的Swift作为未 ...

  4. 关于MVC中模型model的验证问题

    今天在做项目练习的时候发现,MVC中使用自带的模型验证时会提前显示在界面上,比如下面所示: 这是什么原因了,是因为我在表示get请求的action里面返回了其界面所显示使用的model,我们知道mvc ...

  5. ab网站压力测试

    ab网站压力测试命令的参数.输出结果的中文注解    permalink 以前安装好APACHE总是不知道该如何测试APACHE的性能,现在总算找到一个测试工具了.就是APACHE自带的测试工具AB( ...

  6. 【C#进阶系列】20 异常和状态管理

    异常就是指成员没有完成它的名称所宣示的行动. public class Girl { public string Name { get; set; } } public class Troy{ Gir ...

  7. jquery基本选择器id

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. hibernate----N-N--(人与地点)

    package com.ij34.dao; import java.util.HashSet; import java.util.Set; import javax.persistence.*; @E ...

  9. 【Linux_Fedora_应用系列】_4_安装chrome浏览器

    在前面一篇文章中,我们讨论了在Linux Fedora 14下安装WMV解码器:[Linux_Fedora_应用系列]_3_如何利用Smplayer播放WMV格式的文件 在文章中介绍的方法同样适合FC ...

  10. 从零开始学Python04作业源码:模拟ATM电子银行(仅供参考)

    bin目录:程序启动入口 ATM_start.py: #!/usr/bin/python # -*- coding: utf-8 -*- # 模拟ATM电子银行+登录账户权限控制+管理员管理模块 # ...