利用LXCFS提升容器资源可见性

由于默认情况下容器挂载的是宿主机的硬件配置信息,导致有些应用根据这些信息来决定启动内存等的大小,导致应用内存溢出等问题。

LXCFS简介

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

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

1
2
3
4
5
6
/proc/cpuinfo
/proc/diskstats
/proc/meminfo
/proc/stat
/proc/swaps
/proc/uptime

LXCFS的示意图如下:

LXCFS的示意图

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

安装lxcfs ,先安装需要使用的依赖包:

yum install http://mirror.centos.org/centos/7/os/x86_64/Packages/fuse-libs-2.9.2-10.el7.x86_64.rpm

用deamonset方式在每个节点启动一个lxcfs,lxcfs-daemonset.yaml配置如下:

nginx-ingress-controller部署

1.打标签

由于nginx要部署到指定节点上,所以需要对node打个label,通过nodeSelector调度到节点上,同时要确保部署节点主机的80、443、18080、10254端口没有被占用。
kubectl label node ss-1-centos221 nginx-ingress=nginx
kubectl label node ss-1-centos221-2 nginx-ingress=nginx

2.准备nginx-ingress-controller部署文件

2.1 nginx-ingress-controller-rbac.yaml :设置rabc权限

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nginx-ingress-serviceaccount
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: nginx-ingress-clusterrole
rules:
- apiGroups:
- ""
resources:
- configmaps
- endpoints
- nodes
- pods
- secrets
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- apiGroups:
- ""
resources:
- services
verbs:
- get
- list
- watch
- apiGroups:
- "extensions"
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- "extensions"
resources:
- ingresses/status
verbs:
- update
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
name: nginx-ingress-role
namespace: kube-system
rules:
- apiGroups:
- ""
resources:
- configmaps
- pods
- secrets
- namespaces
verbs:
- get
- apiGroups:
- ""
resources:
- configmaps
resourceNames:
# Defaults to "<election-id>-<ingress-class>"
# Here: "<ingress-controller-leader>-<nginx>"
# This has to be adapted if you change either parameter
# when launching the nginx-ingress-controller.
- "ingress-controller-leader-nginx"
verbs:
- get
- update
- apiGroups:
- ""
resources:
- configmaps
verbs:
- create
- apiGroups:
- ""
resources:
- endpoints
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: nginx-ingress-role-nisa-binding
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: nginx-ingress-role
subjects:
- kind: ServiceAccount
name: nginx-ingress-serviceaccount
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: nginx-ingress-clusterrole-nisa-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: nginx-ingress-clusterrole
subjects:
- kind: ServiceAccount
name: nginx-ingress-serviceaccount
namespace: kube-system

跨域请求以及实现跨域的方案

1.什么是跨域请求

A cross-domain solution (CDS) is a means of information assurance that provides the ability to manually or automatically access or transfer between two or more differing security domains.

解决两个安全域之间的信息传递,这个就叫做CDS——跨域解决方案.

在 HTML 中,<a>, <form>, <img>, <script>, <iframe>, <link>等标签以及 Ajax(异步 JavaScript 和 XML) 都可以指向一个资源地址,而所谓的跨域请求就是指:当前发起请求的域与该请求指向的资源所在的域不一样。
这里的域指的是这样的一个概念:我们认为若协议 + 域名 + 端口号均相同,那么就是同域.

2.跨域请求的安全问题

通常,浏览器会对上面提到的跨域请求作出限制。浏览器之所以要对跨域请求作出限制,是出于安全方面的考虑,因为跨域请求有可能被不法分子利用来发动 CSRF攻击。

CSRF攻击:
CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。CSRF攻击者在用户已经登录目标网站之后,诱使用户访问一个攻击页面,利用目标网站对用户的信任,以用户身份在攻击页面对目标网站发起伪造用户操作的请求,达到攻击目的。

CSRF 攻击的原理大致描述如下:有两个网站,其中A网站是真实受信任的网站,而B网站是危险网站。在用户登陆了受信任的A网站是,本地会存储A网站相关的Cookie,并且浏览器也维护这一个Session会话。这时,如果用户在没有登出A网站的情况下访问危险网站B,那么危险网站B就可以模拟发出一个对A网站的请求(跨域请求)对A网站进行操作,而在A网站的角度来看是并不知道请求是由B网站发出来的(Session和Cookie均为A网站的),这时便成功发动一次CSRF 攻击。

因而 CSRF 攻击可以简单理解为:攻击者盗用了你的身份,以你的名义发送而已请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账……造成的问题包括:个人隐私泄露以及财产安全。

3.同源策略

