Month: 九月 2018

kubernetes 初探——部署集群

随着 docker cloud 的关闭,容器的编排工具之争似乎已经结束了,Docker Swarm 算是完了,Kubernetes 笑到了最后。然而 k8s 的组件众多,因此部署起来也很麻烦。为此,网上有不少的网上有不少的部署教程和脚本,包括但不限于:

  • kubesaz
  • minikube
  • kubespray
  • rke
  • kubernetes: the hard way

本文基于 ubuntu 18.04. CentOS 上好多默认设置都需要修改,因此建议大家基于 Ubuntu 部署 k8s。

使用 kubespray 安装 k8s

(零) 假设我们要在三台机器上安装,另外一台机器作为控制节点。其中每台都作为工作节点,两台作为 master 节点。

IP | 角色
————|———————–
10.4.17.165 | 控制节点,不参与 k8s 集群
10.4.17.167 | master, node
10.4.17.168 | master, node
10.4.17.169 | node

(一) 下载 kubespray 安装包,这里我们使用最新版 (2018.10), 可能需要安装 python3, 如果没有安装的话

VERSION=2.7.0

# download kubespray
wget https://github.com/kubernetes-incubator/kubespray/archive/v${VERSION}.tar.gz
tar xzf v${VERSION}.tar.gz

# install dependencies
pip3 install -r kubespray-${VERSION}/requirements.txt

(二) 生成部署的 hosts.ini

kubespray 中有一个脚本叫做 inventory_builder 用来生成部署的 hosts.ini

cd kubespray-v${VERSION}
cp -r inventory/sample inventory/mycluster
declare -a IPS=(10.4.17.167 10.4.17.168 10.4.17.169)
CONFIG_FILE=inventory/mycluster/hosts.ini python3 contrib/inventory_builder/inventory.py ${IPS[@]}

生成之后,可以查看生成的文件

cat inventory/mycluster/host.ini

[k8s-cluster:children]
kube-master·▸   ·
kube-node·▸ ·

[all]
node1 ▸  ansible_host=10.4.17.167 ip=10.4.17.167
node2 ▸  ansible_host=10.4.17.168 ip=10.4.17.168
node3 ▸  ansible_host=10.4.17.169 ip=10.4.17.169

[kube-master]
node1·▸ ·
node2·▸ ·

[kube-node]
node1·▸ ·
node2·▸ ·
node3·▸ ·

[etcd]
node1·▸ ·
node2·▸ ·
node3·▸ ·

[calico-rr]

[vault]
node1·▸ ·
node2·▸ ·
node3·▸ ·

(三) 修改一些配置

代理:

由于众所周知的原因,k8s 依赖的 gcr.io 在中国大陆范围内无法访问,我们可以使用代理访问,关于如何搭建代理超出了本文的范围。
假设我们的代理是 http://proxy.com:10086, 修改 inventory/mycluster/group_vars/all/all.yml 文件,设置 httpproxy 和 httpsproxy 两个变量。

下载 kubectl 到本机:

设置 kubectllocalhost 和 kubeconfiglocalhost 两个变量为 true. 安装完成后会在本机安装 kubectl, 并且可以使用 inventory/mycluster/artifacts/admin.conf 使用 kubectl.

(四) 部署

这里我们需要使用 tiger 用户,这个用户需要满足如下条件:

  1. 可以无密码远程登录
  2. 在远程主机上具有无密码 sudo 权限
ansible-playbook -i inventory/mycluster/hosts.ini cluster.yml --become --user tiger -v

大概过十几分钟就部署好了

(五) 验证

cd inventory/mycluster/artifacts
./kubectl.sh get nodes

NAME      STATUS    ROLES         AGE       VERSION
node1     Ready     master,node   1d        v1.11.3
node2     Ready     master,node   1d        v1.11.3
node3     Ready     node          1d        v1.11.3

参考

  1. HN 上关于 Docker Cloud 关闭的讨论
  2. 使用 Kubespray 部署生产可用的 Kubernetes 集群

requests cookies 为空的一个坑

有时候,requests 返回的 cookies 会为空,原因是链接发生了 301/302 跳转,而 cookies 是跟着第一个响应返回的,第二个响应没有返回 Set-Cookie header。所以直接读取 r.cookies 是空的,而在 session.cookies 中是有数据的。

解决方法是直接读 s.cookies。

s = requests.Session()
r = s.get("http://httpbin.org/cookies/set?foo=bar")
cookies = requests.utils.dict_from_cookiejar(s.cookies)
s.cookies.clear()

不过需要注意的是如果在多线程环境中使用 session 需要注意锁的问题,建议把 session 设置成 thread local 的类型。

influxdb+grafana+telegraf 监控系统搭建

本文基于 ubuntu 18.04

要不要用 docker?

这是一个哲学问题,用不用其实都有各自的好处。不过在这里我倾向于不用。因为 influxdb 和 grafana 都有好多的状态,而且不是都可以写到 mysql 中的,所以既然还得 mount 出来,何苦用 docker 呢?telegraf 需要采集系统的相关信息,更不适合放在 docker 里面。

  • InfluxDB,开源的时间序列数据库
  • Grafana,开源的数据可视化工具

搭建过程

influxdb && telegraf

因为这两个都是一家的产品,所以安装步骤都是一样的。按照 官网 给的安装步骤,其实很简单的。

curl -sL https://repos.influxdata.com/influxdb.key | sudo apt-key add -
source /etc/lsb-release
echo "deb https://repos.influxdata.com/${DISTRIB_ID,,} ${DISTRIB_CODENAME} stable" | sudo tee /etc/apt/sources.list.d/influxdb.list

sudo apt-get update && sudo apt-get install influxdb telegraf
sudo systemctl start influxdb telegraf

我们暂时就不配置了,直接使用默认配置。可以通过 systemctl status influxdb 来查看状态

grafana

同样参考 官网 的教程。

基本概念

Grafana 从数据源中读取数据,数据源一般是时间序列数据库。their data can be mixed in a single panel.

Grafana 使用 orginazations and users to manage permissions.

A dashboard consists of rows, rows consist of panels. for each panel, there is a query editor to edit which data the panel should show.

VERSION=5.1.4
wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_${VERSION}_amd64.deb
apt-get install -y adduser libfontconfig
dpkg -i grafana_${VERSION}_amd64.deb

sudo systemctl daemon-reload
sudo systemctl enable grafana-server
sudo systemctl start grafana-server

然后就 ok 啦,打开 http://ip:3000 就能访问 grafana 的界面了,默认用户名和密码是 admin。如果是在阿里云等云上面,注意要在安全组里面开一下 3000 端口。

配置

配置 telegraf 的插件

配置 grafana 的 datasource

未完待续

参考资料

  1. https://blog.csdn.net/w958660278/article/details/80484486
  2. https://juejin.im/post/5b4568c851882519790c72f3
  3. https://grafana.com/dashboards/928
  4. http://docs.grafana.org/guides/gettingstarted/
  5. http://docs.grafana.org/guides/basic_concepts/

监控系统基本概念与选型

时序数据库

监控系统的基础是时序数据库

现代的监控系统一般都有如下几部分组成:

时序数据库 + 前端显示 + 报警系统 + 指标收集

一般需要实现的功能:

  • 度量数据收集和可视化
  • 收集尽可能多的性能和状态数据
  • 图形化做有意义的展示
  • 如果发现可疑问题,可以关联其他图表找到原因
  • 错误检测
  • 按需告警,触发条件越宽松则告警应该越少
  • 避免误报

从监控的层次划分的话,一般包含三层监控:

  • 基础层:主机的 CPU, 内存,网络及 IO 等
  • 中间层:应用运行的中间件层,Nginx, Tomcat, MySQL, Redis
  • 应用层:服务端及客户端性能数据,如 API 访问次数和响应时间等

现代的监控越来越关注应用层和其他层数据的整合能力,具有快速找到系统瓶颈,方便扩容或代码优化。

