锻骨境-第4层 k8s生产环境高可用集群搭建

存储的高可用

官网地址
项目源码地址
上一层文章-开发环境k8s 高可用master 的搭建

申明:

这里用的loadbalance ,还是上层文章开发环境的nginx .

stream {
    server {
        listen 8443;
        proxy_pass kube_apiserver;
    }

    upstream kube_apiserver {
        server 192.168.10.133:6443 weight=50 max_fails=3 fail_timeout=5s;
        server 192.168.10.134:6443 weight=50 max_fails=3 fail_timeout=5s;
        
    }
}

说明

Etcd是一个高可用的键值存储系统,主要用于共享配置和服务发现,它通过Raft一致性算法处理日志复制以保证强一致性,我们可以理解它为一个高可用强一致性的服务发现存储仓库。

在kubernetes集群中,etcd主要用于配置共享和服务发现

Etcd主要解决的是分布式系统中数据一致性的问题,而分布式系统中的数据分为控制数据和应用数据,etcd处理的数据类型为控制数据,对于很少量的应用数据也可以进行处理。

Etcd 好处:

  • 简单。
    使用Go语言编写部署简单;使用HTTP作为接口使用简单;使用Raft算法保证强一致性
    让用户易于理解。
  • 数据持久化。
    etcd默认数据一更新就进行持久化。
  • 安全。
    etcd支持SSL客户端安全认证。

示例部署ETCD高可用集群

上一节的问题,etcd 没有集群化

  • 后果就是etcd 意外死亡,那么k8s 将不可用
  • etcd 还需要做的就是,数据的备份

开始搭建etcd 集群

我们完整的结构应该是这样的:

image.png
  • 我们部署的etcd 是容器化的,并没有独立成一个集群
  • 参考官网 可知,在上一步的kubeadm-config.yaml 中没有配置 etcd 的地址,通过describe 命令查看etcd 也可以知道配置有问题。
    上面基于容器的做法很容易出问题,这次按照生产的标准搭建高可用k8s 集群。

开始

安装cdssl 证书生成工具

wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64

wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64

wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64

chmod +x cfssl_linux-amd64 cfssljson_linux-amd64 cfssl-certinfo_linux-amd64

mv cfssl_linux-amd64 /usr/local/bin/cfssl

mv cfssljson_linux-amd64 /usr/local/bin/cfssljson

mv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo

创建 CA 配置文件(ca-config.json)

{
    "signing": {
        "default": {
            "expiry": "175200h"
        },
        "profiles": {
            "kubernetes": {
                "expiry": "175200h",
                "usages": [
                    "signing",
                    "key encipherment",
                    "server auth",
            "client auth"
                ]
            },
            "etcd": {
                "expiry": "175200h",
                "usages": [
                    "signing",
                    "key encipherment",
                    "server auth",
                    "client auth"
                ]
            }
        }
    }
}

创建 CA 证书签名请求(ca-csr.json)

{
  "CN": "kubernetes",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "shenzhen",
      "L": "shenzhen",
      "O": "k8s",
      "OU": "System"
    }
  ]
}

生成 CA 证书和私钥
cfssl gencert -initca ca-csr.json | cfssljson -bare ca

[root@k8s-node1 bin]# cfssl gencert -initca ca-csr.json | cfssljson -bare ca
2019/10/29 21:10:59 [INFO] generating a new CA key and certificate from CSR
2019/10/29 21:10:59 [INFO] generate received request
2019/10/29 21:10:59 [INFO] received CSR
2019/10/29 21:10:59 [INFO] generating key: rsa-2048
2019/10/29 21:11:00 [INFO] encoded CSR
2019/10/29 21:11:00 [INFO] signed certificate with serial number 213974363926484894183998850838526320112981116568
[root@k8s-node1 bin]# ls
ca-config.json  ca.csr  ca-csr.json  ca-key.pem  ca.pem  cfssl  cfssl-certinfo  cfssljson


创建 kubernetes证书签名请求(k8s-csr.json),这里注意hosts需要配置kubernetes 自身的域名,否则会导致coreDns 不可用(其实就是认证失败,调度不了etcd 接口)