在客户端编程语言中,如javascript和ActionScript,同源策略是一个很重要的安全理念,它在保证数据的安全性方面有着重要的意义。同源策略规定跨域之间的脚本是隔离的,一个域的脚本不能访问和操作另外一个域的绝大部分属性和方法

概述:
同源策略是 Netscape 提出的一个著名的安全策略
同源策略是浏览器最核心最基础的安全策略
现在所有的可支持 Javascript 的浏览器都会使用这个策略
web构建在同源策略基础之上,浏览器对非同源脚本的限制措施是对同源策略的具体实现

同源策略的含义:
DOM 层面的同源策略:限制了来自不同源的”Document”对象或 JS 脚本,对当前“document”对象的读取或设置某些属性
Cookie和XMLHttprequest层面的同源策略:禁止 Ajax 直接发起跨域HTTP请求(其实可以发送请求,结果被浏览器拦截,不展示),同时 Ajax 请求不能携带与本网站不同源的 Cookie。
同源策略的非绝对性:<script><img><iframe><link><video><audio>等带有src属性的标签可以从不同的域加载和执行资源。
其他插件的同源策略:flash、java applet、silverlight、googlegears等浏览器加载的第三方插件也有各自的同源策略,只是这些同源策略不属于浏览器原生的同源策略,如果有漏洞则可能被黑客利用,从而留下XSS攻击的后患

RESTful API 了解

1.REST概念

REST全称是Representational State Transfer。要理解RESTful架构,需要理解Representational State Transfer这个词组到底是什么意思,它的每一个词都有些什么涵义。下面我们结合REST原则,围绕资源展开讨论,从资源的定义、获取、表述、关联、状态变迁等角度,列举一些关键概念并加以解释。

  • 资源与URI
  • 统一资源接口
  • 资源的表述
  • 资源的链接
  • 状态的转移

2.RESTful API概念

在开发的过程中,我们经常会听到前后端分离这个技术名词,顾名思义,就是前台的开发和后台的开发分离开。这个技术方案的实现就是要借助API,API简单说就是开发人员提供编程接口被其他人调用,他们调用之后会返回数据供其使用。API的类型有多种,但是现在比较主流且实用的就是RESTful API。

RESTful API 的总结:
1.每一个URL代表一种资源
2.客户端和服务器之间,传递这种资源的某种表现层
3.客户端通过四个HTTP动词,对服务器端资源进行操作,实现”表现层状态转化”。具体为:
GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源。

2.1 RESTful API方法-GET

  • 安全且幂等

  • 获取表示

  • 变更时获取表示(缓存)

  • 200(OK) - 表示已在响应中发出

  • 204(无内容) - 资源有空表示

  • 301(Moved Permanently) - 资源的URI已被更新

  • 303(See Other) - 其他(如,负载均衡)

  • 304(not modified)- 资源未更改(缓存)

  • 400 (bad request)- 指代坏请求(如,参数错误)

  • 404 (not found)- 资源不存在

  • 406 (not acceptable)- 服务端不支持所需表示

  • 500 (internal server error)- 通用错误响应

  • 503 (Service Unavailable)- 服务端当前无法处理请求

k8s+dubbo架构集群内外网络通讯解决方案

1.问题

k8s有自己的一套网络管理机制,集群内的容器和容器之间是可以相互通信的。

但是在容器化升级改造的过程中,不可能一步到位的将所有的服务全部迁移到k8s的容器当中来,毕竟新的技术在没有经过实践趟坑时,肯定不能轻易的全面铺开升级。

那么就涉及到集群外的服务访问集群内的服务,集群内容器中的ip都是k8s管理的IP,dubbo服务注册的也是获取的容器内分配的IP。

比如宿主机ip是10.201.7.xx,容器内的ip就是172.66.4.x。群外的和宿主主机同网段的服务通过拿到dubbo的注册的172.66.4.x也根本没法访问容器内的dubbo服务。

2.分析

k8s是通过Service来暴露集群内的服务,假如dubbo服务注册的是Service暴露的端口和宿主的IP那么集群外的服务就可以直接访问集群内容器中的服务了。

该方案主要有两个难点:

1.如何获取Service暴露的端口和宿主机的IP注入到POD环境变量;

2.Dubbo服务如何从环境变量获取IP和端口注册到ZK;

关于难点1:

通过downward-api的方式向Pod内注入NodeIP的env;

通过给Pod注入env的方式将NodePort注入到Pod内;(要求先创建Service)

关于难点2:

Dubbo在启动阶段提供两对系统属性,用于设置外部通信的IP和端口地址。

