kube-on-kube-operator 开发(三)

本文是介绍 kubernetes-operator 开发的第三篇,前文已经提到过 kubernetes-operator 的主要目标是实现以下三种场景中的集群管理:

  • kube-on-kube
  • kube-to-kube
  • kube-to-cloud-kube

目前笔者主要在开发 kube-to-kube,这一节会介绍 kube-to-kube 中如何使用二进制方式部署一个集群,问什么要先支持部署二进制集群呢,可以参考之前的文章。目前 kubernetes-operator 中部署集群是通过 ansible 调用笔者写的一些脚本部署的,由于 kubernetes 二进制文件比较大,暂时仅支持离线部署,所有部署请下载好所需的二进制文件,笔者也提供了部署 v1.14 需要的所有二进制文件已经镜像 yaml 等。

手动安装 kubernetes 最困难的地方就在于其复杂的认证(Authentication)以及鉴权(Authorization)机制,上篇文章已经介绍了 kubernetes 中的认证与鉴权机制以及其中的证书链,若不了请参考 http://blog.tianfeiyu.com/2019/08/18/k8s_auth_rbac/

使用 kubernetes-operator 管理集群时首选需要有一个元集群,元集群可以使用 minkube 或者 kind 部署一个单机版集群,然后将 kubernetes-operator 部署到单机版的集群中通过创建 CR 来创建一个业务集群,然后使用该业务集群作为元集群即可,或者直接使用 kubernetes-operator 中的部署业务集群的方式也可以部署一个集群。

部署前请先克隆 https://github.com/gosoon/kubernetes-operatorhttps://github.com/gosoon/kubernetes-utils 项目,部署集群所需要的一些工具、配置以及 bin 文件都存放在这两个项目中,你可以使用自己的配置。

准备环境

禁用防火墙:

$ systemctl stop firewalld
$ systemctl disable firewalld

禁用 SELinux:

$ setenforce 0
$ sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

关闭 swap:

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

配置 CA 及创建 TLS 证书

安装证书生成工具,本文使用 cfssl

