本文用以kubernetes 运维过程中遇到问题汇总,方便日后回顾~

kubernetes多网卡导致的问题

部署机器是阿里云,有两块网卡,eth0外网,eth1 vpc内网,集群的路由信息如下

[root@10 src]# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         gateway         0.0.0.0         UG    0      0        0 eth1
10.0.0.0        10.81.35.247    255.0.0.0       UG    0      0        0 eth0
10.81.32.0      0.0.0.0         255.255.252.0   U     0      0        0 eth0
39.107.40.0     0.0.0.0         255.255.252.0   U     0      0        0 eth1
100.64.0.0      10.81.35.247    255.192.0.0     UG    0      0        0 eth0
link-local      0.0.0.0         255.255.0.0     U     1002   0        0 eth0
link-local      0.0.0.0         255.255.0.0     U     1003   0        0 eth1
172.16.0.0      10.81.35.247    255.240.0.0     UG    0      0        0 eth0
192.168.0.0     0.0.0.0         255.255.255.0   U     0      0        0 cni0
192.168.0.0     0.0.0.0         255.255.240.0   U     0      0        0 docker0
192.168.1.0     192.168.1.0     255.255.255.0   UG    0      0        0 flannel.1
192.168.2.0     192.168.2.0     255.255.255.0   UG    0      0        0 flannel.1
  • docker0网段与cni0网段冲突问题

docker启动时没有指定bip,从上述路由规则发现,docker0使用了192.168的段,刚好给flannel设置的cidr段冲突, 所以需要给docker修改默认的网段,解决方法是给docker配置bip网段,然后重启docker,观察docker0的route规则

[root@10 ~]# cat /etc/docker/daemon.json
{
    "insecure-registries": [],
    "graph": "/var/lib/docker",
    "bip": "172.17.0.1/16",
    "registry-mirrors": ["https://registry.docker-cn.com"],
    "storage-driver": "devicemapper",
    "storage-opts": ["dm.use_deferred_removal=true", "dm.use_deferred_deletion=true"],
    "storage-opts": [
        "dm.thinpooldev=/dev/mapper/docker-thinpool",
        "dm.min_free_space=0%",
        "dm.use_deferred_deletion=true",
        "dm.use_deferred_removal=true",
        "dm.fs=ext4"
    ],
    "log-driver": "fluentd",
    "log-opts":
    {
        "fluentd-address": "localhost:24224",
        "tag": "docker.",
        "fluentd-async-connect": "true"
    }
}
  • 集群初始化问题

使用kubeadm搭建,若未指定–advertise-address地址则k8s默认拿default网卡, 而机器的default网卡刚好是外网eth0,所以初始化集群使用的地址是外网地址,导致一堆端口需要开,然后Node加入集群失败,解决办法是kubeadm初始化的 时候指定–advertise-address为内网地址,下面为kubeadm init使用的conf文件

Read on →

研究完kubectl的认证与授权,使用相同的方式去找kubelet的访问, 首先定位配置文件/etc/kubernetes/kubelet.conf,然后用相同的方式对client-key-data做base64解码,保存为kubelet.crt文件。

openssl查看crt证书,

[root@k8s-master kubernetes]# openssl x509 -text -in kubelet.crt -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 8126553944389053218 (0x70c751c18f5beb22)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=kubernetes
        Validity
            Not Before: Aug 20 05:50:39 2018 GMT
            Not After : Aug 20 05:50:42 2019 GMT
        Subject: O=system:nodes, CN=system:node:k8s-master
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:9f:92:83:49:aa:cc:52:0e:de:bd:af:a6:fd:ef:
    ... ...

得到我们期望的内容:

Subject: O=system:nodes, CN=system:node:k8s-master

关于Subject,在k8s中可以理解为角色绑定主体,RoleBinding或者ClusterRoleBinding可以将角色绑定到角色绑定主体(Subject)。 角色绑定主体可以是用户组(Group)、用户(User)或者服务账户(Service Accounts)

然后我尝试去k8s中找到一些关于system:nodes的RoleBindings或者ClusterRoleBindings,

[root@k8s-master kubernetes]# for bd in `kubectl get clusterrolebindings |awk '{print $1}'`; do echo $bd;kubectl get clusterrolebindings $bd -o yaml|grep 'system:nodes';done
NAME
Error from server (NotFound): clusterrolebindings.rbac.authorization.k8s.io "NAME" not found
cluster-admin
flannel
kubeadm:kubelet-bootstrap
kubeadm:node-autoapprove-bootstrap
kubeadm:node-autoapprove-certificate-rotation
  name: system:nodes
kubeadm:node-proxier
system:aws-cloud-provider
system:basic-user
... ...

结局有点意外,除了kubeadm:node-autoapprove-certificate-rotation外,没有找到system相关的rolebindings,显然和我们的理解不一样。 尝试去找资料,发现了这么一段