DUBBO_IP_TO_REGISTRY — 注册到注册中心的IP地址
DUBBO_PORT_TO_REGISTRY — 注册到注册中心的端口
DUBBO_IP_TO_BIND — 监听IP地址
DUBBO_PORT_TO_BIND — 监听端口

深刻理解Docker镜像大小

1.docker镜像分析

是否还记得第一个接触Docker的时候,你从Docker Hub下拉的那个镜像呢?在那个处女镜像的基础上,你运行了容器生涯的处女容器。镜像的基石作用已经很明显,在Docker的世界里,可以说是:No Image,No Container。

再进一步思考Docker镜像,大家可能很快就会联想到以下几类镜像:

1.系统级镜像:如Ubuntu镜像,CentOS镜像以及Debian容器等;

2.工具栈镜像:如Golang镜像,Flask镜像,Tomcat镜像等;

3.服务级镜像:如MySQL镜像,MongoDB镜像,RabbitMQ镜像等;

4.应用级镜像:如WordPress镜像,DockerRegistry镜像等。

镜像林林总总,想要运行Docker容器,必须要有Docker镜像;想要有Docker镜像,必须要先下载Docker镜像;既然涉及到下载Docker镜像,自然会存在Docker镜像存储。谈到Docker镜像存储,那我们首先来聊聊Docker镜像大小方面的知识。

以下将从三个角度来分析Docker镜像的大小问题:Dockerfile与镜像、联合文件系统以及镜像共享关系。

Dockerfile与镜像
Dockerfile由多条指令构成,随着深入研究Dockerfile与镜像的关系,很快大家就会发现,Dockerfile中的每一条指令都会对应于Docker镜像中的一层。

继续以如下Dockerfile为例:

1
2
3
4
FROM ubuntu:14.04
ADD run.sh /
VOLUME /data
CMD ["./run.sh"]

k8s常见问题解决

1.基础镜像制作规范和使用

1.1 时区修改
官网下载centos镜像默认时区是国外的时区,需要把它修改成上海时区。运维提供提一个基础的镜像给业务部门下载使用。

1.2 规范docker运行程序的用户
基于安全和规范的考虑,docker统一使用一个uid为1001的,用户名为pub的普通账号运行程序,需要在镜像和容器的宿主机上面同时新建。这个也是运维在初始化基础镜像和容器宿主机上面统一创建。

1.3 规范每个容器的cpu和内存(每个容器分配1核2G内存,视情况而定)

2.镜像下载策略

2.1 默认的镜像拉取策略是“IfNotPresent”,在镜像已经存在的情况下,kubelet将不在去拉取镜像。 如果总是想要拉取镜像,必须设置拉取策略为“Always”或者设置镜像标签为“:latest”。

如果没有指定镜像的标签,它会被假定为“:latest”,同时拉取策略为“Always”。

3.增加k8s各个命名空间的服务账号 default 的自定义权限(RABC)

首先,了解下什么是RABC:

基于角色的访问控制(Role-Based Access Control, 即”RBAC”)使用”rbac.authorization.k8s.io” API Group实现授权决策,允许管理员通过Kubernetes API动态配置策略。

在RBAC API中,一个角色包含了一套表示一组权限的规则。 权限以纯粹的累加形式累积(没有”否定”的规则)。 角色可以由命名空间(namespace)内的Role对象定义,而整个Kubernetes集群范围内有效的角色则通过ClusterRole对象实现

比如授予default命名空间的default ServiceAccount账号能够”get”, “watch”, “list”, “patch” default 命名空间里面的pod资源

3.1 定义role,一个Role对象只能用于授予对某一单一命名空间中资源的访问权限。 以下示例描述了”default”命名空间中的一个Role对象的定义,用于授予对pod的读访问权限:

1
2
3
4
5
6
7
8
9
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # 空字符串""表明使用core API group
resources: ["pods"]
verbs: ["get", "watch", "list", "patch"]

k8s专题[10.使用Spinnaker持续发布应用]

本节介绍如何使用spinnaker的持续发布k8s的应用

1.首先使用spinnaker创建一个nginxdemo 的应用,再在nginxdemo应用里面创建 Pipeline。进入nginxdemo 详情页面,点击 “PIPELINES”,目前是没有任何信息的,点击 “+ Create”,弹框中选择类型为 Pipeline,输入流程名称,这里我命名为 nginxdemo-pipe。因为第一次创建,下边 “Copy From” 选择没出来,后续在创建时,我们也可以通过 “Copy From” 方式选择已存在的 Pipeline,非常方便就复制了一个一样配置的流程。创建完毕后,就会出现详细配置 Pipeline State 的页面了

图1

2.配置 Configuration 项

