在CentOS7上部署Memcached主主复制+Keepalived高可用架构

原理:

Memcached主主复制是指在任意一台Memcached服务器修改数据都会被同步到另外一台,但是Memcached API客户端是无法判断连接到哪一台Memcached服务器的,所以需要设置VIP地址,提供给Memcached API客户端进行连接。可以使用Keepalived产生的VIP地址连接主Memcached服务器,并且提供高可用架构。

使用两台Memcached服务器,一台客户机来完成,实验环境表如下:

未分类

1.配置memcached主缓存节点和从缓存节点—–两台配置相同

 [root@localhost ~]# tar zxvf libevent-2.1.8-stable.tar.gz -C /opt/   //解包//
 [root@localhost ~]# tar zxvf memcached-1.5.6.tar.gz -C /opt/
 [root@localhost ~]# mkdir /opt/magent
 [root@localhost ~]# tar zxvf magent-0.5.tar.gz -C /opt/magent/ 
 [root@localhost opt]#cd libevent-2.1.8-stable/
 [root@localhost libevent-2.1.8-stable]# yum install gcc gcc-c++ make -y
 [root@localhost libevent-2.1.8-stable]# ./configure --prefix=/usr
 [root@localhost libevent-2.1.8-stable]# make && make install
 [root@localhost libevent-2.1.8-stable]# cd ../memcached-1.5.6/
 [root@localhost memcached-1.5.6]# ./configure --with-libevent=/usr

 [root@localhost memcached-1.5.6]# ln -s /usr/lib/libevent-2.1.so.6 /usr/lib64/libevent-2.1.so.6    //软链接//

2.关闭防火墙并开启memcached服务

[root@localhost memcached-1.5.6]# systemctl stop firewalld.service 
[root@localhost memcached-1.5.6]# setenforce 0
[root@localhost memcached-1.5.6]# memcached -d -m 32m -p 11211 -u root
[root@localhost memcached-1.5.6]# netstat -ntap | grep 11211
tcp        0      0 0.0.0.0:11211           0.0.0.0:*               LISTEN      11224/memcached     
tcp6       0      0 :::11211                :::*                    LISTEN      11224/memcached

3.在主服务器上安装magent

[root@localhost memcached-1.5.6]# cd /opt/magent/
[root@localhost magent]# ls
ketama.c  ketama.h  magent.c  Makefile
[root@localhost magent]# vim ketama.h

#ifndef SSIZE_MAX
#define SSIZE_MAX 32767
#endif
[root@localhost magent]# vim Makefile 
LIBS = -levent -lm //第一行末尾加-lm (不是数字1
LIBS = -levent -lm
CFLAGS = -Wall -O2 -g

[root@localhost magent]# make
gcc -Wall -O2 -g  -c -o magent.o magent.c
gcc -Wall -O2 -g  -c -o ketama.o ketama.c
gcc -Wall -O2 -g -o magent magent.o ketama.o -levent -lm

4.把生成的mgent程序让系统识别

ls一下可看到magent可执行程序
[root@localhost magent]# ls
ketama.c  ketama.h  ketama.o  magent  magent.c  magent.o  Makefile
[root@localhost magent]# cp magent /usr/bin/

5.把产生的magent文件直接复制到从服务器。

[root@localhost bin]# yum install openssh-clients -y
[root@localhost bin]# scp magent [email protected]:/usr/bin/ 

6.安装keepalived,修改默认配置文件。

[root@localhost bin]# yum install keepalived -y
[root@localhost bin]# vim /etc/keepalived/keepalived.conf 
! Configuration File for keepalived
vrrp_script magent {
        script "/opt/shell/magent.sh"
        interval 2
}

global_defs {
   notification_email {
     [email protected]
     [email protected]
     [email protected]
   }
   notification_email_from [email protected]
   smtp_server 192.168.200.1
   smtp_connect_timeout 30
   router_id MAGENT_HA    //主服务器名称//
}

vrrp_instance VI_1 {
    state MASTER
    interface ens33     //网卡名称//
    virtual_router_id 51
    priority 100    //优先级//
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111   
    }
    virtual_ipaddress {
        192.168.126.188     //虚拟IP//
    }
track_script {
        magent     //函数//
}
}

7.从服务器上安装keepalived,配置文件进行修改。

[root@localhost bin]# vim /etc/keepalived/keepalived.conf 
! Configuration File for keepalived
vi keepalived.conf
vrrp_script magent {
        script "/opt/shell/magent.sh"
        interval 2
}

global_defs {
   notification_email {
     [email protected]
     [email protected]
     [email protected]
   }
   notification_email_from [email protected]
   smtp_server 192.168.200.1
   smtp_connect_timeout 30
   router_id MAGENT_HB      //从服务器的名称//
}

vrrp_instance VI_1 {
    state BACKUP            //从服务器的热备状态要修改成BACKUP//
    interface ens33  //网卡名称//
    virtual_router_id 52    //不能与主服务器相同//
    priority 90       //从调度器的优先级要小于主的//
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.126.188     //虚拟IP//
    }
track_script {        //函数//
        magent  
}
}

8.在主服务器上设置magent管理脚本

[root@localhost bin]# mkdir /opt/shell
[root@localhost bin]# vim /opt/shell/magent.sh

#!/bin/bash
K=`ps -ef | grep keepalived | grep -v grep | wc -l`
if [ $K -gt 0 ]; then
        magent -u root -n 51200 -l 192.168.126.188 -p 12000 -s 192.168.126.138:11211 -b 192.168.126.166:11211
else
pkill -9 magent
fi

参数注解:
-n 51200 //定义用户最大连接数
-l 192.168.126.188 //指定虚拟IP
-p 12000  //指定端口号
-s //指定主缓存服务器
-b //指定从缓存服务器

[root@localhost shell]# chmod +x magent.sh   // 增加执行权限//

9.在从服务器上操作

[root@localhost bin]# mkdir /opt/shell
[root@localhost bin]# cd /opt/shell/
[root@localhost shell]# vim magent.sh
[root@localhost shell]# vim magent.sh
脚本内容如下,与主服务器脚本有区别!
#!/bin/bash
K=`ip addr | grep 192.168.126.188 | grep -v grep | wc -l`
if [ $K -gt 0 ]; then
        magent -u root -n 51200 -l 192.168.126.188 -p 12000 -s 192.168.126.138:11211 -b 192.168.126.166:11211