$ cp kubernetes-utils/scripts/bin/certs/* /usr/bin/

etcd

$ cat << EOF > etcd-root-ca-csr.json
{
    "CN": "etcd-root-ca",
    "key": {
        "algo": "rsa",
        "size": 4096
    },
    "names": [
        {
            "O": "etcd",
            "OU": "etcd Security",
            "L": "Beijing",
            "ST": "Beijing",
            "C": "CN"
        }
    ],
    "ca": {
        "expiry": "87600h"
    }
}
EOF

$ cat << EOF > etcd-gencert.json
{
  "signing": {
    "default": {
        "usages": [
          "signing",
          "key encipherment",
          "server auth",
          "client auth"
        ],
        "expiry": "87600h"
    }
  }
}
EOF

$ cat << EOF > etcd-csr.json
{
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "O": "etcd",
            "OU": "etcd Security",
            "L": "Beijing",
            "ST": "Beijing",
            "C": "CN"
        }
    ],
    "CN": "etcd"
}
EOF

$ cat << EOF > config-etcd-peer.json
{
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "O": "etcd",
            "OU": "etcd Security",
            "L": "Beijing",
            "ST": "Beijing",
            "C": "CN"
        }
    ],
    "CN": "etcd"
}
EOF
$ cfssl gencert --initca=true etcd-root-ca-csr.json | cfssljson -bare output/ca

// 指定 etcd hosts,etcd server 和 etcd peer 中必须包含所有 etcd 的 hosts,eg:ETCD_HOSTS="10.0.4.15,10.0.2.15"
# etcd server
$ cfssl gencert \
  -ca=output/ca.pem \
  -ca-key=output/ca-key.pem \
  -config=ca-config.json \
  -hostname=127.0.0.1,${ETCD_HOSTS} \
  -profile=server \
  server.json | cfssljson -bare output/etcd-server
  
# etcd peer
$ cfssl gencert \
  -ca=output/ca.pem \
  -ca-key=output/ca-key.pem \
  -config=ca-config.json \
  -hostname=127.0.0.1,${ETCD_HOSTS} \
  -profile=peer \
  server.json | cfssljson -bare output/etcd-peer  

反解 etcd server 和 peer 证书校验 ip 是否存在:

$ cfssl certinfo -cert etcd-peer.pem

master

由于 master 下组件 CSR 的配置与 kubernetes 中的认证与鉴权相关联,需要严格按照 kubernetes 中默认的 RBAC 进行配置,每个组件对应的 user 或者 group,请参考上文 :http://blog.tianfeiyu.com/2019/08/18/k8s_auth_rbac/

$ cat << EOF > ca-csr.json
{
  "CN": "Kubernetes",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "China",
      "L": "Shanghai",
      "O": "Kubernetes",
      "OU": "Shanghai",
      "ST": "Shanghai"
    }
  ]
}
EOF

$ cat << EOF > ca-config.json
{
  "signing": {
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "kubernetes": {
        "usages": ["signing", "key encipherment", "server auth", "client auth"],
        "expiry": "87600h"
      }
    }
  }
}
EOF


// kube-apiserver csr
$ cat << EOF > kube-apiserver-csr.json
{
  "CN": "kubernetes",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "China",
      "L": "Shanghai",
      "O": "Kubernetes",
      "OU": "Kubernetes",
      "ST": "Shanghai"
    }
  ]
}
EOF

// kube-controller-manager csr
$ cat << EOF > kube-controller-manager-csr.json
{
  "CN": "system:kube-controller-manager",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "China",
      "L": "Shanghai",
      "O": "system:kube-controller-manager",
      "OU": "Kubernetes",
      "ST": "Shanghai"
    }
  ]
}
EOF

// kube-scheduler csr
$ cat << EOF > kube-scheduler-csr.json
{
  "CN": "system:kube-scheduler",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "China",
      "L": "Shanghai",
      "O": "system:kube-scheduler",
      "OU": "Kubernetes",
      "ST": "Shanghai"
    }
  ]
}
EOF

// kubelet csr,请替换 nodeName
$ cat << EOF > kubelet-csr.json
{
  "CN": "system:node:<nodeName>",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "China",
      "L": "Shanghai",
      "O": "system:nodes",
      "OU": "Kubernetes",
      "ST": "Shanghai"
    }
  ]
}
EOF

// apiserver client csr
$ cat << EOF > apiserver-kubelet-client-csr.json
{
  "CN": "system:kubelet-api-admin",
  "key": {
      "algo": "rsa",
      "size": 2048
  },
  "names": [
    {
      "C": "China",
      "L": "Shanghai",
      "O": "system:masters",
      "OU": "Kubernetes",
      "ST": "Shanghai"
    }
  ]
}
EOF

// kube-proxy csr
$ cat << EOF >  kube-proxy-csr.json
{
  "CN": "system:kube-proxy",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "China",
      "L": "Shanghai",
      "O": "system:node-proxier",
      "OU": "Kubernetes",
      "ST": "Shanghai"
    }
  ]
}
EOF

// kubectl csr
$ cat << EOF >  admin-csr.json
{
  "CN": "admin",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "China",
      "L": "Shanghai",
      "O": "system:masters",
      "OU": "Kubernetes",
      "ST": "Shanghai"
    }
  ]
}
EOF


$ cfssl gencert -initca ca-csr.json | cfssljson -bare output/ca

为了保证客户端与 Kubernetes API 的认证,Kubernetes API Server 凭证中必需包含 master 的静态 IP 地址,在 hostname 中指定
# apiserver
$ cfssl gencert \
  -ca=output/ca.pem \
  -ca-key=output/ca-key.pem \
  -config=ca-config.json \
  -hostname=10.250.0.1,${MASTER_HOSTS},${MASTER_VIP},127.0.0.1,kubernetes,kubernetes.default,kubernetes.default.svc \
  -profile=kubernetes \
  kube-apiserver-csr.json | cfssljson -bare output/kube-apiserver

# kubelet
for node in `echo ${NODE_HOSTS} | tr ',' ' '`;do
    cfssl gencert \
      -ca=output/ca.pem \
      -ca-key=output/ca-key.pem \
      -config=ca-config.json \
      -hostname=${NODE_HOSTS} \
      -profile=kubernetes \
      kubelet-csr.json | cfssljson -bare output/kubelet
done

# other component
for component in kube-controller-manager kube-scheduler kube-proxy apiserver-kubelet-client admin service-account;do
    cfssl gencert \
      -ca=output/ca.pem \
      -ca-key=output/ca-key.pem \
      -config=ca-config.json \
      -profile=kubernetes \
      ${component}-csr.json | cfssljson -bare output/${component}
done

生成 kubeconfig

// 替换 apiserver 
KUBE_APISERVER="https://10.0.4.15:6443"
CERTS_DIR="/etc/kubernetes/ssl"

# 生成 kubectl 配置文件
echo "Create kubectl kubeconfig..."
kubectl config set-cluster kubernetes \
  --certificate-authority=${CERTS_DIR}/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=output/kubectl.kubeconfig
kubectl config set-credentials "system:masters" \
  --client-certificate=${CERTS_DIR}/admin.pem \
  --client-key=${CERTS_DIR}/admin-key.pem \
  --embed-certs=true \
  --kubeconfig=output/kubectl.kubeconfig
kubectl config set-context default \
  --cluster=kubernetes \
  --user=system:masters \
  --kubeconfig=output/kubectl.kubeconfig
kubectl config use-context default --kubeconfig=output/kubectl.kubeconfig

# 生成 kube-controller-manager 配置文件
echo "Create kube-controller-manager kubeconfig..."
kubectl config set-cluster kubernetes \
  --certificate-authority=${CERTS_DIR}/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=output/kube-controller-manager.kubeconfig
kubectl config set-credentials "system:kube-controller-manager" \
  --client-certificate=${CERTS_DIR}/kube-controller-manager.pem \
  --client-key=${CERTS_DIR}/kube-controller-manager-key.pem \
  --embed-certs=true \
  --kubeconfig=output/kube-controller-manager.kubeconfig
kubectl config set-context default \
  --cluster=kubernetes \
  --user=system:kube-controller-manager \
  --kubeconfig=output/kube-controller-manager.kubeconfig
kubectl config use-context default --kubeconfig=output/kube-controller-manager.kubeconfig

# 生成 kube-scheduler 配置文件
echo "Create kube-scheduler kubeconfig..."
kubectl config set-cluster kubernetes \
  --certificate-authority=${CERTS_DIR}/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=output/kube-scheduler.kubeconfig
kubectl config set-credentials "system:kube-scheduler" \
  --client-certificate=${CERTS_DIR}/kube-scheduler.pem \
  --client-key=${CERTS_DIR}/kube-scheduler-key.pem \
  --embed-certs=true \
  --kubeconfig=output/kube-scheduler.kubeconfig
kubectl config set-context default \
  --cluster=kubernetes \
  --user=system:kube-scheduler \
  --kubeconfig=output/kube-scheduler.kubeconfig
kubectl config use-context default --kubeconfig=output/kube-scheduler.kubeconfig


# 生成 kubelet 配置文件,需要添加对应的 nodeName
echo "Create kubelet kubeconfig..."
kubectl config set-cluster kubernetes \
  --certificate-authority=${CERTS_DIR}/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=output/kubelet-${node}.kubeconfig

kubectl config set-credentials system:node:${node} \
  --client-certificate=${CERTS_DIR}/kubelet.pem \
  --client-key=${CERTS_DIR}/kubelet-key.pem \
  --embed-certs=true \
  --kubeconfig=output/kubelet-${node}.kubeconfig

kubectl config set-context default \
  --cluster=kubernetes \
  --user=system:node:${node} \
  --kubeconfig=${CERTS_DIR}/kubelet-${node}.kubeconfig
kubectl config use-context default --kubeconfig=output/kubelet-${node}.kubeconfig


# 生成 kube-proxy 配置文件
echo "Create kube-proxy kubeconfig..."
kubectl config set-cluster kubernetes \
  --certificate-authority=${CERTS_DIR}/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=output/kube-proxy.kubeconfig
kubectl config set-credentials "system:kube-proxy" \
  --client-certificate=${CERTS_DIR}/kube-proxy.pem \
  --client-key=${CERTS_DIR}/kube-proxy-key.pem \
  --embed-certs=true \
  --kubeconfig=output/kube-proxy.kubeconfig
kubectl config set-context default \
  --cluster=kubernetes \
  --user=system:kube-proxy \
  --kubeconfig=output/kube-proxy.kubeconfig
kubectl config use-context default --kubeconfig=output/kube-proxy.kubeconfig

部署

部署 etcd

拷贝证书文件:

$ cp output/* /etc/etcd/ssl/

拷贝 bin 文件:

$ cp kubernetes-utils/scripts/bin/etcd_v3.3.13/* /usr/bin/

拷贝配置文件,配置文件中的 ip 需要手动替换掉:

$ cp kubernetes-operator/scripts/config/etcd/etcd.conf /etc/etcd/

部署 k8s master 组件

拷贝证书文件:

$ cp output/* /etc/kubernetes/ssl/

拷贝 bin 文件:

$ cp kubernetes-utils/scripts/bin/kubernetes_v1.14.0/* /usr/bin/

拷贝配置文件,配置文件中的 ip 需要手动替换掉:

$ cp kubernetes-operator/scripts/config/master/* /etc/kubernetes/

部署 k8s node 组件

部署 docker,拷贝 bin 文件:

$ cp kubernetes-utils/scripts/bin/docker-ce-18.06.1.ce/*  /usr/bin/

拷贝证书文件:

$ cp output/* /etc/kubernetes/ssl/

拷贝配置文件,配置文件中的 ip 需要手动替换掉:

$ cp kubernetes-operator/scripts/config/node/* /etc/kubernetes/

创建 systemd 文件

拷贝所有服务的 systemd 文件:

拷贝配置文件,配置文件中的 ip 需要手动替换掉:

$ cp kubernetes-operator/scripts/systemd/* /usr/lib/systemd/system/

启动服务

首先启动 etcd 服务,etcd 所部署的几个节点需要同时启动,否则服务会启动失败。

然后依次启动 master 上的组件和 node 上的组件。

总结

本文主要讲述了 kubernetes-operator 中 kube-to-kube 部署集群的方式,介绍了主要的部署步骤,文中部署集群所有的操作都提供了脚本的方式:https://github.com/gosoon/kubernetes-operator/tree/master/scripts。kube-to-kube 的部署方式暂时是以 ansible + 自定义脚本的方式部署,后面也会不断升级与完善。接下来会继续开发 kube-on-kube 的部署方式,kube-on-kube 是将业务集群的 master 组件部署在元集群中,kube-on-kube 方式暂时会采用对 kubeadm 封装的形式进行部署。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,542评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,822评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,912评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,449评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,500评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,370评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,193评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,074评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,505评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,722评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,841评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,569评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,168评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,783评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,918评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,962评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,781评论 2 354

推荐阅读更多精彩内容