Kubernetes 1.7开始, apiserver的启动中默认增加了--authorization-mode=Node,RBAC,也就是说,除了RBAC外,还有Node这种特殊的授权方式,

继续查找kubernetes官方的信息,得知

Node authorization is a special-purpose authorization mode that specifically authorizes API requests made by kubelets.

关于k8s认证、授权相关的基础,只简单回顾,具体内容先参考如下文章:

Kubernetes API的访问控制原理回顾

Kubernetes集群的访问权限控制由kube-apiserver负责,kube-apiserver的访问权限控制由身份验证(authentication)、授权(authorization) 和准入控制(admission control)三步骤组成,这三步骤是按序进行的:

身份验证(Authentication)

这个环节它面对的输入是整个http request,它负责对来自client的请求进行身份校验,支持的方法包括:client证书验证(https双向验证)、 basic auth、普通token以及jwt token(用于serviceaccount)。

APIServer启动时,可以指定一种Authentication方法,也可以指定多种方法。如果指定了多种方法,那么APIServer将会逐个使用这些方法对客户端请求进行验证, 只要请求数据通过其中一种方法的验证,APIServer就会认为Authentication成功;

在较新版本kubeadm引导启动的k8s集群的apiserver初始配置中,默认支持client证书验证和serviceaccount两种身份验证方式。 证书认证通过设置--client-ca-file根证书以及--tls-cert-file--tls-private-key-file来开启。

在这个环节,apiserver会通过client证书或 http header中的字段(比如serviceaccount的jwt token)来识别出请求的用户身份,包括”user”、”group”等,这些信息将在后面的authorization环节用到。

授权(Authorization)

这个环节面对的输入是http request context中的各种属性,包括:usergrouprequest path(比如:/api/v1/healthz/version等)、 request verb(比如:getlistcreate等)。

APIServer会将这些属性值与事先配置好的访问策略(access policy)相比较。APIServer支持多种authorization mode,包括Node、RBAC、Webhook等。

APIServer启动时,可以指定一种authorization mode,也可以指定多种authorization mode,如果是后者,只要Request通过了其中一种mode的授权, 那么该环节的最终结果就是授权成功。在较新版本kubeadm引导启动的k8s集群的apiserver初始配置中,authorization-mode的默认配置是”Node,RBAC”

Node授权器主要用于各个node上的kubelet访问apiserver时使用的,其他一般均由RBAC授权器来授权。

Read on →

JavaScript是一种描述型脚本语言,它不同于java或C#等编译性语言,它不需要进行编译成中间语言,而是由浏览器进行动态地解析与执行。如果你不能理解javaScript语言的运行机制,或者简单地说,你不能掌握javascript的执行顺序,那你就犹如伯乐驾驭不了千里马,让千里马脱缰而出,四处乱窜。 那么JavaScript是怎么来进行解析的吗?它的执行顺序又是如何的呢?在了解这些之前,我们先来认识几个重要的术语:

代码块

JavaScript中的代码块是指由<script>标签分割的代码段。例如:

// 示例代码
<script type="text/javascript">
      alert("这是代码块一");
</script>

<script type="text/javascript">
      alert("这是代码块二");
</script>

JS是按照代码块来进行编译和执行的,代码块间相互独立,但变量和方法共享。什么意思呢? 举个例子,你就明白了:

<script type="text/javascript">
    alert(str);   //因为没有定义str,所以浏览器会出错,下面的不能运行
    alert("我是代码块一");  //没有运行到这里
    var test = "我是代码块一变量";
</script>

<script type="text/javascript">
    alert("我是代码块二");  //这里有运行到
    alert(test);  //弹出"我是代码块一变量"
</script>

上面的代码中代码块一中运行报错,但不影响代码块二的执行,这就是代码块间的独立性,而代码块二中能调用到代码一中的变量,则是块间共享性。

Read on →

由于手动安装Greenplum过于繁琐,考虑对安装过程进行自动化,针对手动安装的过程,大致整理了几个脚本,简化安装程序,安装过程中必要的交互操作可以通过expect来实现,比如多机互信环节、master安装GreenPlum过程等。 大致过程如下:

准备脚本

root用户登录master节点,创建/opt/gp目录

mkdir /opt/gp

拷贝gp.tar/opt/gp目录,解压

tar -xvf gp.tar -C /opt/gp
chmod -R 777 /opt/gp

master安装GP

cd /opt/gp
./greenplum-db-4.3.0.0-build-3-RHEL5-x86_64.bin

关闭相关服务,执行脚本拷贝

配置hosts文件,内容参照如下

10.68.28.222 mdw
10.68.28.223 smdw
10.68.28.224 sdw1
10.68.28.225 sdw2
Read on →