{
  "CN": "kubernetes",
  "hosts": [
    "127.0.0.1",
    "192.168.10.133",
    "192.168.10.134",
    "192.168.10.135",
    "10.96.0.1",
      "kubernetes",
      "kubernetes.default",
      "kubernetes.default.svc",
      "kubernetes.default.svc.cluster",
      "kubernetes.default.svc.cluster.local"

  ],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "shenzhen",
      "L": "shenzhen",
      "O": "k8s",
      "OU": "System"
    }
  ]
}


执行

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes k8s-csr.json | cfssljson -bare kubernetes


[root@k8s-node1 bin]# ls
ca-config.json  ca.csr  ca-csr.json  ca-key.pem  ca.pem  cfssl  cfssl-certinfo  cfssljson  k8s-csr.json  kubernetes.csr  kubernetes-key.pem  kubernetes.pem
[root@k8s-node1 bin]# 

复制pem后缀的证书到/etc/kubernetes/ssl下,每个节点都做
这里说明下,kubeadm reset 命令会删除 /etc/kubernetes/pki 下所有的文件。所有有些证书,比如etcd 的,我们存在另一个地方,一个是本地的master 主机上跑了etcd 服务需要,还一个就是存个备份。

在后面,可以看到我把这里的etcd 的各种证书,每次 reset 完之后,都会在 /etc/kubernetes/pki 下创建 etcd目录,然后 cp -r /etc/kubernetes/ssl/*.pem /etc/kubernetes/pki /etcd 。

可以认为。k8s 也是etcd 的一个客户端,etcd 服务做了tls ,客户端当然需要证书才能访问。

# mkdir -p /etc/kubernetes/ssl
# cp *.pem /etc/kubernetes/ssl

https://github.com/etcd-io/etcd/releases
下载安装包,我用到最新的,解压在了 /etc/etcd 目录下即可。

配置 etcd.serice ,使用systemctl 管理 。配置127.0.0.1 不需要https.

[root@k8s-node1 bin]# cat /etc/systemd/system/etcd.service 
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos

[Service]
Type=notify
WorkingDirectory=/var/lib/etcd/
EnvironmentFile=-/etc/etcd/etcd.yaml
ExecStart=/bin/bash -c "GOMAXPROCS=$(nproc) /etc/etcd/etcd --name=etcd-0 --cert-file=/etc/kubernetes/ssl/kubernetes.pem --key-file=/etc/kubernetes/ssl/kubernetes-key.pem --peer-cert-file=/etc/kubernetes/ssl/kubernetes.pem --peer-key-file=/etc/kubernetes/ssl/kubernetes-key.pem --trusted-ca-file=/etc/kubernetes/ssl/ca.pem --peer-trusted-ca-file=/etc/kubernetes/ssl/ca.pem --initial-advertise-peer-urls=https://192.168.10.134:2380 --listen-peer-urls=https://192.168.10.134:2380 --listen-client-urls=https://192.168.10.134:2379,http://127.0.0.1:2379 --advertise-client-urls=https://192.168.10.134:2379 --initial-cluster-token=etcd-cluster-0 --initial-cluster=\"etcd-0=https://192.168.10.133:2380,etcd-1=https://192.168.10.134:2380\" --initial-cluster-state=new --data-dir=/var/lib/etcd"
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target


另一个节点同样做 证书复制,把etcd 放在了 /etc/etcd 下面,配置修改操作。

启动etcd

[root@k8s-node1 bin]# systemctl daemon-reload
[root@k8s-node1 bin]# systemctl start etcd
[root@k8s-node1 bin]# ps -ef |grep etcd 
root      44905      1  2 11:37 ?        00:00:00 /etc/etcd/etcd --name=etcd-1 --cert-file=/etc/kubernetes/ssl/kubernetes.pem --key-file=/etc/kubernetes/ssl/kubernetes-key.pem --peer-cert-file=/etc/kubernetes/ssl/kubernetes.pem --peer-key-file=/etc/kubernetes/ssl/kubernetes-key.pem --trusted-ca-file=/etc/kubernetes/ssl/ca.pem --peer-trusted-ca-file=/etc/kubernetes/ssl/ca.pem --initial-advertise-peer-urls=https://192.168.10.134:2380 --listen-peer-urls=https://192.168.10.134:2380 --listen-client-urls=https://192.168.10.134:2379,http://127.0.0.1:2379 --advertise-client-urls=https://192.168.10.134:2379 --initial-cluster-token=etcd-cluster-0 --initial-cluster=etcd-0=https://192.168.10.133:2380,etcd-1=https://192.168.10.134:2380 --initial-cluster-state=new --data-dir=/var/lib/etcd
root      44918  16456  0 11:38 pts/1    00:00:00 grep --color=auto etcd

查看集群结果


[root@k8s-master k8s]# cd /etc/etcd
[root@k8s-master etcd]# ls
etcd  etcd-0.etcd  etcdctl  etcd.yml  install  nohup.out
[root@k8s-master etcd]# 
[root@k8s-master etcd]# ./etcdctl --cacert=/etc/kubernetes/ssl/ca.pem --cert=/etc/kubernetes/ssl/kubernetes.pem --key=/etc/kubernetes/ssl/kubernetes-key.pem --endpoints=https://192.168.10.133:2379,https://192.168.10.134:2379  endpoint health 
https://192.168.10.134:2379 is healthy: successfully committed proposal: took = 15.768454ms
https://192.168.10.133:2379 is healthy: successfully committed proposal: took = 17.041281ms


由此可知,etcd 集群完成。

开始配置k8s

初始化第一个节点:

  • 重置一个节点
[root@k8s-master k8s]# kubeadm   reset 
[reset] WARNING: changes made to this host by 'kubeadm init' or 'kubeadm join' will be reverted.
[reset] are you sure you want to proceed? [y/N]: y
[preflight] running pre-flight checks
[reset] Reading configuration from the cluster...
[reset] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
W1030 13:25:39.401263   66304 reset.go:213] [reset] Unable to fetch the kubeadm-config ConfigMap, using etcd pod spec as fallback: failed to get config map: Get https://192.168.10.133:8443/api/v1/namespaces/kube-system/configmaps/kubeadm-config: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "kubernetes")
[reset] no etcd config found. Assuming external etcd
[reset] please manually reset etcd to prevent further issues
[reset] stopping the kubelet service
[reset] unmounting mounted directories in "/var/lib/kubelet"
[reset] deleting contents of stateful directories: [/var/lib/kubelet /etc/cni/net.d /var/lib/dockershim /var/run/kubernetes]
[reset] deleting contents of config directories: [/etc/kubernetes/manifests /etc/kubernetes/pki]
[reset] deleting files: [/etc/kubernetes/admin.conf /etc/kubernetes/kubelet.conf /etc/kubernetes/bootstrap-kubelet.conf /etc/kubernetes/controller-manager.conf /etc/kubernetes/scheduler.conf]

The reset process does not reset or clean up iptables rules or IPVS tables.
If you wish to reset iptables, you must do so manually.
For example: 
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X

If your cluster was setup to utilize IPVS, run ipvsadm --clear (or similar)
to reset your system's IPVS tables.

[root@k8s-master k8s]# mkdir -p  /etc/kubernetes/pki/etcd/
[root@k8s-master k8s]# cp  -r /etc/kubernetes/ssl/*.pem  /etc/kubernetes/pki/etcd/
[root@k8s-master k8s]# 

初始化:

重点

先修改kubelet 自带的etcd 配置,这里可恶的竟然是cgroup-driver 设置的是systemd .
删除自带的etcd 配置文件(把所有的master 节点上的这个文件都删除了)。 这里坑了好久。。。。

[root@k8s-master kubelet.service.d]# 
[root@k8s-master kubelet.service.d]# cat 20-etcd-service-manager.conf 
[Service]
ExecStart=
#  Replace "systemd" with the cgroup driver of your container runtime. The default value in the kubelet is "cgroupfs".
ExecStart=/usr/bin/kubelet --address=127.0.0.1 --pod-manifest-path=/etc/kubernetes/manifests --cgroup-driver=systemd
Restart=always
[root@k8s-master kubelet.service.d]# 
[root@k8s-master kubelet.service.d]# 
[root@k8s-master kubelet.service.d]# rm -rf 20-etcd-service-manager.conf 

复制etcd 证书到etc/kubernetes/pki/etcd/ ,这个目录kubeadm reset 之后会被情况

[root@k8s-master k8s]# mkdir -p  /etc/kubernetes/pki/etcd/
[root@k8s-master k8s]# 
[root@k8s-master k8s]# cp  -r /etc/kubernetes/ssl/*.pem  /etc/kubernetes/pki/etcd/

上面这步骤要在所有master 上执行!上面这步骤要在所有master 上执行!上面这步骤要在所有master 上执行!

编写kubeadm 配置文件,certSANs写全自己的 master地址:

apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: stable
apiServer:
  certSANs:
  - "192.168.10.133"
  - "127.0.0.1"
  - "192.168.10.134"
controlPlaneEndpoint: "192.168.10.133:8443"
networking:
  podSubnet: 10.244.0.0/16
etcd:
    external:
        endpoints:
        - https://192.168.10.133:2379
        - https://192.168.10.134:2379
        caFile: /etc/kubernetes/pki/etcd/ca.pem
        certFile: /etc/kubernetes/pki/etcd/kubernetes.pem
        keyFile: /etc/kubernetes/pki/etcd/kubernetes-key.pem


因为前面的etcd 的cfssl 证书都拿来放在了/etc/kubernets/pki/etcd 下面了,直接进行init 操作

[root@k8s-master k8s]# mkdir -p  /etc/kubernetes/pki/etcd/
[root@k8s-master k8s]# cp  -r /etc/kubernetes/ssl/*.pem  /etc/kubernetes/pki/etcd/
[root@k8s-master k8s]# kubeadm init --config=kubeadm-config.yaml   -upload-certs --ignore-preflight-errors=all  
I1030 14:02:04.630701   70169 version.go:94] could not fetch a Kubernetes version from the internet: unable to get URL "https://dl.k8s.io/release/stable.txt": Get https://dl.k8s.io/release/stable.txt: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
I1030 14:02:04.630785   70169 version.go:95] falling back to the local client version: v1.13.0
[init] Using Kubernetes version: v1.13.0
[preflight] Running pre-flight checks
    [WARNING SystemVerification]: this Docker version is not on the list of validated versions: 18.09.0. Latest validated version: 18.06
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Activating the kubelet service
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] External etcd mode: Skipping etcd/ca certificate authority generation
[certs] External etcd mode: Skipping etcd/healthcheck-client certificate authority generation
[certs] External etcd mode: Skipping apiserver-etcd-client certificate authority generation
[certs] External etcd mode: Skipping etcd/server certificate authority generation
[certs] External etcd mode: Skipping etcd/peer certificate authority generation
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [k8s-master kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 192.168.10.133 192.168.10.133 192.168.10.133]
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address
[kubeconfig] Writing "admin.conf" kubeconfig file
[endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 19.504737 seconds
[uploadconfig] storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.13" in namespace kube-system with the configuration for the kubelets in the cluster
[patchnode] Uploading the CRI Socket information "/var/run/dockershim.sock" to the Node API object "k8s-master" as an annotation
[mark-control-plane] Marking the node k8s-master as control-plane by adding the label "node-role.kubernetes.io/master=''"
[mark-control-plane] Marking the node k8s-master as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[bootstrap-token] Using token: s1ry1w.uedyn8db3jnm1tsg
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstraptoken] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstraptoken] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstraptoken] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstraptoken] creating the "cluster-info" ConfigMap in the "kube-public" namespace
[addons] Applied essential addon: CoreDNS
[endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address
[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 192.168.10.133:8443 --token s1ry1w.uedyn8db3jnm1tsg --discovery-token-ca-cert-hash sha256:fdcc767dc0aeebfadaa4faef2ee19642ce6d85462771baaba23f927696c4ef78


安装flannel 组件服务,同上一步,安装完成后,节点变为 ready 状态
见:kube-flannel.yml

[root@k8s-master k8s]# kubectl  apply -f flannel.yaml  
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.extensions/kube-flannel-ds-amd64 created
[root@k8s-master k8s]# kubectl  get no 

NAME         STATUS   ROLES    AGE     VERSION
k8s-master   Ready    master   5m12s   v1.13.0

OK ,第一个节点终于完成了。这时候,这个节点的证书就可以复制到其他的master 主机上了。
高版本的使用upload-certs 参数的话,证书也不需要每次复制了。

初始化第二个master节点:
我用的是1.13 版本的k8s , join 命令带 "--experimental-control-plane " 这个参数,代表加入的是个master 节点,不带就是node 。 注意这里也需要删除kubelete 自带的etcd 文件。

重点:
首先,就是把第一个master 上的证书拿过来,既把maseter1 上的 /etc/kubernetes/pki 文件夹全部复制到master2 上面的 /etc/kubernetes/pki 。 这个文件放的是各种证书。

开始加入主节点

[root@k8s-node1 k8s]# kubeadm join 192.168.10.133:8443 --token f2mitj.hbrghf2lpmy4n91f --discovery-token-ca-cert-hash sha256:2cbd8aa7a7822beec6fff001f8b03f54180ef3924314964e97174562d71a2873    --experimental-control-plane  
[preflight] Running pre-flight checks
    [WARNING SystemVerification]: this Docker version is not on the list of validated versions: 18.09.0. Latest validated version: 18.06
[discovery] Trying to connect to API Server "192.168.10.133:8443"
[discovery] Created cluster-info discovery client, requesting info from "https://192.168.10.133:8443"
[discovery] Requesting info from "https://192.168.10.133:8443" again to validate TLS against the pinned public key
[discovery] Cluster info signature and contents are valid and TLS certificate validates against pinned roots, will use API Server "192.168.10.133:8443"
[discovery] Successfully established connection with API Server "192.168.10.133:8443"
[join] Reading configuration from the cluster...
[join] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
[join] Running pre-flight checks before initializing the new control plane instance
    [WARNING SystemVerification]: this Docker version is not on the list of validated versions: 18.09.0. Latest validated version: 18.06
[certs] Using the existing "front-proxy-client" certificate and key
[certs] Using the existing "apiserver" certificate and key
[certs] Using the existing "apiserver-kubelet-client" certificate and key
[certs] valid certificates and keys now exist in "/etc/kubernetes/pki"
[certs] Using the existing "sa" key
[endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[kubelet] Downloading configuration for the kubelet from the "kubelet-config-1.13" ConfigMap in the kube-system namespace
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Activating the kubelet service
[tlsbootstrap] Waiting for the kubelet to perform the TLS Bootstrap...
[patchnode] Uploading the CRI Socket information "/var/run/dockershim.sock" to the Node API object "k8s-node1" as an annotation
[uploadconfig] storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[mark-control-plane] Marking the node k8s-node1 as control-plane by adding the label "node-role.kubernetes.io/master=''"
[mark-control-plane] Marking the node k8s-node1 as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]

This node has joined the cluster and a new control plane instance was created:

* Certificate signing request was sent to apiserver and approval was received.
* The Kubelet was informed of the new secure connection details.
* Master label and taint were applied to the new node.
* The Kubernetes control plane instances scaled up.


To start administering your cluster from this node, 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

Run 'kubectl get nodes' to see this node join the cluster.

[root@k8s-node1 k8s]# mkdir -p $HOME/.kube
[root@k8s-node1 k8s]# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
cp:是否覆盖"/root/.kube/config"? y
[root@k8s-node1 k8s]# sudo chown $(id -u):$(id -g) $HOME/.kube/config
[root@k8s-node1 k8s]# 
[root@k8s-node1 k8s]# 
[root@k8s-node1 k8s]# kubectl get no 
NAME         STATUS   ROLES    AGE   VERSION
k8s-master   Ready    master   28m   v1.13.0
k8s-node1    Ready    master   17m   v1.13.0

此时查看集群的组件状态:

[root@k8s-node1 pki]# kubectl  get cs 

NAME                 STATUS    MESSAGE             ERROR
controller-manager   Healthy   ok                  
scheduler            Healthy   ok                  
etcd-0               Healthy   {"health":"true"}   
etcd-1               Healthy   {"health":"true"} 

[root@k8s-node1 pki]# kubectl  get  po --all-namespaces
NAMESPACE     NAME                                 READY   STATUS    RESTARTS   AGE
kube-system   coredns-86c58d9df4-4px8n             1/1     Running   0          11m
kube-system   coredns-86c58d9df4-qwbql             1/1     Running   0          11m
kube-system   kube-apiserver-k8s-master            1/1     Running   0          10m
kube-system   kube-apiserver-k8s-node1             1/1     Running   0          6m55s
kube-system   kube-controller-manager-k8s-master   1/1     Running   0          10m
kube-system   kube-controller-manager-k8s-node1    1/1     Running   0          6m55s
kube-system   kube-flannel-ds-amd64-nntpq          1/1     Running   0          10m
kube-system   kube-flannel-ds-amd64-tj4sz          1/1     Running   0          6m55s
kube-system   kube-proxy-fm22x                     1/1     Running   0          11m
kube-system   kube-proxy-ngknh                     1/1     Running   0          6m55s
kube-system   kube-scheduler-k8s-master            1/1     Running   0          10m
kube-system   kube-scheduler-k8s-node1             1/1     Running   0          6m55s

[root@k8s-node1 pki]# kubectl  get  no
NAME         STATUS   ROLES    AGE     VERSION
k8s-master   Ready    master   11m     v1.13.0
k8s-node1    Ready    master   7m12s   v1.13.0


至此,k8s 双master 节点搭建完成,且etcd 集群外置。 当集群死亡之后,再次重启可以从etcd 恢复集群状态。

注意的是,如果想重新搭建k8s集群,需要清空etcd里存储的pod 数据。

[root@k8s-node1 etcd]# ./etcdctl --cacert=/etc/kubernetes/ssl/ca.pem --cert=/etc/kubernetes/ssl/kubernetes.pem --key=/etc/kubernetes/ssl/kubernetes-key.pem --endpoints=https://192.168.10.133:2379,https://192.168.10.134:2379  del / --prefix 
447
[root@k8s-node1 etcd]# 

高版本的 master 扩展

在init 第一个master 时候的不同;

kubeadm init --config=kubeadm-config.yaml --upload-certs --ignore-preflight-errors=all

高版本其实会打出两条join 信息,一个是加入 master 节点的信息,一个是加入node 节点的信息,和低版本的join命令类似,不多在加入master 的时候又多了一个 认证的参数,如下:

kubeadm join master:6443 --token uwm1iq.bydvqhg91670w58g \
  --discovery-token-ca-cert-hash sha256:fef3eba9bc05450a0e3c705239775bf5297a82ecf4faf683a7cbb3a38b433ca0 \
  --experimental-control-plane --certificate-key cdad981734e547e60133a044ac72a60f6021038c5c3ca4d25a886e0ce79f9b57 \
 --ignore-preflight-errors=all
 # --ignore-preflight-errors=all表示忽略错误,可以不加

附 在机房花了20分钟安装k8s v1.16.2 版本安装完之后的效果:

[root@k8s-master1 master]# kubectl  get no  -o wide 
NAME          STATUS   ROLES    AGE         VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION               CONTAINER-RUNTIME
k8s-master1   Ready    master   20m         v1.16.2   192.168.1.110   <none>        CentOS Linux 7 (Core)   3.10.0-1062.4.1.el7.x86_64   docker://18.6.1
k8s-master2   Ready    master   15m         v1.16.2   192.168.1.111   <none>        CentOS Linux 7 (Core)   3.10.0-1062.4.1.el7.x86_64   docker://18.6.1
k8s-node1     Ready    <none>   6m24s       v1.16.2   192.168.1.120   <none>        CentOS Linux 7 (Core)   3.10.0-1062.4.1.el7.x86_64   docker://18.6.1
k8s-node2     Ready    <none>   2m55s       v1.16.2   192.168.1.121   <none>        CentOS Linux 7 (Core)   3.10.0-1062.4.1.el7.x86_64   docker://18.6.1
k8s-node3     Ready    <none>   <invalid>   v1.16.2   192.168.1.122   <none>        CentOS Linux 7 (Core)   3.10.0-1062.4.1.el7.x86_64   docker://18.6.1

  • 安装文件kubeadm-conf.yaml:
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
clusterName: kubernetes
apiServer:
   certSANs:
   - "192.168.1.110"
   - "192.168.1.111"
   - "127.0.0.1"
   - "192.168.1.109"
   - "k8s-master1"
   - "k8s-master2"
    
controlPlaneEndpoint: "192.168.1.109:6443"
imageRepository: registry.aliyuncs.com/google_containers
kubernetesVersion: v1.16.0
networking:
  dnsDomain: cluster.local
  podSubnet: "10.244.0.0/16"
  serviceSubnet: "10.245.0.0/16"
scheduler: {}
controllerManager: {}
etcd:
    external:
        endpoints:
        - https://192.168.1.110:2379
        - https://192.168.1.111:2379
        caFile: /etc/etcd/ssl/ca.pem
        certFile: /etc/etcd/ssl/kubernetes.pem
        keyFile: /etc/etcd/ssl/kubernetes-key.pem

  • master1 初始化成功,看着命令join即可:
[root@k8s-master1 master]# kubeadm init --config=test.yaml  --upload-certs
[init] Using Kubernetes version: v1.16.0
[preflight] Running pre-flight checks
    [WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/
error execution phase preflight: [preflight] Some fatal errors occurred:
    [ERROR ExternalEtcdVersion]: couldn't load external etcd's certificate and key pair /etc/etcd/ssl/kubernetes.pem, /etc/etcd/ssl/kubernetes-key.pe: open /etc/etcd/ssl/kubernetes-key.pe: no such file or directory
    [ERROR ExternalEtcdClientCertificates]: /etc/etcd/ssl/kubernetes-key.pe doesn't exist
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher
[root@k8s-master1 master]# vim test.yaml 
[root@k8s-master1 master]# 
[root@k8s-master1 master]# kubeadm init --config=test.yaml  --upload-certs
[init] Using Kubernetes version: v1.16.0
[preflight] Running pre-flight checks
    [WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Activating the kubelet service
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [k8s-master1 kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local k8s-master1 k8s-master2] and IPs [10.245.0.1 192.168.1.110 192.168.1.109 192.168.1.110 192.168.1.111 127.0.0.1 192.168.1.109]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] External etcd mode: Skipping etcd/ca certificate authority generation
[certs] External etcd mode: Skipping etcd/server certificate generation
[certs] External etcd mode: Skipping etcd/peer certificate generation
[certs] External etcd mode: Skipping etcd/healthcheck-client certificate generation
[certs] External etcd mode: Skipping apiserver-etcd-client certificate generation
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[kubelet-check] Initial timeout of 40s passed.
[apiclient] All control plane components are healthy after 63.035131 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.16" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[upload-certs] Using certificate key:
96dacef0c81bf971bcb39f347c3d3fd6e2fb2c3d253c6da01ec29f1e39eb2713
[mark-control-plane] Marking the node k8s-master1 as control-plane by adding the label "node-role.kubernetes.io/master=''"
[mark-control-plane] Marking the node k8s-master1 as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[bootstrap-token] Using token: 2sqa85.x8jxuibdr19f9wg0
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes control-plane 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 the control-plane node running the following command on each as root:

  kubeadm join 192.168.1.109:6443 --token 2sqa85.x8jxuibdr19f9wg0 \
    --discovery-token-ca-cert-hash sha256:f07f424c74f4871639ac3d4131db7d51c550d0965df1856e9bf51d711f79c43b \
    --control-plane --certificate-key 96dacef0c81bf971bcb39f347c3d3fd6e2fb2c3d253c6da01ec29f1e39eb2713

Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use 
"kubeadm init phase upload-certs --upload-certs" to reload certs afterward.

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.1.109:6443 --token 2sqa85.x8jxuibdr19f9wg0 \
    --discovery-token-ca-cert-hash sha256:f07f424c74f4871639ac3d4131db7d51c550d0965df1856e9bf51d711f79c43b 

默认生成的证书是临时加入使用的,失效可以用:

kubeadm init phase upload-certs --experimental-upload-certs

node 的加入就简单了,和原先的一样,不带这些主节点的参数信息如:

kubeadm join master:6443 --token 74fxrx.34uwnbxun31d9cgc \
    --discovery-token-ca-cert-hash sha256:7056fa528a5f0f962f565ee4eb7a96d7ecc5432883bd3c506ca0fa1eab09064c

例如,忘记了join 命令,如下重新生成即可:

[root@k8s-master1 ~]# kubeadm token  create --print-join-command
kubeadm join 192.168.1.109:6443 --token 779f9q.1jm3gryowdvpreff     --discovery-token-ca-cert-hash sha256:d1e5bb20d5b73dd317e5f9e7e699f5f02932b691608c138af032f45f2838e21e 
[root@k8s-master1 ~]# 
[root@k8s-master1 master]# kubeadm init phase upload-certs --upload-certs 
W1108 12:51:43.116233    8127 version.go:98] could not fetch a Kubernetes version from the internet: unable to get URL "https://dl.k8s.io/release/stable-1.txt": Get https://dl.k8s.io/release/stable-1.txt: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
W1108 12:51:43.116287    8127 version.go:99] falling back to the local client version: v1.15.0
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[upload-certs] Using certificate key:
3461c4d9b5332796907d1412d9cb82a36869c1f3dd171d2d95b496643366183a

有些东西参考上一层。开发环境k8s 高可用master 的搭建

下一层 : 锻骨境-第5层 k8s-ETCD集群备份与恢复

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

推荐阅读更多精彩内容