数据专栏

智能大数据搬运工,你想要的我们都有

科技资讯:

科技学院:

科技百科:

科技书籍:

网站大全:

软件大全:

「深度学习福利」大神带你进阶工程师,立即查看>>>
SVN简介
SVN是Subversion的简称,是一个开放源代码的版本控制系统,相较于RCS、CVS,它采用了分支管理系统,它的设计目标就是取代CVS。互联网上很多版本控制服务已从CVS迁移到Subversion。说得简单一点SVN就是用于多个人共同开发同一个项目,共用资源的目的。
SVN官网
SVN(subversion) 是版本管理工具,是CVS的接班人。目前,绝大多数开源软件都使用svn作为代码版本管理软件。 作为一个运维人员安装和配置SVN服务器和客户端是必须要掌握的内容。

运行方式

svn服务器有2种运行方式: 独立服务器 和借助 apache 运行。两种方式各有利弊,用户可以自行选择。
数据存储

svn存储版本数据也有2种方式: BDB (一种 事务 安全型表类型)和 FSFS (一种不需要数据库的 存储系统 )。因为BDB方式在服务器中断时,有可能锁住数据,所以还是FSFS方式更安全一点。
优缺点

1 存储类型格式
CVS是个基于RCS文件的 版本控制 系统 。每个CVS文件都不过是普通的文件,加上一些额外信息。这些文件会简单的重复本地文件的树结构。因此,不必担心有什么数据损失,如果必要的话可以手工修改RCS文件。
SVN是基于关系数据库的(BerkleyDB)或一系列二进制文件的(FS_FS)。一方面这解决了许多问题 (例如,并行读写共享文件)以及添加了许多新功能(例如运行时的事务特性。)。然而另一方面, 数据存储 由此变得不透明。
2 速度
CVS比较慢。
整体而言,由于架构实现的不同, SVN的确比CVS快很多。在网络上它只传输很少的信息并支持更多的离线模式的功能。但这也是有代价的。速度的代价就是巨大的存储( 完全备份 所有的工作文件)。
3 标志&分支
SVN采用标志和分支而抛弃了其他三件东西,实际上这意味着他们把这个概念替换为在档案库内部复制文件或目录以便保存日志。这样一来,无论标志创建还是分支创建都只是仓库内部的文件复制了。对分支而言:分支不过是在仓库内部的一个单独的目录而已了,不像早期还有些什么交错。对标志而言:已经不能对代码加标志了。在某种程度上说,SVN全文件编号补足了这个缺陷,SVN里整个仓库都有版本号,但不是针对单个文件。
4 元数据
CVS只允许存储文件。
SVN允许一个文件有任意多的可命名属性,功能十分完全。
5 文件类型
CVS最初是为文本文件存储而设计的。因此其他文件类型(二进制,统一码)文件的支持几乎没有,如需要的话则要有其他信息,并且客户端服务器端都要调整。
SVN会关心所有的文件类型,不需要你来手工操作。

常见版本控制软件:
Cvs 由于之前CVS编码的问题,现在大多数软件开发公司都使用SVN替代了CVS
Svn
git 分布式版本控制器

SVN 服务器运行模式:
模式1: svn服务器 监听: 3690 端口 访问: svn://IP
模式2: svn 服务器+ apache : 80 端口 访问: http://IP 今天要讲的
安装: svn服务器,apache, mod_dav_svn 软件包

svn服务器使用流程

实战:CentOS 6 上安装配置 svn server+apache
# yum install subversion httpd mod_dav_svn -y
mod_dav_svn 模块 : apache http 服务器的插件,可以让版本库通过http协议,在网站上展现。

创建版本库目录,并修改相应权限。
[root@localhsot ~]# mkdir /var/repos

创建两个项目仓库。 xuegod.cn和svn2
[root@localhsot ~]# svnadmin create /var/repos/xuegod.cn
[root@localhsot ~]# svnadmin create /var/repos/svn2
[root@localhsot ~]# ls /var/repos/xuegod.cn
conf db format hooks locks README.txt

[root @localhost conf]#ls /var/repos/xuegod.cn/conf
authz passwd svnserve.conf
# 注:用户权限配置我们使用apache的,这里暂时不用svn自带

启动:SVN服务器
[svn@localhsot conf]# svnserve -d -r /var/repos/
  -d表示以daemon方式(后台运行)运行
  -r /var/repos指定svn根目录是/var/repos

[svn@localhsot conf]# ps -axu | grep svn
Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ
root 6982 0.0 0.0 161476 1924 pts/2 S 18:09 0:00 su - svn
svn 6983 0.0 0.0 108392 1864 pts/2 S 18:09 0:00 -bash
svn 7262 0.0 0.0 182760 1056 ? Ss 18:26 0:00 svnserve -d -r /var/repos/

[svn@localhsot conf]# netstat -antup | grep 3690
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp 0 0 0.0.0.0: 3690 0.0.0.0:* LISTEN 7262/svnserve


svn服务器搭建流程:
1 、安装: yum install subversion httpd mod_dav_svn
2 、创建仓库存储代码: svnadmin create /var/repos/xuegod.cn
3 、启动svn服务器:svnserve -d -r /var/repos/

APACHE
第一步,查看apache支持subversion两个动态库有没有安装成功。
查看:
[root@localhost conf]# vim /etc/httpd/conf.d/subversion.conf #看到下面配置文件中两个模块相关信息,说明安装成功。
LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so

配置apache通过mod_dav_svn模块访问SVN服务器
[root@localhost ~]# vim /etc/httpd/conf.d/subversion.conf

DAV svn
SVNParentPath /var/repos
AuthType Basic
AuthName " SVN server of xuegod!"
AuthUserFile /home/svn/passwd
AuthzSVNAccessFile /home/svn/auth
Require valid-user

注释:
#apache 的虚拟目录。后期通过链接:http://192.168.1.63/svn 来访问两个仓库:xuegod和svn2
DAV svn
SVNParentPath /var/repos # 存放 两个仓库:xuegod和svn2的真实目录
AuthType Basic
AuthName " SVN server of xuegod!" #apache 认证时弹出的消息
AuthUserFile /home/svn/passwd # passwd 存储用户名和密码
AuthzSVNAccessFile /home/svn/auth # 存放用户的权限
Require valid-user


建立本地访问控制文件/home/svn/passwd,#后期通过httpd服务器访问svn时,会使用这个文件中的用户信息验证用户和密码

[root@localhsot ~]# mkdir /home/svn
[root@localhsot ~]# htpasswd -c /home/svn/passwd tube
# -c create , 创建/home/svn/passwd文件 。会提示你输入密码,默认是MD5加密
New password: 123456
Re-type new password:
Adding password for user tube

[root@localhost ~]# htpasswd /home/svn/passwd cd #后期再创建时,就不需要加-c参数,否则,会把之前添加到/home/svn/passwd中信息,全部覆盖。
New password: 123456
Re-type new password:123456
Adding password for user tree

查看用户名和密码:
[root@localhost ~]# cat /home/svn/passwd
cd:sjplr6rMtpN3E
tube:gZEcmDnMwFsMc
注:tube和cd两个用户的明文密码都一样,但是加完密码以后是不一样。

加密时: (密码+用户名 ) md5 -》 ll7IH3i5G0JfU

第四步,建立本地项目版本库,权限控制文件。
达到以下目标:
用户 仓库 权限
tube xuegod.cn ,svn2 rw
cd xuegod.cn rw

[root@localhost ~]# vim /home/svn/auth #写入以下内容
[/]
tube = rw
[xuegod.cn:/]
cd = rw

解释:
[/] # 这个表示在所有仓库的根目录下
tube = rw # 表示tube用户对所有仓库根目录下的软件版本库有rm权限
[xuegod.cn:/] # 这表示,仓库xuegod.cn的根目录下的访问权限
cd= rw # cd 用户对xuegod.cn仓库具有读和写权限

给目录权限
[root@localhost conf.d]# chmod 777 /var/repos/ -R

[root@localhost ~]# service httpd restart
svn 的访问地址是: http://192.168.10.64/svn/xuegod.cn
然后在浏览器上面,输入:192.168.168.140/svn
总结:配置apache+svn
1 、修改配置文件:vim /etc/httpd/conf.d/subversion.conf 让apache可以支持svn
2 、创建SVN用户和密码文件: /home/svn/passwd htpasswd
3 、创建SVN权限管理文件:/home/svn/auth
SVN 客户端使用说明
subversion windows 客户端TortoiseSVN配置:
http://tortoisesvn.net/about.zh.html

新一个文件夹:localhost
取出版本为0的数据:



上传代码:
随意保存一个网页,把网页源代码复制到目录localhost中,然后提交第一个网站代码:

在浏览器里输入:192.168.168.140/svn/localhost

在Linux下测试客户端:
[root@localhost ~]# svn checkout http://192.168.10.63/svn/xuegod.cn xuegod.cn
认证领域: SVN server of xuegod!
“root”的密码:
认证领域: SVN server of xuegod!
用户名: tube
“tube”的密码:
通过在“/root/.subversion/servers”中设置选项“store-plaintext-passwords”为“yes”或“no”,
来避免再次出现此警告