else
pkill -9 magent
fi  
[root@localhost shell]# chmod +x magent.sh 

10.开始验证

1)启动主服务器

[root@localhost shell]# systemctl start keepalived.service 
[root@localhost shell]# netstat -ntap | grep 12000  //确认magent运行//
tcp        0      0 192.168.126.188:12000   0.0.0.0:*               LISTEN      12422/magent 

2)启动从服务器

[root@localhost shell]# systemctl start keepalived.service 
[root@localhost shell]# netstat -ntap | grep 12000
tcp        0      0 192.168.126.188:12000   0.0.0.0:*               LISTEN      11716/magent  

3)在主服务器上使用telnet进行简单验证复制功能

[root@localhost shell]# telnet 192.168.126.188 12000  //用漂移地址登陆服务//
Trying 192.168.126.188...
Connected to 192.168.126.188.
Escape character is '^]'.
add username 0 0 7      //添加一条键值数据//
1234567
STORED

在从服务器上查看
[root@localhost shell]# telnet 192.168.126.188 12000 
Trying 192.168.126.188...
Connected to 192.168.126.188.
Escape character is '^]'.
get username    //查看键值数据
VALUE username 0 7
1234567         //内容存在,写入成功//
END

11.在客户端用漂移地址登陆服务

[root@localhost ~]# yum install telnet -y
[root@localhost ~]# telnet 192.168.126.188 12000 
Trying 192.168.126.188...
Connected to 192.168.126.188.
Escape character is '^]'.
add username 0 0 8    //添加一条键值数据//
12345678
STORED

1)在主服务器和从服务器上查看是否写入成功。

主服务器
get username
VALUE username 0 8
12345678
END

从服务器
get username
VALUE username 0 8
12345678
END

2)把主服务器停了业务不影响

[root@localhost shell]# systemctl stop keepalived.service
[root@localhost shell]# ip addr
inet 192.168.126.138/24 brd 192.168.126.255 scope global dynamic ens33

3)在从服务器上查看

[root@localhost shell]# ip addr
inet 192.168.126.166/24 brd 192.168.126.255 scope global dynamic ens33
       valid_lft 1146sec preferred_lft 1146sec
    inet 192.168.126.188/32 scope global ens33
可以看到漂移地址已经转移到从服务器上了,说明从已接受工作。

4)再把主服务器开启

[root@localhost shell]# systemctl start keepalived.service 
[root@localhost shell]# ip addr
inet 192.168.126.138/24 brd 192.168.126.255 scope global dynamic ens33
       valid_lft 1145sec preferred_lft 1145sec
    inet 192.168.126.188/32 scope global ens33
       valid_lft forever preferred_lft forever
漂移地址再次转移到主服务器上,接手地址,服务依然不受影响。

实验成功

MariaDB修改最大连接数

1.mariadb数据库最大连接数,默认为151

MariaDB [(none)]> show variables like 'max_connections';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections |  151  |
+-----------------+-------+

2.配置/etc/my.cnf

[mysqld]下新添加一行如下参数:

max_connections=3000

systemctl restart mariadb 重启mariadb服务,再次查看mariadb数据库最大连接数,最大连接数是214,并非我们设置的3000。

MariaDB [(none)]> show variables like 'max_connections';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections |  214  |
+-----------------+-------+

由于mariadb有默认打开文件数限制

vi /usr/lib/systemd/system/mariadb.service

取消[Service]前的#号,
[Service]新添加两行如下参数:

LimitNOFILE=10000
LimitNPROC=10000

4.重新加载系统服务,并重启mariadb服务

systemctl --system daemon-reload
systemctl restart mariadb.service

再次查看mariadb数据库最大连接数,可以看到最大连接数已经是3000

MariaDB [(none)]> show variables like 'max_connections';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 3000  |

+-----------------+-------+

从数据库延迟同步主数据库;

Mysql (需5.6以上版本)延迟复制配置,通过设置Slave上的MASTER TO MASTER_DELAY参数实现:

CHANGE MASTER TO MASTER_DELAY = N; 

N为多少秒,该语句设置从数据库延时N秒后,再与主数据库进行数据同步复制

具体操作:

登陆到Slave数据库服务器

mysql>stop slave; 
mysql>CHANGE MASTER TO MASTER_DELAY = 600; 
mysql>start slave; 
mysql>show slave status G; 

查看SQL_Delay的值为600,表示设置成功。

注释:
SQL_Delay:一个非负整数,表示秒数,Slave滞后多少秒于master。
SQL_Remaining_Delay:当 Slave_SQL_Running_State 等待,直到MASTER_DELAY秒后,Master执行的事件,

此字段包含一个整数,表示有多少秒左右的延迟。在其他时候,这个字段是0。

【最新发布的MariaDB10.2.3支持延迟复制】

MariaDB修改编码格式

1、通过set修改value字段

2、登录MySQL,使用 show variables like ‘character%’;

3、查看当前编码格式

未分类

4、使用 set character_set_client = ‘utf8mb4’;

5、直接修改variable_name的value

未分类

Mariadb通过配置文件修改编码

1、登录MySQL,使用

SHOW VARIABLES LIKE 'character%';

查看当前使用的字符集,应该有好几个不是UTF-8格式。

2、要修改的配置文件位于 /etc/my.cnf.d目录下:

client.cnf

在[client]字段里加入

default-character-set=utf8

server.cnf

在[mysqld]字段里加入

character-set-server=utf8

systemctl restart mariadb 配置生效,修改后的效果如下:

未分类

3、修改字段编码格式:

4、use 库名

ALTER TABLE  表名 MODIFY `字段` TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '备注';

CentOS LVM卷转变成普通卷操作步骤

CentOS LVM卷转变成普通卷操作步骤

1.系统信息

lsb_release -a
LSB Version:    :core-4.1-amd64:core-4.1-noarch
Distributor ID: CentOS
Description:    CentOS Linux release 7.2.1511 (Core)
Release:    7.2.1511
Codename:   Core

2.背景

公司线上服务器要上线大数据平台,使用LVM卷对生产上业务有
一定的影响。新机器的部署我都是使用的自动化部署脚本进行的,
脚本中对数据盘使用的LVM格式,因此,我需要手动更改
磁盘卷的类型。

3.具体实施步骤

