CentOS 7 使用代理服务器

这篇文章记录如何在 CentOS 7 下使用代理服务器,以此在国内服务器下载 k8s 的镜像,例如<k8s.gcr.io/defaultbackend:1.3>

代理客户端

代理客户端用来连接本地与服务器。

  1. 安装

    sudo yum -y install epel-release
    sudo yum -y install python-pip
    sudo pip install shadowsocks
    
  2. 配置

    sudo mkdir -p /etc/shadowsocks
    sudo vi /etc/shadowsocks/shadowsocks.json
    

    配置信息如下:

    {
        "server":"x.x.x.x",  # 服务器地址
        "server_port":1035,  # 服务器端口
        "local_address": "127.0.0.1", # 本地IP
        "local_port":1080,  # 本地端口
        "password":"password", # 连接密码
        "timeout":300,  # 等待超时时间
        "method":"aes-256-cfb",  # 加密方式
        "fast_open": false,  # true或false。开启fast_open以降低延迟,但要求Linux内核在3.7+
        "workers": 1  #工作线程数 
    }
    
  3. 自启动

    新建脚本

    touch /etc/systemd/system/shadowsocks.service
    # vi /etc/systemd/system/shadowsocks.service
    
    [Unit]
    Description=Shadowsocks
    [Service]
    TimeoutStartSec=0
    ExecStart=/usr/bin/sslocal -c /etc/shadowsocks/shadowsocks.json
    [Install]
    WantedBy=multi-user.target
    
  4. 启动Shadowsocks

    systemctl enable shadowsocks.service
    systemctl start shadowsocks.service
    systemctl status shadowsocks.service
    
  5. 验证运行状况

    curl --socks5 127.0.0.1:1080 -i http://ip.cn
    

    将会显示ip的具体位置。

privoxy

许多应用没有 socks 的能力。privoxy 用来将 socks5 代理转为 http 代理,就可以给大部分应用提供代理支持了。

  1. 安装

    yum install privoxy -y
    systemctl enable privoxy
    systemctl start privoxy
    systemctl status privoxy
    
  2. 配置

    cat >> /etc/privoxy/config << EOF
    forward-socks5t / 127.0.0.1:1080 .
    EOF
    
  3. 设置http、https代理

    # vi ~/.bashrc 在最后添加如下信息
    PROXY_HOST=127.0.0.1
    export all_proxy=http://$PROXY_HOST:8118
    export ftp_proxy=http://$PROXY_HOST:8118
    export http_proxy=http://$PROXY_HOST:8118
    export https_proxy=http://$PROXY_HOST:8118
    export no_proxy=localhost,172.16.0.0/16,192.168.0.0/16.,127.0.0.1,10.10.0.0/16
    
    # 重载环境变量
    source ~/.bashrc
    
  4. 验证运行状况

    curl -i http://ip.cn
    

    将会显示ip的具体位置。

取消代理,只要将 ~/.bashrc 中的内容取消掉,再 source 加载就好了。

参考资料


kubernetes helm 入门

注:这篇文章已经有一定的年代了,可以查看小站2021年更新的文章。

这篇文章记录如何安装和使用helm。

什么是 helm

Kubernetes是容器集群管理系统,每个成功的软件平台都有一个优秀的打包系统,比如 Debian、Ubuntu 的 apt,Redhat、Centos 的 yum。而 Helm 则是 Kubernetes 上的包管理器。

helm相当于一个应用商店,将一个在云上部署的应用相关的组件全部打包起来,进行安装、升级、管理等。

在kubernetes中,我们部署一个标准的应用,以下的应用基本都会使用到:

  1. Service
  2. Secret
  3. PVC
  4. Deployment
  5. ConfigMap

helm 有几个概念名词:chart,release和repository。chart就是包,而release代表一个运行实例,Repository是用于发布和存储 Chart 的存储库。

helm 的工作,就是将这些yaml配置在更高一个层次,统一起来管理:

  1. 新建chart。
  2. 更新chart。
  3. 在kubernetes中安装和卸载release。
  4. 更新、回滚和测试release。

helm 架构

helm 包含两个组件:helm 客户端 和 tiller 服务器:

  • helm客户端负责管理chart
  • tiller服务器负责管理release
  • Repository 是 Chart 存储库,Helm 客户端通过 HTTP 协议来访问存储库中 Chart 的索引文件和压缩包。