保存未加密的密码(yes/no)?no
A localhost .cn/salt主机地址密码.txt
A localhost .cn/新建虚机需知.txt
取出版本 1。
[root@localhost ~]# cd localhost/
[root@localhost localhost ]# ls
index.html TortoiseSVN - About_files TortoiseSVN - About.htm
云计算
2018-06-14 23:04:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
一、简介
Spring 官方网站本身使用Spring 框架开发,随着功能以及业务逻辑的日益复杂,应用伴随着大量的XML配置文件以及复杂的Bean依赖关系。
随着Spring 3.0的发布,Spring IO团队主键开始摆脱XML配置文件,并且在开发过程中大量使用“约定优先配置”(convention over configuration)的思想来摆脱Spring框架中各种复杂的配置,衍生了Java Config。
Spring Boot正是在这样的一个背景下被抽象出来的开发框架,它本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于Spring框架的应用程序。也就是说,它并不是用来替代Spring的解决方案,而是和Spring框架紧密结合用于提升Spring开发者体验的工具。同时它集成了大量常用的第三方库配置(例如Jackson, JDBC, Mongo, Redis, Mail等等),Spring Boot应用中这些第三方库几乎可以零配置的开箱即用(out-of-the-box),大部分的Spring Boot应用都只需要非常少量的配置代码,开发者能够更加专注于业务逻辑。
该项目旨在帮助开发者更容易地创建基于Spring的应用程序和服务,使得现有的和新的Spring开发者能够最快速地获得所需要的Spring功能。
Spring Boot不生成代码,且完全不需要XML配置。其主要目标如下:
- 为所有的Spring开发工作提供一个更快、更广泛的入门经验。
- 开箱即用,你也可以通过修改默认值来快速满足你的项目的需求。
- 提供了一系列大型项目中常见的非功能性特性,如嵌入式服务器、安全、指标,健康检测、外部配置等。
博主准备写一组 Spring-Boot 入门的帖子,仅为了抛砖引玉,让需要的同学可以尽快了解如何使用Spring-Boot,内容参考官网和网上的资料( http://projects.spring.io/spring-boot/ )。
下面是目录:
Spring-Boot 入门
Spring-Boot Controller
Spring-Boot Servlet
Spring-Boot 过滤器、监听器
Spring-Boot 拦截器
Spring-Boot 静态资源处理
Spring-Boot 启动加载数据
Spring-Boot 日志记录
Spring-Boot JDBC 连接数据库
Spring-Boot JPA 连接数据库
Spring-Boot MyBatis 连接数据库
Spring-Boot 连接数据库 - 多数据源
Spring-Boot Shiro 权限管理
Spring-Boot 集成Shiro和CAS
Spring-Boot 环境变量读取 和 属性对象的绑定
Spring-Boot 动态数据源(多数据源自动切换)
Spring-Boot 事务的使用
Spring-Boot 部署与服务配置
开发工具:Spring Tool Suite v_3.7.2(简称STS)
官网地址: http://spring.io/tools/sts
二、入门实例 - HelloWorld
File > New > Spring Starter Project

Next > Finish
项目创建完成:
可以看出,项目源码就一个Java类,在pom.xml中有spring-boot-starter-web的依赖。
SpringBootSampleApplication.java package org.springboot.sample; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringBootSampleApplication { public static void main(String[] args) { SpringApplication.run(SpringBootSampleApplication.class, args); } } 1 2 3 4 5 6 7 8 9 10 11 12
pom.xml 4.0.0 org.springboot.sample spring-boot-sample 0.0.1-SNAPSHOT jar spring-boot-sample Spring Boot Sample Web Application org.springframework.boot spring-boot-starter-parent 1.3.1.RELEASE UTF-8 1.8 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-maven-plugin 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
这样就完成了项目的创建,下面我们创建一个 HelloController.java 定义3个方法 package org.springboot.sample.controller; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/hello") public class HelloController { @RequestMapping public String hello() { return "Hello Spring-Boot"; } @RequestMapping("/info") public Map getInfo(@RequestParam String name) { Map map = new HashMap<>(); map.put("name", name); return map; } @RequestMapping("/list") public List> getList() { List> list = new ArrayList<>(); Map map = null; for (int i = 1; i <= 5; i++) { map = new HashMap<>(); map.put("name", "Shanhy-" + i); list.add(map); } return list; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
然后现在可以直接运行 SpringBootSampleApplication 的main方法,和执行普通java程序一样。
然后可以看到spring-boot 内置server容器(默认为Tomcat),这一切spring-boot 都帮我们做好了。
控制台输出内容 Started SpringBootSampleApplication in 7.358 seconds (JVM running for 9.154) 表示服务已经启动。
在浏览器输入我们3个请求便可看到结果。
http://localhost:8080/hello
输出:Hello Spring-Boot
http://localhost:8080/hello/info?name=shanhy
输出:{“name”:”shanhy”}
http://localhost:8080/hello/list
输出:[{“name”:”Shanhy-1”},{“name”:”Shanhy-2”},{“name”:”Shanhy-3”},{“name”:”Shanhy-4”},{“name”:”Shanhy-5”}]
通过我们的Hello实例,相信大家一目了然,可谓spring-boot创建一个项目如此简单,完全可以在几分钟内将服务启动。
spring-boot抛弃繁琐的配置,让开发人员更专注与业务逻辑的实现。后面几篇文章将会对spring-boot的多个方面通过实例的方式呈现给大家。
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/catoop/article/details/50501664
云计算
2018-06-14 17:41:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
一、简介
Spring 官方网站本身使用Spring 框架开发,随着功能以及业务逻辑的日益复杂,应用伴随着大量的XML配置文件以及复杂的Bean依赖关系。
随着Spring 3.0的发布,Spring IO团队主键开始摆脱XML配置文件,并且在开发过程中大量使用“约定优先配置”(convention over configuration)的思想来摆脱Spring框架中各种复杂的配置,衍生了Java Config。
Spring Boot正是在这样的一个背景下被抽象出来的开发框架,它本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于Spring框架的应用程序。也就是说,它并不是用来替代Spring的解决方案,而是和Spring框架紧密结合用于提升Spring开发者体验的工具。同时它集成了大量常用的第三方库配置(例如Jackson, JDBC, Mongo, Redis, Mail等等),Spring Boot应用中这些第三方库几乎可以零配置的开箱即用(out-of-the-box),大部分的Spring Boot应用都只需要非常少量的配置代码,开发者能够更加专注于业务逻辑。
该项目旨在帮助开发者更容易地创建基于Spring的应用程序和服务,使得现有的和新的Spring开发者能够最快速地获得所需要的Spring功能。
Spring Boot不生成代码,且完全不需要XML配置。其主要目标如下:
- 为所有的Spring开发工作提供一个更快、更广泛的入门经验。
- 开箱即用,你也可以通过修改默认值来快速满足你的项目的需求。
- 提供了一系列大型项目中常见的非功能性特性,如嵌入式服务器、安全、指标,健康检测、外部配置等。
博主准备写一组 Spring-Boot 入门的帖子,仅为了抛砖引玉,让需要的同学可以尽快了解如何使用Spring-Boot,内容参考官网和网上的资料( http://projects.spring.io/spring-boot/ )。
下面是目录:
Spring-Boot 入门
Spring-Boot Controller
Spring-Boot Servlet
Spring-Boot 过滤器、监听器
Spring-Boot 拦截器
Spring-Boot 静态资源处理
Spring-Boot 启动加载数据
Spring-Boot 日志记录
Spring-Boot JDBC 连接数据库
Spring-Boot JPA 连接数据库
Spring-Boot MyBatis 连接数据库
Spring-Boot 连接数据库 - 多数据源
Spring-Boot Shiro 权限管理
Spring-Boot 集成Shiro和CAS
Spring-Boot 环境变量读取 和 属性对象的绑定
Spring-Boot 动态数据源(多数据源自动切换)
Spring-Boot 事务的使用
Spring-Boot 部署与服务配置
开发工具:Spring Tool Suite v_3.7.2(简称STS)
官网地址: http://spring.io/tools/sts
二、入门实例 - HelloWorld
File > New > Spring Starter Project

Next > Finish
项目创建完成:
可以看出,项目源码就一个Java类,在pom.xml中有spring-boot-starter-web的依赖。
SpringBootSampleApplication.java package org.springboot.sample; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringBootSampleApplication { public static void main(String[] args) { SpringApplication.run(SpringBootSampleApplication.class, args); } } 1 2 3 4 5 6 7 8 9 10 11 12
pom.xml 4.0.0 org.springboot.sample spring-boot-sample 0.0.1-SNAPSHOT jar spring-boot-sample Spring Boot Sample Web Application org.springframework.boot spring-boot-starter-parent 1.3.1.RELEASE UTF-8 1.8 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-maven-plugin 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
这样就完成了项目的创建,下面我们创建一个 HelloController.java 定义3个方法 package org.springboot.sample.controller; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/hello") public class HelloController { @RequestMapping public String hello() { return "Hello Spring-Boot"; } @RequestMapping("/info") public Map getInfo(@RequestParam String name) { Map map = new HashMap<>(); map.put("name", name); return map; } @RequestMapping("/list") public List> getList() { List> list = new ArrayList<>(); Map map = null; for (int i = 1; i <= 5; i++) { map = new HashMap<>(); map.put("name", "Shanhy-" + i); list.add(map); } return list; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
然后现在可以直接运行 SpringBootSampleApplication 的main方法,和执行普通java程序一样。
然后可以看到spring-boot 内置server容器(默认为Tomcat),这一切spring-boot 都帮我们做好了。
控制台输出内容 Started SpringBootSampleApplication in 7.358 seconds (JVM running for 9.154) 表示服务已经启动。
在浏览器输入我们3个请求便可看到结果。
http://localhost:8080/hello
输出:Hello Spring-Boot
http://localhost:8080/hello/info?name=shanhy
输出:{“name”:”shanhy”}
http://localhost:8080/hello/list
输出:[{“name”:”Shanhy-1”},{“name”:”Shanhy-2”},{“name”:”Shanhy-3”},{“name”:”Shanhy-4”},{“name”:”Shanhy-5”}]
通过我们的Hello实例,相信大家一目了然,可谓spring-boot创建一个项目如此简单,完全可以在几分钟内将服务启动。
spring-boot抛弃繁琐的配置,让开发人员更专注与业务逻辑的实现。后面几篇文章将会对spring-boot的多个方面通过实例的方式呈现给大家。
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/catoop/article/details/50501664
云计算
2018-06-14 17:41:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
摘要: 6月13日,阿里云宣布弹性计算Apsara Block Storage产品正式发布,为企业级客户量身打造,构建高性能、弹性、可靠的大规模分布式块存储服务平台。 Apsara Block Storage可兼容多种类型的计算平台,包括阿里云ECS、ZStack、OpenStack、Kubernetes以及物理服务器等不同类型,帮助客户轻松应对云时代下海量存储资源的敏捷存取需求,适用于政府、金融、运营商和大型制造企业的线下数据中心云存储业务场景。
6月13日,阿里云宣布弹性计算Apsara Block Storage产品正式发布,为企业级客户量身打造,构建高性能、弹性、可靠的大规模分布式块存储服务平台。
Apsara Block Storage可兼容多种类型的计算平台,包括阿里云ECS、ZStack、OpenStack、Kubernetes以及物理服务器等不同类型,帮助客户轻松应对云时代下海量存储资源的敏捷存取需求,适用于政府、金融、运营商和大型制造企业的线下数据中心云存储业务场景。
客户需求和行业趋势
数字化转型已成为促进客户业务创新和敏捷发展的重要推进力量,传统集中式、“烟囱式”的IT系统建设架构,已经不能满足日益复杂的业务发展需求,特别是在存储资源的灵活使用上,遇到了越来越多的问题。采用资源化、平台化、灵活扩展的云存储架构已成为客户现代化数据中心海量数据存储的不二选择。
分布式存储产品,由于其具备架构上的先天优势,以及对商用X86服务器硬件的良好兼容性,从全球范围来看,已经越来越多的成为客户建设虚拟化云平台的首要选择。
产品特点与业务价值
APSARA Block Storage是依托于阿里云弹性计算块存储服务,针对企业级市场的诉求孵化出来的一个全新的产品。青出于蓝而胜于蓝,Apsara Block Storage在产品和技术体系上,有如下亮点。
开放兼容
阿里云弹性计算块存储团队开发了针对不同计算平台的接入插件,支持多种块设备访问协议,全面支持OpenStack、ZStack、Kubernetes、VMware以及物理服务器等计算平台,真正实现阿里云块存储与客户自有计算资源的无缝兼容,将阿里云在块存储领域多年的技术积累赋能到客户线下IT系统中。
图示一 全面兼容Openstack平台
图示二 全面兼容Docker平台
高可靠性
采用9个9数据可靠性设计,能够满足核心业务的数据安全性要求,同时支持自动快照等高级数据保护功能,全方面保护客户数据安全。
灵活部署&弹性扩展
支持从数台最高扩展至万台级别,随业务需求灵活扩展,不为过渡消费而买单。同时支持计算存储融合和分离两种部署架构,便于客户根据自身机房条件灵活选择。
极致性能
单集群最高支持千万级IOPS能力,百微秒级别时延能力,满足关键业务对性能的极致需求。
交付形态和适用行业
据悉,Apsara Block Storage产品可通过阿里云专有云产品形态对外服务,适用于政府、公共事业、金融、大企业、运营商等多种行业客户在线下专有云平台建设中进行使用。当前已有若干政府、企业和金融客户选择了Apsara Block Storage产品,作为政务云、金融云、企业开发测试云平台的核心数据存储平台。
历经近10年的技术沉淀,阿里云将块存储在公共云上的技术精华沉淀在Apsara Block Storage上,希望客户在自己的数据中心中也能享受到与阿里云同等级别的数据存储服务,为客户构建高性能、稳定可靠、弹性扩展的云存储平台,真正助力企业实现数字化转型。
原文链接
本文为云栖社区原创内容,未经允许不得转载。
云计算
2018-06-14 17:20:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
摘要: 6月13日,阿里云宣布弹性计算Apsara Block Storage产品正式发布,为企业级客户量身打造,构建高性能、弹性、可靠的大规模分布式块存储服务平台。 Apsara Block Storage可兼容多种类型的计算平台,包括阿里云ECS、ZStack、OpenStack、Kubernetes以及物理服务器等不同类型,帮助客户轻松应对云时代下海量存储资源的敏捷存取需求,适用于政府、金融、运营商和大型制造企业的线下数据中心云存储业务场景。
6月13日,阿里云宣布弹性计算Apsara Block Storage产品正式发布,为企业级客户量身打造,构建高性能、弹性、可靠的大规模分布式块存储服务平台。
Apsara Block Storage可兼容多种类型的计算平台,包括阿里云ECS、ZStack、OpenStack、Kubernetes以及物理服务器等不同类型,帮助客户轻松应对云时代下海量存储资源的敏捷存取需求,适用于政府、金融、运营商和大型制造企业的线下数据中心云存储业务场景。
客户需求和行业趋势
数字化转型已成为促进客户业务创新和敏捷发展的重要推进力量,传统集中式、“烟囱式”的IT系统建设架构,已经不能满足日益复杂的业务发展需求,特别是在存储资源的灵活使用上,遇到了越来越多的问题。采用资源化、平台化、灵活扩展的云存储架构已成为客户现代化数据中心海量数据存储的不二选择。
分布式存储产品,由于其具备架构上的先天优势,以及对商用X86服务器硬件的良好兼容性,从全球范围来看,已经越来越多的成为客户建设虚拟化云平台的首要选择。
产品特点与业务价值
APSARA Block Storage是依托于阿里云弹性计算块存储服务,针对企业级市场的诉求孵化出来的一个全新的产品。青出于蓝而胜于蓝,Apsara Block Storage在产品和技术体系上,有如下亮点。
开放兼容
阿里云弹性计算块存储团队开发了针对不同计算平台的接入插件,支持多种块设备访问协议,全面支持OpenStack、ZStack、Kubernetes、VMware以及物理服务器等计算平台,真正实现阿里云块存储与客户自有计算资源的无缝兼容,将阿里云在块存储领域多年的技术积累赋能到客户线下IT系统中。
图示一 全面兼容Openstack平台
图示二 全面兼容Docker平台
高可靠性
采用9个9数据可靠性设计,能够满足核心业务的数据安全性要求,同时支持自动快照等高级数据保护功能,全方面保护客户数据安全。
灵活部署&弹性扩展
支持从数台最高扩展至万台级别,随业务需求灵活扩展,不为过渡消费而买单。同时支持计算存储融合和分离两种部署架构,便于客户根据自身机房条件灵活选择。
极致性能
单集群最高支持千万级IOPS能力,百微秒级别时延能力,满足关键业务对性能的极致需求。
交付形态和适用行业
据悉,Apsara Block Storage产品可通过阿里云专有云产品形态对外服务,适用于政府、公共事业、金融、大企业、运营商等多种行业客户在线下专有云平台建设中进行使用。当前已有若干政府、企业和金融客户选择了Apsara Block Storage产品,作为政务云、金融云、企业开发测试云平台的核心数据存储平台。
历经近10年的技术沉淀,阿里云将块存储在公共云上的技术精华沉淀在Apsara Block Storage上,希望客户在自己的数据中心中也能享受到与阿里云同等级别的数据存储服务,为客户构建高性能、稳定可靠、弹性扩展的云存储平台,真正助力企业实现数字化转型。
原文链接
云计算
2018-06-14 17:12:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
摘要: 今年的先知白帽大会,与会者将能够亲身感受到非常多有趣的技术议题,如HITCON在国际赛事中屡夺佳绩的CTF团队,其队长Orange将亲临现场,分享穿针引线般的漏洞利用艺术。 当然,还有代码审计圈的新锐phithon、jkgh006、廖新喜,在国际会议锤炼过的redrain、白小龙、蒸米、kevin2600,战斗在阿里一线的安全工程师菜丝、cdxy、猪猪侠等知名白帽也会现身现场,与大家一起畅聊技术思路和攻防实践经验。
今年的先知白帽大会,与会者将能够亲身感受到非常多有趣的技术议题,如HITCON在国际赛事中屡夺佳绩的CTF团队,其队长Orange将亲临现场,分享穿针引线般的漏洞利用艺术。
当然,还有代码审计圈的新锐phithon、jkgh006、廖新喜,在国际会议锤炼过的redrain、白小龙、蒸米、kevin2600,战斗在阿里一线的安全工程师菜丝、cdxy、猪猪侠等知名白帽也会现身现场,与大家一起畅聊技术思路和攻防实践经验。
大会将持续奋战一整天,疲劳在所难免。为避免错过精彩内容,先知君提前曝光议题详情,方便各位能在会议当天,把最好的时间和精力留给最感兴趣的内容。
01 macOS 上的逻辑提权漏洞
菜丝
蚂蚁金服安全工程师。主要从事桌面端和移动端、IoT 设备安全漏洞的攻防,安全工具开发。曾参加过 GeekPwn、XPwn 等赛事。
议题解读
通过结合真实环境案例,介绍如何在 macOS 平台上不破坏一个字节内存的情况下稳定地获得 root 权限。议题将会分析较为通用的挖掘思路,并针对开发者给出安全设计建议。
02 弑君者Kingslayer:供应链攻击前餐
redrain(洪宇)
360CERT安全分析团队技术负责⼈,8年安全经验,聚焦于攻击对抗和应⽤安全研究,为Apple, Atlassian, Microsoft, Artifex 等知名⼚商和开源软件基⾦会提交漏洞, 相关研究曾在HITB, RUXCON, Syscan360, Qcon, xKungfoo等发表演讲, Atlassian Hall of Fame成员。
议题解读
2017年的xShellGhost, CCleaner事件让供应链攻击在此前XCodeghost沉寂近⼀年后重回⼈们视野, 然⽽鲜为⼈知的是,2016年,⼀个精巧且庞⼤的攻击悄然落地, 攻击者⾄少在开发环节, 交付环节, 使⽤环节进⾏了不同 程度的攻击, 可能对US Army, NASA, MIT等多个机构造成不同程度的影响, 该事件被命名为Kingslayer(弑君者)。
作为事件为数不多的研究者, 本⽂将详细阐述并回顾攻击过程并分析其中利⽤的攻击机巧, 并深⼊追溯攻 击者和组织, 披露⼀些研究猜想。
03 代码审计点线面实战
jkgh006
敏信科技创始人之一,安全团队负责人,擅长各类语言代码审计,众测资深玩家。
议题解读
从一个个案例,深入了解java业务系统审计方法和规律,采用黑白结合方式快速完成审计项目。
04 边信道硬件攻击实战
KEVIN2600(狗汪汪)
独立安全研究员, 专注无线电和嵌入式系统安全研究,坚信黑客精神就是不断探索未知领域。
议题解读
物联网嵌入式设备已逐渐融人们生活当中, 其在安全及隐私保护上一直都受到黑客和安全研究人员的重点关注. 正所谓魔高一尺道高一丈, 随着物联网设备安全事故的频发, 各厂商在安全防御上也有了一定提升. 这同时也给安全研究带来了更高的挑战。
边信道攻击众人皆知, 但往往给人神秘莫测的感觉. 因此在物联网安全研究人员中还鲜有提及. 本议题将从实战的角度出发. 通过多个简单实用的案例分析, 来揭开 Side-Channel 在硬件设备攻击中的神秘面纱及其强大威力. 也希望给嵌入式设备的开发人员在安全防御上引入新的思路。
05 从一个脆弱点到串起整个攻击面
Orange Tsai
来自台湾,DEVCORE 及 HITCON 成员,讲师经历: Black Hat USA, DEFCON, HITB, WooYun 等多场会议讲者。奖金猎人: 回报 Facebook, Uber, Apple, GitHub, Yahoo 及 Imgur 的远端代码执行漏洞。电竞选手: 多场 CTF 竞赛冠军 及 DEFCON CTF 22/25 亚军。
议题解读
当业务逻辑扩增、企业架构逐渐复杂时,Bug 或是能解决问题的替代方案便开始增加, 这些问题单独看来可能不起眼或根本无害,但许多微小问题串在一起时,便可能产生严重的风险。
本议程将以 Java 为主轴,分析一个笔者所报告的 0day 以及一个在 Bug Bounty 中因多层次架构所导致远端代码执行的案例。
06 攻击GraphQL
phithon
安全开发与研究员。长期从事开发工作,熟悉多种语言开发与合作流程,擅长从代码中发现安全漏洞。
议题解读
GraphQL是一个具有划时代意义的前后端通信语言,也是一门比较年轻的技术(诞生于2012年,开源于2015年),新技术的诞生与广泛应用,对于安全人员来说是一种挑战和机遇。本议题从开发的角度,理解GraphQL的设计与运行思路,分析其中可能存在的安全风险,并从前、后端多角度介绍GraphQL的漏洞利用技巧。
07 Java反序列化实战
廖新喜(xxlegend)
绿盟科技安全研究员,擅长代码审计,漏洞挖掘,拥有丰富的代码审计经验,曾在Pycon 2015 China大会上分享Python安全编码,2016年网络安全周接受央视专访 安全行业从业七年,三年开发经历。
目前专注于Web漏洞挖掘、Java反序列化漏洞挖掘,2017年在看雪大会分享Java 反序列化之殇,曾向RedHat、Apache、Amazon、Oracle,阿里巴巴提交多份远程代码执行漏洞报告。最近的Weblogic CVE-2018-2628就是一个。
议题解读
2017年又是反序列漏洞的大年,涌现了许多经典的因为反序列化导致的远程代码执行漏洞,像fastjson,jackson,struts2,weblogic这些使用量非常大的产品都存在这类漏洞,但不幸的是,这些漏洞的修复方式都是基于黑名单,每次都是旧洞未补全,新洞已面世。随着虚拟货币的暴涨,这些直接的远程执行代码漏洞都成了挖矿者的乐园。
本议题将从那些经典案例入手,分析攻击方和防御方的对抗过程。首先是fastjson的最近的安全补丁的分析,由于黑名单做了加密处理,这里会展开如何得到其黑名单,如何构造PoC。当然2018年的重点还是weblogic,由我给大家剖析CVE-2018-2628及其他Weblogic经典漏洞,带大家傲游反序列化的世界,同时也是希望开发者多多借鉴做好安全编码。
08 智能合约消息调用攻防
隐形人真忙
百度安全工程师,从事攻防技术研究与安全产品研发,曾为Microsoft,Redhat,Pivotal,Apache,Eclipse, Alibaba等著名厂商提交过高危漏洞。
议题解读
随着区块链技术的流行,以以太坊为基础的智能合约应用也层出不穷,但也伴随着巨大的安全风险。本议题从EVM底层机制与原理出发,结合一些作者发现的特性、场景,介绍消息调用风险点和攻击技术,并从开发者角度给出防护措施。
09 从数据视角探索安全威胁
cdxy
阿里云安全工程师
议题解读
本议题讨论了数据为安全人员思维方式带来的变化。尝试从数据角度对传统威胁感知方案进行再设计,并展示其在入侵检测、攻击识别、0day预警等方面落地效果。
10 WEB 2.0 启发式爬虫实战
猪猪侠
阿里云高级安全专家,长期从事自动化安全测试工作,熟悉多种开发技术,擅长渗透测试与数据挖掘。
议题解读
在WEB1.0时代网站均由静态页面构成,随着JS动态脚本的兴起和Ajax技术的发展,WEB2.0崛地而起,前端开发框架(JQuery、AngularJS、Vue.js、React)也相继流行,基于WEB2.0框架开发的网页内容会通过事件对DOM结构进行动态地触发与加载,导致在浏览器中看到的页面是缺失的。
依靠静态分析已不能满足需求,通过浏览器提供的Headless调试模式,我们可遍历一个网页的所有动态对象,自动填充输入表单的参数值,并触发对象上的绑定的事件,有效解决安全测试过程中的攻击面挖掘。
启发式爬虫:基于历史经验和已知场景,构造并实现规则的爬虫。
11 如何利用Ryuk分析和挖掘macOS&iOS内核驱动漏洞
白小龙
白小龙,阿里巴巴高级安全工程师,博士,毕业于清华大学计算机系。主要研究方向:系统安全和移动安全。作为第一作者曾在IEEE S&P、Usenix Security等学术界安全顶会中发表过高水平研究论文,也曾在Black Hat USA、HITB等工业界顶级黑客会议中发表过演讲。其贡献和成果受到过包括苹果、谷歌、Facebook、腾讯等多家公司的致谢。Twitter、微博: bxl1989 。
蒸米
阿里巴巴安全专家,香港中文大学博士,其他简介请参考《黑客蒸米:一个大V的生活意见》。
议题解读
作为苹果macOS和iOS系统的重要组成部分,苹果系统中的设备驱动(简称苹果驱动)与内核使用着相同的地址空间并具有系统中最高的内核权限。但是,苹果驱动经常因其较差的代码质量而饱受诟病,产生过众多的安全性问题,在针对苹果系统的攻击中作为攻击内核的入口被多次利用。在本次演讲中,我们将分享对苹果驱动进行安全性分析和漏洞挖掘的最新研究。
首先,我们将公开苹果驱动中我们发现的两个安全漏洞。这两个漏洞可以被分别用于泄露内核信息和内核代码任意执行。利用漏洞,攻击者可以控制macOS系统的内核,并提升至系统最高权限。除了漏洞细节,我们还将介绍如何利用这些漏洞实现控制内核的整套攻击流程,包括一些崭新的内核漏洞利用技术和技巧。相比于漏洞细节和利用技巧,发现这些安全漏洞的技术更为重要。
然而,在苹果驱动中挖掘安全性漏洞并非易事,其主要原因在于苹果驱动多为闭源且大量使用面向对象编程。我们将分享一款自研的用于分析macOS及iOS内核驱动的静态分析工具Ryuk。Ryuk使用静态分析技术对苹果驱动的二进制代码进行解析,识别代码特征,能够极大地加速苹果驱动逆向和安全性分析流程,加快漏洞挖掘进程。
原文链接
本文为云栖社区原创内容,未经允许不得转载。
云计算
2018-06-14 16:49:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
Kasun Indrasiri
service mesh与api gateway的关键特征可以帮助我们更好的区分两者。
API Gateway: 将服务作为托管api暴露给外部
api gateway的核心目标是将微服务作为托管的api暴露给外部系统,我们在api gateway层开发api或是边界服务以提供特定的业务功能。
api/边界服务调用下游微服务,并包含业务逻辑的多个服务下游服务组合。
api/边界服务同时需要以弹性的方式调用下游服务,并应用多种稳定性相关模块,例如断路器、超时、负载均衡/故障转移等等。大多数api gateway解决方案均内置以上模块或功能。
api gateway往往同时包含内置的服务发现、分析(指标、监控、分布式日志、分布式跟踪)以及安全。
api gateway常与api管理生态中的一些其他组件协作,例如api商店、api分发门户。
service mesh
那么再看看service mesh有何不同。
我们可以认为service mesh是网络通信基础设施,它允许我们从服务代码中剥离大部分应用网络功能。
在service mesh下,我们处理service-to-service通信时,不需要刻意在服务代码中实现包括断路器、超时等弹性通信功能特性。同样的,service mesh提供服务发现、监控等功能。
api gateway和service mesh
api gateway和service mesh最大的不同在于,api gateway是暴露api/边界服务的关键部分,而service mesh仅仅是一种服务间通信的基础设施,不包含任何业务概念。
上图说明了api gateway和service mesh的所处。除了上面提到的不同点,api gateway和service mesh之间存在着很多重叠特性,但需要特别注意的是两者所针对的要求和需求不同。
图中service mesh以sidecar形势,与其他服务一起部署,独立于服务的业务功能。
而api gateway托管了所有的api服务,属于业务功能解决方案的一部分。api gateway可能会包含服务间通信的支持,但并不影响api gateway通过service mesh来调用下游服务。
阅读更多 Service Mesh服务网格:8种方式简化微服务部署 Service Mesh服务网格:是什么和为什么 解读Rainbond ServiceMesh微服务架构_开源PaaS Rainbond
开源PaaS Rainbond 原生支持Service Mesh服务网格,用非入侵、透明化的方式解决服务发现和注册、弹性伸缩与负载均衡、容错处理(断路器与限流)、监控与警报、数据存储与共享、日志分析等等微服务架构难题,提供开箱即用、简单强大的微服务体验。
请访问 Rainbond 或试用 公有云 进一步了解Rainbond如何实现Service Mesh微服务治理
云计算
2018-06-14 08:35:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
使用docker创建calico网络失败。 # docker network create --driver calico --ipam-driver calico-ipam testcalico Error response from daemon: failed to update store for object type *libnetwork.endpointCnt: client: response is invalid json. The endpoint is probably not valid etcd cluster endpoint.
查看docker日志: # journalctl -fu docker -- Logs begin at Sun 2018-05-06 10:42:10 CST. -- May 06 10:51:11 gpu16 dockerd[1045]: time="2018-05-06T10:51:11.997488908+08:00" level=warning msg="Registering as \"192.168.56.16:2375\" in discovery failed: client: response is invalid json. The endpoint is probably not valid etcd cluster endpoint." May 06 10:51:13 gpu16 dockerd[1045]: time="2018-05-06T10:51:13.209441579+08:00" level=error msg="discovery error: client: response is invalid json. The endpoint is probably not valid etcd cluster endpoint." May 06 10:51:13 gpu16 dockerd[1045]: time="2018-05-06T10:51:13.211323271+08:00" level=error msg="discovery error: client: response is invalid json. The endpoint is probably not valid etcd cluster endpoint." May 06 10:51:13 gpu16 dockerd[1045]: time="2018-05-06T10:51:13.213320054+08:00" level=error msg="discovery error: Unexpected watch error"
首先想到的错误原因可能是:calico网络后台的分布式存储是etcd,而环境中使用的V3版本的etcd,而该版本在API方面既支持V2又支持V3。docker中未正确配置需要的版本,即docker要求使用的etcd API版本和etcd提供的API版本不一致,导致出现该问题。
验证:命令行手动去获取etcd的版本号:curl http://:2379/version # curl http://192.168.56.96:2379/version {"etcdserver":"3.1.9","etcdcluster":"3.1.0"}
返回正常。
看到http,忽然想到我们的环境访问http和https是需要设置代理http_proxy和https_proxy,同样,也需要设置no_proxy来过滤不使用代理的IP。如果要访问的IP不在no_proxy的范围内,代理就会返回非法的http应答,而这个应答不是json格式的,很可能就对应了错误日志中的“response is invalid json”部分。在环境变量中,已经设置了http_proxy,https_proxy和no_proxy,但是,docker不能使用操作系统的这三个环境变量,我们需要配置docker的这三个环境变量。而且,在创建calico网络时,docker会通过http请求向etcd注册,因此 在no_proxy中需要包含etcd集群的IP 。 # mkdir -p /etc/systemd/system/docker.service.d/ # vim /etc/systemd/system/docker.service.d/http-proxy.conf [Service] Environment="HTTP_PROXY=http://192.168.11.200:8080/" "HTTPS_PROXY=https://192.168.11.200:8080/" "NO_PROXY=192.168.56.109,192.168.56.96" # systemctl daemon-reload # systemctl restart docker
待docker服务重启完毕,再尝试创建calico网络,成功。 # docker network create --driver calico --ipam-driver calico-ipam testcalico 53cbe9b82451b017be6d5d80a8fc17e320f6269521dfeabb7e07fd79ee92e3ef
云计算
2018-06-14 06:07:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
This article is part of an Virtualization Technology tutorial series. Make sure to check out my other articles as well: 2018 年度 Docker 用户报告 - Sysdig Edition Cyber-Security: Linux 容器安全的十重境界 DevOps漫谈:Docker ABC
根据 Sysdig 发表的年度 [Docker](( https://riboseyim.github.io/2017/08/21/DevOps-Docker/ ) 用户报告,在容器市场 Docker 仍然是事实上的行业标准,但是其它品牌的容器运行环境正在发展;Kubernetes 仍然是容器编排领域的王者。报告的数据来源主要依据 Sysdig Monitor 和 Sysdig Secure cloud service 提供的容器使用状况的实时快照报告,它们从容器健康、性能和安全性等方面提供度量指标和可视化服务。样本集包括垂直行业和各类规模不等的大中型企业,地域覆盖北美洲、拉丁美洲、EMEA(欧洲、中东、非洲)和亚太地区。与去年一样,这份报告并不是用来代表整个容器市场。因为数据仅限于 Sysdig 客户,所以对于那些选择商业和开源解决方案的公司来说不具有代表性。但是来自 90000 个容器用户汇总数据,确实提供了了解真实生产环境容器使用状况的独特视角。
2018 Docker 用户报告 - Sysdig Edition
容器应用排行榜
容器部署应用榜首:Java Virtual Machines (JVM)。在容器时代之前,Java 就广泛应用于企业级服务,目前两者 —— Java 和容器更加紧密地融合到了一起。
我们还看到数据库解决方案的使用在增加, 例如在容器环境中运行 PostgreSQL 和 MongoDB 。这是一个信号, 表明在容器中部署有状态服务已经成为现实。容器的短暂性,让许多人对于在容器中运行高价值数据服务抱有怀疑态度, 但是市场回答了问题的解决方案--即为微服务设计的持久、便携和共享存储。数据显示, 客户开始转向完全由容器驱动的环境。
容器密度
在2017年每个主机的容器数的中位数是 10 。2018年,这个数字上升到 15,同比增长 50% 。另一方面,我们看到一个客户的单台主机上运行了 154 个容器,比我们去年观察到的最大 95 个增长了。

容器运行环境 Docker still reigns, but we’re seeing what might be the first signs of cracks in the dam.
事实上的容器运行环境依然是[Docker](( https://riboseyim.github.io/2017/08/21/DevOps-Docker/ )。我们在 2017 年的报告中没有提及其他容器运行环境的详细信息, 因为在当时 Docker 的占有率接近 99% 。但是, 鉴于最近的一些变化: Red Hat 收购 CoreOS 的 (RKT 的制造商),以及 Open Container Initiative (OCI) 项目 — 旨在推进容器运行环境和镜像标准化。
事实上,在过去的一年里, 客户对其他平台的使用增加了。CoreOS RKT 显著增长到 12% , Mesos containerizer 占有 4% 。LXC 也在增长, 尽管从业人员规模比例还较低。数据显示, 客户在生产环境中使用 "non-Docker" 解决方案更加便利了。
容器存活周期
95% 的容器存活时间低于一周。
容器和服务的生存时间是多少? 我们观察了容器、容器镜像和服务的数量, 它们在短时间内开始并停止, 存活10秒或更短, 或者一周或更长。下图显示不同间隔内的容器百分比。 11% 的容器活了不到10秒。大部分容器(27%) 的生存期在五分钟之内。
为什么这么多的容器寿命如此之短呢?我们知道许多定制的系统都是按照需求来扩展的。容器被创建, 做他们的工作, 然后离开。例如, 一个客户为他们在 Jenkins 创建的每个作业配置一个容器,执行变更测试, 然后关闭容器。对他们来说, 类似活动每天会发生上千次。(Jenkins:一个用 Java 编写的开源持续集成工具,MIT许可证。它支持软件配置管理工具,如CVS、Subversion 和 Git 等,可以执行基于 Apache Ant 和 Apache Maven 的项目,以及任意的Shell 脚本/批处理命令。)
镜像存活周期
我们还观察了容器镜像的使用时间。通过查看这些数据, 我们了解到客户在 DevOps CI/CD 流程的一部分中是如何频繁地进行新的容器更新部署的。 一小部分 -- 一个百分点--在不到10秒内更新。69% 的容器镜像在一周的跨度内更新。
服务存活周期
"服务的寿命是多少?" 在 Kubernetes 中, 服务抽象定义了一组提供特定函数以及如何访问它们的 Pods 。服务允许 Pods 在不影响应用程序的情况下注销和复制。例如, 一个群集可以运行一个 Node.js JavaScript 运行时服务、MySQL 数据库服务和 NGINX 前端服务。
我们看到大多数服务(67%)生存期超过一周。少量的服务在更频繁的基础上被停止, 但是对于大多数客户来说, 目标是让应用程序 24 小时持续工作。容器和 Pods 可能会来了又走, 但是服务持续处于启动并且可用状态。
容器编排器 First place goes to Kubernetes, followed by Kubernetes and then Kubernetes.
例如, Mesosphere 能够在 DC/OS 环境中部署和管理 "Kubernetes-as-a-service"。可以将多个 Kubernetes 群集部署在一个 Mesosphere 群集上。
今年 Docker Swarm 的排名上升到第二位, 超过了基于 Mesos 的工具。根据 Sysdig ServiceVision 我们能自动标识出是否使用编排器, 并将逻辑基础结构对象与容器度量关联起来。在 2018 年, Kubernetes 可以确保领先地位。 Swarm 的进入门槛 例如, 微软使用 Kubernetes 为其 Azure Kubernetes 服务 (AKS), IBM 的云容器服务和私有云产品也是基于 Kubernetes 。即使是 Docker 和 Mesosphere 也增加支持了 Kubernetes 的功能。 Docker 企业版, 具有通用控制平面 (Universal Control Plane (UCP) ), 在许多操作层面上降低了启动 Swarm 的门槛。
容器集群大小 Mesos owns the big cluster game.
”集群大小对与组织选择编排器的影响是什么?“ 这项研究显示基于 Mesos 的编排器, 包括 Mesos Marathon 和 Mesosphere DC/OS 降至第三位。在使用 Mesos 的地方, 部署的容器数(中位数)比 Kubernetes 环境多 50% 。鉴于 Mesos 倾向于在大规模的容器和云部署, 所以这是有意义的。因此, 虽然 Mesos 集群的数量较少, 但是 Mesos 集群通常是意味着更大的企业规模。
我们的客户, 往往是更大的企业(在私有数据中心运行 Sysdig 解决方案)采用 OpenShift 的数量比我们的 SaaS 客户数量还要多。 Rancher Labs 于 2015 年出现, 为 Docker Swarm 和 Kubernetes 提供支持。直到 2017 年, Rancher (“大农场主”)才完全兼容 Kubernetes 作为其编排器。
Kubernetes 分发版
今年我们分析了使用 Kubernetes 的“品牌”分布, 看看在使用的 Kubernetes 是开源版本, 或由特定供应商提供的软件包。我们发现开源 Kubernetes 继续占有最大的份额, 但是 OpenShift 似乎正在取得突破进展, Rancher 也占有了一些份额。
OpenShift 获得接受不应该是一个惊喜。Kubernetes 于 2014 年诞生于 Google , Red Hat 也发布了该平台的 OpenShift 分发版, 并提出了针对企业客户实现 Kubernetes 的目标。
容器健康与应用性能监控
了解用户体验的四个“黄金信号” :延迟(latency),流量(traffic),错误(errors)和饱和度(saturation)。 响应时间(Response time)是配置最广泛的告警类型,紧随其后的是正常运行时间(uptime)和停机告警。基于主机的告警是最常用的,包括主要资源指标 - CPU ,内存和磁盘使用率等仍然被广泛使用。用户想知道托管 Docker 的服务器(物理机,虚拟机或云实例)是否处于资源紧张或达到容量上限的状态。这些告警的触发条件通常设置在利用率达到 80%-95% 之间。
同时,出现了越来越多的以容器为中心的资源告警。最主要有两种风格: 1)资源利用率 2)容器数量
默认情况下容器没有资源限制 。鉴于客户越来越注意容器限制方面的告警,这意味着他们正在使用 Docker运行时配置来控制容器使用内存,CPU或磁盘I / O 的上限,用户希望知道何时会超出阈值,应用程序的性能风险需要处于可控状态。
对于容器数量来说,这个问题通常与用户至少需要 X 个给定类型的容器并运行以提供所需的服务级别有关,特别是在微服务部署中。例如,“我知道如果需要确保应用程序运行良好,至少有三个 NGINX 容器可用。如果任何一个有问题,我都想知道。”
基于编排的告警(Orchestration-focused alerts) 也越来越受欢迎。与我们 2017 年的报告类似,“Pod Restart Count” 位列榜首。在一个 Pod 中,一个或多个容器是定位相同、共同调度(通常作为微服务的一部分)。如果某个容器重新启动太频繁,则表示存在可能影响应用程序性能的问题。
Kubernetes 管理员也经常使用 基于事件的告警( Event-based alerts ) 。与基于度量的告警相比,它的区别在于,监控程序需要查找环境中生成的事件消息,例如 Kurthnetes “CrashLoopBackoff” 条件 — 代表 Pod 反复失败或重启,或者“Liveness probe failed”,表示容器是否为活跃和运行。这些告警有助于 DevOps 工程师快速定位问题。
Http 错误可能表明软件或基础架构存在问题,最终会影响性能。
Alerts are not a one-size-fits-all approach.
告警不是一种万能的方法。有时需要设置基于指定范围的告警,无论是逻辑或物理实体,还是整个基础结构(注:Sysdig 通过标签实现)。
在 2018 年的研究中,用于确定告警范围的最常用标签与 Kubernetes 有关(Scoping by pods),命名空间(namespace)紧随其后。特定的容器范围(Container specific scoping)也很受欢迎,包括容器名称,容器镜像和容器 ID 。2018年再次名列榜首的是云服务提供商标签,通常针对“名称”,“环境”,“ID”和“区域”标签以区分开发、测试和生产资源,以及标记云数据中心的位置。
容器和基础设施自定义监控指标 There’s no one custom metrics format to rule them all.
"在环境中运行容器的客户,使用自定义指标的比例是多少,都是哪些?"
55% 的 Sysdig SaaS 用户使用与 Java 应用程序相关的 JMX 指标。这与我们看到的 Java 应用程序部署非常广泛的事实一致。 StatsD 占有 29% 的份额,Prometheus 占有 20% 的份额(预计这个数字会随着时间的推移而增长)。
容器注册 It’s a split decision - registries are critical but there’s no clear leader.
注册管理机构至关重要,但是目前没有明确的领导者。 容器注册表(container registry)是任何容器部署的基本组件。市场上有许多解决方案:一些是公共的,一些是私有的,一些是作为服务提供,一些是作为本地软件(private registry)部署。
2018 年前三名中,Google Container Registry(GCR)的比例最高,其次是 Quay ,之后是 Docker和 Amazon Elastic Container Registry(ECR)。 GCR 和 ACR 都是完全基于云托管的(private Docker container registries)。Quay 和 Docker 既可以用作本地解决方案也可以在云中运行(注:Sysdig 的用户群只有 50% 能够清楚地识别出容器注册方案)
New approaches are maturing and helping organizations develop applications more quickly to solve real business challenges and compete in the digital marketplace.
扩展阅读: 网络安全专题合辑《Cyber-Security Manual》 Cyber-Security: Linux 容器安全的十重境界 Cyber-Security: 警惕 Wi-Fi 漏洞,争取安全上网 Cyber-Security: Web应用安全:攻击、防护和检测 Cyber-Security: IPv6 & Security Cyber-Security: OpenSSH 并不安全 Cyber-Security: Linux/XOR.DDoS 木马样本分析 浅谈基于数据分析的网络态势感知 Packet Capturing:关于网络数据包的捕获、过滤和分析 新一代Ntopng网络流量监控—可视化和架构分析 Cyber-Security: 事与愿违的后门程序 | Economist Cyber-Security: 美国网络安全立法策略 Cyber-Security: 香港警务处拟增设网络安全与科技罪案总警司
扩展阅读: DevOps 漫谈系列 《凤凰项目》:从作坊到工厂的寓言故事 Kanban 看板管理实践 DevOps 漫谈:基础设施部署和配置管理 Linux 容器安全的十重境界 工程师的自我修养:全英文技术学习实践
更多精彩内容扫码关注公众号: RiboseYim's Blog
云计算
2018-06-13 09:58:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
摘要: 在刚刚结束的上海云栖大会飞天技术汇分论坛上,阿里云视频云产品架构师罗小飞进行了《阿里云CDN——面向金融政企的CDN最佳实践》主题分享,为上海的嘉宾介绍CDN的解决方案与技术服务体系。
在刚刚结束的上海云栖大会飞天技术汇分论坛上,阿里云视频云产品架构师罗小飞进行了《阿里云CDN——面向金融政企的CDN最佳实践》主题分享,为上海的嘉宾介绍CDN的解决方案与技术服务体系。
在分享的最初,罗小飞与现场嘉宾共同回顾了阿里云CDN的前世今生,他形象地比喻阿里集团的CDN发展是从“在家做饭”到“宴请朋友”再到“开饭店”的过程。
2006年-2010年,淘宝CDN诞生,为淘宝网提供服务,随着电商业务的大力发展而不断优化,也就是“在家做饭”的阶段。到了2011年,淘宝CDN开始具备一定的对外服务能力,开始承接阿里集团所有子公司的内容分发加速服务,发展到了“宴请朋友”的阶段。直到2014年3月,阿里云CDN服务正式上线,开启了商业化之路,这也意味着任何企业或者个人用户,都可以吃到“阿里CDN”这道菜了。随后,2015年阿里云CDN宣布全面降价21%,打破了CDN行业原有的价格不透明“一客一价”的模式。并在2016、2017年不断节点扩建,相继发布了很多功能,更好的服务全球客户。
2018年阿里云CDN也注定是不平凡的一年,在年初,Gartner最新全球CDN报告中,阿里云凭借全球服务能力和产品技术优势被评为全球级(Global)服务商(国内唯一一家),即面向全球五大洲提供围绕密集商业和消费城市的接入服务。随后,阿里云CDN也推出了安全加速、全站加速、HTTPS免费证书等更多解决方案。
目前,阿里云CDN在全球有1500多个节点,带宽储备能力已经达到120Tbps。全球覆盖六个大洲,国内节点1200+,覆盖20多家运营商。
在强大的基础设施之上,阿里云CDN根据用户的典型使用场景,产品体系分为:静态加速、全站加速、安全加速、点播加速、直播加速等。虽然点播和直播加速占CDN的流量大头,但在金融政企行业中比较常见的是静态、全站和安全加速,今天罗小飞老师就为我们重点带来这三种加速产品解决方案的分享。
网页加速产品与解决方案
阿里云CDN的整个系统更趋于简单化,简单意味着更加高效和更加可靠。它主要分为边缘层和二级节点两层,边缘层负责服务用户访问,二级节点负责回源到源站。静态网页加速主要是通过缓存来实现的,由用户端第一次访问触发或主动预热。当内容被首次访问时,加速节点上没有缓存内容,加速节点就要回到客户源站获取内容并提供给用户,同时将内容缓存在加速节点上,供后续其他用户访问。
阿里云通过分布在全球的CDN节点,与智能调度、边缘缓存及传输协议优化技术,使得每个用户都能快速、可靠、安全地访问到最佳资源,保证多区域多运营商访问效果,成倍提升访问速率,大幅降低源站压力。
全站加速产品与解决方案
全站加速产品不仅涵盖了静态网页加速的能力,还能对动态内容进行加速优化。当内容从边缘节点到二级节点再到源站,CDN系统可以进行全链路的实时探测,并计算出最优路径,给用户使用。目前Vipkid、亚航、今日头条都在使用阿里云全站加速产品。
动静分离加速、智能路由、协议优化、链路复用技术,静态采用缓存 实时探测全链路,提供全天候全网高可用性 回源负载均衡、多源主备、有序回源技术降低源站压力和故障风险 全链路HTTPS安全加速(HTTPS免费证书)、回源鉴权、IP限流等保证源站安全
安全加速产品与解决方案
金融与政企网站内容安全十分重要,如果遭受攻击,后果将不堪设想。阿里云最近推出的安全加速产品集成了各种安全能力,可以有效保护网站安全。
DDoS清洗:海量DDoS清洗,完美防御SYN 、ACK 、ICMP 、UDP 、NTP 、SSDP 、DNS 、HTTP 等Flood 抗CC攻击:分布式架构天然抗CC能力 防刷:智能识别异常频繁访问陌生IP并限制其访问等方法,达到防刷 智能调度:基于阿里云飞天平台的计算能力和深度学习算法,智能预判DDoS攻击,平滑切换高防IP,不影响业务 独立节点:SCDN节点实现物理隔离,完全单独构建,深度集成安全功能,提供单节点百G高防能力 独享IP:每个用户在SCDN有一组独享IP,安全风险隔离,不会在别人受到攻击时被影响 独立SDNS调度:单用户独立调度域,用户之间DNS攻击互不影响,百万QPS的DNS Flood防护
HTTPS无私钥解决方案
不少金融政企类客户,对安全级别有更高的要求,阿里云CDN为此提供了HTTPS无私钥解决方案。这个方案是用户在CDN平台上部署证书的时候,只需要把公钥放上来,私钥不需要放上来,用户在请求到CDN平台的时候,CDN会向KeyServer发起请求,KeyServer给出响应再返回给用户。如果是已经cache的内容,直接授权通过反馈给用户内容,如果需要回源的内容再去回源,整个方案可以为客户提供更高的安全性保障。
阿里云CDN+
很多用户使用了阿里云的众多产品,接下来罗小飞老师为我们介绍了CDN与阿里云其他两款产品的典型结合,帮助用户更加方便快捷的使用服务。
阿里云CDN+云监控
云监控可以监控 CDN 的 QPS、BPS、字节命中率等 9 个监控项,用户添加一个加速域名后,云监控自动开始对其监控,用户登录云监控的 CDN 页面即可查看监控详情,并且还可以对监控项设置报警规则,以便数据异常时收到报警息,支持钉钉机器人/手机/邮箱/旺旺报警,也支持报警回调。如此一来,就能帮助用户获取域名的使用情况。而且云监控目前是免费的,欢迎用户们使用。
阿里云CDN+SLS日志服务
以前,当我们需要对CDN日志去做分析的时候,需要进行从下载、存储、分析到展示等等一系列的工作,调试、变更十分复杂,并且有小时级的延时。而现在,SLS日志服务能够非常实时的将CDN日志导入到服务系统中,没有代码、没有运维,并且可以秒级查询,灵活调整,在控制台界面就可以定制到你需要看到的分析结果。
阿里云CDN 4+1服务体系
阿里云CDN是希望用户能够自主灵活的在控制台进行业务配置,自主发现问题并且具备排查和处理的能力,这样用户对自己的业务有更高的把控和更深的了解,因此业务健康的保障性会更高。同时,阿里云CDN也具备完善的服务体系,帮助用户去解决问题。 第一层是工单体系,用户可以通过工单系统提交,7*24小时支持。 第二层IM企业群专属客户支持,俗称钉钉群,7*24小时在线对客户进行保障。 第三层是专属TAM,资深的专属技术支持人员,对客户的业务情况深入了解,处理问题非常快速。 第四层是架构师/PE,从CDN业务架构层和定制化、复杂化需求上,进行客户进行支持。 当遇到特殊的问题或者涉及到代码层处理,也可能需要研发人员来介入处理。
了解CDN产品详情
CDN学习路径
原文链接
本文为云栖社区原创内容,未经允许不得转载。
云计算
2018-06-21 17:28:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
0、引言
在构建Elasticsearch集群的初期如果集群分片设置不合理,可能在项目的中后期就会出现性能问题。Elasticsearch是一个非常通用的平台,支持各种各样的用例,并且为数据组织和复制策略提供了巨大灵活性。这种灵活性使得作为ELK新手的你将数据组织成索引和分片变得困难。虽然不一定会在首次启动时出现问题,但由于数据量随时间的推移,可能会导致性能问题。集群所拥有的数据越多,纠正问题就越困难,甚至有时可能需要重新索引大量数据。
当我们遇到遭遇性能问题的用户时,可以追溯到关于数据索引的数据和群集数量的问题并不罕见。 对于涉及multi-tenancy或使用基于时间的索引的用户尤其如此。 在与用户讨论这个问题时(会议、论坛形式),引申出的一些最常见的问题是: 1)“我应该有多少个分片?” 2)“我的分片应该有多大”? 1 2
这篇博客文章旨在帮助您回答这些问题,并为使用基于时间的索引的使用案例( 日志记录或安全分析 )提供实用的指导。
1、什么是分片?
在开始之前,让我们约定文章中用到的一些概念和术语。
Elasticsearch中的数据组织成索引。每一个索引由一个或多个分片组成。每个分片是Luncene索引的一个实例,你可以把实例理解成自管理的搜索引擎,用于在Elasticsearch集群中对一部分数据进行索引和处理查询。
【刷新】当数据写入分片时,它会定期地发布到磁盘上的新的不可变的Lucene段中,此时它可用于查询。——这被称为刷新。
【合并】随着分段数(segment)的增长,这些segment被定期地整合到较大的segments。 这个过程被称为合并(merging)。
由于所有段都是不可变的, 因为新的合并段需要创建,旧的分段将被删除 ,这意味着所使用的磁盘空间通常在索引时会波动。 合并可能资源相当密集,特别是在磁盘I/O方面。
分片是Elasticsearch在集群周围分发数据的单位。 Elasticsearch在重新平衡数据时 (例如 发生故障后) 移动分片的速度 取决于分片的大小和数量以及网络和磁盘性能。
提示:避免有非常大的分片,因为大的分片可能会对集群从故障中恢复的能力产生负面影响。 对于多大的分片没有固定的限制,但是 分片大小为50GB通常被界定为适用于各种用例的限制 。
2、索引有效期( retention period )
由于段是不可变的,更新文档需要Elasticsearch首先查找现有文档,然后将其标记为已删除,并添加更新的版本。删除文档还需要找到文档并将其标记为已删除。因此,删除的文档将继续占据磁盘空间和一些系统资源,直到它们被合并,这将消耗大量的系统资源。
Elasticsearch允许从文件系统直接删除完整索引,而不必明确地必须单独删除所有记录。这是迄今为止从Elasticsearch删除数据的最有效的方式。
提示: 尽可能使用基于时间的索引来管理数据。根据保留期(retention period,可以理解成有效期)将数据分组。基于时间的索引还可以轻松地随时间改变主分片和副本分片的数量(以为要生成的下一个索引进行更改)。这简化了适应不断变化的数据量和需求。
3、索引和分片不是空闲的?
【集群状态】对于每个Elasticsearch索引,其映射和状态的信息都存储在集群状态。 这些集群状态信息保存在内存中以便快速访问。 因此,如果在集群中拥有大量索引,可能导致大的集群状态(特别是如果映射较大)。 所有更新集群状态操作为了在集群中保证一致性,需要通过单个线程完成,因此更新速度将变慢。
提示 :为了减少索引数量并避免大的乃至非常庞大的映射,请考虑将 相同索引结构的数据存储在相同的索引中 ,而不是基于数据的来源将数据分割成独立的索引。 在每个索引的索引数量和映射大小之间找到一个很好的平衡很重要。**
每个分片都有数据需要保存在内存中并使用堆空间。 这包括在分片级别保存信息的数据结构,也包括在段级别的数据结构,以便定义数据驻留在磁盘上的位置。 这些数据结构的大小不是固定的,并且将根据用例而有所不同。
然而,段相关开销的一个重要特征是它与分段的大小不成正比。 这意味着与较小的段相比,较大的段的每个数据量具有较少的开销,且这种差异很大。
【堆内存的重要性】为了能够每个节点存储尽可能多的数据,重要的是尽可能多地管理堆内存使用量并减少其开销。 节点拥有的堆空间越多,它可以处理的数据和分片越多。
因此,索引和分片从集群的角度看待不是空闲的,因为每个索引和分片都有一定程度的资源开销。
提示1 :小分片会导致小分段(segment),从而增加开销。目的是保持平均分片大小在几GB和几十GB之间。对于具有基于时间的数据的用例,通 常看到大小在20GB和40GB之间的分片 。
提示2 :由于每个分片的开销取决于分段数和大小,通过强制操作迫使较小的段合并成较大的段可以减少开销并提高查询性能。一旦没有更多的数据被写入索引,这应该是理想的。请注意,这是一个消耗资源的(昂贵的)操作,较为理想的处理时段应该在非高峰时段执行。
提示3 :您可以在集群节点上保存的分片数量与您可用的堆内存大小成正比,但这在Elasticsearch中没有的固定限制。 一个很好的经验法则是:确保每个节点的分片数量保持在低于 每1GB堆内存对应集群的分片在20-25之间 。 因此,具有30GB堆内存的节点最多可以有600-750个分片,但是进一步低于此限制,您可以保持更好。 这通常会帮助群体保持处于健康状态。
4、分片的大小如何影响性能?
在Elasticsearch中,每个查询在每个分片的单个线程中执行。然而,可以并行处理多个分片,并可以在相同分片上执行多个查询和聚合。
【小分片的利弊】这意味着,在不涉及高速缓存时,最小查询延迟将取决于数据、查询的类型、分片的大小。查询大量小分片将使得每个分片的处理速度更快,但是随着更多的任务需要按顺序排队和处理,它不一定要比查询较小数量的更大的分片更快。如果有多个并发查询,则有很多小碎片也会降低查询吞吐量。
提示:从查询性能角度确定最大分片大小的最佳方法是使用逼真的数据和查询进行基准测试(真实数据而非模拟数据)。 始终使用查询和索引负载进行基准测试,代表节点在生产中需要处理的内容,因为单个查询的优化可能会产生误导性的结果。
5、如何管理分片大小?
当使用基于时间的索引时,每个索引传统上都与固定的时间段相关联。 每日索引非常普遍,经常用于持有时间区间短或每日量大的数据。 这些允许数据期限期间以良好的粒度进行管理,并且可以方便地对每天更换调整volumes。
时间周期长的数据,特别是如果每日不保存每天的索引数据,则通常会使用每周或每月的保存的碎片大小的增加。 这减少了随着时间的流逝需要存储在群集中的索引和碎片数量大小(直译有点费劲此处)。
提示:如果使用固定期限的时间索引数据,可以 根据时间周期 和 预期数据量 调整所涵盖的时间范围,以达到目标分片大小。
【均匀更新&快速变化的索引数据对比】具有固定时间间隔的基于时间的索引在数据量合理预测并且变化缓慢的情况下工作良好。 如果索引率可以快速变化,则很难保持均匀的目标分片大小。
为了能够更好地处理这种情况,推出了 Rollover 和S**hrink API**。 这些增加了如何管理索引和分片的灵活性,尤其适用于基于时间的索引。
此处省略了 Rollover和Shrink API的介绍。(建议查询官网补齐概念再深入)
6、结论
这篇博客文章提供了有关如何在Elasticsearch中最好地管理数据的提示和实用指南。 如果您有兴趣了解更多,推荐阅读Google搜索 “Elasticsearch: the definitive guide” (有点旧,值得阅读)。
然而,关于如何最好地在索引和分片上分发数据的许多决策将取决于用例细节,有时可能难以确定如何最佳地应用可用的建议。
文章提及的几个核心建议清单如下,以回答文章开头的提问。 1) “我应该有多少个分片?” 答: 每个节点的分片数量保持在低于每1GB堆内存对应集群的分片在20-25之间。 2) “我的分片应该有多大”? 答:分片大小为50GB通常被界定为适用于各种用例的限制。
云计算
2018-06-21 11:14:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
谈到Service Mesh微服务架构,就不得不谈Sidecar模式——一种单节点、多容器的应用设计形式。Sidecar主张以额外的容器来扩展或增强主容器,而这个额外的容器被称为Sidecar容器。
一些例子如下:
Web-server容器可以与一个sidecar容易共同部署,该sidecar容器从文件系统中读取由Web-server容器生成的web-server日志,并将日志/stream发送到原称服务器(remote server)。Sidecar容器通过处理web-server日志来作为web-server容器的补充。当然,可能会有人说,为什么web-server不自己处理自己的日志?答案在于以下几点: 隔离(separation of concerns):让每个容器都能够关注核心问题。比如web-server提供网页服务,而sidecar则处理web-server的日志,这有助于在解决问题时不与其他问题的处理发生冲突; 单一责任原则(single responsibility principle):容器发生变化需要一个明确的理由。换句更容易理解的话来说,每个容器都应该是能够处理好“一件”事情的,而根据这一原则,我们应该让不同的容器分别展开工作,应该让它们处理的问题足够独立; 内聚性/可重用性(Cohesiveness/Reusability):使用sidecar容器处理日志,这个容器按道理应该可以应用的其他地方重用;
以上例子正如下图所示:
另一个例子是在web-server容器与sidecar容器共同部署时,将文件系统与git存储库同步。(我们需要注意Git同步容器的重用醒)如下图所示,应用容器知识链接到本地机器的Redis服务器上:
开源PaaS Rainbond v3.6.0版本现已发布,提供Service Mesh微服务架构的开箱即用,插件式扩展治理功能,并支持spring cloud、api gateway、dubbo等框架。
进一步了解: Rainbond 技术 开源PaaS Rainbond v3.6.0正式发布,Service Mesh开箱即用 技术 解读Rainbond ServiceMesh微服务架构_开源PaaS Rainbond 2018/05/15 技术 Pinpoint-java性能分析最佳实践_开源PaaS Rainbond 2018/05/08 技术 通过Minio搭建私有化对象存储服务_开源PaaS Rainbond 2018/04/26 技术 揭秘高可用负载均衡组件Rainbond-Entrance_开源PaaS Rainbond 2018/04/25 技术 Rainbond插件体系设计简介_开源PaaS Rainbond 2018/02/24 技术 Rainbond如何对接外部Maven仓库_开源PaaS Rainbond 2018/01/18 技术 Spring Boot框架配置MySQL_开源PaaS Rainbond 2018/01/10 技术 基于Midonet的多租户网络设计_开源PaaS Rainbond 2018/01/09
云计算
2018-06-21 10:55:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
摘要: 日志数据采集与分析对接 课程描述 通过日志服务采集用户、数据库、业务等访问数据。演示对于业务日志分析与处理,程序日志查询与监控,打通日志与数据仓库对接案例。 日志种类 网站访问日志准备步骤 & 依赖 ECS虚拟机(测试账号默认包含,并且访问日志产生) OSSBucket 用做数据仓库,存储日志服.
日志数据采集与分析对接
课程描述
通过日志服务采集用户、数据库、业务等访问数据。演示对于业务日志分析与处理,程序日志查询与监控,打通日志与数据仓库对接案例。
日志种类 网站访问日志
准备步骤 & 依赖 ECS虚拟机(测试账号已默认创建虚拟机- ECS控制台 ) OSSBucket 用做数据仓库,存储日志服务同步的各类数据 RAM服务 生成RAM角色用于同步日志数据至OSSBucket
操作步骤 日志采集配置 登陆 日志服务控制台 ,选择 华东1 创建日志服务project,其中Project名称全局唯一,建议名称加上登陆账号前缀进行区别
创建logstore存储访问日志
向导创建NGINX日志采集
配置文件路径(/var/log)和文件名称(access_log),其中NGINX日志配置为: log_format web_site_com '"$remote_addr" "$remote_user" "[$time_local]" "$request" ' '"$status" "$body_bytes_sent" "$http_referer" "$http_user_agent" "$host" ' '"$http_x_forwarded_for" "$request_time" "$request_length" "$remote_port" ' '"$upstream_response_time"';
创建机器组(打开 ECS控制台 获取机器IP地址)
开启日志分析
开启数仓同步
打开 OSS控制台 ,可以看到一个以 workshop 名称开头的bucket,复制名称至“OSS Bucket”输入框
授权日志服务同步数据至OSS(点击 授权链接 )
获取RAM角色名称(点击 链接 )
指定OSSBucket同步指定日志数据(其中可填入字段名称包括:request_method,request_time,remote_addr,request_length,http_user_agent等在查询页面看到的所有字段)
日志查询分析 根据关键词查询访问日志
分析统计NGINX访问日志(预置仪表盘使用:包含地图/各类基本图形等)
数仓同步 等待1-2min后,可以在OSS中看到生成的数据目录
实验耗费 ECS虚拟机 日志服务 OSS存储
原文链接
本文为云栖社区原创内容,未经允许不得转载。
云计算
2018-06-20 17:14:00
「深度学习福利」大神带你进阶工程师,立即查看>>>