#操作前请做好数据的备份
#卸载逻辑卷之前的文件系统
df -h
文件系统                    容量  已用  可用 已用% 挂载点
/dev/mapper/vgdata-lvdata1  197G   61M  187G    1% /data
#umount文件系统
umount /data
#lvremove操作
lvremove /dev/vgdata/lvdata1
Do you really want to remove active logical volume vgdata/lvdata1? [y/n]: y
Logical volume "lvdata1" successfully removed
#vgremove操作
vgremove vgdata
Volume group "vgdata" successfully removed
#pvremove操作
pvremove /dev/vdb1
Labels on physical volume "/dev/vdb1" successfully wiped.
#fdisk磁盘分区
##查看下当前lvm的分区
fdisk -l
设备 Boot      Start         End      Blocks   Id  System
/dev/vdb1            2048   419430399   209714176   8e  Linux LVM
#重新进行磁盘分区
fdisk /dev/vdb
d --> p --> n --> 三次enter默认 --> p --> w
#对刚分好分区的磁盘格式化
mkfs.ext4 /dev/vdb1
#查看UUID
blkid
/dev/vdb1: UUID="456b88bf-19fe-4b80-b408-13451d10e78w" TYPE="ext4"
#更改/etc/fstab文件
sed -i 's#/dev/vgdata/lvdata1   /data    ext4    defaults        1 1 #UUID="456b88bf-19fe-4b80-b408-13451d10e78w"  /data                ext4    defaults        1 1#g'
#挂载分区
mount -a

kubernetes 与LVM的结合

本文主要介绍k8s与LVM结合使用的场景,在原生的k8s中对于本地存储提供了hostPath与emptyDir两种volme,hostPath是直接将文件存储在本地主机上,存在的问题是无法进行quota管理,单个用户就可能将所有的磁盘打满;在kubernetes 1.10 local ephemeral storage 成为beta版本,可以对emptyDir进行磁盘限制,但是这里的磁盘配额不仅包括用户写入epmtyDir的数据,也包括writable layer和logs,并且emptyDir会随着pod的删除而删除,无法自定义生命周期,如果应用程序需要在pod退出后保留这些数据,emptyDir就无法胜任了。鉴于k8s原生volume的以上特点无法满足复杂的业务需求,我们可以根据LVM提供一种本地存储的volume方案。本文只介绍LVM与k8s结合实现方式,具体LVM及k8s的知识请自行查阅相关资料。

Out-of-Tree Volume Plugins

k8s对于额外的存储提供良好的支持,参见 Out-of-Tree Volume Plugins, 有两种方式实现volume plugin: CSI和FlexVolume,第一种是现在官方推荐的方式,不过第二种官方还继续提供支持而且使用起来更加简单,官方提供了FelxVolme LVM shell版的简单实现,参见github地址,其实就是一个binary或脚本来提供特定的调用,对于LVM来说需要实现基本的mount和umount subcommand供kubelet回调。mount subcommand创建LVM,分为以下几个步骤:

  1. 调用lvcreate创建LVM设备,大小为用户在yaml文件中指定的磁盘大小,会在kubelet调用plugin的时候作为参数传递进来

  2. 调用mkfs格式化LVM为某种文件类型

  3. 创建挂载点目录,该参数一般都由plugin作为参数传递进来,一般就是$KUBELET_ROOT_DIR/pods/$POD_UID/volumes/…目录下

  4. mount LVM设备到挂载点上

  5. 汇报LVM VG的使用情况,因为后面调度pod的时候需要使用这些信息

上述是kubelet在回调plugin mount subcommand的操作,对于umount subcommand因为需要自定义删除策略,我们不能直接将LVM 删除掉,但挂载点目录必须删除掉,否则kubelet会认为该volume没有被正确移除,pod一直处于terminating无法删除,此时有种tricky的方式就是move挂载点目录,这样LVM正常mount到挂载点上,pods也可以正常被删除,至于后续的自定义删除策略就直接操作move之后的挂载点设备了。需要注意的是应用程序如果要查看退出pod的LVM中的数据必须去移动之后的挂载点目录查看。

LVM GC policy

前面了解了如何在k8s中提供LVM支持,umount的时候不删除LVM来为自定义删除策略提供支持,自定义删除策略就需要写一个旁路清理程序,可以是daemon或cron的形式运行,可以基于磁盘容量或pod退出时间进行GC。比较好的方式是不直接清理LVM, 先lvreduce对LVM进行缩容,将未使用的空间还给VG, 这样即提高磁盘使用率,又保留了用户数据,等到合适的时候再删除。注意此处缩容指的是LVM和文件系统两方面,且不能损坏用户的数据为前提。每次GC之后都需要及时上报VG信息,为后面调度提供信息。

schedule pod based on LVM

上面的实现为集群中的每个node提供了一种额外的资源(LVM)的支持, 既然是node级别的资源,就要考虑在调度pod的时候如何选择合适的node assign,需要自定义调度策略,上文中所有对LVM的操作中都提到了要及时上报VG信息,就是为了调度的时候使用这些信息。官方对于node resource提供了调度的支持,参见https://kubernetes.io/docs/tasks/administer-cluster/extended-resource-node/ ,但是这种方式只适合随着pod生命周期结束而结束的资源,例如emptyDir,memroy,cpu等。还有一种扩展是device plugin,可以考虑将LVM作为一种磁盘device使用,这种方式也不适合,因为对于device设备的申请是有粒度的,例如可以说申请一个磁盘设备,但不能说申请1G的空间。

不能通过上述两种声明node resource的方式利用内置的调度策略,我们只能自己实现调度策略了,k8s对于调度的扩展也有很好的支持,可以定义一个scheduler extender提供一个http webhook。要实现一个scheudler extender, 首先要了解kube-scheduler的调度过程,分为三步,首先是做筛选(predict)或称为filter,过滤掉不能调度到其上的node。其次是排序(priorities),为可以调度的node进行打分,决定最适合调度的node;最后是绑定(bind),绑定操作将该pod“分配”给某台node。scheduler-extender相当于上述步骤的“补充协议”, 可选的为上述步骤补充自己的调度逻辑, 当创建一个pod需要调度的时候,首先会执行内置的调度策略,然后将内置调度器的结果传递过来给你的extender server,调度逻辑完成之后将结果返回给kube-scheduler进行下一个过程。