刚开始这里只有一个 Configuration 选项,可以配置 Automated Triggers、Parameters、Notifications 等,这里说下 Automated Triggers 和 Parameters 这两个非常有用,我们可以将此视为 Pipeline 启动前的一些初始化配置,比如启动需要的参数配置、自动触发配置等,为后续各阶段提供必要的信息。
Automated Triggers 自动触发,它提供 7 种类型的触发方式:

  • CRON:调度触发,可以执行一个 cron 调度任务来定时任务触发该流程。
  • Git:当执行 Git push 操作时,触发该流程
  • Jenkins:监听 Jenkins 的某一个 Job
  • Travis:监听 Travis 的某一个 Job
  • Pipeline:监听另一个 Pipeline 执行
  • Pub/Sub:当接受到 pubsub 消息时触发
  • Docker Registry:当 image 更新时触发。

基本能满足我们日常持续集成或交付的需求,当然每一个类型都需要配置相应的参数,比如 Cron 类型,需要配置执行频率、启动时间等。下图我们选择Docker Registry作为触发类型

k8s专题[9.基于Jenkins和Spinnaker的CI/CD流程]

流程图

基于Jenkins和Spinnaker的CI/CD流程

流程说明:
1.用户向Gitlab提交代码,代码中包含Dockerfile
2.将代码提交到远程仓库
3.Gitlab提交触发Jenkins自动构建
4.Jenkins的CI流水线自动编译代码并打包成docker镜像推送到Harbor镜像仓库
5.更新Ingress的配置,根据新部署的应用的名称,在ingress的配置文件中增加一条路由信息(不是新业务不用更改此配置)
6.Jenkins构建完成可触发Spinnaker的自动发布流程,或者手动触发spinnaker发布。
7.Spinnaker会根据发布流程更新kubernetes YAML配置文件
8.Spinnaker调用kubernetes的API,部署应用

k8s专题[8.spinnaker基本介绍]

1.概念

Spinnaker 是 Netflix 的开源项目,是一个持续交付平台,它定位于将产品快速且持续的部署到多种云平台上。Spinnaker 通过将发布和各个云平台解耦,来将部署流程流水线化,从而降低平台迁移或多云品台部署应用的复杂度,它本身内部支持 Google、AWS EC2、Microsoft Azure、Kubernetes和OpenStack 等云平台,并且它可以无缝集成其他持续集成(CI)流程,如 git、Jenkins、Travis CI、Docker registry、cron 调度器等。简而言之,Spinnaker是致力于提供在多种平台上实现开箱即用的集群管理和部署功能的平台。

2.功能

2.1:集群管理主要用于管理云上的资源,它分为以下几个块

  • Server Group:服务组,是资源管理单位,识别可部署组件和基础配置设置,它并且关联了一个负载均衡器和安全组,当部署完毕后,服务组就相当于一组运行中的软件实例集合,如(VM 实例,Kubernetes pods)。
  • Cluster:集群,由用户定义的,对服务组的逻辑分组。
  • Applications:应用,是对集群的逻辑分组。
  • Load Balancer:负载均衡,用于将外部网络流量重定向到服务组中的机器实例,还可以指定一系列规则,用来对服务组中的机器实例做健康监测。
  • Security Group:安全组,定义了网络访问权限,由IP、端口和通信协议组成的防火墙

2.2:部署管理功能用于创建一个持续交付流程,它可分为管道和阶段两大部分

  • 管道 部署管理的核心是管道,在Spinnaker的定义中,管道由一系列的阶段(stages)组成。管道可以人工触发,也可以配置为自动触发,比如由 Jenkins Job 完成时、Docker Images 上传到仓库时,CRON 定时器、其他管道中的某一阶段。同时,管道可以配置参数和通知,可以在管道一些阶段上执行时发送邮件消息。Spinnaker 已经内置了一些阶段,如执行自定义脚本、触发 Jenkins 任务等。
  • 阶段 阶段在 Spinnaker 中,可以作为管道的一个自动构建模块的功能组成。我们可以随意在管道中定义各个阶段执行顺序。Spinnaker 提供了很多阶段供我们选择使用,比如执行发布(Deploy)、执行自定义脚本 (script)、触发 Jenkins 任务 (jenkins)等,功能很强大。
  • 部署策略 Spinnaker 支持精细的部署策略,比如 红/黑(蓝/绿)部署,多阶段环境部署,滚动红/黑策略,canary 发布等。用户可以为每个环境使用不同部署策略,比如,测试环境可以使用红/黑策略,生产环境使用滚动红/黑策略,它封装好了必须的步骤,用户不需要复杂操作,就可以实现企业级上线。

3.Spinnaker 架构所依赖的各个组件


:D 一言句子获取中...