helm安装

  1. helm客户端

    curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get | bash
    helm version
    
    # 安装helm命令补全脚本
    cd ~ && helm completion bash > .helmrc && echo "source .helmrc" >> .bashrc
    
  2. tiller服务器

    创建tiller的serviceaccountclusterrolebinding

    kubectl create serviceaccount --namespace kube-system tiller
    kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
    

    然后安装helm服务端tiller

    helm init -i xxxx/k8s.gcr.io/tiller:v2.9.0
    

    使用-i指定自己的镜像,因为官方的镜像因为某些原因无法拉取。

    为应用程序设置serviceAccount

    kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
    

    检查是否安装成功:

    $ kubectl -n kube-system get pods|grep tiller
    tiller-deploy-f5597467b-wdwfl      1/1       Running   0          2h
    $ helm version
    Client: &version.Version{SemVer:"v2.9.0", GitCommit:"f6025bb9ee7daf9fee0026541c90a6f557a3e0bc", GitTreeState:"clean"}
    Server: &version.Version{SemVer:"v2.9.0", GitCommit:"f6025bb9ee7daf9fee0026541c90a6f557a3e0bc", GitTreeState:"clean"}
    

tips:

安装出问题时使用 helm reset && helm init 重置安装。

  1. 使用第三方的 Chart 存储库

    helm repo add 存储库名 存储库URL
    helm repo update
    

    关于 Helm 相关命令的说明,您可以参阅 Helm 文档

    鉴于国内使用镜像非常不方便Σ(っ °Д °;)っ,请添加国内的镜像进行使用kube-charts-mirror

    helm repo add stable https://burdenbear.github.io/kube-charts-mirror/
    
  2. 使用helm安装应用例子

    • 安装好pv或者storageclass

      apiVersion: v1
      kind: PersistentVolume
      metadata:
        name: helm-mysql
      spec:
        capacity:
          storage: 8Gi
        accessModes:
          - ReadWriteOnce
        persistentVolumeReclaimPolicy: Retain
        mountOptions:
          - hard
          - nfsvers=4
        nfs:
          path: /helm-mysql
          server: 172.10.1.100
      
      kubectl apply -f helm-mysql-pv.yml
      
    • 安装mysql

      helm install stable/mysql --name helm-mysql
      helm list
      

helm的使用

参考官方文档。https://docs.helm.sh/

自定义chart

创建一个Chart的骨架:

helm create testapi-chart

目录结构如下所示,我们主要关注目录中的这三个文件即可:Chart.yaml、values.yaml和NOTES.txt。

testapi-chart
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml
│   ├── _helpers.tpl
│   ├── NOTES.txt
│   └── service.yaml
└── values.yaml

打开Chart.yaml,填写应用的详细信息

打开并根据需要编辑values.yaml

对Chart进行校验

helm lint testapi-chart

对Chart进行打包:

helm package testapi-chart --debug

Successfully packaged chart and saved it to: /var/local/k8s/helm/alpine-0.1.0.tgz
[debug] Successfully saved /var/local/k8s/helm/alpine-0.1.0.tgz to /root/.helm/repository/local

安装本地repository中的chart

helm search local
helm install --name example local/mychart --set service.type=NodePort

使用Helm serve命令启动一个repo server,该server缺省使用’$HELM_HOME/repository/local’目录作为Chart存储,并在8879端口上提供服务。

helm serve --address 0.0.0.0:8879 &

启动本地repo server后,将其加入Helm的repo列表。

helm repo add local http://127.0.0.1:8879
"local" has been added to your repositories

现在再查找testapi chart包,就可以找到了。

chart 搜索

helm search

添加源

添加中国的源:

helm repo add stable https://burdenbear.github.io/kube-charts-mirror/

参考 https://github.com/BurdenBear/kube-charts-mirror

常用命令行

helm list
helm search
helm search mysql --versions
helm repo list
helm serve &

monocular 安装

因为没能把nginx-ingress安装成功,最后选择了Træfik-ingress

Træfik-ingress 安装

官网 https://docs.traefik.io/,以下按照 user-guide 进行安装,其实就是两个命令行:

# 创建角色和rbac绑定
$ kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/traefik-rbac.yaml