除了kube-scheduler的调度步骤外,kube-scheduler为了提高调度性能有一个“资源占用”的概念: kube-scheduler会在本地有一个cache存放所有的node信息,该cache会与api-server进行同步,调度pod的信息直接从cache中取,当pod调度到某个node上后,会将cache中该node的资源进行“预先占用”,假定资源已经被pod消耗了,其实pod只是调度到了该node上面,还未真正启动起来,未真正占用资源,通过假定调度上去的pod已经占用了该资源,为后面调度的pod提供变化的信息,如果在指定的timeout内,pod还未启动则将预先占用的资源返回给该node,通过这种异步的最终一致性的方案能够有效提高pod的调度效率。此外在高可用的方案中需要配置多个kube-scheduler,因为每个kube-scheduler的cache并不同步,无法多个kube-scheduler同时对外提供服务,此时只能通过选主协议选择其中的一个进行处理请求。

明白了kube-scheduler的实现之后,来仿照kube-scheduler实现我们的scheduler extender, extender的httpserver位置通过kube-scheduler的–policy-config-file或–policy-configmap来配置,前者指定一个config file,后者通过一个configmap来配置,笔者建议用configmap来管理,因为更新配置只需要改变一个地方对于多个kube-scheduler同时生效。并且可以单独定义上述三步骤中的其中某一步。

apiVersion: v1
kind: ConfigMap
metadata:
  name: lvm-scheduler-extender
  namespace: kube-system
data:
 policy.cfg : |
  {
  "kind" : "Policy",
  "apiVersion" : "v1",
  "extenders" : [
    {
          "urlPrefix": "http://localhost:8384/lvm-scheduler",
          "apiVersion": "v1alpha1",
          "filterVerb": "predicates/lvm_resource",
          "bindVerb": "bind",
          "prioritizeVerb": "",
          "weight": 1,
          "enableHttps": false,
          "nodeCacheCapable": false
    }
      ],
  "hardPodAffinitySymmetricWeight" : 10
  }

上面的配置configmap指定了extender webhook的位置,并且定义了filter和bind这两个操作,之所以定义这两个操作是因为我们只关心哪些node可以调度上去,将LVM剩余空间不足以创建pod的node过滤掉,以及最后到底调度到了那台node上以便在scheduler extender的cache中将该node的资源进行占用。需要注意的是系统中只能有一个执行bind操作的binder, 如果extender中指定了binder,kube-scheduler内置的就不会生效了,需要通过k8s client-go来绑定:

clientset.CoreV1().Pods(podNamespace).Bind(&v1.Binding{
        ObjectMeta: metav1.ObjectMeta{Namespace: podNamespace, Name: podName, UID: podUID},
        Target: v1.ObjectReference{
            Kind: "Node",
            Name: nodeName,
        }})

前面在介绍plugin和GC的时候每次操作LVM都需要及时将LVM信息上报来提供extender进行调度决策,那么该向哪里汇报这些VG信息?如何汇报? 这个问题根据不同的场景下有不同的解决方案,首先肯定不能直接向extender上报,因为高可用集群中往往不只有一个exteder示例,所以需要提供一个分离的统一后端存储,所有的extender直接从后端存储里取,可以存储在Mysql或redis中,比较tricky的方式是直接存储在k8s的etcd中,这些数据量比较小不会占用太多空间,也免了额外的操作数据库,但是直接操作etcd有点不妥,可以定义一种CRD资源,为每台node创建一个crd资源实体表示该node可用LVM空间的大小,这样就可以像其他资源一样方便查询,在LVM资源发生变化之后对该crd对象进行patch。在extender中watch该crd资源即可。此外需要提供一个cache进行资源的预先占用,同时提供选主协议的实现,以上都可以参考kube-scheduler中的实现。

summary

麻雀虽小,五脏俱全上述通过实现LVM这种node resource的支持,分别涉及到了storage plugin,scheduelr extender,CRD等,虽然内容较多但是实际编码并不多,感谢kubernetes提供了一种灵活的扩展,感兴趣的可以自己去实现一下。

centos7上测试部署kvm虚拟机

华为的云计算已经摒弃xen架构了,使用kvm。目前kvm已经是一种主流虚拟化架构,所以学习kvm是很有必要的。

一、部署环境

使用vmware workstation部署centos7虚拟机,采用最小化安装,硬盘50G,内存2G,开启cpu虚拟化。网络模式采用桥接,ip地址192.168.3.1,kvm
对虚拟机进行初始化操作,包括关闭selinux 等

sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/sysconfig/selinux
systemctl disable firewalld
systemctl stop firewalld

二、安装kvm

验证cpu是否支持kvm,如果结果中有vmx(Intel)或svm(AMD)字样,就说明CPU的支持的

egrep '(vmx|svm)' /proc/cpuinfo

未分类

2.最小化安装依赖包

yum install epel-release net-tools vim unzip zip wget ftp -y

3.安装kvm及依赖项

yum install qemu-kvm libvirt virt-install bridge-utils -y

4.验证安装结果

lsmod | grep kvm

未分类

5.开启kvm服务

systemctl start libvirtd

systemctl enable libvirtd

6.确认服务运行

systemctl status libvirtd

未分类

7.配置网桥模式
先将 /etc/sysconfig/network-scripts/ 目录下的网卡配置文件备份一份(不要备在当前目录以及子目录下,其他目录随意)

cp ifcfg-ens33 /root/   #这里物理网卡配置名称为ens33,复制到/root/

创建 ifcfg-br0 文件,内容如下

cat >>ifcfg-br0 <<EOF
BOOTPROTO=static
DEVICE=br0
TYPE=Bridge
NM_CONTROLLED=no
IPADDR=192.168.3.50
NETMASK=255.255.255.0
GATEWAY=192.168.3.1
DNS1=202.103.24.68
DNS2=202.103.44.150
EOF

未分类

移除掉原来的 ifcfg-ens33 ,重新创建该文件,内容如下:

BOOTPROTO=none
DEVICE=ens33
NM_CONTROLLED=no
ONBOOT=yes
BRIDGE=br0

未分类

重启网络服务

systemctl restart network

使用ifconfig查看,此时多了块网卡br0

未分类

注意virbr0是kvm内部作为nat使用的,没有配置则自动分配192.168.122.1地址,暂时不用管

三、安装虚拟机

准备操作系统,kvm可以很好的支持linux虚拟机,windows虚拟机需要另外装驱动。创建/home/iso目录,使用xftp上传镜像centos7镜像

未分类

未分类

上传完毕后如下图所示

未分类

2.创建虚拟机存放文件目录

mkdir -p /home/kvm

3.使用virt-install创建虚拟机