时序数据库的选择

监控数据往往都带有时间戳,其实就是一种典型时间序列数据,而这方面已经有很多专门的存储系统,如 opentsdb,influxdb,prometheus 等。相比 mysql 这样的传统数据库,这类系统在存储、查询上针对时间序列数据都做了特别的优化。

其中 opentsdb 基于 hadoop 生态系统,考虑到搭建的复杂度,暂时不考虑了。influxdb 和 prometheus 都是 Golang 编写的,直接一个二进制文件就可以运行。两者的区别有:

  • prometheus 对于保存长时间的数据有一些问题,influxdb 似乎没有问题
  • 另外 influxdb 可以直接写入,而 prometheus 是基于拉 (pull) 模式的,也就是说程序不能直接写入 prometheus,而是需要由 prometheus 去定期拉监控数据,太反人类了。
  • influxdb 的查询类似 SQL,而 prometheus 的查询语法更加简洁,但是有学习成本,各有千秋吧

所以选用 influxdb 了。

前端显示

唯一的标准自然是越漂亮越好,所以我们选择 grafana。

当然另一需要考虑的是编写查询界面不要过于复杂,这方面 grafana 只需要拖拽空间和勾勾选选就可以了,显然不成问题。

报警系统

grafan 自带了一些报警,但是只能根据阈值报警,显然不能满足我们的需求。我们这里选择了 bosun,是 Stack Overflow 开源的一款监控系统。通过简单的几个语句就可以编写复杂的报警条件。

指标收集

按照前面的分析,对于应用层,也就是我们自己的代码,可以随意地添加代码打点,这里不再赘述。对于系统的 metrics 的收集,可以使用 influxdb 公司钦定的 telegraf。telegraf 也有一些不同的插件,可以很好地支持 mysql、redis 等的监控数据收集。

参考

  1. Logs and Metrics and Graphs, Oh my!
  2. Prometheus 和 influxdb 对比
  3. 360 基于 Prometheus 的在线服务监控实践
  4. 虎牙直播运维负责人张观石:基于时序数据库的直播业务监控实践
  5. 监控系统选型
  6. openTSDB/Bosun 报警语法 介绍 / 学习笔记
  7. https://zhuanlan.zhihu.com/p/28127748

为什么不使用 scrapy?

请参考更新版本: https://yifei.me/note/838

最近面了几家公司,每当我提到头条的爬虫都是自己写的时候,对方一个下意识的问题就是: “为什么不使用开源的 scrapy?”。实际上我在头条的 lead 就是 scrapy 的 contributor,而他自己也不用自己的框架,显然说明 scrapy 不适合大型项目,那么具体问题在哪儿呢?今天终于有时间了,详细写写这个问题。

爬虫并不需要一个框架

Web 服务器是一个爬虫可以抽象出来的是各种组件。而 scrapy 太简陋了,比如说去重,直接用的是内存中的一个集合。如果要依赖 scrapy 写一个大型的爬虫,几乎每个组件都要自己实现,那有何必用 scrapy 呢?

scrapy 不是完整的爬虫框架

一个完整的爬虫至少需要两部分,fetcher 和 frontier。其中 fetcher 用于下载网页,而 frontier 用于调度。scrapy 重点实现的是 fetcher 部分,也就是下载部分。

scrapy 依赖 twisted

这一点导致 scrapy 深入后曲线非常地陡峭,要想了解一些内部的机理,必须对 twisted 比较明了。而 twisted 正如它的名字一样,是非常扭曲的一些概念,虽然性能非常好,但是要理解起来是要花上不少时间的。

scrapy 适合的领域

scrapy 主要适合一次性地从指定的站点爬取一些数据

最重要的并不是你使用不使用 Scrapy,而是你不能为每一站点去单独写一个爬虫的脚本。代码的灵活度实在太大了,对于没有足够经验的工程师来说,写出来的脚本可能很难维护。重点是要把主循环掌握在爬虫平台的手中,而不是让每一个脚本都各行其是。

参考

  1. scrapy 源码解读