# ServiceAccount, DaemonSet(直接绑定主机端口),service
$ kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/traefik-ds.yaml

就可以看到效果了:

curl $(minikube ip)
404 page not found

traefik

参照GitHub的教程进行安装:

config

我创建了一个自己的配置文件,使用 kubernetes helm 国内镜像的配置 custom.yaml

$ cat > custom.yaml <<EOF
ingress:
  hosts:
  - monocular.local
  annotations:
    traefik.frontend.rule.type: PathPrefixStrip
    kubernetes.io/ingress.class: traefik 
api:
  config:
    repos:
      - name: monocular
        url: https://kubernetes-helm.github.io/monocular
        source: https://github.com/kubernetes-helm/monocular/tree/master/charts     
EOF

添加 repo

helm repo add monocular https://kubernetes-helm.github.io/monocular

# 2018年10月12日 更新,上面那个地址已经不能用了,我今天改成了下面这个:
helm repo add monocular https://helm.github.io/monocular

安装pv

apiVersion: v1
kind: PersistentVolume
metadata:
  name: monocular-mongodb
spec:
  capacity:
    storage: 8Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  mountOptions:
    - hard
    - nfsvers=4
  nfs:
    path: /monocular
    server: 172.10.1.100
    
$ kubectl apply -f monocular-pv.yml    

安装 monocular

helm install monocular/monocular --name monocular --set controller.hostNetwork=true -f custom.yaml

如果出现错误,重新来过的话,清空重置:

helm del --purge monocular
kubectl delete pv monocular-mongodb

获得 ingress 地址:

$ kubectl get ingress monocular-monocular

NAME                  HOSTS           ADDRESS   PORTS     AGE
monocular-monocular   monocular.local            80        9s

访问后自定义域名后界面如下:

参考资料


HTML meta标签 | segmentfault

原文:HTML meta标签总结与属性使用介绍

之前学习前端中,对meta标签的了解仅仅只是这一句。

<meta charset="UTF-8">

但是打开任意的网站,其head标签内都有一列的meta标签。比如我博客的。 Lxxyx博客的meta标签

但是自己却很不熟悉,于是把meta标签加入了寒假学习计划的最前方。

简介

在查阅w3school中,第一句话中的“元数据”就让我开始了Google之旅。然后很顺利的在英文版的w3school找到了想要的结果。(中文w3school说的是元信息,Google和百度都没有相关的词条。但元数据在Google就有详细解释。所以这儿采用英文版W3school的解释。)

The tag provides metadata about the HTML document. Metadata will not be displayed on the page, but will be machine parsable.

不难看出,其中的关键是metadata,中文名叫元数据,是用于描述数据的数据。它不会显示在页面上,但是机器却可以识别。这么一来meta标签的作用方式就很好理解了。

用处

Meta elements are typically used to specify page description, keywords, author of the document, last modified, and other metadata.

The metadata can be used by browsers (how to display content or reload page), search engines (keywords), or other web services

这句话对meta标签用处的介绍,简洁明了。 翻译过来就是:meta常用于定义页面的说明,关键字,最后修改日期,和其它的元数据。这些元数据将服务于浏览器(如何布局或重载页面),搜索引擎和其它网络服务。

组成

meta标签共有两个属性,分别是http-equiv属性和name属性。

1. name属性

name属性主要用于描述网页,比如网页的关键词,叙述等。与之对应的属性值为content,content中的内容是对name填入类型的具体描述,便于搜索引擎抓取。 meta标签中name属性语法格式是:

<meta name="参数" content="具体的描述">。

其中name属性共有以下几种参数。(A-C为常用属性)

A. keywords(关键字)

说明:用于告诉搜索引擎,你网页的关键字。 举例:

<meta name="keywords" content="Lxxyx,博客,文科生,前端">

B. description(网站内容的描述)

说明:用于告诉搜索引擎,你网站的主要内容。 举例:

<meta name="description" content="文科生,热爱前端与编程。目前大二,这是我的前端博客">

C. viewport(移动端的窗口)

说明:这个概念较为复杂,具体的会在下篇博文中讲述。 这个属性常用于设计移动端网页。在用bootstrap,AmazeUI等框架时候都有用过viewport。

举例(常用范例):

<meta name="viewport" content="width=device-width, initial-scale=1">