virt-install --name centos7_kvm --memory 512 --vcpus=1 --disk /home/kvm/centos7_kvm.img,format=qcow2,size=20 --network bridge=br0 --os-type=linux --os-variant=rhel7.3 --cdrom /home/iso/CentOS-7-x86_64-Minimal-1611.iso --noautoconsole --vnc --vncport=5910 --vnclisten=0.0.0.0

未分类

注意,这里参数最好加上–noautoconsole,不然本tty就会一直被占用,会误以为失败死机
检查虚拟机状态,确认运行

virsh list

未分类

virsh工具的相关选项说明
--name 虚拟机名称
--memory 内存大小
--vcpus= vcpu
--disk 创建硬盘 制定硬盘路径,格式,大小
--network 指定网络
--os-type 指定操作系统类型
--os-variant= 指定操作系统版本
--cdrom 指定光驱安装操作系统
--noautoconsosle 虚拟机创建完毕后不会自动切换tty
--vnc 使用vnc
--vncport vnc端口

4.使用vnc登录虚拟机安装操作系统

未分类

安装操作系统

未分类

因为连接br0,虚拟机可以使用dhcp获取ip地址

未分类

kvm中虚拟机创建成功,可以直接使用ssh连接kvm虚拟机进行配置

解决ubuntu安装kubernetes时的网络问题

在kubernetes安装过程中,由于众所周知的原因,导致很多安装包等无法下载。本文记录了解决此问题的步骤。

1、安装shadowsocks

apt install shadowsocks -y

2、将shadowsocks配置写入配置文件

root@ubuntu:~# cat /etc/shadowsocks.json 
{
"server":"********",
"server_port":8086,
"local_address": "127.0.0.1",
"local_port":1080,
"password":"******",
"timeout":300,
"method":"aes-256-cfb",
"fast_open": false,
"workers": 1
}

3、安装privoxy,并编辑其配置文件

root@ubuntu:~# apt-get install privoxy

在/etc/privoxy/config文件末尾加上如下内容:

listen-address 127.0.0.1:9909
forward-socks5 / 127.0.0.1:1080 .

注意最后一行的点.

4、在一个session中启动shadowsocks,启动命令为

sslocal -c /etc/shadowsocks.json

在另一个session中,启动privoxy

systemctl start privoxy

5、这时候,如果哪个session需要下载kubernetes软件等,在当前session执行如下命令,加入环境变量

root@host1:~# export https_proxy="http://127.0.0.1:9909"
root@host1:~# export http_proxy="http://127.0.0.1:9909"

kubernetes pod的弹性伸缩

概念

HPA是kubernetes里面pod弹性伸缩的实现,它能根据设置的监控阀值进行pod的弹性扩缩容,目前默认HPA只能支持cpu和内存的阀值检测扩缩容,但也可以通过custom metric api 调用prometheus实现自定义metric 来更加灵活的监控指标实现弹性伸缩。但hpa不能用于伸缩一些无法进行缩放的控制器如DaemonSet。这里我们用的是resource metric api.

未分类

实现hpa的两大关键

1、监控指标的获取
早期kubernetes版本是使用hepster,在1.10后面版本更推荐使用metric-server

hepster简单来说是api-server获取节点信息,然后通过kubelet获取监控信息,因为kubelet内置了cadvisor。

metric-server,简单来说是通过metric-api来获取节点信息和监控信息。https://github.com/kubernetes-incubator/metrics-server

2、伸缩判定算法
HPA通过定期(定期轮询的时间通过–horizontal-pod-autoscaler-sync-period选项来设置,默认的时间为30秒)查询pod的状态,获得pod的监控数据。然后,通过现有pod的使用率的平均值跟目标使用率进行比较。
pod的使用率的平均值:
监控资源1分钟使用的平均值/设定的每个Pod的request资源值

扩容的pod数计算公式

TargetNumOfPods = ceil(sum(CurrentPodsCPUUtilization) / Target)

celi函数作用:
返回大于或者等于指定表达式的最小整数

在每次扩容和缩容时都有一个窗口时间,在执行伸缩操作后,在这个窗口时间内,不会在进行伸缩操作,可以理解为类似等一下放技能的冷却时间。默认扩容为3分钟(–horizontal-pod-autoscaler-upscale-delay),缩容为5分钟(–horizontal-pod-autoscaler-downscale-delay)。另外还需要以下情况下才会进行任何缩放avg(CurrentPodsConsumption)/ Target下降9%,进行缩容,增加至10%进行扩容。以上两条件需要都满足。

这样做好处是:
1、判断的精度高,不会频繁的扩缩pod,造成集群压力大。
2、避免频繁的扩缩pod,防止应用访问不稳定。

未分类

实现hpa的条件:
1、hpa不能autoscale daemonset类型control
2、要实现autoscale,pod必须设置request

配置HPA

这里以kubeadm 部署和的kubernetes 1.11和Rancher2.0部署的kubernetes 1.10为例
环境信息

操作系统:ubuntu16.04
kubernetes版本:1.11
rancher:2.0.6

kubeadm方式

将metric-server从github拉取下来

git clone [email protected]:kubernetes-incubator/metrics-server.git

早期kubelet的10255端口是开放,但后面由于10255是一个非安全的端口容易被入侵,所以被关闭了。metric-server默认是从kubelet的10255端口去拉取监控信息的,所以这里需要修改从10250去拉取

edit  metrics-server/deploy/1.8+/metrics-server-deployment.yaml

修改source为以下内容。

–source=kubernetes.summary_api:https://kubernetes.default?kubeletHttps=true&kubeletPort=10250&insecure=true

apply yaml文件