今天收到了来自Apache Vote我成为Serviceomb项目Committer的邮件,代表自己的贡献得到了充分的肯定;除了感谢团队的给力支持,我更希望将自己的成长经历——如何践行Apache Way的心得介绍给大家,让大家爱上Apache开源社区,也能和我一样成长为自己喜爱项目的Committer。
根据个人贡献获得价值(Government By Merit)
回忆我刚参与ServiceComb项目,面对上万行的存量代码,总觉得无从下手,甚至认为开源社区高手如云,如果没有深厚且对口的技术功底,还是不要来掺和了。
在这个困难而关键的时候,社区导师给了我明确的指导——不要怕,从小事做起,不要“善小而不为”。于是我静下心来,在Jira上寻找最简单的任务,主动请缨的第一个任务是支持配置兼容,具体需求是 cse.xxx 配置项和 servicecomb.xxx 配置项要具备等同效果,经过一番努力,成功Merge PR ;之后我又接下另一个简单任务,增加一个Annotation用于支持Json String作为请求参数……
Apache Way非常看重个人贡献,没有贡献,一切无从谈起,与开源软件同行,不仅看你获得了多少,更要坚持长期贡献,这是它与商业软件最大的不同。贡献并不区分大小,无论是增加重大特性,还是小小的改进、Bug Fix和修订文档错误,这些同样是项目茁壮成长的关键。
实际上大多数开源爱好者都是从修订文档错误开始的,例如改正错别字、格式不正确以及订正描述等等,我对ServiceComb的理解也绝大多数来自这方面的工作;这样不但能够在阅读文档的过程中更快的了解技术细节,也比较容易入手做出贡献。
总之坚持下来,个人积累的贡献慢慢变厚,获得Apache的认可自然水到渠成。
社区驱动(Community)
参与社区是技术成长最快的方式之一,Follow Apache社区的方式有 订阅邮件列表 和加入 Gitter聊天室 ;从看大家讨论(讨论邮件一般会使用[Discussion]开头),到回答大家的问题(回复邮件和发送Gitter聊天),相信用不了多久你就能收获颇丰,并冒出自己的想法,迈出第一步提交第一个PR也就不难了。
ServiceComb作为一个微服务一站式解决方案,融合侵入式、非侵入式场景并支持多语言,解放开发者,帮助用户和开发者将企业应用轻松微服务化和上云;大家在这里讨论的话题、发起的投票、以及提交的代码,无不与微服务密切相关。在这个社区中我不但学习到了知识,完成了开源(也包含微服务)小白的蜕变,还进一步接受了开源的洗礼——前辈指导我进步,我将所学传递给新人;这个过程中我结识了很多新朋友,大家互通有无,不但极大的开阔了视野,也提高了自己的社交能力。
Apache开发者来自全球,社区大多都是用英文来交流。通过阅读英文资料,使用英文在Gitter[2]上与开发人员直接交流,通过英文邮件来探讨问题,在不知不觉中自己的英文水平也大大提高了。
协作开发(Collaborative Development)
这也是我极力推荐参与开源社区开发的重要原因之一,当你提交PR后,无论代码有多么烂,你总能收获宝贵的Comments,不花钱获得编程大师的指点——教你怎么写出优秀的代码,这是多么合算的买卖!
我在参与ServiceComb社区前,只知道Java基本语法,IDE不熟练(之前一直是用VS写C#,不使用Eclipse和IntelliJ IDEA),不会Git,不懂Maven,还能有更糟糕的起点吗:)
不用担心,社区会指导你。我前文提到的第一个简单的任务,花费了将近一周时间,被打回来了四五次后才被Merge;一个PR收获60+ Comments也是家常便饭。这个过程中我的Java水平成长得飞快,不久后就能独立承担新特性的设计和开发—— Metrics ,当然,完成这个新特性的过程中Committer和其他开发者给予了很多支持,所以,请大胆的提交你的第一个PR,成为一名Contributor吧。
民主,开放和透明(Consensus, Open and Transparency)
在Apache社区里投票至关重要,你可以感受到你的建议将被充分重视,我很喜欢这种参与感;大家的讨论和建议也完全公开透明,并且能够长时间通过邮件列表查询到,沟通效率非常高。所以大家多多参与,一定能收获惊喜,从万能的社区里寻找自己想要的答案,请记住,当你对某个问题产生困惑,即使是强大的StackOverflow也不会有原作者的答复更为准确。
我可以做哪些贡献
你想快速上手,可以在JIRA列表中 认领newbie的任务 。
你规划能力强,可以在邮件列表里为 ServiceComb的发展出谋划策 ;
你擅长设计,可以为 ServiceComb的网站和VI提出自己的意见 ;
你热爱写作,ServiceComb更是欢迎你来补充文档,将 ServiceCenter的英文文档翻译 成中文或许是个不错的上手选择[7]。
写在最后
最后,我想说从一名开源小白成长为Apache Committer并不是无比艰难又遥不可及的事情,只需要日积月累的在社区中投入一点业余时间,就能梦想成真。当然最好找到自己感兴趣的社区,这会让这段旅途更加愉快,也能交到更多志同道合的的朋友。

广告时间:我所在的Apache ServiceComb(incubating)正持续招募贡献者,非常欢迎大家加入,让我们一起构建更好的微服务框架,点击 了解更多 。
云计算
2018-06-20 11:25:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
概述
日志从最初面向人类演变到现在的面向机器发生了巨大的变化。最初的日志主要的消费者是软件工程师,他们通过读取日志来排查问题,如今,大量机器日夜处理日志数据以生成可读性的报告以此来帮助人类做出决策。在这个转变的过程中,日志采集Agent在其中扮演着重要的角色。
作为一个日志采集的Agent简单来看其实就是一个将数据从源端投递到目的端的程序,通常目的端是一个具备数据订阅功能的集中存储,这么做的目的其实是为了将日志分析和日志存储解耦,同一份日志可能会有不同的消费者感兴趣,获取到日志后所处理的方式也会有所不同,通过将数据存储和数据分析进行解耦后,不同的消费者可以订阅自己感兴趣的日志,选择对应的分析工具进行分析。像这样的具备数据订阅功能的集中存储业界比较流行的是 Kafka ,对应到阿里巴巴内部就是 DataHub 还有阿里云的 LogHub 。而数据源端大致可以分为三类,一类就是普通的文本文件,另外一类则是通过网络接收到的日志数据,最后一类则是通过共享内存的方式,本文只会谈及第一类。一个日志采集Agent最为核心的功能大致就是这个样子了。在这个基础上进一步又可以引入日志过滤、日志格式化、路由等功能,看起来就好像是一个生产车间。从日志投递的方式来看,日志采集又可以分为推模式和拉模式,本文主要分析的是推模式的日志采集。 推模式是指日志采集Agent主动从源端取得数据后发送给目的端,而拉模式指的是目的端主动向日志采集Agent获取源端的数据
业界现状
目前业界比较流行的日志采集主要有 Fluentd 、 Logstash 、 Flume 、 scribe 等,阿里巴巴内部则是 LogAgent 、阿里云则是 LogTail ,这些产品中 Fluentd 占据了绝对的优势并成功入驻CNCF阵营,它提出的统一日志层( Unified Logging Layer )大大的减少了整个日志采集和分析的复杂度。 Fluentd 认为大多数现存的日志格式其结构化都很弱,这得益于人类出色的解析日志数据的能力,因为日志数据其最初是面向人类的,人类是其主要的日志数据消费者。为此 Fluentd 希望通过统一日志存储格式来降低整个日志采集接入的复杂度,假想下输入的日志数据比如有M种格式,日志采集Agent后端接入了N种存储,那么每一种存储系统需要实现M种日志格式解析的功能,总的复杂度就是 M*N ,如果日志采集Agent统一了日志格式那么总的复杂度就变成了 M + N 。这就是 Fluentd 的核心思想,另外它的插件机制也是一个值得称赞的地方。 Logstash 和 Fluentd 类似是属于 ELK 技术栈,在业界也被广泛使用,关于两者的对比可以参考这篇文章 Fluentd vs. Logstash: A Comparison of Log Collectors
unified-logging-pluggable.png
从头开始写一个日志采集Agent
作为一个日志采集Agent在大多数人眼中可能就是一个数据“搬运工”,还会经常抱怨这个“搬运工”用了太多的机器资源,简单来看就是一个 tail -f 命令,再贴切不过了,对应到 Fluentd 里面就是 in_tail 插件。笔者作为一个亲身实践过日志采集Agent的开发者,希望通过本篇文章来给大家普及下日志采集Agent开发过程中的一些技术挑战。为了让整篇文章脉络是连续的,笔者试图通过“从头开始写一个日志采集Agent”的主题来讲述在整个开发过程中遇到的问题。
如何发现一个文件?
当我们开始写日志采集Agent的时候遇到的第一个问题就是怎么发现文件,最简单的方式就是用户直接把要采集的文件罗列出来放在配置文件中,然后日志采集Agent会读取配置文件找到要采集的文件列表,最后打开这些文件进行采集,这恐怕是最为简单的了。但是大多数情况日志是动态产生的,会在日志采集的过程中动态的创建出来, 提前罗列到配置文件中就太麻烦了。正常情况下用户只需要配置一个日志采集的目录和文件名字匹配的规则就可以了,比如Nginx的日志是放在 /var/www/log 目录下,日志文件的名字是 access.log 、 access.log-2018-01-10 …..类似于这样的形式,为了描述这类文件可以通过通配符或者正则的表示来匹配这类文件例如: access.log(-[0-9]{4}-[0-9]{2}-[0-9]{2})? 有了这样的描述规则后日志采集Agent就可以知道哪些文件是需要采集的,哪些文件是不用采集的。接下来会遇到另外一个问题就是如何发现新创建的日志文件?,定时去轮询下目录或许是个不错的方法,但是轮询的周期太长会导致不够实时,太短又会耗CPU,你也不希望你的采集Agent被人吐槽占用太多CPU吧。Linux内核给我们提供了高效的 Inotify 的机制,由内核来监测一个目录下文件的变化,然后通过事件的方式通知用户。但是别高兴的太早, Inotify 并没有我们想的那么好,它存在一些问题,首先并不是所有的文件系统都支持 Inotify ,此外它不支持递归的目录监测,比如我们对A目录进行监测,但是如果在A目录下面创建了B目录,然后立刻创建C文件,那么我们只能得到B目录创建的事件,C文件创建的事件就会丢失,最终会导致这个文件没有被发现和采集。对于已经存在的文件 Inotify 也无能为力, Inotify 只能实时的发现新创建的文件。 Inotify manpage 中描述了更多关于 Inotify 的一些使用上的限制以及bug。如果你要保证不漏采那么最佳的方案还是 Inotify+轮询 的组合方式。通过较大的轮询周期来检测漏掉的文件和历史文件,通过 Inotify 来保证新创建的文件在绝大数情况下可以实时发现,即使在不支持 Inotify 的场景下,单独靠轮询也能正常工作。到此为止我们的日志采集Agent可以发现文件了,那么接下来就需要打开这个文件,然后进行采集了。但是天有不测风云,在我们采集的过程中机器 Crash 掉了,我们该如何保证已经采集的数据不要再采集了,能够继续上次没有采集到的地方继续呢? 基于轮询的方式其优点就是保证不会漏掉文件,除非文件系统发生了bug,通过增大轮询的周期可以避免浪费CPU、但是实时性不够。Inotify虽然很高效,实时性很好但是不能保证100%不丢事件。因此通过结合轮询和Inotify后可以相互取长补短。
点位文件高可用
点位文件? 对就是通过点位文件来记录文件名和对应的采集位置。那如何保证这个点位文件可以可靠的写入呢? 因为可能在文件写入的那一刻机器Crash了导致点位数据丢掉或者数据错乱了。要解决这个问题就需要保证文件写入要么成功,要么失败,绝对不能出现写了一半的情况。Linux内核给我们提供了原子的 rename 。一个文件可以原子的 rename 成另外一个文件,利用这个特性可以保证点位文件的高可用。假设我们已经存在一份点位文件叫做 offset ,每一秒我们去更新这个点位文件,将采集的位置实时的记录在里面,整个更新的过程如下: 将点位数据写入到磁盘的 offset.bak 文件中 fdatasync 确保数据写入到磁盘 通过 rename 系统调用将 offset.bak 更名为 offset
通过这个手段可以保证在任何时刻点位文件都是正常的,因为每次写入都会先确保写入到临时文件是成功的,然后原子的进行替换。这样就保证了 offset 文件总是可用的。在极端场景下会导致1秒内的点位没有及时更新,日志采集Agent启动后会再次采集这1秒内的数据进行重发,这基本上满足需求了。
但是点位文件中记录了文件名和对应的采集位置这会带来另外一个问题,如果在进程Crash的过程中,文件被重命名了该怎么办? 那启动后岂不是找不到对应的采集位置了。在日志的这个场景下文件名其实非常不可靠,文件的重命名、删除、软链等都会导致相同的文件名在不同时刻其实指向的是不同的文件,而且将整个文件路径在内存中保存其实是非常耗费内存的。Linux内核提供了 inode 可以作为文件的标识信息,而且保证同一时刻 Inode 是不会重复的,这样就可以解决上面的问题,在点位文件中记录文件的inode和采集的位置即可。日志采集Agent启动后通过文件发现找到要采集的文件,通过获取 Inode 然后从点位文件中查找对应的采集位置,最后接着后面继续采集即可。那么即使文件重命名了但是它的 Inode 不会变化,所以还是可以从点位文件中找到对应的采集位置。但是 Inode 有没有限制呢? 当然有,天下没有免费的午餐,不同的文件系统 Inode 会重复,一个机器可以安装多个文件系统,所以我们还需要通过dev(设备号)来进一步区分,所以点位文件中需要记录的就是 dev、inode、offset 三元组。到此为止我们的采集Agent可以正常的采集日志了,即使Crash了再次启动后仍然可以继续进行采集。但是突然有一天我们发现有两个文件居然是同一个 Inode ,Linux内核不是保证同一时刻不会重复的吗?难道是内核的bug?注意我用的是“同一时刻”,内核只能保证在同一时刻不会重复,这到底是什么意思呢? 这便是日志采集Agent中会遇到的一个比较大的技术挑战,如何准确的标识一个文件。
如何识别一个文件?
如何标识一个文件算是日志采集Agent中一个比较有挑战的技术问题了,我们先是通过文件名来识别,后来发现文件名并不可靠,而且还耗费资源,后来我们换成了 dev+Inode ,但是发现 Inode 只能保证同一时刻 Inode 不重复,那这句话到底是什么意思呢? 想象一下在T1时刻有一个文件 Inode 是1我们发现了并开始采集,一段时间后这个文件被删除了,Linux内核就会将这个 Inode 释放掉,新创建一个文件后Linux内核会将刚释放的 Inode 又分配给这个新文件。那么这个新文件被发现后会从点位文件中查询上次采集到哪了,结果就会找到之前的那个文件记录的点位了,导致新文件是从一个错误的位置进行采集。如果能给每一个文件打上一个唯一标识或许就可以解决这个问题,幸好Linux内核给文件系统提供了扩展属性 xattr ,我们可以给每一个文件生成唯一标识记录在点位文件中,如果文件被删除了,然后创建一个新的文件即使 Inode 相同,但是文件标识不一样,日志采集Agent就可以识别出来这是两个文件了。但是问题来了,并不是所有的文件系统都支持 xattr 扩展属性。所以扩展属性只是解了部分问题。或许我们可以通过文件的内容来解决这个问题,可以读取文件的前N个字节作为文件标识。这也不失为一种解决方案,但是这个N到底取多大呢? 越大相同的概率越小,造成无法识别的概率就越小。要真正做到100%识别出来的通用解决方案还有待调研,姑且认为这里解了80%的问题吧。接下来就可以安心的进行日志采集了,日志采集其实就是读文件了,读文件的过程需要注意的就是尽可能的顺序读,充份利用Linux系统缓存,必要的时候可以用 posix_fadvise 在采集完日志文件后清除页缓存,主动释放系统资源。那么什么时候才算采集完一个文件呢? 采集到末尾返回EOF的时候就算采集完了。可是一会日志文件又会有新内容产生,如何才知道有新数据了,然后继续采集呢?
inode.png
如何知道文件内容更新了?
Inotify 可以解决这个问题、通过 Inotify 监控一个文件,那么只要这个文件有新增数据就会触发事件,得到事件后就可以继续采集了。但是这个方案存在一个问题就是在大量文件写入的场景会导致事件队列溢出,比如用户连续写入日志N次就会产生N个事件,其实对于日志采集Agent只要知道内容就更新就可以了,至于更新几次这个反而不重要, 因为每次采集其实都是持续读文件,直到EOF,只要用户是连续写日志,那么就会一直采集下去。另外 Intofy 能监控的文件数量也是有上限的。所以这里最简单通用的方案就是轮询去查询要采集文件的stat信息,发现文件内容有更新就采集,采集完成后再触发下一次的轮询,既简单又通用。通过这些手段日志采集Agent终于可以不中断的持续采集日志了,既然是日志总会有被删除的一刻,如果在我们采集的过程中被删除了会如何? 大可放心,Linux中的文件是有引用计数的,已经打开的文件即使被删除也只是引用计数减1,只要有进程引用就可以继续读内容的,所以日志采集Agent可以安心的继续把日志读完,然后释放文件的fd,让系统真正的删除文件。但是如何知道采集完了呢? 废话,上面不是说了采集到文件末尾就是采集完了啊,可是如果此刻还有另外一个进程也打开了这个文件,在你采集完所有内容后又追加了一段内容进去,而你此时已经释放了fd了,在文件系统上这个文件已经不在了,再也没办法通过文件发现找到这个文件,打开并读取数据了,这该怎么办?
如何安全的释放文件句柄?
Fluentd 的处理方式就是将这部分的责任推给用户,让用户配置一个时间,文件删除后如果在指定的时间范围内没有数据新增就释放fd,其实这就是间接的甩锅行为了。这个时间配置的太小会造成丢数据的概率增大,这个时间配置的太大会导致fd和磁盘空间一直被占用造成短时间自由浪费的假象。这个问题的本质上其实就是我们不知道还有谁在引用这个文件,如果还有人在引用这个文件就可能会写入数据,此时即使你释放了fd资源仍然是占用的,还不如不释放,如果没有任何人在引用这个文件了,那其实就可以立刻释放fd了。如何知道谁在引用这个文件呢? 想必大家都用过 lsof -f 列出系统中进程打开的文件列表,这个工具通过扫描每一个进程的 /proc/PID/fd/ 目录下的所有文件描述符,通过 readlink 就可以查看这个描述符对应的文件路径,例如下面这个例子:
tianqian-zyf@ubuntu:~$ sudo ls -al /proc/22686/fd total 0 dr-x------ 2 tianqian-zyf tianqian-zyf 0 May 27 12:25 . dr-xr-xr-x 9 tianqian-zyf tianqian-zyf 0 May 27 12:25 .. lrwx------ 1 tianqian-zyf tianqian-zyf 64 May 27 12:25 0 -> /dev/pts/19 lrwx------ 1 tianqian-zyf tianqian-zyf 64 May 27 12:25 1 -> /dev/pts/19 lrwx------ 1 tianqian-zyf tianqian-zyf 64 May 27 12:25 2 -> /dev/pts/19 lrwx------ 1 tianqian-zyf tianqian-zyf 64 May 27 12:25 4 -> /home/tianqian-zyf/.post.lua.swp
22686 这个进程就打开了一个文件,fd是4,对应的文件路径是 /home/tianqian-zyf/.post.lua.swp 。通过这个方法可以查询到文件的引用计数,如果引用计数是1,也就是只有当前进程引用,那么基本上可以做到安全的释放fd,不会造成数据丢失,但是带来的问题就是开销有点大,需要遍历所有的进程查看它们的打开文件表逐一的比较,复杂度是 O(n) ,如果能做到 O(1) 这个问题才算完美解决。通过搜索相关的资料我发现这个在用户态来做几乎是没有办法做到的,Linux内核没有暴露相关的API。只能通过 Kernel 的方式来解决,比如添加一个API通过fd来获取文件的引用计数。这在内核中还是比较容易做到的,每一个进程都保存了打开的文件,在内核中就是 struct file 结构,通过这个结构就可以找到这个文件对应的 struct inode 对象,这个对象内部就维护了引用计数值。期待后续Linux内核能够提供相关的API来完美解决这个问题吧。
p-fd.png
总结
到此为此,一个基于文件的采集Agen涉及到的核心技术点都已经介绍完毕了,这其中涉及到很多文件系统、Linux相关的知识,只有掌握好这些知识才能更好的驾驭日志采集。想要编写一个可靠的日志采集Agent确保数据不丢失,这其中的复杂度和挑战不容忽视。希望通过本文能让读者对日志采集有一个较为全面的认知。
云计算
2018-06-20 09:35:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
摘要: 阿里云正式发布旗下众包平台业务(网址:https://zhongbao.aliyun.com/),支持包括:网站定制开发,APP、电商系统等软件开发,商标、商品LOGO、VI、产品包装设计、营销推广、大数据人工智能等各类企业上云、数字化转型服务。
阿里云正式发布旗下众包平台业务(网址: https://zhongbao.aliyun.com/ ),支持包括:网站定制开发,APP、电商系统等软件开发,商标、商品LOGO、VI、产品包装设计、营销推广、大数据人工智能等各类企业上云、数字化转型服务。
1、平台特色担保服务:给项目免费上保险?!
通过与蚂蚁金服联合第三方保险公司,发布其平台特色服务:免费项目保险担保。凡发布在阿里云众包平台的需求,在与服务商沟通确认下单后都会获得一份由保险公司担保的 免费的项目保险 。此项服务就是要解决困扰外包需求客户:保证金无法覆盖保证项目,付款出现问题无法追偿的难题。
2、120天超长质保服务
截止到平台发布日起,在业内平台敢于承诺的最长的质保服务期。经过多方走访,我们发现其实在众多外包的定制服务项目中,产品的一些细节问题是在后续的使用过程中才会发现,短短的几天验收期也是无法发现的。为此,阿里云众包平台携手平台服务商给予所有需求用户,提供最低120天的质保服务承诺。
3、所有入驻众包平台的服务商:免保证金、免抽佣
对,亲们没有看错,存在当前市场很长时间的保证金以及抽佣,阿里云众包平台全部不再进行收取。这一条,直观看上去感觉好像和我们需求用户没什么关系,但是阿里云通过走访众多服务商后,我们发现占据中国外包市场半壁江山的:网站、软件、设计领域其项目利润空间有限。我们将平台佣金费用让渡给平台服务商,本质目的还是要降低我们需求客户的实施成本,引入实施能力更强的服务商,能够有动力为我们的需求客户提供更上程的定制服务。
这里可能有效小伙伴要有所顾虑了:你们保证金、抽佣不要了,那么服务商会不会不靠谱啊?!……

请不要着急,请继续往下看:众包平台服务商入驻筛选过程,所有入驻阿里云众包平台的服务商要经过四个审核流程步骤:
1.阿里云帐号在线企业认证;
2.通过众包平台提供企业营业执照、历史案例及合同等入驻材料,众包平台进行人工审核;
3.初步电话沟通合作定制服务分类意愿;
4.实地考核服务商办公场地、环境、人员情况;
只有全部通过以上的审核并通过后,才能够成为阿里云众包平台的服务商。
目前,阿里云众包平台已上线并支持需求发布,点击链接: http://zhongbao.aliyun.com
即可访问并发布需求。
4、通过以下小视频代表,可以更加细致了解众包平台的服务商能力:
正邦设计:
正邦成立于1996年,专注品牌与设计20多年,全公司700余人,总部北京,上海广州设有分公司,规模行业一直领先。
点击观看小视频:
http://cloud.video.taobao.com/play/u/2893297392/p/1/e/6/t/1/50165532830.mp4
博雅立方&镖狮
大数据智能营销服务商博雅立方创立于08年,16年在主板上市。镖狮网创立于2015年,定位服务中小企业的网络推广服务。十年来我们为包括达内教育、大地保险、南方航空等大中小型企业客户,提供了包括:新媒体营销、网站建设、品牌文案、口碑营销、搜索引擎营销等专业服务。
点击观看小视频:
http://cloud.video.taobao.com/play/u/2893297392/p/1/e/6/t/1/50165632284.mp4
云顶云
我们创始团队从2013年拥抱阿里云,5年来一直致力于为企业客户提供自上而下的云计算与大数据全方位解决方案,包括上云咨询、迁云实施、云运维托管等一站式上云服务;服务的企业客户包括天津工业互联网平台、深圳乐摇摇、天津市北方人才培训中心等。
点击观看小视频:
http://cloud.video.taobao.com/play/u/2893297392/p/1/e/6/t/1/50165594714.mp4
云梦网络
云梦网络创立于2013年,是阿里云北京授权服务中心,也是阿里云市场首批入驻网站建设服务商。云梦网络已经拥有超过30万家企业用户,同时国内也有近千家网络公司是采用了云梦的技术为客户提供网站建设服务。
点击观看小视频:
http://cloud.video.taobao.com/play/u/2893297392/p/1/e/6/t/1/50165582798.mp4

阿里云众包平台用户手册请点击链接查看:
《众包平台用户指南》
https://help.aliyun.com/document_detail/72468.html?spm=a2c4g.11186623.6.576.0c8CJj
《众包平台服务FAQ》
https://help.aliyun.com/knowledge_detail/72710.html?spm=a2c4g.11186623.6.575.Zj6scs
原文链接
本文为云栖社区原创内容,未经允许不得转载。
云计算
2018-06-19 18:01:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
关于为自己搭建简历网页的详细教程:
【云计算的1024种玩法】为求职加分:为自己建个炫酷的简历网页
对于我们学生来说,个人简历是以后走向工作岗位的第一把钥匙,一份优秀而又美观新颖的简历不仅会让你与其他人与众不同脱颖而出,甚至还可以让面试官因为你的独特而额外加分呢。我相信大部分同学都对自己的简历有着十分的重视,我也是其中之一。
一般来说我们都是用office来制作自己的简历,但是这样的简历需要一个模板而这个模板基本上都是从网上下载很有可能会和别人相似,体现不出自己的独特性,不够出彩。然而通过一个偶然的机会我接触到了阿里云的产品,发现它有着众多强大的功能,其中之一就是可以通过它的服务器来完善自己的简历而且十分方便操作也十分简单。接下来我就把这项酷炫的技术分享给大家,同学们要好好学习哦。
一. 搭建服务器以及安装软件
首先我们要登陆阿里云的官方网站,账号可以新注册也可以用淘宝或者支付宝账号登录,相信大家基本上都有支付宝吧,所以十分方便。
如果是学生的话可以进行学生认证,只需要9.9元/月,对于我们学生党来说简直太划算了。值得注意的是学生认证只能进行三次,所以要仔细的填选千万别浪费了机会。
接着我们要配置镜像,在这里需要注意的是我们用的是LAMP环境(Ubuntu16.04 Apache PHP7.1)要注意镜像的版本,一般来说学生版的是PHP5.6,所以我们就需要在镜像市场上搜索7.1的版本购买并更换。因为镜像是免费的并不收费所以请大家放心使用哦。然后在网址上输入http://你的公网iP/就可以访问了。
接下来就是我们最重要的一步:简历的制作了。在这一部分我们将使用Visual Studio Code(简称VSC) 编辑并制作简历页面。我们通过编写代码来实现简历的编辑,排版以及美化。
最后我们需要将制作好的简历上传到服务器上,这里我们推荐FileZilla,而且非常好用的跨平台 FTP 软件,支持中文哟。
到这里我们所有的准备工作都已经结束了,接下来让我们一起体验下效果吧。
我在这里给大家几点做简历的建议: 结构合理,段落要清晰,重点要有所突出。 控制篇幅,一份简历不应该超过两页纸,如果是中英文的话就不该超过四页,此外对于外贸公司来说一份英文简历是十分必要的。另外错别字一定不要出现。 在有些情况下要写明自己想要申请的职位名称,不要让别人帮你决定。 注意用词的准确性和力度,比如在一个项目中你所担任的角色一定不要模棱两可,必须要明确的指出你是Lead还是Participate等等,当然要实事求是不要自吹自擂。 最好有个简单的概括,包括你的经验,技能,成绩,科研成果等等,清晰明了让面试官一眼就能看到你的深度。
其实阿里云好多的功能我们都可以用的到,希望大家能够和我一起在接下来的日子里继续学习让自己的简历上再添一笔。
更多精品课程:
7天玩转云服务器
云数据库的Redis版使用教程
玩转云存储对象存储OSS使用入门
阿里云CDN使用教程
负载均衡入门与产品使用指南
阿里云大学官网( 阿里云大学 - 官方网站,云生态下的创新人才工场 )
云计算
2018-05-15 16:27:00
「深度学习福利」大神带你进阶工程师,立即查看>>> 从技术实现的维度解读开源PaaS Rainbond如何支持ServiceMesh微服务架构
当我们谈论微服务架构时,我们在谈论什么?
服务发现和注册、弹性伸缩与负载均衡、容错处理(断路器与限流)、监控与报警、数据存储与共享、日志分析……
除了以上自然联想到的技术点,还有如Spring Cloud、Dubbo这样在过去几年受到广泛关注和应用的微服务架构框架,以及最近数个月内在国内外技术圈异军突起的Service Mesh。
什么是ServiceMesh
Service Mesh是一种非入侵、透明化的微服务治理框架。作为服务与服务直接通信的透明化管理框架,Service Mesh不限制服务开发语言、使用轻量级的通信协议(HTTP、gRPC等),并插件式的提供各类功能,如服务发现、负载均衡、智能路由、流量管控、性能分析等等,换而言之,用户通过Service Mesh得以用简单的方式获取高级的功能。
Rainbond原生支持Service Mesh,接下来我们将从服务发现和注册、弹性伸缩与负载均衡、容错处理(断路器与限流)、监控与报警、数据存储与共享、日志分析等方面进行解读。
服务发现和注册
服务注册是任何一个SOA/服务化/微服务框架必不可少的关键部分,与之密切相关的是一些强一致性分布式存储:Zookeeper、Etcd、Consul,其中Consul和Etcd基于Raft协议实现,Zookeeper基于PAXOS协议实现。
几乎所有的服务注册和发现都需要基于以上强一致性分布式存储实现,例如SpringCloud的两个重要的子项目Spring_Cloud_Consul/Spring_Cloud_Zookeeper。
对于Rainbond来说,通过应用/服务统一管理实现了所有部署应用/服务的自动注册。其原理在于Rainbond内部基于Kubernetes实现应用调度,注册于Kubernetes集群中的应用/服务信息,实际也是注册到了Etcd之中。应用实例每次重启,Rianbond都会为其分配不同的IP地址,服务注册信息将动态地改变。
我们知道,应用与应用直接通信之前必须首先发现对方,在这方面,Rainbond采用了声明式的发现机制,即当A服务需要与B服务通信,那么首先需要在A服务声明依赖B服务,而Rainbond应用运行时模块会基于用户声明发现对方服务地址,注入到A服务内部, 赋予A服务一个本地访问地址(127.0.0.1)访问B服务。
平台服务间的依赖关系
弹性伸缩与负载均衡
说到服务发现和注册,弹性伸缩与负载均衡也就不得不谈。
上文中A服务连接B服务,B服务可以是有状态的数据库服务,例如Mysql、MongoDB等,也可以是无状态的restfulAPI服务。
对于可以水平伸缩的应用(无状态应用或者分布式有状态应用),服务发现注入多个端点地址,必然需要负载均衡,因此A服务内部需要支持4层网络代理或者7层网络代理,通过应用运行时模块发现的后端地址注入到代理插件内部。
Rainbond默认的代理插件支持4层负载均衡,借助Service Mesh便于扩展得特性,我们可以再针对各种应用层协议匹配不同的网络治理插件,实现7层负载均衡,例如HTTP、gRPC、Redis等协议。
为什么需要7层负载均衡这样的高级功能?原因在于对于一些在线环境,我们希望可以对服务间调用实现热更改或者更好的容错,比方说A/B测试、灰度发布等等,必须要在7层负载均衡上完成。
Rainbond目前提供“基于envoy的7层网络治理插件”(envoy本身可以与安生运行于Rainbond插件体系之中),用户也可以选择和实现其他插件,Rainbond运行时将提供完善的基础服务。
配置7层高级负载均衡的方式
容错处理(断路器与限流)
能够容忍其中某些服务异常情况的微服务架构,才称得上是健壮的生产级微服务架构。
比方说某购物网站,订单页面会推荐其他相关商品,在大流量异常情况下,为了保证订单功能可用,将推荐功能(计算耗时,性能不好)限制可用,需要优雅的服务降级,将有限的资源用于关键服务的同时,保证整个系统稳定。
这里有两种方案: 限流 ,将某个服务设置其最大的请求量或者连接数,硬性保护下游服务; 断路器 ,当下游服务错误率到达一个阀值,将上游请求快速失败返回,保护上游服务稳定,同时又不给下游服务增加压力,做到快速失败、快速返回。
以上功能的实现对于业务系统来说相对复杂,而在上文提到的Rainbond高级负载均衡支持下,仅需为每个调用线路配置简单的限流参数或者熔断参数,即可实现断路器和限流机制开箱即用。
监控与报警
传统运维关注监控物理资源,例如内存、CPU、负载等指标数据。Rainbond在监控和警报方面,重点没有放在这些侧面体现运行状况的方式,除了基础的资源监控之外,Rainbond核心选择了能够直接体现服务运行情况的 吞吐率 和 响应时间 作为关键指标,如吞吐率异常降低,响应时间增大证明当前服务压力过大,就表示需要扩容了。
Rainbond的业务级监控分析如下图:
对于不同的服务协议,Rainbond使用不同的指标实时表现 吞吐率 、 响应时间 ,例如HTTP协议,使用Path的请求量和相应时间表达,Mysql协议使用SQL执行量和响应时间表达。
后续Rainbond将支持除上述两种协议之外的更多的应用协议,包括gRPC、Redis、postgreSQL等。用户可以自动或手动在这些指标之上配置规则或自动学习规则,实现提供业务报警和自动伸缩。
数据存储与共享
分布式是微服务架构中不可缺少的部分,在运行多种不同类型应用、需求不同存储,并且不同数据中心和不同基础设施提供不同存储类型的情况下,实现和处理起来并不容易。
Rainbond的实现方式是将存储和应用进行解耦和,插件式支持不同的存储类型,例如基于NFS的分布式文件存储、块设备存储、内存虚拟存储等,
当然不同的存储具有不同的属性,Rainbond分布式无状态应用最常用的是共享文件存储,为每个应用分配的存储区域将挂载到所有实例之上,实时同步数据。用户可以自定义需要挂载的路径,应用到哪里,数据就跟到哪里。
日志分析
微服务架构中服务产生的日志处理也是一个难点,日志需要统一收集,同一个应用的多个实例产生的日志需要汇聚,然后需要分析和报警。
服务的日志一般会分为两部分:系统日志和访问日志,Rainbond推荐将两类日志区别处理。
对于系统日志,其主要作用是调试系统、记录异常,Rainbond提供基于应用级别的应用日志汇聚和实时展示,因此只需要将系统日志输出到标准输出(stdout),系统将自动收集和汇聚,以应用的维度存储。
对于访问日志,我们一般需要对其进行分析和监控,日志分析常用的方案是ELK系统,Rainbond建议的方式是将访问日志输出到指定文件,并安装Elasticsearch插件,以便将收集文件日志发送到指定Elasticsearch服务端(平台一键部署ELK完整服务)。如果使用其他分析系统,同样使用插件的形式将应用日志输送到指定服务端即可。
结语
总结来说,Rainbond在Service Mesh微服务架构方面,核心的原则在于开放,通过各类优秀解决方案标准化的接入,来为用户提供开箱即用、强大简单的微服务体验。
进一步了解开源PaaS Rainbond 网站: https://www.rainbond.com 试用Rainbond公有云: https://www.goodrain.com Github: https://github.com/goodrain/rainbond 码云: https://gitee.com/rainbond/Rainbond 微信群: 添加微信“zqg5258423”并接受邀请入群
云计算
2018-05-15 12:02:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
摘要: AliOS Things实现了基本的SMP调度框架,支持多CPU体系的系统运行和调度机制。任务可以动态在多核间进行切换或者绑定运行;高优先级任务可以最大化利用空闲资源核运行。基于此框架,可以快速实现AliOS Things在各种不同多核CPU架构下的移植。
AliOS Things实现了基本的SMP调度框架,支持多CPU体系的系统运行和调度机制。多CPU之间对用户系统运行无区别,能平等访问共享内存、外设等共享资源;任务可以动态在多核间进行切换或者绑定运行;高优先级任务可以最大化利用空闲资源核运行。
基于此框架,可以快速实现AliOS Things在各种不同多核CPU架构下的移植;对于上层应用,可以不需要关注任务的运行核以及底层实现,也可以指定某任务在特定核运行。此实现框架,最大化地提高SMP功能在不同CPU上的移植效率,并保证上层应用使用SMP系统的简洁性。

1、 AliOS Things SMP基础特性
特性1:多CPU公平的任务切换机制,平等访问共享资源
特性2:高优先级任务合理利用空闲CPU资源
特性3:支持任务绑定核运行
特性4:支持不同CPU下快速移植
特性5:兼容单核接口并提供SMP内核扩展接口
2、 AliOS Things SMP特性移植框架
使用AliOS Things的SMP框架,可以快速在不同CPU体系下移植,以快速实现SMP功能。以下列出移植需要实现项,即可完成对应CPU的SMP功能:
2.1 核启动加载
目前的启动顺序是,系统默认开始启动0核,在0核的主任务入口内启动其他核的加载,使其都进入任务调度,并完成多核启动阶段的同步工作:核进入idle任务作为核启动完成的标志。
2.2 核间中断
主要作用:触发其他核进行调度。在任务加入ready任务队列或者任务超时到期后,如果此任务绑定到其他核,或者比其他核正在执行的任务优先级高,则会触发对应核进行任务切换。
2.3 核间锁
由于多核之间的同步互斥问题,需要实现核间锁功能,用于访问共享资源,如任务队列、内存等资源时,核内的资源互斥采用开关中断来实现。目前任务相关的资源调度和内存管理分别采用两把核间锁,该锁的实现必须支持核内的可重入性,而能达到核间互斥的目的。
以上功能需要在不同CPU/MCU架构下进行移植实现,即可完成SMP需要的底层接口支持。OS已经提供了标准的实现接口,参考下面esp32的SMP移植示例。
3、 Esp32上支持SMP移植示例
目前AliOS Things在esp32上完成了SMP的实现,后续将继续支持其他多核CPU比如cortex-A9等系列的多核CPU。参考下面的移植描述点进行移植:
3.1 SMP编译宏
对于某多核CPU,OS通过单版本不同编译宏来同时支持单核和多核的框架。在Makefile中指定-DRHINO_CONFIG_CPU_NUM=X(核数目),或者修改k_config.h内RHINO_CONFIG_CPU_NUM宏来指定核数目。推荐第一种方式。
3.2 多核加载接口
按照2.1章节描述,系统的启动顺序为默认先启动0核,在0核主任务内启动其他从核并实现同步。
需要实现加载其他核接口:void os_load_slavecpu(void);
内部实现需要完成剩余核的复位启动、必要硬件的初始化,并在从属核初始化完后,同样进入cpu_first_task_start开始进入调度;此阶段,0核需要执行os_wait_allcore接口来等待所有核的启动完成,以所有核都能进入idle任务为启动完成标志。os_wait_allcore为通用实现接口,cpu_first_task_start同单核实现。
3.3 核间中断接口
此部分需要完成三个接口的适配:
3.3.1初始化:void os_crosscore_int_init();
完成核间中断的硬件初始化,此接口需要在多核初始化时调用。
3.3.2触发接口:void cpu_signal(uint8_t cpu_num)
触发目标核对应的中断,需要完成内部实现。
3.3.3 核间中断处理:void os_crosscore_isr(void *arg)
接口内部需要调用krhino_intrpt_exit接口,其通过cpu_intrpt_switch来实现当前核的任务调度;如果需要清中断源,则清中断源。
3.4核间锁接口
此部分需要完成三个必要接口的适配,:
3.4.1 初始化:void cpu_spin_lock_init(kspinlock_t *lock);
对锁结构体赋初值;用户可以按照自身需求实现,也可参考esp32实现代码。
3.4.2 加解锁:基本原则是支持核内嵌套,核间互斥
void cpu_spin_lock(kspinlock_t *lock);
int32_t cpu_spin_unlock(kspinlock_t *lock);
锁实现可以参考在esp32上对应实现。
3.5 SMP目录结构
参考esp32,在platform/mcu/esp32下新建smp目录。smp_port.h列出上述描述的需要移植的接口,smp_load.c为核加载实现,smp_int.c为核间中断实现,smp_sync.c为核间同步接口实现。
将上述接口对接后,对应文件加入编译体系内,即可完成SMP移植适配。
3.6 其他注意事项
在实现任务和中断切换汇编portXX.S时,需要考虑到兼容单核和多核,主要是对于g_current_task等多核数组的访问,可以参考esp32中portasm.S实现。
4、SMP相关内核接口
多核SMP机制下,kernel兼容所有单核的对外接口,并提供必要的SMP扩展接口供用户使用。
上述接口将任务和核绑定,使其固定在某核运行。如果使用非绑定接口,则任务运行的核是随机的。
5、esp32上SMP运行示例
下图为Alios Things在esp32上实现SMP的任务状态图:
Cpu_binded列表示任务是否绑定核,cpu_num表示任务当前运行核,cur_exc表示当前任务运行状态。
Smp特性移植完成后,同样需要通过内核用例的测试认证。kernel测试认证请参考: https://github.com/alibaba/AliOS-Things/wiki/Manual-API
原文链接
本文为云栖社区原创内容,未经允许不得转载。
云计算
2018-05-14 20:55:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
之前在eclipse中单儿构建第一个Ribbon时,只需要加入以下依赖即可: com.netflix.ribbon ribbon 2.2.2 com.netflix.ribbon ribbon-httpclient 2.2.2
但是以上的依赖,单独在命令行中使用Maven命令构建,或者在IDEA中构建,则会抛出异常,信息如下: [ERROR] 符号: 变量 ConfigurationManager [ERROR] 位置: 类 org.crazyit.cloud.TestPingUrlConfig [ERROR] /D:/s_book/Spring Cloud/codes/04/4.2/first-ribbon-client/src/main/java/org/crazyit/cloud/TestPingUrlConfig.java:[19,17] 找不到符号 [ERROR] 符号: 变量 ConfigurationManager [ERROR] 位置: 类 org.crazyit.cloud.TestPingUrlConfig [ERROR] /D:/s_book/Spring Cloud/codes/04/4.2/first-ribbon-client/src/main/java/org/crazyit/cloud/TestPingUrlConfig.java:[23,17] 找不到符号 [ERROR] 符号: 变量 ConfigurationManager [ERROR] 位置: 类 org.crazyit.cloud.TestPingUrlConfig [ERROR] /D:/s_book/Spring Cloud/codes/04/4.2/first-ribbon-client/src/main/java/org/crazyit/cloud/TestRestClient.java:[14,17] 找不到符号 [ERROR] 符号: 变量 ConfigurationManager [ERROR] 位置: 类 org.crazyit.cloud.TestRestClient [ERROR] /D:/s_book/Spring Cloud/codes/04/4.2/first-ribbon-client/src/main/java/org/crazyit/cloud/TestRestClient.java:[25,49] 无法访问com.google.common.reflect. ypeToken [ERROR] 找不到com.google.common.reflect.TypeToken的类文件 [ERROR] /D:/s_book/Spring Cloud/codes/04/4.2/first-ribbon-client/src/main/java/org/crazyit/cloud/MyPingTest.java:[15,17] 找不到符号 [ERROR] 符号: 变量 ConfigurationManager
解决方法,使用eclispe或者修改pom.xml,修改后的pom.xml内容如下: com.netflix.ribbon ribbon-core 2.2.2 com.netflix.ribbon ribbon-loadbalancer 2.2.2 com.netflix.archaius archaius-core 0.7.5 commons-configuration commons-configuration 1.9 com.netflix.ribbon ribbon-httpclient 2.2.2 com.google.guava guava 18.0
暂时不知道原因,估计是eclipse的Maven插件有问题,自动引入许多依赖。
云计算
2018-05-14 18:25:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
摘要: 产品介绍: 阿里云专有宿主机是一台物理独享的云主机,和其他租户在物理级别上隔离。专有宿主机提供给用户一种依托阿里云虚拟化服务的单租户运行环境,彻底解决多租户争抢问题,获得更高隔离性,满足更严格合规监管,满足自带许可证上云场景。
阿里云专有宿主机正式上线,这个产品会给您的云上业务带来哪些变化?
自带许可证上云(BYOL)
随着迁移至阿里云的企业客户越来越多,自带许可证上云的诉求越来越强烈,也就是我们常说的:BYOL(Bring-Your-Own-License)。
有些license的许可证授权是根据物理机的Socket数量,或者是根据物理Core的个数来进行授权的。比如:Windows Server、SQL Server、Oracle Database、SUSE Enterprise等。而如何在将您线下服务器迁移上云的同时,能够复用已经购买的许可证,节省上云成本?专有宿主机能够给您提供合适的解决方案。
专有宿主机是一台物理独享的物理服务器。在创建之后,您获得宿主机所在物理服务器的所有资源,包括:CPU,内存,本地盘(本地盘类型专有宿主机)。您可以使用宿主机上所有资源来创建ECS实例,相较于AWS提供的产品形态,阿里云提供的专有宿主机能够单机支持多种ECS实例的创建,方便您灵活的规划自己的业务部署。而除了在资源部署上可以感知的物理独享,在控制台用户可以查看到宿主机的Socket数,物理核数和资源使用情况(可用vCPU/内存,剩余vCPU/内存),另外每一台宿主机有一台唯一的机器码。能够让您从容应对许可证验证的同时,提供便捷、可视化的方式管理自己的专有资源池。
满足安全合规监管
对于金融等具有严格监管规定的行业,专有宿主机不仅具备ECS云服务器所有的安全保障能力,还提供物理级别的用户隔离,无论是CPU、内存、网卡还是数据盘(本地盘类型专有宿主机),都是物理级别的独享环境。在应用的部署和备案上,专有宿主机能够提供公共云不能提供的一些能力。如:怎么指定物理机去部署您的业务,并对物理机和虚拟机的部署关系做出说明?在ECS实例重启时,是否可以保证实例不漂移?对于如何控制自己的应用部署,专有宿主机能给您提供更大的自主性。
调整部署的成本问题
云计算的一项核心优势就是部署的灵活性和弹性,如果在宿主机上创建了ECS实例之后不能再次调整部署,那和一台线下物理机房的物理机其实没有太大的区别。为了提供迁移的灵活性,阿里云提供ECS实例从共享宿主机迁移至专有宿主机的选项,同时也支持ECS实例从一台专有宿主机迁移至另一台专有宿主机。部署的灵活性能够给与您更大的部署选择,降低调整部署的成本。
再通过一张图来了解一下
原文链接
本文为云栖社区原创内容,未经允许不得转载
云计算
2018-05-14 15:50:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
云计算并不关心计算机在寻找处理能力时是否位于云中,而在iot时代,我们负担不起。随着物联网迅速成为一切事物的互联网,是时候重新设想一下,需要什么样的基础设施才能跟上步伐。2018年将是雾的起源年。

自从第一台IoT设备于1990年问世以来,物联网已经有了长足的发展,这是一种可以在互联网上开启和关闭的烤面包机。27年之后,联网设备已经从新奇产品变成了日常生活中必不可少的一部分。最近的估计显示,美国成年人平均每天花在智能手机上的时间超过4个小时,这是一种装有物联网传感器数据的设备。这是一个以自身为基础的循环。目前,81%的美国成年人拥有智能手机。想象一下,当81%的美国人拥有智能汽车和智能家居时,我们将会收到多少数据。
今天,IoT设备的大部分数据都在云中处理,这意味着全球所有角落产生的数据都被发送到集中数据中心的少数计算机上。然而,随着IoT设备的数量预计将在2020年猛增至200亿,通过互联网发送数据的体积和速度对云计算方法提出了严峻的挑战。
以下是关于IoT基础设施的三个关键事实,将迫使IoT制造商在2018年将云计算模式从云计算模式转移到一种称为“雾计算”的新范式。
1. 随着越来越多的数据访问,云的距离问题变得越来越明显
由于它的方便、可伸缩性和可访问性,云模型越来越受欢迎。然而,随着数据量的增加,“眼不见心不烦”的吸引力已经变得越来越明显和有问题了。
其中最主要的是延迟(发送和接收数据的延迟),这很大程度上是由于云的距离造成的。集中的云数据中心是在房地产和公用设施便宜的地方建造的,而不是靠近主要的人口中心。这意味着,具有讽刺意味的是,越来越多的人和设备区域越不可能位于数据中心附近。
最近的亚马逊数据中心距纽约市近300英里,这也让人感觉不太清楚。从我们的可穿戴设备和智能办公室发来的数据可以让我们在600英里的范围内往返于云端进行处理,并在其附近通过数以千万计的计算机。
据国际数据公司(IDC)的数据,云计算的距离问题是,估计有一半的云客户会因为延迟和性能的原因,投资额外的本地计算。
2. 问:我们家里和办公室里的电脑和云里的电脑有什么不同?答:没有
好消息是,我们已经被大量的未开发的处理能力所包围,这有助于缩小我们当前云模型的差距。总的来说,我们拥有超过50亿台设备:服务器、工作站、笔记本电脑、平板电脑、甚至是智能手机,它们与云计算系统的不同之处是,它们的所有者没有得到支付租金的计算。
有了软件,任何计算机都可以运行在云端运行的相同的web服务,我们可以利用我们周围已经存在的数十亿台计算机的巨大的未开发的处理能力。就像云把工作负载分配到它所拥有的计算机中一样,物联网数据的负担也可以分布在办公室和个人拥有的任意数量的计算机中,这些计算机通常只发挥其潜力的一小部分。
授权在全球范围内的现有计算机租用计算不仅有助于分配物联网的处理负担,它还引入竞争进入云市场,使计算更适合所有人。由于计算已成为企业经营的基本成本,使其更容易获得,将推动企业家、研究人员、学生和企业发展未来最具创新性的技术。
3. 未来是雾计算
从设备到云,处理能力在任何地方都可以利用的基础设施的术语是“雾计算”。雾将云计算扩展到网络的边缘,使任何计算设备都能够承载软件服务和过程,并分析和存储更靠近它产生的数据。例如,与其把一个智能的恒温器发送到一个云数据中心的每分钟,一个服务器在同一个房间可以处理数据,以决定是否需要对其进行处理。
雾状结构将大量的处理能力折叠起来,由于处理能力通常位于需要它的设备附近,因此它减少了距离数据以指数级的速度移动,减少了延迟。因此,可以更快地做出决策,而IoT的制造商和软件开发人员将通过限制发送的数据量来查看更低的云账单。雾使云自由发挥其所能做的最佳全球协调、长期数据存储和分析,而不是时间的关键。
云计算将云计算和现场技术的最佳部分融合在一起,形成了一个整体的整体架构。有很多人已经开始在建筑上做这种基本的转变,我的公司ActiveAether就是其中之一。这项专利技术利用了可用的计算机来部署软件,以满足在地理上适合的计算机的需求,无论是办公服务器还是家里的笔记本电脑。
云计算并不关心计算机在寻找处理能力时是否位于云中,而在iot时代,我们负担不起。
随着物联网迅速成为一切事物的互联网,是时候重新设想一下,需要什么样的基础设施才能跟上步伐。2018年将是雾的起源年。 原文来自: http://cloud.51cto.com/art/201805/571990.htm
本文地址: https://www.linuxprobe.com/internet-of-thing.html 编辑:王华超,审核员:逄增宝
云计算
2018-05-14 09:16:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
Kubernetes 给我们提供了大量官方 chart,不过要部署微服务应用,还是需要开发自己的 chart,下面就来实践这个主题。
创建 chart
执行 helm create mychart 的命令创建 chart mychart :
Helm 会帮我们创建目录 mychart ,并生成了各类 chart 文件。这样我们就可以在此基础上开发自己的 chart 了。
新建的 chart 默认包含一个 nginx 应用示例,values.yaml 内容如下:
开发时建议大家参考官方 chart 中的模板、values.yaml、Chart.yaml,里面包含了大量最佳实践和最常用的函数、流控制,这里就不一一展开了。
调试 chart
只要是程序就会有 bug,chart 也不例外。Helm 提供了 debug 的工具: helm lint 和 helm install --dry-run --debug 。
helm lint 会检测 chart 的语法,报告错误以及给出建议。
比如我们故意在 values.yaml 的第 8 行漏掉了一个 : ,
helm lint mychart 会指出这个语法错误。
mychart 目录被作为参数传递给 helm lint 。错误修复后则能通过检测。
helm install --dry-run --debug 会模拟安装 chart,并输出每个模板生成的 YAML 内容。

我们可以检视这些输出,判断是否与预期相符。
同样, mychart 目录作为参数传递给 helm install --dry-run --debug 。
下一节我们讨论如何安装并将 chart 添加到仓库。
书籍:
1.《每天5分钟玩转Kubernetes》
https://item.jd.com/26225745440.html
2.《每天5分钟玩转Docker容器技术》
https://item.jd.com/16936307278.html
3.《每天5分钟玩转OpenStack》
https://item.jd.com/12086376.html
云计算
2018-05-14 06:18:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
SAP云平台以微服务的方式提供了Document的CRUD(增删改查)操作。该微服务基于标准的CMIS协议(Content Management Interoperability Service)。

同标准的CMIS相比,SAP云平台的Document Service增添了一些功能的支持:
通过一个Hello World应用来了解如何在Java程序里消费SAP云平台的Document Service。
通过这个 链接 下载例子程序。
点击该超链接下载Java Web Tomcat 8 SDK。
例子程序位于该SDK的samples文件夹下。
将该应用部署到SAP云平台之后,访问该应用看到如下提示信息:
该提示信息是由应用的DocumentStoreServlet的goGet方法输出:
一旦点击Connect超链接之后:
调用另一个Servlet DocumentStoreConnectServlet的doGet方法,执行三个逻辑:
Step 1的Ecm即Enterprise Content Management,指SAP云平台上的Document Service。
该Document Service的实例句柄通过JNDI获得:
在web.xml里进行配置:
第一次点击Connect时,会执行下图catch分支的代码,用硬编码的密匙创建一个新的repository。第二次执行即进入第85行逻辑,因此此时repository已经存在。
第一次点击Connect的输出:
第二次的输出:
在SAP云平台的Cockpit里能够看到成功创建的repository:
如果需要删除该repository,需提供创建时硬编码的密匙abcdef0123456789。
要获取更多Jerry的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:
云计算
2018-05-12 17:20:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
1. 首先根据这个 链接 配置好Eclipse。
确保SAP Cloud Platform Tools for Java正确安装。
确保neo SDK的路径配置正确:
我使用的是下图这个SDK:neo-java-web-sdk-3.51.14.zip
将我的 github 项目 下载到本地, 导入到Eclipse去,确保本地能够运行成功。
然后新建一个服务器实例,类型为SAP Cloud Platform,主机名填hanatrial.ondemand.com:
应用程序的名称填jerrydemo,Runtime选择Java Web Tomcat 8,输入SCP平台的用户名和密码:
成功之后,即可在Eclipse里看到SAP云平台的实例,jerrydemo这个应用在上面的状态处于Started状态。Eclipse内置的浏览器自动打开该应用。
在SCP的cockpit里能看到更多关于该应用的明细:

您可以访问这个 链接 测试SCP平台上运行的应用的效果:
要获取更多Jerry的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:
云计算
2018-05-12 17:17:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
选择Services Catalog,根据关键字搜索到WebIDE服务,点击超链接打开WebIDE:
进入workspace,选择Git->Clone Repository:
从我的github clone: https://github.com/i042416/jerrylist
clone完毕之后选择Run->Run index.html, 检查clone是否成功。
正常情况下应该看到这个UI5应用:
将该应用从git的workspace部署到SAP cloud platform上:
Application Name可以随便起,我用的jerrylistfordemo。
成功部署后,在HTML5 Application能看到刚刚部署成功的应用jerrylistfordemo:
点击该应用的超链接能看到访问这个应用的url:
这样既可访问部署在SAP云平台上的应用。
同样的url也能在手机上访问:
要获取更多Jerry的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:
云计算
2018-05-12 17:11:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
SAP云平台的帮助文档很多时候将12-factor应用和微服务架构的应用相提并论。
然而从Allan Beck和John Mcteague的Cloud成熟度模型概念里,12-factor应用从成熟度上来说在微服务架构应用之上。
所谓Twelve-factor应用,详细定义在这个 链接 里, 点击每个标题的超链接能看到明细。
要获取更多Jerry的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:
云计算
2018-05-12 17:09:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
SAP云平台提供了两套运行环境:Cloud Foundry和Neo
从下图能发现,Cloud Foundry的运行环境,基础设施由第三方公司提供,比如Amazon亚马逊和Microsoft微软,SAP只负责提供和维护platform layer。而Neo环境的基础设施和platform layer均由SAP提供。
Cloud Foundry运行环境包含了Cloud Foundry application runtime,基于Cloud Foundry基金会的开源应用平台构建而成。
这两个环境的具体比较:
从使用场景比较
如果当您需要开发基于微服务架构的应用,使用物联网Internet of Things或者机器学习使用场景时,SAP推荐您选择Cloud Foundry运行环境。在Cloud Foundry运行环境下您能使用多种编程模型,例如Java,nodejs和SAP HANA extended application services, advanced model (SAP HANA XSA)。
Neo则用于UI5,Java和HANA Extended Service开发。
从可用地区比较

从上面两张图能看出Neo的可用区域比Cloud Foundry广泛。注意Region指的是数据中心的物理地址。作为开发人员,我们在做开发时,尽量选择使用离自己所在物理物质近的Region所在的环境以获得更好的性能。
从支持的buildpack比较
Cloud Foundry支持如下buildpack甚至自定义buildpack,而Neo不支持。
一个应用实例能够分配的最大内存限额
Cloud Foundry为4GB,Neo为16GB
对HANA编程模型的支持
Neo只支持SAP HANA extended application services的经典模型(SAP HANA XS), 而Cloud Foundry支持高级模型(SAP HANA XS)。
对虚拟机的支持
Neo提供了虚拟机的支持,以便在平台不支持的场景下仍然能够允许您安装和维护您需要的应用。Cloud Foundry不支持虚拟机。
Docker support
Cloud Foundry支持Docker,Neo不支持。
要获取更多Jerry的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:
云计算
2018-05-12 17:05:00
「深度学习福利」大神带你进阶工程师,立即查看>>> Author: xidianwangtao@gmail.com
从Kubernetes 1.8开始,Scheduler提供了基于Pod Priorty的抢占式调度,我在 解析Kubernetes 1.8中的基于Pod优先级的抢占式调度 和 Kubernetes 1.8抢占式调度Preemption源码分析 中对此做过深入分析。但这还不够,当时调度队列只有FIFO类型,并不支持优先级队列,这会导致High Priority Pod抢占Lower Priority Pod后再次进入FIFO队列中排队,经常会导致抢占的资源被队列前面的Lower Priority Pod占用,导致High Priority Pod Starvation的问题。为了减轻这一问题,从Kubernetes 1.9开始提供Pod优先级的调度队列,即PriorityQueue,这同样需要用户打开PodPriority这个Feature Gate。
PriorityQueue
PriorityQueue Struct
先看看PriorityQueue的结构定义。 type PriorityQueue struct { lock sync.RWMutex cond sync.Cond activeQ *Heap unschedulableQ *UnschedulablePodsMap nominatedPods map[string][]*v1.Pod receivedMoveRequest bool }
activeQ :PriorityQueue的Sub-Queue之一,是一个有序的Heap结构,按照Pod优先级从高到低递减的顺序存放待调度的Pending Pod相关信息,优先级最高的Pod信息在最上面,Pop Heap时将得到最高优先级的Pod信息。 unschedulableQ :PriorityQueue的Sub-Queue之一,主要是是一个无序的Map,key为 pod.Name + "_" + pod.Namespace ,value为那些已经尝试调度并且调度失败的UnSchedulable的Pod Object。 nominatedPods :为Map结构,key为node name,value为该Node上Nominated Pod Objects。当发生抢占调度时,preemptor pods会打上 NominatedNodeName Annotation,表示经过抢占调度的逻辑后,该Pod希望能调度到 NominatedNodeName 这个Node上,调度时会考虑这个,防止高优先级的Pods进行抢占调度释放了低优先级Pods到它被再次调度这个时间段内,抢占的资源又被低优先级的Pods占用了。关于scheduler怎么处理Nominated Pods,我后续会单独写篇博客来分析。 receivedMoveRequest :当scheduler将Pods从unschedulableQ移到activeQ时,这个值设为true。当scheduler从activeQ中Pop一个Pods时,这个值设为false。这表示当scheduler要调度某个Pod时是否接受到Move请求。当调度发生Error时,会尝试将UnSchedulable Pod重新加入到调度队列(unSchedulableQ or activeQ)中,这时只有当receivedMoveRequest为false并且该Pod Condition Status为False或者Unschedulable时,才会将该Pod Add到unschedulableQ(或者Update it)。
activeQ
active是真正实现优先级调度的Heap,我们继续看看这个Heap的实现。 type Heap struct { data *heapData } type heapData struct { items map[string]*heapItem queue []string keyFunc KeyFunc lessFunc LessFunc } type heapItem struct { obj interface{} // The object which is stored in the heap. index int // The index of the object's key in the Heap.queue. }
heapData是activeQ中真正用来存放items的结构: items:Map结构,key为Heap中对象的key,通过下面的keyFunc生成,value为heapItem对象,heapItem包括真正的Pod Object及其在Heap中的index。 queue:string array,顺序存放Pod对应的key,按照优先级从高到低的顺序对应index从0到高。 keyFunc:根据Pod Object生成对应的key的Function,格式为"meta.GetNamespace() + "/" + meta.GetName"。 lessFunc:用来根据Pod优先级比较Heap中的Pod Object(然后决定其在Heap中的index,index为0的Pod优先级最高,随着index递增,Pod优先级递减)。
NewPriorityQueue
在scheduler config factory创建时,会注册podQueue的创建Func为NewSchedulingQueue。NewSchedulingQueue会检查PodPriority Feature Gate是否enable(截止Kubernetes 1.10版本,默认disable),如果PodPriority enable,则会invoke NewPriorityQueue创建PriorityQueue来管理未调度的Pods。如果PodPriority disable,则使用大家熟悉的FIFO Queue。 func NewSchedulingQueue() SchedulingQueue { if util.PodPriorityEnabled() { return NewPriorityQueue() } return NewFIFO() }
NewPriorityQueue初始化优先级队列代码如下。 // NewPriorityQueue creates a PriorityQueue object. func NewPriorityQueue() *PriorityQueue { pq := &PriorityQueue{ activeQ: newHeap(cache.MetaNamespaceKeyFunc, util.HigherPriorityPod), unschedulableQ: newUnschedulablePodsMap(), nominatedPods: map[string][]*v1.Pod{}, } pq.cond.L = &pq.lock return pq } 主要初始化activeQ、unschedulableQ、nominatedPods。 newHeap初始化activeQ时,注册heapData对应的keyFunc和lessFunc。 unschedulableQ初始化时,注册keyFunc。
cache.MetaNamespaceKeyFunc
newHeap构建activeQ的时候,传入两个参数,第一个就是keyFunc: MetaNamespaceKeyFunc。 func MetaNamespaceKeyFunc(obj interface{}) (string, error) { if key, ok := obj.(ExplicitKey); ok { return string(key), nil } meta, err := meta.Accessor(obj) if err != nil { return "", fmt.Errorf("object has no meta: %v", err) } if len(meta.GetNamespace()) > 0 { return meta.GetNamespace() + "/" + meta.GetName(), nil } return meta.GetName(), nil } MetaNamespaceKeyFunc根据Pod Object生成对应的key的Function,格式为"meta.GetNamespace() + "/" + meta.GetName"。
util.HigherPriorityPod
newHeap传入的第二个参数是lessFunc:HigherPriorityPod。 const ( DefaultPriorityWhenNoDefaultClassExists = 0 ) func HigherPriorityPod(pod1, pod2 interface{}) bool { return GetPodPriority(pod1.(*v1.Pod)) > GetPodPriority(pod2.(*v1.Pod)) } func GetPodPriority(pod *v1.Pod) int32 { if pod.Spec.Priority != nil { return *pod.Spec.Priority } return scheduling.DefaultPriorityWhenNoDefaultClassExists } HigherPriorityPod用来根据Pod优先级比较Heap中的Pod Object,然后决定其在Heap中的index。 index为0的Pod优先级最高,随着index递增,Pod优先级递减。 注意:如果pod.Spec.Priority为nil(意味着这个Pod在创建时集群里还没有对应的global default PriorityClass Object),并不是去把现在global default PriorityClass中的值设置给这个Pod.Spec.Priority,而是设置为0。个人觉得,设置为默认值比较合理。
newUnschedulablePodsMap
unschedulableQ的构建是通过调用newUnschedulablePodsMap完成的,里面进行了UnschedulablePodsMap的pods的初始化,以及pods map中keyFunc的注册。 func newUnschedulablePodsMap() *UnschedulablePodsMap { return &UnschedulablePodsMap{ pods: make(map[string]*v1.Pod), keyFunc: util.GetPodFullName, } } func GetPodFullName(pod *v1.Pod) string { return pod.Name + "_" + pod.Namespace } 注意:unschedulableQ中keyFunc实现的key生成规则是 pod.Name + "_" + pod.Namespace ,不同于activeQ中keyFunc(格式为"meta.GetNamespace() + "/" + meta.GetName")。我也不理解为何要搞成两种不同的格式,统一按照activeQ中的keyFunc就很好。
Add Object to Heap
前面了解了PriorityQueue的结构,接着我们就要思考怎么往优先级Heap(activeQ)中添加对象了。 func (h *Heap) Add(obj interface{}) error { key, err := h.data.keyFunc(obj) if err != nil { return cache.KeyError{Obj: obj, Err: err} } if _, exists := h.data.items[key]; exists { h.data.items[key].obj = obj heap.Fix(h.data, h.data.items[key].index) } else { heap.Push(h.data, &itemKeyValue{key, obj}) } return nil } func Push(h Interface, x interface{}) { h.Push(x) up(h, h.Len()-1) } func up(h Interface, j int) { for { i := (j - 1) / 2 // parent if i == j || !h.Less(j, i) { break } h.Swap(i, j) j = i } } func (h *heapData) Less(i, j int) bool { if i > len(h.queue) || j > len(h.queue) { return false } itemi, ok := h.items[h.queue[i]] if !ok { return false } itemj, ok := h.items[h.queue[j]] if !ok { return false } return h.lessFunc(itemi.obj, itemj.obj) } 往activeQ中添加Pod时,如果该Pod已经存在,则根据其PriorityClass Value更新它在heap中的index,否则把它Push入堆。 Push和Fix类似,都需要对该Pod在activeQ heap中进行重新排序。排序时,通过Less Func进行比较,Less Func最终就是invoke前面注册的activeQ中的lessFunc,即HigherPriorityPod。也就说Push和Fix时会根据Pod的优先级从高到低依次对应index从小到大。
Pop Object from Heap
使用PriorityQueue进行待调度Pod管理时,会从activeQ中Pop一个Pod出来,这个Pod是heap中的第一个Pod,也是优先级最高的Pod。 func (h *Heap) Pop() (interface{}, error) { obj := heap.Pop(h.data) if obj != nil { return obj, nil } return nil, fmt.Errorf("object was removed from heap data") } func Pop(h Interface) interface{} { n := h.Len() - 1 h.Swap(0, n) down(h, 0, n) return h.Pop() } func down(h Interface, i, n int) { for { j1 := 2*i + 1 if j1 >= n || j1 < 0 { // j1 < 0 after int overflow break } j := j1 // left child if j2 := j1 + 1; j2 < n && !h.Less(j1, j2) { j = j2 // = 2*i + 2 // right child } if !h.Less(j, i) { break } h.Swap(i, j) i = j } } 从activeQ heap中Pop一个Pod出来时,最终也是通过Less Func进行比较(即HigherPriorityPod)找出最高优先级的Pod。
Pod Queue Handler
了解了PriorityQueue及Pod进出Heap的原理之后,我们回到Scheduler Config Factory,看看Scheduler中podInformer、nodeInformer、serviceInformer、pvcInformer等注册的EventHandler中对PriorityQueue的操作。 func NewConfigFactory(...) scheduler.Configurator { ... // scheduled pod cache podInformer.Informer().AddEventHandler( cache.FilteringResourceEventHandler{ FilterFunc: func(obj interface{}) bool { switch t := obj.(type) { case *v1.Pod: return assignedNonTerminatedPod(t) case cache.DeletedFinalStateUnknown: if pod, ok := t.Obj.(*v1.Pod); ok { return assignedNonTerminatedPod(pod) } runtime.HandleError(fmt.Errorf("unable to convert object %T to *v1.Pod in %T", obj, c)) return false default: runtime.HandleError(fmt.Errorf("unable to handle object in %T: %T", c, obj)) return false } }, Handler: cache.ResourceEventHandlerFuncs{ AddFunc: c.addPodToCache, UpdateFunc: c.updatePodInCache, DeleteFunc: c.deletePodFromCache, }, }, ) // unscheduled pod queue podInformer.Informer().AddEventHandler( cache.FilteringResourceEventHandler{ FilterFunc: func(obj interface{}) bool { switch t := obj.(type) { case *v1.Pod: return unassignedNonTerminatedPod(t) case cache.DeletedFinalStateUnknown: if pod, ok := t.Obj.(*v1.Pod); ok { return unassignedNonTerminatedPod(pod) } runtime.HandleError(fmt.Errorf("unable to convert object %T to *v1.Pod in %T", obj, c)) return false default: runtime.HandleError(fmt.Errorf("unable to handle object in %T: %T", c, obj)) return false } }, Handler: cache.ResourceEventHandlerFuncs{ AddFunc: c.addPodToSchedulingQueue, UpdateFunc: c.updatePodInSchedulingQueue, DeleteFunc: c.deletePodFromSchedulingQueue, }, }, ) // ScheduledPodLister is something we provide to plug-in functions that // they may need to call. c.scheduledPodLister = assignedPodLister{podInformer.Lister()} nodeInformer.Informer().AddEventHandler( cache.ResourceEventHandlerFuncs{ AddFunc: c.addNodeToCache, UpdateFunc: c.updateNodeInCache, DeleteFunc: c.deleteNodeFromCache, }, ) c.nodeLister = nodeInformer.Lister() ... // This is for MaxPDVolumeCountPredicate: add/delete PVC will affect counts of PV when it is bound. pvcInformer.Informer().AddEventHandler( cache.ResourceEventHandlerFuncs{ AddFunc: c.onPvcAdd, UpdateFunc: c.onPvcUpdate, DeleteFunc: c.onPvcDelete, }, ) c.pVCLister = pvcInformer.Lister() // This is for ServiceAffinity: affected by the selector of the service is updated. // Also, if new service is added, equivalence cache will also become invalid since // existing pods may be "captured" by this service and change this predicate result. serviceInformer.Informer().AddEventHandler( cache.ResourceEventHandlerFuncs{ AddFunc: c.onServiceAdd, UpdateFunc: c.onServiceUpdate, DeleteFunc: c.onServiceDelete, }, ) c.serviceLister = serviceInformer.Lister() ... }
PodInformer EventHandler for Scheduled Pod
通过assignedNonTerminatedPod FilterFunc过滤出那些已经Scheduled并且NonTerminated Pods,然后再对这些Pods的Add/Update/Delete Event Handler进行注册,这里我们只关注对PriorityQueue的操作。 // assignedNonTerminatedPod selects pods that are assigned and non-terminal (scheduled and running). func assignedNonTerminatedPod(pod *v1.Pod) bool { if len(pod.Spec.NodeName) == 0 { return false } if pod.Status.Phase == v1.PodSucceeded || pod.Status.Phase == v1.PodFailed { return false } return true }
addPodToCache Handler
注册Add assignedNonTerminatedPod Event Handler为addPodToCache。 func (c *configFactory) addPodToCache(obj interface{}) { ... c.podQueue.AssignedPodAdded(pod) } // AssignedPodAdded is called when a bound pod is added. Creation of this pod // may make pending pods with matching affinity terms schedulable. func (p *PriorityQueue) AssignedPodAdded(pod *v1.Pod) { p.movePodsToActiveQueue(p.getUnschedulablePodsWithMatchingAffinityTerm(pod)) } func (p *PriorityQueue) movePodsToActiveQueue(pods []*v1.Pod) { p.lock.Lock() defer p.lock.Unlock() for _, pod := range pods { if err := p.activeQ.Add(pod); err == nil { p.unschedulableQ.delete(pod) } else { glog.Errorf("Error adding pod %v to the scheduling queue: %v", pod.Name, err) } } p.receivedMoveRequest = true p.cond.Broadcast() } // getUnschedulablePodsWithMatchingAffinityTerm returns unschedulable pods which have // any affinity term that matches "pod". func (p *PriorityQueue) getUnschedulablePodsWithMatchingAffinityTerm(pod *v1.Pod) []*v1.Pod { p.lock.RLock() defer p.lock.RUnlock() var podsToMove []*v1.Pod for _, up := range p.unschedulableQ.pods { affinity := up.Spec.Affinity if affinity != nil && affinity.PodAffinity != nil { terms := predicates.GetPodAffinityTerms(affinity.PodAffinity) for _, term := range terms { namespaces := priorityutil.GetNamespacesFromPodAffinityTerm(up, &term) selector, err := metav1.LabelSelectorAsSelector(term.LabelSelector) if err != nil { glog.Errorf("Error getting label selectors for pod: %v.", up.Name) } if priorityutil.PodMatchesTermsNamespaceAndSelector(pod, namespaces, selector) { podsToMove = append(podsToMove, up) break } } } } return podsToMove } addPodToCache除了将pod加入到schedulerCache中之外,还会调用podQueue.AssignedPodAdded。 对于PriorityQueue而言,AssignedPodAdded负责unSchedulableQ中的pods进行与该pod的Pod Affinity检查,把那些满足Pod Affinity的pods从unSchedulableQ中移到activeQ中,待scheduler进行调度。 在这里要注意movePodsToActiveQueue中设置了receivedMoveRequest为true。 但是这里应该是有问题的,如果getUnschedulablePodsWithMatchingAffinityTerm得到的podsToMove数组为空时,并没有pods会真正从unSchedulableQ中移到activeQ中,此时MoveRequest是无效的,receivedMoveRequest仍然应该为false。 上面的receivedMoveRequest设置不对带来什么问题呢?当某个pod调度发生Error时会调用AddUnschedulableIfNotPresent将该pod加入到unSchedulableQ或者activeQ中。 如果receivedMoveRequest为false并且该Pod Condition Status为 False 或者 Unschedulable 时,才会将该Pod Add/Update到unschedulableQ,否则加入到activeQ。 因此receivedMoveRequest设置错误可能会导致该pod本应该加入到unSchedulableQ中,却被加入到了activeQ中,这会导致scheduler多做一次无效的调度,当然这对性能的影响是很小的。 func (p *PriorityQueue) AddUnschedulableIfNotPresent(pod *v1.Pod) error { p.lock.Lock() defer p.lock.Unlock() if p.unschedulableQ.get(pod) != nil { return fmt.Errorf("pod is already present in unschedulableQ") } if _, exists, _ := p.activeQ.Get(pod); exists { return fmt.Errorf("pod is already present in the activeQ") } if !p.receivedMoveRequest && isPodUnschedulable(pod) { p.unschedulableQ.addOrUpdate(pod) p.addNominatedPodIfNeeded(pod) return nil } err := p.activeQ.Add(pod) if err == nil { p.addNominatedPodIfNeeded(pod) p.cond.Broadcast() } return err }
updatePodInCache
注册Update assignedNonTerminatedPod Event Handler为updatePodInCache。 func (c *configFactory) updatePodInCache(oldObj, newObj interface{}) { ... c.podQueue.AssignedPodUpdated(newPod) } // AssignedPodUpdated is called when a bound pod is updated. Change of labels // may make pending pods with matching affinity terms schedulable. func (p *PriorityQueue) AssignedPodUpdated(pod *v1.Pod) { p.movePodsToActiveQueue(p.getUnschedulablePodsWithMatchingAffinityTerm(pod)) }
updatePodInCache中对podQueue的操作是AssignedPodUpdated,其实现同AssignedPodAdded,不再多说。
deletePodFromCache
注册Delete assignedNonTerminatedPod Event Handler为deletePodFromCache。 func (c *configFactory) deletePodFromCache(obj interface{}) { ... c.podQueue.MoveAllToActiveQueue() } func (p *PriorityQueue) MoveAllToActiveQueue() { p.lock.Lock() defer p.lock.Unlock() for _, pod := range p.unschedulableQ.pods { if err := p.activeQ.Add(pod); err != nil { glog.Errorf("Error adding pod %v to the scheduling queue: %v", pod.Name, err) } } p.unschedulableQ.clear() p.receivedMoveRequest = true p.cond.Broadcast() } 当发生Delete assignedNonTerminatedPod Event时,会调用podQueue.MoveAllToActiveQueue将unSchedulableQ中的所有Pods移到activeQ中,unSchedulableQ也就被清空了。 如果集群中出现频繁删除pods的动作,会导致频繁将unSchedulableQ中的所有Pods移到activeQ中。如果unSchedulableQ中有个High Priority的Pod,那么就会导致频繁的抢占Lower Priority Pods的调度机会,使得Lower Priority Pod长期处于饥饿状态。关于这个问题,社区已经在考虑增加对应的back-off机制,减轻这种情况带来的影响。
PodInformer EventHandler for UnScheduled Pod
通过unassignedNonTerminatedPod FilterFunc过滤出那些还未成功调度的并且NonTerminated Pods,然后再对这些Pods的Add/Update/Delete Event Handler进行注册,这里我们只关注对PriorityQueue的操作。 // unassignedNonTerminatedPod selects pods that are unassigned and non-terminal. func unassignedNonTerminatedPod(pod *v1.Pod) bool { if len(pod.Spec.NodeName) != 0 { return false } if pod.Status.Phase == v1.PodSucceeded || pod.Status.Phase == v1.PodFailed { return false } return true }
addPodToSchedulingQueue
注册Add unassignedNonTerminatedPod Event Handler为addPodToSchedulingQueue。 func (c *configFactory) addPodToSchedulingQueue(obj interface{}) { if err := c.podQueue.Add(obj.(*v1.Pod)); err != nil { runtime.HandleError(fmt.Errorf("unable to queue %T: %v", obj, err)) } } func (p *PriorityQueue) Add(pod *v1.Pod) error { p.lock.Lock() defer p.lock.Unlock() err := p.activeQ.Add(pod) if err != nil { glog.Errorf("Error adding pod %v to the scheduling queue: %v", pod.Name, err) } else { if p.unschedulableQ.get(pod) != nil { glog.Errorf("Error: pod %v is already in the unschedulable queue.", pod.Name) p.deleteNominatedPodIfExists(pod) p.unschedulableQ.delete(pod) } p.addNominatedPodIfNeeded(pod) p.cond.Broadcast() } return err } 当发现有unassigned Pods Add时,addPodToSchedulingQueue负责把该pods加入到activeQ中,并确保unSchedulableQ中没有这些unassigned pods。
updatePodInSchedulingQueue
注册Update unassignedNonTerminatedPod Event Handler为updatePodInSchedulingQueue。 func (c *configFactory) updatePodInSchedulingQueue(oldObj, newObj interface{}) { pod := newObj.(*v1.Pod) if c.skipPodUpdate(pod) { return } if err := c.podQueue.Update(oldObj.(*v1.Pod), pod); err != nil { runtime.HandleError(fmt.Errorf("unable to update %T: %v", newObj, err)) } } updatePodInSchedulingQueue中先调用skipPodUpdate检查是否该pod update event可以忽略。 如果不能忽略该pod update,再invoke podQueue.Update更新activeQ,如果该pod不在activeQ中,则从unSchedulableQ中删除该pod,然后把新的pod Push到activeQ中。 func (c *configFactory) skipPodUpdate(pod *v1.Pod) bool { // Non-assumed pods should never be skipped. isAssumed, err := c.schedulerCache.IsAssumedPod(pod) if err != nil { runtime.HandleError(fmt.Errorf("failed to check whether pod %s/%s is assumed: %v", pod.Namespace, pod.Name, err)) return false } if !isAssumed { return false } // Gets the assumed pod from the cache. assumedPod, err := c.schedulerCache.GetPod(pod) if err != nil { runtime.HandleError(fmt.Errorf("failed to get assumed pod %s/%s from cache: %v", pod.Namespace, pod.Name, err)) return false } // Compares the assumed pod in the cache with the pod update. If they are // equal (with certain fields excluded), this pod update will be skipped. f := func(pod *v1.Pod) *v1.Pod { p := pod.DeepCopy() // ResourceVersion must be excluded because each object update will // have a new resource version. p.ResourceVersion = "" // Spec.NodeName must be excluded because the pod assumed in the cache // is expected to have a node assigned while the pod update may nor may // not have this field set. p.Spec.NodeName = "" // Annotations must be excluded for the reasons described in // https://github.com/kubernetes/kubernetes/issues/52914. p.Annotations = nil return p } assumedPodCopy, podCopy := f(assumedPod), f(pod) if !reflect.DeepEqual(assumedPodCopy, podCopy) { return false } glog.V(3).Infof("Skipping pod %s/%s update", pod.Namespace, pod.Name) return true }
skipPodUpdate检查到以下情况同时发生时,都会返回true,表示忽略该pod update event。 该pod已经Assumed:检查scheduler cache中assumePods中是否包含该pod,如果包含,说明它已经Assumed(当pod完成了scheduler的Predicate和Priority后,立刻就设置为Assumed,之后再调用apiserver的Bind接口)。 该pod update只更新了它的ResourceVersion, Spec.NodeName, Annotations三者之一或者全部。 func (p *PriorityQueue) Update(oldPod, newPod *v1.Pod) error { p.lock.Lock() defer p.lock.Unlock() // If the pod is already in the active queue, just update it there. if _, exists, _ := p.activeQ.Get(newPod); exists { p.updateNominatedPod(oldPod, newPod) err := p.activeQ.Update(newPod) return err } // If the pod is in the unschedulable queue, updating it may make it schedulable. if usPod := p.unschedulableQ.get(newPod); usPod != nil { p.updateNominatedPod(oldPod, newPod) if isPodUpdated(oldPod, newPod) { p.unschedulableQ.delete(usPod) err := p.activeQ.Add(newPod) if err == nil { p.cond.Broadcast() } return err } p.unschedulableQ.addOrUpdate(newPod) return nil } // If pod is not in any of the two queue, we put it in the active queue. err := p.activeQ.Add(newPod) if err == nil { p.addNominatedPodIfNeeded(newPod) p.cond.Broadcast() } return err }
当skipPodUpdate为true时,接着调用PriorityQueue.Update: 如果该pod已经在activeQ中,则更新它。 如果该pod在unSchedulableQ中,检查该Pod是不是有效更新(忽略ResourceVersion、Generation、PodStatus)。 如果是有效更新,则从unSchedulableQ中删除该,并将更新的pod加到activeQ中待调度。 如果是无效更新,则更新unSchedulableQ中的该pod信息。 如果activeQ和unSchedulableQ中都没有该pod,则把该pod添加到activeQ中。
deletePodFromSchedulingQueue
注册Delete unassignedNonTerminatedPod Event Handler为deletePodFromSchedulingQueue。 func (c *configFactory) deletePodFromSchedulingQueue(obj interface{}) { ... if err := c.podQueue.Delete(pod); err != nil { runtime.HandleError(fmt.Errorf("unable to dequeue %T: %v", obj, err)) } ... } func (p *PriorityQueue) Delete(pod *v1.Pod) error { p.lock.Lock() defer p.lock.Unlock() p.deleteNominatedPodIfExists(pod) err := p.activeQ.Delete(pod) if err != nil { // The item was probably not found in the activeQ. p.unschedulableQ.delete(pod) } return nil } deletePodFromSchedulingQueue中对podQueue的处理就是调用其Delete接口,将该pod从activeQ或者unSchedulableQ中删除。
Node Informer
NodeInformer注册了Node的Add/Update/Delete Event Handler,这里我们只关注这些Handler对PriorityQueue的操作。
addNodeToCache and updateNodeInCache 注册Add Node Event Handler为addNodeToCache。 注册Update Node Event Handler为updateNodeInCache。 注册Delete Node Event Handler为deleteNodeFromCache。 func (c *configFactory) addNodeToCache(obj interface{}) { ... c.podQueue.MoveAllToActiveQueue() } func (c *configFactory) updateNodeInCache(oldObj, newObj interface{}) { ... c.podQueue.MoveAllToActiveQueue() } addNodeToCache和updateNodeInCache对PriorityQueue的操作都是一样的,调用PriorityQueue.MoveAllToActiveQueue将所有unSchedulableQ中的Pods移到activeQ中,意味着集群中增加或者更新Node时,所有未成功调度的pods都会重新在activeQ中按优先级进行重新排序等待调度。 deleteNodeFromCache中不涉及PodQueue的操作。 同 PodInformer EventHandler for Scheduled Pod 中提到的一样,如果集群中出现频繁增加或者更新Node的动作,会导致频繁将unSchedulableQ中的所有Pods移到activeQ中。如果unSchedulableQ中有个High Priority的Pod,那么就会导致频繁的抢占Lower Priority Pods的调度机会,使得Lower Priority Pod长期处于饥饿状态。
serviceInformer
serviceInformer注册了Service的Add/Update/Delete Event Handler,这里我们只关注这些Handler对PriorityQueue的操作。 注册Add Service Event Handler为onServiceAdd。 注册Update Service Event Handler为onServiceUpdate。 注册Delete Service Event Handler为onServiceDelete。 func (c *configFactory) onServiceAdd(obj interface{}) { ... c.podQueue.MoveAllToActiveQueue() } func (c *configFactory) onServiceUpdate(oldObj interface{}, newObj interface{}) { ... c.podQueue.MoveAllToActiveQueue() } func (c *configFactory) onServiceDelete(obj interface{}) { ... c.podQueue.MoveAllToActiveQueue() } Service的Add/Update/Delete Event Handler对podQueue的操作都是一样的,调用PriorityQueue.MoveAllToActiveQueue将所有unSchedulableQ中的Pods移到activeQ中,意味着集群中增加、更新或者删除Service时,所有未成功调度的pods都会重新在activeQ中按优先级进行重新排序等待调度。 同 PodInformer EventHandler for Scheduled Pod 中提到的一样,如果集群中出现频繁Add/Update/Delete Service的动作,会导致频繁将unSchedulableQ中的所有Pods移到activeQ中。如果unSchedulableQ中有个High Priority的Pod,那么就会导致频繁的抢占Lower Priority Pods的调度机会,使得Lower Priority Pod长期处于饥饿状态。
pvc Informer
pvcInformer注册了pvc的Add/Update/Delete Event Handler,这里我们只关注这些Handler对PriorityQueue的操作。 注册Add PVC Event Handler为onPvcAdd。 注册Update PVC Event Handler为onPvcUpdate。 注册Delete PVC Event Handler为onPvcDelete。 func (c *configFactory) onPvcAdd(obj interface{}) { ... c.podQueue.MoveAllToActiveQueue() } func (c *configFactory) onPvcUpdate(old, new interface{}) { ... c.podQueue.MoveAllToActiveQueue() } sheduler对PVC的Add和Update Event的操作都是一样的,调用PriorityQueue.MoveAllToActiveQueue将所有unSchedulableQ中的Pods移到activeQ中,意味着集群中增加或者更新PVC时,所有未成功调度的pods都会重新在activeQ中按优先级进行重新排序等待调度。 Delete PVC不涉及PodQueue的操作。 PV的Add/Update/Delete也不涉及PodQueue的操作。 同 PodInformer EventHandler for Scheduled Pod 中提到的一样,如果集群中出现频繁Add/Update PVC的动作,会导致频繁将unSchedulableQ中的所有Pods移到activeQ中。如果unSchedulableQ中有个High Priority的Pod,那么就会导致频繁的抢占Lower Priority Pods的调度机会,使得Lower Priority Pod长期处于饥饿状态。
总结
本文基于Kubernetes 1.10的代码,对scheduler的PriorityQueue进行了代码分析,包括PriorityQueue的内部结构(两个重要的Sub-Queue),Pod如何Push进队列,Pod如何Pop出队列,以及Pod/Service/Node/PVC对象的Add/Update/Delete事件对PriorityQueue中两个Sub-Queue的操作等。如今的scheduler比起1.8之前的版本复杂了很多,后面我会再对scheduler相关的Equivalence Class,Nominated Pods,VolumeScheduling等方面单独写博客进行分析。
云计算
2018-05-12 01:48:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
MySQL分页优化: SQL: select * from t_user u order by id limit 5000000, 10 分析:mysql会读取5000010条数据,然后只返回最后10条,查询的时间很长。 优化方案: 方案一:只允许查询前面的数据,不允许查询特别靠后的数据。eg:百度搜索出的结果,最多七十多页。 方案二:在查询下一页时把上一页最后一条数据的id(lastId)传过来,即:select * from t_user u where id > 5000000 order by id limit 10 注意:如果where条件中的判断条件还有其它非主键列,则需要建立复合索引,复合索引中必须包含where语句中的列。 方案三:延迟关联非索引列,即:select * from t_user u1 inner join (select id from t_user order by id limit 5000000, 10 ) u2 on u1.id=u2.id 实验: 环境:win7下MySQL5.6 t_user表中有6,274,934条数据,以下是t_user的建表语句: CREATE TABLE `t_user` ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT, `bu_id` INT(20) NOT NULL, `name` VARCHAR(255) NOT NULL, `age` INT(11) NOT NULL, `sex` VARCHAR(255) NULL DEFAULT NULL, PRIMARY KEY (`id`) ) COLLATE='utf8_general_ci' ENGINE=InnoDB; select * from t_user u order by id limit 5000000, 10 # 2.746 sec 只有这一个查询sql时,查询所需的时间。 # 25.615 sec 有一个不断往t_user表中插新数据的函数(或过程)一直在跑的情况下,执行上面的sql查询出数据所需的时间。 select * from t_user u where id > 5000000 order by id limit 10 # 0.047 sec 只有这一个查询sql时,查询所需的时间。 # 0.063 sec 有一个不断往t_user表中插新数据的函数(或过程)一直在跑的情况下,执行上面的sql查询出数据所需的时间。 select * from t_user u1 inner join (select id from t_user order by id limit 5000000, 10 ) u2 on u1.id=u2.id # 2.137 sec 只有这一个查询sql时,查询所需的时间。 # 13.604 sec 有一个不断往t_user表中插新数据的函数(或过程)一直在跑的情况下,执行上面的sql查询出数据所需的时间。
云计算
2018-05-11 20:53:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
初试Spring Cloud Gateway
构建服务端
使用Spring Boot构建一个简单的Web应用,外界向网关发送请求后,会转发到该应用,pom.xml文件内容如下: org.springframework.boot spring-boot-starter-parent 2.0.2.RELEASE org.springframework.boot spring-boot-starter-web
编写启动类与控制器,提供一个“hello”服务: @SpringBootApplication @RestController public class ServerApp { public static void main(String[] args) { SpringApplication.run(ServerApp.class, args); } @GetMapping("/hello") public String hello() { System.out.println("调用 hello 方法"); return "hello"; } }
ServerApp中的hello方法,会返回hello字符串,启动ServerApp,默认使用8080端口,浏览器中访问 http://localhost:8080/hello ,可看到浏览器输出结果。
构建网关
新建一个普通的Maven项目,加入Spring Cloud Gateway的依赖,pom.xml内容如下: org.springframework.boot spring-boot-starter-parent 2.0.0.RELEASE org.springframework.cloud spring-cloud-dependencies Finchley.RC1 pom import org.springframework.cloud spring-cloud-starter-gateway

为网关项目加入配置文件application.yml,修改服务器端口为9000,配置文件内容如下: server: port: 9000
添加启动类,配置一个路由定位器的bean,代码如下: @SpringBootApplication public class RouterApp { public static void main(String[] args) { SpringApplication.run(RouterApp.class, args); } @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { Function fn = new Function() { public Route.Builder apply(PredicateSpec t) { t.path("/hello"); return t.uri("http://localhost:8080"); } }; return builder.routes().route(fn).build(); } }
以上代码中,使用Spring容器中的RouteLocatorBuilder bean来创建路由定位器,调用Builder的route方法时,传入java.util.function.Function实例,这是Java8加入的其中一个函数式接口,我们可以使用函数式编程来实现以上的代码,下面的代码等价于前面的代码: @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route(t -> t.path("/hello") .and() .uri("http://localhost:8080")) .build(); }
以上的两段代码设定了一个路由规则,当浏览器访问网关的 http://localhost:9000/hello 地址后,就会路由到 http://localhost:8080/hello 。
除了可以路由到我们本例的8080端口外,还可以路由到其他网站,只需要改变一下PredicateSpec的uri即可,例如将.uri("http://localhost:8080")改为.uri(“http://www.163.com”)。

云计算
2018-05-11 19:47:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
摘要: 2017年Gartner发布的数据库厂商推荐报告中首次收录了来自中国的数据库厂商,分别是阿里云、巨杉数据库SequoiaDB以及南大通用GBase。在这三家厂商中,巨杉数据库和南大通用是专注于企业级市场的数据库厂商,而阿里云严格来说则是一家云计算公司。
2017年Gartner发布的数据库厂商推荐报告中首次收录了来自中国的数据库厂商,分别是阿里云、巨杉数据库SequoiaDB以及南大通用GBase。在这三家厂商中,巨杉数据库和南大通用是专注于企业级市场的数据库厂商,而阿里云严格来说则是一家 云计算 公司。
  为什么 云计算 公司会想要“跨界”数据库领域,而且还搞得有声有色呢?什么样的数据库才是云原生数据库?有何标准?……针对这些问题,我们在DTCC 2018开幕之前采访了阿里云数据库总架构师——蔡松露(花名:子嘉)。
▲阿里云云数据库总架构师 蔡松露
  蔡松露(子嘉),阿里云云数据库总架构师,主要负责阿里云POLARDB、NoSQL技术以及阿里云数据库整体架构等工作。在搜索引擎、NoSQL数据库、分布式系统、 操作系统 内核等领域有深厚积累与丰富的经验。
   云计算公司跨界数据库是趋势,自研数据库是水到渠成
  云计算公司为什么要“跨界”做数据库呢?AWS首席执行官Andy Jassy在自家大会上说的一句话给了我们很好的答案,“云计算的下一个竞争战场是数据库。”当然,在很多同行云计算公司的发展战略中也印证了这句话,我们看到国内外的云计算公司都在争相提供数据库服务,例如阿里云提供的数据库服务就达20多种。
  对此,子嘉表示云计算公司跨界数据库是大势所趋,首先数据库技术含金量很高,代表了数据最复杂的技术之一。其次,数据库是云计算中利润极其丰厚的一个领域。第三,物联网的持续发展会引发数据的爆炸式增长,而人工智能想要发展则需要大量数据的加持。如何将这两个爆红的领域连接起来?数据库就是一个很好的桥梁。
  如果说阿里云入局数据库领域是大势所趋,那么自研数据库就是水到渠成。阿里云的数据库体系有两大主线,一是开源数据库,包括MySQL、PostgreSQL、MongoDB等等,开源数据库产品主要面向中小客户。而大型客户对于性能、稳定性等诸多方面的要求较高,开源产品并不能完全满足需求,这就自然的引出了阿里云数据库的第二条主线——自研数据库。阿里云自研数据库的质量很高,以POLARDB为例,不仅对外兼容MySQL,符合云上原生架构,同时还应用了众多前沿的硬件。
   云原生数据库像是跑车,需要由内而外的与众不同
  云原生数据库应该是什么样的呢?子嘉认为首先必须要有优越的性能,能达到百万级别的QPS;其次要有超大规模的存储,阿里云POLARDB现在可达100TB存储空间;最后是生态,数据库必须要兼容开源生态。
  云原生数据库像一辆跑车,跑车有很多特性,比如外观、速度,但是一个有这样外观和速度的车不一定是跑车。所以,云原生数据库必须要有一个标准来界定它与普通数据库的不同之处。
  1. 一个云原生数据库不仅要是一个TP数据库,还要是一个AP数据库,也就是我们常说的HTAP;
  2. 一个云原生数据库必须是Serverless的,可以大幅削减成本;
  3. 一个云原生数据库必须是智能化的,可以承担很多枯燥棘手的诊断和管理工作。
  POLARDB是百分百的云原生数据库,以POLARDB为例,我们来看看云原生数据库由内而外有哪些具体的与众不同?经过优化的计算和存储引擎使得POLARDB读性能可达百万QPS,写性能超过13万QPS;采用计算节点和存储节点分离的设计,满足公有云计算环境下用户业务弹性扩展的需求;100%兼容MySQL,但性能却达MySQL的6倍;分布式块存储设备可为数据带来99.9999999%的高可靠性;采用白名单、VPC网络、SSL加密、SQL审计、数据多副本存储、备份恢复等全方位的手段保证数据库数据各个环节的安全。
   低价竞争不可惧,竞争真正靠的是核心技术
  国产数据库的痛点在哪里呢?之前,我们采访了多家国产数据库厂商,他们都不约而同的表示技术并不是他们的主要痛点,反而厂商之间的低价竞争是让他们最头疼的。为了抢占市场,很多厂商采用低价策略导致国产软件的市场利润不断压缩。此外,还有一些厂商急于求成,直接在现成的开源系统上进行改装。
  “低价竞争其实并不可惧”,子嘉表示,“竞争真正靠的还是核心技术,核心技术会让我们的成本比别人更低。”国内现在有70%的企业都因为数据挑战而对业务产生了影响,而面临的首要难题就是高成本,负担不起商业license和专业的工程师。
  而如何解决高成本问题就可以成为国产数据库的突破点之一。云原生数据库的Serverless在产品规格或版本升级的时候可以做到0成本,而且可以做到按需使用、按存储付费,同时计算成本也很低。
  “21世纪最贵的是人才!”对于企业来说,人力成本也是一项很沉重的负担,尤其是想要聘请经验丰富的DBA,如果数据库厂商能够帮助企业节约这部分费用,那么也会成为极具竞争力的部分。例如阿里云推出的智能顾问,它可以表现得像一个专业的DBA,当数据链路上有问题发生时,诊断整个链路并迅速给出根本原因,同时还可以负责成本控制、安全、审计等等职能。
   写在最后
  “中兴事件”爆发之后,国内对于基础软件的国产化热情高涨,数据库作为基础软件的重要组成部分,自然也就受到了更多关注。这次DTCC 2018大会上,子嘉将带来《深度解析云原生数据库POLARDB》的主题演讲,全方位阐述POLARDB的架构、产品设计以及未来工作,相信阿里云POLARDB的自研之路会给大家带来很多启发,感兴趣的朋友也可以关注5月11日子嘉现场演讲的视频直播。(以上文章转载自IT168)
原文链接
云计算
2018-05-11 11:05:01
「深度学习福利」大神带你进阶工程师,立即查看>>>
学习了 chart 结构和模板的知识后,现在重新实践一次 MySQL chart,相信会有更多收获。
chart 安装前的准备
作为准备工作,安装之前需要先清楚 chart 的使用方法。这些信息通常记录在 values.yaml 和 README.md 中。除了下载源文件查看,执行 helm inspect values 可能是更方便的方法。
输出的实际上是 values.yaml 的内容。阅读注释就可以知道 MySQL chart 支持哪些参数,安装之前需要做哪些准备。其中有一部分是关于存储的:
chart 定义了一个 PersistentVolumeClaim,申请 8G 的 PersistentVolume。由于我们的实验环境不支持动态供给,所以得预先创建好相应的 PV,其配置文件 mysql-pv.yml 内容为:
创建 PV mysql-pv :
接下来就可以安装 chart 了。
定制化安装 chart
除了接受 values.yaml 的默认值,我们还可以定制化 chart,比如设置 mysqlRootPassword 。
Helm 有两种方式传递配置参数: 指定自己的 values 文件。
通常的做法是首先通过 helm inspect values mysql > myvalues.yaml 生成 values 文件,然后设置 mysqlRootPassword ,之后执行 helm install --values=myvalues.yaml mysql 。 通过 --set 直接传入参数值,比如:
mysqlRootPassword 设置为 abc123 。另外, -n 设置 release 为 my ,各类资源的名称即为 my-mysql 。
通过 helm list 和 helm status 可以查看 chart 的最新状态。
PVC 已经 Bound ,Deployment 也 AVAILABLE 。
升级和回滚 release
release 发布后可以执行 helm upgrade 对其升级,通过 --values 或 --set 应用新的配置。比如将当前的 MySQL 版本升级到 5.7.15:
等待一些时间,升级成功。
helm history 可以查看 release 所有的版本。通过 helm rollback 可以回滚到任何版本。
回滚成功,MySQL 恢复到 5.7.14。
到这里,相信大家已经会使用 chart 了。下一节我们学习如何开发自己的 chart。
书籍:
1.《每天5分钟玩转Kubernetes》
https://item.jd.com/26225745440.html
2.《每天5分钟玩转Docker容器技术》
https://item.jd.com/16936307278.html
3.《每天5分钟玩转OpenStack》
https://item.jd.com/12086376.html
云计算
2018-05-11 06:30:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
功能场景
不需要别的理由,就是省钱。
以 华北1 ecs.t5-c1m2.xlarge ( 4vCPU 8GB ) 为例:
按量付费一周需要 131 元,而按周付费只需要 68 元。
如果您正在使用按量付费,但又不会使用一个月那么久(超过一个月可以转包月),还在等什么,果断转为按周实例吧。
操作步骤(ECS 控制台) 在 ECS 控制台选择按量付费的实例,单击 按量转包年包月 选择一周
操作步骤(使用OpenAPI) 点此查看代码示例 ,时长传入 1 Week 即可 其他 按量转包年包月使用说明 自动续费 原文链接
云计算
2018-05-15 19:44:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
背景
在云计算飞速发展的今天,用户ECS服务器身处的网络环境越来越复杂,弹性网卡让ECS服务器完美游走在日益复杂的网络环境中。但是以前服务器必须是 Stopped 状态才可以进行弹性网卡( ENI )的插拔,这样可能会影响运行在服务器上的业务。现在很高兴的向大家宣布:弹性网卡从今天开始支持热插拨,即ECS服务器只要处在稳定状态( Running Stopped ),就可以对弹性网卡进行插拔操作。
弹性网卡热插拔:控制台 控制台操作弹性网卡的位置:进入控制台 -> 云服务器 ECS -> 弹性网卡。 创建弹性网卡:点击 创建弹性网卡 按钮,在弹窗中填写网卡名称,选择专有网络 交换机 安全组等信息后创建弹性网卡。 热挂载弹性网卡:点击弹性网卡对应的 绑定实例 按钮,在弹窗中选择要绑定实例。实例状态只要求为稳定状态( Running Stopped )。 热卸载弹性网卡:点击弹性网卡对应的 解绑实例 按钮,确定即可解绑。实例状态只要求为稳定状态( Running Stopped )。 弹性网卡热插拔:OpenAPI
attach_eni detach_eni 分别可以根据弹性网卡ID,实例ID,进行弹性网卡的热插拔。相关API参考帮助文档: 挂载弹性网卡 , 卸载弹性网卡 。 # coding=utf-8 # if the python sdk is not install using 'sudo pip install aliyun-python-sdk-ecs' # if the python sdk is install using 'sudo pip install --upgrade aliyun-python-sdk-ecs' # make sure the sdk version is 4.7.1, you can use command 'pip show aliyun-python-sdk-ecs' to check import json import logging from aliyunsdkcore import client from aliyunsdkecs.request.v20140526.CreateNetworkInterfaceRequest import CreateNetworkInterfaceRequest from aliyunsdkecs.request.v20140526.AttachNetworkInterfaceRequest import AttachNetworkInterfaceRequest from aliyunsdkecs.request.v20140526.DetachNetworkInterfaceRequest import DetachNetworkInterfaceRequest from aliyunsdkecs.request.v20140526.DeleteNetworkInterfaceRequest import DeleteNetworkInterfaceRequest # configuration the log output formatter, if you want to save the output to file, # append ",filename='ecs_invoke.log'" after datefmt. logging.basicConfig(level=logging.INFO, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S') # send open api request def _send_request(request): request.set_accept_format('json') try: response_str = clt.do_action(request) logging.info(response_str) response_detail = json.loads(response_str) return response_detail except Exception as e: logging.error(e) # create eni def create_eni(vSwitchId, securityGroupId, networkInterfaceName=None, primaryIpAddress=None, description=None, clientToken=None): request = CreateNetworkInterfaceRequest() request.set_VSwitchId(vSwitchId) request.set_SecurityGroupId(securityGroupId) if (networkInterfaceName != None): request.set_NetworkInterfaceName(networkInterfaceName) if (primaryIpAddress != None): request.set_PrimaryIpAddress(primaryIpAddress) if (description != None): request.set_Description(description) if (clientToken != None): request.set_ClientToken(clientToken) _send_request(request) # attach eni to instance def attach_eni(eniId, instanceId): request = AttachNetworkInterfaceRequest() request.set_NetworkInterfaceId(eniId) request.set_InstanceId(instanceId) _send_request(request) # detach eni from instance def detach_eni(eniId, instanceId): request = DetachNetworkInterfaceRequest() request.set_NetworkInterfaceId(eniId) request.set_InstanceId(instanceId) _send_request(request) # delete eni def delete_eni(eniId): request = DeleteNetworkInterfaceRequest() request.set_NetworkInterfaceId(eniId) _send_request(request) if __name__ == '__main__': clt = client.AcsClient('Your Access Key Id', 'Your Access Key Secrect', 'cn-zhangjiakou') vSwitchId = "vsw-test" securityGroupId = "sg-test" # create_eni(vSwitchId=vSwitchId, securityGroupId=securityGroupId) attach_eniId = "eni-test" attach_instanceId = "i-test" # attach_eni(attach_eniId, attach_instanceId) detach_eniId = "eni-test" detach_instanceId = "i-test" # detach_eni(detach_eniId, detach_instanceId) delete_eniId = "eni-test" # delete_eni(delete_eniId) 小结
现在的弹性网卡热插拔只要求实例为稳定状态即可,改进了以前实例只能为 Stopped 状态才能插拔弹性网卡的现状。提升了用户体验,现在服务器不用关机就能轻松配置弹性网卡,更加灵活实用。
原文链接
本文为云栖社区原创内容,未经允许不得转载。
云计算
2018-05-15 19:08:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
近日,阿里云宣布推出Serverless Kubernetes服务此举意在降低容器技术的使用门槛、简化容器平台运维。并同时发布阿里云服务对Open Service Broker API标准支持,通过一致、简单、可扩展的接口,将各种类型开发服务便捷统一化地交付到Cloud Foundry、Kubernetes等云原生应用平台;轻松实现多云环境下应用开发,让用户更多关注自身业务创新。
不断演进的云计算
如今大家已经不再质疑“是否应该采用云计算”这个命题,更多的关注点则是“云计算将怎样进一步节省成本并创造业务价值”。
业界普遍认为,更进阶的云计算服务应该使得用户无需关注环境配置、服务器管理、维护升级等操作,即剥离掉与云端资源层的耗时工作并将更多精力集中到业务层的开发与实现。
整个IT运维技术已经经历了物理机、虚拟机和云化三个阶段,而新兴的容器技术和Serverless则被业界视为云计算的更高阶段;即IT的角色重心从节省成本、提供支撑转变为高效备战、引领创新。容器技术和Serverless作为新兴技术,相对于传统庞大的单体架构而言,更加简捷高效;是当下业界推崇的微服务和DevOps文化的重要工具。
容器技术创新点在于应用会以标准的形式打包成镜像,镜像中含有应用运行的所需全部信息,可以屏蔽差异性并快速启若干容器,从而实现应用服务层面的弹性扩容。镜像作为交付物使得开发、测试、运维、部署和发布各个环节更顺畅高效。正如掀起容器浪潮的Docker公司所说,容器可以“Build, Ship, and Run Any App, Anywhere”。
与容器技术类似,serverless也有着‘让开发应用过程更简单’的初心。Serverless是一个宽泛的且再不断演进的概念,它意在让用户使用云服务时不再有机器的概念,不需要手动管理底层资源便可以实时按需弹性伸缩。相对传统的server-base模式,它更注重的将用户从复杂繁琐的配置管理工作中解脱出来、更多地专注于自身业务逻辑的创新。
Kubernetes联合创始人Brendan Burns表示,回顾整体容器技术发展可以发现两个非常清晰的演进线索:其一是通过解耦业务架构可以明晰团队职责,其二是研发人员需要更多地倾注于应用开发(这才是最重要的事情);他同时表示“Kubernetes的未来就是Serverless”, Kubernetes屏蔽掉底层的机器信息,为使用者们呈现容器提供无服务器化运行的体验。Kubernetes的建立是为了给开发人员面向应用的API,并希望让使用者忘记掉机器和机器管理的细节,但是实际上兑现这个初心并不是一帆风顺,他预计未来大多数人的Kubernetes集群将是专用机器和无服务器计算容器基础设施之间的混合体。
忘掉服务器管理的细节,无服务器运行容器应用
阿里云提供着国内最大规模的公共云容器服务, 也是国内首家推出函数计算服务的供应商。如今,在容器和Serverless之间,阿里云也提供了一种新形态的云服务——Serverless Kubernetes容器服务。相比函数计算的代码无服务器化运行,Serverless Kubernetes提供容器应用的无服务器运行环境,基于强大的阿里云弹性计算基础设施,具备简单易用、按需付费、兼容并包、安全隔离、按需扩容、互联互通等优势。
在经典的Kubernetes容器集群模式中,用户有高度的灵活性,可以对集群基础设施和容器应用进行细粒度的控制,如可以选择宿主机实例(如GPU实例、裸金属服务器)和操作系统、K8S版本、网络模型等,也可以根据自己的节奏都对集群进行升级、监控应用容器资源利用率、根据容量规划手工或自动对集群扩缩容。
而在Serverless集群模式下,用户只需指明应用容器镜像、对CPU和内存需求,选定对外服务模式,即可直接启动应用程序。简单易用,用户可以实现5秒创建集群、30秒部署应用、按需扩展;与现有Kubernetes应用完全兼容,支持标准的API、CLI来部署和管理应用;与专有网络(VPC)中已有应用、数据库互联互通的同时,应用容器之间依旧保持安全隔离、防止互相干扰,并且确保企业级的高可用和安全性。
Serverless Kubernetes结合容器的高移植性和高灵活性与阿里云弹性计算提供的弹性调度和隔离性,其应用场景非常广泛,可敏捷便利部署于包括web应用、移动应用后端服务、多媒体处理、数据处理、持续集成等多种场景,非常适合批量任务和突发工作。
阿里云Serverless Kubernetes基于阿里云基础设施能力,与Kubernetes生态兼容,并且可以与用户现有应用环境完全融合。
作为国内最大规模的公共云容器服务,阿里云容器产品已经服务了超过数千家企业。容器服务的愿景是帮助企业IT迁云、实现多云战略,利用云原生技术进行IT现代化改造,从而助推业务创新。而Serverless Kubernetes将给用户一个更多的选择,在与现有主流开源技术兼容的基础上,进一步降低使用容器技术的门槛,让用户关注在应用和创新。
尊重多云意愿,支持Open Service Broker API标准
在云计算的时代,由于地域覆盖、数据安全、成本等多种原因,企业们开始考虑选用混合云或者多云模式。为了给用户更多选择的自由,阿里云提供了对Cloud Foundry、Kubernetes/Docker、Terraform、Ansible、Chef、Open Service Broker API等开源社区主流技术的支持,帮助用户在云端和本地数据中心有一致的应用和资源管理体验。不久前,阿里云成为Cloud Foundry认证云基础设计供应商,并成为CF基金会黄金会员。
5月2日,阿里云容器服务正式发布对Open Service Broker API标准支持。用户可以通过一致、简单、可扩展的接口,将开发的各种类型服务便捷统一化地交付到如Cloud Foundry、Kubernetes等多个不同的云原生应用平台。
Open Service Broker API来源于Cloud Foundry Service Brokers组件, 并于2016年被贡献成为独立的社区开源项目。目前已成为业界关于云应用集成和管理服务的事实标准。
在以往,如果选用了多种类云服务,用户往往需要编写不同的代码并执行不同的操作流程,才能实现应用的集中化集成与管理,使用起来复杂且低效。
而如今,阿里云遵循Open Service Broker API 标准,提供一系列服务代理组件,实现了对阿里云服务如云数据库服务RDS,对象存储服务OSS等,以及主流开源服务如MySQL/MariaDB,Spark,RabbitMQ等的完美支持。具体而言,用户可以在容器服务提供的服务目录界面浏览到各种服务,便捷地创建和销毁不同规格服务实例,实现服务实例与目标应用动态绑定,以安全的方式将服务实例的访问信息注入到相应应用容器中。
在支持Open Service Broker API标准时,阿里云特别考虑到了跨平台通用性。目前,用户部署在阿里云Kubernetes服务和Cloud Foundry中的应用,都能够以同样地方式创建、绑定、调用上述各种服务,并已有数家国内外客户受益于此。
除了持续优化Cloud Foundry/Kubernetes生态与阿里云的链接之外,未来用户还可以通过Open Service Broker API将应用集成到其他云平台或自有的服务。阿里云帮助用户实现多云策略和混合云方案,尊重用户意愿并为用户提供极大的灵活性。
原文链接
本文为云栖社区原创内容,未经允许不得转载。
云计算
2018-05-15 18:35:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
摘要: 容器开启数据服务之旅系列(二):Kubernetes如何助力Spark大数据分析 (二):Kubernetes如何助力Spark大数据分析 概述 本文为大家介绍一种容器化的数据服务Spark + OSS on ACK,允许Spark分布式计算节点对阿里云OSS对象存储的直接访问。
容器开启数据服务之旅系列(二):Kubernetes如何助力Spark大数据分析
(二):Kubernetes如何助力Spark大数据分析
概述
本文为大家介绍一种容器化的数据服务Spark + OSS on ACK,允许Spark分布式计算节点对阿里云OSS对象存储的直接访问。借助阿里云Kubernetes容器服务与阿里云OSS存储资源的深度整合,允许Spark分布式内存计算,机器学习集群对云上的大数据直接进行分析和保存结果。
先决条件 你已经通过阿里云容器服务创建了一个Kubernetes集群,详细步骤参见 创建Kubernetes集群
从容器服务控制台创建一个Spark OSS实例
使用三次点击来创建一个1 master + 3 worker 的Spark OSS的实例
1 登录 https://cs.console.aliyun.com/
2 点击 “应用目录”
3 选择 "spark-oss", 点击 “参数”

给你的应用一个名字, e.g. spark-oss-online2 (必选) 填写你的oss_access_key_id和oss_access_key_secret Worker: # set OSS access keyID and secret oss_access_key_id: oss_access_key_secret: (可选)修改工作节点数目 Worker.Replicas: 3

4 点击 “部署”
5 点击 “Kubernetes 控制台”,查看部署实例

6 点击 服务, 查看外部端点, 点击URL访问Spark集群


7 测试Spark集群 打开一个spark-shell kubectl get pod | grep worker spark-oss-online2-worker-57894f65d8-fmzjs 1/1 Running 0 44m
spark-oss-online2-worker-57894f65d8-mbsc4 1/1 Running 0 44m
spark-oss-online2-worker-57894f65d8-zhwr4 1/1 Running 0 44m kubectl exec -it spark-oss-online2-worker-57894f65d8-fmzjs -- /opt/spark/bin/spark-shell --master spark://spark-oss-online2-master:7077 粘贴下列代码,使用Spark测试OSS的读写性 // Save RDD to OSS bucket val stringRdd = sc.parallelize(Seq("Test Strings\n Test String2")) stringRdd.saveAsTextFile("oss://eric-new/testwrite12") // Read data from OSS bucket val lines = sc.textFile("oss://eric-new/testwrite12") lines.take(10).foreach(println) Test Strings
Test String2
CLI 命令行操作
Setup keys and deploy spark cluster in one command export OSS_ID= export OSS_SECRET= helm install -n myspark-oss --set "Worker.oss_access_key_id="$OSS_ID",Worker.oss_access_key_secret="$OSS_SECRET incubator/spark-oss kubectl get svc| grep oss myspark-oss-master ClusterIP 172.19.9.111 7077/TCP 2m myspark-oss-webui LoadBalancer 172.19.13.1 120.55.104.27 8080:30477/TCP 2m
云计算
2018-04-17 15:04:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
摘要: 在Kubernetes集群中,Ingress作为集群流量接入层,Ingress的高可靠性显得尤为重要,今天我们主要探讨如何部署一套高性能高可靠的Ingress接入层。

简介

在Kubernetes集群中,Ingress是授权入站连接到达集群服务的规则集合,为您提供七层负载均衡能力,您可以通过 Ingress 配置提供外部可访问的 URL、负载均衡、SSL、基于名称的虚拟主机等。作为集群流量接入层,Ingress的高可靠性显得尤为重要,今天我们主要探讨如何部署一套高性能高可靠的Ingress接入层。

高可靠部署架构

高可靠性首先要解决的就是单点故障问题,一般常用的是采用多副本部署的方式,我们在Kubernetes集群中部署高可靠Ingress接入层同样采用多节点部署架构,同时由于Ingress作为集群流量接入口,建议采用独占Ingress节点的方式,以避免业务应用与Ingress服务发生资源争抢。

如上述部署架构图,由多个独占Ingress实例组成统一接入层承载集群入口流量,同时可依据后端业务流量水平扩缩容Ingress节点。当然如果您前期的集群规模并不大,也可以采用将Ingress服务与业务应用混部的方式,但建议进行资源限制和隔离。

在阿里云容器服务集群中部署高可靠Ingress接入层

部署说明
Ingress SLB:Ingress接入层前端SLB实例 Ingress Node:部署Ingress Pod的集群节点 Ingress Pod:Ingress服务实例
这三者之间依据标签node-role.kubernetes.io/ingress=true进行关联:
1.Ingress SLB后端只会挂载打标了node-role.kubernetes.io/ingress=true的集群Node;
2.Ingress Pod只会被部署到打标了node-role.kubernetes.io/ingress=true的集群Node;
开始部署

1、创建 Kubernetes 集群

在创建集群之前,我们需要依据自身具体业务场景来适当规划集群的规模以及集群内各节点角色,比如业务节点数、Ingress节点数等,注意集群默认会初始化3台Master节点来部署集群管控服务。

我们通过 阿里云容器服务控制台 创建一个Kubernetes集群,这里以创建3台Worker节点集群为例。

2、打标 Ingress Node

由于测试集群规模较小,我们暂采用混部的方式:即3台Worker节点既作为业务节点又作为Ingress节点。我们给3台Worker节点同时打标node-role.kubernetes.io/ingress=true,注意不建议将Ingress Pod部署在集群Master节点上,因为Master节点承载着集群的所有管控服务,以避免集群接入流量过高时对管控服务造成影响。

~ kubectl label no cn-hangzhou.i-bp1ecwpuisra0y0bizdb node-role.kubernetes.io/ingress=true node "cn-hangzhou.i-bp1ecwpuisra0y0bizdb" labeled ~ kubectl label no cn-hangzhou.i-bp1ecwpuisra0y0bizdc node-role.kubernetes.io/ingress=true node "cn-hangzhou.i-bp1ecwpuisra0y0bizdc" labeled ~ kubectl label no cn-hangzhou.i-bp1ecwpuisra0y0bizdd node-role.kubernetes.io/ingress=true node "cn-hangzhou.i-bp1ecwpuisra0y0bizdd" labeled ~ kubectl get no NAME STATUS ROLES AGE VERSION cn-hangzhou.i-bp11psgsvkxklfvb8vvj Ready master 1h v1.9.3 cn-hangzhou.i-bp183t1a82uun0s12ddr Ready master 1h v1.9.3 cn-hangzhou.i-bp1ecwpuisra0y0bizdb Ready ingress 56m v1.9.3 cn-hangzhou.i-bp1ecwpuisra0y0bizdc Ready ingress 56m v1.9.3 cn-hangzhou.i-bp1ecwpuisra0y0bizdd Ready ingress 57m v1.9.3 cn-hangzhou.i-bp1gb2498ykvy23k0jsy Ready master 1h v1.9.3

3、创建 Ingress 服务

集群初始化时默认部署了一个Ingress Controller,具体部署说明请 参考 。这里我们通过DaemonSet方式将其重新部署到目标Ingress Node上,当然您也可以采用Deployment配合亲和性方式来部署。

~ kubectl -n kube-system delete deploy nginx-ingress-controller deployment "nginx-ingress-controller" deleted ~ kubectl create -f https://acs-k8s-ingress.oss-cn-hangzhou.aliyuncs.com/nginx-ingress-controller-ds.yml daemonset "nginx-ingress-controller" created ~ kubectl -n kube-system get ds | grep nginx-ingress-controller nginx-ingress-controller 3 3 3 3 3 node-role.kubernetes.io/ingress=true 42s ~ kubectl -n kube-system get pod -o wide | grep nginx-ingress-controller nginx-ingress-controller-57j4l 1/1 Running 0 1m 172.16.3.2 cn-hangzhou.i-bp1ecwpuisra0y0bizdd nginx-ingress-controller-d7cxb 1/1 Running 0 1m 172.16.5.7 cn-hangzhou.i-bp1ecwpuisra0y0bizdc nginx-ingress-controller-m9w75 1/1 Running 0 1m 172.16.4.2 cn-hangzhou.i-bp1ecwpuisra0y0bizdb

4、更新 Ingress SLB 服务

集群初始化时默认部署了一个Ingress LoadBalancer Service,具体部署说明请 参考 ,这里需要更新下Ingress LoadBalancer Service,以自动识别挂载打标的Ingress Node。
~ kubectl apply -f https://acs-k8s-ingress.oss-cn-hangzhou.aliyuncs.com/nginx-ingress-slb-service.yml service "nginx-ingress-lb" configured

5、此时具有3个Ingress实例的高可靠接入层部署完成。

快速扩容

随着您的业务流量不断增长,集群规模不断扩大,您只需要简单地通过打标的方式来快速扩容Ingress接入层。

全方位监控

集群Ingress接入层的监控是必不可少的,您可以通过 阿里云容器服务监控 以及 阿里云云监控 对Ingress Pod和Ingress Node进行全方位监控。

原文链接
阅读更多干货好文,请关注扫描以下二维码:
云计算
2018-04-17 14:39:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
摘要: 在Kubernetes集群中,Ingress作为集群流量接入层,Ingress的高可靠性显得尤为重要,今天我们主要探讨如何部署一套高性能高可靠的Ingress接入层。
简介
在Kubernetes集群中,Ingress是授权入站连接到达集群服务的规则集合,为您提供七层负载均衡能力,您可以通过 Ingress 配置提供外部可访问的 URL、负载均衡、SSL、基于名称的虚拟主机等。作为集群流量接入层,Ingress的高可靠性显得尤为重要,今天我们主要探讨如何部署一套高性能高可靠的Ingress接入层。
高可靠部署架构
高可靠性首先要解决的就是单点故障问题,一般常用的是采用多副本部署的方式,我们在Kubernetes集群中部署高可靠Ingress接入层同样采用多节点部署架构,同时由于Ingress作为集群流量接入口,建议采用独占Ingress节点的方式,以避免业务应用与Ingress服务发生资源争抢。
如上述部署架构图,由多个独占Ingress实例组成统一接入层承载集群入口流量,同时可依据后端业务流量水平扩缩容Ingress节点。当然如果您前期的集群规模并不大,也可以采用将Ingress服务与业务应用混部的方式,但建议进行资源限制和隔离。
在阿里云容器服务集群中部署高可靠Ingress接入层
部署说明
Ingress SLB:Ingress接入层前端SLB实例 Ingress Node:部署Ingress Pod的集群节点 Ingress Pod:Ingress服务实例
这三者之间依据标签node-role.kubernetes.io/ingress=true进行关联: Ingress SLB后端只会挂载打标了node-role.kubernetes.io/ingress=true的集群Node; Ingress Pod只会被部署到打标了node-role.kubernetes.io/ingress=true的集群Node;
开始部署
1、创建 Kubernetes 集群
在创建集群之前,我们需要依据自身具体业务场景来适当规划集群的规模以及集群内各节点角色,比如业务节点数、Ingress节点数等,注意集群默认会初始化3台Master节点来部署集群管控服务。
我们通过 阿里云容器服务控制台 创建一个Kubernetes集群,这里以创建3台Worker节点集群为例。
2、打标 Ingress Node
由于测试集群规模较小,我们暂采用混部的方式:即3台Worker节点既作为业务节点又作为Ingress节点。我们给3台Worker节点同时打标node-role.kubernetes.io/ingress=true,注意不建议将Ingress Pod部署在集群Master节点上,因为Master节点承载着集群的所有管控服务,以避免集群接入流量过高时对管控服务造成影响。 ~ kubectl label no cn-hangzhou.i-bp1ecwpuisra0y0bizdb node-role.kubernetes.io/ingress=true node "cn-hangzhou.i-bp1ecwpuisra0y0bizdb" labeled ~ kubectl label no cn-hangzhou.i-bp1ecwpuisra0y0bizdc node-role.kubernetes.io/ingress=true node "cn-hangzhou.i-bp1ecwpuisra0y0bizdc" labeled ~ kubectl label no cn-hangzhou.i-bp1ecwpuisra0y0bizdd node-role.kubernetes.io/ingress=true node "cn-hangzhou.i-bp1ecwpuisra0y0bizdd" labeled ~ kubectl get no NAME STATUS ROLES AGE VERSION cn-hangzhou.i-bp11psgsvkxklfvb8vvj Ready master 1h v1.9.3 cn-hangzhou.i-bp183t1a82uun0s12ddr Ready master 1h v1.9.3 cn-hangzhou.i-bp1ecwpuisra0y0bizdb Ready ingress 56m v1.9.3 cn-hangzhou.i-bp1ecwpuisra0y0bizdc Ready ingress 56m v1.9.3 cn-hangzhou.i-bp1ecwpuisra0y0bizdd Ready ingress 57m v1.9.3 cn-hangzhou.i-bp1gb2498ykvy23k0jsy Ready master 1h v1.9.3
3、创建 Ingress 服务
集群初始化时默认部署了一个Ingress Controller,具体部署说明请 参考 。这里我们通过DaemonSet方式将其重新部署到目标Ingress Node上,当然您也可以采用Deployment配合亲和性方式来部署。 ~ kubectl -n kube-system delete deploy nginx-ingress-controller deployment "nginx-ingress-controller" deleted ~ kubectl create -f https://acs-k8s-ingress.oss-cn-hangzhou.aliyuncs.com/nginx-ingress-controller-ds.yml daemonset "nginx-ingress-controller" created ~ kubectl -n kube-system get ds | grep nginx-ingress-controller nginx-ingress-controller 3 3 3 3 3 node-role.kubernetes.io/ingress=true 42s ~ kubectl -n kube-system get pod -o wide | grep nginx-ingress-controller nginx-ingress-controller-57j4l 1/1 Running 0 1m 172.16.3.2 cn-hangzhou.i-bp1ecwpuisra0y0bizdd nginx-ingress-controller-d7cxb 1/1 Running 0 1m 172.16.5.7 cn-hangzhou.i-bp1ecwpuisra0y0bizdc nginx-ingress-controller-m9w75 1/1 Running 0 1m 172.16.4.2 cn-hangzhou.i-bp1ecwpuisra0y0bizdb
4、更新 Ingress SLB 服务
集群初始化时默认部署了一个Ingress LoadBalancer Service,具体部署说明请 参考 ,这里需要更新下Ingress LoadBalancer Service,以自动识别挂载打标的Ingress Node。 ~ kubectl apply -f https://acs-k8s-ingress.oss-cn-hangzhou.aliyuncs.com/nginx-ingress-slb-service.yml service "nginx-ingress-lb" configured
5、此时具有3个Ingress实例的高可靠接入层部署完成。
快速扩容
随着您的业务流量不断增长,集群规模不断扩大,您只需要简单地通过打标的方式来快速扩容Ingress接入层。
全方位监控
集群Ingress接入层的监控是必不可少的,您可以通过 阿里云容器服务监控 以及 阿里云云监控 对Ingress Pod和Ingress Node进行全方位监控。
原文链接
云计算
2018-04-17 14:33:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
摘要: 这是本系列的第2篇内容,将介绍在Docker和Kubernetes环境中解决遗留应用无法识别容器资源限制的问题。
本系列文章记录了企业客户在应用Kubernetes时的一些常见问题 第一篇:Java应用资源限制的迷思 第二篇:利用LXCFS提升容器资源可见性 第三篇:解决服务依赖

这是本系列的第2篇内容,将介绍在Docker和Kubernetes环境中解决遗留应用无法识别容器资源限制的问题。

Linuxs利用Cgroup实现了对容器的资源限制,但在容器内部依然缺省挂载了宿主机上的procfs的/proc目录,其包含如:meminfo, cpuinfo,stat, uptime等资源信息。一些监控工具如free/top或遗留应用还依赖上述文件内容获取资源配置和使用情况。当它们在容器中运行时,就会把宿主机的资源状态读取出来,引起错误和不便。

LXCFS简介

社区中常见的做法是利用 lxcfs 来提供容器中的资源可见性。lxcfs 是一个开源的FUSE(用户态文件系统)实现来支持LXC容器,它也可以支持Docker容器。

LXCFS通过用户态文件系统,在容器中提供下列 procfs 的文件。

/proc/cpuinfo /proc/diskstats /proc/meminfo /proc/stat /proc/swaps /proc/uptime

LXCFS的示意图如下
比如,把宿主机的 /var/lib/lxcfs/proc/memoinfo 文件挂载到Docker容器的/proc/meminfo位置后。容器中进程读取相应文件内容时,LXCFS的FUSE实现会从容器对应的Cgroup中读取正确的内存限制。从而使得应用获得正确的资源约束设定。

Docker环境下LXCFS使用

注: 本文采用CentOS 7.4作为测试环境,并已经开启FUSE模块支持。 Docker for Mac/Minikube等开发环境由于采用高度剪裁过的操作系统,无法支持FUSE,并运行LXCFS进行测试。
安装 lxcfs 的RPM包

wget https://copr-be.cloud.fedoraproject.org/results/ganto/lxd/epel-7-x86_64/00486278-lxcfs/lxcfs-2.0.5-3.el7.centos.x86_64.rpm yum install lxcfs-2.0.5-3.el7.centos.x86_64.rpm

启动 lxcfs

lxcfs /var/lib/lxcfs &

测试

$docker run -it -m 256m \ -v /var/lib/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw \ -v /var/lib/lxcfs/proc/diskstats:/proc/diskstats:rw \ -v /var/lib/lxcfs/proc/meminfo:/proc/meminfo:rw \ -v /var/lib/lxcfs/proc/stat:/proc/stat:rw \ -v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw \ -v /var/lib/lxcfs/proc/uptime:/proc/uptime:rw \ ubuntu:16.04 /bin/bash root@f4a2a01e61cd:/# free total used free shared buff/cache available Mem: 262144 708 261436 2364 0 261436 Swap: 0 0 0

我们可以看到total的内存为256MB,配置已经生效。

lxcfs 的 Kubernetes实践

一些同学问过如何在Kubernetes集群环境中使用lxcfs,我们将给大家一个示例方法供参考。
首先我们要在集群节点上安装并启动lxcfs,我们将用Kubernetes的方式,用利用容器和DaemonSet方式来运行 lxcfs FUSE文件系统。

本文所有示例代码可以通过以下地址从Github上获得

git clone https://github.com/denverdino/lxcfs-initializer cd lxcfs-initializer

其manifest文件如下

apiVersion: apps/v1beta2 kind: DaemonSet metadata: name: lxcfs labels: app: lxcfs spec: selector: matchLabels: app: lxcfs template: metadata: labels: app: lxcfs spec: hostPID: true tolerations: - key: node-role.kubernetes.io/master effect: NoSchedule containers: - name: lxcfs image: registry.cn-hangzhou.aliyuncs.com/denverdino/lxcfs:2.0.8 imagePullPolicy: Always securityContext: privileged: true volumeMounts: - name: rootfs mountPath: /host volumes: - name: rootfs hostPath: path: /
注: 由于 lxcfs FUSE需要共享系统的PID名空间以及需要特权模式,所有我们配置了相应的容器启动参数。

可以通过如下命令在所有集群节点上自动安装、部署完成 lxcfs,是不是很简单?:-)
kubectl create -f lxcfs-daemonset.yaml
那么如何在Kubernetes中使用 lxcfs 呢?和上文一样,我们可以在Pod的定义中添加对 /proc 下面文件的 volume(文件卷)和对 volumeMounts(文件卷挂载)定义。然而这就让K8S的应用部署文件变得比较复杂,有没有办法让系统自动完成相应文件的挂载呢?

Kubernetes提供了 Initializer 扩展机制,可以用于对资源创建进行拦截和注入处理,我们可以借助它优雅地完成对lxcfs文件的自动化挂载。

注: 阿里云Kubernetes集群,已经默认开启了对 Initializer 的支持,如果是在自建集群上进行测试请参见 文档 开启相应功能

其 manifest 文件如下
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: lxcfs-initializer-default namespace: default rules: - apiGroups: ["*"] resources: ["deployments"] verbs: ["initialize", "patch", "watch", "list"] --- apiVersion: v1 kind: ServiceAccount metadata: name: lxcfs-initializer-service-account namespace: default --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: lxcfs-initializer-role-binding subjects: - kind: ServiceAccount name: lxcfs-initializer-service-account namespace: default roleRef: kind: ClusterRole name: lxcfs-initializer-default apiGroup: rbac.authorization.k8s.io --- apiVersion: apps/v1beta1 kind: Deployment metadata: initializers: pending: [] labels: app: lxcfs-initializer name: lxcfs-initializer spec: replicas: 1 template: metadata: labels: app: lxcfs-initializer name: lxcfs-initializer spec: serviceAccountName: lxcfs-initializer-service-account containers: - name: lxcfs-initializer image: registry.cn-hangzhou.aliyuncs.com/denverdino/lxcfs-initializer:0.0.2 imagePullPolicy: Always args: - "-annotation=initializer.kubernetes.io/lxcfs" - "-require-annotation=true" --- apiVersion: admissionregistration.k8s.io/v1alpha1 kind: InitializerConfiguration metadata: name: lxcfs.initializer initializers: - name: lxcfs.initializer.kubernetes.io rules: - apiGroups: - "*" apiVersions: - "*" resources: - deployments

注: 这是一个典型的 Initializer 部署描述,首先我们创建了service account lxcfs-initializer-service-account,并对其授权了 “deployments” 资源的查找、更改等权限。然后我们部署了一个名为 “lxcfs-initializer” 的Initializer,利用上述SA启动一个容器来处理对 “deployments” 资源的创建,如果deployment中包含 initializer.kubernetes.io/lxcfs为true的注释,就会对该应用中容器进行文件挂载

我们可以执行如下命令,部署完成之后就可以愉快地玩耍了

kubectl apply -f lxcfs-initializer.yaml

下面我们部署一个简单的Apache应用,为其分配256MB内存,并且声明了如下注释 “initializer.kubernetes.io/lxcfs”: “true”

其manifest文件如下
apiVersion: apps/v1beta1 kind: Deployment metadata: annotations: "initializer.kubernetes.io/lxcfs": "true" labels: app: web name: web spec: replicas: 1 template: metadata: labels: app: web name: web spec: containers: - name: web image: httpd:2 imagePullPolicy: Always resources: requests: memory: "256Mi" cpu: "500m" limits: memory: "256Mi" cpu: "500m"

我们可以用如下方式进行部署和测试

$ kubectl create -f web.yaml deployment "web" created $ kubectl get pod NAME READY STATUS RESTARTS AGE web-7f6bc6797c-rb9sk 1/1 Running 0 32s $ kubectl exec web-7f6bc6797c-rb9sk free total used free shared buffers cached Mem: 262144 2876 259268 2292 0 304 -/+ buffers/cache: 2572 259572 Swap: 0 0 0

我们可以看到free命令返回的 total memory 就是我们设置的容器资源容量。

我们可以检查上述Pod的配置,果然相关的 procfs 文件都已经挂载正确

$ kubectl describe pod web-7f6bc6797c-rb9sk ... Mounts: /proc/cpuinfo from lxcfs-proc-cpuinfo (rw) /proc/diskstats from lxcfs-proc-diskstats (rw) /proc/meminfo from lxcfs-proc-meminfo (rw) /proc/stat from lxcfs-proc-stat (rw) ...

在Kubernetes中,还可以通过 Preset 实现类似的功能,篇幅有限。本文不再赘述了。

总结

本文介绍了通过 lxcfs 提供容器资源可见性的方法,可以帮助一些遗留系统更好的识别容器运行时的资源限制。

同时,在本文中我们介绍了利用容器和DaemonSet的方式部署lxcfs FUSE,这不但极大简化了部署。也可以方便地利用Kubernetes自身的容器管理能力,支持lxcfs进程失效时自动恢复,在集群伸缩时也可以保证节点部署的一致性。这个技巧对于其他类似的监控或者系统扩展都是适用的。

另外我们介绍了利用Kubernetes的扩展机制 Initializer,实现对 lxcfs 文件的自动化挂载。整个过程对于应用部署人员是透明的,可以极大简化运维复杂度。同时利用类似的方法,我们可以灵活地定制应用部署的行为,满足业务的特殊要求。

阿里云Kubernetes服务 全球首批通过Kubernetes一致性认证,简化了Kubernetes集群生命周期管理,内置了与阿里云产品集成,也将进一步简化Kubernetes的开发者体验,帮助用户关注云端应用价值创新。

原文链接
阅读更多干货好文,请关注扫描以下二维码:
云计算
2018-04-17 14:10:00