D. robots(定义搜索引擎爬虫的索引方式)

说明:robots用来告诉爬虫哪些页面需要索引,哪些页面不需要索引。 content的参数有all,none,index,noindex,follow,nofollow。默认是all。

举例:

<meta name="robots" content="none">

具体参数如下:

1.none : 搜索引擎将忽略此网页,等价于noindex,nofollow。 2.noindex : 搜索引擎不索引此网页。 3.nofollow: 搜索引擎不继续通过此网页的链接索引搜索其它的网页。 4.all : 搜索引擎将索引此网页与继续通过此网页的链接索引,等价于index,follow。 5.index : 搜索引擎索引此网页。 6.follow : 搜索引擎继续通过此网页的链接索引搜索其它的网页。

E. author(作者)

说明:用于标注网页作者 举例:

<meta name="author" content="Lxxyx,841380530@qq.com">

F. generator(网页制作软件)

说明:用于标明网页是什么软件做的 举例: (不知道能不能这样写):

<meta name="generator" content="Sublime Text3">

G. copyright(版权)

说明:用于标注版权信息 举例:

<meta name="copyright" content="Lxxyx"> //代表该网站为Lxxyx个人版权所有。

H. revisit-after(搜索引擎爬虫重访时间)

说明:如果页面不是经常更新,为了减轻搜索引擎爬虫对服务器带来的压力,可以设置一个爬虫的重访时间。如果重访时间过短,爬虫将按它们定义的默认时间来访问。 举例:

<meta name="revisit-after" content="7 days" >

I. renderer(双核浏览器渲染方式)

说明:renderer是为双核浏览器准备的,用于指定双核浏览器默认以何种方式渲染页面。比如说360浏览器。 举例:

<meta name="renderer" content="webkit"> //默认webkit内核
<meta name="renderer" content="ie-comp"> //默认IE兼容模式
<meta name="renderer" content="ie-stand"> //默认IE标准模式

2. http-equiv属性

介绍之前,先说个小插曲。看文档和博客关于http-equiv的介绍时,有这么一句。

http-equiv顾名思义,相当于http的文件头作用。

一开始看到这句话的时候,我是迷糊的。因为我看各类技术名词,都会习惯性的去记住它的英文全称。equiv的全称是”equivalent”,意思是相等,相当于。然后我脑子里出现了大大的迷惑:“HTTP相等?”

后来还准备去Segmentfault提问来着。结果在写问题的时候,突然反应出equivalent还有相当于的意思。意思就是相当于http的作用。至于文件头是哪儿出来的,估计是从其作用来分析的。我认为顾名思义并不能得出”相当于http的文件头作用”这个论断。

这个我所认为的http-equiv意思的简介。 相当于HTTP的作用,比如说定义些HTTP参数啥的。

meta标签中http-equiv属性语法格式是:

<meta http-equiv="参数" content="具体的描述">

其中http-equiv属性主要有以下几种参数:

A. content-Type(设定网页字符集)(推荐使用HTML5的方式)

说明:用于设定网页字符集,便于浏览器解析与渲染页面 举例:

<meta http-equiv="content-Type" content="text/html;charset=utf-8">  //旧的HTML,不推荐

<meta charset="utf-8"> //HTML5设定网页字符集的方式,推荐使用UTF-8

B. X-UA-Compatible(浏览器采取何种版本渲染当前页面)

说明:用于告知浏览器以何种版本来渲染页面。(一般都设置为最新模式,在各大框架中这个设置也很常见。) 举例:

<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/> //指定IE和Chrome使用最新版本渲染当前页面

C. cache-control(指定请求和响应遵循的缓存机制)

用法1.

说明:指导浏览器如何缓存某个响应以及缓存多长时间。这一段内容我在网上找了很久,但都没有找到满意的。 最后终于在Google Developers中发现了我想要的答案。

cache简介

举例:

<meta http-equiv="cache-control" content="no-cache">

共有以下几种用法:

  1. no-cache: 先发送请求,与服务器确认该资源是否被更改,如果未被更改,则使用缓存。
  2. no-store: 不允许缓存,每次都要去服务器上,下载完整的响应。(安全措施)
  3. public : 缓存所有响应,但并非必须。因为max-age也可以做到相同效果
  4. private : 只为单个用户缓存,因此不允许任何中继进行缓存。(比如说CDN就不允许缓存private的响应)
  5. maxage : 表示当前请求开始,该响应在多久内能被缓存和重用,而不去服务器重新请求。例如:max-age=60表示响应可以再缓存和重用 60 秒。

参考链接:HTTP缓存

用法2.(禁止百度自动转码)

说明:用于禁止当前页面在移动端浏览时,被百度自动转码。虽然百度的本意是好的,但是转码效果很多时候却不尽人意。所以可以在head中加入例子中的那句话,就可以避免百度自动转码了。 举例:

<meta http-equiv="Cache-Control" content="no-siteapp" />

D. expires(网页到期时间)

说明:用于设定网页的到期时间,过期后网页必须到服务器上重新传输。 举例:

<meta http-equiv="expires" content="Sunday 26 October 2016 01:00 GMT" />

E. refresh(自动刷新并指向某页面)

说明:网页将在设定的时间内,自动刷新并调向设定的网址。 举例:

<meta http-equiv="refresh" content="2;URL=http://www.lxxyx.win/"> //意思是2秒后跳转向我的博客

F. Set-Cookie(cookie设定)

说明:如果网页过期。那么这个网页存在本地的cookies也会被自动删除。

<meta http-equiv="Set-Cookie" content="name, date"> //格式

<meta http-equiv="Set-Cookie" content="User=Lxxyx; path=/; expires=Sunday, 10-Jan-16 10:00:00 GMT"> //具体范例

最后

暂时总结的就这么多了,meta标签的自定义属性实在太多了。所以只去找了常用的一些,还有像Window-target这样已经基本被废弃的属性,我也没有添加。 一开始以为一两个小时就能学习完毕,结果没想到竟然花了五六个小时,各处查资料,推敲文字。敲击文字的时候,也感觉自己学习了非常多。比如基本的SEO,HTTP协议的再次理解等。

参考资料


kubernetes 简介

kubernetes 网上的资料良莠不均,刚开始表示完全不知道从何入手。最近在入门中,将一些资料做了整理,精简了大部分得出了这一篇文章。可以参照文末参考资料查看原文。当前最新版的k8s版本为:1.10.

一 什么是Kubernetes?

Kubernetes(k8s)是 google 开源的一套自动化容器管理平台,前身是 Borg,用于容器的部署、自动化调度和集群管理。

为什么使用容器?

传统的应用部署方式是通过插件或脚本来安装应用。这样做的缺点是应用的运行、配置、管理、所有生存周期将与当前操作系统绑定,这样做并不利于应用的升级更新/回滚等操作,当然也可以通过创建虚机的方式来实现某些功能,但是虚拟机非常重,并不利于可移植性。

新的方式是通过部署容器方式实现,每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。相对于虚拟机,容器能快速部署,由于容器与底层设施、机器文件系统解耦的,所以它能在不同云、不同版本操作系统间进行迁移。

为什么使用容器

kubernetes能做什么?

Kubernetes能提供一个以“容器为中心的基础架构”,可以在物理或虚拟机的Kubernetes集群上运行容器化应用,满足在生产环境中运行应用的一些常见需求:负载均衡、服务发现、高可用、滚动升级、自动伸缩等。

kubernetes不能做什么?

  • Kubernetes不提供中间件(如message buses)、数据处理框架(如Spark)、数据库(如Mysql)或者集群存储系统(如Ceph)作为内置服务。但这些应用都可以运行在Kubernetes上面。
  • Kubernetes 不部署源码不编译应用。持续集成的 (CI)工作流方面,不同的用户有不同的需求和偏好的区域,因此,我们提供分层的 CI工作流,但并不定义它应该如何工作。
  • Kubernetes 允许用户选择自己的日志、监控和报警系统。
  • Kubernetes 不提供或授权一个全面的应用程序配置 语言/系统。
  • Kubernetes 不提供任何机器配置、维护、管理或者自修复系统。

Kubernetes是什么意思?

Kubernetes 实际上是一个希腊词κυβερνήτης, 意思是”船的舵手”。K8s是将中间8个字母“ubernete”替换为“8”的缩写。

二 Kubernetes 架构

一个K8s集群是由分布式存储(etcd)、服务节点(Node)和控制节点(Master)构成的。所有的集群状态都保存在etcd中,Master节点上则运行集群的管理控制模块。Node节点是真正运行应用容器的主机节点,在每个Minion节点上都会运行一个Kubelet代理,控制该节点上的容器、镜像和存储卷等。

Master 节点::

Master 是 Kubernetes Cluster 的大脑,运行着如下 Daemon 服务:

  • kube-apiserver

    Kubernetes Cluster 的前端接口,各种客户端工具(CLI 或 UI)以及 Kubernetes 其他组件可以通过它管理 Cluster 的各种资源。

  • kube-scheduler

    负责决定将 Pod 放在哪个 Node 上运行。Scheduler 在调度时会充分考虑 Cluster 的拓扑结构,当前各个节点的负载,以及应用对高可用、性能、数据亲和性的需求。

  • kube-controller-manager

    负责管理 Cluster 各种资源,保证资源处于预期的状态。

  • etcd

    负责保存 Kubernetes Cluster 的配置信息和各种资源的状态信息。当数据发生变化时,etcd 会快速地通知 Kubernetes 相关组件。

  • Pod 网络

    Pod 要能够相互通信,Kubernetes Cluster 必须部署 Pod 网络,flannel 是其中一个可选方案。

Node节点:

Node 是 Pod 运行的地方,Kubernetes 支持 Docker、rkt 等容器 Runtime。 Node上运行的 Kubernetes 组件有

  • kubelet

    kubelet 是 Node 的 agent,当 Scheduler 确定在某个 Node 上运行 Pod 后,会将 Pod 的具体配置信息(image、volume 等)发送给该节点的 kubelet,kubelet 根据这些信息创建和运行容器,并向 Master 报告运行状态。

  • kube-proxy

    service 在逻辑上代表了后端的多个 Pod,外界通过 service 访问 Pod。

    kube-proxy 就是负责将访问 service 的 TCP/UPD 数据流转发到后端的容器。如果有多个副本,kube-proxy 会实现负载均衡。

  • Pod 网络

K8s在实现上述架构时基于以下架构理念:

  • 只有API Server与存储通信,其他模块通过API Server访问集群状态。这样第一,是为了保证集群状态访问的安全。第二,是为了隔离集群状态访问的方式和后端存储实现的方式:API Server是状态访问的方式,不会因为后端存储技术etcd的改变而改变。加入以后将etcd更换成其他的存储方式,并不会影响依赖依赖API Server的其他K8s系统模块。
  • 一个工作节点被攻破不能导致整个K8s集群被攻破。这是所有分布式系统架构设计中都应该考虑的问题。
  • 考虑网络随时可能断开的情况,没有新配置声明时各模块按照之前的配置声明继续工作。在K8s集群中,所有的配置管理操作都声明式而非命令式的,因为声明式操作对于网络故障等分布式系统常见的故障情况更加稳定。
  • 各个模块在内存中缓存自己的相关状态以提高系统性能。
  • 需要监控某个系统状态来做下一步动作的时候,优先考虑观察通知模式,其次再考虑轮询模式,这也是为了提高系统的响应速度。

分层架构

Kubernetes设计理念和功能其实就是一个类似Linux的分层架构,如下图所示

img

  • 核心层:Kubernetes最核心的功能,对外提供API构建高层的应用,对内提供插件式应用执行环境
  • 应用层:部署(无状态应用、有状态应用、批处理任务、集群应用等)和路由(服务发现、DNS解析等)
  • 管理层:系统度量(如基础设施、容器和网络的度量),自动化(如自动扩展、动态Provision等)以及策略管理(RBAC、Quota、PSP、NetworkPolicy等)
  • 接口层:kubectl命令行工具、客户端SDK以及集群联邦
  • 生态系统:在接口层之上的庞大容器集群管理调度的生态系统,可以划分为两个范畴
    • Kubernetes外部:日志、监控、配置管理、CI、CD、Workflow、FaaS、OTS应用、ChatOps等
    • Kubernetes内部:CRI、CNI、CVI、镜像仓库、Cloud Provider、集群自身的配置和管理等

Kubernetes的核心技术概念

API对象是K8s集群中的管理操作单元。K8s集群系统每支持一项新功能,引入一项新技术,一定会新引入对应的API对象,支持对该功能的管理操作。

每个API对象都有3大类属性:

  • 元数据metadata,用来标识API对象,每个对象都至少有3个元数据:namespace,name和uid。

    除此以外还有各种各样的标签labels用来标识和匹配不同的对象,例如用户可以用标签env来标识区分不同的服务部署环境,分别用env=dev、env=testing、env=production来标识开发、测试、生产的不同服务。

  • 规范spec

    规范描述了用户期望K8s集群中的分布式系统达到的理想状态(Desired State),例如用户可以通过复制控制器Replication Controller设置期望的Pod副本数为3。

  • 状态status

    status描述了系统实际当前达到的状态(Status),例如系统当前实际的Pod副本数为2;那么复制控制器当前的程序逻辑就是自动启动新的Pod,争取达到副本数为3。

K8s中所有的配置都是通过API对象的spec去设置的,也就是用户通过配置系统的理想状态来改变系统,这是k8s重要设计理念之一,即所有的操作都是声明式(Declarative)的而不是命令式(Imperative)的。

声明式操作在分布式系统中的好处是稳定,不怕丢操作或运行多次,例如设置副本数为3的操作运行多次也还是一个结果,而给副本数加1的操作就不是声明式的,运行多次结果就错了。

概念

  1. Pod

    Pod是在K8s集群中运行部署应用或服务的最小单元,每个 Pod 包含一个或多个容器。Pod 中的容器会作为一个整体被 Master 调度到一个 Node 上运行。

  2. Controller

Kubernetes 通常不会直接创建 Pod,而是通过 Controller 来管理 Pod 的。Controller 中定义了 Pod 的部署特性,比如有几个副本,在什么样的 Node 上运行等。为了满足不同的业务场景,Kubernetes 提供了多种 Controller。

  • Deployment 管理 Pod 的多个副本,并确保 Pod 按照期望的状态运行。
  • ReplicaSet 实现了 Pod 的多副本管理。
  • DaemonSet 用于每个 Node 最多只运行一个 Pod 副本的场景。
  • StatefuleSet 保证 Pod 的每个副本在整个生命周期中名称是不变的。而其他 Controller 不提供这个功能,当某个 Pod 发生故障需要删除并重新启动时,Pod 的名称会发生变化。同时 StatefuleSet 会保证副本按照固定的顺序启动、更新或者删除。
  • Job :用于运行结束就删除的应用。而其他 Controller 中的 Pod 通常是长期持续运行。
  1. Service

    Deployment 可以部署多个副本,每个 Pod 都有自己的 IP,每次销毁重启时IP都会发生变化。

    而 Service 定义了外界访问一组特定 Pod 的方式。Service 有自己的 IP 和端口,Service 为 Pod 提供了负载均衡。

    Kubernetes 运行容器(Pod)与访问容器(Pod)这两项任务分别由 Controller 和 Service 执行。

  2. Namespace

    Namespace 为K8s集群提供虚拟的隔离作用。Namespace 可以将一个物理的 Cluster 逻辑上划分成多个虚拟 Cluster,每个 Cluster 就是一个 Namespace。不同 Namespace 里的资源是完全隔离的。

用 kubeadm 创建 Cluster

这里只做一些概念描述,具体步骤会再开一篇新文章描述。这部分摘自《部署 k8s Cluster(上)- 每天5分钟玩转 Docker 容器技术(118)》有删减。

  • kubelet 运行在 Cluster 所有节点上,负责启动 Pod 和容器。

  • kubeadm 用于初始化 Cluster。

  • kubectl 是 Kubernetes 命令行工具。

    通过 kubectl 可以部署和管理应用,查看各种资源,创建、删除和更新各种组件。

  1. 初始化master

    kubeadm init --apiserver-advertise-address 192.168.56.105 --pod-network-cidr=10.244.0.0/16
    
    --apiserver-advertise-address 指明用 Master 的哪个 interface 与 Cluster 的其他节点通信。如果 Master 有多个 interface,建议明确指定,如果不指定,kubeadm 会自动选择有默认网关的 interface。
    
    --pod-network-cidr 指定 Pod 网络的范围。Kubernetes 支持多种网络方案,而且不同网络方案对 --pod-network-cidr 有自己的要求,这里设置为 10.244.0.0/16 是因为我们将使用 flannel 网络方案,必须设置成这个 CIDR。在后面的实践中我们会切换到其他网络方案,比如 Canal。
    

    初始化做的事情有:

    ① kubeadm 执行初始化前的检查。

    ② 生成 token 和证书。

    ③ 生成 KubeConfig 文件,kubelet 需要这个文件与 Master 通信。

    ④ 安装 Master 组件,会从 goolge 的 Registry 下载组件的 Docker 镜像,这一步可能会花一些时间,主要取决于网络质量。

    ⑤ 安装附加组件 kube-proxy 和 kube-dns。

    ⑥ Kubernetes Master 初始化成功。

    ⑦ 提示如何配置 kubectl。

    ⑧ 提示如何安装 Pod 网络。

    ⑨ 提示如何注册其他节点到 Cluster。

  2. 配置 kubectl

  3. 安装 Pod 网络

    要让 Kubernetes Cluster 能够工作,必须安装 Pod 网络,否则 Pod 之间无法通信。

    Kubernetes 支持多种网络方案,例如 flannel 和 Canal。

  4. 注册其他节点到 Cluster

几乎所有的 Kubernetes 组件本身也运行在 Pod 里,kubelet 是唯一没有以容器形式运行的 Kubernetes 组件,它在 Ubuntu 中通过 Systemd 运行。

附录:

云计算与弹性伸缩

从云计算的定义出发,云计算系统一个基本特性就是计算能力的弹性和伸缩性。弹性和伸缩性的意思是能够根据实际的需要,随时增多或减少计算能力。弹性伸缩针对不同的处理对象,有不同的伸缩模式,如下图,分别处于X、Y、Z轴3个不同维度。

  1. 对于同一类事物的无状态服务,数据不需要持久化,处理结果不需要保存在信息系统中,可以通过X轴计算实例的水平复制进行伸缩,这就是Kubernetes系统中Replication Controller和ReplicaSet所完成的功能;举例说明,一个电子商务系统的下订单服务,本身只是做订单处理但不存储数据的无状态服务,这个微服务就可以用水平复制的模式来伸缩。

  2. 对于同一类事物的有状态服务,数据存储的内容各不相同,身份也各不相同,可以通过Z轴存储实例的数据分片进行伸缩,这就是Kuberenetes的PetSet或者StatefulSet所完成的功能;举例说明,下订单服务的订单数据存储在MySQL数据库中,要想增加订单数据存储的能力,就需要对针对订单数据库表进行数据分片。

    tips: 何为数据分片(segment,fragment, shard, partition),就是按照一定的规则,将数据集划分成相互独立、正交的数据子集,然后将数据子集分布到不同的节点上。注意,数据分片需要按照一定的规则,不同的分布式应用有不同的规则,但都遵循同样的原则:按照最主要、最频繁使用的访问方式来分片。)

  3. 对于不同类别事物的处理,则需要通过Y轴的功能分割来进行伸缩,Y轴的分割也称为垂直分割;举例说明,一个完整的电子商务系统,可以根据业务功能分割成用户管理、购物车管理、订单管理、产品目录管理、库存管理、支付管理、配送管理等多个独立的微服务。需要说明的是,功能分割(Y轴)是水平复制(X轴)和数据分片(Z轴)的前提,只有通过功能分割解耦将不同的事物分割出来,才能针对同一事物进行水平复制或数据分片。

4bd0da72f12b4c47834228a74a169ca219208981

容器与微服务架构

微服务架构的理念,是将一个完整的应用,按照业务拆分成彼此独立的模块以支撑服务的独立开发、部署和伸缩。

微服务分割也就是业务功能分割。微服务分割和传统软件模块分割的一大区别是,

微服务分割强调领域数据模型的分割,也就是数据存储服务的分割,以保证不同微服务之间没有持久化数据方面的依赖性,从而使得不同的微服务真正可以在运行时独立进行部署和伸缩。

传统的软件模块分割,比较多的是考虑代码的重用性和各模块开发的独立性,但因为并没有为超高用户压力的弹性要求做准备,比较少考虑数据持久化层面的伸缩性。

而如前所述,Y轴业务功能分割是Z轴数据分片的前提,因此要想真正应对超高用户压力的弹性计算要求,进行业务功能分割是第一步。

参考资料