kubectl apply -f metrics-server/deploy/1.8+/.1
![](http://ohx02qrb8.bkt.clouddn.com/kube_hpa_3.png)
![](http://ohx02qrb8.bkt.clouddn.com/kube_hpa_4.png)
![](http://ohx02qrb8.bkt.clouddn.com/kube_hpa_5.png)
等待一分钟  
执行
kubect top node
kubectl top pods

查看pod和node监控信息

未分类

创建个一个deployment,配置hpa测试

apiVersion: v1
kind: Service
metadata:
  name: podinfo
  labels:
    app: podinfo
spec:
  type: NodePort
  ports:
    - port: 9898
      targetPort: 9898
      nodePort: 31198
      protocol: TCP
  selector:
    app: podinfo
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: podinfo
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: podinfo
      annotations:
        prometheus.io/scrape: 'true'
    spec:
      containers:
      - name: podinfod
        image: stefanprodan/podinfo:0.0.1
        imagePullPolicy: Always
        command:
          - ./podinfo
          - -port=9898
          - -logtostderr=true
          - -v=2
        volumeMounts:
          - name: metadata
            mountPath: /etc/podinfod/metadata
            readOnly: true
        ports:
        - containerPort: 9898
          protocol: TCP
        resources:
          requests:
            memory: "32Mi"
            cpu: "1m"
          limits:
            memory: "256Mi"
            cpu: "100m"
      volumes:
        - name: metadata
          downwardAPI:
            items:
              - path: "labels"
                fieldRef:
                  fieldPath: metadata.labels
              - path: "annotations"
                fieldRef:
                  fieldPath: metadata.annotations

apply yaml文件

配置hpa

apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
  name: podinfo
spec:
  scaleTargetRef:
    apiVersion: extensions/v1beta1
    kind: Deployment
    name: podinfo
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      targetAverageUtilization: 80
  - type: Resource
    resource:
      name: memory
      targetAverageValue: 200Mi

apply yaml文件

get hpa

未分类

测试
使用webbench进行压力测试。

wget http://home.tiscali.cz/~cz210552/distfiles/webbench-1.5.tar.gz
tar -xvf webbench-1.5.tar.gz
cd webbench-1.5/
make && make install

webbench -c 1000 -t 12360 http://172.31.164.104:31198/

未分类

可以看见随着cpu压力的增加,已经自动scale了,需要注意的是,scale up是一个阶段性的过程,并不是一次性就直接scale到max了,而是一个阶段性的过程,判定算法就是上文介绍的内容。
隔断时间没操作压力下来后,自动缩减pod

未分类

Rancher2.0

使用rancher2.0部署的kubernetes如何开启HPA,因为rancher2.0将所有的kubernetes组件都容器化了,所以有些地方需要配置
配置方法
rancher2.0部署的kubernetes默认没有配置Metrics API aggregator的证书所以需要手动生成
生成证书文件

cat >> /etc/kubernetes/ssl/ca-config.json<< EOF
{
  "signing": {
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "kubernetes": {
        "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ],
        "expiry": "87600h"
      }
    }
  }
}
EOF
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
mv cfssljson_linux-amd64  /usr/bin/cfssljson
mv cfssl_linux-amd64  /usr/bin/cfssl
chmod a+x  /usr/bin/cfssljson
chmod a+x  /usr/bin/cfssl
cd /etc/kubernetes/ssl/
cat >> front-proxy-ca-csr.json <<EOF
{
    "CN": "kubernetes",
    "key": {
        "algo": "rsa",
        "size": 2048
    }
}
EOF
cat >>front-proxy-client-csr.json<<EOF
{
    "CN": "front-proxy-client",
        "algo": "rsa",
        "size": 2048
    }
}
EOF
cfssl gencert   -initca front-proxy-ca-csr.json |
cfssljson -bare front-proxy-ca
cfssl gencert   -ca=front-proxy-ca.pem  
  -ca-key=front-proxy-ca-key.pem 
-config=/etc/kubernetes/ssl/ca-config.json   
-profile=kubernetes   
front-proxy-client-csr.json | cfssljson -bare front-proxy-client

拷贝证书导集群其他节点

scp /etc/kubernetes/ssl/front-*

修改api-server的启动参数

--requestheader-client-ca-file=/etc/kubernetes/ssl/front-proxy-ca.pem 
--requestheader-allowed-names=front-proxy-client
--proxy-client-cert-file=/etc/kubernetes/ssl/front-proxy-client.pem
--proxy-client-key-file=/etc/kubernetes/ssl/front-proxy-client-key.pem

rancher2.0 custom集群时需要rke的启动修改参数,来修改api-server启动参数

未分类

view in API—>edit

未分类

将其部署方式的value设置为null

未分类

未分类

未分类

修改rancherKubernetesEngineConfig
这里面内容是json的,可以复制出来通过json解析工具解析

未分类

未分类

我们需要添加的参数
api-server配置

--requestheader-client-ca-file=/etc/kubernetes/ssl/front-proxy-ca.pem 
--requestheader-allowed-names=front-proxy-client
--proxy-client-cert-file=/etc/kubernetes/ssl/front-proxy-client.pem
--proxy-client-key-file=/etc/kubernetes/ssl/front-proxy-client-key.pem

json文件

{"addonJobTimeout":30,"authentication":{"strategy":"x509","type":"/v3/schemas/authnConfig"},"authorization":{"type":"/v3/schemas/authzConfig"},"bastionHost":{"sshAgentAuth":false,"type":"/v3/schemas/bastionHost"},"cloudProvider":{"type":"/v3/schemas/cloudProvider"},"ignoreDockerVersion":true,"ingress":{"provider":"nginx","type":"/v3/schemas/ingressConfig"},"kubernetesVersion":"v1.10.1-rancher1","network":{"canalNetworkProvider":{"iface":"","type":"/v3/schemas/canalNetworkProvider"},"plugin":"canal","type":"/v3/schemas/networkConfig"},"services":{"etcd":{"extraArgs":{"election-timeout":"5000","heartbeat-interval":"500"},"snapshot":false,"type":"/v3/schemas/etcdService"},"kubeApi":{"extraArgs":{"enable-aggregator-routing":"true","proxy-client-cert-file":"/etc/kubernetes/ssl/front-proxy-client.pem","proxy-client-key-file":"/etc/kubernetes/ssl/front-proxy-client-key.pem","requestheader-allowed-names":"front-proxy-client","requestheader-client-ca-file":"/etc/kubernetes/ssl/front-proxy-ca.pem","requestheader-extra-headers-prefix":"X-Remote-Extra-","requestheader-group-headers":"X-Remote-Group","requestheader-username-headers":"X-Remote-User"},"podSecurityPolicy":false,"type":"/v3/schemas/kubeAPIService"},"kubeController":{"type":"/v3/schemas/kubeControllerService"},"kubelet":{"extraArgs":{"anonymous-auth":"true","read-only-port":"10255"},"failSwapOn":false,"type":"/v3/schemas/kubeletService"},"kubeproxy":{"type":"/v3/schemas/kubeproxyService"},"scheduler":{"type":"/v3/schemas/schedulerService"},"type":"/v3/schemas/rkeConfigServices"},"sshAgentAuth":false,"type":"/v3/schemas/rancherKubernetesEngineConfig"}

未分类

然后集群会出现update状态,会将api-server和kubelt滚动更新

未分类

部署metric-server
修改yaml文件

apiVersion: v1
kind: ServiceAccount
metadata:
  name: metrics-server
  namespace: kube-system
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: metrics-server
  namespace: kube-system
  labels:
    k8s-app: metrics-server
spec:
  selector:
    matchLabels:
      k8s-app: metrics-server
  template:
    metadata:
      name: metrics-server
      labels:
        k8s-app: metrics-server
    spec:
      serviceAccountName: metrics-server
      containers:
      - name: metrics-server
        image: wanshaoyuan/metric-server:v1.0
        imagePullPolicy: Always
        command:
        - /metrics-server
        - --source=kubernetes.summary_api:https://kubernetes.default?kubeletHttps=true&kubeletPort=10250&insecure=true

部署

kubectl apply -f /root/k8s-prom-hpa/metrics-server/.

未分类

创建应用,查看hpa

kubectl apply -f /root/k8s-prom-hpa/podinfo/.

查看hpa

未分类

过几分钟可以看见应用在弹性扩容

未分类

https://zhuanlan.zhihu.com/p/34555654
https://github.com/kubernetes/community/blob/master/contributors/design-proposals/autoscaling/horizontal-pod-autoscaler.md#autoscaling-algorithm
https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#support-for-metrics-APIs

Kubernetes之配置与自定义DNS服务

本文解释如何为kubernetes集群配置及自定义DNS服务。从kubernetes1.11版本开始,coreDNS插件被包含在GA发行版中,并且被kubeadm默认安装。详情:Configuring CoreDNS and Using CoreDNS for Service Discovery。除特别说明,本文讨论的是默认dns插件。

介绍

Kubernetes的DNS功能以插件形式提供,是自动启动的系统内置服务。服务包含如下三个容器:

  • kubedns:监控Kubernetes master的service与endpoint变更,增删改DNS记录,将相关数据保存在内存中,为DNS查询提供服务。
  • dnsmasq: 充当DNS缓存,提高性能。
  • sidecar:挂斗容器,对dnsmasq与kubedns进行单点健康检查。

DNS服务拥有静态IP地址,将各节点kubeletr的–cluster-dns=设置成DNS服务的静态IP地址,当kubelet创建容器时则将此地址传递给容器。Kubernetes的DNS服务基于skyDNS库,支持forward lookups (A records)、service lookups (SRV records)、reverse IP address lookups (PTR records)。

从节点继承DNS配置

当kubelet启动容器时,除使用kubernetes内置的DNS服务,默认从节点继承其DNS配置。此特性使kubernetes系统中的容器DNS行为高度依赖低层节点,建议关闭,设置kubelet–resolv-conf选项为用户自定义配置文件,而非系统默认/etc/resolve.conf,这样容器继承的DNS配置由用户提供的配置文件决定,而非节点,降低耦合度。

配置存根域及上游DNS服务器

集群管理员可通过为kubernetes中DNS服务kube-system:kube-dns提供ConfigMap对象,设置自定义存根域及上游DNS服务器。以下示例为DNS服务配置一个存根域及两个上游DNS服务器:

apiVersion: v1
kind: ConfigMap
metadata:
  name: kube-dns
  namespace: kube-system
data:
  stubDomains: |
    {"acme.local": ["1.2.3.4"]}
  upstreamNameservers: |
    ["8.8.8.8", "8.8.4.4"]

如果查询请求的前缀为”acme.local”则被直接转发到1.2.3.4。下表列出不同域名前缀与DNS服务器对应关系:

未分类

对pod的影响

如果pod Spec之dnsPolicy设置为”Default”或者”Node”,则用户自定义存根服务器与上游服务器对pod没有影响。当值为”Default”时,pod之DNS配置完全从节点继承。如果为Node,则取决于pod Spec中的dnsConfig配置。

当dnsPolicy设置为”ClusterFirst”时,pod的DNS配置分成没无自定义存根域与上游服务器、有自定义存根域与上游服务器两种情况。

无自定义存根域与上游服务器:如果查询请求之域名前缀与集群默认域名匹配,则使用kubernetes内置DNS服务,如果不匹配则使用从节点继承之DNS服务。

有自定义存根域与上游服务器,域名解析流程如下:

  1. 请求首先发送到kube-dns缓存层。

  2. 在缓存层,检查请求的域名前缀并将请求转发到与之匹配的DNS服务器,流程如下:

  • 与集群域名前缀匹配,如“.cluster.local”,则发往kube-dns。

  • 如与存根域匹配,如“.acme.local”, 则发往匹配的存根域服务器。

  • 否则,发往上游服务器。

未分类

ConfigMap选项

未分类

配置CoreDNS

从1.9版本开始,CoreDNS成为GA可选特性,将来可能会取代kube-dns成为默认集群默认DNS解决方案,CoreDNS具备kube-dns所有功能并更强大。在CoreDNS插件内部通过一种Corefile文件管理配置。可以直接将为kube-dns设置的ConfigMap直接指定给CoreDNS,CoreDNS自动将此ConfigMap转换成Corefile。示例如下:

apiVersion: v1
data:
  federations: |
    {"foo" : "foo.feddomain.com"}
  stubDomains: |
    {"abc.com" : ["1.2.3.4"], "my.cluster.local" : ["2.3.4.5"]}
  upstreamNameservers: |
    ["8.8.8.8", "8.8.4.4"]
kind: ConfigMap

转换结果:

.:53 {
        errors
        health
        kubernetes cluster.local  in-addr.arpa ip6.arpa {
           upstream  8.8.8.8 8.8.4.4
           pods insecure
           fallthrough in-addr.arpa ip6.arpa
        }
        federation cluster.local {
           foo foo.feddomain.com
        }
        prometheus :9153
        proxy .  8.8.8.8 8.8.4.4
        cache 30
    }
    abc.com:53 {
        errors
        cache 30
        proxy . 1.2.3.4
    }
    my.cluster.local:53 {
        errors
        cache 30
        proxy . 2.3.4.5
    }

使用 kubeadm 安装k8s

安装版本

Kubernetes – 1.11.1

机器规划

未分类

注:三台机器已做key认证并添加hosts, 方便传送文件

系统配置(三台机器都执行)

关闭selinux及firewalld

sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
setenforce 0
systemctl stop firewalld && systemctl disable firewalld

内核参数调整

cat <<EOF >  /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system

关闭swap, 注释fstab中的swap配置

swapoff -a

注: k8s 版本1.8开始要求关闭系统的swap,否则启动不了kubelet;

安装docker并启动(三台机器都执行)

docker从1.13版本之后采用时间线的方式作为版本号,分为社区版CE和企业版EE; 比如: 18.06 为18年6月份发布的版本;

安装包官方地址:

https://download.docker.com/linux/centos/7/x86_64/stable/Packages/

下载安装 docker-ce 17.03版本:

wget -c https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-17.03.2.ce-1.el7.centos.x86_64.rpm
wget -c https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-selinux-17.03.2.ce-1.el7.centos.noarch.rpm
yum install -y docker-ce-selinux-17.03.2.ce-1.el7.centos.noarch.rpm docker-ce-17.03.2.ce-1.el7.centos.x86_64.rpm

注:本次安装的版本为 17.03 ; k8s-1.11.1 对应的最高版本docker是 17.03 ;

修改docker启动配置文件:

/usr/lib/systemd/system/docker.service

# 指定监听端口、数据存储目录以及加速镜像源
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H 127.0.0.1:8888 -g /data/docker --registry-mirror=http://xxxx.io --exec-opt native.cgroupdriver=systemd

启动 docker :

systemctl daemon-reload && systemctl enable docker && systemctl start docker

导入必要的镜像

默认使用 kubeadm 初始化集群时需要从 k8s.gcr.io 地址上拉取相关镜像,如果可以科学上网的,这一步可以省略;

master节点执行:

images=(kube-apiserver-amd64.tar kube-controller-manager-amd64.tar kube-scheduler-amd64.tar kubernetes-dashboard-amd64.tar etcd-amd64.tar coredns.tar flannel.tar kube-proxy-amd64.tar pause.tar)
for i in ${images[@]};do
    docker load < $(dirname $script_dir)/$i
done

node节点执行:

images=(flannel.tar kube-proxy-amd64.tar pause.tar)
for i in ${images[@]};do
    docker load < $(dirname $script_dir)/$i
done

镜像分享地址:

链接: https://pan.baidu.com/s/1jtT0qHpcz1WjovIBP6JOwQ 密码:5xxn

安装 kubeadm (三台机器都执行)

添加 yum 源:

cat > /etc/yum.repos.d/kubernetes.repo <<EOF 
[kubernetes] 
name=Kubernetes 
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64 
enabled=1 
gpgcheck=0 
repo_gpgcheck=0 
EOF

安装 kubeadm :

# 列出最新版本
yum list kubeadm --showduplicates
# 安装
yum install kubeadm-1.11.1

注:安装 kubeadm ,相关依赖会安装 kubectl、kubelet、kubernetes-cni ; kubectl 是管理集群的工具,kubelet 是每个node节点都会运行的一个服务,用于管理节点的docker启动、网络组件等功能;

配置启动 kubelet (三台机器都执行)

确保kubelet和docker使用同一个cgroupdriver, 这里使用systemd;

kubelet 额外参数配置:

/etc/sysconfig/kubelet

KUBELET_EXTRA_ARGS="--runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice"

启动 kubelet :

systemctl enable kubelet && systemctl start kubelet

初始化k8s集群 (master机器执行)

初始化:

kubeadm init --apiserver-advertise-address 10.211.55.10 --pod-network-cidr=10.10.0.0/16  --kubernetes-version=v1.11.1

初始化完成后会有以下提示:

[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes master has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

You can now join any number of machines by running the following on each node
as root:

  kubeadm join 10.211.55.10:6443 --token 4zfhdz.8jue59q95hzoc7p9 --discovery-token-ca-cert-hash sha256:da756adb30db06963db480d3868b9acd02c2e38271314baf62e9d28c6629ae92

增加kubectl权限访问:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

配置 k8s 网络 – flannel

Kubernetes支持Flannel、Calico、Weave network等多种cni网络Drivers;

配置 flannel :

wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
kubectl apply -f  kube-flannel.yml

如果有多张网卡,需要在kube-flannel.yml中使用–iface参数指定集群主机内网网卡的名称, 类似 :

args:
- --ip-masq
- --kube-subnet-mgr
- --iface=eth1

查看 k8s 集群状态

查看集群状态 :

kubectl get cs

查看 pods :

kubectl get pod --all-namespaces

其它节点添加到集群

集群初始化完成后可以看到,最后有提示加入集群的命令,但token是有时间限制的,可能过一段时间就过期了,可以通过以下命令成生新的命令:

kubeadm token create --print-join-command

输出类似:

kubeadm join 10.211.55.10:6443 --token pxlvg5.puu7a0mrhpoif16e --discovery-token-ca-cert-hash sha256:f732ceef958151c56583641048ce6a11c39f960166969fb8f782374c3b4a7570

查看已有 token :

kubeadm token list

部署 k8s Dashboard

下载部署配置文件:

wget https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml

指向端口类型为 NodePort , 可以使用 节点ip:端口 访问 :

修改 kubernetes-dashboard.yaml

# ------------------- Dashboard Service ------------------- #

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system
spec:
  type: NodePort
  ports:
    - port: 443
      targetPort: 8443
  selector:
    k8s-app: kubernetes-dashboard

因 k8s 在1.6版本以后 kube-apiserver 启用了 RBAC 授权, 因此需要认证权限配置文件 :

增加 kubernetes-dashboard-admin.rbac.yaml

---
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-admin
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: kubernetes-dashboard-admin
  labels:
    k8s-app: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: kubernetes-dashboard-admin
  namespace: kube-system

节点增加标签用法:

kubectl label nodes <node-name> <label-key>=<label-value>
kubectl get nodes
kubectl label nodes k8s-master1 k8s-app=kubernetes-dashboard

查看 dashboard 分配到的 NodePort :

kubectl get svc,pod --all-namespaces | grep dashboard

创建 dashboard 的 pod :

kubectl create -f kubernetes-dashboard.yaml
kubectl create -f kubernetes-dashboard-admin.rbac.yaml

查看登陆 dashboard 的token :

kubectl -n kube-system describe $(kubectl -n kube-system get secret -n kube-system -o name | grep namespace) | grep token

kubectl 命令补全

yum install -y bash-completion
source /usr/share/bash-completion/bash_completion
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc